@rotki/ui-library 2.22.2 → 2.23.0

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 (100) hide show
  1. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js +1 -1
  2. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/buttons/button/RuiButton.vue.d.ts +1 -1
  4. package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +1 -1
  5. package/dist/components/calendar/RuiCalendar.js.map +1 -1
  6. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js +3 -1
  7. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  8. package/dist/components/calendar/RuiCalendarGrid.js.map +1 -1
  9. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +121 -25
  10. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +11 -4
  12. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  14. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +23 -1
  15. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +136 -24
  16. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  18. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue.d.ts +7 -0
  19. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +70 -25
  20. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  22. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +7 -3
  23. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/date-time-picker/segment-utils.d.ts +28 -0
  25. package/dist/components/date-time-picker/segment-utils.js +42 -1
  26. package/dist/components/date-time-picker/segment-utils.js.map +1 -1
  27. package/dist/components/date-time-picker/types.d.ts +2 -0
  28. package/dist/components/date-time-picker/types.js.map +1 -1
  29. package/dist/components/date-time-picker/use-date-time-selection.d.ts +6 -0
  30. package/dist/components/date-time-picker/use-date-time-selection.js +65 -42
  31. package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
  32. package/dist/components/date-time-picker/use-keyboard-handler.js +4 -3
  33. package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
  34. package/dist/components/date-time-picker/utils.d.ts +5 -0
  35. package/dist/components/date-time-picker/utils.js +12 -1
  36. package/dist/components/date-time-picker/utils.js.map +1 -1
  37. package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +1 -1
  38. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +2 -5
  39. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +1 -1
  41. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +3 -2
  42. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +1 -1
  44. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.d.ts +1 -1
  45. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +2 -1
  46. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +1 -1
  48. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +1 -1
  49. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +1 -1
  50. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +2 -1
  51. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  52. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +2 -2
  53. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +2 -2
  55. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  56. package/dist/components/tables/RuiDataTable.vue.d.ts +1 -1
  57. package/dist/components/tables/RuiTableHead.vue.d.ts +1 -1
  58. package/dist/components/tables/data-table/RuiDataTableBody.vue.d.ts +1 -1
  59. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js +2 -8
  60. package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
  61. package/dist/components/tables/data-table/RuiDataTableCell.vue.d.ts +1 -1
  62. package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue.d.ts +1 -1
  63. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue.d.ts +1 -1
  64. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +1 -1
  65. package/dist/components/tables/data-table/RuiDataTableRow.vue.d.ts +1 -1
  66. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +1 -2
  67. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/tables/use-pagination-navigation.js.map +1 -1
  69. package/dist/components/tabs/tab-items/RuiTabItems.vue.d.ts +1 -1
  70. package/dist/components/tabs/tabs/use-tab-scroll.js +2 -1
  71. package/dist/components/tabs/tabs/use-tab-scroll.js.map +1 -1
  72. package/dist/composables/forms/auto-complete/search.d.ts +1 -2
  73. package/dist/composables/forms/auto-complete/search.js.map +1 -1
  74. package/dist/composables/forms/auto-complete/value.d.ts +1 -2
  75. package/dist/composables/forms/auto-complete/value.js.map +1 -1
  76. package/dist/i18n/keys.d.ts +10 -0
  77. package/dist/i18n/keys.js +15 -5
  78. package/dist/i18n/keys.js.map +1 -1
  79. package/dist/icons/icons_1.d.ts +1 -1
  80. package/dist/icons/icons_1.js +25 -22
  81. package/dist/icons/icons_1.js.map +1 -1
  82. package/dist/icons/icons_2.d.ts +7 -7
  83. package/dist/icons/icons_2.js +126 -92
  84. package/dist/icons/icons_2.js.map +1 -1
  85. package/dist/icons/icons_3.d.ts +12 -12
  86. package/dist/icons/icons_3.js +119 -177
  87. package/dist/icons/icons_3.js.map +1 -1
  88. package/dist/icons/icons_4.d.ts +26 -26
  89. package/dist/icons/icons_4.js +320 -285
  90. package/dist/icons/icons_4.js.map +1 -1
  91. package/dist/icons/icons_5.d.ts +13 -1
  92. package/dist/icons/icons_5.js +149 -9
  93. package/dist/icons/icons_5.js.map +1 -1
  94. package/dist/icons/index.d.ts +1 -1
  95. package/dist/icons/index.js +34 -22
  96. package/dist/icons/index.js.map +1 -1
  97. package/dist/index.js +7 -7
  98. package/dist/style.css +12 -756
  99. package/dist/web-types.json +75 -10
  100. package/package.json +32 -32
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ComponentPublicInstance } from 'vue';\nimport type { DateTimePickerAction, DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n /**\n * Renders the timezone selector in the menu. Off by default: the value is\n * emitted as a date or an epoch, so the picked timezone does not survive a\n * round trip and most consumers work in local time.\n */\n showTimezone?: boolean;\n /**\n * Actions rendered in the menu footer. `clear` is only rendered when the\n * picker is `allowEmpty`. Pass an empty array to drop the footer entirely.\n */\n actions?: DateTimePickerAction[];\n /**\n * Focuses the field once it is mounted. The native attribute is ignored for\n * an input inserted into an already loaded document, which is the usual case\n * for a picker revealed by an editor or a dialog.\n */\n autofocus?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label,\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n showTimezone = false,\n actions = ['now'],\n autofocus = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst { t } = useRuiI8n();\n\nconst keys = RUI_I18N_KEYS.dateTimePicker;\n\nconst fieldLabel = computed<string>(() => label ?? t(keys.label, 'Pick a date'));\nconst clearLabel = computed<string>(() => t(keys.clearValue, 'Clear the date'));\nconst toggleLabel = computed<string>(() => (get(isOpen)\n ? t(keys.closeCalendar, 'Close the calendar')\n : t(keys.openCalendar, 'Open the calendar')));\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<ComponentPublicInstance>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n selectedYear,\n selectedMonth,\n selectedDay,\n selectedHour,\n selectedMinute,\n selectedSecond,\n selectedMillisecond,\n].some(segment => isDefined(segment)));\n\nconst formattedDisplay = computed<string>(() => {\n // An untouched field shows its format through the placeholder rather than\n // holding the tokens as its value, where a screen reader reads them as\n // content and select-all copies them. The tokens stay while the field is\n // focused: that is when the segment machinery highlights them, and\n // collapsing the value mid-edit would blank the field under the cursor.\n // The guard is \"no segment set\" and not `valueSet`, so blurring a half\n // typed date keeps what was entered on screen.\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float))\n return '';\n const resolved = get(fieldLabel);\n return required ? `${resolved} ﹡` : resolved;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\n/**\n * The menu is teleported to the body, so it never sits next to the field in\n * the tab sequence. Opening it from the keyboard therefore moves focus into\n * the calendar; opening it with the mouse leaves focus in the field, which is\n * what `disable-auto-focus` on the menu is there for.\n */\nconst focusCalendarOnOpen = ref<boolean>(false);\n\nfunction focusCalendar(): void {\n // the menu is teleported and mounts a frame later, so this waits for the\n // wrapper to appear rather than guessing at a number of ticks\n set(focusCalendarOnOpen, true);\n}\n\nwatch(menuWrapperRef, (menu) => {\n if (!menu || !get(focusCalendarOnOpen))\n return;\n\n set(focusCalendarOnOpen, false);\n nextTick(() => {\n const el = menu.$el as HTMLElement | undefined;\n el?.querySelector<HTMLButtonElement>('[role=\"gridcell\"][tabindex=\"0\"]')?.focus({ preventScroll: true });\n });\n});\n\n/** Moves focus to the field. Exposed so a consumer can drive it from a ref. */\nfunction focus(): void {\n get(textInput)?.focus({ preventScroll: true });\n}\n\nfunction focusField(): void {\n nextTick(focus);\n}\n\nonMounted(() => {\n if (autofocus && !disabled)\n focusField();\n});\n\n/** Escape inside the calendar closes it and hands focus back to the field. */\nfunction closeFromMenu(): void {\n set(isOpen, false);\n focusField();\n}\n\n/**\n * The menu used to be mouse-only: the activator carried no key handlers, so\n * there was no way to reach the calendar from the keyboard. Alt+ArrowDown\n * opens it and Escape closes it, following the combobox convention, and the\n * append chevron is a real button for anyone who tabs to it instead.\n */\nfunction onKeyDown(event: KeyboardEvent): void {\n if (disabled || readonly)\n return;\n\n if (event.altKey && event.key === 'ArrowDown') {\n event.preventDefault();\n set(isOpen, true);\n focusCalendar();\n return;\n }\n\n if (event.key === 'Escape' && get(isOpen)) {\n set(isOpen, false);\n return;\n }\n\n handleKeyDown(event);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst menuActions = computed<DateTimePickerAction[]>(\n () => actions.filter(action => action !== 'clear' || allowEmpty),\n);\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n\ndefineExpose({\n focus,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ fieldLabel }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n inputmode=\"numeric\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n :aria-label=\"fieldLabel\"\n :aria-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n color=\"error\"\n :aria-label=\"clearLabel\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"dialog\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </button>\n <span\n v-else\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n :show-timezone=\"showTimezone\"\n :actions=\"menuActions\"\n @keydown.escape=\"closeFromMenu()\"\n @set-now=\"setNow()\"\n @set-today=\"setToday()\"\n @clear=\"clear()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -1,3 +1,4 @@
1
+ import type { DateTimePickerAction } from '../../components/date-time-picker/types.js';
1
2
  import { type DateTimePickerVariant } from '../../components/date-time-picker/date-time-picker-styles.js';
2
3
  type DateFormat = 'year-first' | 'month-first' | 'day-first';
3
4
  type DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';
@@ -19,17 +20,38 @@ export interface RuiDateTimePickerProps {
19
20
  successMessages?: string | string[];
20
21
  hideDetails?: boolean;
21
22
  required?: boolean;
23
+ /**
24
+ * Renders the timezone selector in the menu. Off by default: the value is
25
+ * emitted as a date or an epoch, so the picked timezone does not survive a
26
+ * round trip and most consumers work in local time.
27
+ */
28
+ showTimezone?: boolean;
29
+ /**
30
+ * Actions rendered in the menu footer. `clear` is only rendered when the
31
+ * picker is `allowEmpty`. Pass an empty array to drop the footer entirely.
32
+ */
33
+ actions?: DateTimePickerAction[];
34
+ /**
35
+ * Focuses the field once it is mounted. The native attribute is ignored for
36
+ * an input inserted into an already loaded document, which is the usual case
37
+ * for a picker revealed by an editor or a dialog.
38
+ */
39
+ autofocus?: boolean;
22
40
  }
23
41
  type __VLS_Props = RuiDateTimePickerProps;
24
42
  type __VLS_Slots = {
25
43
  'menu-content': () => any;
26
44
  };
45
+ /** Moves focus to the field. Exposed so a consumer can drive it from a ref. */
46
+ declare function focus(): void;
27
47
  type __VLS_ModelProps = {
28
48
  modelValue: ModelValueType<DateTimeModelType>;
29
49
  'menuOpen'?: boolean;
30
50
  };
31
51
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
32
- declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
52
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
53
+ focus: typeof focus;
54
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
33
55
  "update:modelValue": (value: number | Date | undefined) => any;
34
56
  "update:menuOpen": (value: boolean) => any;
35
57
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
@@ -1,3 +1,4 @@
1
+ import { useRuiI8n } from "../../composables/use-rui-i18n.js";
1
2
  import { cn } from "../../utils/tv.js";
2
3
  import RuiIcon_default from "../icons/RuiIcon.js";
3
4
  import RuiButton_default from "../buttons/button/RuiButton.js";
@@ -6,22 +7,26 @@ import { Placement } from "../../composables/floating.js";
6
7
  import RuiMenu_default from "../overlays/menu/RuiMenu.js";
7
8
  import { getNonRootAttrs, getRootAttrs } from "../../utils/helpers.js";
8
9
  import { dateTimePickerStyles } from "./date-time-picker-styles.js";
10
+ import { RUI_I18N_KEYS } from "../../i18n/keys.js";
9
11
  import RuiDateTimePickerMenu_default from "./RuiDateTimePickerMenu.js";
10
12
  import { useDateTimeSelection } from "./use-date-time-selection.js";
11
13
  import { useInputHandler } from "./use-input-handler.js";
12
14
  import { useKeyboardHandler } from "./use-keyboard-handler.js";
13
- import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, isRef, mergeModels, mergeProps, nextTick, normalizeClass, openBlock, ref, renderSlot, toDisplayString, unref, useModel, useTemplateRef, watch, withCtx, withModifiers } from "vue";
15
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, isRef, mergeModels, mergeProps, nextTick, normalizeClass, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
14
16
  import { isDefined, useFocus, useFocusWithin } from "@vueuse/core";
15
17
  import { get as get$1, set as set$1 } from "@vueuse/shared";
16
18
  //#region src/components/date-time-picker/RuiDateTimePicker.vue?vue&type=script&setup=true&lang.ts
17
- var _hoisted_1 = ["aria-invalid", "tabindex"];
19
+ var _hoisted_1 = ["aria-invalid"];
18
20
  var _hoisted_2 = [
19
21
  "disabled",
20
22
  "value",
21
23
  "placeholder",
22
24
  "readonly",
23
- "aria-invalid"
25
+ "aria-invalid",
26
+ "aria-label",
27
+ "aria-required"
24
28
  ];
29
+ var _hoisted_3 = ["aria-label", "aria-expanded"];
25
30
  var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
26
31
  name: "RuiDateTimePicker",
27
32
  inheritAttrs: false,
@@ -48,7 +53,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
48
53
  type: Boolean,
49
54
  default: false
50
55
  },
