@rotki/ui-library 2.23.3 → 2.23.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +5 -1
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/icons/RuiIcon.js.map +1 -1
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +15 -9
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js +23 -14
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/progress/RuiProgress.js.map +1 -1
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js +35 -8
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableCell.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +4 -3
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/composables/forms/auto-complete/value.d.ts +2 -0
- package/dist/composables/forms/auto-complete/value.js +16 -12
- package/dist/composables/forms/auto-complete/value.js.map +1 -1
- package/dist/style.css +5 -0
- package/dist/web-types.json +1 -1
- package/package.json +1 -1
|
@@ -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 GroupBy,\n type ItemDisabled,\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\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 /**\n * Custom search predicate. Receives the resolved group label as a third\n * argument when `groupBy` is set, so callers don't have to re-run the\n * `groupBy` resolver themselves.\n */\n filter?: (item: TItem, queryText: string, group?: 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 groupBy?: GroupBy<TItem>;\n itemDisabled?: ItemDisabled<TItem>;\n /**\n * When true and `groupBy` is set, the default search predicate also matches\n * against the resolved group label. Items belonging to a group whose label\n * matches the query stay visible (group header included), even when the\n * items themselves don't match. No effect when a custom `filter` is supplied\n * or when `groupBy` is undefined.\n */\n searchIncludesGroupLabel?: 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 groupBy,\n itemDisabled,\n searchIncludesGroupLabel = 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 'group-header'?: (props: { group: string; items: TItem[] }) => any;\n 'no-data'?: () => any;\n 'placeholder'?: (props: { disabled: boolean; readOnly: boolean }) => any;\n 'footer'?: () => 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 groupBy: () => groupBy,\n searchIncludesGroupLabel: () => searchIncludesGroupLabel,\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 groupedOptions,\n isGrouped,\n isItemDisabled,\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 groupBy: () => groupBy,\n itemDisabled: () => itemDisabled,\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\n// True when the consumer's #placeholder slot is taking over the resting\n// content area, so the outlined/resting label must hide to avoid overlapping\n// the slot content.\nconst placeholderSlotActive = computed<boolean>(() => Boolean(slots.placeholder) && !get(valueSet) && !get(searchInputFocused));\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 // Alt/Option + delete converts the chip back into editable search text\n // instead of removing it outright. Only meaningful when custom values\n // are accepted, since the restored text has to be re-selectable.\n if (event.altKey && customValue) {\n const text = getText(item) ?? '';\n setValue(item);\n updateInternalSearch(text);\n }\n else {\n setValue(item);\n }\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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)) && !placeholderSlotActive\"\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 <!--\n Placeholder slot occupies the same flex space the input takes\n when focused, so transitioning into the focused state doesn't\n shift the activator's content. pointer-events-none is required\n so clicks pass through to the activator (otherwise the slot\n swallows the first click and the menu needs two taps to open).\n -->\n <div\n v-if=\"!valueSet && !searchInputFocused && slots.placeholder\"\n data-id=\"placeholder\"\n class=\"flex-1 min-w-0 pointer-events-none\"\n >\n <slot\n name=\"placeholder\"\n v-bind=\"{ disabled, readOnly }\"\n />\n </div>\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-if=\"isGrouped\"\n ref=\"menuRef\"\n >\n <template\n v-for=\"(bucket, bucketIndex) in groupedOptions\"\n :key=\"bucket.group || `group-${bucketIndex}`\"\n >\n <div\n class=\"sticky top-0 z-10 bg-white dark:bg-rui-grey-900\"\n data-id=\"group-header\"\n >\n <slot\n name=\"group-header\"\n v-bind=\"{ group: bucket.group, items: bucket.items }\"\n >\n <div class=\"px-3 py-1 text-xs uppercase tracking-wide text-rui-text-secondary\">\n {{ bucket.group }}\n </div>\n </slot>\n </div>\n <RuiButton\n v-for=\"item in bucket.items\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"optionsWithSelectedHidden.indexOf(item) === highlightedIndex\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && optionsWithSelectedHidden.indexOf(item) === highlightedIndex,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n <div\n v-else\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 :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), 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 <!--\n The scroll container above reserves ~15px on the right for the\n scrollbar gutter. We render an equivalent right-padding here so the\n footer's content aligns with the option rows' content rather than\n the menu's outer edge. `pr-[var(--rui-scrollbar-gutter,15px)]`\n lets consumers override if their theme reserves a different width.\n -->\n <div\n v-if=\"slots.footer\"\n class=\"bg-white dark:bg-rui-grey-900 border-t border-black/[0.12] dark:border-white/[0.12] pr-[var(--rui-scrollbar-gutter,15px)] -mb-2\"\n data-id=\"footer\"\n >\n <slot name=\"footer\" />\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 GroupBy,\n type ItemDisabled,\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\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 /**\n * Custom search predicate. Receives the resolved group label as a third\n * argument when `groupBy` is set, so callers don't have to re-run the\n * `groupBy` resolver themselves.\n */\n filter?: (item: TItem, queryText: string, group?: 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 groupBy?: GroupBy<TItem>;\n itemDisabled?: ItemDisabled<TItem>;\n /**\n * When true and `groupBy` is set, the default search predicate also matches\n * against the resolved group label. Items belonging to a group whose label\n * matches the query stay visible (group header included), even when the\n * items themselves don't match. No effect when a custom `filter` is supplied\n * or when `groupBy` is undefined.\n */\n searchIncludesGroupLabel?: 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 groupBy,\n itemDisabled,\n searchIncludesGroupLabel = 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 'group-header'?: (props: { group: string; items: TItem[] }) => any;\n 'no-data'?: () => any;\n 'placeholder'?: (props: { disabled: boolean; readOnly: boolean }) => any;\n 'footer'?: () => 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 groupBy: () => groupBy,\n searchIncludesGroupLabel: () => searchIncludesGroupLabel,\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 { resolveIn, 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 groupedOptions,\n isGrouped,\n isItemDisabled,\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 groupBy: () => groupBy,\n itemDisabled: () => itemDisabled,\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\n// True when the consumer's #placeholder slot is taking over the resting\n// content area, so the outlined/resting label must hide to avoid overlapping\n// the slot content.\nconst placeholderSlotActive = computed<boolean>(() => Boolean(slots.placeholder) && !get(valueSet) && !get(searchInputFocused));\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 // Alt/Option + delete converts the chip back into editable search text\n // instead of removing it outright. Only meaningful when custom values\n // are accepted, since the restored text has to be re-selectable.\n if (event.altKey && customValue) {\n const text = getText(item) ?? '';\n setValue(item);\n updateInternalSearch(text);\n }\n else {\n setValue(item);\n }\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 // Only reconcile a selection the previous options could actually resolve. A value\n // that was already unresolvable is one the consumer set before its options arrived\n // (async lists start empty), so clearing it here would discard a legitimate value.\n if (!get(multiple) && resolveIn(old).length === 0)\n return;\n\n setSelected(get(value));\n});\n\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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)) && !placeholderSlotActive\"\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 <!--\n Placeholder slot occupies the same flex space the input takes\n when focused, so transitioning into the focused state doesn't\n shift the activator's content. pointer-events-none is required\n so clicks pass through to the activator (otherwise the slot\n swallows the first click and the menu needs two taps to open).\n -->\n <div\n v-if=\"!valueSet && !searchInputFocused && slots.placeholder\"\n data-id=\"placeholder\"\n class=\"flex-1 min-w-0 pointer-events-none\"\n >\n <slot\n name=\"placeholder\"\n v-bind=\"{ disabled, readOnly }\"\n />\n </div>\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-if=\"isGrouped\"\n ref=\"menuRef\"\n >\n <template\n v-for=\"(bucket, bucketIndex) in groupedOptions\"\n :key=\"bucket.group || `group-${bucketIndex}`\"\n >\n <div\n class=\"sticky top-0 z-10 bg-white dark:bg-rui-grey-900\"\n data-id=\"group-header\"\n >\n <slot\n name=\"group-header\"\n v-bind=\"{ group: bucket.group, items: bucket.items }\"\n >\n <div class=\"px-3 py-1 text-xs uppercase tracking-wide text-rui-text-secondary\">\n {{ bucket.group }}\n </div>\n </slot>\n </div>\n <RuiButton\n v-for=\"item in bucket.items\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"optionsWithSelectedHidden.indexOf(item) === highlightedIndex\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && optionsWithSelectedHidden.indexOf(item) === highlightedIndex,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n <div\n v-else\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 :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), 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 <!--\n The scroll container above reserves ~15px on the right for the\n scrollbar gutter. We render an equivalent right-padding here so the\n footer's content aligns with the option rows' content rather than\n the menu's outer edge. `pr-[var(--rui-scrollbar-gutter,15px)]`\n lets consumers override if their theme reserves a different width.\n -->\n <div\n v-if=\"slots.footer\"\n class=\"bg-white dark:bg-rui-grey-900 border-t border-black/[0.12] dark:border-white/[0.12] pr-[var(--rui-scrollbar-gutter,15px)] -mb-2\"\n data-id=\"footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":""}
|
package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js
CHANGED
|
@@ -190,7 +190,7 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
190
190
|
const isHovered = ref(false);
|
|
191
191
|
const multiple = computed(() => Array.isArray(get$1(modelValue)));
|
|
192
192
|
const shouldApplyValueAsSearch = computed(() => !(slots.selection || get$1(multiple) || __props.chips));
|
|
193
|
-
const { value, setSelected } = useAutoCompleteValue(modelValue, () => __props.options, {
|
|
193
|
+
const { resolveIn, value, setSelected } = useAutoCompleteValue(modelValue, () => __props.options, {
|
|
194
194
|
keyAttr: () => __props.keyAttr,
|
|
195
195
|
returnObject: () => __props.returnObject,
|
|
196
196
|
customValue: () => __props.customValue
|
|
@@ -371,6 +371,7 @@ var RuiAutoComplete_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
371
371
|
watch(() => __props.options, (curr, old) => {
|
|
372
372
|
if (curr === old || __props.customValue) return;
|
|
373
373
|
if (isEqual(curr, old)) return;
|
|
374
|
+
if (!get$1(multiple) && resolveIn(old).length === 0) return;
|
|
374
375
|
setSelected(get$1(value));
|
|
375
376
|
});
|
|
376
377
|
const menuFloatingOptions = computed(() => ({
|
|
@@ -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 GroupBy,\n type ItemDisabled,\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\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 /**\n * Custom search predicate. Receives the resolved group label as a third\n * argument when `groupBy` is set, so callers don't have to re-run the\n * `groupBy` resolver themselves.\n */\n filter?: (item: TItem, queryText: string, group?: 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 groupBy?: GroupBy<TItem>;\n itemDisabled?: ItemDisabled<TItem>;\n /**\n * When true and `groupBy` is set, the default search predicate also matches\n * against the resolved group label. Items belonging to a group whose label\n * matches the query stay visible (group header included), even when the\n * items themselves don't match. No effect when a custom `filter` is supplied\n * or when `groupBy` is undefined.\n */\n searchIncludesGroupLabel?: 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 groupBy,\n itemDisabled,\n searchIncludesGroupLabel = 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 'group-header'?: (props: { group: string; items: TItem[] }) => any;\n 'no-data'?: () => any;\n 'placeholder'?: (props: { disabled: boolean; readOnly: boolean }) => any;\n 'footer'?: () => 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 groupBy: () => groupBy,\n searchIncludesGroupLabel: () => searchIncludesGroupLabel,\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 groupedOptions,\n isGrouped,\n isItemDisabled,\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 groupBy: () => groupBy,\n itemDisabled: () => itemDisabled,\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\n// True when the consumer's #placeholder slot is taking over the resting\n// content area, so the outlined/resting label must hide to avoid overlapping\n// the slot content.\nconst placeholderSlotActive = computed<boolean>(() => Boolean(slots.placeholder) && !get(valueSet) && !get(searchInputFocused));\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 // Alt/Option + delete converts the chip back into editable search text\n // instead of removing it outright. Only meaningful when custom values\n // are accepted, since the restored text has to be re-selectable.\n if (event.altKey && customValue) {\n const text = getText(item) ?? '';\n setValue(item);\n updateInternalSearch(text);\n }\n else {\n setValue(item);\n }\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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)) && !placeholderSlotActive\"\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 <!--\n Placeholder slot occupies the same flex space the input takes\n when focused, so transitioning into the focused state doesn't\n shift the activator's content. pointer-events-none is required\n so clicks pass through to the activator (otherwise the slot\n swallows the first click and the menu needs two taps to open).\n -->\n <div\n v-if=\"!valueSet && !searchInputFocused && slots.placeholder\"\n data-id=\"placeholder\"\n class=\"flex-1 min-w-0 pointer-events-none\"\n >\n <slot\n name=\"placeholder\"\n v-bind=\"{ disabled, readOnly }\"\n />\n </div>\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-if=\"isGrouped\"\n ref=\"menuRef\"\n >\n <template\n v-for=\"(bucket, bucketIndex) in groupedOptions\"\n :key=\"bucket.group || `group-${bucketIndex}`\"\n >\n <div\n class=\"sticky top-0 z-10 bg-white dark:bg-rui-grey-900\"\n data-id=\"group-header\"\n >\n <slot\n name=\"group-header\"\n v-bind=\"{ group: bucket.group, items: bucket.items }\"\n >\n <div class=\"px-3 py-1 text-xs uppercase tracking-wide text-rui-text-secondary\">\n {{ bucket.group }}\n </div>\n </slot>\n </div>\n <RuiButton\n v-for=\"item in bucket.items\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"optionsWithSelectedHidden.indexOf(item) === highlightedIndex\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && optionsWithSelectedHidden.indexOf(item) === highlightedIndex,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n <div\n v-else\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 :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), 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 <!--\n The scroll container above reserves ~15px on the right for the\n scrollbar gutter. We render an equivalent right-padding here so the\n footer's content aligns with the option rows' content rather than\n the menu's outer edge. `pr-[var(--rui-scrollbar-gutter,15px)]`\n lets consumers override if their theme reserves a different width.\n -->\n <div\n v-if=\"slots.footer\"\n class=\"bg-white dark:bg-rui-grey-900 border-t border-black/[0.12] dark:border-white/[0.12] pr-[var(--rui-scrollbar-gutter,15px)] -mb-2\"\n data-id=\"footer\"\n >\n <slot name=\"footer\" />\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 GroupBy,\n type ItemDisabled,\n type KeyOfType,\n useDropdownMenu,\n useDropdownOptionProperty,\n} from '@/composables/dropdown-menu';\nimport { type FloatingOptions, Placement } from '@/composables/floating';\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 /**\n * Custom search predicate. Receives the resolved group label as a third\n * argument when `groupBy` is set, so callers don't have to re-run the\n * `groupBy` resolver themselves.\n */\n filter?: (item: TItem, queryText: string, group?: 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 groupBy?: GroupBy<TItem>;\n itemDisabled?: ItemDisabled<TItem>;\n /**\n * When true and `groupBy` is set, the default search predicate also matches\n * against the resolved group label. Items belonging to a group whose label\n * matches the query stay visible (group header included), even when the\n * items themselves don't match. No effect when a custom `filter` is supplied\n * or when `groupBy` is undefined.\n */\n searchIncludesGroupLabel?: 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 groupBy,\n itemDisabled,\n searchIncludesGroupLabel = 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 'group-header'?: (props: { group: string; items: TItem[] }) => any;\n 'no-data'?: () => any;\n 'placeholder'?: (props: { disabled: boolean; readOnly: boolean }) => any;\n 'footer'?: () => 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 groupBy: () => groupBy,\n searchIncludesGroupLabel: () => searchIncludesGroupLabel,\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 { resolveIn, 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 groupedOptions,\n isGrouped,\n isItemDisabled,\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 groupBy: () => groupBy,\n itemDisabled: () => itemDisabled,\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\n// True when the consumer's #placeholder slot is taking over the resting\n// content area, so the outlined/resting label must hide to avoid overlapping\n// the slot content.\nconst placeholderSlotActive = computed<boolean>(() => Boolean(slots.placeholder) && !get(valueSet) && !get(searchInputFocused));\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 // Alt/Option + delete converts the chip back into editable search text\n // instead of removing it outright. Only meaningful when custom values\n // are accepted, since the restored text has to be re-selectable.\n if (event.altKey && customValue) {\n const text = getText(item) ?? '';\n setValue(item);\n updateInternalSearch(text);\n }\n else {\n setValue(item);\n }\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 // Only reconcile a selection the previous options could actually resolve. A value\n // that was already unresolvable is one the consumer set before its options arrived\n // (async lists start empty), so clearing it here would discard a legitimate value.\n if (!get(multiple) && resolveIn(old).length === 0)\n return;\n\n setSelected(get(value));\n});\n\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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)) && !placeholderSlotActive\"\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 <!--\n Placeholder slot occupies the same flex space the input takes\n when focused, so transitioning into the focused state doesn't\n shift the activator's content. pointer-events-none is required\n so clicks pass through to the activator (otherwise the slot\n swallows the first click and the menu needs two taps to open).\n -->\n <div\n v-if=\"!valueSet && !searchInputFocused && slots.placeholder\"\n data-id=\"placeholder\"\n class=\"flex-1 min-w-0 pointer-events-none\"\n >\n <slot\n name=\"placeholder\"\n v-bind=\"{ disabled, readOnly }\"\n />\n </div>\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-if=\"isGrouped\"\n ref=\"menuRef\"\n >\n <template\n v-for=\"(bucket, bucketIndex) in groupedOptions\"\n :key=\"bucket.group || `group-${bucketIndex}`\"\n >\n <div\n class=\"sticky top-0 z-10 bg-white dark:bg-rui-grey-900\"\n data-id=\"group-header\"\n >\n <slot\n name=\"group-header\"\n v-bind=\"{ group: bucket.group, items: bucket.items }\"\n >\n <div class=\"px-3 py-1 text-xs uppercase tracking-wide text-rui-text-secondary\">\n {{ bucket.group }}\n </div>\n </slot>\n </div>\n <RuiButton\n v-for=\"item in bucket.items\"\n :key=\"getIdentifier(item)?.toString()\"\n :active=\"isActiveItem(item)\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"optionsWithSelectedHidden.indexOf(item) === highlightedIndex\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && optionsWithSelectedHidden.indexOf(item) === highlightedIndex,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n <div\n v-else\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 :disabled=\"isItemDisabled(item)\"\n tabindex=\"0\"\n variant=\"list\"\n :data-highlighted=\"highlightedIndex === _index\"\n :data-disabled=\"isItemDisabled(item) || undefined\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && highlightedIndex === _index,\n }\"\n @click=\"!isItemDisabled(item) && setValue(item)\"\n >\n <template #prepend>\n <slot\n name=\"item.prepend\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ disabled: isItemDisabled(item), item, active: isActiveItem(item) }\"\n >\n {{ getText(item) }}\n </slot>\n <template #append>\n <slot\n name=\"item.append\"\n v-bind=\"{ disabled: isItemDisabled(item), 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 <!--\n The scroll container above reserves ~15px on the right for the\n scrollbar gutter. We render an equivalent right-padding here so the\n footer's content aligns with the option rows' content rather than\n the menu's outer edge. `pr-[var(--rui-scrollbar-gutter,15px)]`\n lets consumers override if their theme reserves a different width.\n -->\n <div\n v-if=\"slots.footer\"\n class=\"bg-white dark:bg-rui-grey-900 border-t border-black/[0.12] dark:border-white/[0.12] pr-[var(--rui-scrollbar-gutter,15px)] -mb-2\"\n data-id=\"footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </template>\n </RuiMenu>\n</template>\n"],"mappings":"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"}
|
|
@@ -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 { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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":""}
|
|
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 { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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', { 'mr-2': !dense }]\"\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":""}
|
|
@@ -219,7 +219,11 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
219
219
|
__props.clearable && unref(value) && !__props.disabled ? (openBlock(), createElementBlock("span", {
|
|
220
220
|
key: 2,
|
|
221
221
|
"data-id": "clear",
|
|
222
|
-
class: normalizeClass([
|
|
222
|
+
class: normalizeClass([
|
|
223
|
+
unref(ui).clear(),
|
|
224
|
+
unref(focused) && "!visible",
|
|
225
|
+
{ "mr-2": !__props.dense }
|
|
226
|
+
]),
|
|
223
227
|
onClick: _cache[0] || (_cache[0] = withModifiers(($event) => clear(), ["stop", "prevent"]))
|
|
224
228
|
}, [createVNode(RuiIcon_default, {
|
|
225
229
|
color: "error",
|
package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -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 { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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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"}
|
|
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 { type FloatingOptions, Placement } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\nimport { cn } from '@/utils/tv';\n\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\nconst menuFloatingOptions = computed<FloatingOptions>(() => ({\n placement: Placement.bottomStart,\n ...menuOptions?.options,\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 :options=\"menuFloatingOptions\"\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', { 'mr-2': !dense }]\"\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiIcon.js","names":[],"sources":["../../../src/components/icons/RuiIcon.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport { useIcons } from '@/composables/icons';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n name: RuiIcons;\n size?: number | string;\n color?: ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiIcon',\n});\n\nconst { name, size, color } = defineProps<Props>();\n\nconst { registeredIcons } = useIcons();\n\ntype SvgComponent = [tag: string, attrs: Record<string, string>];\n\nconst iconStyles = tv({\n // `shrink-0` keeps the icon at its declared `--rui-icon-size` when it sits\n // in a flex container next to a long flex-grow sibling (e.g. a `w-full`\n // button label in `variant=\"list\"`). Without it, the SVG — even with an\n // explicit width — gets compressed along the main axis when the row is\n // narrower than the label's intrinsic width, while the height stays put,\n // producing a sliver glyph. The icon's box is always intentionally driven\n // by `--rui-icon-size`, so flex shrinking is never the desired behavior.\n base: 'shrink-0 w-[var(--rui-icon-size,1.5rem)] h-[var(--rui-icon-size,1.5rem)]',\n variants: {\n color: {\n primary: 'text-rui-primary',\n secondary: 'text-rui-secondary',\n error: 'text-rui-error',\n warning: 'text-rui-warning',\n info: 'text-rui-info',\n success: 'text-rui-success',\n },\n },\n});\n\nconst hasExplicitSize = computed<boolean>(() => size !== undefined);\
|
|
1
|
+
{"version":3,"file":"RuiIcon.js","names":[],"sources":["../../../src/components/icons/RuiIcon.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ClassValue } from 'vue';\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport { objectOmit } from '@vueuse/shared';\nimport { useIcons } from '@/composables/icons';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface Props {\n name: RuiIcons;\n size?: number | string;\n color?: ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiIcon',\n // the svg is the only root, so a fallthrough class would land beside the\n // variant classes and leave the cascade to break the tie; `ui` merges instead\n inheritAttrs: false,\n});\n\nconst { name, size, color } = defineProps<Props>();\n\nconst { registeredIcons } = useIcons();\n\ntype SvgComponent = [tag: string, attrs: Record<string, string>];\n\nconst iconStyles = tv({\n // `shrink-0` keeps the icon at its declared `--rui-icon-size` when it sits\n // in a flex container next to a long flex-grow sibling (e.g. a `w-full`\n // button label in `variant=\"list\"`). Without it, the SVG — even with an\n // explicit width — gets compressed along the main axis when the row is\n // narrower than the label's intrinsic width, while the height stays put,\n // producing a sliver glyph. The icon's box is always intentionally driven\n // by `--rui-icon-size`, so flex shrinking is never the desired behavior.\n base: 'shrink-0 w-[var(--rui-icon-size,1.5rem)] h-[var(--rui-icon-size,1.5rem)]',\n variants: {\n color: {\n primary: 'text-rui-primary',\n secondary: 'text-rui-secondary',\n error: 'text-rui-error',\n warning: 'text-rui-warning',\n info: 'text-rui-info',\n success: 'text-rui-success',\n },\n },\n});\n\nconst hasExplicitSize = computed<boolean>(() => size !== undefined);\n\nfunction ui(attrsClass: ClassValue): string {\n return iconStyles({ color, class: cn(attrsClass) });\n}\n\n// Render the `size` prop as an inline CSS custom property on the svg. Because\n// inline style wins against any inherited value for the same property on this\n// element, the consumer-supplied size beats the button's `--rui-icon-size`\n// assignment without needing !important. A bare number (or numeric string —\n// `:size=\"16\"` resolves to a string in the template binding) is coerced to px;\n// values that already include a unit (`1rem`, `18px`, `calc(...)`) pass\n// through unchanged. The previous SVG-attr path accepted bare numbers because\n// `width`/`height` presentation attrs treat them as px; CSS does not.\nconst sizeStyle = computed<Record<string, string> | undefined>(() => {\n if (!get(hasExplicitSize))\n return undefined;\n const raw = String(size);\n const value = /^\\d+(?:\\.\\d+)?$/.test(raw) ? `${raw}px` : raw;\n return { '--rui-icon-size': value };\n});\n\nconst isFill = computed<boolean>(() => name.endsWith('-fill'));\n\n// What is registered is the only thing that matters here. An app may register\n// its own icons through `createRui({ theme: { icons } })` — brand logos, since\n// the library carries none — and those names can never appear in the generated\n// `RuiIcons` list, so validating against that list warned for precisely the\n// icons the registration API exists to support. A genuinely unknown name is\n// still caught below, by the check that decides whether anything renders.\nconst components = computed<SvgComponent[] | undefined>(() => {\n const found = registeredIcons[name];\n\n if (!found) {\n console.error(\n `Icons \"${name}\" not found. Make sure that you have register the icon when installing the RuiPlugin`,\n );\n }\n return found;\n});\n</script>\n\n<template>\n <svg\n aria-hidden=\"true\"\n class=\"rui-icon\"\n :class=\"ui($attrs.class)\"\n :style=\"sizeStyle\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n v-bind=\"objectOmit($attrs, ['class'])\"\n >\n <component\n :is=\"component[0]\"\n v-for=\"(component, index) in components\"\n :key=\"index\"\n v-bind=\"component[1]\"\n :fill=\"!isFill ? 'none' : 'currentColor'\"\n :stroke=\"!isFill ? 'currentColor' : 'none'\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n />\n </svg>\n</template>\n"],"mappings":""}
|