Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1import { boxWith, onDestroyEffect, attachRef, DOMContext, simpleBox, } from "svelte-toolbelt";2import { onMount, untrack } from "svelte";3import { Context, watch } from "runed";4import { createBitsAttrs, boolToStr, boolToStrTrueOrUndef, boolToEmptyStrOrUndef, } from "../../internal/attrs.js";5import { isBrowser, isNumberString } from "../../internal/is.js";6import { kbd } from "../../internal/kbd.js";7import { useId } from "../../internal/use-id.js";8import { createFormatter } from "../../internal/date-time/formatter.js";9import { getAnnouncer } from "../../internal/date-time/announcer.js";10import { areAllSegmentsFilled, createContent, getDefaultHourCycle, getValueFromSegments, inferGranularity, initSegmentStates, initializeSegmentValues, isAcceptableSegmentKey, isDateAndTimeSegmentObj, isDateSegmentPart, isFirstSegment, removeDescriptionElement, setDescription, } from "../../internal/date-time/field/helpers.js";11import { DATE_SEGMENT_PARTS, EDITABLE_TIME_SEGMENT_PARTS, } from "../../internal/date-time/field/parts.js";12import { getDaysInMonth, isBefore, toDate } from "../../internal/date-time/utils.js";13import { getFirstSegment, handleSegmentNavigation, isSegmentNavigationKey, moveToNextSegment, moveToPrevSegment, } from "../../internal/date-time/field/segments.js";14export const dateFieldAttrs = createBitsAttrs({15 component: "date-field",16 parts: ["input", "label", "segment"],17});18const SEGMENT_CONFIGS = {19 day: {20 min: 1,21 max: (root) => {22 const segmentMonthValue = root.segmentValues.month;23 const placeholder = root.value.current ?? root.placeholder.current;24 return segmentMonthValue25 ? getDaysInMonth(placeholder.set({ month: Number.parseInt(segmentMonthValue) }))26 : getDaysInMonth(placeholder);27 },28 cycle: 1,29 padZero: true,30 },31 month: {32 min: 1,33 max: 12,34 cycle: 1,35 padZero: true,36 getAnnouncement: (month, root) => {37 if (!root.placeholder.current)38 return "";39 return `${month} - ${root.formatter.fullMonth(toDate(root.placeholder.current.set({ month })))}`;40 },41 },42 year: {43 min: 1,44 max: 9999,45 cycle: 1,46 padZero: false,47 },48 hour: {49 min: (root) => (root.hourCycle.current === 12 ? 1 : 0),50 max: (root) => {51 if (root.hourCycle.current === 24)52 return 23;53 if (root.hourCycle.current === 12)54 return 12;55 // if hourCycle is undefined, infer from locale56 const inferredHourCycle = getDefaultHourCycle(root.locale.current);57 return inferredHourCycle === 12 ? 12 : 23;58 },59 cycle: 1,60 canBeZero: true,61 padZero: true,62 },63 minute: {64 min: 0,65 max: 59,66 cycle: 1,67 canBeZero: true,68 padZero: true,69 },70 second: {71 min: 0,72 max: 59,73 cycle: 1,74 canBeZero: true,75 padZero: true,76 },77};78const DateFieldRootContext = new Context("DateField.Root");79export class DateFieldRootState {80 static create(opts, rangeRoot) {81 return DateFieldRootContext.set(new DateFieldRootState(opts, rangeRoot));82 }83 value;84 placeholder;85 validate;86 minValue;87 maxValue;88 disabled;89 readonly;90 granularity;91 readonlySegments;92 hourCycle;93 locale;94 hideTimeZone;95 required;96 onInvalid;97 errorMessageId;98 isInvalidProp;99 descriptionId = useId();100 formatter;101 initialSegments;102 segmentValues = $state();103 announcer;104 readonlySegmentsSet = $derived.by(() => new Set(this.readonlySegments.current));105 segmentStates = initSegmentStates();106 #fieldNode = $state(null);107 #labelNode = $state(null);108 descriptionNode = $state(null);109 validationNode = $state(null);110 states = initSegmentStates();111 dayPeriodNode = $state(null);112 rangeRoot = undefined;113 name = $state("");114 domContext = new DOMContext(() => null);115 constructor(props, rangeRoot) {116 this.rangeRoot = rangeRoot;117 /**118 * Since the `DateFieldRootState` can be used in two contexts, as a standalone119 * field or as a field within a `DateRangeField` component, we handle assigning120 * the props based on that context.121 */122 this.value = props.value;123 this.placeholder = rangeRoot ? rangeRoot.opts.placeholder : props.placeholder;124 this.validate = rangeRoot ? simpleBox(undefined) : props.validate;125 this.minValue = rangeRoot ? rangeRoot.opts.minValue : props.minValue;126 this.maxValue = rangeRoot ? rangeRoot.opts.maxValue : props.maxValue;127 this.disabled = rangeRoot ? rangeRoot.opts.disabled : props.disabled;128 this.readonly = rangeRoot ? rangeRoot.opts.readonly : props.readonly;129 this.granularity = rangeRoot ? rangeRoot.opts.granularity : props.granularity;130 this.readonlySegments = rangeRoot131 ? rangeRoot.opts.readonlySegments132 : props.readonlySegments;133 this.hourCycle = rangeRoot ? rangeRoot.opts.hourCycle : props.hourCycle;134 this.locale = rangeRoot ? rangeRoot.opts.locale : props.locale;135 this.hideTimeZone = rangeRoot ? rangeRoot.opts.hideTimeZone : props.hideTimeZone;136 this.required = rangeRoot ? rangeRoot.opts.required : props.required;137 this.onInvalid = rangeRoot ? rangeRoot.opts.onInvalid : props.onInvalid;138 this.errorMessageId = rangeRoot ? rangeRoot.opts.errorMessageId : props.errorMessageId;139 this.isInvalidProp = props.isInvalidProp;140 this.formatter = createFormatter({141 initialLocale: this.locale.current,142 monthFormat: boxWith(() => "long"),143 yearFormat: boxWith(() => "numeric"),144 });145 this.initialSegments = initializeSegmentValues(this.inferredGranularity);146 this.segmentValues = this.initialSegments;147 this.announcer = getAnnouncer(null);148 this.getFieldNode = this.getFieldNode.bind(this);149 this.updateSegment = this.updateSegment.bind(this);150 this.handleSegmentClick = this.handleSegmentClick.bind(this);151 this.getBaseSegmentAttrs = this.getBaseSegmentAttrs.bind(this);152 $effect(() => {153 untrack(() => {154 this.initialSegments = initializeSegmentValues(this.inferredGranularity);155 });156 });157 onMount(() => {158 this.announcer = getAnnouncer(this.domContext.getDocument());159 });160 onDestroyEffect(() => {161 if (rangeRoot)162 return;163 removeDescriptionElement(this.descriptionId, this.domContext.getDocument());164 });165 $effect(() => {166 if (rangeRoot)167 return;168 if (this.formatter.getLocale() === this.locale.current)169 return;170 this.formatter.setLocale(this.locale.current);171 });172 $effect(() => {173 if (rangeRoot)174 return;175 if (this.value.current) {176 const descriptionId = untrack(() => this.descriptionId);177 setDescription({178 id: descriptionId,179 formatter: this.formatter,180 value: this.value.current,181 doc: this.domContext.getDocument(),182 });183 }184 const placeholder = untrack(() => this.placeholder.current);185 if (this.value.current && placeholder !== this.value.current) {186 untrack(() => {187 if (this.value.current) {188 this.placeholder.current = this.value.current;189 }190 });191 }192 });193 if (this.value.current) {194 this.syncSegmentValues(this.value.current);195 }196 $effect(() => {197 this.locale.current;198 if (this.value.current) {199 this.syncSegmentValues(this.value.current);200 }201 this.#clearUpdating();202 });203 $effect(() => {204 if (this.value.current === undefined) {205 this.segmentValues = initializeSegmentValues(this.inferredGranularity);206 }207 });208 watch(() => this.validationStatus, () => {209 if (this.validationStatus !== false) {210 this.onInvalid.current?.(this.validationStatus.reason, this.validationStatus.message);211 }212 });213 }214 setName(name) {215 this.name = name;216 }217 /**218 * Sets the field node for the `DateFieldRootState` instance. We use this method so we can219 * keep `#fieldNode` private to prevent accidental usage of the incorrect field node.220 */221 setFieldNode(node) {222 this.#fieldNode = node;223 }224 /**225 * Gets the correct field node for the date field regardless of whether it's being226 * used in a standalone context or within a `DateRangeField` component.227 */228 getFieldNode() {229 /** If we're not within a DateRangeField, we return this field. */230 if (!this.rangeRoot) {231 return this.#fieldNode;232 }233 else {234 /**235 * Otherwise, we return the rangeRoot's field node which236 * contains both start and end fields.237 */238 return this.rangeRoot.fieldNode;239 }240 }241 /**242 * Sets the label node for the `DateFieldRootState` instance. We use this method so we can243 * keep `#labelNode` private to prevent accidental usage of the incorrect label node.244 */245 setLabelNode(node) {246 this.#labelNode = node;247 }248 /**249 * Gets the correct label node for the date field regardless of whether it's being used in250 * a standalone context or within a `DateRangeField` component.251 */252 getLabelNode() {253 /** If we're not within a DateRangeField, we return this field. */254 if (!this.rangeRoot) {255 return this.#labelNode;256 }257 /** Otherwise we return the rangeRoot's label node. */258 return this.rangeRoot.labelNode;259 }260 #clearUpdating() {261 this.states.day.updating = null;262 this.states.month.updating = null;263 this.states.year.updating = null;264 this.states.hour.updating = null;265 this.states.minute.updating = null;266 this.states.dayPeriod.updating = null;267 }268 setValue(value) {269 this.value.current = value;270 }271 syncSegmentValues(value) {272 const dateValues = DATE_SEGMENT_PARTS.map((part) => {273 const partValue = value[part];274 if (part === "month") {275 if (this.states.month.updating) {276 return [part, this.states.month.updating];277 }278 if (partValue < 10) {279 return [part, `0${partValue}`];280 }281 }282 if (part === "day") {283 if (this.states.day.updating) {284 return [part, this.states.day.updating];285 }286 if (partValue < 10) {287 return [part, `0${partValue}`];288 }289 }290 if (part === "year") {291 if (this.states.year.updating) {292 return [part, this.states.year.updating];293 }294 const valueDigits = `${partValue}`.length;295 const diff = 4 - valueDigits;296 if (diff > 0) {297 return [part, `${"0".repeat(diff)}${partValue}`];298 }299 }300 return [part, `${partValue}`];301 });302 if ("hour" in value) {303 const timeValues = EDITABLE_TIME_SEGMENT_PARTS.map((part) => {304 if (part === "dayPeriod") {305 if (this.states.dayPeriod.updating) {306 return [part, this.states.dayPeriod.updating];307 }308 else {309 return [part, this.formatter.dayPeriod(toDate(value))];310 }311 }312 else if (part === "hour") {313 if (this.states.hour.updating) {314 return [part, this.states.hour.updating];315 }316 if (value[part] !== undefined && value[part] < 10) {317 return [part, `0${value[part]}`];318 }319 if (value[part] === 0) {320 /**321 * If we're rendering a `dayPeriod` segment, we're operating in a322 * 12-hour clock, so we never allow the displayed hour to be 0.323 */324 if (this.dayPeriodNode) {325 return [part, "12"];326 }327 }328 }329 else if (part === "minute") {330 if (this.states.minute.updating) {331 return [part, this.states.minute.updating];332 }333 if (value[part] !== undefined && value[part] < 10) {334 return [part, `0${value[part]}`];335 }336 }337 else if (part === "second") {338 if (this.states.second.updating) {339 return [part, this.states.second.updating];340 }341 if (value[part] !== undefined && value[part] < 10) {342 return [part, `0${value[part]}`];343 }344 }345 return [part, `${value[part]}`];346 });347 const mergedSegmentValues = [...dateValues, ...timeValues];348 this.segmentValues = Object.fromEntries(mergedSegmentValues);349 this.#clearUpdating();350 return;351 }352 this.segmentValues = Object.fromEntries(dateValues);353 }354 validationStatus = $derived.by(() => {355 const value = this.value.current;356 if (!value)357 return false;358 const msg = this.validate.current?.(value);359 if (msg) {360 return {361 reason: "custom",362 message: msg,363 };364 }365 const minValue = this.minValue.current;366 if (minValue && isBefore(value, minValue)) {367 return {368 reason: "min",369 };370 }371 const maxValue = this.maxValue.current;372 if (maxValue && isBefore(maxValue, value)) {373 return {374 reason: "max",375 };376 }377 return false;378 });379 isInvalid = $derived.by(() => {380 if (this.validationStatus === false)381 return false;382 if (this.isInvalidProp.current)383 return true;384 return true;385 });386 inferredGranularity = $derived.by(() => {387 const granularity = this.granularity.current;388 if (granularity)389 return granularity;390 const inferred = inferGranularity(this.placeholder.current, this.granularity.current);391 return inferred;392 });393 dateRef = $derived.by(() => this.value.current !== undefined ? this.value.current : this.placeholder.current);394 allSegmentContent = $derived.by(() => {395 return createContent({396 segmentValues: this.segmentValues,397 formatter: this.formatter,398 locale: this.locale.current,399 granularity: this.inferredGranularity,400 dateRef: this.dateRef,401 hideTimeZone: this.hideTimeZone.current,402 hourCycle: this.hourCycle.current,403 });404 });405 segmentContents = $derived.by(() => this.allSegmentContent.arr);406 sharedSegmentAttrs = {407 role: "spinbutton",408 contenteditable: "true",409 tabindex: 0,410 spellcheck: false,411 inputmode: "numeric",412 autocorrect: "off",413 enterkeyhint: "next",414 style: {415 caretColor: "transparent",416 },417 onbeforeinput: (e) => {418 if (!e.data || e.data.length <= 1) {419 e.preventDefault();420 }421 },422 };423 #getLabelledBy(segmentId) {424 return `${segmentId} ${this.getLabelNode()?.id ?? ""}`;425 }426 updateSegment(part, cb) {427 const disabled = this.disabled.current;428 const readonly = this.readonly.current;429 const readonlySegmentsSet = this.readonlySegmentsSet;430 if (disabled || readonly || readonlySegmentsSet.has(part))431 return;432 const prev = this.segmentValues;433 let newSegmentValues = prev;434 const dateRef = this.placeholder.current;435 if (isDateAndTimeSegmentObj(prev)) {436 const pVal = prev[part];437 const castCb = cb;438 if (part === "month") {439 const next = castCb(pVal);440 this.states.month.updating = next;441 if (next !== null && prev.day !== null) {442 const date = dateRef.set({ month: Number.parseInt(next) });443 const daysInMonth = getDaysInMonth(toDate(date));444 const prevDay = Number.parseInt(prev.day);445 if (prevDay > daysInMonth) {446 prev.day = `${daysInMonth}`;447 }448 }449 newSegmentValues = { ...prev, [part]: next };450 }451 else if (part === "dayPeriod") {452 const next = castCb(pVal);453 this.states.dayPeriod.updating = next;454 const date = this.value.current;455 if (date && "hour" in date) {456 const trueHour = date.hour;457 if (next === "AM") {458 if (trueHour >= 12) {459 prev.hour = `${trueHour - 12}`;460 }461 }462 else if (next === "PM") {463 if (trueHour < 12) {464 prev.hour = `${trueHour + 12}`;465 }466 }467 }468 newSegmentValues = { ...prev, [part]: next };469 }470 else if (part === "hour") {471 const next = castCb(pVal);472 this.states.hour.updating = next;473 if (next !== null && prev.dayPeriod !== null) {474 const dayPeriod = this.formatter.dayPeriod(toDate(dateRef.set({ hour: Number.parseInt(next) })), this.hourCycle.current);475 if (dayPeriod === "AM" || dayPeriod === "PM") {476 prev.dayPeriod = dayPeriod;477 }478 }479 newSegmentValues = { ...prev, [part]: next };480 }481 else if (part === "minute") {482 const next = castCb(pVal);483 this.states.minute.updating = next;484 newSegmentValues = { ...prev, [part]: next };485 }486 else if (part === "second") {487 const next = castCb(pVal);488 this.states.second.updating = next;489 newSegmentValues = { ...prev, [part]: next };490 }491 else if (part === "year") {492 const next = castCb(pVal);493 this.states.year.updating = next;494 newSegmentValues = { ...prev, [part]: next };495 }496 else if (part === "day") {497 const next = castCb(pVal);498 this.states.day.updating = next;499 newSegmentValues = { ...prev, [part]: next };500 }501 else {502 const next = castCb(pVal);503 newSegmentValues = { ...prev, [part]: next };504 }505 }506 else if (isDateSegmentPart(part)) {507 const pVal = prev[part];508 const castCb = cb;509 const next = castCb(pVal);510 if (part === "month" && next !== null && prev.day !== null) {511 this.states.month.updating = next;512 const date = dateRef.set({ month: Number.parseInt(next) });513 const daysInMonth = getDaysInMonth(toDate(date));514 if (Number.parseInt(prev.day) > daysInMonth) {515 prev.day = `${daysInMonth}`;516 }517 newSegmentValues = { ...prev, [part]: next };518 }519 else if (part === "year") {520 const next = castCb(pVal);521 this.states.year.updating = next;522 newSegmentValues = { ...prev, [part]: next };523 }524 else if (part === "day") {525 const next = castCb(pVal);526 this.states.day.updating = next;527 newSegmentValues = { ...prev, [part]: next };528 }529 else {530 newSegmentValues = { ...prev, [part]: next };531 }532 }533 this.segmentValues = newSegmentValues;534 if (areAllSegmentsFilled(newSegmentValues, this.#fieldNode)) {535 this.setValue(getValueFromSegments({536 segmentObj: newSegmentValues,537 fieldNode: this.#fieldNode,538 dateRef: this.placeholder.current,539 }));540 }541 else {542 this.setValue(undefined);543 this.segmentValues = newSegmentValues;544 }545 }546 handleSegmentClick(e) {547 if (this.disabled.current) {548 e.preventDefault();549 }550 }551 getBaseSegmentAttrs(part, segmentId) {552 const inReadonlySegments = this.readonlySegmentsSet.has(part);553 const defaultAttrs = {554 "aria-invalid": boolToStrTrueOrUndef(this.isInvalid),555 "aria-disabled": boolToStr(this.disabled.current),556 "aria-readonly": boolToStr(this.readonly.current || inReadonlySegments),557 "data-invalid": boolToEmptyStrOrUndef(this.isInvalid),558 "data-disabled": boolToEmptyStrOrUndef(this.disabled.current),559 "data-readonly": boolToEmptyStrOrUndef(this.readonly.current || inReadonlySegments),560 "data-segment": `${part}`,561 [dateFieldAttrs.segment]: "",562 };563 if (part === "literal")564 return defaultAttrs;565 const descriptionId = this.descriptionNode?.id;566 const hasDescription = isFirstSegment(segmentId, this.#fieldNode) && descriptionId;567 const errorMsgId = this.errorMessageId?.current;568 const describedBy = hasDescription569 ? `${descriptionId} ${this.isInvalid && errorMsgId ? errorMsgId : ""}`570 : undefined;571 const contenteditable = !(this.readonly.current ||572 inReadonlySegments ||573 this.disabled.current);574 return {575 ...defaultAttrs,576 "aria-labelledby": this.#getLabelledBy(segmentId),577 contenteditable: contenteditable ? "true" : undefined,578 "aria-describedby": describedBy,579 tabindex: this.disabled.current ? undefined : 0,580 };581 }582}583export class DateFieldInputState {584 static create(opts) {585 return new DateFieldInputState(opts, DateFieldRootContext.get());586 }587 opts;588 root;589 domContext;590 attachment;591 constructor(opts, root) {592 this.opts = opts;593 this.root = root;594 this.domContext = new DOMContext(opts.ref);595 this.root.domContext = this.domContext;596 this.attachment = attachRef(opts.ref, (v) => this.root.setFieldNode(v));597 watch(() => this.opts.name.current, (v) => {598 this.root.setName(v);599 });600 }601 #ariaDescribedBy = $derived.by(() => {602 if (!isBrowser)603 return undefined;604 const doesDescriptionExist = this.domContext.getElementById(this.root.descriptionId);605 if (!doesDescriptionExist)606 return undefined;607 return this.root.descriptionId;608 });609 props = $derived.by(() => ({610 id: this.opts.id.current,611 role: "group",612 "aria-labelledby": this.root.getLabelNode()?.id ?? undefined,613 "aria-describedby": this.#ariaDescribedBy,614 "aria-disabled": boolToStr(this.root.disabled.current),615 "data-invalid": this.root.isInvalid ? "" : undefined,616 "data-disabled": boolToEmptyStrOrUndef(this.root.disabled.current),617 [dateFieldAttrs.input]: "",618 ...this.attachment,619 }));620}621export class DateFieldHiddenInputState {622 static create() {623 return new DateFieldHiddenInputState(DateFieldRootContext.get());624 }625 root;626 shouldRender = $derived.by(() => this.root.name !== "");627 isoValue = $derived.by(() => this.root.value.current ? this.root.value.current.toString() : "");628 constructor(root) {629 this.root = root;630 }631 props = $derived.by(() => {632 return {633 name: this.root.name,634 value: this.isoValue,635 required: this.root.required.current,636 };637 });638}639export class DateFieldLabelState {640 static create(opts) {641 return new DateFieldLabelState(opts, DateFieldRootContext.get());642 }643 opts;644 root;645 attachment;646 constructor(opts, root) {647 this.opts = opts;648 this.root = root;649 this.onclick = this.onclick.bind(this);650 this.attachment = attachRef(opts.ref, (v) => this.root.setLabelNode(v));651 }652 onclick(_) {653 if (this.root.disabled.current)654 return;655 const firstSegment = getFirstSegment(this.root.getFieldNode());656 if (!firstSegment)657 return;658 firstSegment.focus();659 }660 props = $derived.by(() => ({661 id: this.opts.id.current,662 "data-invalid": boolToEmptyStrOrUndef(this.root.isInvalid),663 "data-disabled": boolToEmptyStrOrUndef(this.root.disabled.current),664 [dateFieldAttrs.label]: "",665 onclick: this.onclick,666 ...this.attachment,667 }));668}669// Base class for numeric segments670class BaseNumericSegmentState {671 opts;672 root;673 announcer;674 part;675 config;676 attachment;677 constructor(opts, root, part, config) {678 this.opts = opts;679 this.root = root;680 this.part = part;681 this.config = config;682 this.announcer = root.announcer;683 this.onkeydown = this.onkeydown.bind(this);684 this.onfocusout = this.onfocusout.bind(this);685 this.attachment = attachRef(opts.ref);686 }687 #getMax() {688 return typeof this.config.max === "function" ? this.config.max(this.root) : this.config.max;689 }690 #getMin() {691 return typeof this.config.min === "function" ? this.config.min(this.root) : this.config.min;692 }693 #getAnnouncement(value) {694 if (this.config.getAnnouncement) {695 return this.config.getAnnouncement(value, this.root);696 }697 return value;698 }699 #formatValue(value, forDisplay = true) {700 const str = String(value);701 if (forDisplay && this.config.padZero && str.length === 1) {702 return `0${value}`;703 }704 return str;705 }706 onkeydown(e) {707 const placeholder = this.root.value.current ?? this.root.placeholder.current;708 if (e.ctrlKey || e.metaKey || this.root.disabled.current)709 return;710 // Special check for time segments711 if ((this.part === "hour" || this.part === "minute" || this.part === "second") &&712 !(this.part in placeholder))713 return;714 if (e.key !== kbd.TAB)715 e.preventDefault();716 if (!isAcceptableSegmentKey(e.key))717 return;718 if (isArrowUp(e.key)) {719 this.#handleArrowUp(placeholder);720 return;721 }722 if (isArrowDown(e.key)) {723 this.#handleArrowDown(placeholder);724 return;725 }726 if (isNumberString(e.key)) {727 this.#handleNumberKey(e);728 return;729 }730 if (isBackspace(e.key)) {731 this.#handleBackspace(e);732 return;733 }734 if (isSegmentNavigationKey(e.key)) {735 handleSegmentNavigation(e, this.root.getFieldNode());736 }737 }738 #handleArrowUp(placeholder) {739 const stateKey = this.part;740 if (stateKey in this.root.states) {741 this.root.states[stateKey].hasLeftFocus = false;742 }743 // @ts-expect-error this is a part744 this.root.updateSegment(this.part, (prev) => {745 if (prev === null) {746 const next = placeholder[this.part];747 this.announcer.announce(this.#getAnnouncement(next));748 return this.#formatValue(next);749 }750 const current = placeholder.set({751 [this.part]: Number.parseInt(prev),752 });753 // @ts-expect-error this is a part754 const next = current.cycle(this.part, this.config.cycle)[this.part];755 this.announcer.announce(this.#getAnnouncement(next));756 return this.#formatValue(next);757 });758 }759 #handleArrowDown(placeholder) {760 const stateKey = this.part;761 if (stateKey in this.root.states) {762 this.root.states[stateKey].hasLeftFocus = false;763 }764 // @ts-expect-error this is a part765 this.root.updateSegment(this.part, (prev) => {766 if (prev === null) {767 const next = placeholder[this.part];768 this.announcer.announce(this.#getAnnouncement(next));769 return this.#formatValue(next);770 }771 const current = placeholder.set({772 [this.part]: Number.parseInt(prev),773 });774 // @ts-expect-error this is a part775 const next = current.cycle(this.part, -this.config.cycle)[this.part];776 this.announcer.announce(this.#getAnnouncement(next));777 return this.#formatValue(next);778 });779 }780 #handleNumberKey(e) {781 const num = Number.parseInt(e.key);782 let moveToNext = false;783 const max = this.#getMax();784 const maxStart = Math.floor(max / 10);785 const numIsZero = num === 0;786 const stateKey = this.part;787 // @ts-expect-error this is a part788 this.root.updateSegment(this.part, (prev) => {789 // Check if user has left focus790 if (stateKey in this.root.states && this.root.states[stateKey].hasLeftFocus) {791 prev = null;792 this.root.states[stateKey].hasLeftFocus = false;793 }794 // Starting fresh795 if (prev === null) {796 if (numIsZero) {797 if (stateKey in this.root.states) {798 this.root.states[stateKey].lastKeyZero = true;799 }800 this.announcer.announce("0");801 return "0";802 }803 if (stateKey in this.root.states &&804 (this.root.states[stateKey].lastKeyZero || num > maxStart)) {805 moveToNext = true;806 }807 if (stateKey in this.root.states) {808 this.root.states[stateKey].lastKeyZero = false;809 }810 if (moveToNext && String(num).length === 1) {811 this.announcer.announce(num);812 return `0${num}`;813 }814 return `${num}`;815 }816 // Handle special cases for segments with lastKeyZero tracking817 if (stateKey in this.root.states && this.root.states[stateKey].lastKeyZero) {818 if (num !== 0) {819 moveToNext = true;820 this.root.states[stateKey].lastKeyZero = false;821 return `0${num}`;822 }823 // Special handling for hour segment with 24-hour cycle824 if (this.part === "hour" && num === 0 && this.root.hourCycle.current === 24) {825 moveToNext = true;826 this.root.states[stateKey].lastKeyZero = false;827 return `00`;828 }829 // Special handling for minute/second segments830 if ((this.part === "minute" || this.part === "second") && num === 0) {831 moveToNext = true;832 this.root.states[stateKey].lastKeyZero = false;833 return "00";834 }835 return prev;836 }837 const total = Number.parseInt(prev + num.toString());838 if (total > max) {839 moveToNext = true;840 return `0${num}`;841 }842 moveToNext = true;843 return `${total}`;844 });845 if (moveToNext) {846 moveToNextSegment(e, this.root.getFieldNode());847 }848 }849 #handleBackspace(e) {850 const stateKey = this.part;851 if (stateKey in this.root.states) {852 this.root.states[stateKey].hasLeftFocus = false;853 }854 let moveToPrev = false;855 // @ts-expect-error this is a part856 this.root.updateSegment(this.part, (prev) => {857 if (prev === null) {858 moveToPrev = true;859 this.announcer.announce(null);860 return null;861 }862 if (prev.length === 2 && prev.startsWith("0")) {863 this.announcer.announce(null);864 return null;865 }866 const str = prev.toString();867 if (str.length === 1) {868 this.announcer.announce(null);869 return null;870 }871 const next = Number.parseInt(str.slice(0, -1));872 this.announcer.announce(this.#getAnnouncement(next));873 return `${next}`;874 });875 if (moveToPrev) {876 moveToPrevSegment(e, this.root.getFieldNode());877 }878 }879 onfocusout(_) {880 const stateKey = this.part;881 if (stateKey in this.root.states) {882 this.root.states[stateKey].hasLeftFocus = true;883 }884 // Pad with zero if needed885 if (this.config.padZero) {886 // @ts-expect-error this is a part887 this.root.updateSegment(this.part, (prev) => {888 if (prev && prev.length === 1) {889 return `0${prev}`;890 }891 return prev;892 });893 }894 }895 getSegmentProps() {896 const segmentValues = this.root.segmentValues;897 const placeholder = this.root.placeholder.current;898 const isEmpty = segmentValues[this.part] === null;899 let date = placeholder;900 if (segmentValues[this.part]) {901 date = placeholder.set({902 [this.part]: Number.parseInt(segmentValues[this.part]),903 });904 }905 const valueNow = date[this.part];906 const valueMin = this.#getMin();907 const valueMax = this.#getMax();908 let valueText = isEmpty ? "Empty" : `${valueNow}`;909 // Special handling for hour segment with dayPeriod910 if (this.part === "hour" && "dayPeriod" in segmentValues && segmentValues.dayPeriod) {911 valueText = isEmpty ? "Empty" : `${valueNow} ${segmentValues.dayPeriod}`;912 }913 return {914 "aria-label": `${this.part}, `,915 "aria-valuemin": valueMin,916 "aria-valuemax": valueMax,917 "aria-valuenow": valueNow,918 "aria-valuetext": valueText,919 };920 }921 props = $derived.by(() => {922 return {923 ...this.root.sharedSegmentAttrs,924 id: this.opts.id.current,925 ...this.getSegmentProps(),926 onkeydown: this.onkeydown,927 onfocusout: this.onfocusout,928 onclick: this.root.handleSegmentClick,929 ...this.root.getBaseSegmentAttrs(this.part, this.opts.id.current),930 ...this.attachment,931 };932 });933}934class DateFieldYearSegmentState extends BaseNumericSegmentState {935 #pressedKeys = [];936 #backspaceCount = 0;937 constructor(opts, root) {938 super(opts, root, "year", SEGMENT_CONFIGS.year);939 }940 onkeydown(e) {941 if (e.ctrlKey || e.metaKey || this.root.disabled.current)942 return;943 if (e.key !== kbd.TAB)944 e.preventDefault();945 if (!isAcceptableSegmentKey(e.key))946 return;947 if (isArrowUp(e.key)) {948 this.#resetBackspaceCount();949 super.onkeydown(e);950 return;951 }952 if (isArrowDown(e.key)) {953 this.#resetBackspaceCount();954 super.onkeydown(e);955 return;956 }957 if (isNumberString(e.key)) {958 this.#handleYearNumberKey(e);959 return;960 }961 if (isBackspace(e.key)) {962 this.#handleYearBackspace(e);963 return;964 }965 if (isSegmentNavigationKey(e.key)) {966 handleSegmentNavigation(e, this.root.getFieldNode());967 }968 }969 #resetBackspaceCount() {970 this.#backspaceCount = 0;971 }972 #incrementBackspaceCount() {973 this.#backspaceCount++;974 }975 #handleYearNumberKey(e) {976 this.#pressedKeys.push(e.key);977 let moveToNext = false;978 const num = Number.parseInt(e.key);979 this.root.updateSegment("year", (prev) => {980 if (this.root.states.year.hasLeftFocus) {981 prev = null;982 this.root.states.year.hasLeftFocus = false;983 }984 if (prev === null) {985 this.announcer.announce(num);986 return `000${num}`;987 }988 const str = prev.toString() + num.toString();989 const mergedInt = Number.parseInt(str);990 const mergedIntDigits = String(mergedInt).length;991 if (mergedIntDigits < 4) {992 if (this.#backspaceCount > 0 &&993 this.#pressedKeys.length <= this.#backspaceCount &&994 str.length <= 4) {995 this.announcer.announce(mergedInt);996 return str;997 }998 this.announcer.announce(mergedInt);999 return prependYearZeros(mergedInt);1000 }1001 this.announcer.announce(mergedInt);1002 moveToNext = true;1003 const mergedIntStr = `${mergedInt}`;1004 if (mergedIntStr.length > 4) {1005 return mergedIntStr.slice(0, 4);1006 }1007 return mergedIntStr;1008 });1009 if (this.#pressedKeys.length === 4 || this.#pressedKeys.length === this.#backspaceCount) {1010 moveToNext = true;1011 }1012 if (moveToNext) {1013 moveToNextSegment(e, this.root.getFieldNode());1014 }1015 }1016 #handleYearBackspace(e) {1017 this.#pressedKeys = [];1018 this.#incrementBackspaceCount();1019 let moveToPrev = false;1020 this.root.updateSegment("year", (prev) => {1021 this.root.states.year.hasLeftFocus = false;1022 if (prev === null) {1023 moveToPrev = true;1024 this.announcer.announce(null);1025 return null;1026 }1027 const str = prev.toString();1028 if (str.length === 1) {1029 this.announcer.announce(null);1030 return null;1031 }1032 const next = str.slice(0, -1);1033 this.announcer.announce(next);1034 return `${next}`;1035 });1036 if (moveToPrev) {1037 moveToPrevSegment(e, this.root.getFieldNode());1038 }1039 }1040 onfocusout(_) {1041 this.root.states.year.hasLeftFocus = true;1042 this.#pressedKeys = [];1043 this.#resetBackspaceCount();1044 this.root.updateSegment("year", (prev) => {1045 if (prev && prev.length !== 4) {1046 return prependYearZeros(Number.parseInt(prev));1047 }1048 return prev;1049 });1050 }1051}1052class DateFieldDaySegmentState extends BaseNumericSegmentState {1053 constructor(opts, root) {1054 super(opts, root, "day", SEGMENT_CONFIGS.day);1055 }1056}1057class DateFieldMonthSegmentState extends BaseNumericSegmentState {1058 constructor(opts, root) {1059 super(opts, root, "month", SEGMENT_CONFIGS.month);1060 }1061}1062class DateFieldHourSegmentState extends BaseNumericSegmentState {1063 constructor(opts, root) {1064 super(opts, root, "hour", SEGMENT_CONFIGS.hour);1065 }1066 // Override to handle special hour logic1067 onkeydown(e) {1068 // Add special handling for hour display with dayPeriod1069 if (isNumberString(e.key)) {1070 const oldUpdateSegment = this.root.updateSegment.bind(this.root);1071 // oxlint-disable-next-line no-explicit-any1072 this.root.updateSegment = (part, cb) => {1073 const result = oldUpdateSegment(part, cb);1074 // After updating hour, check if we need to display "12" instead of "0"1075 if (part === "hour" && "hour" in this.root.segmentValues) {1076 const hourValue = this.root.segmentValues.hour;1077 if (hourValue === "0" &&1078 this.root.dayPeriodNode &&1079 this.root.hourCycle.current !== 24) {1080 this.root.segmentValues.hour = "12";1081 }1082 }1083 return result;1084 };1085 }1086 super.onkeydown(e);1087 // Restore original updateSegment1088 this.root.updateSegment = this.root.updateSegment.bind(this.root);1089 }1090}1091class DateFieldMinuteSegmentState extends BaseNumericSegmentState {1092 constructor(opts, root) {1093 super(opts, root, "minute", SEGMENT_CONFIGS.minute);1094 }1095}1096class DateFieldSecondSegmentState extends BaseNumericSegmentState {1097 constructor(opts, root) {1098 super(opts, root, "second", SEGMENT_CONFIGS.second);1099 }1100}1101export class DateFieldDayPeriodSegmentState {1102 static create(opts) {1103 return new DateFieldDayPeriodSegmentState(opts, DateFieldRootContext.get());1104 }1105 opts;1106 root;1107 attachment;1108 #announcer;1109 constructor(opts, root) {1110 this.opts = opts;1111 this.root = root;1112 this.#announcer = this.root.announcer;1113 this.onkeydown = this.onkeydown.bind(this);1114 this.attachment = attachRef(opts.ref, (v) => (this.root.dayPeriodNode = v));1115 }1116 onkeydown(e) {1117 if (e.ctrlKey || e.metaKey || this.root.disabled.current)1118 return;1119 if (e.key !== kbd.TAB)1120 e.preventDefault();1121 if (!isAcceptableDayPeriodKey(e.key))1122 return;1123 if (isArrowUp(e.key) || isArrowDown(e.key)) {1124 this.root.updateSegment("dayPeriod", (prev) => {1125 if (prev === "AM") {1126 const next = "PM";1127 this.#announcer.announce(next);1128 return next;1129 }1130 const next = "AM";1131 this.#announcer.announce(next);1132 return next;1133 });1134 return;1135 }1136 if (isBackspace(e.key)) {1137 this.root.states.dayPeriod.hasLeftFocus = false;1138 this.root.updateSegment("dayPeriod", () => {1139 const next = "AM";1140 this.#announcer.announce(next);1141 return next;1142 });1143 }1144 if (e.key === kbd.A || e.key === kbd.P || kbd.a || kbd.p) {1145 this.root.updateSegment("dayPeriod", () => {1146 const next = e.key === kbd.A || e.key === kbd.a ? "AM" : "PM";1147 this.#announcer.announce(next);1148 return next;1149 });1150 }1151 if (isSegmentNavigationKey(e.key)) {1152 handleSegmentNavigation(e, this.root.getFieldNode());1153 }1154 }1155 props = $derived.by(() => {1156 const segmentValues = this.root.segmentValues;1157 if (!("dayPeriod" in segmentValues))1158 return;1159 const valueMin = 0;1160 const valueMax = 12;1161 const valueNow = segmentValues.dayPeriod === "AM" ? 0 : 12;1162 const valueText = segmentValues.dayPeriod ?? "AM";1163 return {1164 ...this.root.sharedSegmentAttrs,1165 id: this.opts.id.current,1166 inputmode: "text",1167 "aria-label": "AM/PM",1168 "aria-valuemin": valueMin,1169 "aria-valuemax": valueMax,1170 "aria-valuenow": valueNow,1171 "aria-valuetext": valueText,1172 onkeydown: this.onkeydown,1173 onclick: this.root.handleSegmentClick,1174 ...this.root.getBaseSegmentAttrs("dayPeriod", this.opts.id.current),1175 ...this.attachment,1176 };1177 });1178}1179export class DateFieldLiteralSegmentState {1180 static create(opts) {1181 return new DateFieldLiteralSegmentState(opts, DateFieldRootContext.get());1182 }1183 opts;1184 root;1185 attachment;1186 constructor(opts, root) {1187 this.opts = opts;1188 this.root = root;1189 this.attachment = attachRef(opts.ref);1190 }1191 props = $derived.by(() => ({1192 id: this.opts.id.current,1193 "aria-hidden": boolToStrTrueOrUndef(true),1194 ...this.root.getBaseSegmentAttrs("literal", this.opts.id.current),1195 ...this.attachment,1196 }));1197}1198export class DateFieldTimeZoneSegmentState {1199 static create(opts) {1200 return new DateFieldTimeZoneSegmentState(opts, DateFieldRootContext.get());