@rotki/ui-library 3.0.0 → 3.1.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 (155) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
  2. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +13 -2
  3. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/components/alerts/RuiAlert.vue.d.ts +2 -2
  5. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  6. package/dist/components/buttons/button/RuiButton.vue.d.ts +7 -1
  7. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +4 -2
  8. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/buttons/button/button-props.d.ts +3 -0
  10. package/dist/components/buttons/button/button-props.js +2 -1
  11. package/dist/components/buttons/button/button-props.js.map +1 -1
  12. package/dist/components/buttons/button/button-styles.d.ts +75 -0
  13. package/dist/components/buttons/button/button-styles.js +135 -4
  14. package/dist/components/buttons/button/button-styles.js.map +1 -1
  15. package/dist/components/cards/RuiCard.js.map +1 -1
  16. package/dist/components/cards/RuiCard.vue.d.ts +6 -0
  17. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js +14 -2
  18. package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/chips/RuiChip.js.map +1 -1
  20. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +14 -0
  21. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/chips/chip-props.d.ts +2 -0
  23. package/dist/components/chips/chip-props.js +3 -0
  24. package/dist/components/chips/chip-props.js.map +1 -1
  25. package/dist/components/color-picker/RuiColorInput.js.map +1 -1
  26. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +2 -2
  27. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
  29. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +4 -0
  30. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +6 -2
  31. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
  33. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  34. package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/date-time-picker/RuiTimezoneSelect.js.map +1 -1
  36. package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +4 -0
  37. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +3 -2
  38. package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
  40. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +6 -2
  41. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/forms/auto-complete/auto-complete-props.d.ts +4 -0
  43. package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
  44. package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +4 -1
  45. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +7 -4
  46. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/components/forms/check-control-styles.d.ts +27 -0
  48. package/dist/components/forms/check-control-styles.js +26 -1
  49. package/dist/components/forms/check-control-styles.js.map +1 -1
  50. package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
  51. package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +6 -0
  52. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +14 -4
  53. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.js.map +1 -1
  55. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue.d.ts +4 -0
  56. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +7 -2
  57. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/forms/field-defaults/RuiFieldDefaults.js.map +1 -1
  59. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue.d.ts +3 -0
  60. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js +8 -2
  61. package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -1
  62. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  63. package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +4 -1
  64. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +10 -3
  65. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/forms/radio-button/radio/RuiRadio.js.map +1 -1
  67. package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +6 -0
  68. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +14 -3
  69. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
  71. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +4 -0
  72. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +7 -2
  73. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.js.map +1 -1
  75. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js +3 -2
  76. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
  78. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +4 -0
  79. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +6 -2
  80. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  81. package/dist/components/forms/slider/RuiSlider.js.map +1 -1
  82. package/dist/components/forms/slider/RuiSlider.vue.d.ts +4 -0
  83. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +6 -3
  84. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
  86. package/dist/components/forms/switch/RuiSwitch.vue.d.ts +6 -0
  87. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +25 -5
  88. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  89. package/dist/components/forms/text-area/RuiTextArea.js.map +1 -1
  90. package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +4 -0
  91. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +6 -4
  92. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/forms/text-area/text-area-styles.d.ts +0 -1
  94. package/dist/components/forms/text-area/text-area-styles.js +0 -1
  95. package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
  96. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  97. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +6 -2
  98. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +6 -4
  99. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  100. package/dist/components/forms/text-field/text-field-styles.d.ts +0 -1
  101. package/dist/components/forms/text-field/text-field-styles.js +0 -1
  102. package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
  103. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  104. package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +14 -0
  105. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +41 -11
  106. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  107. package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
  108. package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
  110. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +3 -0
  111. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +9 -1
  112. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  113. package/dist/components/tables/RuiDataTable.js.map +1 -1
  114. package/dist/components/tables/RuiDataTable.vue.d.ts +4 -0
  115. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +7 -1
  116. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/tables/RuiExpandButton.js.map +1 -1
  118. package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/tables/RuiTableHead.js.map +1 -1
  120. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
  121. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/tables/RuiTablePagination.js.map +1 -1
  123. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +3 -3
  124. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  125. package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -1
  126. package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
  128. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +2 -2
  129. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/tables/data-table-styles.d.ts +6 -0
  131. package/dist/components/tables/data-table-styles.js +11 -3
  132. package/dist/components/tables/data-table-styles.js.map +1 -1
  133. package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
  134. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +9 -2
  135. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/composables/clip-while-resizing.d.ts +15 -0
  137. package/dist/composables/clip-while-resizing.js +46 -0
  138. package/dist/composables/clip-while-resizing.js.map +1 -0
  139. package/dist/composables/defaults/field.d.ts +19 -3
  140. package/dist/composables/defaults/field.js +32 -6
  141. package/dist/composables/defaults/field.js.map +1 -1
  142. package/dist/composables/sticky-blocker.d.ts +20 -0
  143. package/dist/composables/sticky-blocker.js +62 -0
  144. package/dist/composables/sticky-blocker.js.map +1 -0
  145. package/dist/index.d.ts +6 -2
  146. package/dist/index.js.map +1 -1
  147. package/dist/style.css +275 -0
  148. package/dist/utils/development.d.ts +6 -0
  149. package/dist/utils/development.js +17 -0
  150. package/dist/utils/development.js.map +1 -0
  151. package/dist/utils/form-text-detail.d.ts +15 -0
  152. package/dist/utils/form-text-detail.js +11 -1
  153. package/dist/utils/form-text-detail.js.map +1 -1
  154. package/dist/web-types.json +232 -3
  155. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.js","names":["_sfc_main"],"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 } 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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { activatorHandlers } from '@/components/overlays/menu/activator-handlers';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\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 * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\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 labelPlacement = undefined,\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 partialTime,\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 inputId = useId();\nconst placement = useLabelPlacement(() => labelPlacement);\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 commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\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 pasteRejected,\n selectFirstSegment,\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 timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\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 content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 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\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\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 ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\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 pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...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\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\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\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\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 *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\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 if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\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 :class-names=\"{ details: 'px-0', content: 'p-0' }\"\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 :menu-label=\"fieldLabel\"\n role=\"dialog\"\n full-width\n disable-auto-focus\n >\n <template #label>\n <RuiFieldLabel\n :for=\"inputId\"\n :text=\"fieldLabel\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : activatorHandlers(attrs)),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-neutral-500 dark:text-rui-neutral-400 transition\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n :id=\"inputId\"\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-hidden 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-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled && !readonly\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\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=\"16\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\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 : 20\"\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 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset :class=\"ui.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=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\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 <!-- only when given, or the panel draws an empty third column with its divider -->\n <template\n v-if=\"$slots['menu-content']\"\n #default\n >\n <slot name=\"menu-content\" />\n </template>\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiDateTimePicker.js","names":["_sfc_main"],"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 } 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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { activatorHandlers } from '@/components/overlays/menu/activator-handlers';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { type FormDetails, useFormDetails, 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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\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 * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\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 details = undefined,\n hideDetails = false,\n label,\n labelPlacement = undefined,\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 partialTime,\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 inputId = useId();\nconst placement = useLabelPlacement(() => labelPlacement);\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 commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\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 pasteRejected,\n selectFirstSegment,\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 timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\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 content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 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\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\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 ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\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 pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...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\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\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\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\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 *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\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 if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\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 :class-names=\"{ details: 'px-0', content: 'p-0' }\"\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=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode === 'auto' ? 'auto' : 'reserve'\"\n :persistent=\"calendarMenuOpen\"\n :menu-label=\"fieldLabel\"\n role=\"dialog\"\n full-width\n disable-auto-focus\n >\n <template #label>\n <RuiFieldLabel\n :for=\"inputId\"\n :text=\"fieldLabel\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : activatorHandlers(attrs)),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-neutral-500 dark:text-rui-neutral-400 transition\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n :id=\"inputId\"\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-hidden 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-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled && !readonly\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\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=\"16\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\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 : 20\"\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 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset :class=\"ui.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=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\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 <!-- only when given, or the panel draws an empty third column with its divider -->\n <template\n v-if=\"$slots['menu-content']\"\n #default\n >\n <slot name=\"menu-content\" />\n </template>\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -1,5 +1,6 @@
