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 { CalendarDateTime, Time, ZonedDateTime } from "@internationalized/date";2import { onDestroyEffect, attachRef, DOMContext, simpleBox, } from "svelte-toolbelt";3import { onMount, untrack } from "svelte";4import { Context, watch } from "runed";5import { createBitsAttrs, boolToStr, boolToStrTrueOrUndef, boolToEmptyStrOrUndef, } from "../../internal/attrs.js";6import { isBrowser, isNumberString } from "../../internal/is.js";7import { kbd } from "../../internal/kbd.js";8import { useId } from "../../internal/use-id.js";9import { createTimeFormatter } from "../../internal/date-time/formatter.js";10import { getAnnouncer } from "../../internal/date-time/announcer.js";11import { EDITABLE_TIME_SEGMENT_PARTS } from "../../internal/date-time/field/parts.js";12import { toDate } from "../../internal/date-time/utils.js";13import { areAllTimeSegmentsFilled, convertTimeValueToTime, createTimeContent, getISOTimeValue, getTimeValueFromSegments, initTimeSegmentStates, isFirstTimeSegment, isTimeBefore, removeTimeDescriptionElement, setTimeDescription, } from "../../internal/date-time/field/time-helpers.js";14import { getFirstTimeSegment, handleTimeSegmentNavigation, isSegmentNavigationKey, moveToNextTimeSegment, moveToPrevTimeSegment, } from "../../internal/date-time/field/segments.js";15import { getDefaultHourCycle, isAcceptableSegmentKey, } from "../../internal/date-time/field/helpers.js";16export const timeFieldAttrs = createBitsAttrs({17 component: "time-field",18 parts: ["input", "label"],19});20const TimeFieldRootContext = new Context("TimeField.Root");21const SEGMENT_CONFIGS = {22 hour: {23 min: (root) => (root.hourCycle === 12 ? 1 : 0),24 max: (root) => {25 if (root.hourCycle === 24)26 return 23;27 if ("dayPeriod" in root.segmentValues && root.segmentValues.dayPeriod !== null)28 return 12;29 return 23;30 },31 cycle: 1,32 canBeZero: true,33 padZero: true,34 },35 minute: {36 min: 0,37 max: 59,38 cycle: 1,39 canBeZero: true,40 padZero: true,41 },42 second: {43 min: 0,44 max: 59,45 cycle: 1,46 canBeZero: true,47 padZero: true,48 },49};50function get24HourValueFromTypedHour(hour, dayPeriod) {51 const parsedHour = Number.parseInt(hour);52 if (Number.isNaN(parsedHour))53 return hour;54 if (dayPeriod === "AM") {55 return parsedHour === 12 ? "0" : `${parsedHour}`;56 }57 return parsedHour < 12 ? `${parsedHour + 12}` : `${parsedHour}`;58}59export class TimeFieldRootState {60 static create(opts, rangeRoot) {61 return TimeFieldRootContext.set(new TimeFieldRootState(opts, rangeRoot));62 }63 value;64 placeholder;65 validate;66 minValue;67 maxValue;68 disabled;69 readonly;70 granularity;71 readonlySegments;72 hourCycleProp;73 locale;74 hideTimeZone;75 required;76 onInvalid;77 errorMessageId;78 isInvalidProp;79 descriptionId = useId();80 formatter;81 initialSegments;82 segmentValues = $state();83 announcer;84 readonlySegmentsSet = $derived.by(() => new Set(this.readonlySegments.current));85 segmentStates = initTimeSegmentStates();86 #fieldNode = $state(null);87 #labelNode = $state(null);88 descriptionNode = $state(null);89 validationNode = $state(null);90 states = initTimeSegmentStates();91 hourInputDayPeriodHint = null;92 dayPeriodNode = $state(null);93 name = $state("");94 maxValueTime = $derived.by(() => {95 if (!this.maxValue.current)96 return undefined;97 return convertTimeValueToTime(this.maxValue.current);98 });99 minValueTime = $derived.by(() => {100 if (!this.minValue.current)101 return undefined;102 return convertTimeValueToTime(this.minValue.current);103 });104 valueTime = $derived.by(() => {105 if (!this.value.current)106 return undefined;107 return convertTimeValueToTime(this.value.current);108 });109 hourCycle = $derived.by(() => {110 if (this.hourCycleProp.current)111 return this.hourCycleProp.current;112 return getDefaultHourCycle(this.locale.current);113 });114 rangeRoot = undefined;115 domContext = new DOMContext(() => null);116 constructor(props, rangeRoot) {117 this.rangeRoot = rangeRoot;118 /**119 * Since the `TimeFieldRootState` can be used in two contexts, as a standalone120 * field or as a field within a `TimeRangeField` component, we handle assigning121 * the props based on that context.122 */123 this.value = props.value;124 this.placeholder = rangeRoot ? rangeRoot.opts.placeholder : props.placeholder;125 this.validate = rangeRoot ? simpleBox(undefined) : props.validate;126 this.minValue = rangeRoot ? rangeRoot.opts.minValue : props.minValue;127 this.maxValue = rangeRoot ? rangeRoot.opts.maxValue : props.maxValue;128 this.disabled = rangeRoot ? rangeRoot.opts.disabled : props.disabled;129 this.readonly = rangeRoot ? rangeRoot.opts.readonly : props.readonly;130 this.granularity = rangeRoot ? rangeRoot.opts.granularity : props.granularity;131 this.readonlySegments = rangeRoot132 ? rangeRoot.opts.readonlySegments133 : props.readonlySegments;134 this.hourCycleProp = rangeRoot ? rangeRoot.opts.hourCycle : props.hourCycle;135 this.locale = rangeRoot ? rangeRoot.opts.locale : props.locale;136 this.hideTimeZone = rangeRoot ? rangeRoot.opts.hideTimeZone : props.hideTimeZone;137 this.required = rangeRoot ? rangeRoot.opts.required : props.required;138 this.onInvalid = rangeRoot ? rangeRoot.opts.onInvalid : props.onInvalid;139 this.errorMessageId = rangeRoot ? rangeRoot.opts.errorMessageId : props.errorMessageId;140 this.isInvalidProp = props.isInvalidProp;141 this.formatter = createTimeFormatter(this.locale.current);142 this.initialSegments = this.#initializeTimeSegmentValues();143 this.segmentValues = this.initialSegments;144 this.announcer = getAnnouncer(null);145 this.getFieldNode = this.getFieldNode.bind(this);146 this.updateSegment = this.updateSegment.bind(this);147 this.handleSegmentClick = this.handleSegmentClick.bind(this);148 this.getBaseSegmentAttrs = this.getBaseSegmentAttrs.bind(this);149 $effect(() => {150 untrack(() => {151 this.initialSegments = this.#initializeTimeSegmentValues();152 });153 });154 onMount(() => {155 this.announcer = getAnnouncer(this.domContext.getDocument());156 });157 onDestroyEffect(() => {158 removeTimeDescriptionElement(this.descriptionId, this.domContext.getDocument());159 });160 $effect(() => {161 if (this.formatter.getLocale() === this.locale.current)162 return;163 this.formatter.setLocale(this.locale.current);164 });165 $effect(() => {166 if (this.value.current) {167 const descriptionId = untrack(() => this.descriptionId);168 setTimeDescription({169 id: descriptionId,170 formatter: this.formatter,171 value: this.#toDateValue(this.value.current),172 doc: this.domContext.getDocument(),173 });174 }175 const placeholder = untrack(() => this.placeholder.current);176 if (this.value.current && placeholder !== this.value.current) {177 untrack(() => {178 if (this.value.current) {179 this.placeholder.current = this.value.current;180 }181 });182 }183 });184 if (this.value.current) {185 this.syncSegmentValues(this.value.current);186 }187 $effect(() => {188 this.locale.current;189 if (this.value.current) {190 this.syncSegmentValues(this.value.current);191 }192 this.#clearUpdating();193 });194 $effect(() => {195 if (this.value.current === undefined) {196 this.segmentValues = this.#initializeTimeSegmentValues();197 }198 });199 watch(() => this.validationStatus, () => {200 if (this.validationStatus !== false) {201 this.onInvalid.current?.(this.validationStatus.reason, this.validationStatus.message);202 }203 });204 }205 #initializeTimeSegmentValues() {206 const granularity = this.inferredGranularity;207 const segments = {208 hour: null,209 minute: null,210 second: null,211 dayPeriod: "AM",212 };213 if (granularity === "second") {214 segments.second = null;215 }216 if (this.hourCycle === 24) {217 segments.dayPeriod = null;218 }219 return segments;220 }221 #toDateValue(timeValue) {222 if ("calendar" in timeValue) {223 // CalendarDateTime or ZonedDateTime224 return timeValue;225 }226 else {227 return new CalendarDateTime(2000, 1, 1, timeValue.hour, timeValue.minute, timeValue.second, timeValue.millisecond);228 }229 }230 #clearUpdating() {231 this.states.hour.updating = null;232 this.states.minute.updating = null;233 this.states.second.updating = null;234 this.states.dayPeriod.updating = null;235 }236 setName(name) {237 this.name = name;238 }239 setFieldNode(node) {240 this.#fieldNode = node;241 }242 /**243 * Gets the correct field node for the time field regardless of whether it's being244 * used in a standalone context or within a `TimeRangeField` component.245 */246 getFieldNode() {247 /** If we're not within a TimeRangeField, we return this field. */248 if (!this.rangeRoot) {249 return this.#fieldNode;250 }251 else {252 /**253 * Otherwise, we return the rangeRoot's field node which254 * contains both start and end fields.255 */256 return this.rangeRoot.fieldNode;257 }258 }259 setLabelNode(node) {260 this.#labelNode = node;261 }262 getLabelNode() {263 return this.#labelNode;264 }265 setValue(value) {266 this.value.current = value;267 }268 syncSegmentValues(value) {269 const timeValues = EDITABLE_TIME_SEGMENT_PARTS.map((part) => {270 if (part === "dayPeriod") {271 if (this.states.dayPeriod.updating) {272 return [part, this.states.dayPeriod.updating];273 }274 else {275 return [part, this.formatter.dayPeriod(toDate(this.#toDateValue(value)))];276 }277 }278 else if (part === "hour") {279 if (this.states.hour.updating) {280 return [part, this.states.hour.updating];281 }282 if (value[part] !== undefined && value[part] < 10) {283 return [part, `0${value[part]}`];284 }285 if (value[part] === 0 && this.dayPeriodNode) {286 return [part, "12"];287 }288 }289 else if (part === "minute") {290 if (this.states.minute.updating) {291 return [part, this.states.minute.updating];292 }293 if (value[part] !== undefined && value[part] < 10) {294 return [part, `0${value[part]}`];295 }296 }297 else if (part === "second") {298 if (this.states.second.updating) {299 return [part, this.states.second.updating];300 }301 if (value[part] !== undefined && value[part] < 10) {302 return [part, `0${value[part]}`];303 }304 }305 return [part, `${value[part]}`];306 });307 this.segmentValues = Object.fromEntries(timeValues);308 this.#clearUpdating();309 }310 validationStatus = $derived.by(() => {311 const value = this.value.current;312 if (!value)313 return false;314 const msg = this.validate.current?.(value);315 if (msg) {316 return {317 reason: "custom",318 message: msg,319 };320 }321 if (!this.valueTime)322 return false;323 if (this.minValueTime && isTimeBefore(this.valueTime, this.minValueTime)) {324 return {325 reason: "min",326 };327 }328 if (this.maxValueTime && isTimeBefore(this.maxValueTime, this.valueTime)) {329 return {330 reason: "max",331 };332 }333 return false;334 });335 isInvalid = $derived.by(() => {336 if (this.validationStatus === false)337 return false;338 if (this.isInvalidProp.current)339 return true;340 return true;341 });342 inferredGranularity = $derived.by(() => {343 return this.granularity.current ?? "minute";344 });345 timeRef = $derived.by(() => this.value.current ?? this.placeholder.current);346 allSegmentContent = $derived.by(() => createTimeContent({347 segmentValues: this.segmentValues,348 formatter: this.formatter,349 locale: this.locale.current,350 granularity: this.inferredGranularity,351 timeRef: this.timeRef,352 hideTimeZone: this.hideTimeZone.current,353 hourCycle: this.hourCycle,354 }));355 segmentContents = $derived.by(() => this.allSegmentContent.arr);356 sharedSegmentAttrs = {357 role: "spinbutton",358 contenteditable: "true",359 tabindex: 0,360 spellcheck: false,361 inputmode: "numeric",362 autocorrect: "off",363 enterkeyhint: "next",364 style: {365 caretColor: "transparent",366 },367 };368 #getLabelledBy(segmentId) {369 return `${segmentId} ${this.getLabelNode()?.id ?? ""}`;370 }371 updateSegment(part, cb) {372 const disabled = this.disabled.current;373 const readonly = this.readonly.current;374 const readonlySegmentsSet = this.readonlySegmentsSet;375 if (disabled || readonly || readonlySegmentsSet.has(part))376 return;377 const prev = this.segmentValues;378 let newSegmentValues = prev;379 if (part === "dayPeriod") {380 const next = cb(prev[part]);381 this.states.dayPeriod.updating = next;382 const value = this.value.current;383 if (value && "hour" in value) {384 const trueHour = value.hour;385 if (next === "AM") {386 if (trueHour >= 12) {387 prev.hour = `${trueHour - 12}`;388 }389 }390 else if (next === "PM") {391 if (trueHour < 12) {392 prev.hour = `${trueHour + 12}`;393 }394 }395 }396 newSegmentValues = { ...prev, [part]: next };397 }398 else if (part === "hour") {399 const next = cb(prev[part]);400 this.states.hour.updating = next;401 if (next !== null && prev.dayPeriod !== null) {402 if (this.hourCycle !== 24 && this.hourInputDayPeriodHint !== null) {403 prev.dayPeriod = this.hourInputDayPeriodHint;404 }405 else {406 const dayPeriod = this.formatter.dayPeriod(toDate(this.#toDateValue(this.timeRef.set({ hour: Number.parseInt(next) }))), this.hourCycle);407 if (dayPeriod === "AM" || dayPeriod === "PM") {408 prev.dayPeriod = dayPeriod;409 }410 }411 }412 newSegmentValues = { ...prev, [part]: next };413 }414 else if (part === "minute") {415 const next = cb(prev[part]);416 this.states.minute.updating = next;417 newSegmentValues = { ...prev, [part]: next };418 }419 else if (part === "second") {420 const next = cb(prev[part]);421 this.states.second.updating = next;422 newSegmentValues = { ...prev, [part]: next };423 }424 this.segmentValues = newSegmentValues;425 const segmentObjForValue = part === "hour" &&426 this.hourCycle !== 24 &&427 this.hourInputDayPeriodHint !== null &&428 newSegmentValues.hour !== null429 ? {430 ...newSegmentValues,431 hour: get24HourValueFromTypedHour(newSegmentValues.hour, this.hourInputDayPeriodHint),432 }433 : newSegmentValues;434 if (areAllTimeSegmentsFilled(newSegmentValues, this.#fieldNode)) {435 this.setValue(getTimeValueFromSegments({436 segmentObj: segmentObjForValue,437 fieldNode: this.#fieldNode,438 timeRef: this.timeRef,439 }));440 }441 }442 handleSegmentClick(e) {443 if (this.disabled.current) {444 e.preventDefault();445 }446 }447 getBaseSegmentAttrs(part, segmentId) {448 const inReadonlySegments = this.readonlySegmentsSet.has(part);449 const defaultAttrs = {450 "aria-invalid": boolToStrTrueOrUndef(this.isInvalid),451 "aria-disabled": boolToStr(this.disabled.current),452 "aria-readonly": boolToStr(this.readonly.current || inReadonlySegments),453 "data-invalid": boolToEmptyStrOrUndef(this.isInvalid),454 "data-disabled": boolToEmptyStrOrUndef(this.disabled.current),455 "data-readonly": boolToEmptyStrOrUndef(this.readonly.current || inReadonlySegments),456 "data-segment": `${part}`,457 };458 if (part === "literal")459 return defaultAttrs;460 const descriptionId = this.descriptionNode?.id;461 const hasDescription = isFirstTimeSegment(segmentId, this.#fieldNode) && descriptionId;462 const errorMsgId = this.errorMessageId?.current;463 const describedBy = hasDescription464 ? `${descriptionId} ${this.isInvalid && errorMsgId ? errorMsgId : ""}`465 : undefined;466 const contenteditable = !(this.readonly.current ||467 inReadonlySegments ||468 this.disabled.current);469 return {470 ...defaultAttrs,471 "aria-labelledby": this.#getLabelledBy(segmentId),472 contenteditable: contenteditable ? "true" : undefined,473 "aria-describedby": describedBy,474 tabindex: this.disabled.current ? undefined : 0,475 };476 }477}478export class TimeFieldInputState {479 static create(opts) {480 return new TimeFieldInputState(opts, TimeFieldRootContext.get());481 }482 opts;483 root;484 attachment;485 domContext;486 constructor(opts, root) {487 this.opts = opts;488 this.root = root;489 this.attachment = attachRef(opts.ref, (v) => this.root.setFieldNode(v));490 this.domContext = new DOMContext(opts.ref);491 this.root.setName(this.opts.name.current);492 $effect(() => {493 this.root.setName(this.opts.name.current);494 });495 }496 #ariaDescribedBy = $derived.by(() => {497 if (!isBrowser)498 return undefined;499 const doesDescriptionExist = this.domContext.getElementById(this.root.descriptionId);500 if (!doesDescriptionExist)501 return undefined;502 return this.root.descriptionId;503 });504 props = $derived.by(() => ({505 id: this.opts.id.current,506 role: "group",507 "aria-labelledby": this.root.getLabelNode()?.id ?? undefined,508 "aria-describedby": this.#ariaDescribedBy,509 "aria-disabled": boolToStr(this.root.disabled.current),510 "data-invalid": this.root.isInvalid ? "" : undefined,511 "data-disabled": boolToEmptyStrOrUndef(this.root.disabled.current),512 [timeFieldAttrs.input]: "",513 ...this.attachment,514 }));515}516export class TimeFieldHiddenInputState {517 static create() {518 return new TimeFieldHiddenInputState(TimeFieldRootContext.get());519 }520 root;521 shouldRender = $derived.by(() => this.root.name !== "");522 isoValue = $derived.by(() => this.root.value.current ? getISOTimeValue(this.root.value.current) : undefined);523 constructor(root) {524 this.root = root;525 }526 props = $derived.by(() => ({527 name: this.root.name,528 value: this.isoValue,529 required: this.root.required.current,530 }));531}532export class TimeFieldLabelState {533 static create(opts) {534 return new TimeFieldLabelState(opts, TimeFieldRootContext.get());535 }536 opts;537 root;538 attachment;539 constructor(opts, root) {540 this.opts = opts;541 this.root = root;542 this.attachment = attachRef(opts.ref, (v) => this.root.setLabelNode(v));543 this.onclick = this.onclick.bind(this);544 }545 onclick(_) {546 if (this.root.disabled.current)547 return;548 const firstSegment = getFirstTimeSegment(this.root.getFieldNode());549 if (!firstSegment)550 return;551 firstSegment.focus();552 }553 props = $derived.by(() => ({554 id: this.opts.id.current,555 "data-invalid": boolToEmptyStrOrUndef(this.root.isInvalid),556 "data-disabled": boolToEmptyStrOrUndef(this.root.disabled.current),557 [timeFieldAttrs.label]: "",558 onclick: this.onclick,559 ...this.attachment,560 }));561}562// Base class for time segments - simplified from date-field version563class BaseTimeSegmentState {564 opts;565 root;566 announcer;567 part;568 config;569 attachment;570 constructor(opts, root, part, config) {571 this.opts = opts;572 this.root = root;573 this.part = part;574 this.config = config;575 this.announcer = root.announcer;576 this.attachment = attachRef(opts.ref);577 this.onkeydown = this.onkeydown.bind(this);578 this.onfocusout = this.onfocusout.bind(this);579 }580 #getMax() {581 return typeof this.config.max === "function" ? this.config.max(this.root) : this.config.max;582 }583 #getMin() {584 return typeof this.config.min === "function" ? this.config.min(this.root) : this.config.min;585 }586 #formatValue(value, forDisplay = true) {587 const str = String(value);588 if (forDisplay && this.config.padZero && str.length === 1) {589 return `0${value}`;590 }591 return str;592 }593 onkeydown(e) {594 const placeholder = this.root.value.current ?? this.root.placeholder.current;595 if (e.ctrlKey || e.metaKey || this.root.disabled.current)596 return;597 if (e.key !== kbd.TAB)598 e.preventDefault();599 if (!isAcceptableSegmentKey(e.key))600 return;601 if (isArrowUp(e.key)) {602 this.#handleArrowUp(placeholder);603 return;604 }605 if (isArrowDown(e.key)) {606 this.#handleArrowDown(placeholder);607 return;608 }609 if (isNumberString(e.key)) {610 this.#handleNumberKey(e);611 return;612 }613 if (isBackspace(e.key)) {614 this.#handleBackspace(e);615 return;616 }617 if (isSegmentNavigationKey(e.key)) {618 handleTimeSegmentNavigation(e, this.root.getFieldNode());619 }620 }621 #handleArrowUp(placeholder) {622 const stateKey = this.part;623 if (stateKey in this.root.states) {624 this.root.states[stateKey].hasLeftFocus = false;625 }626 // @ts-expect-error shhh627 this.root.updateSegment(this.part, (prev) => {628 if (prev === null) {629 const next = placeholder[this.part];630 this.announcer.announce(String(next));631 return this.#formatValue(next);632 }633 const current = placeholder.set({634 [this.part]: Number.parseInt(prev),635 });636 // @ts-expect-error shhh637 const next = current.cycle(this.part, this.config.cycle)[this.part];638 this.announcer.announce(String(next));639 return this.#formatValue(next);640 });641 }642 #handleArrowDown(placeholder) {643 const stateKey = this.part;644 if (stateKey in this.root.states) {645 this.root.states[stateKey].hasLeftFocus = false;646 }647 // @ts-expect-error - this is a part648 this.root.updateSegment(this.part, (prev) => {649 if (prev === null) {650 const next = placeholder[this.part];651 this.announcer.announce(String(next));652 return this.#formatValue(next);653 }654 const current = placeholder.set({655 [this.part]: Number.parseInt(prev),656 });657 // @ts-expect-error shhh658 const next = current.cycle(this.part, -this.config.cycle)[this.part];659 this.announcer.announce(String(next));660 return this.#formatValue(next);661 });662 }663 #handleNumberKey(e) {664 const num = Number.parseInt(e.key);665 let moveToNext = false;666 const max = this.#getMax();667 const maxStart = Math.floor(max / 10);668 const numIsZero = num === 0;669 const stateKey = this.part;670 // @ts-expect-error this is a part671 this.root.updateSegment(this.part, (prev) => {672 if (stateKey in this.root.states && this.root.states[stateKey].hasLeftFocus) {673 prev = null;674 this.root.states[stateKey].hasLeftFocus = false;675 }676 if (prev === null) {677 if (numIsZero) {678 if (stateKey in this.root.states) {679 this.root.states[stateKey].lastKeyZero = true;680 }681 this.announcer.announce("0");682 return "0";683 }684 if (stateKey in this.root.states &&685 (this.root.states[stateKey].lastKeyZero || num > maxStart)) {686 moveToNext = true;687 }688 if (stateKey in this.root.states) {689 this.root.states[stateKey].lastKeyZero = false;690 }691 if (moveToNext && String(num).length === 1) {692 this.announcer.announce(num);693 return `0${num}`;694 }695 return `${num}`;696 }697 if (stateKey in this.root.states && this.root.states[stateKey].lastKeyZero) {698 if (num !== 0) {699 moveToNext = true;700 this.root.states[stateKey].lastKeyZero = false;701 return `0${num}`;702 }703 if (this.part === "hour" && num === 0 && this.root.hourCycle === 24) {704 moveToNext = true;705 this.root.states[stateKey].lastKeyZero = false;706 return `00`;707 }708 if ((this.part === "minute" || this.part === "second") && num === 0) {709 moveToNext = true;710 this.root.states[stateKey].lastKeyZero = false;711 return "00";712 }713 return prev;714 }715 const total = Number.parseInt(prev + num.toString());716 if (total > max) {717 moveToNext = true;718 return `0${num}`;719 }720 moveToNext = true;721 return `${total}`;722 });723 if (moveToNext) {724 moveToNextTimeSegment(e, this.root.getFieldNode());725 }726 }727 #handleBackspace(e) {728 const stateKey = this.part;729 if (stateKey in this.root.states) {730 this.root.states[stateKey].hasLeftFocus = false;731 }732 let moveToPrev = false;733 // @ts-expect-error this is a part734 this.root.updateSegment(this.part, (prev) => {735 if (prev === null) {736 moveToPrev = true;737 this.announcer.announce(null);738 return null;739 }740 if (prev.length === 2 && prev.startsWith("0")) {741 this.announcer.announce(null);742 return null;743 }744 const str = prev.toString();745 if (str.length === 1) {746 this.announcer.announce(null);747 return null;748 }749 const next = Number.parseInt(str.slice(0, -1));750 this.announcer.announce(String(next));751 return `${next}`;752 });753 if (moveToPrev) {754 moveToPrevTimeSegment(e, this.root.getFieldNode());755 }756 }757 onfocusout(_) {758 const stateKey = this.part;759 if (stateKey in this.root.states) {760 this.root.states[stateKey].hasLeftFocus = true;761 }762 // Pad with zero if needed763 if (this.config.padZero) {764 // @ts-expect-error this is a part765 this.root.updateSegment(this.part, (prev) => {766 if (prev && prev.length === 1) {767 return `0${prev}`;768 }769 return prev;770 });771 }772 }773 getSegmentProps() {774 const segmentValues = this.root.segmentValues;775 const placeholder = this.root.placeholder.current;776 const isEmpty = segmentValues[this.part] === null;777 let value = placeholder;778 if (segmentValues[this.part]) {779 value = placeholder.set({780 [this.part]: Number.parseInt(segmentValues[this.part]),781 });782 }783 const valueNow = value[this.part];784 const valueMin = this.#getMin();785 const valueMax = this.#getMax();786 let valueText = isEmpty ? "Empty" : `${valueNow}`;787 // special handling for hour segment with dayPeriod788 if (this.part === "hour" && "dayPeriod" in segmentValues && segmentValues.dayPeriod) {789 valueText = isEmpty ? "Empty" : `${valueNow} ${segmentValues.dayPeriod}`;790 }791 return {792 "aria-label": `${this.part}, `,793 "aria-valuemin": valueMin,794 "aria-valuemax": valueMax,795 "aria-valuenow": valueNow,796 "aria-valuetext": valueText,797 };798 }799 props = $derived.by(() => {800 return {801 ...this.root.sharedSegmentAttrs,802 id: this.opts.id.current,803 ...this.getSegmentProps(),804 onkeydown: this.onkeydown,805 onfocusout: this.onfocusout,806 onclick: this.root.handleSegmentClick,807 ...this.root.getBaseSegmentAttrs(this.part, this.opts.id.current),808 ...this.attachment,809 };810 });811}812class TimeFieldHourSegmentState extends BaseTimeSegmentState {813 constructor(opts, root) {814 super(opts, root, "hour", SEGMENT_CONFIGS.hour);815 }816 onkeydown(e) {817 const oldUpdateSegment = this.root.updateSegment.bind(this.root);818 if (isNumberString(e.key)) {819 this.root.hourInputDayPeriodHint =820 this.root.hourCycle === 24 ? null : this.root.segmentValues.dayPeriod;821 this.root.updateSegment = (part, cb) => {822 oldUpdateSegment(part, cb);823 // after updating hour, check if we need to display "12" instead of "0"824 if (part === "hour" && "hour" in this.root.segmentValues) {825 const hourValue = this.root.segmentValues.hour;826 if (hourValue === "0" &&827 this.root.dayPeriodNode &&828 this.root.hourCycle !== 24) {829 this.root.segmentValues.hour = "12";830 }831 }832 };833 }834 super.onkeydown(e);835 this.root.updateSegment = oldUpdateSegment;836 this.root.hourInputDayPeriodHint = null;837 }838}839class TimeFieldMinuteSegmentState extends BaseTimeSegmentState {840 constructor(opts, root) {841 super(opts, root, "minute", SEGMENT_CONFIGS.minute);842 }843}844class TimeFieldSecondSegmentState extends BaseTimeSegmentState {845 constructor(opts, root) {846 super(opts, root, "second", SEGMENT_CONFIGS.second);847 }848}849class TimeFieldDayPeriodSegmentState {850 opts;851 root;852 attachment;853 #announcer;854 constructor(opts, root) {855 this.opts = opts;856 this.root = root;857 this.#announcer = this.root.announcer;858 this.attachment = attachRef(opts.ref, (v) => (this.root.dayPeriodNode = v));859 this.onkeydown = this.onkeydown.bind(this);860 this.onbeforeinput = this.onbeforeinput.bind(this);861 }862 onbeforeinput(e) {863 if (this.root.disabled.current)864 return;865 const data = typeof e.data === "string" ? e.data.trim().toLowerCase() : "";866 if (!data)867 return;868 e.preventDefault();869 if (data === "a" || data === "p") {870 this.root.updateSegment("dayPeriod", () => {871 const next = data === "a" ? "AM" : "PM";872 this.#announcer.announce(next);873 return next;874 });875 }876 }877 onkeydown(e) {878 if (e.ctrlKey || e.metaKey || this.root.disabled.current)879 return;880 if (e.key !== kbd.TAB)881 e.preventDefault();882 if (!isAcceptableDayPeriodKey(e.key))883 return;884 if (isArrowUp(e.key) || isArrowDown(e.key)) {885 this.root.updateSegment("dayPeriod", (prev) => {886 if (prev === "AM") {887 const next = "PM";888 this.#announcer.announce(next);889 return next;890 }891 const next = "AM";892 this.#announcer.announce(next);893 return next;894 });895 return;896 }897 if (isBackspace(e.key)) {898 this.root.states.dayPeriod.hasLeftFocus = false;899 this.root.updateSegment("dayPeriod", () => {900 const next = "AM";901 this.#announcer.announce(next);902 return next;903 });904 }905 if (e.key === kbd.A || e.key === kbd.P || e.key === kbd.a || e.key === kbd.p) {906 this.root.updateSegment("dayPeriod", () => {907 const next = e.key === kbd.A || e.key === kbd.a ? "AM" : "PM";908 this.#announcer.announce(next);909 return next;910 });911 }912 if (isSegmentNavigationKey(e.key)) {913 handleTimeSegmentNavigation(e, this.root.getFieldNode());914 }915 }916 props = $derived.by(() => {917 const segmentValues = this.root.segmentValues;918 if (!("dayPeriod" in segmentValues))919 return;920 const valueMin = 0;921 const valueMax = 12;922 const valueNow = segmentValues.dayPeriod === "AM" ? 0 : 12;923 const valueText = segmentValues.dayPeriod === "AM" ? "AM" : "PM";924 return {925 ...this.root.sharedSegmentAttrs,926 id: this.opts.id.current,927 inputmode: "text",928 "aria-label": "AM/PM",929 "aria-valuemin": valueMin,930 "aria-valuemax": valueMax,931 "aria-valuenow": valueNow,932 "aria-valuetext": valueText,933 onkeydown: this.onkeydown,934 onbeforeinput: this.onbeforeinput,935 onclick: this.root.handleSegmentClick,936 ...this.root.getBaseSegmentAttrs("dayPeriod", this.opts.id.current),937 ...this.attachment,938 };939 });940}941class TimeFieldLiteralSegmentState {942 opts;943 root;944 attachment;945 constructor(opts, root) {946 this.opts = opts;947 this.root = root;948 this.attachment = attachRef(opts.ref);949 }950 props = $derived.by(() => ({951 id: this.opts.id.current,952 "aria-hidden": boolToStrTrueOrUndef(true),953 ...this.root.getBaseSegmentAttrs("literal", this.opts.id.current),954 ...this.attachment,955 }));956}957class TimeFieldTimeZoneSegmentState {958 opts;959 root;960 attachment;961 constructor(opts, root) {962 this.opts = opts;963 this.root = root;964 this.attachment = attachRef(opts.ref);965 this.onkeydown = this.onkeydown.bind(this);966 }967 onkeydown(e) {968 if (e.key !== kbd.TAB)969 e.preventDefault();970 if (this.root.disabled.current)971 return;972 if (isSegmentNavigationKey(e.key)) {973 handleTimeSegmentNavigation(e, this.root.getFieldNode());974 }975 }976 props = $derived.by(() => ({977 role: "textbox",978 id: this.opts.id.current,979 "aria-label": "timezone, ",980 style: {981 caretColor: "transparent",982 },983 onkeydown: this.onkeydown,984 tabindex: 0,985 ...this.root.getBaseSegmentAttrs("timeZoneName", this.opts.id.current),986 "data-readonly": boolToEmptyStrOrUndef(true),987 ...this.attachment,988 }));989}990export class DateFieldSegmentState {991 static create(part, opts) {992 const root = TimeFieldRootContext.get();993 switch (part) {994 case "hour":995 return new TimeFieldHourSegmentState(opts, root);996 case "minute":997 return new TimeFieldMinuteSegmentState(opts, root);998 case "second":999 return new TimeFieldSecondSegmentState(opts, root);1000 case "dayPeriod":1001 return new TimeFieldDayPeriodSegmentState(opts, root);1002 case "literal":1003 return new TimeFieldLiteralSegmentState(opts, root);1004 case "timeZoneName":1005 return new TimeFieldTimeZoneSegmentState(opts, root);1006 default:1007 throw new Error(`Invalid part: ${part}`);1008 }1009 }1010}1011// Utils/helpers1012function isAcceptableDayPeriodKey(key) {1013 return (isAcceptableSegmentKey(key) ||1014 key === kbd.A ||1015 key === kbd.P ||1016 key === kbd.a ||1017 key === kbd.p);1018}1019function isArrowUp(key) {1020 return key === kbd.ARROW_UP;1021}1022function isArrowDown(key) {1023 return key === kbd.ARROW_DOWN;1024}1025function isBackspace(key) {1026 return key === kbd.BACKSPACE;1027}1028 