@auronui/vue 1.0.1 → 1.0.3

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.
Files changed (29) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/index.cjs +760 -194
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/components/autocomplete/Autocomplete.context.js.map +1 -1
  5. package/dist/components/autocomplete/Autocomplete.js.map +1 -1
  6. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js +7 -0
  7. package/dist/components/autocomplete/Autocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  8. package/dist/components/autocomplete/AutocompleteContent.js.map +1 -1
  9. package/dist/components/autocomplete/AutocompleteContent.vue_vue_type_script_setup_true_lang.js +10 -4
  10. package/dist/components/autocomplete/AutocompleteContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/autocomplete/AutocompleteInput.js.map +1 -1
  12. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js +2 -1
  13. package/dist/components/autocomplete/AutocompleteInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/autocomplete/AutocompleteItem.js.map +1 -1
  15. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js +5 -1
  16. package/dist/components/autocomplete/AutocompleteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/date-picker/DatePicker.js.map +1 -1
  18. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js +6 -1
  19. package/dist/components/date-picker/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/components/date-time-picker/DateTimePicker.js +7 -0
  21. package/dist/components/date-time-picker/DateTimePicker.js.map +1 -0
  22. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js +398 -0
  23. package/dist/components/date-time-picker/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  24. package/dist/components/date-time-picker/DateTimePickerTimeScroller.js +7 -0
  25. package/dist/components/date-time-picker/DateTimePickerTimeScroller.js.map +1 -0
  26. package/dist/components/date-time-picker/DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js +157 -0
  27. package/dist/components/date-time-picker/DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js.map +1 -0
  28. package/dist/index.js +2 -1
  29. package/package.json +15 -15
