@rotki/ui-library 2.19.1 → 2.19.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst 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 cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiDateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -79,6 +79,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
79
79
  "year-first": "YYYY/MM/DD HH:mm"
80
80
  };
81
81
  const isOpen = ref(false);
82
+ const isHovered = ref(false);
82
83
  const cursorPosition = ref(0);
83
84
  const currentValue = ref();
84
85
  const textInput = useTemplateRef("textInput");
@@ -179,6 +180,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
179
180
  outlined: get$1(isOutlined),
180
181
  float: get$1(float),
181
182
  opened: get$1(isOpen),
183
+ hovered: get$1(isHovered),
182
184
  dense: __props.dense,
183
185
  disabled: __props.disabled,
184
186
  readonly: __props.readonly,
@@ -221,7 +223,7 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
221
223
  return (_ctx, _cache) => {
222
224
  return openBlock(), createBlock(RuiMenu_default, mergeProps({
223
225
  modelValue: unref(isOpen),
224
- "onUpdate:modelValue": _cache[21] || (_cache[21] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
226
+ "onUpdate:modelValue": _cache[23] || (_cache[23] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
225
227
  }, unref(getRootAttrs)(_ctx.$attrs, []), {
226
228
  class: unref(ui).wrapper({ class: unref(cn)(_ctx.$attrs.class) }),
227
229
  placement: "bottom-start",
@@ -247,7 +249,9 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
247
249
  "data-id": "activator",
248
250
  "aria-invalid": unref(hasError),
249
251
  tabindex: __props.disabled || __props.readonly ? -1 : 0,
250
- onClick: _cache[10] || (_cache[10] = ($event) => setInputFocus())
252
+ onMouseenter: _cache[10] || (_cache[10] = ($event) => isHovered.value = true),
253
+ onMouseleave: _cache[11] || (_cache[11] = ($event) => isHovered.value = false),
254
+ onClick: _cache[12] || (_cache[12] = ($event) => setInputFocus())
251
255
  }), [
252
256
  unref(isOutlined) && (unref(searchInputFocused) || open || unref(valueSet)) ? (openBlock(), createElementBlock("span", {
253
257
  key: 0,
@@ -320,27 +324,27 @@ var RuiDateTimePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__
320
324
  ref_key: "menuWrapperRef",
321
325
  ref: menuWrapperRef,
322
326
  "selected-date": unref(selectedDate),
323
- "onUpdate:selectedDate": _cache[11] || (_cache[11] = ($event) => isRef(selectedDate) ? selectedDate.value = $event : null),
327
+ "onUpdate:selectedDate": _cache[13] || (_cache[13] = ($event) => isRef(selectedDate) ? selectedDate.value = $event : null),
324
328
  "selected-time": unref(selectedTime),
325
- "onUpdate:selectedTime": _cache[12] || (_cache[12] = ($event) => isRef(selectedTime) ? selectedTime.value = $event : null),
329
+ "onUpdate:selectedTime": _cache[14] || (_cache[14] = ($event) => isRef(selectedTime) ? selectedTime.value = $event : null),
326
330
  "selected-hour": unref(selectedHour),
327
- "onUpdate:selectedHour": _cache[13] || (_cache[13] = ($event) => isRef(selectedHour) ? selectedHour.value = $event : null),
331
+ "onUpdate:selectedHour": _cache[15] || (_cache[15] = ($event) => isRef(selectedHour) ? selectedHour.value = $event : null),
328
332
  "selected-minute": unref(selectedMinute),
329
- "onUpdate:selectedMinute": _cache[14] || (_cache[14] = ($event) => isRef(selectedMinute) ? selectedMinute.value = $event : null),
333
+ "onUpdate:selectedMinute": _cache[16] || (_cache[16] = ($event) => isRef(selectedMinute) ? selectedMinute.value = $event : null),
330
334
  "selected-second": unref(selectedSecond),
331
- "onUpdate:selectedSecond": _cache[15] || (_cache[15] = ($event) => isRef(selectedSecond) ? selectedSecond.value = $event : null),
335
+ "onUpdate:selectedSecond": _cache[17] || (_cache[17] = ($event) => isRef(selectedSecond) ? selectedSecond.value = $event : null),
332
336
  "selected-millisecond": unref(selectedMillisecond),
333
- "onUpdate:selectedMillisecond": _cache[16] || (_cache[16] = ($event) => isRef(selectedMillisecond) ? selectedMillisecond.value = $event : null),
337
+ "onUpdate:selectedMillisecond": _cache[18] || (_cache[18] = ($event) => isRef(selectedMillisecond) ? selectedMillisecond.value = $event : null),
334
338
  "time-selection": unref(timeSelection),
335
- "onUpdate:timeSelection": _cache[17] || (_cache[17] = ($event) => isRef(timeSelection) ? timeSelection.value = $event : null),
339
+ "onUpdate:timeSelection": _cache[19] || (_cache[19] = ($event) => isRef(timeSelection) ? timeSelection.value = $event : null),
336
340
  "selected-timezone": unref(selectedTimezone),
337
- "onUpdate:selectedTimezone": _cache[18] || (_cache[18] = ($event) => isRef(selectedTimezone) ? selectedTimezone.value = $event : null),
341
+ "onUpdate:selectedTimezone": _cache[20] || (_cache[20] = ($event) => isRef(selectedTimezone) ? selectedTimezone.value = $event : null),
338
342
  "calendar-menu-open": unref(calendarMenuOpen),
339
- "onUpdate:calendarMenuOpen": _cache[19] || (_cache[19] = ($event) => isRef(calendarMenuOpen) ? calendarMenuOpen.value = $event : null),
343
+ "onUpdate:calendarMenuOpen": _cache[21] || (_cache[21] = ($event) => isRef(calendarMenuOpen) ? calendarMenuOpen.value = $event : null),
340
344
  accuracy: __props.accuracy,
341
345
  "max-date": unref(maxAllowedDate),
342
346
  "min-date": unref(minAllowedDate),
343
- onSetNow: _cache[20] || (_cache[20] = ($event) => unref(setNow)())
347
+ onSetNow: _cache[22] || (_cache[22] = ($event) => unref(setNow)())
344
348
  }, {
345
349
  default: withCtx(() => [renderSlot(_ctx.$slots, "menu-content")]),
346
350
  _: 3
@@ -1 +1 @@
1
- {"version":3,"file":"RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst 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 cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../src/components/date-time-picker/RuiDateTimePicker.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { DateTimeSegmentType } from '@/components/date-time-picker/types';\nimport type { TimePickerSelection } from '@/components/time-picker/RuiTimePicker.vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { dateTimePickerStyles, type DateTimePickerVariant } from '@/components/date-time-picker/date-time-picker-styles';\nimport RuiDateTimePickerMenu from '@/components/date-time-picker/RuiDateTimePickerMenu.vue';\nimport { useDateTimeSelection } from '@/components/date-time-picker/use-date-time-selection';\nimport { useInputHandler } from '@/components/date-time-picker/use-input-handler';\nimport { useKeyboardHandler } from '@/components/date-time-picker/use-keyboard-handler';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\ntype DateFormat = 'year-first' | 'month-first' | 'day-first';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> = T extends 'date'\n ? Date | undefined\n : T extends 'epoch-ms'\n ? number | undefined\n : T extends 'epoch'\n ? number | undefined\n : Date | number | undefined;\n\nexport interface RuiDateTimePickerProps {\n minDate?: Date | number;\n maxDate?: Date | number | 'now';\n format?: DateFormat;\n type?: DateTimeModelType;\n accuracy?: 'minute' | 'second' | 'millisecond';\n disabled?: boolean;\n allowEmpty?: boolean;\n readonly?: boolean;\n dense?: boolean;\n label?: string;\n variant?: DateTimePickerVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiDateTimePicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<ModelValueType<DateTimeModelType>>({ required: true });\nconst menuOpen = defineModel<boolean>('menuOpen', { default: false });\n\nconst {\n disabled = false,\n readonly = false,\n allowEmpty = false,\n dense = false,\n type = 'epoch-ms',\n hideDetails = false,\n label = 'Pick a date',\n variant = 'default',\n hint,\n maxDate,\n minDate,\n format = 'day-first',\n accuracy = 'minute',\n errorMessages = [],\n successMessages = [],\n required = false,\n} = defineProps<RuiDateTimePickerProps>();\n\ndefineSlots<{\n 'menu-content': () => any;\n}>();\n\nconst baseFormats: Record<DateFormat, string> = {\n 'day-first': 'DD/MM/YYYY HH:mm',\n 'month-first': 'MM/DD/YYYY HH:mm',\n 'year-first': 'YYYY/MM/DD HH:mm',\n};\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\nconst cursorPosition = ref<number>(0);\nconst currentValue = ref<number>();\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\nconst calendarMenuOpen = ref<boolean>(false);\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\n\nconst anyFocused = computed<boolean>(() => get(activatorFocusedWithin) || get(menuWrapperFocusedWithin));\n\nconst {\n clear: clearSelection,\n getDateTime,\n internalErrorMessages,\n maxAllowedDate,\n minAllowedDate,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n} = useDateTimeSelection({\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n});\n\nconst { setValue, getCurrent } = useInputHandler(segmentData, currentValue);\n\nconst dateFormat = computed<string>(() => {\n const fmt = baseFormats[format];\n if (accuracy === 'second') {\n return fmt.replace('HH:mm', 'HH:mm:ss');\n }\n else if (accuracy === 'millisecond') {\n return fmt.replace('HH:mm', 'HH:mm:ss.SSS');\n }\n return fmt;\n});\n\nconst {\n clear: clearSegment,\n getCurrentSegment,\n handleBlur,\n handleClick,\n handleFocus,\n handleInput,\n handleInputSelection,\n handleKeyDown,\n handleMouseDown,\n handlePaste,\n setSegment,\n} = useKeyboardHandler({\n accuracy,\n currentValue,\n cursorPosition,\n dateFormat,\n disabled,\n getCurrent,\n getDateTime,\n readonly,\n setValue,\n textInput,\n});\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst isOutlined = computed<boolean>(() => variant === 'outlined');\n\nconst formattedDisplay = computed<string>(() => {\n let result = get(dateFormat);\n\n const replacements = [\n { pattern: 'YYYY', value: getDisplayValue(selectedYear, 4) },\n { pattern: 'MM', value: getDisplayValue(selectedMonth, 2) },\n { pattern: 'DD', value: getDisplayValue(selectedDay, 2) },\n { pattern: 'HH', value: getDisplayValue(selectedHour, 2) },\n { pattern: 'mm', value: getDisplayValue(selectedMinute, 2) },\n { pattern: 'ss', value: getDisplayValue(selectedSecond, 2) },\n { pattern: 'SSS', value: getDisplayValue(selectedMillisecond, 3) },\n ];\n\n for (const { pattern, value } of replacements) {\n if (value !== undefined) {\n result = result.replace(pattern, value);\n }\n }\n\n return result;\n});\n\nconst timeSelection = computed<TimePickerSelection>({\n get() {\n const type = getCurrentSegment()?.type;\n\n if (type === 'mm') {\n return 'minute';\n }\n else if (type === 'ss') {\n return 'second';\n }\n else if (type === 'SSS') {\n return 'millisecond';\n }\n return 'hour';\n },\n set(value: TimePickerSelection) {\n let segmentType: DateTimeSegmentType = 'HH';\n if (value === 'minute') {\n segmentType = 'mm';\n }\n else if (value === 'second') {\n segmentType = 'ss';\n }\n else if (value === 'millisecond') {\n segmentType = 'SSS';\n }\n\n setSegment(segmentType);\n },\n});\n\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(isOutlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof dateTimePickerStyles>>(() => dateTimePickerStyles({\n filled: variant === 'filled',\n outlined: get(isOutlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst combinedErrorMessages = computed<string[]>(() => {\n if (!errorMessages)\n return get(internalErrorMessages);\n\n const propErrors = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n return [...propErrors, ...get(internalErrorMessages)];\n});\n\nfunction getDisplayValue(digit: Ref<number | undefined>, padding: number): string | undefined {\n return isDefined(digit) ? get(digit).toString().padStart(padding, '0') : undefined;\n}\n\nasync function setInputFocus(): Promise<void> {\n await nextTick(() => {\n set(searchInputFocused, true);\n });\n}\n\nfunction clear(segmentType?: string): void {\n if (!segmentType) {\n clearSelection();\n set(currentValue, undefined);\n return;\n }\n\n clearSegment(segmentType);\n}\n\nfunction handleInputClick(event: MouseEvent): void {\n // Handle segment selection first, before any DOM changes from menu opening\n handleClick(event);\n // Open menu if not already open\n if (!get(isOpen)) {\n set(isOpen, true);\n }\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nconst anyMenuOpen = computed<boolean>(() => get(isOpen) || get(calendarMenuOpen));\n\nwatch(anyMenuOpen, (value) => {\n set(menuOpen, value);\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"getRootAttrs($attrs, [])\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :dense=\"dense\"\n :hint=\"hint\"\n :disabled=\"disabled\"\n :success-messages=\"successMessages\"\n :error-messages=\"combinedErrorMessages\"\n :close-on-content-click=\"false\"\n :show-details=\"!hideDetails\"\n :persistent=\"calendarMenuOpen\"\n full-width\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open }\">\n <div\n ref=\"activator\"\n :class=\"ui.activator()\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readonly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readonly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"setInputFocus()\"\n >\n <span\n v-if=\"isOutlined && (searchInputFocused || open || valueSet)\"\n data-id=\"label\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && isOutlined },\n ]\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n data-id=\"required-indicator\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n\n <span :class=\"ui.iconPrepend()\">\n <RuiIcon\n class=\"text-rui-text-secondary transition\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-calendar-days\"\n />\n </span>\n\n <div :class=\"ui.value()\">\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"formattedDisplay\"\n class=\"bg-transparent outline-none flex-1 min-w-0\"\n type=\"text\"\n :placeholder=\"dateFormat\"\n :readonly=\"readonly\"\n :aria-invalid=\"hasError\"\n @mousedown=\"handleMouseDown($event)\"\n @focus=\"handleFocus()\"\n @blur=\"handleBlur()\"\n @select=\"handleInputSelection($event)\"\n @click.stop=\"handleInputClick($event)\"\n @keydown=\"handleKeyDown($event)\"\n @paste=\"handlePaste($event)\"\n @input=\"handleInput($event)\"\n />\n </div>\n\n <RuiButton\n v-if=\"allowEmpty && valueSet && !disabled\"\n variant=\"text\"\n icon\n data-id=\"clear-button\"\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n :class=\"[\n ui.clear(),\n anyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n data-id=\"append\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n </div>\n <fieldset\n v-if=\"isOutlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </template>\n <template #default>\n <RuiDateTimePickerMenu\n ref=\"menuWrapperRef\"\n v-model:selected-date=\"selectedDate\"\n v-model:selected-time=\"selectedTime\"\n v-model:selected-hour=\"selectedHour\"\n v-model:selected-minute=\"selectedMinute\"\n v-model:selected-second=\"selectedSecond\"\n v-model:selected-millisecond=\"selectedMillisecond\"\n v-model:time-selection=\"timeSelection\"\n v-model:selected-timezone=\"selectedTimezone\"\n v-model:calendar-menu-open=\"calendarMenuOpen\"\n :accuracy=\"accuracy\"\n :max-date=\"maxAllowedDate\"\n :min-date=\"minAllowedDate\"\n @set-now=\"setNow()\"\n >\n <slot name=\"menu-content\" />\n </RuiDateTimePickerMenu>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
@@ -63,6 +63,9 @@ export declare const dateTimePickerStyles: import("tailwind-variants").TVReturnT
63
63
  hasSuccess: {
64
64
  true: {};
65
65
  };
66
+ hovered: {
67
+ true: {};
68
+ };
66
69
  }, {
67
70
  fieldset: string;
68
71
  legend: string;
@@ -129,6 +132,9 @@ export declare const dateTimePickerStyles: import("tailwind-variants").TVReturnT
129
132
  hasSuccess: {
130
133
  true: {};
131
134
  };
135
+ hovered: {
136
+ true: {};
137
+ };
132
138
  }, {
133
139
  fieldset: string;
134
140
  legend: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiAutoComplete.js","names":[],"sources":["../../../../src/components/forms/auto-complete/RuiAutoComplete.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiChip from '@/components/chips/RuiChip.vue';\nimport { autoCompleteStyles, type AutoCompleteVariant } from '@/components/forms/auto-complete/auto-complete-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport {\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport {\n useAutoCompleteFocus,\n useAutoCompleteKeyboardNavigation,\n useAutoCompleteSearch,\n useAutoCompleteValue,\n} from '@/composables/forms/auto-complete';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs, getTextToken } from '@/utils/helpers';\nimport { isEqual } from '@/utils/is-equal';\nimport { cn } from '@/utils/tv';\n\nexport type AutoCompleteModelValue<TValue> =\n TValue extends Array<infer U> ? U[] : TValue | undefined;\n\nexport interface RuiAutoCompleteClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n}\n\nexport interface AutoCompleteProps<TValue, TItem> {\n options?: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiAutoCompleteClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: AutoCompleteVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n chips?: boolean;\n noFilter?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n filter?: (item: TItem, queryText: string) => boolean;\n hideSelected?: boolean;\n placeholder?: string;\n returnObject?: boolean;\n customValue?: boolean;\n hideCustomValue?: boolean;\n required?: boolean;\n hideSearchInput?: boolean;\n hideSelectionWrapper?: boolean;\n}\n\ndefineOptions({\n name: 'RuiAutoComplete',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<AutoCompleteModelValue<TValue>>({ required: true });\n\nconst searchInputModel = defineModel<string>('searchInput', { default: '' });\n\nconst {\n options = [],\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n chips = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n noFilter = false,\n hideNoData = false,\n noDataText = 'No data available',\n filter,\n hideSelected = false,\n placeholder = '',\n returnObject = false,\n customValue = false,\n hideCustomValue = false,\n required = false,\n hideSearchInput = false,\n hideSelectionWrapper = false,\n} = defineProps<AutoCompleteProps<TValue, TItem>>();\n\nconst slots = defineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem[];\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem[] }) => any;\n 'selection.prepend'?: (props: { index: number; item: TItem }) => any;\n 'selection'?: (props: { index: number; item: TItem; chipAttrs: Record<string, unknown> }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst { getText, getIdentifier } = useDropdownOptionProperty<TValue, TItem>({\n keyAttr,\n textAttr,\n});\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\nconst { focused: activatorFocused } = useFocus(activator);\n\nconst {\n internalSearch,\n filteredOptions,\n justOpened,\n updateInternalSearch,\n textValueToProperValue,\n} = useAutoCompleteSearch<TItem>(\n () => options,\n searchInputModel,\n {\n keyAttr: () => keyAttr,\n textAttr: () => textAttr,\n noFilter: () => noFilter,\n filter: () => filter,\n customValue: () => customValue,\n hideCustomValue: () => hideCustomValue,\n returnObject: () => returnObject,\n },\n);\n\nconst isOpen = ref<boolean>(false);\n\n// Calculate multiple from modelValue directly to avoid circular dependency\nconst multiple = computed<boolean>(() => Array.isArray(get(modelValue)));\n\nconst shouldApplyValueAsSearch = computed<boolean>(\n () => !(slots.selection || get(multiple) || chips),\n);\n\nconst { value, setSelected } = useAutoCompleteValue<AutoCompleteModelValue<TValue>, TItem>(\n modelValue,\n () => options,\n {\n keyAttr: () => keyAttr,\n returnObject: () => returnObject,\n customValue: () => customValue,\n },\n {\n getIdentifier,\n getText,\n textValueToProperValue,\n shouldApplyValueAsSearch,\n isOpen,\n multiple,\n updateInternalSearch,\n },\n);\n\nconst resolvedItemHeight = itemHeight ?? (dense ? 30 : 48);\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n menuWidth,\n isActiveItem,\n itemIndexInValue,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n optionsWithSelectedHidden,\n userNavigated,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: resolvedItemHeight,\n keyAttr,\n textAttr,\n options: filteredOptions,\n dense: () => dense,\n value,\n menuRef,\n setValue,\n autoSelectFirst,\n hideSelected,\n isOpen,\n getText,\n getIdentifier,\n});\n\nconst {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n} = useAutoCompleteKeyboardNavigation<TItem>(\n {\n chips: () => chips,\n customValue: () => customValue,\n multiple,\n },\n {\n activator,\n applyHighlighted,\n clear,\n filteredOptions,\n getText,\n highlightedIndex,\n internalSearch,\n isOpen,\n removeValue: (item: TItem): void => { setValue(item); },\n searchInputFocused,\n setSearchAsValue,\n userNavigated,\n value,\n },\n);\n\nconst {\n anyFocused: focusAnyFocused,\n inputClass: focusInputClass,\n onActivatorFocused: focusOnActivatorFocused,\n onInputFocused: focusOnInputFocused,\n setInputFocus: focusSetInputFocus,\n} = useAutoCompleteFocus(\n {\n customValue: () => customValue,\n disabled: () => disabled,\n shouldApplyValueAsSearch,\n },\n {\n activatorFocused,\n activatorFocusedWithin,\n focusedValueIndex,\n internalSearch,\n isOpen,\n justOpened,\n menuWrapperFocusedWithin,\n searchInputFocused,\n setSearchAsValue,\n textInput,\n updateInternalSearch,\n },\n);\n\nconst menuMinHeight = computed<number>(\n () => Math.min(5, get(optionsWithSelectedHidden).length) * resolvedItemHeight,\n);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst valueSet = computed<boolean>(() => get(value).length > 0);\n\nconst usedPlaceholder = computed<string>(() => {\n if (get(searchInputFocused))\n return placeholder;\n return '';\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof autoCompleteStyles>>(() => autoCompleteStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = autoCompleteStyles({}).highlighted();\n\nfunction updateSearchInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n set(isOpen, true);\n updateInternalSearch(value);\n set(justOpened, false);\n}\n\nasync function setValue(val: TItem, skipRefocused = false): Promise<void> {\n const isMultiple = get(multiple);\n\n if (isMultiple) {\n const newValue = [...get(value)];\n const indexInValue = itemIndexInValue(val);\n if (indexInValue === -1) {\n updateInternalSearch();\n newValue.push(val);\n }\n else {\n newValue.splice(indexInValue, 1);\n }\n set(value, newValue);\n }\n else {\n if (get(shouldApplyValueAsSearch))\n updateInternalSearch(getText(val));\n else updateInternalSearch();\n\n set(value, [val]);\n }\n\n if (!isMultiple) {\n if (!skipRefocused) {\n set(activatorFocused, true);\n get(activator)?.focus();\n await nextTick(() => {\n set(isOpen, false);\n });\n }\n else {\n set(isOpen, false);\n }\n }\n else if (!skipRefocused) {\n set(searchInputFocused, true);\n }\n}\n\nfunction setSearchAsValue(): void {\n const searchToBeValue = get(internalSearch);\n if (!searchToBeValue)\n return;\n\n const newValue: TItem = textValueToProperValue(searchToBeValue);\n setValue(newValue, true);\n}\n\nfunction clear(): void {\n updateInternalSearch();\n set(modelValue, (Array.isArray(get(modelValue)) ? [] : undefined) as AutoCompleteModelValue<TValue>);\n}\n\nfunction chipAttrs(item: TItem, index: number): Record<string, unknown> {\n return {\n 'data-index': index,\n 'data-value': getIdentifier(item),\n 'onKeydown': (event: KeyboardEvent): void => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n event.stopPropagation();\n event.preventDefault();\n setValue(item);\n }\n },\n 'onClick': (e: MouseEvent): void => {\n e.stopPropagation();\n setValueFocus(index);\n },\n 'onClick:close': (): void => {\n setValue(item);\n },\n };\n}\n\nfunction setSelectionRange(start: number, end: number): void {\n set(searchInputFocused, true);\n get(textInput)?.setSelectionRange?.(start, end);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nfunction openMenu(): void {\n set(isOpen, true);\n}\n\nfunction closeMenu(): void {\n set(isOpen, false);\n}\n\n// Optimize options watcher with shallow comparison first\nwatch(() => options, (curr, old) => {\n if (curr === old || customValue)\n return;\n\n // Only do deep comparison if reference changed\n if (isEqual(curr, old))\n return;\n\n setSelected(get(value));\n});\n\ndefineExpose({\n closeMenu,\n focus: focusSetInputFocus,\n openMenu,\n setSelectionRange,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"false\"\n :full-width=\"true\"\n :persist-on-activator-click=\"true\"\n :menu-class=\"[\n { hidden: optionsWithSelectedHidden.length === 0 && customValue && !slots['no-data'] },\n menuOptions?.menuClass,\n ]\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readOnly ? {} : attrs),\n }\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n @click=\"focusSetInputFocus()\"\n @focus=\"focusOnActivatorFocused()\"\n @keydown.enter=\"onEnter($event)\"\n @keydown.tab=\"onTab($event)\"\n @keydown.left=\"moveSelectedValueHighlight($event, false)\"\n @keydown.right=\"moveSelectedValueHighlight($event, true)\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = optionsWithSelectedHidden.length - 1\"\n >\n <span\n v-if=\"outlined || (!valueSet && !searchInputFocused)\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <div\n data-id=\"value\"\n :class=\"ui.value()\"\n >\n <template\n v-for=\"(item, i) in value\"\n :key=\"getIdentifier(item)\"\n >\n <RuiChip\n v-if=\"chips\"\n :key=\"getTextToken(getIdentifier(item))\"\n tabindex=\"-1\"\n :size=\"dense ? 'sm' : 'md'\"\n closeable\n :class=\"{ 'leading-3': dense }\"\n clickable\n v-bind=\"chipAttrs(item, i)\"\n >\n <div class=\"flex\">\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </RuiChip>\n <div\n v-else-if=\"\n multiple\n || (!searchInputFocused && (slots['selection.prepend'] || slots.selection))\n \"\n :class=\"hideSelectionWrapper ? 'contents' : 'flex'\"\n >\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n v-if=\"multiple || slots.selection\"\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </template>\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"internalSearch\"\n class=\"bg-transparent outline-none\"\n type=\"text\"\n :placeholder=\"usedPlaceholder\"\n :class=\"[focusInputClass, { hidden: hideSearchInput }]\"\n :aria-invalid=\"hasError\"\n aria-autocomplete=\"list\"\n @keydown.delete=\"onInputDeletePressed()\"\n @input.stop=\"updateSearchInput($event)\"\n @focus=\"focusOnInputFocused()\"\n />\n </div>\n\n <RuiButton\n v-if=\"clearable && valueSet && !disabled\"\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n data-id=\"clear\"\n :class=\"[\n ui.clear(),\n focusAnyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </div>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n </template>\n <template #default=\"{ width }\">\n <div ref=\"menuWrapperRef\">\n <div\n v-if=\"optionsWithSelectedHidden.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth, minHeight: `${menuMinHeight}px` }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div\n v-if=\"!customValue\"\n class=\"p-4\"\n data-id=\"no-data\"\n >\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiAutoComplete.js","names":[],"sources":["../../../../src/components/forms/auto-complete/RuiAutoComplete.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiChip from '@/components/chips/RuiChip.vue';\nimport { autoCompleteStyles, type AutoCompleteVariant } from '@/components/forms/auto-complete/auto-complete-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport {\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport {\n useAutoCompleteFocus,\n useAutoCompleteKeyboardNavigation,\n useAutoCompleteSearch,\n useAutoCompleteValue,\n} from '@/composables/forms/auto-complete';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs, getTextToken } from '@/utils/helpers';\nimport { isEqual } from '@/utils/is-equal';\nimport { cn } from '@/utils/tv';\n\nexport type AutoCompleteModelValue<TValue> =\n TValue extends Array<infer U> ? U[] : TValue | undefined;\n\nexport interface RuiAutoCompleteClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n}\n\nexport interface AutoCompleteProps<TValue, TItem> {\n options?: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiAutoCompleteClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: AutoCompleteVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n chips?: boolean;\n noFilter?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n filter?: (item: TItem, queryText: string) => boolean;\n hideSelected?: boolean;\n placeholder?: string;\n returnObject?: boolean;\n customValue?: boolean;\n hideCustomValue?: boolean;\n required?: boolean;\n hideSearchInput?: boolean;\n hideSelectionWrapper?: boolean;\n}\n\ndefineOptions({\n name: 'RuiAutoComplete',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<AutoCompleteModelValue<TValue>>({ required: true });\n\nconst searchInputModel = defineModel<string>('searchInput', { default: '' });\n\nconst {\n options = [],\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n chips = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n noFilter = false,\n hideNoData = false,\n noDataText = 'No data available',\n filter,\n hideSelected = false,\n placeholder = '',\n returnObject = false,\n customValue = false,\n hideCustomValue = false,\n required = false,\n hideSearchInput = false,\n hideSelectionWrapper = false,\n} = defineProps<AutoCompleteProps<TValue, TItem>>();\n\nconst slots = defineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem[];\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem[] }) => any;\n 'selection.prepend'?: (props: { index: number; item: TItem }) => any;\n 'selection'?: (props: { index: number; item: TItem; chipAttrs: Record<string, unknown> }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst { getText, getIdentifier } = useDropdownOptionProperty<TValue, TItem>({\n keyAttr,\n textAttr,\n});\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\nconst { focused: activatorFocused } = useFocus(activator);\n\nconst {\n internalSearch,\n filteredOptions,\n justOpened,\n updateInternalSearch,\n textValueToProperValue,\n} = useAutoCompleteSearch<TItem>(\n () => options,\n searchInputModel,\n {\n keyAttr: () => keyAttr,\n textAttr: () => textAttr,\n noFilter: () => noFilter,\n filter: () => filter,\n customValue: () => customValue,\n hideCustomValue: () => hideCustomValue,\n returnObject: () => returnObject,\n },\n);\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\n\n// Calculate multiple from modelValue directly to avoid circular dependency\nconst multiple = computed<boolean>(() => Array.isArray(get(modelValue)));\n\nconst shouldApplyValueAsSearch = computed<boolean>(\n () => !(slots.selection || get(multiple) || chips),\n);\n\nconst { value, setSelected } = useAutoCompleteValue<AutoCompleteModelValue<TValue>, TItem>(\n modelValue,\n () => options,\n {\n keyAttr: () => keyAttr,\n returnObject: () => returnObject,\n customValue: () => customValue,\n },\n {\n getIdentifier,\n getText,\n textValueToProperValue,\n shouldApplyValueAsSearch,\n isOpen,\n multiple,\n updateInternalSearch,\n },\n);\n\nconst resolvedItemHeight = itemHeight ?? (dense ? 30 : 48);\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n menuWidth,\n isActiveItem,\n itemIndexInValue,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n optionsWithSelectedHidden,\n userNavigated,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: resolvedItemHeight,\n keyAttr,\n textAttr,\n options: filteredOptions,\n dense: () => dense,\n value,\n menuRef,\n setValue,\n autoSelectFirst,\n hideSelected,\n isOpen,\n getText,\n getIdentifier,\n});\n\nconst {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n} = useAutoCompleteKeyboardNavigation<TItem>(\n {\n chips: () => chips,\n customValue: () => customValue,\n multiple,\n },\n {\n activator,\n applyHighlighted,\n clear,\n filteredOptions,\n getText,\n highlightedIndex,\n internalSearch,\n isOpen,\n removeValue: (item: TItem): void => { setValue(item); },\n searchInputFocused,\n setSearchAsValue,\n userNavigated,\n value,\n },\n);\n\nconst {\n anyFocused: focusAnyFocused,\n inputClass: focusInputClass,\n onActivatorFocused: focusOnActivatorFocused,\n onInputFocused: focusOnInputFocused,\n setInputFocus: focusSetInputFocus,\n} = useAutoCompleteFocus(\n {\n customValue: () => customValue,\n disabled: () => disabled,\n shouldApplyValueAsSearch,\n },\n {\n activatorFocused,\n activatorFocusedWithin,\n focusedValueIndex,\n internalSearch,\n isOpen,\n justOpened,\n menuWrapperFocusedWithin,\n searchInputFocused,\n setSearchAsValue,\n textInput,\n updateInternalSearch,\n },\n);\n\nconst menuMinHeight = computed<number>(\n () => Math.min(5, get(optionsWithSelectedHidden).length) * resolvedItemHeight,\n);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst valueSet = computed<boolean>(() => get(value).length > 0);\n\nconst usedPlaceholder = computed<string>(() => {\n if (get(searchInputFocused))\n return placeholder;\n return '';\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof autoCompleteStyles>>(() => autoCompleteStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = autoCompleteStyles({}).highlighted();\n\nfunction updateSearchInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n set(isOpen, true);\n updateInternalSearch(value);\n set(justOpened, false);\n}\n\nasync function setValue(val: TItem, skipRefocused = false): Promise<void> {\n const isMultiple = get(multiple);\n\n if (isMultiple) {\n const newValue = [...get(value)];\n const indexInValue = itemIndexInValue(val);\n if (indexInValue === -1) {\n updateInternalSearch();\n newValue.push(val);\n }\n else {\n newValue.splice(indexInValue, 1);\n }\n set(value, newValue);\n }\n else {\n if (get(shouldApplyValueAsSearch))\n updateInternalSearch(getText(val));\n else updateInternalSearch();\n\n set(value, [val]);\n }\n\n if (!isMultiple) {\n if (!skipRefocused) {\n set(activatorFocused, true);\n get(activator)?.focus();\n await nextTick(() => {\n set(isOpen, false);\n });\n }\n else {\n set(isOpen, false);\n }\n }\n else if (!skipRefocused) {\n set(searchInputFocused, true);\n }\n}\n\nfunction setSearchAsValue(): void {\n const searchToBeValue = get(internalSearch);\n if (!searchToBeValue)\n return;\n\n const newValue: TItem = textValueToProperValue(searchToBeValue);\n setValue(newValue, true);\n}\n\nfunction clear(): void {\n updateInternalSearch();\n set(modelValue, (Array.isArray(get(modelValue)) ? [] : undefined) as AutoCompleteModelValue<TValue>);\n}\n\nfunction chipAttrs(item: TItem, index: number): Record<string, unknown> {\n return {\n 'data-index': index,\n 'data-value': getIdentifier(item),\n 'onKeydown': (event: KeyboardEvent): void => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n event.stopPropagation();\n event.preventDefault();\n setValue(item);\n }\n },\n 'onClick': (e: MouseEvent): void => {\n e.stopPropagation();\n setValueFocus(index);\n },\n 'onClick:close': (): void => {\n setValue(item);\n },\n };\n}\n\nfunction setSelectionRange(start: number, end: number): void {\n set(searchInputFocused, true);\n get(textInput)?.setSelectionRange?.(start, end);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nfunction openMenu(): void {\n set(isOpen, true);\n}\n\nfunction closeMenu(): void {\n set(isOpen, false);\n}\n\n// Optimize options watcher with shallow comparison first\nwatch(() => options, (curr, old) => {\n if (curr === old || customValue)\n return;\n\n // Only do deep comparison if reference changed\n if (isEqual(curr, old))\n return;\n\n setSelected(get(value));\n});\n\ndefineExpose({\n closeMenu,\n focus: focusSetInputFocus,\n openMenu,\n setSelectionRange,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"false\"\n :full-width=\"true\"\n :persist-on-activator-click=\"true\"\n :menu-class=\"[\n { hidden: optionsWithSelectedHidden.length === 0 && customValue && !slots['no-data'] },\n menuOptions?.menuClass,\n ]\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readOnly ? {} : attrs),\n }\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"focusSetInputFocus()\"\n @focus=\"focusOnActivatorFocused()\"\n @keydown.enter=\"onEnter($event)\"\n @keydown.tab=\"onTab($event)\"\n @keydown.left=\"moveSelectedValueHighlight($event, false)\"\n @keydown.right=\"moveSelectedValueHighlight($event, true)\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = optionsWithSelectedHidden.length - 1\"\n >\n <span\n v-if=\"outlined || (!valueSet && !searchInputFocused)\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <div\n data-id=\"value\"\n :class=\"ui.value()\"\n >\n <template\n v-for=\"(item, i) in value\"\n :key=\"getIdentifier(item)\"\n >\n <RuiChip\n v-if=\"chips\"\n :key=\"getTextToken(getIdentifier(item))\"\n tabindex=\"-1\"\n :size=\"dense ? 'sm' : 'md'\"\n closeable\n :class=\"{ 'leading-3': dense }\"\n clickable\n v-bind=\"chipAttrs(item, i)\"\n >\n <div class=\"flex\">\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </RuiChip>\n <div\n v-else-if=\"\n multiple\n || (!searchInputFocused && (slots['selection.prepend'] || slots.selection))\n \"\n :class=\"hideSelectionWrapper ? 'contents' : 'flex'\"\n >\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n v-if=\"multiple || slots.selection\"\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </template>\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"internalSearch\"\n class=\"bg-transparent outline-none\"\n type=\"text\"\n :placeholder=\"usedPlaceholder\"\n :class=\"[focusInputClass, { hidden: hideSearchInput }]\"\n :aria-invalid=\"hasError\"\n aria-autocomplete=\"list\"\n @keydown.delete=\"onInputDeletePressed()\"\n @input.stop=\"updateSearchInput($event)\"\n @focus=\"focusOnInputFocused()\"\n />\n </div>\n\n <RuiButton\n v-if=\"clearable && valueSet && !disabled\"\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n data-id=\"clear\"\n :class=\"[\n ui.clear(),\n focusAnyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </div>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n </template>\n <template #default=\"{ width }\">\n <div ref=\"menuWrapperRef\">\n <div\n v-if=\"optionsWithSelectedHidden.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth, minHeight: `${menuMinHeight}px` }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div\n v-if=\"!customValue\"\n class=\"p-4\"\n data-id=\"no-data\"\n >\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -163,6 +163,7 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
163
163
  returnObject: () => __props.returnObject
164
164
  });
165
165
  const isOpen = ref(false);
166
+ const isHovered = ref(false);
166
167
  const multiple = computed(() => Array.isArray(get$1(modelValue)));
167
168
  const shouldApplyValueAsSearch = computed(() => !(slots.selection || get$1(multiple) || __props.chips));
168
169
  const { value, setSelected } = useAutoCompleteValue(modelValue, () => __props.options, {
@@ -250,6 +251,7 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
250
251
  outlined: get$1(outlined),
251
252
  float: get$1(float),
252
253
  opened: get$1(isOpen),
254
+ hovered: get$1(isHovered),
253
255
  dense: __props.dense,
254
256
  disabled: __props.disabled,
255
257
  readonly: __props.readOnly,
@@ -349,7 +351,7 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
349
351
  return (_ctx, _cache) => {
350
352
  return openBlock(), createBlock(RuiMenu_default, mergeProps({
351
353
  modelValue: unref(isOpen),
352
- "onUpdate:modelValue": _cache[18] || (_cache[18] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
354
+ "onUpdate:modelValue": _cache[20] || (_cache[20] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
353
355
  }, {
354
356
  ...unref(getRootAttrs)(_ctx.$attrs, []),
355
357
  ...__props.menuOptions
@@ -394,17 +396,19 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
394
396
  "data-id": "activator",
395
397
  "aria-invalid": unref(hasError),
396
398
  tabindex: __props.disabled || __props.readOnly ? -1 : 0,
397
- onClick: _cache[5] || (_cache[5] = ($event) => unref(focusSetInputFocus)()),
398
- onFocus: _cache[6] || (_cache[6] = ($event) => unref(focusOnActivatorFocused)()),
399
+ onMouseenter: _cache[5] || (_cache[5] = ($event) => isHovered.value = true),
400
+ onMouseleave: _cache[6] || (_cache[6] = ($event) => isHovered.value = false),
401
+ onClick: _cache[7] || (_cache[7] = ($event) => unref(focusSetInputFocus)()),
402
+ onFocus: _cache[8] || (_cache[8] = ($event) => unref(focusOnActivatorFocused)()),
399
403
  onKeydown: [
400
- _cache[7] || (_cache[7] = withKeys(($event) => unref(onEnter)($event), ["enter"])),
401
- _cache[8] || (_cache[8] = withKeys(($event) => unref(onTab)($event), ["tab"])),
402
- _cache[9] || (_cache[9] = withKeys(($event) => unref(moveSelectedValueHighlight)($event, false), ["left"])),
403
- _cache[10] || (_cache[10] = withKeys(($event) => unref(moveSelectedValueHighlight)($event, true), ["right"])),
404
- _cache[11] || (_cache[11] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])),
405
- _cache[12] || (_cache[12] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"])),
406
- _cache[13] || (_cache[13] = withKeys(withModifiers(($event) => highlightedIndex.value = 0, ["prevent"]), ["home"])),
407
- _cache[14] || (_cache[14] = withKeys(withModifiers(($event) => highlightedIndex.value = unref(optionsWithSelectedHidden).length - 1, ["prevent"]), ["end"]))
404
+ _cache[9] || (_cache[9] = withKeys(($event) => unref(onEnter)($event), ["enter"])),
405
+ _cache[10] || (_cache[10] = withKeys(($event) => unref(onTab)($event), ["tab"])),
406
+ _cache[11] || (_cache[11] = withKeys(($event) => unref(moveSelectedValueHighlight)($event, false), ["left"])),
407
+ _cache[12] || (_cache[12] = withKeys(($event) => unref(moveSelectedValueHighlight)($event, true), ["right"])),
408
+ _cache[13] || (_cache[13] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])),
409
+ _cache[14] || (_cache[14] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"])),
410
+ _cache[15] || (_cache[15] = withKeys(withModifiers(($event) => highlightedIndex.value = 0, ["prevent"]), ["home"])),
411
+ _cache[16] || (_cache[16] = withKeys(withModifiers(($event) => highlightedIndex.value = unref(optionsWithSelectedHidden).length - 1, ["prevent"]), ["end"]))
408
412
  ]
409
413
  }), [
410
414
  unref(outlined) || !unref(valueSet) && !unref(searchInputFocused) ? (openBlock(), createElementBlock("span", {
@@ -507,8 +511,8 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ *
507
511
  minWidth: unref(menuWidth),
508
512
  minHeight: `${unref(menuMinHeight)}px`
509
513
  }]),
510
- onScroll: _cache[15] || (_cache[15] = (...args) => unref(containerProps).onScroll && unref(containerProps).onScroll(...args)),
511
- onKeydown: [_cache[16] || (_cache[16] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])), _cache[17] || (_cache[17] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"]))]
514
+ onScroll: _cache[17] || (_cache[17] = (...args) => unref(containerProps).onScroll && unref(containerProps).onScroll(...args)),
515
+ onKeydown: [_cache[18] || (_cache[18] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])), _cache[19] || (_cache[19] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"]))]
512
516
  }, [createElementVNode("div", mergeProps(unref(wrapperProps), {
513
517
  ref_key: "menuRef",
514
518
  ref: menuRef
@@ -1 +1 @@
1
- {"version":3,"file":"RuiAutoComplete.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/auto-complete/RuiAutoComplete.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiChip from '@/components/chips/RuiChip.vue';\nimport { autoCompleteStyles, type AutoCompleteVariant } from '@/components/forms/auto-complete/auto-complete-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport {\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport {\n useAutoCompleteFocus,\n useAutoCompleteKeyboardNavigation,\n useAutoCompleteSearch,\n useAutoCompleteValue,\n} from '@/composables/forms/auto-complete';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs, getTextToken } from '@/utils/helpers';\nimport { isEqual } from '@/utils/is-equal';\nimport { cn } from '@/utils/tv';\n\nexport type AutoCompleteModelValue<TValue> =\n TValue extends Array<infer U> ? U[] : TValue | undefined;\n\nexport interface RuiAutoCompleteClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n}\n\nexport interface AutoCompleteProps<TValue, TItem> {\n options?: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiAutoCompleteClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: AutoCompleteVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n chips?: boolean;\n noFilter?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n filter?: (item: TItem, queryText: string) => boolean;\n hideSelected?: boolean;\n placeholder?: string;\n returnObject?: boolean;\n customValue?: boolean;\n hideCustomValue?: boolean;\n required?: boolean;\n hideSearchInput?: boolean;\n hideSelectionWrapper?: boolean;\n}\n\ndefineOptions({\n name: 'RuiAutoComplete',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<AutoCompleteModelValue<TValue>>({ required: true });\n\nconst searchInputModel = defineModel<string>('searchInput', { default: '' });\n\nconst {\n options = [],\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n chips = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n noFilter = false,\n hideNoData = false,\n noDataText = 'No data available',\n filter,\n hideSelected = false,\n placeholder = '',\n returnObject = false,\n customValue = false,\n hideCustomValue = false,\n required = false,\n hideSearchInput = false,\n hideSelectionWrapper = false,\n} = defineProps<AutoCompleteProps<TValue, TItem>>();\n\nconst slots = defineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem[];\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem[] }) => any;\n 'selection.prepend'?: (props: { index: number; item: TItem }) => any;\n 'selection'?: (props: { index: number; item: TItem; chipAttrs: Record<string, unknown> }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst { getText, getIdentifier } = useDropdownOptionProperty<TValue, TItem>({\n keyAttr,\n textAttr,\n});\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\nconst { focused: activatorFocused } = useFocus(activator);\n\nconst {\n internalSearch,\n filteredOptions,\n justOpened,\n updateInternalSearch,\n textValueToProperValue,\n} = useAutoCompleteSearch<TItem>(\n () => options,\n searchInputModel,\n {\n keyAttr: () => keyAttr,\n textAttr: () => textAttr,\n noFilter: () => noFilter,\n filter: () => filter,\n customValue: () => customValue,\n hideCustomValue: () => hideCustomValue,\n returnObject: () => returnObject,\n },\n);\n\nconst isOpen = ref<boolean>(false);\n\n// Calculate multiple from modelValue directly to avoid circular dependency\nconst multiple = computed<boolean>(() => Array.isArray(get(modelValue)));\n\nconst shouldApplyValueAsSearch = computed<boolean>(\n () => !(slots.selection || get(multiple) || chips),\n);\n\nconst { value, setSelected } = useAutoCompleteValue<AutoCompleteModelValue<TValue>, TItem>(\n modelValue,\n () => options,\n {\n keyAttr: () => keyAttr,\n returnObject: () => returnObject,\n customValue: () => customValue,\n },\n {\n getIdentifier,\n getText,\n textValueToProperValue,\n shouldApplyValueAsSearch,\n isOpen,\n multiple,\n updateInternalSearch,\n },\n);\n\nconst resolvedItemHeight = itemHeight ?? (dense ? 30 : 48);\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n menuWidth,\n isActiveItem,\n itemIndexInValue,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n optionsWithSelectedHidden,\n userNavigated,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: resolvedItemHeight,\n keyAttr,\n textAttr,\n options: filteredOptions,\n dense: () => dense,\n value,\n menuRef,\n setValue,\n autoSelectFirst,\n hideSelected,\n isOpen,\n getText,\n getIdentifier,\n});\n\nconst {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n} = useAutoCompleteKeyboardNavigation<TItem>(\n {\n chips: () => chips,\n customValue: () => customValue,\n multiple,\n },\n {\n activator,\n applyHighlighted,\n clear,\n filteredOptions,\n getText,\n highlightedIndex,\n internalSearch,\n isOpen,\n removeValue: (item: TItem): void => { setValue(item); },\n searchInputFocused,\n setSearchAsValue,\n userNavigated,\n value,\n },\n);\n\nconst {\n anyFocused: focusAnyFocused,\n inputClass: focusInputClass,\n onActivatorFocused: focusOnActivatorFocused,\n onInputFocused: focusOnInputFocused,\n setInputFocus: focusSetInputFocus,\n} = useAutoCompleteFocus(\n {\n customValue: () => customValue,\n disabled: () => disabled,\n shouldApplyValueAsSearch,\n },\n {\n activatorFocused,\n activatorFocusedWithin,\n focusedValueIndex,\n internalSearch,\n isOpen,\n justOpened,\n menuWrapperFocusedWithin,\n searchInputFocused,\n setSearchAsValue,\n textInput,\n updateInternalSearch,\n },\n);\n\nconst menuMinHeight = computed<number>(\n () => Math.min(5, get(optionsWithSelectedHidden).length) * resolvedItemHeight,\n);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst valueSet = computed<boolean>(() => get(value).length > 0);\n\nconst usedPlaceholder = computed<string>(() => {\n if (get(searchInputFocused))\n return placeholder;\n return '';\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof autoCompleteStyles>>(() => autoCompleteStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = autoCompleteStyles({}).highlighted();\n\nfunction updateSearchInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n set(isOpen, true);\n updateInternalSearch(value);\n set(justOpened, false);\n}\n\nasync function setValue(val: TItem, skipRefocused = false): Promise<void> {\n const isMultiple = get(multiple);\n\n if (isMultiple) {\n const newValue = [...get(value)];\n const indexInValue = itemIndexInValue(val);\n if (indexInValue === -1) {\n updateInternalSearch();\n newValue.push(val);\n }\n else {\n newValue.splice(indexInValue, 1);\n }\n set(value, newValue);\n }\n else {\n if (get(shouldApplyValueAsSearch))\n updateInternalSearch(getText(val));\n else updateInternalSearch();\n\n set(value, [val]);\n }\n\n if (!isMultiple) {\n if (!skipRefocused) {\n set(activatorFocused, true);\n get(activator)?.focus();\n await nextTick(() => {\n set(isOpen, false);\n });\n }\n else {\n set(isOpen, false);\n }\n }\n else if (!skipRefocused) {\n set(searchInputFocused, true);\n }\n}\n\nfunction setSearchAsValue(): void {\n const searchToBeValue = get(internalSearch);\n if (!searchToBeValue)\n return;\n\n const newValue: TItem = textValueToProperValue(searchToBeValue);\n setValue(newValue, true);\n}\n\nfunction clear(): void {\n updateInternalSearch();\n set(modelValue, (Array.isArray(get(modelValue)) ? [] : undefined) as AutoCompleteModelValue<TValue>);\n}\n\nfunction chipAttrs(item: TItem, index: number): Record<string, unknown> {\n return {\n 'data-index': index,\n 'data-value': getIdentifier(item),\n 'onKeydown': (event: KeyboardEvent): void => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n event.stopPropagation();\n event.preventDefault();\n setValue(item);\n }\n },\n 'onClick': (e: MouseEvent): void => {\n e.stopPropagation();\n setValueFocus(index);\n },\n 'onClick:close': (): void => {\n setValue(item);\n },\n };\n}\n\nfunction setSelectionRange(start: number, end: number): void {\n set(searchInputFocused, true);\n get(textInput)?.setSelectionRange?.(start, end);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nfunction openMenu(): void {\n set(isOpen, true);\n}\n\nfunction closeMenu(): void {\n set(isOpen, false);\n}\n\n// Optimize options watcher with shallow comparison first\nwatch(() => options, (curr, old) => {\n if (curr === old || customValue)\n return;\n\n // Only do deep comparison if reference changed\n if (isEqual(curr, old))\n return;\n\n setSelected(get(value));\n});\n\ndefineExpose({\n closeMenu,\n focus: focusSetInputFocus,\n openMenu,\n setSelectionRange,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"false\"\n :full-width=\"true\"\n :persist-on-activator-click=\"true\"\n :menu-class=\"[\n { hidden: optionsWithSelectedHidden.length === 0 && customValue && !slots['no-data'] },\n menuOptions?.menuClass,\n ]\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readOnly ? {} : attrs),\n }\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n @click=\"focusSetInputFocus()\"\n @focus=\"focusOnActivatorFocused()\"\n @keydown.enter=\"onEnter($event)\"\n @keydown.tab=\"onTab($event)\"\n @keydown.left=\"moveSelectedValueHighlight($event, false)\"\n @keydown.right=\"moveSelectedValueHighlight($event, true)\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = optionsWithSelectedHidden.length - 1\"\n >\n <span\n v-if=\"outlined || (!valueSet && !searchInputFocused)\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <div\n data-id=\"value\"\n :class=\"ui.value()\"\n >\n <template\n v-for=\"(item, i) in value\"\n :key=\"getIdentifier(item)\"\n >\n <RuiChip\n v-if=\"chips\"\n :key=\"getTextToken(getIdentifier(item))\"\n tabindex=\"-1\"\n :size=\"dense ? 'sm' : 'md'\"\n closeable\n :class=\"{ 'leading-3': dense }\"\n clickable\n v-bind=\"chipAttrs(item, i)\"\n >\n <div class=\"flex\">\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </RuiChip>\n <div\n v-else-if=\"\n multiple\n || (!searchInputFocused && (slots['selection.prepend'] || slots.selection))\n \"\n :class=\"hideSelectionWrapper ? 'contents' : 'flex'\"\n >\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n v-if=\"multiple || slots.selection\"\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </template>\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"internalSearch\"\n class=\"bg-transparent outline-none\"\n type=\"text\"\n :placeholder=\"usedPlaceholder\"\n :class=\"[focusInputClass, { hidden: hideSearchInput }]\"\n :aria-invalid=\"hasError\"\n aria-autocomplete=\"list\"\n @keydown.delete=\"onInputDeletePressed()\"\n @input.stop=\"updateSearchInput($event)\"\n @focus=\"focusOnInputFocused()\"\n />\n </div>\n\n <RuiButton\n v-if=\"clearable && valueSet && !disabled\"\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n data-id=\"clear\"\n :class=\"[\n ui.clear(),\n focusAnyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </div>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n </template>\n <template #default=\"{ width }\">\n <div ref=\"menuWrapperRef\">\n <div\n v-if=\"optionsWithSelectedHidden.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth, minHeight: `${menuMinHeight}px` }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div\n v-if=\"!customValue\"\n class=\"p-4\"\n data-id=\"no-data\"\n >\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiAutoComplete.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/auto-complete/RuiAutoComplete.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiChip from '@/components/chips/RuiChip.vue';\nimport { autoCompleteStyles, type AutoCompleteVariant } from '@/components/forms/auto-complete/auto-complete-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport {\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport {\n useAutoCompleteFocus,\n useAutoCompleteKeyboardNavigation,\n useAutoCompleteSearch,\n useAutoCompleteValue,\n} from '@/composables/forms/auto-complete';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs, getTextToken } from '@/utils/helpers';\nimport { isEqual } from '@/utils/is-equal';\nimport { cn } from '@/utils/tv';\n\nexport type AutoCompleteModelValue<TValue> =\n TValue extends Array<infer U> ? U[] : TValue | undefined;\n\nexport interface RuiAutoCompleteClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n}\n\nexport interface AutoCompleteProps<TValue, TItem> {\n options?: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiAutoCompleteClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: AutoCompleteVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n chips?: boolean;\n noFilter?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n filter?: (item: TItem, queryText: string) => boolean;\n hideSelected?: boolean;\n placeholder?: string;\n returnObject?: boolean;\n customValue?: boolean;\n hideCustomValue?: boolean;\n required?: boolean;\n hideSearchInput?: boolean;\n hideSelectionWrapper?: boolean;\n}\n\ndefineOptions({\n name: 'RuiAutoComplete',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<AutoCompleteModelValue<TValue>>({ required: true });\n\nconst searchInputModel = defineModel<string>('searchInput', { default: '' });\n\nconst {\n options = [],\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n chips = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n noFilter = false,\n hideNoData = false,\n noDataText = 'No data available',\n filter,\n hideSelected = false,\n placeholder = '',\n returnObject = false,\n customValue = false,\n hideCustomValue = false,\n required = false,\n hideSearchInput = false,\n hideSelectionWrapper = false,\n} = defineProps<AutoCompleteProps<TValue, TItem>>();\n\nconst slots = defineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem[];\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem[] }) => any;\n 'selection.prepend'?: (props: { index: number; item: TItem }) => any;\n 'selection'?: (props: { index: number; item: TItem; chipAttrs: Record<string, unknown> }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst { getText, getIdentifier } = useDropdownOptionProperty<TValue, TItem>({\n keyAttr,\n textAttr,\n});\n\nconst textInput = useTemplateRef<HTMLInputElement>('textInput');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst menuWrapperRef = useTemplateRef<HTMLDivElement>('menuWrapperRef');\n\nconst { focused: activatorFocusedWithin } = useFocusWithin(activator);\nconst { focused: menuWrapperFocusedWithin } = useFocusWithin(menuWrapperRef);\nconst { focused: searchInputFocused } = useFocus(textInput);\nconst { focused: activatorFocused } = useFocus(activator);\n\nconst {\n internalSearch,\n filteredOptions,\n justOpened,\n updateInternalSearch,\n textValueToProperValue,\n} = useAutoCompleteSearch<TItem>(\n () => options,\n searchInputModel,\n {\n keyAttr: () => keyAttr,\n textAttr: () => textAttr,\n noFilter: () => noFilter,\n filter: () => filter,\n customValue: () => customValue,\n hideCustomValue: () => hideCustomValue,\n returnObject: () => returnObject,\n },\n);\n\nconst isOpen = ref<boolean>(false);\nconst isHovered = ref<boolean>(false);\n\n// Calculate multiple from modelValue directly to avoid circular dependency\nconst multiple = computed<boolean>(() => Array.isArray(get(modelValue)));\n\nconst shouldApplyValueAsSearch = computed<boolean>(\n () => !(slots.selection || get(multiple) || chips),\n);\n\nconst { value, setSelected } = useAutoCompleteValue<AutoCompleteModelValue<TValue>, TItem>(\n modelValue,\n () => options,\n {\n keyAttr: () => keyAttr,\n returnObject: () => returnObject,\n customValue: () => customValue,\n },\n {\n getIdentifier,\n getText,\n textValueToProperValue,\n shouldApplyValueAsSearch,\n isOpen,\n multiple,\n updateInternalSearch,\n },\n);\n\nconst resolvedItemHeight = itemHeight ?? (dense ? 30 : 48);\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n menuWidth,\n isActiveItem,\n itemIndexInValue,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n optionsWithSelectedHidden,\n userNavigated,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: resolvedItemHeight,\n keyAttr,\n textAttr,\n options: filteredOptions,\n dense: () => dense,\n value,\n menuRef,\n setValue,\n autoSelectFirst,\n hideSelected,\n isOpen,\n getText,\n getIdentifier,\n});\n\nconst {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n} = useAutoCompleteKeyboardNavigation<TItem>(\n {\n chips: () => chips,\n customValue: () => customValue,\n multiple,\n },\n {\n activator,\n applyHighlighted,\n clear,\n filteredOptions,\n getText,\n highlightedIndex,\n internalSearch,\n isOpen,\n removeValue: (item: TItem): void => { setValue(item); },\n searchInputFocused,\n setSearchAsValue,\n userNavigated,\n value,\n },\n);\n\nconst {\n anyFocused: focusAnyFocused,\n inputClass: focusInputClass,\n onActivatorFocused: focusOnActivatorFocused,\n onInputFocused: focusOnInputFocused,\n setInputFocus: focusSetInputFocus,\n} = useAutoCompleteFocus(\n {\n customValue: () => customValue,\n disabled: () => disabled,\n shouldApplyValueAsSearch,\n },\n {\n activatorFocused,\n activatorFocusedWithin,\n focusedValueIndex,\n internalSearch,\n isOpen,\n justOpened,\n menuWrapperFocusedWithin,\n searchInputFocused,\n setSearchAsValue,\n textInput,\n updateInternalSearch,\n },\n);\n\nconst menuMinHeight = computed<number>(\n () => Math.min(5, get(optionsWithSelectedHidden).length) * resolvedItemHeight,\n);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst valueSet = computed<boolean>(() => get(value).length > 0);\n\nconst usedPlaceholder = computed<string>(() => {\n if (get(searchInputFocused))\n return placeholder;\n return '';\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || get(valueSet) || get(searchInputFocused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof autoCompleteStyles>>(() => autoCompleteStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = autoCompleteStyles({}).highlighted();\n\nfunction updateSearchInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n\n const value = target.value;\n set(isOpen, true);\n updateInternalSearch(value);\n set(justOpened, false);\n}\n\nasync function setValue(val: TItem, skipRefocused = false): Promise<void> {\n const isMultiple = get(multiple);\n\n if (isMultiple) {\n const newValue = [...get(value)];\n const indexInValue = itemIndexInValue(val);\n if (indexInValue === -1) {\n updateInternalSearch();\n newValue.push(val);\n }\n else {\n newValue.splice(indexInValue, 1);\n }\n set(value, newValue);\n }\n else {\n if (get(shouldApplyValueAsSearch))\n updateInternalSearch(getText(val));\n else updateInternalSearch();\n\n set(value, [val]);\n }\n\n if (!isMultiple) {\n if (!skipRefocused) {\n set(activatorFocused, true);\n get(activator)?.focus();\n await nextTick(() => {\n set(isOpen, false);\n });\n }\n else {\n set(isOpen, false);\n }\n }\n else if (!skipRefocused) {\n set(searchInputFocused, true);\n }\n}\n\nfunction setSearchAsValue(): void {\n const searchToBeValue = get(internalSearch);\n if (!searchToBeValue)\n return;\n\n const newValue: TItem = textValueToProperValue(searchToBeValue);\n setValue(newValue, true);\n}\n\nfunction clear(): void {\n updateInternalSearch();\n set(modelValue, (Array.isArray(get(modelValue)) ? [] : undefined) as AutoCompleteModelValue<TValue>);\n}\n\nfunction chipAttrs(item: TItem, index: number): Record<string, unknown> {\n return {\n 'data-index': index,\n 'data-value': getIdentifier(item),\n 'onKeydown': (event: KeyboardEvent): void => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n event.stopPropagation();\n event.preventDefault();\n setValue(item);\n }\n },\n 'onClick': (e: MouseEvent): void => {\n e.stopPropagation();\n setValueFocus(index);\n },\n 'onClick:close': (): void => {\n setValue(item);\n },\n };\n}\n\nfunction setSelectionRange(start: number, end: number): void {\n set(searchInputFocused, true);\n get(textInput)?.setSelectionRange?.(start, end);\n}\n\nfunction arrowClicked(event: MouseEvent): void {\n if (get(isOpen)) {\n set(isOpen, false);\n event.stopPropagation();\n }\n}\n\nfunction openMenu(): void {\n set(isOpen, true);\n}\n\nfunction closeMenu(): void {\n set(isOpen, false);\n}\n\n// Optimize options watcher with shallow comparison first\nwatch(() => options, (curr, old) => {\n if (curr === old || customValue)\n return;\n\n // Only do deep comparison if reference changed\n if (isEqual(curr, old))\n return;\n\n setSelected(get(value));\n});\n\ndefineExpose({\n closeMenu,\n focus: focusSetInputFocus,\n openMenu,\n setSelectionRange,\n});\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"false\"\n :full-width=\"true\"\n :persist-on-activator-click=\"true\"\n :menu-class=\"[\n { hidden: optionsWithSelectedHidden.length === 0 && customValue && !slots['no-data'] },\n menuOptions?.menuClass,\n ]\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs, ['onClick', 'class']),\n ...(readOnly ? {} : attrs),\n }\"\n role=\"combobox\"\n :aria-expanded=\"open\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @click=\"focusSetInputFocus()\"\n @focus=\"focusOnActivatorFocused()\"\n @keydown.enter=\"onEnter($event)\"\n @keydown.tab=\"onTab($event)\"\n @keydown.left=\"moveSelectedValueHighlight($event, false)\"\n @keydown.right=\"moveSelectedValueHighlight($event, true)\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = optionsWithSelectedHidden.length - 1\"\n >\n <span\n v-if=\"outlined || (!valueSet && !searchInputFocused)\"\n :class=\"[\n ui.label(),\n { 'pr-2': !valueSet && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <div\n data-id=\"value\"\n :class=\"ui.value()\"\n >\n <template\n v-for=\"(item, i) in value\"\n :key=\"getIdentifier(item)\"\n >\n <RuiChip\n v-if=\"chips\"\n :key=\"getTextToken(getIdentifier(item))\"\n tabindex=\"-1\"\n :size=\"dense ? 'sm' : 'md'\"\n closeable\n :class=\"{ 'leading-3': dense }\"\n clickable\n v-bind=\"chipAttrs(item, i)\"\n >\n <div class=\"flex\">\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </RuiChip>\n <div\n v-else-if=\"\n multiple\n || (!searchInputFocused && (slots['selection.prepend'] || slots.selection))\n \"\n :class=\"hideSelectionWrapper ? 'contents' : 'flex'\"\n >\n <slot\n name=\"selection.prepend\"\n :index=\"i\"\n v-bind=\"{ item }\"\n />\n <slot\n v-if=\"multiple || slots.selection\"\n :index=\"i\"\n name=\"selection\"\n v-bind=\"{ item, chipAttrs: chipAttrs(item, i) }\"\n >\n {{ getText(item) }}\n </slot>\n </div>\n </template>\n <input\n ref=\"textInput\"\n :disabled=\"disabled\"\n :value=\"internalSearch\"\n class=\"bg-transparent outline-none\"\n type=\"text\"\n :placeholder=\"usedPlaceholder\"\n :class=\"[focusInputClass, { hidden: hideSearchInput }]\"\n :aria-invalid=\"hasError\"\n aria-autocomplete=\"list\"\n @keydown.delete=\"onInputDeletePressed()\"\n @input.stop=\"updateSearchInput($event)\"\n @focus=\"focusOnInputFocused()\"\n />\n </div>\n\n <RuiButton\n v-if=\"clearable && valueSet && !disabled\"\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n color=\"error\"\n data-id=\"clear\"\n :class=\"[\n ui.clear(),\n focusAnyFocused && '!visible',\n { 'mr-2': !dense },\n ]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"18\"\n />\n </RuiButton>\n\n <span\n :class=\"ui.iconWrapper()\"\n @click=\"arrowClicked($event)\"\n >\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </div>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n </template>\n <template #default=\"{ width }\">\n <div ref=\"menuWrapperRef\">\n <div\n v-if=\"optionsWithSelectedHidden.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth, minHeight: `${menuMinHeight}px` }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div\n v-if=\"!customValue\"\n class=\"p-4\"\n data-id=\"no-data\"\n >\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
@@ -61,6 +61,9 @@ export declare const autoCompleteStyles: import("tailwind-variants").TVReturnTyp
61
61
  hasSuccess: {
62
62
  true: {};
63
63
  };
64
+ hovered: {
65
+ true: {};
66
+ };
64
67
  }, {
65
68
  fieldset: string;
66
69
  legend: string;
@@ -127,6 +130,9 @@ export declare const autoCompleteStyles: import("tailwind-variants").TVReturnTyp
127
130
  hasSuccess: {
128
131
  true: {};
129
132
  };
133
+ hovered: {
134
+ true: {};
135
+ };
130
136
  }, {
131
137
  fieldset: string;
132
138
  legend: string;
@@ -1 +1 @@
1
- {"version":3,"file":"RuiMenuSelect.js","names":[],"sources":["../../../../src/components/forms/select/RuiMenuSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { menuSelectStyles, type MenuSelectVariant } from '@/components/forms/select/menu-select-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { type KeyOfType, useDropdownMenu } from '@/composables/dropdown-menu';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiMenuSelectClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n option?: VueClassValue;\n}\n\nexport interface MenuSelectProps<TValue, TItem> {\n options: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n /** @deprecated Use `classNames.option` instead */\n optionClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: MenuSelectVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiMenuSelect',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue | undefined>({ required: true });\n\nconst {\n options,\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n hideNoData = false,\n noDataText = 'No data available',\n required = false,\n} = defineProps<MenuSelectProps<TValue, TItem>>();\n\ndefineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem | undefined;\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem | undefined }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst { focused } = useFocus(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst value = computed<TItem | undefined>({\n get: () => {\n const value = get(modelValue);\n if (keyAttr)\n return options.find(option => option[keyAttr] === value);\n return value as unknown as TItem;\n },\n set: (selected?: TItem) => {\n const selection = keyAttr && selected ? selected[keyAttr] : selected;\n set(modelValue, selection as TValue);\n },\n});\n\nfunction setValue(val: TItem): void {\n set(value, val);\n set(focused, true);\n}\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n isOpen,\n menuWidth,\n getText,\n getIdentifier,\n isActiveItem,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? (dense ? 30 : 48),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || !!get(value)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = menuSelectStyles({}).highlighted();\n\nfunction clear(): void {\n set(modelValue, undefined);\n}\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"true\"\n :full-width=\"true\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <button\n ref=\"activator\"\n :disabled=\"disabled\"\n :aria-disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs),\n ...(readOnly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.enter.prevent=\"applyHighlighted()\"\n @keydown.space.prevent=\"applyHighlighted()\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = options.length - 1\"\n >\n <span\n v-if=\"outlined || !value\"\n :class=\"[\n ui.label(),\n { 'pr-2': !value && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"value\"\n :class=\"ui.value()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: value }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: value }\"\n >\n {{ getText(value) }}\n </slot>\n </span>\n\n <span\n v-if=\"clearable && value && !disabled\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && '!visible']\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n <input\n :value=\"valueKey\"\n class=\"hidden\"\n type=\"hidden\"\n />\n </template>\n <template #default=\"{ width }\">\n <div\n v-if=\"options.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n data-id=\"no-data\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div class=\"p-4\">\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiMenuSelect.js","names":[],"sources":["../../../../src/components/forms/select/RuiMenuSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { menuSelectStyles, type MenuSelectVariant } from '@/components/forms/select/menu-select-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { type KeyOfType, useDropdownMenu } from '@/composables/dropdown-menu';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiMenuSelectClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n option?: VueClassValue;\n}\n\nexport interface MenuSelectProps<TValue, TItem> {\n options: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n /** @deprecated Use `classNames.option` instead */\n optionClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: MenuSelectVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiMenuSelect',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue | undefined>({ required: true });\n\nconst {\n options,\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n hideNoData = false,\n noDataText = 'No data available',\n required = false,\n} = defineProps<MenuSelectProps<TValue, TItem>>();\n\ndefineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem | undefined;\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem | undefined }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst { focused } = useFocus(activator);\nconst isHovered = ref<boolean>(false);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst value = computed<TItem | undefined>({\n get: () => {\n const value = get(modelValue);\n if (keyAttr)\n return options.find(option => option[keyAttr] === value);\n return value as unknown as TItem;\n },\n set: (selected?: TItem) => {\n const selection = keyAttr && selected ? selected[keyAttr] : selected;\n set(modelValue, selection as TValue);\n },\n});\n\nfunction setValue(val: TItem): void {\n set(value, val);\n set(focused, true);\n}\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n isOpen,\n menuWidth,\n getText,\n getIdentifier,\n isActiveItem,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? (dense ? 30 : 48),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || !!get(value)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = menuSelectStyles({}).highlighted();\n\nfunction clear(): void {\n set(modelValue, undefined);\n}\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"true\"\n :full-width=\"true\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <button\n ref=\"activator\"\n :disabled=\"disabled\"\n :aria-disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs),\n ...(readOnly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.enter.prevent=\"applyHighlighted()\"\n @keydown.space.prevent=\"applyHighlighted()\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = options.length - 1\"\n >\n <span\n v-if=\"outlined || !value\"\n :class=\"[\n ui.label(),\n { 'pr-2': !value && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"value\"\n :class=\"ui.value()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: value }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: value }\"\n >\n {{ getText(value) }}\n </slot>\n </span>\n\n <span\n v-if=\"clearable && value && !disabled\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && '!visible']\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n <input\n :value=\"valueKey\"\n class=\"hidden\"\n type=\"hidden\"\n />\n </template>\n <template #default=\"{ width }\">\n <div\n v-if=\"options.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n data-id=\"no-data\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div class=\"p-4\">\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
@@ -7,7 +7,7 @@ import RuiMenu_default from "../../overlays/menu/RuiMenu.js";
7
7
  import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
8
8
  import { useDropdownMenu } from "../../../composables/dropdown-menu.js";
9
9
  import { menuSelectStyles } from "./menu-select-styles.js";
10
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, guardReactiveProps, isRef, mergeModels, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, renderList, renderSlot, toDisplayString, unref, useModel, useTemplateRef, withCtx, withKeys, withModifiers } from "vue";
10
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, guardReactiveProps, isRef, mergeModels, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useModel, useTemplateRef, withCtx, withKeys, withModifiers } from "vue";
11
11
  import { useFocus } from "@vueuse/core";
12
12
  import { get as get$1, set as set$1 } from "@vueuse/shared";
13
13
  //#region src/components/forms/select/RuiMenuSelect.vue?vue&type=script&setup=true&lang.ts
@@ -91,6 +91,7 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
91
91
  const menuRef = useTemplateRef("menuRef");
92
92
  const activator = useTemplateRef("activator");
93
93
  const { focused } = useFocus(activator);
94
+ const isHovered = ref(false);
94
95
  const { hasError, hasSuccess } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
95
96
  const value = computed({
96
97
  get: () => {
@@ -129,6 +130,7 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
129
130
  outlined: get$1(outlined),
130
131
  float: get$1(float),
131
132
  opened: get$1(isOpen),
133
+ hovered: get$1(isHovered),
132
134
  dense: __props.dense,
133
135
  disabled: __props.disabled,
134
136
  readonly: __props.readOnly,
@@ -142,7 +144,7 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
142
144
  return (_ctx, _cache) => {
143
145
  return openBlock(), createBlock(RuiMenu_default, mergeProps({
144
146
  modelValue: unref(isOpen),
145
- "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
147
+ "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => isRef(isOpen) ? isOpen.value = $event : null)
146
148
  }, {
147
149
  ...unref(getRootAttrs)(_ctx.$attrs, []),
148
150
  ...__props.menuOptions
@@ -186,13 +188,15 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
186
188
  }, {
187
189
  "data-id": "activator",
188
190
  "aria-invalid": unref(hasError),
191
+ onMouseenter: _cache[1] || (_cache[1] = ($event) => isHovered.value = true),
192
+ onMouseleave: _cache[2] || (_cache[2] = ($event) => isHovered.value = false),
189
193
  onKeydown: [
190
- _cache[1] || (_cache[1] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])),
191
- _cache[2] || (_cache[2] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"])),
192
- _cache[3] || (_cache[3] = withKeys(withModifiers(($event) => unref(applyHighlighted)(), ["prevent"]), ["enter"])),
193
- _cache[4] || (_cache[4] = withKeys(withModifiers(($event) => unref(applyHighlighted)(), ["prevent"]), ["space"])),
194
- _cache[5] || (_cache[5] = withKeys(withModifiers(($event) => highlightedIndex.value = 0, ["prevent"]), ["home"])),
195
- _cache[6] || (_cache[6] = withKeys(withModifiers(($event) => highlightedIndex.value = __props.options.length - 1, ["prevent"]), ["end"]))
194
+ _cache[3] || (_cache[3] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])),
195
+ _cache[4] || (_cache[4] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"])),
196
+ _cache[5] || (_cache[5] = withKeys(withModifiers(($event) => unref(applyHighlighted)(), ["prevent"]), ["enter"])),
197
+ _cache[6] || (_cache[6] = withKeys(withModifiers(($event) => unref(applyHighlighted)(), ["prevent"]), ["space"])),
198
+ _cache[7] || (_cache[7] = withKeys(withModifiers(($event) => highlightedIndex.value = 0, ["prevent"]), ["home"])),
199
+ _cache[8] || (_cache[8] = withKeys(withModifiers(($event) => highlightedIndex.value = __props.options.length - 1, ["prevent"]), ["end"]))
196
200
  ]
197
201
  }), [
198
202
  unref(outlined) || !unref(value) ? (openBlock(), createElementBlock("span", {
@@ -244,8 +248,8 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
244
248
  width: `${width}px`,
245
249
  minWidth: unref(menuWidth)
246
250
  }]),
247
- onScroll: _cache[7] || (_cache[7] = (...args) => unref(containerProps).onScroll && unref(containerProps).onScroll(...args)),
248
- onKeydown: [_cache[8] || (_cache[8] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])), _cache[9] || (_cache[9] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"]))]
251
+ onScroll: _cache[9] || (_cache[9] = (...args) => unref(containerProps).onScroll && unref(containerProps).onScroll(...args)),
252
+ onKeydown: [_cache[10] || (_cache[10] = withKeys(withModifiers(($event) => unref(moveHighlight)(true), ["prevent"]), ["up"])), _cache[11] || (_cache[11] = withKeys(withModifiers(($event) => unref(moveHighlight)(false), ["prevent"]), ["down"]))]
249
253
  }, [createElementVNode("div", mergeProps(unref(wrapperProps), {
250
254
  ref_key: "menuRef",
251
255
  ref: menuRef
@@ -1 +1 @@
1
- {"version":3,"file":"RuiMenuSelect.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/select/RuiMenuSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { menuSelectStyles, type MenuSelectVariant } from '@/components/forms/select/menu-select-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { type KeyOfType, useDropdownMenu } from '@/composables/dropdown-menu';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiMenuSelectClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n option?: VueClassValue;\n}\n\nexport interface MenuSelectProps<TValue, TItem> {\n options: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n /** @deprecated Use `classNames.option` instead */\n optionClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: MenuSelectVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiMenuSelect',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue | undefined>({ required: true });\n\nconst {\n options,\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n hideNoData = false,\n noDataText = 'No data available',\n required = false,\n} = defineProps<MenuSelectProps<TValue, TItem>>();\n\ndefineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem | undefined;\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem | undefined }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst { focused } = useFocus(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst value = computed<TItem | undefined>({\n get: () => {\n const value = get(modelValue);\n if (keyAttr)\n return options.find(option => option[keyAttr] === value);\n return value as unknown as TItem;\n },\n set: (selected?: TItem) => {\n const selection = keyAttr && selected ? selected[keyAttr] : selected;\n set(modelValue, selection as TValue);\n },\n});\n\nfunction setValue(val: TItem): void {\n set(value, val);\n set(focused, true);\n}\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n isOpen,\n menuWidth,\n getText,\n getIdentifier,\n isActiveItem,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? (dense ? 30 : 48),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || !!get(value)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = menuSelectStyles({}).highlighted();\n\nfunction clear(): void {\n set(modelValue, undefined);\n}\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"true\"\n :full-width=\"true\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <button\n ref=\"activator\"\n :disabled=\"disabled\"\n :aria-disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs),\n ...(readOnly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.enter.prevent=\"applyHighlighted()\"\n @keydown.space.prevent=\"applyHighlighted()\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = options.length - 1\"\n >\n <span\n v-if=\"outlined || !value\"\n :class=\"[\n ui.label(),\n { 'pr-2': !value && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"value\"\n :class=\"ui.value()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: value }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: value }\"\n >\n {{ getText(value) }}\n </slot>\n </span>\n\n <span\n v-if=\"clearable && value && !disabled\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && '!visible']\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n <input\n :value=\"valueKey\"\n class=\"hidden\"\n type=\"hidden\"\n />\n </template>\n <template #default=\"{ width }\">\n <div\n v-if=\"options.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n data-id=\"no-data\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div class=\"p-4\">\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiMenuSelect.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/select/RuiMenuSelect.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { menuSelectStyles, type MenuSelectVariant } from '@/components/forms/select/menu-select-styles';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiMenu, { type MenuProps } from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { type KeyOfType, useDropdownMenu } from '@/composables/dropdown-menu';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiMenuSelectClassNames {\n root?: VueClassValue;\n label?: VueClassValue;\n menu?: VueClassValue;\n option?: VueClassValue;\n}\n\nexport interface MenuSelectProps<TValue, TItem> {\n options: TItem[];\n keyAttr?: KeyOfType<TItem, TValue extends Array<infer U> ? U : TValue>;\n textAttr?: keyof TItem;\n disabled?: boolean;\n loading?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n label?: string;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n /** @deprecated Use `classNames.label` instead */\n labelClass?: string;\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string;\n /** @deprecated Use `classNames.option` instead */\n optionClass?: string;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\n variant?: MenuSelectVariant;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n autoSelectFirst?: boolean;\n hideNoData?: boolean;\n noDataText?: string;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiMenuSelect',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue | undefined>({ required: true });\n\nconst {\n options,\n disabled = false,\n loading = false,\n readOnly = false,\n dense = false,\n clearable = false,\n hideDetails = false,\n label = 'Select',\n menuOptions,\n classNames,\n labelClass,\n menuClass,\n variant = 'default',\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n errorMessages = [],\n successMessages = [],\n autoSelectFirst = false,\n hideNoData = false,\n noDataText = 'No data available',\n required = false,\n} = defineProps<MenuSelectProps<TValue, TItem>>();\n\ndefineSlots<{\n 'activator'?: (props: {\n disabled: boolean;\n value: TItem | undefined;\n variant: string;\n readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n 'activator.label'?: (props: { value: TItem | undefined }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'item.prepend'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'item.append'?: (props: { disabled: boolean; item: TItem; active: boolean }) => any;\n 'no-data'?: () => any;\n}>();\n\nconst menuRef = useTemplateRef<HTMLDivElement>('menuRef');\nconst activator = useTemplateRef<HTMLDivElement>('activator');\nconst { focused } = useFocus(activator);\nconst isHovered = ref<boolean>(false);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst value = computed<TItem | undefined>({\n get: () => {\n const value = get(modelValue);\n if (keyAttr)\n return options.find(option => option[keyAttr] === value);\n return value as unknown as TItem;\n },\n set: (selected?: TItem) => {\n const selection = keyAttr && selected ? selected[keyAttr] : selected;\n set(modelValue, selection as TValue);\n },\n});\n\nfunction setValue(val: TItem): void {\n set(value, val);\n set(focused, true);\n}\n\nconst {\n containerProps,\n wrapperProps,\n renderedData,\n isOpen,\n menuWidth,\n getText,\n getIdentifier,\n isActiveItem,\n highlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? (dense ? 30 : 48),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\nconst float = computed<boolean>(() => (get(isOpen) || !!get(value)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\n filled: variant === 'filled',\n outlined: get(outlined),\n float: get(float),\n opened: get(isOpen),\n hovered: get(isHovered),\n dense,\n disabled,\n readonly: readOnly,\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n}));\n\nconst highlightedClass = menuSelectStyles({}).highlighted();\n\nfunction clear(): void {\n set(modelValue, undefined);\n}\n</script>\n\n<template>\n <RuiMenu\n v-model=\"isOpen\"\n v-bind=\"{ ...getRootAttrs($attrs, []), ...menuOptions }\"\n :class=\"ui.wrapper({ class: cn($attrs.class) })\"\n placement=\"bottom-start\"\n :close-on-content-click=\"true\"\n :full-width=\"true\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n :dense=\"dense\"\n :show-details=\"!hideDetails\"\n :disabled=\"disabled\"\n disable-auto-focus\n >\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, variant, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <button\n ref=\"activator\"\n :disabled=\"disabled\"\n :aria-disabled=\"disabled\"\n :aria-expanded=\"isOpen\"\n :aria-readonly=\"readOnly || undefined\"\n :aria-required=\"required || undefined\"\n :aria-busy=\"loading || undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) ?? labelClass })\"\n v-bind=\"{\n ...getNonRootAttrs($attrs),\n ...(readOnly ? {} : attrs),\n }\"\n data-id=\"activator\"\n :aria-invalid=\"hasError\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n @keydown.enter.prevent=\"applyHighlighted()\"\n @keydown.space.prevent=\"applyHighlighted()\"\n @keydown.home.prevent=\"highlightedIndex = 0\"\n @keydown.end.prevent=\"highlightedIndex = options.length - 1\"\n >\n <span\n v-if=\"outlined || !value\"\n :class=\"[\n ui.label(),\n { 'pr-2': !value && !open && outlined },\n ]\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ value }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"ui.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"value\"\n :class=\"ui.value()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: value }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: value }\"\n >\n {{ getText(value) }}\n </slot>\n </span>\n\n <span\n v-if=\"clearable && value && !disabled\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && '!visible']\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset\n v-if=\"outlined\"\n :class=\"ui.fieldset()\"\n >\n <legend :class=\"ui.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </slot>\n <input\n :value=\"valueKey\"\n class=\"hidden\"\n type=\"hidden\"\n />\n </template>\n <template #default=\"{ width }\">\n <div\n v-if=\"options.length > 0\"\n :ref=\"containerProps.ref\"\n :class=\"ui.menu({ class: cn(classNames?.menu) ?? menuClass })\"\n :style=\"[containerProps.style, { width: `${width}px`, minWidth: menuWidth }]\"\n @scroll=\"containerProps.onScroll\"\n @keydown.up.prevent=\"moveHighlight(true)\"\n @keydown.down.prevent=\"moveHighlight(false)\"\n >\n <div\n v-bind=\"wrapperProps\"\n ref=\"menuRef\"\n >\n <RuiButton\n v-for=\"{ item, _index } in renderedData\"\n :key=\"getIdentifier(item)\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled, item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </div>\n </div>\n\n <div\n v-else-if=\"!hideNoData\"\n data-id=\"no-data\"\n :style=\"{ width: `${width}px`, minWidth: menuWidth }\"\n :class=\"classNames?.menu ?? menuClass\"\n >\n <slot name=\"no-data\">\n <div class=\"p-4\">\n {{ noDataText }}\n </div>\n </slot>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
@@ -56,6 +56,9 @@ export declare const menuSelectStyles: import("tailwind-variants").TVReturnType<
56
56
  hasSuccess: {
57
57
  true: {};
58
58
  };
59
+ hovered: {
60
+ true: {};
61
+ };
59
62
  }, {
60
63
  fieldset: string;
61
64
  legend: string;
@@ -122,6 +125,9 @@ export declare const menuSelectStyles: import("tailwind-variants").TVReturnType<
122
125
  hasSuccess: {
123
126
  true: {};
124
127
  };
128
+ hovered: {
129
+ true: {};
130
+ };
125
131
  }, {
126
132
  fieldset: string;
127
133
  legend: string;
@@ -191,7 +191,7 @@ var textFieldStyles = tv({
191
191
  active: true,
192
192
  class: {
193
193
  input: "border-t-transparent",
194
- label: "!h-auto -translate-y-1/2 pl-4"
194
+ label: "!h-auto -translate-y-[0.5rem] pl-4"
195
195
  }
196
196
  },
197
197
  {
@@ -1 +1 @@
1
- {"version":3,"file":"text-field-styles.js","names":[],"sources":["../../../../src/components/forms/text-field/text-field-styles.ts"],"sourcesContent":["import { textInputBase, type TextInputVariant, underlinePseudo } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\nexport type TextFieldVariant = TextInputVariant;\n\n/**\n * tv() styles for RuiTextField. Extends textInputBase for shared\n * fieldset/legend/label/validation core.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes\n * between base and extension. Never put a class in the base slot that a\n * variant needs to override — put variant-specific classes in the variants.\n */\n\nexport const textFieldStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare base slots for type inference (extend merges classes at runtime)\n fieldset: '',\n legend: '',\n // No pt-* here — each variant sets its own padding-top\n wrapper: 'relative w-full flex items-center rounded bg-white dark:bg-transparent',\n input: [\n 'peer leading-6 text-rui-text w-full bg-transparent pr-4',\n 'outline-0 outline-none transition-all',\n 'placeholder:opacity-0 focus:placeholder:opacity-100',\n ].join(' '),\n // No border-b or display here — each variant sets its own\n label: [\n // Use arbitrary `text-[1rem]` instead of `text-base` — the named class\n // bundles `line-height: 1.5rem`, and the consumer's later-loaded\n // `.text-base` rule would override our `leading-*` per variant. The\n // arbitrary form emits font-size only, so `leading-*` stays authoritative.\n 'left-0 text-[1rem] pointer-events-none',\n 'absolute top-0 h-full w-full select-none',\n // Dynamic padding via CSS variables\n '[padding-left:calc(var(--x-padding,0px)+var(--prepend-w,0px))]',\n '[padding-right:calc(var(--x-padding,0px)+var(--append-w,0px))]',\n // CSS-only autofill fallback (before JS catches up)\n 'peer-autofill:text-[0.75rem] peer-autofill:leading-tight',\n ].join(' '),\n labelText: 'truncate transition-all duration-75',\n inputWrapper: 'flex flex-1 overflow-hidden',\n prepend: 'flex items-center gap-1 shrink-0',\n append: 'flex items-center gap-1 shrink-0',\n icon: 'text-black/[0.54] dark:text-white/[0.56]',\n details: 'pt-1 px-4',\n required: 'text-rui-error',\n clearButton: '!p-2',\n },\n variants: {\n variant: {\n default: {\n wrapper: 'pt-3',\n input: 'py-1.5',\n label: `flex leading-[3.75] ${underlinePseudo}`,\n prepend: 'pr-3',\n append: 'pl-3',\n },\n filled: {\n input: 'px-4 py-4',\n label: `flex leading-[3.5] [--x-padding:1rem] rounded-t bg-black/[0.06] dark:bg-white/[0.09] ${underlinePseudo}`,\n prepend: 'pl-3',\n append: 'pr-3',\n },\n outlined: {\n inputWrapper: '!overflow-visible',\n input: 'px-4 py-4',\n label: [\n 'flex leading-[3.5] [--x-padding:1rem]',\n 'border-0 border-transparent',\n 'after:content-none',\n ].join(' '),\n fieldset: '!mt-0 !h-full',\n prepend: 'pl-3',\n append: 'pr-3',\n },\n },\n dense: {\n true: {},\n },\n hovered: {\n true: {\n label: 'border-black dark:border-white',\n },\n },\n focused: {\n true: {},\n },\n active: {\n true: {\n label: [\n 'text-[0.75rem] leading-tight',\n '[padding-left:var(--x-padding,0px)]',\n '[padding-right:var(--x-padding,0px)]',\n ].join(' '),\n },\n },\n noLabel: {\n true: {},\n },\n showLabel: {\n true: {},\n },\n textColor: {\n primary: { prepend: 'text-rui-primary', append: 'text-rui-primary', input: 'text-rui-primary', icon: 'text-rui-primary' },\n secondary: { prepend: 'text-rui-secondary', append: 'text-rui-secondary', input: 'text-rui-secondary', icon: 'text-rui-secondary' },\n error: { prepend: 'text-rui-error', append: 'text-rui-error', input: 'text-rui-error', icon: 'text-rui-error' },\n warning: { prepend: 'text-rui-warning', append: 'text-rui-warning', input: 'text-rui-warning', icon: 'text-rui-warning' },\n info: { prepend: 'text-rui-info', append: 'text-rui-info', input: 'text-rui-info', icon: 'text-rui-info' },\n success: { prepend: 'text-rui-success', append: 'text-rui-success', input: 'text-rui-success', icon: 'text-rui-success' },\n },\n validation: {\n error: {\n input: '!border-rui-error',\n label: '!text-rui-error !after:border-rui-error',\n },\n success: {\n input: '!border-rui-success',\n label: '!text-rui-success !after:border-rui-success',\n },\n },\n },\n compoundVariants: [\n // --- Default variant ---\n { variant: 'default', focused: true, class: { label: 'after:scale-x-100' } },\n { variant: 'default', dense: true, class: { input: 'py-1', label: 'leading-[3.5]' } },\n // Without a label, the wrapper's `pt-3` floating-label reserve serves no\n // purpose and leaves the field ~4–12px taller than an equivalent\n // RuiMenuSelect dense activator. Strip it and tighten the input padding\n // so the underline sits at a matching baseline (40px non-dense, 32px\n // dense) — these match min-h-10 and !min-h-8 of the menu-select\n // activator.\n { variant: 'default', noLabel: true, class: { wrapper: '!pt-0', input: 'py-2' } },\n { variant: 'default', noLabel: true, dense: true, class: { input: 'py-1' } },\n\n // --- Filled variant ---\n { variant: 'filled', focused: true, class: { label: 'bg-black/[0.09] dark:bg-white/[0.13]' } },\n { variant: 'filled', active: true, class: { label: 'leading-[1.5]' } },\n { variant: 'filled', dense: true, class: { input: 'pt-5 pb-1', label: 'leading-[3]' } },\n { variant: 'filled', dense: true, active: true, class: { label: 'leading-[2.25]' } },\n { variant: 'filled', noLabel: true, class: { input: 'py-4' } },\n { variant: 'filled', noLabel: true, dense: true, class: { input: 'py-3' } },\n\n // --- Outlined variant ---\n { variant: 'outlined', active: true, class: {\n input: 'border-t-transparent',\n label: '!h-auto -translate-y-1/2 pl-4',\n } },\n { variant: 'outlined', dense: true, class: { input: 'py-2', label: 'leading-[2.5]' } },\n\n // --- Focus label color (per color) ---\n { focused: true, color: 'primary', class: { label: 'text-rui-primary' } },\n { focused: true, color: 'secondary', class: { label: 'text-rui-secondary' } },\n { focused: true, color: 'error', class: { label: 'text-rui-error' } },\n { focused: true, color: 'warning', class: { label: 'text-rui-warning' } },\n { focused: true, color: 'info', class: { label: 'text-rui-info' } },\n { focused: true, color: 'success', class: { label: 'text-rui-success' } },\n\n // --- Label after border color (always applied when color set) ---\n { color: 'primary', class: { label: 'after:border-rui-primary' } },\n { color: 'secondary', class: { label: 'after:border-rui-secondary' } },\n { color: 'error', class: { label: 'after:border-rui-error' } },\n { color: 'warning', class: { label: 'after:border-rui-warning' } },\n { color: 'info', class: { label: 'after:border-rui-info' } },\n { color: 'success', class: { label: 'after:border-rui-success' } },\n ],\n defaultVariants: {\n variant: 'default',\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"text-field-styles.js","names":[],"sources":["../../../../src/components/forms/text-field/text-field-styles.ts"],"sourcesContent":["import { textInputBase, type TextInputVariant, underlinePseudo } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\nexport type TextFieldVariant = TextInputVariant;\n\n/**\n * tv() styles for RuiTextField. Extends textInputBase for shared\n * fieldset/legend/label/validation core.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes\n * between base and extension. Never put a class in the base slot that a\n * variant needs to override — put variant-specific classes in the variants.\n */\n\nexport const textFieldStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare base slots for type inference (extend merges classes at runtime)\n fieldset: '',\n legend: '',\n // No pt-* here — each variant sets its own padding-top\n wrapper: 'relative w-full flex items-center rounded bg-white dark:bg-transparent',\n input: [\n 'peer leading-6 text-rui-text w-full bg-transparent pr-4',\n 'outline-0 outline-none transition-all',\n 'placeholder:opacity-0 focus:placeholder:opacity-100',\n ].join(' '),\n // No border-b or display here — each variant sets its own\n label: [\n // Use arbitrary `text-[1rem]` instead of `text-base` — the named class\n // bundles `line-height: 1.5rem`, and the consumer's later-loaded\n // `.text-base` rule would override our `leading-*` per variant. The\n // arbitrary form emits font-size only, so `leading-*` stays authoritative.\n 'left-0 text-[1rem] pointer-events-none',\n 'absolute top-0 h-full w-full select-none',\n // Dynamic padding via CSS variables\n '[padding-left:calc(var(--x-padding,0px)+var(--prepend-w,0px))]',\n '[padding-right:calc(var(--x-padding,0px)+var(--append-w,0px))]',\n // CSS-only autofill fallback (before JS catches up)\n 'peer-autofill:text-[0.75rem] peer-autofill:leading-tight',\n ].join(' '),\n labelText: 'truncate transition-all duration-75',\n inputWrapper: 'flex flex-1 overflow-hidden',\n prepend: 'flex items-center gap-1 shrink-0',\n append: 'flex items-center gap-1 shrink-0',\n icon: 'text-black/[0.54] dark:text-white/[0.56]',\n details: 'pt-1 px-4',\n required: 'text-rui-error',\n clearButton: '!p-2',\n },\n variants: {\n variant: {\n default: {\n wrapper: 'pt-3',\n input: 'py-1.5',\n label: `flex leading-[3.75] ${underlinePseudo}`,\n prepend: 'pr-3',\n append: 'pl-3',\n },\n filled: {\n input: 'px-4 py-4',\n label: `flex leading-[3.5] [--x-padding:1rem] rounded-t bg-black/[0.06] dark:bg-white/[0.09] ${underlinePseudo}`,\n prepend: 'pl-3',\n append: 'pr-3',\n },\n outlined: {\n inputWrapper: '!overflow-visible',\n input: 'px-4 py-4',\n label: [\n 'flex leading-[3.5] [--x-padding:1rem]',\n 'border-0 border-transparent',\n 'after:content-none',\n ].join(' '),\n fieldset: '!mt-0 !h-full',\n prepend: 'pl-3',\n append: 'pr-3',\n },\n },\n dense: {\n true: {},\n },\n hovered: {\n true: {\n label: 'border-black dark:border-white',\n },\n },\n focused: {\n true: {},\n },\n active: {\n true: {\n label: [\n 'text-[0.75rem] leading-tight',\n '[padding-left:var(--x-padding,0px)]',\n '[padding-right:var(--x-padding,0px)]',\n ].join(' '),\n },\n },\n noLabel: {\n true: {},\n },\n showLabel: {\n true: {},\n },\n textColor: {\n primary: { prepend: 'text-rui-primary', append: 'text-rui-primary', input: 'text-rui-primary', icon: 'text-rui-primary' },\n secondary: { prepend: 'text-rui-secondary', append: 'text-rui-secondary', input: 'text-rui-secondary', icon: 'text-rui-secondary' },\n error: { prepend: 'text-rui-error', append: 'text-rui-error', input: 'text-rui-error', icon: 'text-rui-error' },\n warning: { prepend: 'text-rui-warning', append: 'text-rui-warning', input: 'text-rui-warning', icon: 'text-rui-warning' },\n info: { prepend: 'text-rui-info', append: 'text-rui-info', input: 'text-rui-info', icon: 'text-rui-info' },\n success: { prepend: 'text-rui-success', append: 'text-rui-success', input: 'text-rui-success', icon: 'text-rui-success' },\n },\n validation: {\n error: {\n input: '!border-rui-error',\n label: '!text-rui-error !after:border-rui-error',\n },\n success: {\n input: '!border-rui-success',\n label: '!text-rui-success !after:border-rui-success',\n },\n },\n },\n compoundVariants: [\n // --- Default variant ---\n { variant: 'default', focused: true, class: { label: 'after:scale-x-100' } },\n { variant: 'default', dense: true, class: { input: 'py-1', label: 'leading-[3.5]' } },\n // Without a label, the wrapper's `pt-3` floating-label reserve serves no\n // purpose and leaves the field ~4–12px taller than an equivalent\n // RuiMenuSelect dense activator. Strip it and tighten the input padding\n // so the underline sits at a matching baseline (40px non-dense, 32px\n // dense) — these match min-h-10 and !min-h-8 of the menu-select\n // activator.\n { variant: 'default', noLabel: true, class: { wrapper: '!pt-0', input: 'py-2' } },\n { variant: 'default', noLabel: true, dense: true, class: { input: 'py-1' } },\n\n // --- Filled variant ---\n { variant: 'filled', focused: true, class: { label: 'bg-black/[0.09] dark:bg-white/[0.13]' } },\n { variant: 'filled', active: true, class: { label: 'leading-[1.5]' } },\n { variant: 'filled', dense: true, class: { input: 'pt-5 pb-1', label: 'leading-[3]' } },\n { variant: 'filled', dense: true, active: true, class: { label: 'leading-[2.25]' } },\n { variant: 'filled', noLabel: true, class: { input: 'py-4' } },\n { variant: 'filled', noLabel: true, dense: true, class: { input: 'py-3' } },\n\n // --- Outlined variant ---\n { variant: 'outlined', active: true, class: {\n input: 'border-t-transparent',\n // Use a fixed translate in rem (≈50% of the active label's\n // 0.9375rem height — text-[0.75rem] × leading-tight). A percentage\n // translate gets recomputed against the *current* label height,\n // which jumps from 0.9375rem to the input's full height the moment\n // !h-auto is removed on blur — producing a transient transform far\n // larger than the floated value and a visible upward overshoot\n // before the transition settles. Anchoring in rem (rather than %)\n // keeps the start/end values consistent across the height swap and\n // scales with the root font-size.\n label: '!h-auto -translate-y-[0.5rem] pl-4',\n } },\n { variant: 'outlined', dense: true, class: { input: 'py-2', label: 'leading-[2.5]' } },\n\n // --- Focus label color (per color) ---\n { focused: true, color: 'primary', class: { label: 'text-rui-primary' } },\n { focused: true, color: 'secondary', class: { label: 'text-rui-secondary' } },\n { focused: true, color: 'error', class: { label: 'text-rui-error' } },\n { focused: true, color: 'warning', class: { label: 'text-rui-warning' } },\n { focused: true, color: 'info', class: { label: 'text-rui-info' } },\n { focused: true, color: 'success', class: { label: 'text-rui-success' } },\n\n // --- Label after border color (always applied when color set) ---\n { color: 'primary', class: { label: 'after:border-rui-primary' } },\n { color: 'secondary', class: { label: 'after:border-rui-secondary' } },\n { color: 'error', class: { label: 'after:border-rui-error' } },\n { color: 'warning', class: { label: 'after:border-rui-warning' } },\n { color: 'info', class: { label: 'after:border-rui-info' } },\n { color: 'success', class: { label: 'after:border-rui-success' } },\n ],\n defaultVariants: {\n variant: 'default',\n },\n});\n"],"mappings":"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"}
@@ -225,6 +225,9 @@ export declare const activatorStyles: import("tailwind-variants").TVReturnType<{
225
225
  hasSuccess: {
226
226
  true: {};
227
227
  };
228
+ hovered: {
229
+ true: {};
230
+ };
228
231
  }, {
229
232
  fieldset: string;
230
233
  legend: string;
@@ -35,7 +35,8 @@ var textInputBase = tv({
35
35
  "absolute w-full min-w-0 h-[calc(100%+0.5rem)] top-0 left-0",
36
36
  "rounded pointer-events-none px-2 transition-all -mt-2",
37
37
  "border border-black/[0.23]",
38
- "dark:border-white/[0.23]"
38
+ "dark:border-white/[0.23]",
39
+ "transform-gpu"
39
40
  ].join(" "),
40
41
  legend: "invisible text-[0.75rem] truncate [max-width:calc(100%-1rem)] leading-[0]"
41
42
  },
@@ -162,7 +163,8 @@ var activatorStyles = tv({
162
163
  opened: { true: { icon: "rotate-180" } },
163
164
  active: { true: { highlighted: "!bg-rui-grey-300 dark:!bg-rui-grey-700" } },
164
165
  hasError: { true: {} },
165
- hasSuccess: { true: {} }
166
+ hasSuccess: { true: {} },
167
+ hovered: { true: {} }
166
168
  },
167
169
  compoundVariants: [
168
170
  {
@@ -1 +1 @@
1
- {"version":3,"file":"text-input-styles.js","names":[],"sources":["../../../src/components/forms/text-input-styles.ts"],"sourcesContent":["import { tv } from '@/utils/tv';\n\nexport const TextInputVariant = {\n default: 'default',\n filled: 'filled',\n outlined: 'outlined',\n} as const;\n\nexport type TextInputVariant = (typeof TextInputVariant)[keyof typeof TextInputVariant];\n\n/**\n * Shared underline pseudo-element classes for default and filled variants.\n * Used by TextField and TextArea label slots.\n */\nexport const underlinePseudo = [\n 'border-b border-black/[0.42] dark:border-white/[0.42]',\n 'after:content-[\\'\\'] after:absolute after:bottom-0 after:left-0 after:block after:w-full',\n 'after:scale-x-0 after:border-b-2 after:mb-[-1px] after:transition-transform after:duration-300',\n 'after:border-black dark:after:border-white',\n].join(' ');\n\n/**\n * Shared base tv() for all text-input-family components.\n * Extended by: TextField, TextArea, MenuSelect, AutoComplete, DateTimePicker.\n *\n * Provides the common core: floating label, fieldset/legend (outlined),\n * validation colors, disabled state, dark mode, and focus color.\n *\n * ## State approach (JS-driven for all 5 components)\n *\n * - `focused`: from useFocus (Group A) or computed from isOpen (Group B)\n * - `active`: focused || hasValue — drives label float\n * - `hovered`: mouseenter/mouseleave ref\n *\n * ## Legend content\n *\n * The legend's `after:content` uses CSS variable `--rui-legend`.\n * Bind via `:style=\"{ '--rui-legend': labelWithQuote }\"` on the legend element.\n */\nexport const textInputBase = tv({\n slots: {\n label: 'text-rui-text-secondary transition-all duration-75',\n fieldset: [\n 'absolute w-full min-w-0 h-[calc(100%+0.5rem)] top-0 left-0',\n 'rounded pointer-events-none px-2 transition-all -mt-2',\n 'border border-black/[0.23]',\n 'dark:border-white/[0.23]',\n ].join(' '),\n legend: 'invisible text-[0.75rem] truncate [max-width:calc(100%-1rem)] leading-[0]',\n },\n variants: {\n focused: {\n true: {\n fieldset: '!border-2',\n },\n },\n hovered: {\n true: {\n fieldset: 'border-black dark:border-white',\n },\n },\n disabled: {\n true: {\n fieldset: '!border-dotted !border-black/[0.23] dark:!border-white/[0.23]',\n label: 'text-rui-text-disabled',\n },\n },\n active: {\n true: {},\n },\n showLabel: {\n true: {},\n },\n validation: {\n error: {\n fieldset: '!border-rui-error',\n label: '!text-rui-error',\n },\n success: {\n fieldset: '!border-rui-success',\n label: '!text-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n // Legend padding only when label is floated (active + has label)\n { showLabel: true, active: true, class: { legend: 'px-2' } },\n // Focused + color → fieldset border takes the color\n { focused: true, color: 'primary', class: { fieldset: '!border-rui-primary' } },\n { focused: true, color: 'secondary', class: { fieldset: '!border-rui-secondary' } },\n { focused: true, color: 'error', class: { fieldset: '!border-rui-error' } },\n { focused: true, color: 'warning', class: { fieldset: '!border-rui-warning' } },\n { focused: true, color: 'info', class: { fieldset: '!border-rui-info' } },\n { focused: true, color: 'success', class: { fieldset: '!border-rui-success' } },\n ],\n defaultVariants: {\n color: 'primary',\n },\n});\n\n/**\n * Shared tv() styles for the activator-based components (Group B):\n * MenuSelect, AutoComplete, DateTimePicker.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes.\n * Never put a class in the base slot that a variant needs to override.\n *\n * State-driven via JS refs: `outlined`, `float` (open || hasValue),\n * `opened`, `disabled`, `readonly`, `dense`.\n */\nexport const activatorStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare base slots for type inference\n fieldset: '',\n legend: '',\n // `w-full inline-flex flex-col` so the activator fills its parent\n // regardless of context (block, flex-row, grid). A consumer-passed\n // width utility like `w-[20rem]` would normally collide with `w-full`\n // on the same element and lose to cascade order; RuiAutoComplete /\n // RuiMenuSelect / RuiDateTimePicker route consumer classes through\n // `ui.wrapper({ class })` so tailwind-variants' twMerge deduplicates\n // and the consumer's width wins.\n wrapper: 'w-full inline-flex flex-col',\n activator: [\n 'group relative inline-flex items-center w-full',\n 'outline-none focus:outline-none focus-within:outline-none cursor-pointer',\n 'min-h-14 pl-4 py-2 pr-8 rounded',\n 'm-0 transition-all text-body-1 text-left',\n 'dark:text-rui-text',\n ].join(' '),\n label: [\n 'text-rui-text-secondary [max-width:calc(100%-2.5rem)]',\n 'block truncate transition-all duration-75',\n ].join(' '),\n value: 'w-full block truncate transition-all duration-75',\n clear: 'ml-auto shrink-0 invisible group-hover:!visible',\n menu: 'overflow-y-auto max-h-60 min-w-[2.5rem]',\n highlighted: '!bg-rui-grey-200 dark:!bg-rui-grey-800',\n progress: 'absolute left-0 bottom-0 w-full',\n icon: 'text-rui-text transition',\n iconWrapper: 'flex items-center justify-end absolute right-3 top-px bottom-0',\n required: 'text-rui-error',\n },\n variants: {\n dense: {\n true: {\n activator: 'py-1.5 min-h-10',\n },\n },\n disabled: {\n true: {\n activator: 'opacity-65 text-rui-text-disabled active:text-rui-text-disabled cursor-default pointer-events-none',\n },\n },\n readonly: {\n true: {\n activator: 'opacity-80 pointer-events-none cursor-default bg-gray-50 dark:bg-white/10',\n },\n },\n filled: {\n true: {\n activator: [\n '!rounded-t !rounded-b-none !bg-black/[0.06]',\n '!hover:bg-black/[0.09] !focus-within:bg-black/[0.09]',\n 'dark:!bg-white/[0.09]',\n 'dark:!hover:bg-white/[0.13] dark:!focus-within:bg-white/[0.13]',\n underlinePseudo,\n ].join(' '),\n },\n },\n outlined: {\n true: {\n activator: 'bg-white dark:bg-transparent border-none hover:border-none',\n label: 'absolute',\n fieldset: '!mt-0 !h-full',\n },\n false: {\n activator: `!rounded-none ${underlinePseudo}`,\n },\n },\n float: {\n true: {\n label: '-translate-y-2 top-0 text-[0.75rem] leading-4',\n },\n },\n opened: {\n true: {\n icon: 'rotate-180',\n },\n },\n active: {\n true: {\n highlighted: '!bg-rui-grey-300 dark:!bg-rui-grey-700',\n },\n },\n hasError: {\n true: {},\n },\n hasSuccess: {\n true: {},\n },\n },\n compoundVariants: [\n // Legend padding when label is floated\n { float: true, class: { legend: 'px-2' } },\n\n // Non-outlined + opened → underline scales up\n { outlined: false, opened: true, class: { activator: 'after:scale-x-100 after:border-rui-primary' } },\n\n // Non-outlined + error → underline color\n { outlined: false, hasError: true, class: { activator: 'after:scale-x-100 after:!border-rui-error' } },\n\n // Non-outlined + success → underline color\n { outlined: false, hasSuccess: true, class: { activator: 'after:scale-x-100 after:!border-rui-success' } },\n\n // Non-outlined + disabled in dark mode\n { outlined: false, disabled: true, class: { activator: 'dark:bg-white/10' } },\n\n // Filled + disabled\n { filled: true, disabled: true, class: { activator: 'bg-black/[0.03] dark:bg-white/[0.05]' } },\n\n // Outlined + hovered → fieldset border\n { outlined: true, hovered: true, class: { fieldset: 'border-black dark:border-white' } },\n\n // Outlined + opened/focused → primary border\n { outlined: true, opened: true, class: {\n fieldset: '!border-rui-primary !border-2',\n label: 'text-rui-primary',\n } },\n\n // Outlined + error → fieldset + label\n { outlined: true, hasError: true, class: {\n fieldset: '!border-rui-error',\n label: '!text-rui-error',\n } },\n // Outlined + success → fieldset + label\n { outlined: true, hasSuccess: true, class: {\n fieldset: '!border-rui-success',\n label: '!text-rui-success',\n } },\n\n // Outlined + disabled → dotted fieldset\n { outlined: true, disabled: true, class: {\n fieldset: '!border-dotted !border-black/[0.23] dark:!border-white/[0.23]',\n } },\n\n // Float + opened → label color\n { float: true, opened: true, class: { label: 'text-rui-primary' } },\n ],\n defaultVariants: {\n filled: false,\n outlined: false,\n dense: false,\n disabled: false,\n readonly: false,\n float: false,\n opened: false,\n },\n});\n"],"mappings":";;;;;;AAcA,IAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACD,CAAC,KAAK,IAAI;;;;;;;;;;;;;;;;;;;AAoBX,IAAa,gBAAgB,GAAG;CAC9B,OAAO;EACL,OAAO;EACP,UAAU;GACR;GACA;GACA;GACA;GACD,CAAC,KAAK,IAAI;EACX,QAAQ;EACT;CACD,UAAU;EACR,SAAS,EACP,MAAM,EACJ,UAAU,aACX,EACF;EACD,SAAS,EACP,MAAM,EACJ,UAAU,kCACX,EACF;EACD,UAAU,EACR,MAAM;GACJ,UAAU;GACV,OAAO;GACR,EACF;EACD,QAAQ,EACN,MAAM,EAAE,EACT;EACD,WAAW,EACT,MAAM,EAAE,EACT;EACD,YAAY;GACV,OAAO;IACL,UAAU;IACV,OAAO;IACR;GACD,SAAS;IACP,UAAU;IACV,OAAO;IACR;GACF;EACD,OAAO;GACL,SAAS,EAAE;GACX,WAAW,EAAE;GACb,OAAO,EAAE;GACT,SAAS,EAAE;GACX,MAAM,EAAE;GACR,SAAS,EAAE;GACZ;EACF;CACD,kBAAkB;EAEhB;GAAE,WAAW;GAAM,QAAQ;GAAM,OAAO,EAAE,QAAQ,QAAQ;GAAE;EAE5D;GAAE,SAAS;GAAM,OAAO;GAAW,OAAO,EAAE,UAAU,uBAAuB;GAAE;EAC/E;GAAE,SAAS;GAAM,OAAO;GAAa,OAAO,EAAE,UAAU,yBAAyB;GAAE;EACnF;GAAE,SAAS;GAAM,OAAO;GAAS,OAAO,EAAE,UAAU,qBAAqB;GAAE;EAC3E;GAAE,SAAS;GAAM,OAAO;GAAW,OAAO,EAAE,UAAU,uBAAuB;GAAE;EAC/E;GAAE,SAAS;GAAM,OAAO;GAAQ,OAAO,EAAE,UAAU,oBAAoB;GAAE;EACzE;GAAE,SAAS;GAAM,OAAO;GAAW,OAAO,EAAE,UAAU,uBAAuB;GAAE;EAChF;CACD,iBAAiB,EACf,OAAO,WACR;CACF,CAAC;;;;;;;;;;;AAYF,IAAa,kBAAkB,GAAG;CAChC,QAAQ;CACR,OAAO;EAEL,UAAU;EACV,QAAQ;EAQR,SAAS;EACT,WAAW;GACT;GACA;GACA;GACA;GACA;GACD,CAAC,KAAK,IAAI;EACX,OAAO,CACL,yDACA,4CACD,CAAC,KAAK,IAAI;EACX,OAAO;EACP,OAAO;EACP,MAAM;EACN,aAAa;EACb,UAAU;EACV,MAAM;EACN,aAAa;EACb,UAAU;EACX;CACD,UAAU;EACR,OAAO,EACL,MAAM,EACJ,WAAW,mBACZ,EACF;EACD,UAAU,EACR,MAAM,EACJ,WAAW,sGACZ,EACF;EACD,UAAU,EACR,MAAM,EACJ,WAAW,6EACZ,EACF;EACD,QAAQ,EACN,MAAM,EACJ,WAAW;GACT;GACA;GACA;GACA;GACA;GACD,CAAC,KAAK,IAAI,EACZ,EACF;EACD,UAAU;GACR,MAAM;IACJ,WAAW;IACX,OAAO;IACP,UAAU;IACX;GACD,OAAO,EACL,WAAW,iBAAiB,mBAC7B;GACF;EACD,OAAO,EACL,MAAM,EACJ,OAAO,iDACR,EACF;EACD,QAAQ,EACN,MAAM,EACJ,MAAM,cACP,EACF;EACD,QAAQ,EACN,MAAM,EACJ,aAAa,0CACd,EACF;EACD,UAAU,EACR,MAAM,EAAE,EACT;EACD,YAAY,EACV,MAAM,EAAE,EACT;EACF;CACD,kBAAkB;EAEhB;GAAE,OAAO;GAAM,OAAO,EAAE,QAAQ,QAAQ;GAAE;EAG1C;GAAE,UAAU;GAAO,QAAQ;GAAM,OAAO,EAAE,WAAW,8CAA8C;GAAE;EAGrG;GAAE,UAAU;GAAO,UAAU;GAAM,OAAO,EAAE,WAAW,6CAA6C;GAAE;EAGtG;GAAE,UAAU;GAAO,YAAY;GAAM,OAAO,EAAE,WAAW,+CAA+C;GAAE;EAG1G;GAAE,UAAU;GAAO,UAAU;GAAM,OAAO,EAAE,WAAW,oBAAoB;GAAE;EAG7E;GAAE,QAAQ;GAAM,UAAU;GAAM,OAAO,EAAE,WAAW,wCAAwC;GAAE;EAG9F;GAAE,UAAU;GAAM,SAAS;GAAM,OAAO,EAAE,UAAU,kCAAkC;GAAE;EAGxF;GAAE,UAAU;GAAM,QAAQ;GAAM,OAAO;IACrC,UAAU;IACV,OAAO;IACR;GAAE;EAGH;GAAE,UAAU;GAAM,UAAU;GAAM,OAAO;IACvC,UAAU;IACV,OAAO;IACR;GAAE;EAEH;GAAE,UAAU;GAAM,YAAY;GAAM,OAAO;IACzC,UAAU;IACV,OAAO;IACR;GAAE;EAGH;GAAE,UAAU;GAAM,UAAU;GAAM,OAAO,EACvC,UAAU,iEACX;GAAE;EAGH;GAAE,OAAO;GAAM,QAAQ;GAAM,OAAO,EAAE,OAAO,oBAAoB;GAAE;EACpE;CACD,iBAAiB;EACf,QAAQ;EACR,UAAU;EACV,OAAO;EACP,UAAU;EACV,UAAU;EACV,OAAO;EACP,QAAQ;EACT;CACF,CAAC"}
1
+ {"version":3,"file":"text-input-styles.js","names":[],"sources":["../../../src/components/forms/text-input-styles.ts"],"sourcesContent":["import { tv } from '@/utils/tv';\n\nexport const TextInputVariant = {\n default: 'default',\n filled: 'filled',\n outlined: 'outlined',\n} as const;\n\nexport type TextInputVariant = (typeof TextInputVariant)[keyof typeof TextInputVariant];\n\n/**\n * Shared underline pseudo-element classes for default and filled variants.\n * Used by TextField and TextArea label slots.\n */\nexport const underlinePseudo = [\n 'border-b border-black/[0.42] dark:border-white/[0.42]',\n 'after:content-[\\'\\'] after:absolute after:bottom-0 after:left-0 after:block after:w-full',\n 'after:scale-x-0 after:border-b-2 after:mb-[-1px] after:transition-transform after:duration-300',\n 'after:border-black dark:after:border-white',\n].join(' ');\n\n/**\n * Shared base tv() for all text-input-family components.\n * Extended by: TextField, TextArea, MenuSelect, AutoComplete, DateTimePicker.\n *\n * Provides the common core: floating label, fieldset/legend (outlined),\n * validation colors, disabled state, dark mode, and focus color.\n *\n * ## State approach (JS-driven for all 5 components)\n *\n * - `focused`: from useFocus (Group A) or computed from isOpen (Group B)\n * - `active`: focused || hasValue — drives label float\n * - `hovered`: mouseenter/mouseleave ref\n *\n * ## Legend content\n *\n * The legend's `after:content` uses CSS variable `--rui-legend`.\n * Bind via `:style=\"{ '--rui-legend': labelWithQuote }\"` on the legend element.\n */\nexport const textInputBase = tv({\n slots: {\n label: 'text-rui-text-secondary transition-all duration-75',\n fieldset: [\n 'absolute w-full min-w-0 h-[calc(100%+0.5rem)] top-0 left-0',\n 'rounded pointer-events-none px-2 transition-all -mt-2',\n 'border border-black/[0.23]',\n 'dark:border-white/[0.23]',\n // Force the fieldset onto its own GPU compositing layer so the\n // focused border is rasterized on integer pixel boundaries. Without\n // this, at fractional y-coordinates with non-integer device pixel\n // ratios (e.g. DPR 1.25), Chromium anti-aliases the 1.6px-2px focus\n // border across two physical pixel rows behind the floated label,\n // appearing as \"two thin lines crossing the label\". translateZ(0)\n // promotes to a layer; the layer's raster snaps to integer pixels.\n 'transform-gpu',\n ].join(' '),\n legend: 'invisible text-[0.75rem] truncate [max-width:calc(100%-1rem)] leading-[0]',\n },\n variants: {\n focused: {\n true: {\n fieldset: '!border-2',\n },\n },\n hovered: {\n true: {\n fieldset: 'border-black dark:border-white',\n },\n },\n disabled: {\n true: {\n fieldset: '!border-dotted !border-black/[0.23] dark:!border-white/[0.23]',\n label: 'text-rui-text-disabled',\n },\n },\n active: {\n true: {},\n },\n showLabel: {\n true: {},\n },\n validation: {\n error: {\n fieldset: '!border-rui-error',\n label: '!text-rui-error',\n },\n success: {\n fieldset: '!border-rui-success',\n label: '!text-rui-success',\n },\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n },\n compoundVariants: [\n // Legend padding only when label is floated (active + has label)\n { showLabel: true, active: true, class: { legend: 'px-2' } },\n // Focused + color → fieldset border takes the color\n { focused: true, color: 'primary', class: { fieldset: '!border-rui-primary' } },\n { focused: true, color: 'secondary', class: { fieldset: '!border-rui-secondary' } },\n { focused: true, color: 'error', class: { fieldset: '!border-rui-error' } },\n { focused: true, color: 'warning', class: { fieldset: '!border-rui-warning' } },\n { focused: true, color: 'info', class: { fieldset: '!border-rui-info' } },\n { focused: true, color: 'success', class: { fieldset: '!border-rui-success' } },\n ],\n defaultVariants: {\n color: 'primary',\n },\n});\n\n/**\n * Shared tv() styles for the activator-based components (Group B):\n * MenuSelect, AutoComplete, DateTimePicker.\n *\n * IMPORTANT: tv() extend does NOT deduplicate conflicting Tailwind classes.\n * Never put a class in the base slot that a variant needs to override.\n *\n * State-driven via JS refs: `outlined`, `float` (open || hasValue),\n * `opened`, `disabled`, `readonly`, `dense`.\n */\nexport const activatorStyles = tv({\n extend: textInputBase,\n slots: {\n // Re-declare base slots for type inference\n fieldset: '',\n legend: '',\n // `w-full inline-flex flex-col` so the activator fills its parent\n // regardless of context (block, flex-row, grid). A consumer-passed\n // width utility like `w-[20rem]` would normally collide with `w-full`\n // on the same element and lose to cascade order; RuiAutoComplete /\n // RuiMenuSelect / RuiDateTimePicker route consumer classes through\n // `ui.wrapper({ class })` so tailwind-variants' twMerge deduplicates\n // and the consumer's width wins.\n wrapper: 'w-full inline-flex flex-col',\n activator: [\n 'group relative inline-flex items-center w-full',\n 'outline-none focus:outline-none focus-within:outline-none cursor-pointer',\n 'min-h-14 pl-4 py-2 pr-8 rounded',\n 'm-0 transition-all text-body-1 text-left',\n 'dark:text-rui-text',\n ].join(' '),\n label: [\n 'text-rui-text-secondary [max-width:calc(100%-2.5rem)]',\n 'block truncate transition-all duration-75',\n ].join(' '),\n value: 'w-full block truncate transition-all duration-75',\n clear: 'ml-auto shrink-0 invisible group-hover:!visible',\n menu: 'overflow-y-auto max-h-60 min-w-[2.5rem]',\n highlighted: '!bg-rui-grey-200 dark:!bg-rui-grey-800',\n progress: 'absolute left-0 bottom-0 w-full',\n icon: 'text-rui-text transition',\n iconWrapper: 'flex items-center justify-end absolute right-3 top-px bottom-0',\n required: 'text-rui-error',\n },\n variants: {\n dense: {\n true: {\n activator: 'py-1.5 min-h-10',\n },\n },\n disabled: {\n true: {\n activator: 'opacity-65 text-rui-text-disabled active:text-rui-text-disabled cursor-default pointer-events-none',\n },\n },\n readonly: {\n true: {\n activator: 'opacity-80 pointer-events-none cursor-default bg-gray-50 dark:bg-white/10',\n },\n },\n filled: {\n true: {\n activator: [\n '!rounded-t !rounded-b-none !bg-black/[0.06]',\n '!hover:bg-black/[0.09] !focus-within:bg-black/[0.09]',\n 'dark:!bg-white/[0.09]',\n 'dark:!hover:bg-white/[0.13] dark:!focus-within:bg-white/[0.13]',\n underlinePseudo,\n ].join(' '),\n },\n },\n outlined: {\n true: {\n activator: 'bg-white dark:bg-transparent border-none hover:border-none',\n label: 'absolute',\n fieldset: '!mt-0 !h-full',\n },\n false: {\n activator: `!rounded-none ${underlinePseudo}`,\n },\n },\n float: {\n true: {\n label: '-translate-y-2 top-0 text-[0.75rem] leading-4',\n },\n },\n opened: {\n true: {\n icon: 'rotate-180',\n },\n },\n active: {\n true: {\n highlighted: '!bg-rui-grey-300 dark:!bg-rui-grey-700',\n },\n },\n hasError: {\n true: {},\n },\n hasSuccess: {\n true: {},\n },\n // Re-declare for type inference — actual styles are in textInputBase\n hovered: { true: {} },\n },\n compoundVariants: [\n // Legend padding when label is floated\n { float: true, class: { legend: 'px-2' } },\n\n // Non-outlined + opened → underline scales up\n { outlined: false, opened: true, class: { activator: 'after:scale-x-100 after:border-rui-primary' } },\n\n // Non-outlined + error → underline color\n { outlined: false, hasError: true, class: { activator: 'after:scale-x-100 after:!border-rui-error' } },\n\n // Non-outlined + success → underline color\n { outlined: false, hasSuccess: true, class: { activator: 'after:scale-x-100 after:!border-rui-success' } },\n\n // Non-outlined + disabled in dark mode\n { outlined: false, disabled: true, class: { activator: 'dark:bg-white/10' } },\n\n // Filled + disabled\n { filled: true, disabled: true, class: { activator: 'bg-black/[0.03] dark:bg-white/[0.05]' } },\n\n // Outlined + hovered → fieldset border\n { outlined: true, hovered: true, class: { fieldset: 'border-black dark:border-white' } },\n\n // Outlined + opened/focused → primary border\n { outlined: true, opened: true, class: {\n fieldset: '!border-rui-primary !border-2',\n label: 'text-rui-primary',\n } },\n\n // Outlined + error → fieldset + label\n { outlined: true, hasError: true, class: {\n fieldset: '!border-rui-error',\n label: '!text-rui-error',\n } },\n // Outlined + success → fieldset + label\n { outlined: true, hasSuccess: true, class: {\n fieldset: '!border-rui-success',\n label: '!text-rui-success',\n } },\n\n // Outlined + disabled → dotted fieldset\n { outlined: true, disabled: true, class: {\n fieldset: '!border-dotted !border-black/[0.23] dark:!border-white/[0.23]',\n } },\n\n // Float + opened → label color\n { float: true, opened: true, class: { label: 'text-rui-primary' } },\n ],\n defaultVariants: {\n filled: false,\n outlined: false,\n dense: false,\n disabled: false,\n readonly: false,\n float: false,\n opened: false,\n },\n});\n"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -1742,6 +1742,11 @@ html[data-theme="dark"], html.dark {
1742
1742
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1743
1743
  }
1744
1744
 
1745
+ .-translate-y-\[0\.5rem\] {
1746
+ --tw-translate-y: -0.5rem;
1747
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1748
+ }
1749
+
1745
1750
  .translate-x-0 {
1746
1751
  --tw-translate-x: 0px;
1747
1752
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -1844,6 +1849,10 @@ html[data-theme="dark"], html.dark {
1844
1849
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1845
1850
  }
1846
1851
 
1852
+ .transform-gpu {
1853
+ transform: translate3d(var(--tw-translate-x), var(--tw-translate-y), 0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1854
+ }
1855
+
1847
1856
  @keyframes buffer-pulse {
1848
1857
 
1849
1858
  0% {
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json.schemastore.org/web-types",
3
3
  "framework": "vue",
4
4
  "name": "@rotki/ui-library",
5
- "version": "2.19.1",
5
+ "version": "2.19.2",
6
6
  "js-types-syntax": "typescript",
7
7
  "description-markup": "markdown",
8
8
  "contributions": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotki/ui-library",
3
- "version": "2.19.1",
3
+ "version": "2.19.2",
4
4
  "description": "A vue design system and component library for rotki",
5
5
  "type": "module",
6
6
  "keywords": [