1
1
  import type { DateTimePickerAction } from './types.js';
2
2
  import { type LabelPlacement } from '../../composables/defaults/field.js';
3
+ import { type FormDetails } from '../../utils/form-text-detail.js';
3
4
  type DateFormat = 'year-first' | 'month-first' | 'day-first';
4
5
  type DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';
5
6
  type ModelValueType<T extends DateTimeModelType> = T extends 'date' ? Date | undefined : T extends 'epoch-ms' ? number | undefined : T extends 'epoch' ? number | undefined : Date | number | undefined;
@@ -19,6 +20,9 @@ export interface RuiDateTimePickerProps {
19
20
  hint?: string;
20
21
  errorMessages?: string | string[];
21
22
  successMessages?: string | string[];
23
+ /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */
24
+ details?: FormDetails;
25
+ /** @deprecated Use `details="hidden"`. Removed in 4.0. */
22
26
  hideDetails?: boolean;
23
27
  required?: boolean;
24
28
  /**
@@ -5,7 +5,7 @@ import { useRuiI8n } from "../../composables/use-rui-i18n.js";
5
5
  import { cn } from "../../utils/tv.js";
6
6
  import RuiIcon_default from "../icons/RuiIcon.js";
7
7
  import RuiButton_default from "../buttons/button/RuiButton.js";
8
- import { useFormTextDetail } from "../../utils/form-text-detail.js";
8
+ import { useFormDetails, useFormTextDetail } from "../../utils/form-text-detail.js";
9
9
  import { Placement } from "../../composables/floating.js";
10
10
  import RuiMenu_default from "../overlays/menu/RuiMenu.js";
11
11
  import RuiFieldLabel_default from "../forms/field-label/RuiFieldLabel.js";
@@ -66,6 +66,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
66
66
  hint: {},
67
67
  errorMessages: { default: () => [] },
68
68
  successMessages: { default: () => [] },
69
+ details: { default: () => void 0 },
69
70
  hideDetails: {
70
71
  type: Boolean,
71
72
  default: false
@@ -153,6 +154,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
153
154
  timezone: modelTimezone
154
155
  });
155
156
  const { hasError, hasSuccess } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
157
+ const detailsMode = useFormDetails(() => __props.details, () => __props.hideDetails);
156
158
  /** True once any segment holds a digit, even a partially typed date. */
157
159
  const anySegmentSet = computed(() => [
158
160
  modelYear,
@@ -391,7 +393,8 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
391
393
  "success-messages": __props.successMessages,
392
394
  "error-messages": unref(combinedErrorMessages),
393
395
  "close-on-content-click": false,
394
- "show-details": !__props.hideDetails,
396
+ "show-details": unref(detailsMode) !== "hidden",
397
+ details: unref(detailsMode) === "auto" ? "auto" : "reserve",
395
398
  persistent: unref(calendarMenuOpen),
396
399
  "menu-label": unref(fieldLabel),
397
400
  role: "dialog",
@@ -560,6 +563,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
560
563
  "success-messages",
561
564
  "error-messages",
562
565
  "show-details",
566
+ "details",
563
567
  "persistent",
564
568
  "menu-label"
565
569
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots","_useModel","_openBlock","_createBlock","RuiMenu","_mergeProps","_unref","_isRef","_withCtx","_createVNode","RuiFieldLabel","_createElementVNode","_normalizeClass","RuiIcon","_withModifiers","_toDisplayString","RuiButton","_createCommentVNode","_createElementBlock","RuiDateTimePickerMenu","_withKeys","_createSlots","_renderSlot"],"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 } 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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { activatorHandlers } from '@/components/overlays/menu/activator-handlers';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\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 * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\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 labelPlacement = undefined,\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 partialTime,\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 inputId = useId();\nconst placement = useLabelPlacement(() => labelPlacement);\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 commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\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 pasteRejected,\n selectFirstSegment,\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 timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\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 content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 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\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\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 ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\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 pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...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\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\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\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\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 *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\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 if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\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 :class-names=\"{ details: 'px-0', content: 'p-0' }\"\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 :menu-label=\"fieldLabel\"\n role=\"dialog\"\n full-width\n disable-auto-focus\n >\n <template #label>\n <RuiFieldLabel\n :for=\"inputId\"\n :text=\"fieldLabel\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : activatorHandlers(attrs)),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-neutral-500 dark:text-rui-neutral-400 transition\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n :id=\"inputId\"\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-hidden 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-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled && !readonly\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\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=\"16\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\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 : 20\"\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 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset :class=\"ui.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=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\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 <!-- only when given, or the panel draws an empty third column with its divider -->\n <template\n v-if=\"$slots['menu-content']\"\n #default\n >\n <slot name=\"menu-content\" />\n </template>\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","$slots","_useModel","_openBlock","_createBlock","RuiMenu","_mergeProps","_unref","_isRef","_withCtx","_createVNode","RuiFieldLabel","_createElementVNode","_normalizeClass","RuiIcon","_withModifiers","_toDisplayString","RuiButton","_createCommentVNode","_createElementBlock","RuiDateTimePickerMenu","_withKeys","_createSlots","_renderSlot"],"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 } 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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { activatorHandlers } from '@/components/overlays/menu/activator-handlers';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { type LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\nimport { type FormDetails, useFormDetails, 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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\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 * Accepts an entry that stops short of the full format, filling the segments\n * it never reached from one end of the day: `start` gives a bare date\n * 00:00:00.000 and `end` gives it 23:59:59.999. Meant for a range, where the\n * two bounds want opposite ends. Left unset, an entry missing its time is not\n * a value and nothing is emitted.\n *\n * The fill runs when the user is done with the field - leaving it, pressing\n * enter, or closing the calendar - and is written back into the segments, so\n * what it decided on is on screen.\n *\n * Spelled out rather than written as `PartialTimeMode`: a consumer that hands\n * this whole interface to its own `defineProps` needs every member resolvable\n * by the SFC compiler, which does not follow the type into the package.\n */\n partialTime?: 'start' | 'end';\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 details = undefined,\n hideDetails = false,\n label,\n labelPlacement = undefined,\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 partialTime,\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 inputId = useId();\nconst placement = useLabelPlacement(() => labelPlacement);\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 commitPartialTime,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n modelDay,\n modelHour,\n modelMillisecond,\n modelMinute,\n modelMonth,\n modelSecond,\n selectedTime,\n modelTimezone,\n modelYear,\n setNow,\n setToday,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n dateFormat,\n maxDate,\n minDate,\n modelValue,\n partialTime,\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 pasteRejected,\n selectFirstSegment,\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 timezone: modelTimezone,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\nconst detailsMode = useFormDetails(() => details, () => hideDetails);\n\n/** True once any segment holds a digit, even a partially typed date. */\nconst anySegmentSet = computed<boolean>(() => [\n modelYear,\n modelMonth,\n modelDay,\n modelHour,\n modelMinute,\n modelSecond,\n modelMillisecond,\n].some(segment => isDefined(segment)));\n\n/**\n * The field's text.\n *\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 content\n * and select-all copies them. The tokens stay while the field is focused: that\n * is when the segment machinery highlights them, and collapsing the value\n * mid-edit would blank the field under the cursor. The guard is \"no segment\n * set\" rather than `valueSet`, so blurring a half-typed date keeps what was\n * entered on screen.\n */\nconst formattedDisplay = computed<string>(() => {\n if (!get(anySegmentSet) && !get(searchInputFocused)) {\n return '';\n }\n\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(modelYear, 4) },\n { pattern: 'MM', value: getDisplayValue(modelMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(modelDay, 2) },\n { pattern: 'HH', value: getDisplayValue(modelHour, 2) },\n { pattern: 'mm', value: getDisplayValue(modelMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(modelSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(modelMillisecond, 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\n/**\n * An untouched field holds no value until focus expands the format tokens into\n * it. That patch overwrites the input's value, and writing a value drops any\n * selection with it, so the highlight `handleFocus` just set is gone by the\n * time the tokens are on screen and the caret ends up after them. Re-select\n * the first segment once the tokens have actually landed.\n */\nwatch(formattedDisplay, (value, previous) => {\n if (previous === '' && value !== '' && get(searchInputFocused))\n selectFirstSegment();\n}, { flush: 'post' });\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 ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\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 pasteMessage = computed<string>(() => (get(pasteRejected)\n ? t(keys.pasteUnreadable, 'Could not read a date from the pasted text')\n : ''));\n\n/**\n * The paste message goes first: the details show one message, and it answers\n * what the user just did, which a standing validation error does not.\n */\nconst combinedErrorMessages = computed<string[]>(() => {\n const paste = get(pasteMessage) ? [get(pasteMessage)] : [];\n if (!errorMessages)\n return [...paste, ...get(internalErrorMessages)];\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...paste, ...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\n/**\n * An entry left incomplete is completed once the user is done with the field,\n * never while they are still filling it in: a half typed hour is not a segment\n * they left out. Leaving the field counts, unless the calendar is open, since\n * then the focus is only moving into it and the menu closing covers that.\n */\nfunction onBlur(): void {\n handleBlur();\n if (!get(isOpen))\n commitPartialTime();\n}\n\nwatch(isOpen, (open) => {\n if (!open && !get(searchInputFocused))\n commitPartialTime();\n});\n\n/**\n * Selects the clicked segment before opening the menu, so the selection is not\n * lost to the DOM changes that opening brings.\n */\nfunction handleInputClick(event: MouseEvent): void {\n handleClick(event);\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\n/**\n * Asks for focus to move into the calendar. The menu is teleported and mounts\n * a frame later, so the watcher below waits for the wrapper to appear rather\n * than guessing at a number of ticks.\n */\nfunction focusCalendar(): void {\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 *\n * Enter and Escape are the other ways to be done with the field, and the keys\n * a consumer tends to close its editor on. Escape reaches that point only once\n * the calendar is already shut, and discards nothing, since the segments stay\n * on screen either way, so it commits what was entered rather than dropping it\n * when the field goes. Both write the value before the key carries on\n * bubbling, so it survives that close.\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 if (event.key === 'Enter' || event.key === 'Escape')\n commitPartialTime();\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 :class-names=\"{ details: 'px-0', content: 'p-0' }\"\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=\"detailsMode !== 'hidden'\"\n :details=\"detailsMode === 'auto' ? 'auto' : 'reserve'\"\n :persistent=\"calendarMenuOpen\"\n :menu-label=\"fieldLabel\"\n role=\"dialog\"\n full-width\n disable-auto-focus\n >\n <template #label>\n <RuiFieldLabel\n :for=\"inputId\"\n :text=\"fieldLabel\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : activatorHandlers(attrs)),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-neutral-500 dark:text-rui-neutral-400 transition\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n :id=\"inputId\"\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-hidden 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-required=\"required || undefined\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"onBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"onKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n <!-- The details line is not a live region, so a rejected paste is announced from here -->\n <span\n class=\"sr-only\"\n aria-live=\"polite\"\n data-id=\"paste-status\"\n >\n {{ pasteMessage }}\n </span>\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled && !readonly\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\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=\"16\"\n />\n </RuiButton>\n\n <!-- Out of the tab sequence, following the combobox pattern: the button only duplicates\n Alt+ArrowDown on the field, so leaving it in cost two stops to cross one date field\n and four to cross a from/to pair, for nothing a keyboard user could not already do.\n It stays a real button, so it keeps its label and its expanded state for anyone\n reaching it by any other means. -->\n <button\n v-if=\"!disabled && !readonly\"\n type=\"button\"\n tabindex=\"-1\"\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 : 20\"\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 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset :class=\"ui.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=\"modelHour\"\n v-model:selected-minute=\"modelMinute\"\n v-model:selected-second=\"modelSecond\"\n v-model:selected-millisecond=\"modelMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"modelTimezone\"\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 <!-- only when given, or the panel draws an empty third column with its divider -->\n <template\n v-if=\"$slots['menu-content']\"\n #default\n >\n <slot name=\"menu-content\" />\n </template>\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePickerMenu.js","names":["_sfc_main"],"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 between:border-l between:border-r-0 between:border-rui-divider\">\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-divider\"\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":""}
1
+ {"version":3,"file":"RuiDateTimePickerMenu.js","names":["_sfc_main"],"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 between:border-l between:border-r-0 between:border-rui-divider\">\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 details=\"hidden\"\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-divider\"\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":""}
@@ -146,7 +146,7 @@ var RuiDateTimePickerMenu_vue_vue_type_script_setup_true_lang_default = /*@__PUR
146
146
  modelValue: selectedTimezone.value,
147
147
  "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => selectedTimezone.value = $event),
148
148
  "data-id": "timezone-select",
149
- "hide-details": "",
149
+ details: "hidden",
150
150
  class: "pt-0 pr-0"
151
151
  }, null, 8, ["modelValue"])])) : createCommentVNode("", true), renderSlot(_ctx.$slots, "default")])) : createCommentVNode("", true)
152
152
  ]), unref(actionConfig).length > 0 ? (openBlock(), createElementBlock("div", _hoisted_5, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(actionConfig), (action) => {
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","RuiCalendar","RuiTimePicker","RuiTimezoneSelect","_createCommentVNode","_renderSlot","_unref","_Fragment","_renderList","_createBlock","RuiButton","_withCtx","RuiIcon","_createTextVNode","_toDisplayString"],"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 between:border-l between:border-r-0 between:border-rui-divider\">\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-divider\"\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":"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"}
1
+ {"version":3,"file":"RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js","names":["$slots","_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","RuiCalendar","RuiTimePicker","RuiTimezoneSelect","_createCommentVNode","_renderSlot","_unref","_Fragment","_renderList","_createBlock","RuiButton","_withCtx","RuiIcon","_createTextVNode","_toDisplayString"],"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 between:border-l between:border-r-0 between:border-rui-divider\">\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 details=\"hidden\"\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-divider\"\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":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTimezoneSelect.js","names":["_sfc_main"],"sources":["../../../src/components/date-time-picker/RuiTimezoneSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RuiAutoCompleteClassNames } from '@/components/forms/auto-complete/auto-complete-props';\nimport type { MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport type { LabelPlacement } from '@/composables/defaults/field';\nimport { timezones } from '@/components/date-time-picker/timezones';\nimport RuiAutoComplete from '@/components/forms/auto-complete/RuiAutoComplete.vue';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\nexport interface RuiTimezoneSelectProps {\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n placeholder?: string;\n required?: boolean;\n classNames?: RuiAutoCompleteClassNames;\n menuOptions?: MenuProps;\n}\n\ndefineOptions({\n name: 'RuiTimezoneSelect',\n});\n\nconst modelValue = defineModel<string | undefined>({ required: true });\n\nconst {\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n label,\n labelPlacement = undefined,\n hint,\n errorMessages,\n successMessages,\n hideDetails = false,\n placeholder,\n required = false,\n classNames,\n menuOptions,\n} = defineProps<RuiTimezoneSelectProps>();\n\nconst { t } = useRuiI8n();\n\nconst fieldLabel = computed<string>(() => label ?? t(RUI_I18N_KEYS.timezoneSelect.label, 'Timezone'));\n\ninterface TimezoneOption {\n value: string;\n label: string;\n}\n\nconst options: TimezoneOption[] = timezones.map(value => ({\n value,\n label: value.replace(/_/g, ' '),\n}));\n</script>\n\n<template>\n <RuiAutoComplete\n v-model=\"modelValue\"\n key-attr=\"value\"\n text-attr=\"label\"\n auto-select-first\n :options=\"options\"\n :label=\"fieldLabel\"\n :label-placement=\"labelPlacement\"\n :disabled=\"disabled\"\n :read-only=\"readOnly\"\n :dense=\"dense\"\n :clearable=\"clearable\"\n :hint=\"hint\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hide-details=\"hideDetails\"\n :placeholder=\"placeholder\"\n :required=\"required\"\n :class-names=\"classNames\"\n :menu-options=\"menuOptions\"\n />\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiTimezoneSelect.js","names":["_sfc_main"],"sources":["../../../src/components/date-time-picker/RuiTimezoneSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RuiAutoCompleteClassNames } from '@/components/forms/auto-complete/auto-complete-props';\nimport type { MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport type { LabelPlacement } from '@/composables/defaults/field';\nimport type { FormDetails } from '@/utils/form-text-detail';\nimport { timezones } from '@/components/date-time-picker/timezones';\nimport RuiAutoComplete from '@/components/forms/auto-complete/RuiAutoComplete.vue';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\nexport interface RuiTimezoneSelectProps {\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n placeholder?: string;\n required?: boolean;\n classNames?: RuiAutoCompleteClassNames;\n menuOptions?: MenuProps;\n}\n\ndefineOptions({\n name: 'RuiTimezoneSelect',\n});\n\nconst modelValue = defineModel<string | undefined>({ required: true });\n\nconst {\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n label,\n labelPlacement = undefined,\n hint,\n errorMessages,\n successMessages,\n details = undefined,\n hideDetails = false,\n placeholder,\n required = false,\n classNames,\n menuOptions,\n} = defineProps<RuiTimezoneSelectProps>();\n\nconst { t } = useRuiI8n();\n\nconst fieldLabel = computed<string>(() => label ?? t(RUI_I18N_KEYS.timezoneSelect.label, 'Timezone'));\n\ninterface TimezoneOption {\n value: string;\n label: string;\n}\n\nconst options: TimezoneOption[] = timezones.map(value => ({\n value,\n label: value.replace(/_/g, ' '),\n}));\n</script>\n\n<template>\n <RuiAutoComplete\n v-model=\"modelValue\"\n key-attr=\"value\"\n text-attr=\"label\"\n auto-select-first\n :options=\"options\"\n :label=\"fieldLabel\"\n :label-placement=\"labelPlacement\"\n :disabled=\"disabled\"\n :read-only=\"readOnly\"\n :dense=\"dense\"\n :clearable=\"clearable\"\n :hint=\"hint\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :details=\"hideDetails ? 'hidden' : details\"\n :placeholder=\"placeholder\"\n :required=\"required\"\n :class-names=\"classNames\"\n :menu-options=\"menuOptions\"\n />\n</template>\n"],"mappings":""}
@@ -1,6 +1,7 @@
1
1
  import type { RuiAutoCompleteClassNames } from '../forms/auto-complete/auto-complete-props.js';
2
2
  import type { MenuProps } from '../overlays/menu/RuiMenu.vue.js';
3
3
  import type { LabelPlacement } from '../../composables/defaults/field.js';
4
+ import type { FormDetails } from '../../utils/form-text-detail.js';
4
5
  export interface RuiTimezoneSelectProps {
5
6
  disabled?: boolean;
6
7
  readOnly?: boolean;
@@ -12,6 +13,9 @@ export interface RuiTimezoneSelectProps {
12
13
  hint?: string;
13
14
  errorMessages?: string | string[];
14
15
  successMessages?: string | string[];
16
+ /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */
17
+ details?: FormDetails;
18
+ /** @deprecated Use `details="hidden"`. Removed in 4.0. */
15
19
  hideDetails?: boolean;