@@ -0,0 +1,398 @@
1
+ import { composeClassName } from "../../utils/composeClassName.js";
2
+ import { motion } from "../../node_modules/.pnpm/motion-v@2.2.1_@vueuse_core@14.2.1_vue@3.5.32_typescript@6.0.2___react-dom@19.2.5_react_8b28b23614a2152514812dba6ef76a55/node_modules/motion-v/dist/es/components/motion/index.js";
3
+ import { AnimatePresence_default } from "../../node_modules/.pnpm/motion-v@2.2.1_@vueuse_core@14.2.1_vue@3.5.32_typescript@6.0.2___react-dom@19.2.5_react_8b28b23614a2152514812dba6ef76a55/node_modules/motion-v/dist/es/components/animate-presence/AnimatePresence.js";
4
+ import { $ad063034c8620db8$export$aa8b41735afcabd2, $ad063034c8620db8$export$d0bdf45af03a6ea3 } from "../../node_modules/.pnpm/@internationalized_date@3.12.1/node_modules/@internationalized/date/dist/private/queries.js";
5
+ import { $d07e34cce18680fd$export$93522d1a439f3617 } from "../../node_modules/.pnpm/@internationalized_date@3.12.1/node_modules/@internationalized/date/dist/private/conversion.js";
6
+ import { $2aaf608024c21ca1$export$ca871e8dbb80966f } from "../../node_modules/.pnpm/@internationalized_date@3.12.1/node_modules/@internationalized/date/dist/private/CalendarDate.js";
7
+ import Calendar_default from "../calendar/Calendar.js";
8
+ import DateInput_default from "../date-input/DateInput.js";
9
+ import DateTimePickerTimeScroller_default from "./DateTimePickerTimeScroller.js";
10
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeModels, normalizeClass, openBlock, ref, renderSlot, shallowRef, toDisplayString, unref, useModel, watch, withCtx, withModifiers } from "vue";
11
+ import { dateTimePickerVariants } from "@auronui/styles";
12
+ import { DatePickerContent, DatePickerRoot, DatePickerTrigger } from "reka-ui";
13
+ //#region src/components/date-time-picker/DateTimePicker.vue?vue&type=script&setup=true&lang.ts
14
+ var _hoisted_1 = ["data-hidden"];
15
+ var _hoisted_2 = ["aria-label"];
16
+ var _hoisted_3 = {
17
+ key: 1,
18
+ width: "14",
19
+ height: "14",
20
+ viewBox: "0 0 24 24",
21
+ fill: "none",
22
+ stroke: "currentColor",
23
+ "stroke-width": "2.5",
24
+ "stroke-linecap": "round",
25
+ "stroke-linejoin": "round",
26
+ "aria-hidden": "true"
27
+ };
28
+ var DateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
29
+ inheritAttrs: false,
30
+ __name: "DateTimePicker",
31
+ props: /* @__PURE__ */ mergeModels({
32
+ variant: {},
33
+ size: { default: "md" },
34
+ color: { default: "default" },
35
+ labelPlacement: { default: "inside" },
36
+ fullWidth: {
37
+ type: Boolean,
38
+ default: false
39
+ },
40
+ label: {},
41
+ description: {},
42
+ errorMessage: {},
43
+ isInvalid: {
44
+ type: Boolean,
45
+ default: false
46
+ },
47
+ isDisabled: {
48
+ type: Boolean,
49
+ default: false
50
+ },
51
+ isReadOnly: {
52
+ type: Boolean,
53
+ default: false
54
+ },
55
+ isRequired: {
56
+ type: Boolean,
57
+ default: false
58
+ },
59
+ name: {},
60
+ class: {},
61
+ granularity: { default: "minute" },
62
+ hourCycle: {},
63
+ hideTimeZone: {
64
+ type: Boolean,
65
+ default: false
66
+ },
67
+ defaultOpen: {
68
+ type: Boolean,
69
+ default: false
70
+ },
71
+ closeOnSelect: {
72
+ type: Boolean,
73
+ default: true
74
+ },
75
+ locale: {},
76
+ defaultValue: {},
77
+ minValue: {},
78
+ maxValue: {},
79
+ isDateUnavailable: {},
80
+ isDateDisabled: {}
81
+ }, {
82
+ "modelValue": {},
83
+ "modelModifiers": {},
84
+ "open": {
85
+ type: Boolean,
86
+ default: void 0
87
+ },
88
+ "openModifiers": {}
89
+ }),
90
+ emits: ["update:modelValue", "update:open"],
91
+ setup(__props) {
92
+ const props = __props;
93
+ const modelValue = useModel(__props, "modelValue");
94
+ const openModel = useModel(__props, "open");
95
+ const STEP_TITLES = {
96
+ date: "Pick a date",
97
+ time: "Pick a time"
98
+ };
99
+ const STEP_ORDER = ["date", "time"];
100
+ if (props.defaultOpen && openModel.value === void 0) openModel.value = true;
101
+ if (modelValue.value == null && props.defaultValue != null) modelValue.value = props.defaultValue;
102
+ const _today = $ad063034c8620db8$export$d0bdf45af03a6ea3($ad063034c8620db8$export$aa8b41735afcabd2());
103
+ const internalValue = shallowRef(modelValue.value ?? props.defaultValue ?? new $2aaf608024c21ca1$export$ca871e8dbb80966f(_today.year, _today.month, _today.day, 0, 0));
104
+ watch(modelValue, (v) => {
105
+ if (v instanceof $2aaf608024c21ca1$export$ca871e8dbb80966f) internalValue.value = v;
106
+ });
107
+ function onInputChange(v) {
108
+ if (!(v instanceof $2aaf608024c21ca1$export$ca871e8dbb80966f)) return;
109
+ internalValue.value = v;
110
+ modelValue.value = v;
111
+ }
112
+ const activeStep = ref("date");
113
+ const direction = ref(1);
114
+ watch(openModel, (open) => {
115
+ if (open) activeStep.value = "date";
116
+ });
117
+ function goTo(step) {
118
+ const from = STEP_ORDER.indexOf(activeStep.value);
119
+ direction.value = STEP_ORDER.indexOf(step) > from ? 1 : -1;
120
+ activeStep.value = step;
121
+ }
122
+ function goBack() {
123
+ const idx = STEP_ORDER.indexOf(activeStep.value);
124
+ if (idx > 0) goTo(STEP_ORDER[idx - 1]);
125
+ }
126
+ function goForward() {
127
+ const idx = STEP_ORDER.indexOf(activeStep.value);
128
+ if (idx < STEP_ORDER.length - 1) goTo(STEP_ORDER[idx + 1]);
129
+ else if (props.closeOnSelect) openModel.value = false;
130
+ }
131
+ const panelInitial = computed(() => ({
132
+ x: direction.value > 0 ? "100%" : "-100%",
133
+ opacity: 0
134
+ }));
135
+ const panelAnimate = {
136
+ x: "0%",
137
+ opacity: 1
138
+ };
139
+ const panelExit = computed(() => ({
140
+ x: direction.value > 0 ? "-100%" : "100%",
141
+ opacity: 0
142
+ }));
143
+ const calendarValue = computed({
144
+ get: () => $d07e34cce18680fd$export$93522d1a439f3617(internalValue.value),
145
+ set: (val) => {
146
+ if (!val) return;
147
+ internalValue.value = internalValue.value.set({
148
+ year: val.year,
149
+ month: val.month,
150
+ day: val.day
151
+ });
152
+ modelValue.value = internalValue.value;
153
+ goTo("time");
154
+ }
155
+ });
156
+ function onTimeUpdate(val) {
157
+ internalValue.value = val;
158
+ modelValue.value = val;
159
+ }
160
+ const slotFns = computed(() => dateTimePickerVariants({
161
+ isInvalid: props.isInvalid,
162
+ isDisabled: props.isDisabled,
163
+ fullWidth: props.fullWidth
164
+ }));
165
+ return (_ctx, _cache) => {
166
+ return openBlock(), createBlock(unref(DatePickerRoot), {
167
+ modelValue: modelValue.value,
168
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => modelValue.value = $event),
169
+ open: openModel.value,
170
+ "onUpdate:open": _cache[3] || (_cache[3] = ($event) => openModel.value = $event),
171
+ "default-value": __props.defaultValue,
172
+ "default-open": __props.defaultOpen,
173
+ "min-value": __props.minValue,
174
+ "max-value": __props.maxValue,
175
+ "is-date-unavailable": __props.isDateUnavailable,
176
+ "is-date-disabled": __props.isDateDisabled,
177
+ locale: __props.locale,
178
+ granularity: __props.granularity,
179
+ "hour-cycle": __props.hourCycle,
180
+ disabled: __props.isDisabled,
181
+ readonly: __props.isReadOnly,
182
+ name: __props.name,
183
+ class: normalizeClass(unref(composeClassName)(slotFns.value.base(), props.class)),
184
+ "data-slot": "date-time-picker"
185
+ }, {
186
+ default: withCtx(() => [createVNode(DateInput_default, {
187
+ "model-value": internalValue.value,
188
+ "onUpdate:modelValue": onInputChange,
189
+ variant: __props.variant,
190
+ size: __props.size,
191
+ color: __props.color,
192
+ "label-placement": __props.labelPlacement,
193
+ "full-width": __props.fullWidth,
194
+ "default-value": __props.defaultValue,
195
+ granularity: __props.granularity,
196
+ "hour-cycle": __props.hourCycle,
197
+ locale: __props.locale,
198
+ label: __props.label,
199
+ description: __props.description,
200
+ "error-message": __props.errorMessage,
201
+ "is-invalid": __props.isInvalid,
202
+ "is-disabled": __props.isDisabled,
203
+ "is-read-only": __props.isReadOnly,
204
+ "is-required": __props.isRequired,
205
+ name: __props.name,
206
+ "hide-time-zone": __props.hideTimeZone
207
+ }, {
208
+ endContent: withCtx(() => [createVNode(unref(DatePickerTrigger), {
209
+ class: normalizeClass(slotFns.value.trigger()),
210
+ "aria-label": "Open date time picker",
211
+ onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["prevent"]))
212
+ }, {
213
+ default: withCtx(() => [renderSlot(_ctx.$slots, "selectorIcon", {}, () => [(openBlock(), createElementBlock("svg", {
214
+ class: normalizeClass(slotFns.value.triggerIndicator()),
215
+ xmlns: "http://www.w3.org/2000/svg",
216
+ width: "16",
217
+ height: "16",
218
+ viewBox: "0 0 24 24",
219
+ fill: "none",
220
+ stroke: "currentColor",
221
+ "stroke-width": "2",
222
+ "stroke-linecap": "round",
223
+ "stroke-linejoin": "round",
224
+ "aria-hidden": "true",
225
+ focusable: "false"
226
+ }, [..._cache[4] || (_cache[4] = [
227
+ createElementVNode("rect", {
228
+ x: "3",
229
+ y: "4",
230
+ width: "18",
231
+ height: "18",
232
+ rx: "2",
233
+ ry: "2"
234
+ }, null, -1),
235
+ createElementVNode("line", {
236
+ x1: "16",
237
+ y1: "2",
238
+ x2: "16",
239
+ y2: "6"
240
+ }, null, -1),
241
+ createElementVNode("line", {
242
+ x1: "8",
243
+ y1: "2",
244
+ x2: "8",
245
+ y2: "6"
246
+ }, null, -1),
247
+ createElementVNode("line", {
248
+ x1: "3",
249
+ y1: "10",
250
+ x2: "21",
251
+ y2: "10"
252
+ }, null, -1)
253
+ ])], 2))])]),
254
+ _: 3
255
+ }, 8, ["class"])]),
256
+ _: 3
257
+ }, 8, [
258
+ "model-value",
259
+ "variant",
260
+ "size",
261
+ "color",
262
+ "label-placement",
263
+ "full-width",
264
+ "default-value",
265
+ "granularity",
266
+ "hour-cycle",
267
+ "locale",
268
+ "label",
269
+ "description",
270
+ "error-message",
271
+ "is-invalid",
272
+ "is-disabled",
273
+ "is-read-only",
274
+ "is-required",
275
+ "name",
276
+ "hide-time-zone"
277
+ ]), createVNode(unref(DatePickerContent), {
278
+ class: normalizeClass(slotFns.value.popover()),
279
+ "data-slot": "popover",
280
+ "side-offset": 8
281
+ }, {
282
+ default: withCtx(() => [createElementVNode("div", {
283
+ class: normalizeClass(slotFns.value.stepHeader()),
284
+ "data-slot": "step-header"
285
+ }, [
286
+ createElementVNode("button", {
287
+ type: "button",
288
+ class: normalizeClass(slotFns.value.navButton()),
289
+ "data-hidden": activeStep.value === "date" ? "true" : void 0,
290
+ "aria-label": "Previous step",
291
+ "data-slot": "back-button",
292
+ onClick: goBack
293
+ }, [..._cache[5] || (_cache[5] = [createElementVNode("svg", {
294
+ width: "14",
295
+ height: "14",
296
+ viewBox: "0 0 24 24",
297
+ fill: "none",
298
+ stroke: "currentColor",
299
+ "stroke-width": "2.5",
300
+ "stroke-linecap": "round",
301
+ "stroke-linejoin": "round",
302
+ "aria-hidden": "true"
303
+ }, [createElementVNode("polyline", { points: "15 18 9 12 15 6" })], -1)])], 10, _hoisted_1),
304
+ createElementVNode("span", { class: normalizeClass(slotFns.value.stepTitle()) }, toDisplayString(STEP_TITLES[activeStep.value]), 3),
305
+ createElementVNode("button", {
306
+ type: "button",
307
+ class: normalizeClass(slotFns.value.navButton()),
308
+ "aria-label": activeStep.value === "time" ? "Done" : "Next step",
309
+ "data-slot": "forward-button",
310
+ onClick: goForward
311
+ }, [activeStep.value === "time" ? (openBlock(), createElementBlock("span", {
312
+ key: 0,
313
+ class: normalizeClass(slotFns.value.doneLabel())
314
+ }, "Done", 2)) : (openBlock(), createElementBlock("svg", _hoisted_3, [..._cache[6] || (_cache[6] = [createElementVNode("polyline", { points: "9 18 15 12 9 6" }, null, -1)])]))], 10, _hoisted_2)
315
+ ], 2), createElementVNode("div", {
316
+ class: normalizeClass(slotFns.value.panelWrap()),
317
+ style: { "overflow": "hidden" }
318
+ }, [createVNode(unref(AnimatePresence_default), { mode: "popLayout" }, {
319
+ default: withCtx(() => [activeStep.value === "date" ? (openBlock(), createBlock(unref(motion).div, {
320
+ key: "date",
321
+ initial: panelInitial.value,
322
+ animate: panelAnimate,
323
+ exit: panelExit.value,
324
+ transition: { duration: .15 },
325
+ class: "px-3 pb-3",
326
+ "data-slot": "calendar-panel"
327
+ }, {
328
+ default: withCtx(() => [createVNode(Calendar_default, {
329
+ modelValue: calendarValue.value,
330
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => calendarValue.value = $event),
331
+ "default-value": __props.defaultValue,
332
+ "min-value": __props.minValue,
333
+ "max-value": __props.maxValue,
334
+ "is-date-disabled": __props.isDateDisabled,
335
+ "is-date-unavailable": __props.isDateUnavailable,
336
+ locale: __props.locale,
337
+ readonly: __props.isReadOnly,
338
+ disabled: __props.isDisabled
339
+ }, null, 8, [
340
+ "modelValue",
341
+ "default-value",
342
+ "min-value",
343
+ "max-value",
344
+ "is-date-disabled",
345
+ "is-date-unavailable",
346
+ "locale",
347
+ "readonly",
348
+ "disabled"
349
+ ])]),
350
+ _: 1
351
+ }, 8, ["initial", "exit"])) : activeStep.value === "time" ? (openBlock(), createBlock(unref(motion).div, {
352
+ key: "time",
353
+ initial: panelInitial.value,
354
+ animate: panelAnimate,
355
+ exit: panelExit.value,
356
+ transition: { duration: .15 }
357
+ }, {
358
+ default: withCtx(() => [createVNode(DateTimePickerTimeScroller_default, {
359
+ "model-value": internalValue.value,
360
+ granularity: __props.granularity,
361
+ "hour-cycle": __props.hourCycle,
362
+ "onUpdate:modelValue": onTimeUpdate
363
+ }, null, 8, [
364
+ "model-value",
365
+ "granularity",
366
+ "hour-cycle"
367
+ ])]),
368
+ _: 1
369
+ }, 8, ["initial", "exit"])) : createCommentVNode("", true)]),
370
+ _: 1
371
+ })], 2)]),
372
+ _: 1
373
+ }, 8, ["class"])]),
374
+ _: 3
375
+ }, 8, [
376
+ "modelValue",
377
+ "open",
378
+ "default-value",
379
+ "default-open",
380
+ "min-value",
381
+ "max-value",
382
+ "is-date-unavailable",
383
+ "is-date-disabled",
384
+ "locale",
385
+ "granularity",
386
+ "hour-cycle",
387
+ "disabled",
388
+ "readonly",
389
+ "name",
390
+ "class"
391
+ ]);
392
+ };
393
+ }
394
+ });
395
+ //#endregion
396
+ export { DateTimePicker_vue_vue_type_script_setup_true_lang_default as default };
397
+
398
+ //# sourceMappingURL=DateTimePicker.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateTimePicker.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.vue"],"sourcesContent":["<!-- packages/vue/src/components/date-time-picker/DateTimePicker.vue -->\n<script setup lang=\"ts\">\nimport { computed, ref, shallowRef, watch } from 'vue'\nimport {\n DatePickerRoot,\n DatePickerTrigger,\n DatePickerContent,\n} from 'reka-ui'\nimport {\n type DateValue,\n CalendarDateTime,\n toCalendarDate,\n today,\n getLocalTimeZone,\n} from '@internationalized/date'\nimport { AnimatePresence, motion } from 'motion-v'\nimport { dateTimePickerVariants } from '@auronui/styles'\nimport { composeClassName } from '../../utils/composeClassName'\nimport Calendar from '../calendar/Calendar.vue'\nimport DateInput from '../date-input/DateInput.vue'\nimport DateTimePickerTimeScroller from './DateTimePickerTimeScroller.vue'\n\ntype Step = 'date' | 'time'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n variant?: 'flat' | 'bordered' | 'faded' | 'underlined'\n size?: 'sm' | 'md' | 'lg'\n color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'\n labelPlacement?: 'inside' | 'outside' | 'outside-left'\n fullWidth?: boolean\n label?: string\n description?: string\n errorMessage?: string\n isInvalid?: boolean\n isDisabled?: boolean\n isReadOnly?: boolean\n isRequired?: boolean\n name?: string\n class?: string\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n hideTimeZone?: boolean\n defaultOpen?: boolean\n closeOnSelect?: boolean\n locale?: string\n defaultValue?: CalendarDateTime\n minValue?: CalendarDateTime\n maxValue?: CalendarDateTime\n isDateUnavailable?: (date: DateValue) => boolean\n isDateDisabled?: (date: DateValue) => boolean\n}>(), {\n size: 'md',\n color: 'default',\n labelPlacement: 'inside',\n fullWidth: false,\n isInvalid: false,\n isDisabled: false,\n isReadOnly: false,\n isRequired: false,\n hideTimeZone: false,\n granularity: 'minute',\n defaultOpen: false,\n closeOnSelect: true,\n})\n\nconst modelValue = defineModel<CalendarDateTime | null | undefined>('modelValue')\nconst openModel = defineModel<boolean>('open', { default: undefined })\n\nconst STEP_TITLES: Record<Step, string> = {\n date: 'Pick a date',\n time: 'Pick a time',\n}\nconst STEP_ORDER: Step[] = ['date', 'time']\n\n// Seed controlled open state from defaultOpen so portal renders in uncontrolled mode too\nif (props.defaultOpen && openModel.value === undefined) {\n openModel.value = true\n}\n\n// Seed controlled value from defaultValue so DateFieldRoot is always in controlled\n// mode from the start. Without this, an uncontrolled→controlled transition\n// happens mid-lifecycle and Reka's DateFieldRoot won't re-render segments.\nif (modelValue.value == null && props.defaultValue != null) {\n modelValue.value = props.defaultValue\n}\n\n// Internal working value — always a CalendarDateTime, never null/undefined.\nconst _today = today(getLocalTimeZone())\nconst internalValue = shallowRef<CalendarDateTime>(\n modelValue.value ?? props.defaultValue ?? new CalendarDateTime(_today.year, _today.month, _today.day, 0, 0),\n)\n\n// Sync inbound: parent resets the value → update internalValue.\n// Guard on CalendarDateTime: ignore CalendarDate emits (no time info).\nwatch(modelValue, (v) => {\n if (v instanceof CalendarDateTime) internalValue.value = v\n})\n\n// Route segment edits from DateInput back to both internalValue and modelValue.\n// DateInput is bound to internalValue (not modelValue) so this is the only place\n// that propagates user-typed changes outward.\nfunction onInputChange(v: DateValue | null | undefined) {\n if (!(v instanceof CalendarDateTime)) return\n internalValue.value = v\n modelValue.value = v\n}\n\n// ─── Step state ──────────────────────────────────────────────────────────\n\nconst activeStep = ref<Step>('date')\nconst direction = ref<1 | -1>(1)\n\nwatch(openModel, (open) => {\n if (open) activeStep.value = 'date'\n})\n\nfunction goTo(step: Step) {\n const from = STEP_ORDER.indexOf(activeStep.value)\n const to = STEP_ORDER.indexOf(step)\n direction.value = to > from ? 1 : -1\n activeStep.value = step\n}\n\nfunction goBack() {\n const idx = STEP_ORDER.indexOf(activeStep.value)\n if (idx > 0) goTo(STEP_ORDER[idx - 1])\n}\n\nfunction goForward() {\n const idx = STEP_ORDER.indexOf(activeStep.value)\n if (idx < STEP_ORDER.length - 1) {\n goTo(STEP_ORDER[idx + 1])\n } else if (props.closeOnSelect) {\n openModel.value = false\n }\n}\n\n// ─── Panel animation variants ────────────────────────────────────────────\n\nconst panelInitial = computed(() => ({ x: direction.value > 0 ? '100%' : '-100%', opacity: 0 }))\nconst panelAnimate = { x: '0%', opacity: 1 }\nconst panelExit = computed(() => ({ x: direction.value > 0 ? '-100%' : '100%', opacity: 0 }))\n\n// ─── Calendar value sync ─────────────────────────────────────────────────\n\nconst calendarValue = computed<DateValue | undefined>({\n // Pass CalendarDate to CalendarRoot — Reka always emits CalendarDate from\n // onDateChange. The setter reconstructs the full CalendarDateTime.\n get: () => toCalendarDate(internalValue.value),\n set: (val) => {\n if (!val) return\n internalValue.value = internalValue.value.set({\n year: val.year,\n month: val.month,\n day: val.day,\n })\n modelValue.value = internalValue.value\n goTo('time')\n },\n})\n\n// ─── Time update ─────────────────────────────────────────────────────────\n\nfunction onTimeUpdate(val: CalendarDateTime) {\n internalValue.value = val\n modelValue.value = val\n}\n\n// ─── Styles ──────────────────────────────────────────────────────────────\n\nconst slotFns = computed(() =>\n dateTimePickerVariants({\n isInvalid: props.isInvalid,\n isDisabled: props.isDisabled,\n fullWidth: props.fullWidth,\n }),\n)\n</script>\n\n<template>\n <DatePickerRoot\n v-model=\"modelValue\"\n v-model:open=\"openModel\"\n :default-value=\"defaultValue\"\n :default-open=\"defaultOpen\"\n :min-value=\"minValue\"\n :max-value=\"maxValue\"\n :is-date-unavailable=\"isDateUnavailable\"\n :is-date-disabled=\"isDateDisabled\"\n :locale=\"locale\"\n :granularity=\"granularity\"\n :hour-cycle=\"hourCycle\"\n :disabled=\"isDisabled\"\n :readonly=\"isReadOnly\"\n :name=\"name\"\n :class=\"composeClassName(slotFns.base(), props.class)\"\n data-slot=\"date-time-picker\"\n >\n <DateInput\n :model-value=\"internalValue\"\n @update:model-value=\"onInputChange\"\n :variant=\"variant\"\n :size=\"size\"\n :color=\"color\"\n :label-placement=\"labelPlacement\"\n :full-width=\"fullWidth\"\n :default-value=\"defaultValue\"\n :granularity=\"granularity\"\n :hour-cycle=\"hourCycle\"\n :locale=\"locale\"\n :label=\"label\"\n :description=\"description\"\n :error-message=\"errorMessage\"\n :is-invalid=\"isInvalid\"\n :is-disabled=\"isDisabled\"\n :is-read-only=\"isReadOnly\"\n :is-required=\"isRequired\"\n :name=\"name\"\n :hide-time-zone=\"hideTimeZone\"\n >\n <template #endContent>\n <DatePickerTrigger\n :class=\"slotFns.trigger()\"\n aria-label=\"Open date time picker\"\n @mousedown.prevent\n >\n <slot name=\"selectorIcon\">\n <svg\n :class=\"slotFns.triggerIndicator()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" />\n <line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\" />\n <line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\" />\n <line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" />\n </svg>\n </slot>\n </DatePickerTrigger>\n </template>\n </DateInput>\n\n <DatePickerContent\n :class=\"slotFns.popover()\"\n data-slot=\"popover\"\n :side-offset=\"8\"\n >\n <!-- Step header -->\n <div :class=\"slotFns.stepHeader()\" data-slot=\"step-header\">\n <button\n type=\"button\"\n :class=\"slotFns.navButton()\"\n :data-hidden=\"activeStep === 'date' ? 'true' : undefined\"\n aria-label=\"Previous step\"\n data-slot=\"back-button\"\n @click=\"goBack\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n\n <span :class=\"slotFns.stepTitle()\">{{ STEP_TITLES[activeStep] }}</span>\n\n <button\n type=\"button\"\n :class=\"slotFns.navButton()\"\n :aria-label=\"activeStep === 'time' ? 'Done' : 'Next step'\"\n data-slot=\"forward-button\"\n @click=\"goForward\"\n >\n <span v-if=\"activeStep === 'time'\" :class=\"slotFns.doneLabel()\">Done</span>\n <svg v-else width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </button>\n </div>\n\n <!-- Sliding panels -->\n <div :class=\"slotFns.panelWrap()\" style=\"overflow: hidden;\">\n <AnimatePresence mode=\"popLayout\">\n <motion.div\n v-if=\"activeStep === 'date'\"\n key=\"date\"\n :initial=\"panelInitial\"\n :animate=\"panelAnimate\"\n :exit=\"panelExit\"\n :transition=\"{ duration: 0.15 }\"\n class=\"px-3 pb-3\"\n data-slot=\"calendar-panel\"\n >\n <Calendar\n v-model=\"calendarValue\"\n :default-value=\"defaultValue\"\n :min-value=\"minValue\"\n :max-value=\"maxValue\"\n :is-date-disabled=\"isDateDisabled\"\n :is-date-unavailable=\"isDateUnavailable\"\n :locale=\"locale\"\n :readonly=\"isReadOnly\"\n :disabled=\"isDisabled\"\n />\n </motion.div>\n\n <motion.div\n v-else-if=\"activeStep === 'time'\"\n key=\"time\"\n :initial=\"panelInitial\"\n :animate=\"panelAnimate\"\n :exit=\"panelExit\"\n :transition=\"{ duration: 0.15 }\"\n >\n <DateTimePickerTimeScroller\n :model-value=\"internalValue\"\n :granularity=\"granularity\"\n :hour-cycle=\"hourCycle\"\n @update:model-value=\"onTimeUpdate\"\n />\n </motion.div>\n\n </AnimatePresence>\n </div>\n </DatePickerContent>\n </DatePickerRoot>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default from "./DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/date-time-picker/DateTimePickerTimeScroller.vue
3
+ var DateTimePickerTimeScroller_default = DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { DateTimePickerTimeScroller_default as default };
6
+
7
+ //# sourceMappingURL=DateTimePickerTimeScroller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateTimePickerTimeScroller.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePickerTimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/date-time-picker/DateTimePickerTimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport { CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\nconst columns = computed(() => {\n const cols: Array<{ key: string; items: (number | string)[] }> = [\n { key: 'hour', items: hourItems.value },\n { key: 'minute', items: minutes },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds })\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm })\n return cols\n})\n\n// ─── Current index computation ───────────────────────────────────────────\n\nfunction currentIndexFor(key: string): number {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return hours12.indexOf(h12)\n }\n return v.hour\n }\n if (key === 'minute') return v.minute\n if (key === 'second') return v.second ?? 0\n if (key === 'ampm') return v.hour >= 12 ? 1 : 0\n return 0\n}\n\n// ─── Scroll-to-selected ──────────────────────────────────────────────────\n\nconst columnRefs = ref<HTMLElement[]>([])\n\nconst ITEM_H = 40 // 2.5rem at 16px base\n\nfunction scrollColumnToIndex(colEl: HTMLElement, index: number) {\n colEl.scrollTop = index * ITEM_H\n}\n\nfunction syncScrollPositions() {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el) scrollColumnToIndex(el, currentIndexFor(col.key))\n })\n}\n\nonMounted(() => nextTick(syncScrollPositions))\nwatch(() => props.modelValue, () => nextTick(syncScrollPositions))\n\n// ─── Scroll → value update ───────────────────────────────────────────────\n\nfunction onColumnScroll(key: string, colEl: HTMLElement) {\n const idx = Math.round(colEl.scrollTop / ITEM_H)\n const col = columns.value.find(c => c.key === key)!\n const item = col.items[idx]\n if (item === undefined) return\n\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Keyboard navigation ─────────────────────────────────────────────────\n\nfunction onKeyDown(e: KeyboardEvent, colEl: HTMLElement) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n colEl.scrollTop += ITEM_H\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n colEl.scrollTop -= ITEM_H\n }\n}\n\n// ─── Click-to-select ─────────────────────────────────────────────────────\n\nfunction onItemClick(colEl: HTMLElement, idx: number) {\n colEl.scrollTo({ top: idx * ITEM_H, behavior: 'smooth' })\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(_key: string, item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\n// expose for testing\ndefineExpose({ columnRefs, columns, currentIndexFor })\n</script>\n\n<template>\n <div\n :class=\"['date-time-picker__scroller-wrap', props.class]\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n class=\"date-time-picker__scroller-column\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(col.key, ($event.currentTarget as HTMLElement))\"\n @keydown=\"onKeyDown($event, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in col.items\"\n :key=\"idx\"\n class=\"date-time-picker__scroller-item\"\n :data-selected=\"idx === currentIndexFor(col.key) ? 'true' : undefined\"\n :aria-selected=\"idx === currentIndexFor(col.key)\"\n role=\"option\"\n @click=\"onItemClick(columnRefs[i]!, idx)\"\n >\n {{ itemLabel(col.key, item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,157 @@
1
+ import { Fragment, computed, createElementBlock, defineComponent, nextTick, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString, watch } from "vue";
2
+ //#region src/components/date-time-picker/DateTimePickerTimeScroller.vue?vue&type=script&setup=true&lang.ts
3
+ var _hoisted_1 = ["aria-label", "onScrollPassive"];
4
+ var _hoisted_2 = [
5
+ "data-selected",
6
+ "aria-selected",
7
+ "onClick"
8
+ ];
9
+ var ITEM_H = 40;
10
+ var DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
11
+ __name: "DateTimePickerTimeScroller",
12
+ props: {
13
+ modelValue: {},
14
+ granularity: { default: "minute" },
15
+ hourCycle: { default: 24 },
16
+ class: { default: void 0 }
17
+ },
18
+ emits: ["update:modelValue"],
19
+ setup(__props, { expose: __expose, emit: __emit }) {
20
+ const props = __props;
21
+ const emit = __emit;
22
+ const hours24 = Array.from({ length: 24 }, (_, i) => i);
23
+ const hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)];
24
+ const minutes = Array.from({ length: 60 }, (_, i) => i);
25
+ const seconds = Array.from({ length: 60 }, (_, i) => i);
26
+ const ampm = ["AM", "PM"];
27
+ const hourItems = computed(() => props.hourCycle === 12 ? hours12 : hours24);
28
+ const columns = computed(() => {
29
+ const cols = [{
30
+ key: "hour",
31
+ items: hourItems.value
32
+ }, {
33
+ key: "minute",
34
+ items: minutes
35
+ }];
36
+ if (props.granularity === "second") cols.push({
37
+ key: "second",
38
+ items: seconds
39
+ });
40
+ if (props.hourCycle === 12) cols.push({
41
+ key: "ampm",
42
+ items: ampm
43
+ });
44
+ return cols;
45
+ });
46
+ function currentIndexFor(key) {
47
+ const v = props.modelValue;
48
+ if (key === "hour") {
49
+ if (props.hourCycle === 12) {
50
+ const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12;
51
+ return hours12.indexOf(h12);
52
+ }
53
+ return v.hour;
54
+ }
55
+ if (key === "minute") return v.minute;
56
+ if (key === "second") return v.second ?? 0;
57
+ if (key === "ampm") return v.hour >= 12 ? 1 : 0;
58
+ return 0;
59
+ }
60
+ const columnRefs = ref([]);
61
+ function scrollColumnToIndex(colEl, index) {
62
+ colEl.scrollTop = index * ITEM_H;
63
+ }
64
+ function syncScrollPositions() {
65
+ columns.value.forEach((col, i) => {
66
+ const el = columnRefs.value[i];
67
+ if (el) scrollColumnToIndex(el, currentIndexFor(col.key));
68
+ });
69
+ }
70
+ onMounted(() => nextTick(syncScrollPositions));
71
+ watch(() => props.modelValue, () => nextTick(syncScrollPositions));
72
+ function onColumnScroll(key, colEl) {
73
+ const idx = Math.round(colEl.scrollTop / ITEM_H);
74
+ const item = columns.value.find((c) => c.key === key).items[idx];
75
+ if (item === void 0) return;
76
+ const v = props.modelValue;
77
+ if (key === "hour") {
78
+ let newHour;
79
+ if (props.hourCycle === 12) {
80
+ const isPm = v.hour >= 12;
81
+ const h12 = item;
82
+ newHour = h12 === 12 ? isPm ? 12 : 0 : isPm ? h12 + 12 : h12;
83
+ } else newHour = item;
84
+ emit("update:modelValue", v.set({ hour: newHour }));
85
+ } else if (key === "minute") emit("update:modelValue", v.set({ minute: item }));
86
+ else if (key === "second") emit("update:modelValue", v.set({ second: item }));
87
+ else if (key === "ampm") {
88
+ const isPm = item === "PM";
89
+ if (isPm !== v.hour >= 12) emit("update:modelValue", v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }));
90
+ }
91
+ }
92
+ function onKeyDown(e, colEl) {
93
+ if (e.key === "ArrowDown") {
94
+ e.preventDefault();
95
+ colEl.scrollTop += ITEM_H;
96
+ } else if (e.key === "ArrowUp") {
97
+ e.preventDefault();
98
+ colEl.scrollTop -= ITEM_H;
99
+ }
100
+ }
101
+ function onItemClick(colEl, idx) {
102
+ colEl.scrollTo({
103
+ top: idx * ITEM_H,
104
+ behavior: "smooth"
105
+ });
106
+ }
107
+ function columnLabel(key) {
108
+ if (key === "hour") return "Hour";
109
+ if (key === "minute") return "Minute";
110
+ if (key === "second") return "Second";
111
+ return "AM/PM";
112
+ }
113
+ function itemLabel(_key, item) {
114
+ if (typeof item === "string") return item;
115
+ return String(item).padStart(2, "0");
116
+ }
117
+ __expose({
118
+ columnRefs,
119
+ columns,
120
+ currentIndexFor
121
+ });
122
+ return (_ctx, _cache) => {
123
+ return openBlock(), createElementBlock("div", {
124
+ class: normalizeClass(["date-time-picker__scroller-wrap", props.class]),
125
+ "data-slot": "time-scroller"
126
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(columns.value, (col, i) => {
127
+ return openBlock(), createElementBlock("div", {
128
+ key: col.key,
129
+ ref_for: true,
130
+ ref: (el) => {
131
+ if (el) columnRefs.value[i] = el;
132
+ },
133
+ class: "date-time-picker__scroller-column",
134
+ "aria-label": columnLabel(col.key),
135
+ "data-slot": "scroller-column",
136
+ role: "listbox",
137
+ tabindex: "0",
138
+ onScrollPassive: ($event) => onColumnScroll(col.key, $event.currentTarget),
139
+ onKeydown: _cache[0] || (_cache[0] = ($event) => onKeyDown($event, $event.currentTarget))
140
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(col.items, (item, idx) => {
141
+ return openBlock(), createElementBlock("div", {
142
+ key: idx,
143
+ class: "date-time-picker__scroller-item",
144
+ "data-selected": idx === currentIndexFor(col.key) ? "true" : void 0,
145
+ "aria-selected": idx === currentIndexFor(col.key),
146
+ role: "option",
147
+ onClick: ($event) => onItemClick(columnRefs.value[i], idx)
148
+ }, toDisplayString(itemLabel(col.key, item)), 9, _hoisted_2);
149
+ }), 128))], 40, _hoisted_1);
150
+ }), 128))], 2);
151
+ };
152
+ }
153
+ });
154
+ //#endregion
155
+ export { DateTimePickerTimeScroller_vue_vue_type_script_setup_true_lang_default as default };
156
+
157
+ //# sourceMappingURL=DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateTimePickerTimeScroller.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePickerTimeScroller.vue"],"sourcesContent":["<!-- packages/vue/src/components/date-time-picker/DateTimePickerTimeScroller.vue -->\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, ref, watch } from 'vue'\nimport { CalendarDateTime } from '@internationalized/date'\n\nconst props = withDefaults(defineProps<{\n modelValue: CalendarDateTime\n granularity?: 'minute' | 'second'\n hourCycle?: 12 | 24\n class?: string\n}>(), {\n granularity: 'minute',\n hourCycle: 24,\n class: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: CalendarDateTime]\n}>()\n\n// ─── Column data ─────────────────────────────────────────────────────────\n\nconst hours24 = Array.from({ length: 24 }, (_, i) => i)\nconst hours12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)] // 12,1..11\nconst minutes = Array.from({ length: 60 }, (_, i) => i)\nconst seconds = Array.from({ length: 60 }, (_, i) => i)\nconst ampm = ['AM', 'PM']\n\nconst hourItems = computed(() =>\n props.hourCycle === 12 ? hours12 : hours24,\n)\n\nconst columns = computed(() => {\n const cols: Array<{ key: string; items: (number | string)[] }> = [\n { key: 'hour', items: hourItems.value },\n { key: 'minute', items: minutes },\n ]\n if (props.granularity === 'second') cols.push({ key: 'second', items: seconds })\n if (props.hourCycle === 12) cols.push({ key: 'ampm', items: ampm })\n return cols\n})\n\n// ─── Current index computation ───────────────────────────────────────────\n\nfunction currentIndexFor(key: string): number {\n const v = props.modelValue\n if (key === 'hour') {\n if (props.hourCycle === 12) {\n const h12 = v.hour % 12 === 0 ? 12 : v.hour % 12\n return hours12.indexOf(h12)\n }\n return v.hour\n }\n if (key === 'minute') return v.minute\n if (key === 'second') return v.second ?? 0\n if (key === 'ampm') return v.hour >= 12 ? 1 : 0\n return 0\n}\n\n// ─── Scroll-to-selected ──────────────────────────────────────────────────\n\nconst columnRefs = ref<HTMLElement[]>([])\n\nconst ITEM_H = 40 // 2.5rem at 16px base\n\nfunction scrollColumnToIndex(colEl: HTMLElement, index: number) {\n colEl.scrollTop = index * ITEM_H\n}\n\nfunction syncScrollPositions() {\n columns.value.forEach((col, i) => {\n const el = columnRefs.value[i]\n if (el) scrollColumnToIndex(el, currentIndexFor(col.key))\n })\n}\n\nonMounted(() => nextTick(syncScrollPositions))\nwatch(() => props.modelValue, () => nextTick(syncScrollPositions))\n\n// ─── Scroll → value update ───────────────────────────────────────────────\n\nfunction onColumnScroll(key: string, colEl: HTMLElement) {\n const idx = Math.round(colEl.scrollTop / ITEM_H)\n const col = columns.value.find(c => c.key === key)!\n const item = col.items[idx]\n if (item === undefined) return\n\n const v = props.modelValue\n if (key === 'hour') {\n let newHour: number\n if (props.hourCycle === 12) {\n const isPm = v.hour >= 12\n const h12 = item as number\n newHour = h12 === 12 ? (isPm ? 12 : 0) : isPm ? h12 + 12 : h12\n } else {\n newHour = item as number\n }\n emit('update:modelValue', v.set({ hour: newHour }))\n } else if (key === 'minute') {\n emit('update:modelValue', v.set({ minute: item as number }))\n } else if (key === 'second') {\n emit('update:modelValue', v.set({ second: item as number }))\n } else if (key === 'ampm') {\n const isPm = item === 'PM'\n const currentPm = v.hour >= 12\n if (isPm !== currentPm) {\n emit('update:modelValue', v.set({ hour: isPm ? v.hour + 12 : v.hour - 12 }))\n }\n }\n}\n\n// ─── Keyboard navigation ─────────────────────────────────────────────────\n\nfunction onKeyDown(e: KeyboardEvent, colEl: HTMLElement) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n colEl.scrollTop += ITEM_H\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n colEl.scrollTop -= ITEM_H\n }\n}\n\n// ─── Click-to-select ─────────────────────────────────────────────────────\n\nfunction onItemClick(colEl: HTMLElement, idx: number) {\n colEl.scrollTo({ top: idx * ITEM_H, behavior: 'smooth' })\n}\n\n// ─── Label helpers ───────────────────────────────────────────────────────\n\nfunction columnLabel(key: string): string {\n if (key === 'hour') return 'Hour'\n if (key === 'minute') return 'Minute'\n if (key === 'second') return 'Second'\n return 'AM/PM'\n}\n\nfunction itemLabel(_key: string, item: number | string): string {\n if (typeof item === 'string') return item\n return String(item).padStart(2, '0')\n}\n\n// expose for testing\ndefineExpose({ columnRefs, columns, currentIndexFor })\n</script>\n\n<template>\n <div\n :class=\"['date-time-picker__scroller-wrap', props.class]\"\n data-slot=\"time-scroller\"\n >\n <div\n v-for=\"(col, i) in columns\"\n :key=\"col.key\"\n :ref=\"(el) => { if (el) columnRefs[i] = el as HTMLElement }\"\n class=\"date-time-picker__scroller-column\"\n :aria-label=\"columnLabel(col.key)\"\n data-slot=\"scroller-column\"\n role=\"listbox\"\n tabindex=\"0\"\n @scroll.passive=\"onColumnScroll(col.key, ($event.currentTarget as HTMLElement))\"\n @keydown=\"onKeyDown($event, ($event.currentTarget as HTMLElement))\"\n >\n <div\n v-for=\"(item, idx) in col.items\"\n :key=\"idx\"\n class=\"date-time-picker__scroller-item\"\n :data-selected=\"idx === currentIndexFor(col.key) ? 'true' : undefined\"\n :aria-selected=\"idx === currentIndexFor(col.key)\"\n role=\"option\"\n @click=\"onItemClick(columnRefs[i]!, idx)\"\n >\n {{ itemLabel(col.key, item) }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"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"}