svelte-ag 0.0.2-dev.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/app.css +209 -0
- package/dist/app.d.ts +13 -0
- package/dist/app.html +12 -0
- package/dist/icons.css +6 -0
- package/dist/lib/bits/internal/arrays.d.ts +95 -0
- package/dist/lib/bits/internal/arrays.js +250 -0
- package/dist/lib/bits/internal/arrays.test.d.ts +1 -0
- package/dist/lib/bits/internal/arrays.test.js +366 -0
- package/dist/lib/bits/internal/attrs.d.ts +22 -0
- package/dist/lib/bits/internal/attrs.js +69 -0
- package/dist/lib/bits/internal/box-auto-reset.svelte.d.ts +8 -0
- package/dist/lib/bits/internal/box-auto-reset.svelte.js +31 -0
- package/dist/lib/bits/internal/box.svelte.d.ts +21 -0
- package/dist/lib/bits/internal/box.svelte.js +26 -0
- package/dist/lib/bits/internal/clamp.d.ts +4 -0
- package/dist/lib/bits/internal/clamp.js +6 -0
- package/dist/lib/bits/internal/clamp.test.d.ts +1 -0
- package/dist/lib/bits/internal/clamp.test.js +31 -0
- package/dist/lib/bits/internal/create-event-hook.svelte.d.ts +18 -0
- package/dist/lib/bits/internal/create-event-hook.svelte.js +29 -0
- package/dist/lib/bits/internal/create-shared-hook.svelte.d.ts +2 -0
- package/dist/lib/bits/internal/create-shared-hook.svelte.js +27 -0
- package/dist/lib/bits/internal/date-time/announcer.d.ts +7 -0
- package/dist/lib/bits/internal/date-time/announcer.js +82 -0
- package/dist/lib/bits/internal/date-time/calendar-helpers.svelte.d.ts +201 -0
- package/dist/lib/bits/internal/date-time/calendar-helpers.svelte.js +510 -0
- package/dist/lib/bits/internal/date-time/field/helpers.d.ts +76 -0
- package/dist/lib/bits/internal/date-time/field/helpers.js +378 -0
- package/dist/lib/bits/internal/date-time/field/parts.d.ts +6 -0
- package/dist/lib/bits/internal/date-time/field/parts.js +9 -0
- package/dist/lib/bits/internal/date-time/field/segments.d.ts +51 -0
- package/dist/lib/bits/internal/date-time/field/segments.js +128 -0
- package/dist/lib/bits/internal/date-time/field/types.d.ts +25 -0
- package/dist/lib/bits/internal/date-time/field/types.js +1 -0
- package/dist/lib/bits/internal/date-time/formatter.d.ts +24 -0
- package/dist/lib/bits/internal/date-time/formatter.js +97 -0
- package/dist/lib/bits/internal/date-time/placeholders.d.ts +8 -0
- package/dist/lib/bits/internal/date-time/placeholders.js +129 -0
- package/dist/lib/bits/internal/date-time/utils.d.ts +69 -0
- package/dist/lib/bits/internal/date-time/utils.js +212 -0
- package/dist/lib/bits/internal/debounce.d.ts +4 -0
- package/dist/lib/bits/internal/debounce.js +19 -0
- package/dist/lib/bits/internal/debounce.test.d.ts +1 -0
- package/dist/lib/bits/internal/debounce.test.js +50 -0
- package/dist/lib/bits/internal/dom.d.ts +10 -0
- package/dist/lib/bits/internal/dom.js +38 -0
- package/dist/lib/bits/internal/elements.d.ts +2 -0
- package/dist/lib/bits/internal/elements.js +6 -0
- package/dist/lib/bits/internal/events.d.ts +21 -0
- package/dist/lib/bits/internal/events.js +49 -0
- package/dist/lib/bits/internal/floating-svelte/floating-utils.svelte.d.ts +7 -0
- package/dist/lib/bits/internal/floating-svelte/floating-utils.svelte.js +24 -0
- package/dist/lib/bits/internal/floating-svelte/types.d.ts +85 -0
- package/dist/lib/bits/internal/floating-svelte/types.js +1 -0
- package/dist/lib/bits/internal/floating-svelte/use-floating.svelte.d.ts +2 -0
- package/dist/lib/bits/internal/floating-svelte/use-floating.svelte.js +112 -0
- package/dist/lib/bits/internal/focus.d.ts +46 -0
- package/dist/lib/bits/internal/focus.js +109 -0
- package/dist/lib/bits/internal/get-directional-keys.d.ts +21 -0
- package/dist/lib/bits/internal/get-directional-keys.js +37 -0
- package/dist/lib/bits/internal/get-directional-keys.test.d.ts +1 -0
- package/dist/lib/bits/internal/get-directional-keys.test.js +46 -0
- package/dist/lib/bits/internal/is.d.ts +25 -0
- package/dist/lib/bits/internal/is.js +62 -0
- package/dist/lib/bits/internal/is.test.d.ts +1 -0
- package/dist/lib/bits/internal/is.test.js +34 -0
- package/dist/lib/bits/internal/kbd-constants.d.ts +40 -0
- package/dist/lib/bits/internal/kbd-constants.js +40 -0
- package/dist/lib/bits/internal/kbd.d.ts +1 -0
- package/dist/lib/bits/internal/kbd.js +1 -0
- package/dist/lib/bits/internal/locale.d.ts +6 -0
- package/dist/lib/bits/internal/locale.js +9 -0
- package/dist/lib/bits/internal/math.d.ts +5 -0
- package/dist/lib/bits/internal/math.js +43 -0
- package/dist/lib/bits/internal/math.test.d.ts +1 -0
- package/dist/lib/bits/internal/math.test.js +71 -0
- package/dist/lib/bits/internal/noop.d.ts +4 -0
- package/dist/lib/bits/internal/noop.js +4 -0
- package/dist/lib/bits/internal/should-trap-focus.d.ts +6 -0
- package/dist/lib/bits/internal/should-trap-focus.js +6 -0
- package/dist/lib/bits/internal/sleep.d.ts +1 -0
- package/dist/lib/bits/internal/sleep.js +3 -0
- package/dist/lib/bits/internal/tabbable.d.ts +10 -0
- package/dist/lib/bits/internal/tabbable.js +66 -0
- package/dist/lib/bits/internal/types.d.ts +92 -0
- package/dist/lib/bits/internal/types.js +1 -0
- package/dist/lib/bits/internal/use-after-animations.svelte.d.ts +5 -0
- package/dist/lib/bits/internal/use-after-animations.svelte.js +27 -0
- package/dist/lib/bits/internal/use-arrow-navigation.d.ts +62 -0
- package/dist/lib/bits/internal/use-arrow-navigation.js +76 -0
- package/dist/lib/bits/internal/use-body-scroll-lock.svelte.d.ts +6 -0
- package/dist/lib/bits/internal/use-body-scroll-lock.svelte.js +106 -0
- package/dist/lib/bits/internal/use-data-typeahead.svelte.d.ts +14 -0
- package/dist/lib/bits/internal/use-data-typeahead.svelte.js +31 -0
- package/dist/lib/bits/internal/use-dom-typeahead.svelte.d.ts +11 -0
- package/dist/lib/bits/internal/use-dom-typeahead.svelte.js +30 -0
- package/dist/lib/bits/internal/use-form-control.svelte.d.ts +4 -0
- package/dist/lib/bits/internal/use-form-control.svelte.js +16 -0
- package/dist/lib/bits/internal/use-grace-area.svelte.d.ts +12 -0
- package/dist/lib/bits/internal/use-grace-area.svelte.js +197 -0
- package/dist/lib/bits/internal/use-id.d.ts +4 -0
- package/dist/lib/bits/internal/use-id.js +8 -0
- package/dist/lib/bits/internal/use-resize-observer.svelte.d.ts +2 -0
- package/dist/lib/bits/internal/use-resize-observer.svelte.js +17 -0
- package/dist/lib/bits/internal/use-roving-focus.svelte.d.ts +38 -0
- package/dist/lib/bits/internal/use-roving-focus.svelte.js +91 -0
- package/dist/lib/bits/internal/use-size.svelte.d.ts +7 -0
- package/dist/lib/bits/internal/use-size.svelte.js +54 -0
- package/dist/lib/bits/internal/use-state-machine.svelte.d.ts +24 -0
- package/dist/lib/bits/internal/use-state-machine.svelte.js +28 -0
- package/dist/lib/bits/internal/use-timeout-fn.svelte.d.ts +25 -0
- package/dist/lib/bits/internal/use-timeout-fn.svelte.js +39 -0
- package/dist/lib/components/Typeahead.svelte.d.ts +47 -0
- package/dist/lib/components/Typeahead.svelte.js +150 -0
- package/dist/lib/components/animated/animated.svelte +244 -0
- package/dist/lib/components/animated/animated.svelte.d.ts +61 -0
- package/dist/lib/components/animated/index.d.ts +2 -0
- package/dist/lib/components/animated/index.js +2 -0
- package/dist/lib/components/combo/combo.svelte +186 -0
- package/dist/lib/components/combo/combo.svelte.d.ts +21 -0
- package/dist/lib/components/combo/index.d.ts +2 -0
- package/dist/lib/components/combo/index.js +2 -0
- package/dist/lib/components/dnd/Droppable.svelte +25 -0
- package/dist/lib/components/dnd/Droppable.svelte.d.ts +10 -0
- package/dist/lib/components/dnd/context.svelte.d.ts +22 -0
- package/dist/lib/components/dnd/context.svelte.js +25 -0
- package/dist/lib/components/dnd/dnd-context.svelte +45 -0
- package/dist/lib/components/dnd/dnd-context.svelte.d.ts +30 -0
- package/dist/lib/components/dnd/dnd-drag-overlay.svelte +44 -0
- package/dist/lib/components/dnd/dnd-drag-overlay.svelte.d.ts +27 -0
- package/dist/lib/components/dnd/dnd-drag-placeholder.svelte +24 -0
- package/dist/lib/components/dnd/dnd-drag-placeholder.svelte.d.ts +9 -0
- package/dist/lib/components/dnd/dnd-draghandle.svelte +30 -0
- package/dist/lib/components/dnd/dnd-draghandle.svelte.d.ts +6 -0
- package/dist/lib/components/dnd/dnd-overlay.svelte +0 -0
- package/dist/lib/components/dnd/dnd-overlay.svelte.d.ts +26 -0
- package/dist/lib/components/dnd/dnd-sortable-context.svelte +18 -0
- package/dist/lib/components/dnd/dnd-sortable-context.svelte.d.ts +8 -0
- package/dist/lib/components/dnd/dnd-sortable-item.svelte +68 -0
- package/dist/lib/components/dnd/dnd-sortable-item.svelte.d.ts +23 -0
- package/dist/lib/components/dnd/example.svelte +109 -0
- package/dist/lib/components/dnd/example.svelte.d.ts +3 -0
- package/dist/lib/components/dnd/exports.d.ts +9 -0
- package/dist/lib/components/dnd/exports.js +9 -0
- package/dist/lib/components/dnd/index.d.ts +1 -0
- package/dist/lib/components/dnd/index.js +1 -0
- package/dist/lib/components/dnd/sortable.svelte.d.ts +13 -0
- package/dist/lib/components/dnd/sortable.svelte.js +70 -0
- package/dist/lib/components/dnd/utils.svelte.d.ts +20 -0
- package/dist/lib/components/dnd/utils.svelte.js +20 -0
- package/dist/lib/components/search/combinations/searchPopover.svelte +68 -0
- package/dist/lib/components/search/combinations/searchPopover.svelte.d.ts +22 -0
- package/dist/lib/components/search/components/search-empty.svelte +28 -0
- package/dist/lib/components/search/components/search-empty.svelte.d.ts +4 -0
- package/dist/lib/components/search/components/search-input.svelte +53 -0
- package/dist/lib/components/search/components/search-input.svelte.d.ts +4 -0
- package/dist/lib/components/search/components/search-list.svelte +46 -0
- package/dist/lib/components/search/components/search-list.svelte.d.ts +4 -0
- package/dist/lib/components/search/components/search-pagnation.svelte +68 -0
- package/dist/lib/components/search/components/search-pagnation.svelte.d.ts +8 -0
- package/dist/lib/components/search/components/search.svelte +47 -0
- package/dist/lib/components/search/components/search.svelte.d.ts +4 -0
- package/dist/lib/components/search/exports.d.ts +6 -0
- package/dist/lib/components/search/exports.js +5 -0
- package/dist/lib/components/search/index.d.ts +2 -0
- package/dist/lib/components/search/index.js +2 -0
- package/dist/lib/components/search/search.svelte.d.ts +102 -0
- package/dist/lib/components/search/search.svelte.js +202 -0
- package/dist/lib/components/search/types.d.ts +28 -0
- package/dist/lib/components/search/types.js +1 -0
- package/dist/lib/components/utilities/arrow/arrow.svelte +23 -0
- package/dist/lib/components/utilities/arrow/arrow.svelte.d.ts +3 -0
- package/dist/lib/components/utilities/arrow/index.d.ts +2 -0
- package/dist/lib/components/utilities/arrow/index.js +1 -0
- package/dist/lib/components/utilities/arrow/types.d.ts +17 -0
- package/dist/lib/components/utilities/arrow/types.js +1 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-anchor.svelte +15 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-anchor.svelte.d.ts +4 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-arrow.svelte +20 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-arrow.svelte.d.ts +3 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-content-static.svelte +19 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-content-static.svelte.d.ts +13 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-content.svelte +61 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer-content.svelte.d.ts +4 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer.svelte +10 -0
- package/dist/lib/components/utilities/floating-layer/components/floating-layer.svelte.d.ts +7 -0
- package/dist/lib/components/utilities/floating-layer/components/index.d.ts +6 -0
- package/dist/lib/components/utilities/floating-layer/components/index.js +5 -0
- package/dist/lib/components/utilities/floating-layer/index.d.ts +1 -0
- package/dist/lib/components/utilities/floating-layer/index.js +1 -0
- package/dist/lib/components/utilities/floating-layer/types.d.ts +115 -0
- package/dist/lib/components/utilities/floating-layer/types.js +1 -0
- package/dist/lib/components/utilities/floating-layer/use-floating-layer.svelte.d.ts +118 -0
- package/dist/lib/components/utilities/floating-layer/use-floating-layer.svelte.js +311 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/utils/asyncDerived.svelte.d.ts +12 -0
- package/dist/lib/utils/asyncDerived.svelte.js +26 -0
- package/dist/lib/utils/bits.d.ts +39 -0
- package/dist/lib/utils/bits.js +69 -0
- package/dist/lib/utils/index.d.ts +3 -0
- package/dist/lib/utils/index.js +3 -0
- package/dist/lib/utils/utils.d.ts +21 -0
- package/dist/lib/utils/utils.js +72 -0
- package/dist/routes/+layout.svelte +0 -0
- package/dist/routes/+layout.svelte.d.ts +26 -0
- package/package.json +79 -0
- package/src/app.css +209 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +12 -0
- package/src/icons.css +6 -0
- package/src/lib/bits/internal/arrays.test.ts +460 -0
- package/src/lib/bits/internal/arrays.ts +301 -0
- package/src/lib/bits/internal/attrs.ts +97 -0
- package/src/lib/bits/internal/box-auto-reset.svelte.ts +40 -0
- package/src/lib/bits/internal/box.svelte.ts +60 -0
- package/src/lib/bits/internal/clamp.test.ts +37 -0
- package/src/lib/bits/internal/clamp.ts +6 -0
- package/src/lib/bits/internal/create-event-hook.svelte.ts +64 -0
- package/src/lib/bits/internal/create-shared-hook.svelte.ts +33 -0
- package/src/lib/bits/internal/date-time/announcer.ts +88 -0
- package/src/lib/bits/internal/date-time/calendar-helpers.svelte.ts +815 -0
- package/src/lib/bits/internal/date-time/field/helpers.ts +441 -0
- package/src/lib/bits/internal/date-time/field/parts.ts +9 -0
- package/src/lib/bits/internal/date-time/field/segments.ts +126 -0
- package/src/lib/bits/internal/date-time/field/types.ts +35 -0
- package/src/lib/bits/internal/date-time/formatter.ts +116 -0
- package/src/lib/bits/internal/date-time/placeholders.ts +143 -0
- package/src/lib/bits/internal/date-time/utils.ts +261 -0
- package/src/lib/bits/internal/debounce.test.ts +67 -0
- package/src/lib/bits/internal/debounce.ts +22 -0
- package/src/lib/bits/internal/dom.ts +47 -0
- package/src/lib/bits/internal/elements.ts +7 -0
- package/src/lib/bits/internal/events.ts +89 -0
- package/src/lib/bits/internal/floating-svelte/floating-utils.svelte.ts +28 -0
- package/src/lib/bits/internal/floating-svelte/types.ts +108 -0
- package/src/lib/bits/internal/floating-svelte/use-floating.svelte.ts +133 -0
- package/src/lib/bits/internal/focus.ts +111 -0
- package/src/lib/bits/internal/get-directional-keys.test.ts +51 -0
- package/src/lib/bits/internal/get-directional-keys.ts +43 -0
- package/src/lib/bits/internal/is.test.ts +40 -0
- package/src/lib/bits/internal/is.ts +78 -0
- package/src/lib/bits/internal/kbd-constants.ts +40 -0
- package/src/lib/bits/internal/kbd.ts +1 -0
- package/src/lib/bits/internal/locale.ts +13 -0
- package/src/lib/bits/internal/math.test.ts +88 -0
- package/src/lib/bits/internal/math.ts +50 -0
- package/src/lib/bits/internal/noop.ts +4 -0
- package/src/lib/bits/internal/should-trap-focus.ts +16 -0
- package/src/lib/bits/internal/sleep.ts +3 -0
- package/src/lib/bits/internal/tabbable.ts +76 -0
- package/src/lib/bits/internal/types.ts +91 -0
- package/src/lib/bits/internal/use-after-animations.svelte.ts +30 -0
- package/src/lib/bits/internal/use-arrow-navigation.ts +168 -0
- package/src/lib/bits/internal/use-body-scroll-lock.svelte.ts +138 -0
- package/src/lib/bits/internal/use-data-typeahead.svelte.ts +44 -0
- package/src/lib/bits/internal/use-dom-typeahead.svelte.ts +44 -0
- package/src/lib/bits/internal/use-form-control.svelte.ts +17 -0
- package/src/lib/bits/internal/use-grace-area.svelte.ts +229 -0
- package/src/lib/bits/internal/use-id.ts +9 -0
- package/src/lib/bits/internal/use-resize-observer.svelte.ts +19 -0
- package/src/lib/bits/internal/use-roving-focus.svelte.ts +141 -0
- package/src/lib/bits/internal/use-size.svelte.ts +60 -0
- package/src/lib/bits/internal/use-state-machine.svelte.ts +46 -0
- package/src/lib/bits/internal/use-timeout-fn.svelte.ts +80 -0
- package/src/lib/components/Typeahead.svelte.ts +200 -0
- package/src/lib/components/animated/animated.svelte +244 -0
- package/src/lib/components/animated/index.ts +3 -0
- package/src/lib/components/combo/combo.svelte +186 -0
- package/src/lib/components/combo/index.ts +3 -0
- package/src/lib/components/dnd/Droppable.svelte +25 -0
- package/src/lib/components/dnd/context.svelte.ts +30 -0
- package/src/lib/components/dnd/dnd-context.svelte +45 -0
- package/src/lib/components/dnd/dnd-drag-overlay.svelte +44 -0
- package/src/lib/components/dnd/dnd-drag-placeholder.svelte +24 -0
- package/src/lib/components/dnd/dnd-draghandle.svelte +30 -0
- package/src/lib/components/dnd/dnd-overlay.svelte +0 -0
- package/src/lib/components/dnd/dnd-sortable-context.svelte +18 -0
- package/src/lib/components/dnd/dnd-sortable-item.svelte +68 -0
- package/src/lib/components/dnd/example.svelte +109 -0
- package/src/lib/components/dnd/exports.ts +12 -0
- package/src/lib/components/dnd/index.ts +1 -0
- package/src/lib/components/dnd/sortable.svelte.ts +82 -0
- package/src/lib/components/dnd/utils.svelte.ts +29 -0
- package/src/lib/components/search/combinations/searchPopover.svelte +68 -0
- package/src/lib/components/search/components/search-empty.svelte +28 -0
- package/src/lib/components/search/components/search-input.svelte +53 -0
- package/src/lib/components/search/components/search-list.svelte +46 -0
- package/src/lib/components/search/components/search-pagnation.svelte +68 -0
- package/src/lib/components/search/components/search.svelte +47 -0
- package/src/lib/components/search/exports.ts +13 -0
- package/src/lib/components/search/index.ts +2 -0
- package/src/lib/components/search/search.svelte.ts +286 -0
- package/src/lib/components/search/types.ts +48 -0
- package/src/lib/components/utilities/arrow/arrow.svelte +23 -0
- package/src/lib/components/utilities/arrow/index.ts +2 -0
- package/src/lib/components/utilities/arrow/types.ts +20 -0
- package/src/lib/components/utilities/floating-layer/components/floating-layer-anchor.svelte +15 -0
- package/src/lib/components/utilities/floating-layer/components/floating-layer-arrow.svelte +20 -0
- package/src/lib/components/utilities/floating-layer/components/floating-layer-content-static.svelte +19 -0
- package/src/lib/components/utilities/floating-layer/components/floating-layer-content.svelte +61 -0
- package/src/lib/components/utilities/floating-layer/components/floating-layer.svelte +10 -0
- package/src/lib/components/utilities/floating-layer/components/index.ts +11 -0
- package/src/lib/components/utilities/floating-layer/index.ts +1 -0
- package/src/lib/components/utilities/floating-layer/types.ts +133 -0
- package/src/lib/components/utilities/floating-layer/use-floating-layer.svelte.ts +406 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/utils/asyncDerived.svelte.ts +38 -0
- package/src/lib/utils/bits.ts +93 -0
- package/src/lib/utils/index.ts +3 -0
- package/src/lib/utils/utils.ts +97 -0
- package/src/routes/+layout.svelte +0 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { styleToString } from "svelte-toolbelt";
|
|
2
|
+
import { getPlaceholder } from "../placeholders.js";
|
|
3
|
+
import { hasTime, isZonedDateTime } from "../utils.js";
|
|
4
|
+
import { ALL_SEGMENT_PARTS, DATE_SEGMENT_PARTS, EDITABLE_SEGMENT_PARTS, TIME_SEGMENT_PARTS, } from "./parts.js";
|
|
5
|
+
import { getSegments } from "./segments.js";
|
|
6
|
+
import { isBrowser, isNull, isNumberString } from "../../../../internal/is.js";
|
|
7
|
+
import { useId } from "../../../../internal/use-id.js";
|
|
8
|
+
import { kbd } from "../../../../internal/kbd.js";
|
|
9
|
+
export function initializeSegmentValues(granularity) {
|
|
10
|
+
const calendarDateTimeGranularities = ["hour", "minute", "second"];
|
|
11
|
+
const initialParts = EDITABLE_SEGMENT_PARTS.map((part) => {
|
|
12
|
+
if (part === "dayPeriod") {
|
|
13
|
+
return [part, "AM"];
|
|
14
|
+
}
|
|
15
|
+
return [part, null];
|
|
16
|
+
}).filter(([key]) => {
|
|
17
|
+
if (key === "literal" || key === null)
|
|
18
|
+
return false;
|
|
19
|
+
if (granularity === "day") {
|
|
20
|
+
return !calendarDateTimeGranularities.includes(key);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return Object.fromEntries(initialParts);
|
|
27
|
+
}
|
|
28
|
+
function createContentObj(props) {
|
|
29
|
+
const { segmentValues, formatter, locale, dateRef } = props;
|
|
30
|
+
const content = Object.keys(segmentValues).reduce((obj, part) => {
|
|
31
|
+
if (!isSegmentPart(part))
|
|
32
|
+
return obj;
|
|
33
|
+
if ("hour" in segmentValues && part === "dayPeriod") {
|
|
34
|
+
const value = segmentValues[part];
|
|
35
|
+
if (!isNull(value)) {
|
|
36
|
+
obj[part] = value;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
obj[part] = getPlaceholder(part, "AM", locale);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
obj[part] = getPartContent(part);
|
|
44
|
+
}
|
|
45
|
+
return obj;
|
|
46
|
+
}, {});
|
|
47
|
+
function getPartContent(part) {
|
|
48
|
+
if ("hour" in segmentValues) {
|
|
49
|
+
const value = segmentValues[part];
|
|
50
|
+
const leadingZero = typeof value === "string" && value?.startsWith("0");
|
|
51
|
+
const intValue = value !== null ? Number.parseInt(value) : null;
|
|
52
|
+
if (value === "0" && part !== "year") {
|
|
53
|
+
return "0";
|
|
54
|
+
}
|
|
55
|
+
else if (!isNull(value) && !isNull(intValue)) {
|
|
56
|
+
const formatted = formatter.part(dateRef.set({ [part]: value }), part, {
|
|
57
|
+
hourCycle: props.hourCycle === 24 ? "h23" : undefined,
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* If we're operating in a 12 hour clock and the part is an hour, we handle
|
|
61
|
+
* the conversion to 12 hour format with 2 digit hours and leading zeros here.
|
|
62
|
+
*/
|
|
63
|
+
if (part === "hour" && "dayPeriod" in segmentValues && props.hourCycle !== 24) {
|
|
64
|
+
/**
|
|
65
|
+
* If the value is over 12, we convert to 12 hour format and add leading
|
|
66
|
+
* zeroes if the value is less than 10.
|
|
67
|
+
*/
|
|
68
|
+
if (intValue > 12) {
|
|
69
|
+
const hour = intValue - 12;
|
|
70
|
+
if (hour === 0) {
|
|
71
|
+
return "12";
|
|
72
|
+
}
|
|
73
|
+
else if (hour < 10) {
|
|
74
|
+
return `0${hour}`;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return `${hour}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* If the value is 0, we convert to 12, since 0 is not a valid 12 hour time.
|
|
82
|
+
*/
|
|
83
|
+
if (intValue === 0) {
|
|
84
|
+
return "12";
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* If the value is less than 10, we add a leading zero to the value.
|
|
88
|
+
*/
|
|
89
|
+
if (intValue < 10) {
|
|
90
|
+
return `0${intValue}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Otherwise, we don't need to do anything to the value.
|
|
94
|
+
*/
|
|
95
|
+
return `${intValue}`;
|
|
96
|
+
}
|
|
97
|
+
if (part === "year") {
|
|
98
|
+
return `${value}`;
|
|
99
|
+
}
|
|
100
|
+
if (leadingZero && formatted.length === 1) {
|
|
101
|
+
return `0${formatted}`;
|
|
102
|
+
}
|
|
103
|
+
return formatted;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return getPlaceholder(part, "", locale);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
if (isDateSegmentPart(part)) {
|
|
111
|
+
const value = segmentValues[part];
|
|
112
|
+
const leadingZero = typeof value === "string" && value?.startsWith("0");
|
|
113
|
+
if (value === "0") {
|
|
114
|
+
return "0";
|
|
115
|
+
}
|
|
116
|
+
else if (!isNull(value)) {
|
|
117
|
+
const formatted = formatter.part(dateRef.set({ [part]: value }), part);
|
|
118
|
+
if (part === "year") {
|
|
119
|
+
return `${value}`;
|
|
120
|
+
}
|
|
121
|
+
if (leadingZero && formatted.length === 1) {
|
|
122
|
+
return `0${formatted}`;
|
|
123
|
+
}
|
|
124
|
+
return formatted;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return getPlaceholder(part, "", locale);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return "";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return content;
|
|
134
|
+
}
|
|
135
|
+
function createContentArr(props) {
|
|
136
|
+
const { granularity, dateRef, formatter, contentObj, hideTimeZone, hourCycle } = props;
|
|
137
|
+
const parts = formatter.toParts(dateRef, getOptsByGranularity(granularity, hourCycle));
|
|
138
|
+
const segmentContentArr = parts
|
|
139
|
+
.map((part) => {
|
|
140
|
+
const defaultParts = ["literal", "dayPeriod", "timeZoneName", null];
|
|
141
|
+
if (defaultParts.includes(part.type) || !isSegmentPart(part.type)) {
|
|
142
|
+
return {
|
|
143
|
+
part: part.type,
|
|
144
|
+
value: part.value,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
part: part.type,
|
|
149
|
+
value: contentObj[part.type],
|
|
150
|
+
};
|
|
151
|
+
})
|
|
152
|
+
.filter((segment) => {
|
|
153
|
+
if (isNull(segment.part) || isNull(segment.value))
|
|
154
|
+
return false;
|
|
155
|
+
if (segment.part === "timeZoneName" && (!isZonedDateTime(dateRef) || hideTimeZone)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
});
|
|
160
|
+
return segmentContentArr;
|
|
161
|
+
}
|
|
162
|
+
export function createContent(props) {
|
|
163
|
+
const contentObj = createContentObj(props);
|
|
164
|
+
const contentArr = createContentArr({
|
|
165
|
+
contentObj,
|
|
166
|
+
...props,
|
|
167
|
+
});
|
|
168
|
+
return {
|
|
169
|
+
obj: contentObj,
|
|
170
|
+
arr: contentArr,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function getOptsByGranularity(granularity, hourCycle) {
|
|
174
|
+
const opts = {
|
|
175
|
+
year: "numeric",
|
|
176
|
+
month: "2-digit",
|
|
177
|
+
day: "2-digit",
|
|
178
|
+
hour: "2-digit",
|
|
179
|
+
minute: "2-digit",
|
|
180
|
+
second: "2-digit",
|
|
181
|
+
timeZoneName: "short",
|
|
182
|
+
hourCycle: hourCycle === 24 ? "h23" : undefined,
|
|
183
|
+
hour12: hourCycle === 24 ? false : undefined,
|
|
184
|
+
};
|
|
185
|
+
if (granularity === "day") {
|
|
186
|
+
delete opts.second;
|
|
187
|
+
delete opts.hour;
|
|
188
|
+
delete opts.minute;
|
|
189
|
+
delete opts.timeZoneName;
|
|
190
|
+
}
|
|
191
|
+
if (granularity === "hour") {
|
|
192
|
+
delete opts.minute;
|
|
193
|
+
}
|
|
194
|
+
if (granularity === "minute") {
|
|
195
|
+
delete opts.second;
|
|
196
|
+
}
|
|
197
|
+
return opts;
|
|
198
|
+
}
|
|
199
|
+
export function initSegmentStates() {
|
|
200
|
+
return EDITABLE_SEGMENT_PARTS.reduce((acc, key) => {
|
|
201
|
+
acc[key] = {
|
|
202
|
+
lastKeyZero: false,
|
|
203
|
+
hasLeftFocus: true,
|
|
204
|
+
updating: null,
|
|
205
|
+
};
|
|
206
|
+
return acc;
|
|
207
|
+
}, {});
|
|
208
|
+
}
|
|
209
|
+
export function initSegmentIds() {
|
|
210
|
+
return Object.fromEntries(ALL_SEGMENT_PARTS.map((part) => {
|
|
211
|
+
return [part, useId()];
|
|
212
|
+
}).filter(([key]) => key !== "literal"));
|
|
213
|
+
}
|
|
214
|
+
export function isDateSegmentPart(part) {
|
|
215
|
+
return DATE_SEGMENT_PARTS.includes(part);
|
|
216
|
+
}
|
|
217
|
+
export function isSegmentPart(part) {
|
|
218
|
+
return EDITABLE_SEGMENT_PARTS.includes(part);
|
|
219
|
+
}
|
|
220
|
+
export function isAnySegmentPart(part) {
|
|
221
|
+
return ALL_SEGMENT_PARTS.includes(part);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Get the segments being used/ are rendered in the DOM.
|
|
225
|
+
* We're using this to determine when to set the value of
|
|
226
|
+
* the date picker, which is when all the segments have
|
|
227
|
+
* been filled.
|
|
228
|
+
*/
|
|
229
|
+
function getUsedSegments(fieldNode) {
|
|
230
|
+
if (!isBrowser || !fieldNode)
|
|
231
|
+
return [];
|
|
232
|
+
const usedSegments = getSegments(fieldNode)
|
|
233
|
+
.map((el) => el.dataset.segment)
|
|
234
|
+
.filter((part) => {
|
|
235
|
+
return EDITABLE_SEGMENT_PARTS.includes(part);
|
|
236
|
+
});
|
|
237
|
+
return usedSegments;
|
|
238
|
+
}
|
|
239
|
+
export function getValueFromSegments(props) {
|
|
240
|
+
const { segmentObj, fieldNode, dateRef } = props;
|
|
241
|
+
const usedSegments = getUsedSegments(fieldNode);
|
|
242
|
+
let date = dateRef;
|
|
243
|
+
for (const part of usedSegments) {
|
|
244
|
+
if ("hour" in segmentObj) {
|
|
245
|
+
const value = segmentObj[part];
|
|
246
|
+
if (isNull(value))
|
|
247
|
+
continue;
|
|
248
|
+
date = date.set({ [part]: segmentObj[part] });
|
|
249
|
+
}
|
|
250
|
+
else if (isDateSegmentPart(part)) {
|
|
251
|
+
const value = segmentObj[part];
|
|
252
|
+
if (isNull(value))
|
|
253
|
+
continue;
|
|
254
|
+
date = date.set({ [part]: segmentObj[part] });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return date;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check if all the segments being used have been filled.
|
|
261
|
+
* We use this to determine when we should set the value
|
|
262
|
+
* store of the date field(s).
|
|
263
|
+
*
|
|
264
|
+
* @param segmentValues - The current `SegmentValueObj`
|
|
265
|
+
* @param fieldNode - The id of the date field
|
|
266
|
+
*/
|
|
267
|
+
export function areAllSegmentsFilled(segmentValues, fieldNode) {
|
|
268
|
+
const usedSegments = getUsedSegments(fieldNode);
|
|
269
|
+
for (const part of usedSegments) {
|
|
270
|
+
if ("hour" in segmentValues) {
|
|
271
|
+
if (segmentValues[part] === null) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else if (isDateSegmentPart(part)) {
|
|
276
|
+
if (segmentValues[part] === null) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Determines if the provided object is a valid `DateAndTimeSegmentObj`
|
|
285
|
+
* by checking if it has the correct keys and values for each key.
|
|
286
|
+
*/
|
|
287
|
+
export function isDateAndTimeSegmentObj(obj) {
|
|
288
|
+
if (typeof obj !== "object" || obj === null) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
return Object.entries(obj).every(([key, value]) => {
|
|
292
|
+
const validKey = TIME_SEGMENT_PARTS.includes(key) ||
|
|
293
|
+
DATE_SEGMENT_PARTS.includes(key);
|
|
294
|
+
const validValue = key === "dayPeriod"
|
|
295
|
+
? value === "AM" || value === "PM" || value === null
|
|
296
|
+
: typeof value === "string" || typeof value === "number" || value === null;
|
|
297
|
+
return validKey && validValue;
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Infer the granularity to use based on the
|
|
302
|
+
* value and granularity props.
|
|
303
|
+
*/
|
|
304
|
+
export function inferGranularity(value, granularity) {
|
|
305
|
+
if (granularity)
|
|
306
|
+
return granularity;
|
|
307
|
+
if (hasTime(value))
|
|
308
|
+
return "minute";
|
|
309
|
+
return "day";
|
|
310
|
+
}
|
|
311
|
+
export function isAcceptableSegmentKey(key) {
|
|
312
|
+
const acceptableSegmentKeys = [
|
|
313
|
+
kbd.ENTER,
|
|
314
|
+
kbd.ARROW_UP,
|
|
315
|
+
kbd.ARROW_DOWN,
|
|
316
|
+
kbd.ARROW_LEFT,
|
|
317
|
+
kbd.ARROW_RIGHT,
|
|
318
|
+
kbd.BACKSPACE,
|
|
319
|
+
kbd.SPACE,
|
|
320
|
+
];
|
|
321
|
+
if (acceptableSegmentKeys.includes(key))
|
|
322
|
+
return true;
|
|
323
|
+
if (isNumberString(key))
|
|
324
|
+
return true;
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Determines if the element with the provided id is the first focusable
|
|
329
|
+
* segment in the date field with the provided fieldId.
|
|
330
|
+
*
|
|
331
|
+
* @param id - The id of the element to check if it's the first segment
|
|
332
|
+
* @param fieldNode - The id of the date field associated with the segment
|
|
333
|
+
*/
|
|
334
|
+
export function isFirstSegment(id, fieldNode) {
|
|
335
|
+
if (!isBrowser)
|
|
336
|
+
return false;
|
|
337
|
+
const segments = getSegments(fieldNode);
|
|
338
|
+
return segments.length ? segments[0].id === id : false;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Creates or updates a description element for a date field
|
|
342
|
+
* which enables screen readers to read the date field's value.
|
|
343
|
+
*
|
|
344
|
+
* This element is hidden from view, and is portalled to the body
|
|
345
|
+
* so it can be associated via `aria-describedby` and read by
|
|
346
|
+
* screen readers as the user interacts with the date field.
|
|
347
|
+
*/
|
|
348
|
+
export function setDescription(id, formatter, value) {
|
|
349
|
+
if (!isBrowser)
|
|
350
|
+
return;
|
|
351
|
+
const valueString = formatter.selectedDate(value);
|
|
352
|
+
const el = document.getElementById(id);
|
|
353
|
+
if (!el) {
|
|
354
|
+
const div = document.createElement("div");
|
|
355
|
+
div.style.cssText = styleToString({
|
|
356
|
+
display: "none",
|
|
357
|
+
});
|
|
358
|
+
div.id = id;
|
|
359
|
+
div.innerText = `Selected Date: ${valueString}`;
|
|
360
|
+
document.body.appendChild(div);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
el.innerText = `Selected Date: ${valueString}`;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Removes the description element for the date field with
|
|
368
|
+
* the provided ID. This function should be called when the
|
|
369
|
+
* date field is unmounted.
|
|
370
|
+
*/
|
|
371
|
+
export function removeDescriptionElement(id) {
|
|
372
|
+
if (!isBrowser)
|
|
373
|
+
return;
|
|
374
|
+
const el = document.getElementById(id);
|
|
375
|
+
if (!el)
|
|
376
|
+
return;
|
|
377
|
+
document.body.removeChild(el);
|
|
378
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const DATE_SEGMENT_PARTS: readonly ["day", "month", "year"];
|
|
2
|
+
export declare const TIME_SEGMENT_PARTS: readonly ["hour", "minute", "second", "dayPeriod"];
|
|
3
|
+
export declare const NON_EDITABLE_SEGMENT_PARTS: readonly ["literal", "timeZoneName"];
|
|
4
|
+
export declare const EDITABLE_SEGMENT_PARTS: readonly ["day", "month", "year", "hour", "minute", "second", "dayPeriod"];
|
|
5
|
+
export declare const ALL_SEGMENT_PARTS: readonly ["day", "month", "year", "hour", "minute", "second", "dayPeriod", "literal", "timeZoneName"];
|
|
6
|
+
export declare const ALL_EXCEPT_LITERAL_PARTS: ("day" | "dayPeriod" | "hour" | "minute" | "month" | "second" | "timeZoneName" | "year")[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DATE_SEGMENT_PARTS = ["day", "month", "year"];
|
|
2
|
+
export const TIME_SEGMENT_PARTS = ["hour", "minute", "second", "dayPeriod"];
|
|
3
|
+
export const NON_EDITABLE_SEGMENT_PARTS = ["literal", "timeZoneName"];
|
|
4
|
+
export const EDITABLE_SEGMENT_PARTS = [...DATE_SEGMENT_PARTS, ...TIME_SEGMENT_PARTS];
|
|
5
|
+
export const ALL_SEGMENT_PARTS = [
|
|
6
|
+
...EDITABLE_SEGMENT_PARTS,
|
|
7
|
+
...NON_EDITABLE_SEGMENT_PARTS,
|
|
8
|
+
];
|
|
9
|
+
export const ALL_EXCEPT_LITERAL_PARTS = ALL_SEGMENT_PARTS.filter((part) => part !== "literal");
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles segment navigation based on the provided keyboard event and field ID.
|
|
3
|
+
*
|
|
4
|
+
* @param e - The keyboard event
|
|
5
|
+
* @param fieldNode - The ID of the field we're navigating within
|
|
6
|
+
*/
|
|
7
|
+
export declare function handleSegmentNavigation(e: KeyboardEvent, fieldNode: HTMLElement | null): void;
|
|
8
|
+
/**
|
|
9
|
+
* Retrieves the next segment in the list of segments relative to the provided node.
|
|
10
|
+
*
|
|
11
|
+
* @param node - The node we're starting from
|
|
12
|
+
* @param segments - The list of candidate segments to navigate through
|
|
13
|
+
*/
|
|
14
|
+
export declare function getNextSegment(node: HTMLElement, segments: HTMLElement[]): HTMLElement | null;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves the previous segment in the list of segments relative to the provided node.
|
|
17
|
+
*
|
|
18
|
+
* @param node - The node we're starting from
|
|
19
|
+
* @param segments - The list of candidate segments to navigate through
|
|
20
|
+
*/
|
|
21
|
+
export declare function getPrevSegment(node: HTMLElement, segments: HTMLElement[]): HTMLElement | null;
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves an object containing the next and previous segments relative to the current node.
|
|
24
|
+
*
|
|
25
|
+
* @param startingNode - The node we're starting from
|
|
26
|
+
* @param fieldNode - The ID of the field we're navigating within
|
|
27
|
+
*/
|
|
28
|
+
export declare function getPrevNextSegments(startingNode: HTMLElement, fieldNode: HTMLElement | null): {
|
|
29
|
+
next: HTMLElement | null;
|
|
30
|
+
prev: HTMLElement | null;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Shifts the focus to the next segment in the list of segments
|
|
34
|
+
* within the field identified by the provided ID.
|
|
35
|
+
*/
|
|
36
|
+
export declare function moveToNextSegment(e: KeyboardEvent, fieldNode: HTMLElement | null): void;
|
|
37
|
+
/**
|
|
38
|
+
* Shifts the focus to the previous segment in the list of segments
|
|
39
|
+
* within the field identified by the provided ID. If this is the first
|
|
40
|
+
* segment, focus will not be shifted.
|
|
41
|
+
*/
|
|
42
|
+
export declare function moveToPrevSegment(e: KeyboardEvent, fieldNode: HTMLElement | null): void;
|
|
43
|
+
export declare function isSegmentNavigationKey(key: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Retrieves all the interactive segments within the field identified by the provided ID.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getSegments(fieldNode: HTMLElement | null): HTMLElement[];
|
|
48
|
+
/**
|
|
49
|
+
* Get the first interactive segment within the field identified by the provided ID.
|
|
50
|
+
*/
|
|
51
|
+
export declare function getFirstSegment(fieldNode: HTMLElement | null): HTMLElement;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { isAnySegmentPart } from "./helpers.js";
|
|
2
|
+
import { isHTMLElement } from "../../../../internal/is.js";
|
|
3
|
+
import { kbd } from "../../../../internal/kbd.js";
|
|
4
|
+
/**
|
|
5
|
+
* Handles segment navigation based on the provided keyboard event and field ID.
|
|
6
|
+
*
|
|
7
|
+
* @param e - The keyboard event
|
|
8
|
+
* @param fieldNode - The ID of the field we're navigating within
|
|
9
|
+
*/
|
|
10
|
+
export function handleSegmentNavigation(e, fieldNode) {
|
|
11
|
+
const currentTarget = e.currentTarget;
|
|
12
|
+
if (!isHTMLElement(currentTarget))
|
|
13
|
+
return;
|
|
14
|
+
const { prev, next } = getPrevNextSegments(currentTarget, fieldNode);
|
|
15
|
+
if (e.key === kbd.ARROW_LEFT) {
|
|
16
|
+
if (!prev)
|
|
17
|
+
return;
|
|
18
|
+
prev.focus();
|
|
19
|
+
}
|
|
20
|
+
else if (e.key === kbd.ARROW_RIGHT) {
|
|
21
|
+
if (!next)
|
|
22
|
+
return;
|
|
23
|
+
next.focus();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves the next segment in the list of segments relative to the provided node.
|
|
28
|
+
*
|
|
29
|
+
* @param node - The node we're starting from
|
|
30
|
+
* @param segments - The list of candidate segments to navigate through
|
|
31
|
+
*/
|
|
32
|
+
export function getNextSegment(node, segments) {
|
|
33
|
+
const index = segments.indexOf(node);
|
|
34
|
+
if (index === segments.length - 1 || index === -1)
|
|
35
|
+
return null;
|
|
36
|
+
const nextIndex = index + 1;
|
|
37
|
+
const nextSegment = segments[nextIndex];
|
|
38
|
+
return nextSegment;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Retrieves the previous segment in the list of segments relative to the provided node.
|
|
42
|
+
*
|
|
43
|
+
* @param node - The node we're starting from
|
|
44
|
+
* @param segments - The list of candidate segments to navigate through
|
|
45
|
+
*/
|
|
46
|
+
export function getPrevSegment(node, segments) {
|
|
47
|
+
const index = segments.indexOf(node);
|
|
48
|
+
if (index === 0 || index === -1)
|
|
49
|
+
return null;
|
|
50
|
+
const prevIndex = index - 1;
|
|
51
|
+
const prevSegment = segments[prevIndex];
|
|
52
|
+
return prevSegment;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Retrieves an object containing the next and previous segments relative to the current node.
|
|
56
|
+
*
|
|
57
|
+
* @param startingNode - The node we're starting from
|
|
58
|
+
* @param fieldNode - The ID of the field we're navigating within
|
|
59
|
+
*/
|
|
60
|
+
export function getPrevNextSegments(startingNode, fieldNode) {
|
|
61
|
+
const segments = getSegments(fieldNode);
|
|
62
|
+
if (!segments.length) {
|
|
63
|
+
return {
|
|
64
|
+
next: null,
|
|
65
|
+
prev: null,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
next: getNextSegment(startingNode, segments),
|
|
70
|
+
prev: getPrevSegment(startingNode, segments),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Shifts the focus to the next segment in the list of segments
|
|
75
|
+
* within the field identified by the provided ID.
|
|
76
|
+
*/
|
|
77
|
+
export function moveToNextSegment(e, fieldNode) {
|
|
78
|
+
const node = e.currentTarget;
|
|
79
|
+
if (!isHTMLElement(node))
|
|
80
|
+
return;
|
|
81
|
+
const { next } = getPrevNextSegments(node, fieldNode);
|
|
82
|
+
if (!next)
|
|
83
|
+
return;
|
|
84
|
+
next.focus();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Shifts the focus to the previous segment in the list of segments
|
|
88
|
+
* within the field identified by the provided ID. If this is the first
|
|
89
|
+
* segment, focus will not be shifted.
|
|
90
|
+
*/
|
|
91
|
+
export function moveToPrevSegment(e, fieldNode) {
|
|
92
|
+
const node = e.currentTarget;
|
|
93
|
+
if (!isHTMLElement(node))
|
|
94
|
+
return;
|
|
95
|
+
const { prev } = getPrevNextSegments(node, fieldNode);
|
|
96
|
+
if (!prev)
|
|
97
|
+
return;
|
|
98
|
+
prev.focus();
|
|
99
|
+
}
|
|
100
|
+
export function isSegmentNavigationKey(key) {
|
|
101
|
+
if (key === kbd.ARROW_RIGHT || key === kbd.ARROW_LEFT)
|
|
102
|
+
return true;
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Retrieves all the interactive segments within the field identified by the provided ID.
|
|
107
|
+
*/
|
|
108
|
+
export function getSegments(fieldNode) {
|
|
109
|
+
if (!fieldNode)
|
|
110
|
+
return [];
|
|
111
|
+
const segments = Array.from(fieldNode.querySelectorAll("[data-segment]")).filter((el) => {
|
|
112
|
+
if (!isHTMLElement(el))
|
|
113
|
+
return false;
|
|
114
|
+
const segment = el.dataset.segment;
|
|
115
|
+
if (segment === "trigger")
|
|
116
|
+
return true;
|
|
117
|
+
if (!isAnySegmentPart(segment) || segment === "literal")
|
|
118
|
+
return false;
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
121
|
+
return segments;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get the first interactive segment within the field identified by the provided ID.
|
|
125
|
+
*/
|
|
126
|
+
export function getFirstSegment(fieldNode) {
|
|
127
|
+
return getSegments(fieldNode)[0];
|
|
128
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DATE_SEGMENT_PARTS, EDITABLE_SEGMENT_PARTS, NON_EDITABLE_SEGMENT_PARTS, TIME_SEGMENT_PARTS } from "./parts.js";
|
|
2
|
+
export type DateSegmentPart = (typeof DATE_SEGMENT_PARTS)[number];
|
|
3
|
+
export type TimeSegmentPart = (typeof TIME_SEGMENT_PARTS)[number];
|
|
4
|
+
export type EditableSegmentPart = (typeof EDITABLE_SEGMENT_PARTS)[number];
|
|
5
|
+
export type NonEditableSegmentPart = (typeof NON_EDITABLE_SEGMENT_PARTS)[number];
|
|
6
|
+
export type SegmentPart = EditableSegmentPart | NonEditableSegmentPart;
|
|
7
|
+
export type AnyExceptLiteral = Exclude<SegmentPart, "literal">;
|
|
8
|
+
export type DayPeriod = "AM" | "PM" | null;
|
|
9
|
+
export type DateSegmentObj = {
|
|
10
|
+
[K in DateSegmentPart]: string | null;
|
|
11
|
+
};
|
|
12
|
+
export type TimeSegmentObj = {
|
|
13
|
+
[K in TimeSegmentPart]: K extends "dayPeriod" ? DayPeriod : string | null;
|
|
14
|
+
};
|
|
15
|
+
export type DateAndTimeSegmentObj = DateSegmentObj & TimeSegmentObj;
|
|
16
|
+
export type SegmentValueObj = DateSegmentObj | DateAndTimeSegmentObj;
|
|
17
|
+
export type SegmentContentObj = Record<EditableSegmentPart, string>;
|
|
18
|
+
export type SegmentState = {
|
|
19
|
+
lastKeyZero: boolean;
|
|
20
|
+
hasLeftFocus: boolean;
|
|
21
|
+
updating: string | null;
|
|
22
|
+
};
|
|
23
|
+
export type SegmentStateMap = {
|
|
24
|
+
[K in EditableSegmentPart]: SegmentState;
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type DateValue } from "@internationalized/date";
|
|
2
|
+
import type { HourCycle } from "../../../shared/date/types.js";
|
|
3
|
+
export type Formatter = ReturnType<typeof createFormatter>;
|
|
4
|
+
/**
|
|
5
|
+
* Creates a wrapper around the `DateFormatter`, which is
|
|
6
|
+
* an improved version of the {@link Intl.DateTimeFormat} API,
|
|
7
|
+
* that is used internally by the various date builders to
|
|
8
|
+
* easily format dates in a consistent way.
|
|
9
|
+
*
|
|
10
|
+
* @see [DateFormatter](https://react-spectrum.adobe.com/internationalized/date/DateFormatter.html)
|
|
11
|
+
*/
|
|
12
|
+
export declare function createFormatter(initialLocale: string): {
|
|
13
|
+
setLocale: (newLocale: string) => void;
|
|
14
|
+
getLocale: () => string;
|
|
15
|
+
fullMonth: (date: Date) => any;
|
|
16
|
+
fullYear: (date: Date) => any;
|
|
17
|
+
fullMonthAndYear: (date: Date) => any;
|
|
18
|
+
toParts: (date: DateValue, options?: Intl.DateTimeFormatOptions) => any;
|
|
19
|
+
custom: (date: Date, options: Intl.DateTimeFormatOptions) => any;
|
|
20
|
+
part: (dateObj: DateValue, type: Intl.DateTimeFormatPartTypes, options?: Intl.DateTimeFormatOptions) => any;
|
|
21
|
+
dayPeriod: (date: Date, hourCycle?: HourCycle | undefined) => "PM" | "AM";
|
|
22
|
+
selectedDate: (date: DateValue, includeTime?: boolean) => any;
|
|
23
|
+
dayOfWeek: (date: Date, length?: Intl.DateTimeFormatOptions["weekday"]) => any;
|
|
24
|
+
};
|