51
- label: { default: "Pick a date" },
56
+ label: {},
52
57
  variant: { default: "default" },
53
58
  hint: {},
54
59
  errorMessages: { default: () => [] },
@@ -60,6 +65,15 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
60
65
  required: {
61
66
  type: Boolean,
62
67
  default: false
68
+ },
69
+ showTimezone: {
70
+ type: Boolean,
71
+ default: false
72
+ },
73
+ actions: { default: () => ["now"] },
74
+ autofocus: {
75
+ type: Boolean,
76
+ default: false
63
77
  }
64
78
  }, {
65
79
  "modelValue": { required: true },
@@ -71,7 +85,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
71
85
  "menuOpenModifiers": {}
72
86
  }),
73
87
  emits: ["update:modelValue", "update:menuOpen"],
74
- setup(__props) {
88
+ setup(__props, { expose: __expose }) {
75
89
  const modelValue = useModel(__props, "modelValue");
76
90
  const menuOpen = useModel(__props, "menuOpen");
77
91
  const MENU_OPTIONS = { placement: Placement.bottomStart };
@@ -84,6 +98,11 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
84
98
  const isHovered = ref(false);
85
99
  const cursorPosition = ref(0);
86
100
  const currentValue = ref();
101
+ const { t } = useRuiI8n();
102
+ const keys = RUI_I18N_KEYS.dateTimePicker;
103
+ const fieldLabel = computed(() => __props.label ?? t(keys.label, "Pick a date"));
104
+ const clearLabel = computed(() => t(keys.clearValue, "Clear the date"));
105
+ const toggleLabel = computed(() => get$1(isOpen) ? t(keys.closeCalendar, "Close the calendar") : t(keys.openCalendar, "Open the calendar"));
87
106
  const textInput = useTemplateRef("textInput");
88
107
  const activator = useTemplateRef("activator");
89
108
  const menuWrapperRef = useTemplateRef("menuWrapperRef");
@@ -92,21 +111,22 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
92
111
  const { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);
93
112
  const { focused: searchInputFocused } = useFocus(textInput);
94
113
  const anyFocused = computed(() => get$1(activatorFocusedWithin) || get$1(menuWrapperFocusedWithin));
95
- const { clear: clearSelection, getDateTime, internalErrorMessages, maxAllowedDate, minAllowedDate, segmentData, selectedDate, selectedDay, selectedHour, selectedMillisecond, selectedMinute, selectedMonth, selectedSecond, selectedTime, selectedTimezone, selectedYear, setNow, valueSet } = useDateTimeSelection({
114
+ const dateFormat = computed(() => {
115
+ const fmt = baseFormats[__props.format];
116
+ if (__props.accuracy === "second") return fmt.replace("HH:mm", "HH:mm:ss");
117
+ else if (__props.accuracy === "millisecond") return fmt.replace("HH:mm", "HH:mm:ss.SSS");
118
+ return fmt;
119
+ });
120
+ const { clear: clearSelection, getDateTime, internalErrorMessages, maxAllowedDate, minAllowedDate, segmentData, selectedDate, selectedDay, selectedHour, selectedMillisecond, selectedMinute, selectedMonth, selectedSecond, selectedTime, selectedTimezone, selectedYear, setNow, setToday, valueSet } = useDateTimeSelection({
96
121
  accuracy: __props.accuracy,
97
122
  allowEmpty: __props.allowEmpty,
123
+ dateFormat,
98
124
  maxDate: __props.maxDate,
99
125
  minDate: __props.minDate,
100
126
  modelValue,
101
127
  type: __props.type
102
128
  });
103
129
  const { setValue, getCurrent } = useInputHandler(segmentData, currentValue);
104
- const dateFormat = computed(() => {
105
- const fmt = baseFormats[__props.format];
106
- if (__props.accuracy === "second") return fmt.replace("HH:mm", "HH:mm:ss");
107
- else if (__props.accuracy === "millisecond") return fmt.replace("HH:mm", "HH:mm:ss.SSS");
108
- return fmt;
109
- });
110
130
  const { clear: clearSegment, getCurrentSegment, handleBlur, handleClick, handleFocus, handleInput, handleInputSelection, handleKeyDown, handleMouseDown, handlePaste, setSegment } = useKeyboardHandler({
111
131
  accuracy: __props.accuracy,
112
132
  currentValue,
@@ -121,7 +141,18 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
121
141
  });
122
142
  const { hasError, hasSuccess } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
123
143
  const isOutlined = computed(() => __props.variant === "outlined");
144
+ /** True once any segment holds a digit, even a partially typed date. */
145
+ const anySegmentSet = computed(() => [
146
+ selectedYear,
147
+ selectedMonth,
148
+ selectedDay,
149
+ selectedHour,
150
+ selectedMinute,
151
+ selectedSecond,
152
+ selectedMillisecond
153
+ ].some((segment) => isDefined(segment)));
124
154
  const formattedDisplay = computed(() => {
155
+ if (!get$1(anySegmentSet) && !get$1(searchInputFocused)) return "";
125
156
  let result = get$1(dateFormat);
126
157
  const replacements = [
127
158
  {
@@ -174,8 +205,9 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
174
205
  });
175
206
  const float = computed(() => (get$1(isOpen) || get$1(valueSet) || get$1(searchInputFocused)) && get$1(isOutlined));
176
207
  const legendText = computed(() => {
177
- if (!get$1(float) || !__props.label) return "";
178
- return __props.required ? `${__props.label} ﹡` : __props.label;
208
+ if (!get$1(float)) return "";
209
+ const resolved = get$1(fieldLabel);
210
+ return __props.required ? `${resolved} ﹡` : resolved;
179
211
  });
180
212
  const ui = computed(() => dateTimePickerStyles({
181
213
  filled: __props.variant === "filled",
@@ -213,19 +245,73 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
213
245
  handleClick(event);
214
246
  if (!get$1(isOpen)) set$1(isOpen, true);
215
247
  }
248
+ /**
249
+ * The menu is teleported to the body, so it never sits next to the field in
250
+ * the tab sequence. Opening it from the keyboard therefore moves focus into
251
+ * the calendar; opening it with the mouse leaves focus in the field, which is
252
+ * what `disable-auto-focus` on the menu is there for.
253
+ */
254
+ const focusCalendarOnOpen = ref(false);
255
+ function focusCalendar() {
256
+ set$1(focusCalendarOnOpen, true);
257
+ }
258
+ watch(menuWrapperRef, (menu) => {
259
+ if (!menu || !get$1(focusCalendarOnOpen)) return;
260
+ set$1(focusCalendarOnOpen, false);
261
+ nextTick(() => {
262
+ menu.$el?.querySelector("[role=\"gridcell\"][tabindex=\"0\"]")?.focus({ preventScroll: true });
263
+ });
264
+ });
265
+ /** Moves focus to the field. Exposed so a consumer can drive it from a ref. */
266
+ function focus() {
267
+ get$1(textInput)?.focus({ preventScroll: true });
268
+ }
269
+ function focusField() {
270
+ nextTick(focus);
271
+ }
272
+ onMounted(() => {
273
+ if (__props.autofocus && !__props.disabled) focusField();
274
+ });
275
+ /** Escape inside the calendar closes it and hands focus back to the field. */
276
+ function closeFromMenu() {
277
+ set$1(isOpen, false);
278
+ focusField();
279
+ }
280
+ /**
281
+ * The menu used to be mouse-only: the activator carried no key handlers, so
282
+ * there was no way to reach the calendar from the keyboard. Alt+ArrowDown
283
+ * opens it and Escape closes it, following the combobox convention, and the
284
+ * append chevron is a real button for anyone who tabs to it instead.
285
+ */
286
+ function onKeyDown(event) {
287
+ if (__props.disabled || __props.readonly) return;
288
+ if (event.altKey && event.key === "ArrowDown") {
289
+ event.preventDefault();
290
+ set$1(isOpen, true);
291
+ focusCalendar();
292
+ return;
293
+ }
294
+ if (event.key === "Escape" && get$1(isOpen)) {
295
+ set$1(isOpen, false);
296
+ return;
297
+ }
298
+ handleKeyDown(event);
299
+ }
216
300
  function arrowClicked(event) {
217
301
  if (get$1(isOpen)) {
218
302
  set$1(isOpen, false);
219
303
  event.stopPropagation();
220
304
  }
221
305
  }
306
+ const menuActions = computed(() => __props.actions.filter((action) => action !== "clear" || __props.allowEmpty));
222
307
  watch(computed(() => get$1(isOpen) || get$1(calendarMenuOpen)), (value) => {
223
308
  set$1(menuOpen, value);
224
309
  });
310
+ __expose({ focus });
225
311
  return (_ctx, _cache) => {
226
312
  return openBlock(), createBlock(RuiMenu_default, mergeProps({
227
313
  modelValue: unref(isOpen),
228
- "onUpdate:modelValue": _cache[23] || (_cache[23] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
314
+ "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
229
315
  }, unref(getRootAttrs)(_ctx.$attrs, []), {
230
316
  class: unref(ui).wrapper({ class: unref(cn)(_ctx.$attrs.class) }),
231
317
  options: MENU_OPTIONS,
@@ -250,7 +336,6 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
250
336
  }, {
251
337
  "data-id": "activator",
252
338
  "aria-invalid": unref(hasError),
253
- tabindex: __props.disabled || __props.readonly ? -1 : 0,
254
339
  onMouseenter: _cache[10] || (_cache[10] = ($event) => isHovered.value = true),
255
340
  onMouseleave: _cache[11] || (_cache[11] = ($event) => isHovered.value = false),
256
341
  onClick: _cache[12] || (_cache[12] = ($event) => setInputFocus())
@@ -259,7 +344,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
259
344
  key: 0,
260
345
  "data-id": "label",
261
346
  class: normalizeClass([unref(ui).label(), { "pr-2": !unref(valueSet) && !open && unref(isOutlined) }])
262
- }, [createTextVNode(toDisplayString(__props.label) + " ", 1), __props.required ? (openBlock(), createElementBlock("span", {
347
+ }, [createTextVNode(toDisplayString(unref(fieldLabel)) + " ", 1), __props.required ? (openBlock(), createElementBlock("span", {
263
348
  key: 0,
264
349
  "data-id": "required-indicator",
265
350
  class: normalizeClass(unref(ui).required())
@@ -276,15 +361,22 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
276
361
  value: unref(formattedDisplay),
277
362
  class: "bg-transparent outline-none flex-1 min-w-0",
278
363
  type: "text",
364
+ inputmode: "numeric",
365
+ spellcheck: "false",
366
+ autocomplete: "off",
367
+ autocorrect: "off",
368
+ autocapitalize: "off",
279
369
  placeholder: unref(dateFormat),
280
370
  readonly: __props.readonly,
281
371
  "aria-invalid": unref(hasError),
372
+ "aria-label": unref(fieldLabel),
373
+ "aria-required": __props.required || void 0,
282
374
  onMousedown: _cache[0] || (_cache[0] = ($event) => unref(handleMouseDown)($event)),
283
375
  onFocus: _cache[1] || (_cache[1] = ($event) => unref(handleFocus)()),
284
376
  onBlur: _cache[2] || (_cache[2] = ($event) => unref(handleBlur)()),
285
377
  onSelect: _cache[3] || (_cache[3] = ($event) => unref(handleInputSelection)($event)),
286
378
  onClick: _cache[4] || (_cache[4] = withModifiers(($event) => handleInputClick($event), ["stop"])),
287
- onKeydown: _cache[5] || (_cache[5] = ($event) => unref(handleKeyDown)($event)),
379
+ onKeydown: _cache[5] || (_cache[5] = ($event) => onKeyDown($event)),
288
380
  onPaste: _cache[6] || (_cache[6] = ($event) => unref(handlePaste)($event)),
289
381
  onInput: _cache[7] || (_cache[7] = ($event) => unref(handleInput)($event))
290
382
  }, null, 40, _hoisted_2)], 2),
@@ -294,8 +386,8 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
294
386
  icon: "",
295
387
  "data-id": "clear-button",
296
388
  size: "sm",
297
- tabindex: "-1",
298
389
  color: "error",
390
+ "aria-label": unref(clearLabel),
299
391
  class: normalizeClass([
300
392
  unref(ui).clear(),
301
393
  unref(anyFocused) && "!visible",
@@ -308,16 +400,29 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
308
400
  size: "18"
309
401
  })]),
310
402
  _: 1
311
- }, 8, ["class"])) : createCommentVNode("", true),
312
- createElementVNode("span", {
403
+ }, 8, ["aria-label", "class"])) : createCommentVNode("", true),
404
+ !__props.disabled && !__props.readonly ? (openBlock(), createElementBlock("button", {
405
+ key: 2,
406
+ type: "button",
313
407
  class: normalizeClass(unref(ui).iconWrapper()),
314
408
  "data-id": "append",
409
+ "aria-label": unref(toggleLabel),
410
+ "aria-expanded": unref(isOpen),
411
+ "aria-haspopup": "dialog",
315
412
  onClick: _cache[9] || (_cache[9] = ($event) => arrowClicked($event))
316
413
  }, [createVNode(RuiIcon_default, {
317
414
  class: normalizeClass(unref(ui).icon()),
318
415
  size: __props.dense ? 16 : 24,
319
416
  name: "lu-chevron-down"
320
- }, null, 8, ["class", "size"])], 2)
417
+ }, null, 8, ["class", "size"])], 10, _hoisted_3)) : (openBlock(), createElementBlock("span", {
418
+ key: 3,
419
+ class: normalizeClass(unref(ui).iconWrapper()),
420
+ "data-id": "append"
421
+ }, [createVNode(RuiIcon_default, {
422
+ class: normalizeClass(unref(ui).icon()),
423
+ size: __props.dense ? 16 : 24,
424
+ name: "lu-chevron-down"
425
+ }, null, 8, ["class", "size"])], 2))
321
426
  ], 16, _hoisted_1), unref(isOutlined) ? (openBlock(), createElementBlock("fieldset", {
322
427
  key: 0,
323
428
  class: normalizeClass(unref(ui).fieldset())
@@ -346,7 +451,12 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
346
451
  accuracy: __props.accuracy,
347
452
  "max-date": unref(maxAllowedDate),
348
453
  "min-date": unref(minAllowedDate),
349
- onSetNow: _cache[22] || (_cache[22] = ($event) => unref(setNow)())
454
+ "show-timezone": __props.showTimezone,
455
+ actions: unref(menuActions),
456
+ onKeydown: _cache[22] || (_cache[22] = withKeys(($event) => closeFromMenu(), ["escape"])),
457
+ onSetNow: _cache[23] || (_cache[23] = ($event) => unref(setNow)()),
458
+ onSetToday: _cache[24] || (_cache[24] = ($event) => unref(setToday)()),
459
+ onClear: _cache[25] || (_cache[25] = ($event) => clear())
350
460
  }, {
351
461
  default: withCtx(() => [renderSlot(_ctx.$slots, "menu-content")]),
352
462
  _: 3
@@ -362,7 +472,9 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
362
472
  "calendar-menu-open",
363
473
  "accuracy",
364
474
  "max-date",
365
- "min-date"
475
+ "min-date",
476
+ "show-timezone",
477
+ "actions"
366
478
  ])]),
367
479
  _: 3
368
480
  }, 16, [
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ComponentPublicInstance } from 'vue';\nimport type { DateTimePickerAction, DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n /**\n * Renders the timezone selector in the menu. Off by default: the value is\n * emitted as a date or an epoch, so the picked timezone does not survive a\n * round trip and most consumers work in local time.\n */\n showTimezone?: boolean;\n /**\n * Actions rendered in the menu footer. `clear` is only rendered when the\n * picker is `allowEmpty`. Pass an empty array to drop the footer entirely.\n */\n actions?: DateTimePickerAction[];\n /**\n * Focuses the field once it is mounted. The native attribute is ignored for\n * an input inserted into an already loaded document, which is the usual case\n * for a picker revealed by an editor or a dialog.\n */\n autofocus?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label,\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n showTimezone = false,\n actions = ['now'],\n autofocus = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst MENU_OPTIONS: FloatingOptions = { placement: Placement.bottomStart };\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst { t } = useRuiI8n();\n\nconst keys = RUI_I18N_KEYS.dateTimePicker;\n\nconst fieldLabel = computed<string>(() => label ?? t(keys.label, 'Pick a date'));\nconst clearLabel = computed<string>(() => t(keys.clearValue, 'Clear the date'));\nconst toggleLabel = computed<string>(() => (get(isOpen)\n ? t(keys.closeCalendar, 'Close the calendar')\n : t(keys.openCalendar, 'Open the calendar')));\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<ComponentPublicInstance>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n selectedYear,\n selectedMonth,\n selectedDay,\n selectedHour,\n selectedMinute,\n selectedSecond,\n selectedMillisecond,\n].some(segment => isDefined(segment)));\n\nconst formattedDisplay = computed<string>(() => {\n // An untouched field shows its format through the placeholder rather than\n // holding the tokens as its value, where a screen reader reads them as\n // content and select-all copies them. The tokens stay while the field is\n // focused: that is when the segment machinery highlights them, and\n // collapsing the value mid-edit would blank the field under the cursor.\n // The guard is \"no segment set\" and not `valueSet`, so blurring a half\n // typed date keeps what was entered on screen.\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float))\n return '';\n const resolved = get(fieldLabel);\n return required ? `${resolved} ﹡` : resolved;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\n/**\n * The menu is teleported to the body, so it never sits next to the field in\n * the tab sequence. Opening it from the keyboard therefore moves focus into\n * the calendar; opening it with the mouse leaves focus in the field, which is\n * what `disable-auto-focus` on the menu is there for.\n */\nconst focusCalendarOnOpen = ref<boolean>(false);\n\nfunction focusCalendar(): void {\n // the menu is teleported and mounts a frame later, so this waits for the\n // wrapper to appear rather than guessing at a number of ticks\n set(focusCalendarOnOpen, true);\n}\n\nwatch(menuWrapperRef, (menu) => {\n if (!menu || !get(focusCalendarOnOpen))\n return;\n\n set(focusCalendarOnOpen, false);\n nextTick(() => {\n const el = menu.$el as HTMLElement | undefined;\n el?.querySelector<HTMLButtonElement>('[role=\"gridcell\"][tabindex=\"0\"]')?.focus({ preventScroll: true });\n });\n});\n\n/** Moves focus to the field. Exposed so a consumer can drive it from a ref. */\nfunction focus(): void {\n get(textInput)?.focus({ preventScroll: true });\n}\n\nfunction focusField(): void {\n nextTick(focus);\n}\n\nonMounted(() => {\n if (autofocus && !disabled)\n focusField();\n});\n\n/** Escape inside the calendar closes it and hands focus back to the field. */\nfunction closeFromMenu(): void {\n set(isOpen, false);\n focusField();\n}\n\n/**\n * The menu used to be mouse-only: the activator carried no key handlers, so\n * there was no way to reach the calendar from the keyboard. Alt+ArrowDown\n * opens it and Escape closes it, following the combobox convention, and the\n * append chevron is a real button for anyone who tabs to it instead.\n */\nfunction onKeyDown(event: KeyboardEvent): void {\n if (disabled || readonly)\n return;\n\n if (event.altKey && event.key === 'ArrowDown') {\n event.preventDefault();\n set(isOpen, true);\n focusCalendar();\n return;\n }\n\n if (event.key === 'Escape' && get(isOpen)) {\n set(isOpen, false);\n return;\n }\n\n handleKeyDown(event);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst menuActions = computed<DateTimePickerAction[]>(\n () => actions.filter(action => action !== 'clear' || allowEmpty),\n);\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n\ndefineExpose({\n focus,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n :options=\"MENU_OPTIONS\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ fieldLabel }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n inputmode=\"numeric\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n :aria-label=\"fieldLabel\"\n :aria-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n color=\"error\"\n :aria-label=\"clearLabel\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n :aria-label=\"toggleLabel\"\n :aria-expanded=\"isOpen\"\n aria-haspopup=\"dialog\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </button>\n <span\n v-else\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n :show-timezone=\"showTimezone\"\n :actions=\"menuActions\"\n @keydown.escape=\"closeFromMenu()\"\n @set-now=\"setNow()\"\n @set-today=\"setToday()\"\n @clear=\"clear()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEA,MAAM,aAAa,SAA8C,SAAA,YAAmB;EACpF,MAAM,WAAW,SAAoB,SAAC,UAA8B;EA4BpE,MAAM,eAAgC,EAAE,WAAW,UAAU,YAAY;EAEzE,MAAM,cAA0C;GAC9C,aAAa;GACb,eAAe;GACf,cAAc;EAChB;EAEA,MAAM,SAAS,IAAa,KAAK;EACjC,MAAM,YAAY,IAAa,KAAK;EACpC,MAAM,iBAAiB,IAAY,CAAC;EACpC,MAAM,eAAe,IAAY;EAEjC,MAAM,EAAE,MAAM,UAAU;EAExB,MAAM,OAAO,cAAc;EAE3B,MAAM,aAAa,eAAuB,QAAA,SAAS,EAAE,KAAK,OAAO,aAAa,CAAC;EAC/E,MAAM,aAAa,eAAuB,EAAE,KAAK,YAAY,gBAAgB,CAAC;EAC9E,MAAM,cAAc,eAAwB,MAAI,MAAM,IAClD,EAAE,KAAK,eAAe,oBAAoB,IAC1C,EAAE,KAAK,cAAc,mBAAmB,CAAE;EAE9C,MAAM,YAAY,eAAiC,WAAW;EAC9D,MAAM,YAAY,eAA+B,WAAW;EAC5D,MAAM,iBAAiB,eAAwC,gBAAgB;EAC/E,MAAM,mBAAmB,IAAa,KAAK;EAE3C,MAAM,EAAE,SAAS,2BAA2B,eAAe,SAAS;EACpE,MAAM,EAAE,SAAS,6BAA6B,eAAe,cAAc;EAC3E,MAAM,EAAE,SAAS,uBAAuB,SAAS,SAAS;EAE1D,MAAM,aAAa,eAAwB,MAAI,sBAAsB,KAAK,MAAI,wBAAwB,CAAC;EAEvG,MAAM,aAAa,eAAuB;GACxC,MAAM,MAAM,YAAY,QAAA;GACxB,IAAI,QAAA,aAAa,UACf,OAAO,IAAI,QAAQ,SAAS,UAAU;QAEnC,IAAI,QAAA,aAAa,eACpB,OAAO,IAAI,QAAQ,SAAS,cAAc;GAE5C,OAAO;EACT,CAAC;EAED,MAAM,EACJ,OAAO,gBACP,aACA,uBACA,gBACA,gBACA,aACA,cACA,aACA,cACA,qBACA,gBACA,eACA,gBACA,cACA,kBACA,cACA,QACA,UACA,aACE,qBAAqB;GACvB,UAAO,QAAA;GACP,YAAS,QAAA;GACT;GACA,SAAM,QAAA;GACN,SAAM,QAAA;GACN;GACA,MAAG,QAAA;EACL,CAAC;EAED,MAAM,EAAE,UAAU,eAAe,gBAAgB,aAAa,YAAY;EAE1E,MAAM,EACJ,OAAO,cACP,mBACA,YACA,aACA,aACA,aACA,sBACA,eACA,iBACA,aACA,eACE,mBAAmB;GACrB,UAAO,QAAA;GACP;GACA;GACA;GACA,UAAO,QAAA;GACP;GACA;GACA,UAAO,QAAA;GACP;GACA;EACF,CAAC;EAED,MAAM,EAAE,UAAU,eAAe,wBACzB,QAAA,qBACA,QAAA,eACR;EAEA,MAAM,aAAa,eAAwB,QAAA,YAAY,UAAU;;EAGjE,MAAM,gBAAgB,eAAwB;GAC5C;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,MAAK,YAAW,UAAU,OAAO,CAAC,CAAC;EAErC,MAAM,mBAAmB,eAAuB;GAQ9C,IAAI,CAAC,MAAI,aAAa,KAAK,CAAC,MAAI,kBAAkB,GAChD,OAAO;GAGT,IAAI,SAAS,MAAI,UAAU;GAE3B,MAAM,eAAe;IACnB;KAAE,SAAS;KAAQ,OAAO,gBAAgB,cAAc,CAAC;IAAE;IAC3D;KAAE,SAAS;KAAM,OAAO,gBAAgB,eAAe,CAAC;IAAE;IAC1D;KAAE,SAAS;KAAM,OAAO,gBAAgB,aAAa,CAAC;IAAE;IACxD;KAAE,SAAS;KAAM,OAAO,gBAAgB,cAAc,CAAC;IAAE;IACzD;KAAE,SAAS;KAAM,OAAO,gBAAgB,gBAAgB,CAAC;IAAE;IAC3D;KAAE,SAAS;KAAM,OAAO,gBAAgB,gBAAgB,CAAC;IAAE;IAC3D;KAAE,SAAS;KAAO,OAAO,gBAAgB,qBAAqB,CAAC;IAAE;GACnE;GAEA,KAAK,MAAM,EAAE,SAAS,WAAW,cAC/B,IAAI,UAAU,KAAA,GACZ,SAAS,OAAO,QAAQ,SAAS,KAAK;GAI1C,OAAO;EACT,CAAC;EAED,MAAM,gBAAgB,SAA8B;GAClD,MAAM;IACJ,MAAM,OAAO,kBAAkB,CAAC,EAAE;IAElC,IAAI,SAAS,MACX,OAAO;SAEJ,IAAI,SAAS,MAChB,OAAO;SAEJ,IAAI,SAAS,OAChB,OAAO;IAET,OAAO;GACT;GACA,IAAI,OAA4B;IAC9B,IAAI,cAAmC;IACvC,IAAI,UAAU,UACZ,cAAc;SAEX,IAAI,UAAU,UACjB,cAAc;SAEX,IAAI,UAAU,eACjB,cAAc;IAGhB,WAAW,WAAW;GACxB;EACF,CAAC;EAED,MAAM,QAAQ,gBAAyB,MAAI,MAAM,KAAK,MAAI,QAAQ,KAAK,MAAI,kBAAkB,MAAM,MAAI,UAAU,CAAC;EAElH,MAAM,aAAa,eAAuB;GACxC,IAAI,CAAC,MAAI,KAAK,GACZ,OAAO;GACT,MAAM,WAAW,MAAI,UAAU;GAC/B,OAAO,QAAA,WAAW,GAAG,SAAS,MAAM;EACtC,CAAC;EAED,MAAM,KAAK,eAAwD,qBAAqB;GACtF,QAAQ,QAAA,YAAY;GACpB,UAAU,MAAI,UAAU;GACxB,OAAO,MAAI,KAAK;GAChB,QAAQ,MAAI,MAAM;GAClB,SAAS,MAAI,SAAS;GACtB,OAAI,QAAA;GACJ,UAAO,QAAA;GACP,UAAO,QAAA;GACP,UAAU,MAAI,QAAQ;GACtB,YAAY,MAAI,UAAU,KAAK,CAAC,MAAI,QAAQ;EAC9C,CAAC,CAAC;EAEF,MAAM,wBAAwB,eAAyB;GACrD,IAAI,CAAC,QAAA,eACH,OAAO,MAAI,qBAAqB;GAGlC,OAAO,CAAC,GADW,MAAM,QAAQ,QAAA,aAAa,IAAI,QAAA,gBAAgB,CAAC,QAAA,aAAa,GACzD,GAAG,MAAI,qBAAqB,CAAC;EACtD,CAAC;EAED,SAAS,gBAAgB,OAAgC,SAAqC;GAC5F,OAAO,UAAU,KAAK,IAAI,MAAI,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,SAAS,GAAG,IAAI,KAAA;EAC3E;EAEA,eAAe,gBAA+B;GAC5C,MAAM,eAAe;IACnB,MAAI,oBAAoB,IAAI;GAC9B,CAAC;EACH;EAEA,SAAS,MAAM,aAA4B;GACzC,IAAI,CAAC,aAAa;IAChB,eAAe;IACf,MAAI,cAAc,KAAA,CAAS;IAC3B;GACF;GAEA,aAAa,WAAW;EAC1B;EAEA,SAAS,iBAAiB,OAAyB;GAEjD,YAAY,KAAK;GAEjB,IAAI,CAAC,MAAI,MAAM,GACb,MAAI,QAAQ,IAAI;EAEpB;;;;;;;EAQA,MAAM,sBAAsB,IAAa,KAAK;EAE9C,SAAS,gBAAsB;GAG7B,MAAI,qBAAqB,IAAI;EAC/B;EAEA,MAAM,iBAAiB,SAAS;GAC9B,IAAI,CAAC,QAAQ,CAAC,MAAI,mBAAmB,GACnC;GAEF,MAAI,qBAAqB,KAAK;GAC9B,eAAe;IAEb,KADgB,KACZ,cAAiC,qCAAiC,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;GACxG,CAAC;EACH,CAAC;;EAGD,SAAS,QAAc;GACrB,MAAI,SAAS,CAAC,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC;EAC/C;EAEA,SAAS,aAAmB;GAC1B,SAAS,KAAK;EAChB;EAEA,gBAAgB;GACd,IAAI,QAAA,aAAa,CAAC,QAAA,UAChB,WAAW;EACf,CAAC;;EAGD,SAAS,gBAAsB;GAC7B,MAAI,QAAQ,KAAK;GACjB,WAAW;EACb;;;;;;;EAQA,SAAS,UAAU,OAA4B;GAC7C,IAAI,QAAA,YAAY,QAAA,UACd;GAEF,IAAI,MAAM,UAAU,MAAM,QAAQ,aAAa;IAC7C,MAAM,eAAe;IACrB,MAAI,QAAQ,IAAI;IAChB,cAAc;IACd;GACF;GAEA,IAAI,MAAM,QAAQ,YAAY,MAAI,MAAM,GAAG;IACzC,MAAI,QAAQ,KAAK;IACjB;GACF;GAEA,cAAc,KAAK;EACrB;EAEA,SAAS,aAAa,OAAyB;GAC7C,IAAI,MAAI,MAAM,GAAG;IACf,MAAI,QAAQ,KAAK;IACjB,MAAM,gBAAgB;GACxB;EACF;EAEA,MAAM,cAAc,eACZ,QAAA,QAAQ,QAAO,WAAU,WAAW,WAAW,QAAA,UAAU,CACjE;EAIA,MAFoB,eAAwB,MAAI,MAAM,KAAK,MAAI,gBAAgB,CAEzE,IAAc,UAAU;GAC5B,MAAI,UAAU,KAAK;EACrB,CAAC;EAED,SAAa,EACX,MACF,CAAC;;uBAIC,YAuKU,iBAvKV,WAuKU;gBAtKC,MAAA,MAAA;0FAAM,QAAA,SAAA;MACP,MAAA,YAAA,CAAY,CAACA,KAAAA,QAAM,CAAA,CAAA,GAAA;IAC1B,OAAO,MAAA,EAAA,CAAE,CAAC,QAAO,EAAA,OAAU,MAAA,EAAA,CAAE,CAACA,KAAAA,OAAO,KAAK,EAAA,CAAA;IAC1C,SAAS;IACT,OAAO,QAAA;IACP,MAAM,QAAA;IACN,UAAU,QAAA;IACV,oBAAkB,QAAA;IAClB,kBAAgB,MAAA,qBAAA;IAChB,0BAAwB;IACxB,gBAAY,CAAG,QAAA;IACf,YAAY,MAAA,gBAAA;IACb,cAAA;IACA,sBAAA;;IAEW,WAAS,SAoHZ,EApHgB,OAAO,WAAI,CACjC,mBAmHM,OAnHN,WAmHM;cAlHA;KAAJ,KAAI;KACH,OAAO,MAAA,EAAA,CAAE,CAAC,UAAS;;QACG,MAAA,eAAA,CAAe,CAACA,KAAAA,QAAM,CAAA,WAAA,OAAA,CAAA;QAAuC,QAAA,WAAQ,CAAA,IAAQ;;KAIpG,WAAQ;KACP,gBAAc,MAAA,QAAA;KACd,cAAU,OAAA,QAAA,OAAA,OAAA,WAAE,UAAA,QAAS;KACrB,cAAU,OAAA,QAAA,OAAA,OAAA,WAAE,UAAA,QAAS;KACrB,SAAK,OAAA,QAAA,OAAA,OAAA,WAAE,cAAa;;KAGb,MAAA,UAAA,MAAe,MAAA,kBAAA,KAAsB,QAAQ,MAAA,QAAA,MAAA,UAAA,GADrD,mBAgBO,QAAA;;MAdL,WAAQ;MACP,OAAK,eAAA,CAAgB,MAAA,EAAA,CAAE,CAAC,MAAK,GAAA,EAAA,QAAA,CAA2B,MAAA,QAAA,KAAQ,CAAK,QAAQ,MAAA,UAAA,EAAU,CAAA,CAAA;yCAKrF,MAAA,UAAA,CAAU,IAAG,KAChB,CAAA,GACQ,QAAA,YAAA,UAAA,GADR,mBAMO,QAAA;;MAJL,WAAQ;MACP,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,SAAQ,CAAA;QACpB,OAED,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;KAGF,mBAMO,QAAA,EANA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,YAAW,CAAA,EAAA,GAAA,CAC1B,YAIE,iBAAA;MAHA,OAAM;MACL,MAAM,QAAA,QAAK,KAAA;MACZ,MAAK;;KAIT,mBA0BM,OAAA,EA1BA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAK,CAAA,EAAA,GAAA,CACnB,mBAwBE,SAAA;eAvBI;MAAJ,KAAI;MACH,UAAU,QAAA;MACV,OAAO,MAAA,gBAAA;MACR,OAAM;MACN,MAAK;MACL,WAAU;MACV,YAAW;MACX,cAAa;MACb,aAAY;MACZ,gBAAe;MACd,aAAa,MAAA,UAAA;MACb,UAAU,QAAA;MACV,gBAAc,MAAA,QAAA;MACd,cAAY,MAAA,UAAA;MACZ,iBAAe,QAAA,YAAY,KAAA;MAC3B,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,eAAA,CAAe,CAAC,MAAM;MACjC,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,WAAA,CAAW,CAAA;MAClB,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,UAAA,CAAU,CAAA;MAChB,UAAM,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,oBAAA,CAAoB,CAAC,MAAM;MACnC,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,iBAAiB,MAAM,GAAA,CAAA,MAAA,CAAA;MACnC,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,UAAU,MAAM;MACzB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,WAAA,CAAW,CAAC,MAAM;MACzB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,WAAA,CAAW,CAAC,MAAM;;KAKtB,QAAA,cAAc,MAAA,QAAA,KAAQ,CAAK,QAAA,YAAA,UAAA,GADnC,YAmBY,mBAAA;;MAjBV,SAAQ;MACR,MAAA;MACA,WAAQ;MACR,MAAK;MACL,OAAM;MACL,cAAY,MAAA,UAAA;MACZ,OAAK,eAAA;OAAgB,MAAA,EAAA,CAAE,CAAC,MAAK;OAAgB,MAAA,UAAA,KAAU;kBAAuC,QAAA,MAAK;;MAKnG,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAe,MAAK,GAAA,CAAA,QAAA,SAAA,CAAA;;6BAKxB,CAHF,YAGE,iBAAA;OAFA,MAAK;OACL,MAAK;;;;MAKA,QAAA,YAAQ,CAAK,QAAA,YAAA,UAAA,GADtB,mBAeS,UAAA;;MAbP,MAAK;MACJ,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,YAAW,CAAA;MACtB,WAAQ;MACP,cAAY,MAAA,WAAA;MACZ,iBAAe,MAAA,MAAA;MAChB,iBAAc;MACb,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,aAAa,MAAM;SAE3B,YAIE,iBAAA;MAHC,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,KAAI,CAAA;MACd,MAAM,QAAA,QAAK,KAAA;MACZ,MAAK;uEAGT,mBAUO,QAAA;;MARJ,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,YAAW,CAAA;MACtB,WAAQ;SAER,YAIE,iBAAA;MAHC,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,KAAI,CAAA;MACd,MAAM,QAAA,QAAK,KAAA;MACZ,MAAK;;wBAKH,MAAA,UAAA,KAAA,UAAA,GADR,mBAOW,YAAA;;KALR,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,SAAQ,CAAA;QAEnB,mBAES,UAAA,EAFA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,OAAM,CAAA,EAAA,GAAA,gBACpB,MAAA,UAAA,CAAU,GAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA;IAIR,SAAO,cAuBQ,CAtBxB,YAsBwB,+BAAA;cArBlB;KAAJ,KAAI;KACI,iBAAe,MAAA,YAAA;yGAAY,QAAA,SAAA;KAC3B,iBAAe,MAAA,YAAA;yGAAY,QAAA,SAAA;KAC3B,iBAAe,MAAA,YAAA;yGAAY,QAAA,SAAA;KAC3B,mBAAiB,MAAA,cAAA;+GAAc,QAAA,SAAA;KAC/B,mBAAiB,MAAA,cAAA;+GAAc,QAAA,SAAA;KAC/B,wBAAsB,MAAA,mBAAA;8HAAmB,QAAA,SAAA;KACzC,kBAAgB,MAAA,aAAA;4GAAa,QAAA,SAAA;KAC7B,qBAAmB,MAAA,gBAAA;qHAAgB,QAAA,SAAA;KACnC,sBAAoB,MAAA,gBAAA;qHAAgB,QAAA,SAAA;KAC3C,UAAU,QAAA;KACV,YAAU,MAAA,cAAA;KACV,YAAU,MAAA,cAAA;KACV,iBAAe,QAAA;KACf,SAAS,MAAA,WAAA;KACT,WAAO,OAAA,QAAA,OAAA,MAAA,UAAA,WAAS,cAAa,GAAA,CAAA,QAAA,CAAA;KAC7B,UAAO,OAAA,QAAA,OAAA,OAAA,WAAE,MAAA,MAAA,CAAM,CAAA;KACf,YAAS,OAAA,QAAA,OAAA,OAAA,WAAE,MAAA,QAAA,CAAQ,CAAA;KACnB,SAAK,OAAA,QAAA,OAAA,OAAA,WAAE,MAAK;;4BAEe,CAA5B,WAA4B,KAAA,QAAA,cAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePickerMenu.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePickerMenu.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { TimeAccuracy } from '@/consts/time-accuracy';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiCalendar from '@/components/calendar/RuiCalendar.vue';\nimport RuiTimezoneSelect from '@/components/date-time-picker/RuiTimezoneSelect.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiTimePicker, { type TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\n\ndefineOptions({\n name: 'RuiDateTimePickerMenu',\n});\n\nconst selectedDate = defineModel<Date | undefined>('selectedDate', { required: true });\nconst selectedTime = defineModel<Date | undefined>('selectedTime', { required: true });\nconst selectedHour = defineModel<number | undefined>('selectedHour', { required: true });\nconst selectedMinute = defineModel<number | undefined>('selectedMinute', { required: true });\nconst selectedSecond = defineModel<number | undefined>('selectedSecond', { required: true });\nconst selectedMillisecond = defineModel<number | undefined>('selectedMillisecond', { required: true });\nconst timeSelection = defineModel<TimePickerSelection>('timeSelection', { required: true });\nconst selectedTimezone = defineModel<string | undefined>('selectedTimezone', { required: true });\nconst calendarMenuOpen = defineModel<boolean>('calendarMenuOpen', { required: true });\n\ndefineProps<{\n accuracy: TimeAccuracy;\n maxDate?: Date | number;\n minDate?: Date | number;\n}>();\n\nconst emit = defineEmits<{\n 'set-now': [];\n}>();\n\ndefineSlots<{\n default: () => any;\n}>();\n\nfunction setNow(): void {\n emit('set-now');\n}\n</script>\n\n<template>\n <div class=\"flex divide-x divide-rui-grey-200 dark:divide-rui-grey-800\">\n <RuiCalendar\n v-model=\"selectedDate\"\n v-model:menu-open=\"calendarMenuOpen\"\n borderless\n :max-date=\"maxDate\"\n :min-date=\"minDate\"\n />\n <RuiTimePicker\n v-model=\"selectedTime\"\n v-model:hour=\"selectedHour\"\n v-model:minute=\"selectedMinute\"\n v-model:second=\"selectedSecond\"\n v-model:millisecond=\"selectedMillisecond\"\n v-model:selection=\"timeSelection\"\n :accuracy=\"accuracy\"\n borderless\n />\n <div>\n <div class=\"flex gap-3 p-4 pl-3\">\n <div class=\"flex flex-col justify-center items-center\">\n <RuiButton\n variant=\"text\"\n icon\n data-id=\"set-now\"\n @click=\"setNow()\"\n >\n <RuiIcon\n name=\"lu-clock\"\n size=\"18\"\n />\n </RuiButton>\n </div>\n <RuiTimezoneSelect\n v-model=\"selectedTimezone\"\n hide-details\n class=\"pt-0 pr-0\"\n />\n </div>\n <slot />\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiDateTimePickerMenu.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePickerMenu.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimePickerAction } from '@/components/date-time-picker/types';\nimport type { TimeAccuracy } from '@/consts/time-accuracy';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiCalendar from '@/components/calendar/RuiCalendar.vue';\nimport RuiTimezoneSelect from '@/components/date-time-picker/RuiTimezoneSelect.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiTimePicker, { type TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\ndefineOptions({\n name: 'RuiDateTimePickerMenu',\n});\n\nconst selectedDate = defineModel<Date | undefined>('selectedDate', { required: true });\nconst selectedTime = defineModel<Date | undefined>('selectedTime', { required: true });\nconst selectedHour = defineModel<number | undefined>('selectedHour', { required: true });\nconst selectedMinute = defineModel<number | undefined>('selectedMinute', { required: true });\nconst selectedSecond = defineModel<number | undefined>('selectedSecond', { required: true });\nconst selectedMillisecond = defineModel<number | undefined>('selectedMillisecond', { required: true });\nconst timeSelection = defineModel<TimePickerSelection>('timeSelection', { required: true });\nconst selectedTimezone = defineModel<string | undefined>('selectedTimezone', { required: true });\nconst calendarMenuOpen = defineModel<boolean>('calendarMenuOpen', { required: true });\n\nconst { actions = [] } = defineProps<{\n accuracy: TimeAccuracy;\n actions?: DateTimePickerAction[];\n maxDate?: Date | number;\n minDate?: Date | number;\n showTimezone?: boolean;\n}>();\n\nconst emit = defineEmits<{\n 'set-now': [];\n 'set-today': [];\n 'clear': [];\n}>();\n\ndefineSlots<{\n default: () => any;\n}>();\n\nconst { t } = useRuiI8n();\n\nconst keys = RUI_I18N_KEYS.dateTimePicker;\n\ninterface ActionConfig {\n id: DateTimePickerAction;\n icon: 'lu-clock' | 'lu-calendar-days' | 'lu-x';\n label: string;\n handler: () => void;\n}\n\nconst actionConfig = computed<ActionConfig[]>(() => {\n const available: Record<DateTimePickerAction, ActionConfig> = {\n clear: {\n handler: () => emit('clear'),\n icon: 'lu-x',\n id: 'clear',\n label: t(keys.clear, 'Clear'),\n },\n now: {\n handler: () => emit('set-now'),\n icon: 'lu-clock',\n id: 'now',\n label: t(keys.now, 'Now'),\n },\n today: {\n handler: () => emit('set-today'),\n icon: 'lu-calendar-days',\n id: 'today',\n label: t(keys.today, 'Today'),\n },\n };\n\n return actions.map(action => available[action]).filter(Boolean);\n});\n</script>\n\n<template>\n <div class=\"flex flex-col\">\n <div class=\"flex divide-x divide-rui-grey-200 dark:divide-rui-grey-800\">\n <RuiCalendar\n v-model=\"selectedDate\"\n v-model:menu-open=\"calendarMenuOpen\"\n borderless\n :max-date=\"maxDate\"\n :min-date=\"minDate\"\n />\n <RuiTimePicker\n v-model=\"selectedTime\"\n v-model:hour=\"selectedHour\"\n v-model:minute=\"selectedMinute\"\n v-model:second=\"selectedSecond\"\n v-model:millisecond=\"selectedMillisecond\"\n v-model:selection=\"timeSelection\"\n :accuracy=\"accuracy\"\n borderless\n />\n <div v-if=\"showTimezone || $slots.default\">\n <div\n v-if=\"showTimezone\"\n class=\"p-4 pl-3\"\n >\n <RuiTimezoneSelect\n v-model=\"selectedTimezone\"\n data-id=\"timezone-select\"\n hide-details\n class=\"pt-0 pr-0\"\n />\n </div>\n <slot />\n </div>\n </div>\n <div\n v-if=\"actionConfig.length > 0\"\n data-id=\"actions\"\n class=\"flex justify-end gap-1 px-3 py-2 border-t border-rui-grey-200 dark:border-rui-grey-800\"\n >\n <RuiButton\n v-for=\"action in actionConfig\"\n :key=\"action.id\"\n variant=\"text\"\n size=\"sm\"\n color=\"primary\"\n :data-id=\"`action-${action.id}`\"\n @click=\"action.handler()\"\n >\n <template #prepend>\n <RuiIcon\n :name=\"action.icon\"\n size=\"16\"\n />\n </template>\n {{ action.label }}\n </RuiButton>\n </div>\n </div>\n</template>\n"],"mappings":""}