16
20
  placeholder?: string;
17
21
  required?: boolean;
@@ -29,6 +29,7 @@ var RuiTimezoneSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
29
29
  hint: {},
30
30
  errorMessages: {},
31
31
  successMessages: {},
32
+ details: { default: () => void 0 },
32
33
  hideDetails: {
33
34
  type: Boolean,
34
35
  default: false
@@ -70,7 +71,7 @@ var RuiTimezoneSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
70
71
  hint: __props.hint,
71
72
  "error-messages": __props.errorMessages,
72
73
  "success-messages": __props.successMessages,
73
- "hide-details": __props.hideDetails,
74
+ details: __props.hideDetails ? "hidden" : __props.details,
74
75
  placeholder: __props.placeholder,
75
76
  required: __props.required,
76
77
  "class-names": __props.classNames,
@@ -87,7 +88,7 @@ var RuiTimezoneSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*
87
88
  "hint",
88
89
  "error-messages",
89
90
  "success-messages",
90
- "hide-details",
91
+ "details",
91
92
  "placeholder",
92
93
  "required",
93
94
  "class-names",
@@ -1 +1 @@
1
- {"version":3,"file":"RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","RuiAutoComplete","_unref"],"sources":["../../../src/components/date-time-picker/RuiTimezoneSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RuiAutoCompleteClassNames } from '@/components/forms/auto-complete/auto-complete-props';\nimport type { MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport type { LabelPlacement } from '@/composables/defaults/field';\nimport { timezones } from '@/components/date-time-picker/timezones';\nimport RuiAutoComplete from '@/components/forms/auto-complete/RuiAutoComplete.vue';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\nexport interface RuiTimezoneSelectProps {\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n placeholder?: string;\n required?: boolean;\n classNames?: RuiAutoCompleteClassNames;\n menuOptions?: MenuProps;\n}\n\ndefineOptions({\n name: 'RuiTimezoneSelect',\n});\n\nconst modelValue = defineModel<string | undefined>({ required: true });\n\nconst {\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n label,\n labelPlacement = undefined,\n hint,\n errorMessages,\n successMessages,\n hideDetails = false,\n placeholder,\n required = false,\n classNames,\n menuOptions,\n} = defineProps<RuiTimezoneSelectProps>();\n\nconst { t } = useRuiI8n();\n\nconst fieldLabel = computed<string>(() => label ?? t(RUI_I18N_KEYS.timezoneSelect.label, 'Timezone'));\n\ninterface TimezoneOption {\n value: string;\n label: string;\n}\n\nconst options: TimezoneOption[] = timezones.map(value => ({\n value,\n label: value.replace(/_/g, ' '),\n}));\n</script>\n\n<template>\n <RuiAutoComplete\n v-model=\"modelValue\"\n key-attr=\"value\"\n text-attr=\"label\"\n auto-select-first\n :options=\"options\"\n :label=\"fieldLabel\"\n :label-placement=\"labelPlacement\"\n :disabled=\"disabled\"\n :read-only=\"readOnly\"\n :dense=\"dense\"\n :clearable=\"clearable\"\n :hint=\"hint\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hide-details=\"hideDetails\"\n :placeholder=\"placeholder\"\n :required=\"required\"\n :class-names=\"classNames\"\n :menu-options=\"menuOptions\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BA,MAAM,aAAaA,SAA+B,SAAA,YAAmB;EAmBrE,MAAM,EAAE,MAAM,UAAU;EAExB,MAAM,aAAa,eAAuB,QAAA,SAAS,EAAE,cAAc,eAAe,OAAO,UAAU,CAAC;EAOpG,MAAM,UAA4B,UAAU,KAAI,WAAU;GACxD;GACA,OAAO,MAAM,QAAQ,MAAM,GAAG;EAChC,EAAE;;GAIA,OAAAC,UAAA,GAAAC,YAoBEC,yBAAA;IAnBS,YAAA,WAAA;IAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;IACnB,YAAS;IACT,aAAU;IACV,qBAAA;IACC,SAASC,MAAA,OAAA;IACT,OAAOA,MAAA,UAAA;IACP,mBAAiB,QAAA;IACjB,UAAU,QAAA;IACV,aAAW,QAAA;IACX,OAAO,QAAA;IACP,WAAW,QAAA;IACX,MAAM,QAAA;IACN,kBAAgB,QAAA;IAChB,oBAAkB,QAAA;IAClB,gBAAc,QAAA;IACd,aAAa,QAAA;IACb,UAAU,QAAA;IACV,eAAa,QAAA;IACb,gBAAc,QAAA"}
1
+ {"version":3,"file":"RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createBlock","RuiAutoComplete","_unref"],"sources":["../../../src/components/date-time-picker/RuiTimezoneSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RuiAutoCompleteClassNames } from '@/components/forms/auto-complete/auto-complete-props';\nimport type { MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport type { LabelPlacement } from '@/composables/defaults/field';\nimport type { FormDetails } from '@/utils/form-text-detail';\nimport { timezones } from '@/components/date-time-picker/timezones';\nimport RuiAutoComplete from '@/components/forms/auto-complete/RuiAutoComplete.vue';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\nexport interface RuiTimezoneSelectProps {\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n /** The line under the field for its hint and messages: `reserve`, `auto` or `hidden`; falls back to the nearest `RuiFieldDefaults`, then the app default, then `reserve`. */\n details?: FormDetails;\n /** @deprecated Use `details=\"hidden\"`. Removed in 4.0. */\n hideDetails?: boolean;\n placeholder?: string;\n required?: boolean;\n classNames?: RuiAutoCompleteClassNames;\n menuOptions?: MenuProps;\n}\n\ndefineOptions({\n name: 'RuiTimezoneSelect',\n});\n\nconst modelValue = defineModel<string | undefined>({ required: true });\n\nconst {\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n label,\n labelPlacement = undefined,\n hint,\n errorMessages,\n successMessages,\n details = undefined,\n hideDetails = false,\n placeholder,\n required = false,\n classNames,\n menuOptions,\n} = defineProps<RuiTimezoneSelectProps>();\n\nconst { t } = useRuiI8n();\n\nconst fieldLabel = computed<string>(() => label ?? t(RUI_I18N_KEYS.timezoneSelect.label, 'Timezone'));\n\ninterface TimezoneOption {\n value: string;\n label: string;\n}\n\nconst options: TimezoneOption[] = timezones.map(value => ({\n value,\n label: value.replace(/_/g, ' '),\n}));\n</script>\n\n<template>\n <RuiAutoComplete\n v-model=\"modelValue\"\n key-attr=\"value\"\n text-attr=\"label\"\n auto-select-first\n :options=\"options\"\n :label=\"fieldLabel\"\n :label-placement=\"labelPlacement\"\n :disabled=\"disabled\"\n :read-only=\"readOnly\"\n :dense=\"dense\"\n :clearable=\"clearable\"\n :hint=\"hint\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :details=\"hideDetails ? 'hidden' : details\"\n :placeholder=\"placeholder\"\n :required=\"required\"\n :class-names=\"classNames\"\n :menu-options=\"menuOptions\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,MAAM,aAAaA,SAA+B,SAAA,YAAmB;EAoBrE,MAAM,EAAE,MAAM,UAAU;EAExB,MAAM,aAAa,eAAuB,QAAA,SAAS,EAAE,cAAc,eAAe,OAAO,UAAU,CAAC;EAOpG,MAAM,UAA4B,UAAU,KAAI,WAAU;GACxD;GACA,OAAO,MAAM,QAAQ,MAAM,GAAG;EAChC,EAAE;;GAIA,OAAAC,UAAA,GAAAC,YAoBEC,yBAAA;IAnBS,YAAA,WAAA;IAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;IACnB,YAAS;IACT,aAAU;IACV,qBAAA;IACC,SAASC,MAAA,OAAA;IACT,OAAOA,MAAA,UAAA;IACP,mBAAiB,QAAA;IACjB,UAAU,QAAA;IACV,aAAW,QAAA;IACX,OAAO,QAAA;IACP,WAAW,QAAA;IACX,MAAM,QAAA;IACN,kBAAgB,QAAA;IAChB,oBAAkB,QAAA;IAClB,SAAS,QAAA,cAAW,WAAc,QAAA;IAClC,aAAa,QAAA;IACb,UAAU,QAAA;IACV,eAAa,QAAA;IACb,gBAAc,QAAA"}