@rotki/ui-library 2.23.3 → 2.23.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"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([unref(ui).clear(), unref(focused) && "!visible"]),
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",
@@ -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);\nconst ui = computed<string>(() => iconStyles({ color }));\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\"\n :style=\"sizeStyle\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\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":""}
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":""}
@@ -1,10 +1,11 @@
1
1
  import { useIcons } from "../../composables/icons.js";
2
- import { tv } from "../../utils/tv.js";
3
- import { Fragment, computed, createBlock, createElementBlock, defineComponent, mergeProps, normalizeClass, normalizeStyle, openBlock, renderList, resolveDynamicComponent, unref } from "vue";
4
- import { get } from "@vueuse/shared";
2
+ import { cn, tv } from "../../utils/tv.js";
3
+ import { Fragment, computed, createBlock, createElementBlock, defineComponent, mergeProps, openBlock, renderList, resolveDynamicComponent, unref } from "vue";
4
+ import { get, objectOmit } from "@vueuse/shared";
5
5
  //#region src/components/icons/RuiIcon.vue?vue&type=script&setup=true&lang.ts
6
6
  var RuiIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
7
  name: "RuiIcon",
8
+ inheritAttrs: false,
8
9
  __name: "RuiIcon",
9
10
  props: {
10
11
  name: {},
@@ -25,7 +26,12 @@ var RuiIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCo
25
26
  } }
26
27
  });
27
28
  const hasExplicitSize = computed(() => __props.size !== void 0);
28
- const ui = computed(() => iconStyles({ color: __props.color }));
29
+ function ui(attrsClass) {
30
+ return iconStyles({
31
+ color: __props.color,
32
+ class: cn(attrsClass)
33
+ });
34
+ }
29
35
  const sizeStyle = computed(() => {
30
36
  if (!get(hasExplicitSize)) return void 0;
31
37
  const raw = String(__props.size);
@@ -38,13 +44,13 @@ var RuiIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCo
38
44
  return found;
39
45
  });
40
46
  return (_ctx, _cache) => {
41
- return openBlock(), createElementBlock("svg", {
47
+ return openBlock(), createElementBlock("svg", mergeProps({
42
48
  "aria-hidden": "true",
43
- class: normalizeClass(["rui-icon", unref(ui)]),
44
- style: normalizeStyle(unref(sizeStyle)),
49
+ class: ["rui-icon", ui(_ctx.$attrs.class)],
50
+ style: unref(sizeStyle),
45
51
  viewBox: "0 0 24 24",
46
52
  xmlns: "http://www.w3.org/2000/svg"
47
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(components), (component, index) => {
53
+ }, unref(objectOmit)(_ctx.$attrs, ["class"])), [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(components), (component, index) => {
48
54
  return openBlock(), createBlock(resolveDynamicComponent(component[0]), mergeProps({ key: index }, { ref_for: true }, component[1], {
49
55
  fill: !unref(isFill) ? "none" : "currentColor",
50
56
  stroke: !unref(isFill) ? "currentColor" : "none",
@@ -54,7 +60,7 @@ var RuiIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCo
54
60
  "fill-rule": "evenodd",
55
61
  "clip-rule": "evenodd"
56
62
  }), null, 16, ["fill", "stroke"]);
57
- }), 128))], 6);
63
+ }), 128))], 16);
58
64
  };
59
65
  }
60
66
  });
@@ -1 +1 @@
1
- {"version":3,"file":"RuiIcon.vue_vue_type_script_setup_true_lang.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);\nconst ui = computed<string>(() => iconStyles({ color }));\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\"\n :style=\"sizeStyle\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\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":";;;;;;;;;;;;;;EAkBA,MAAM,EAAE,oBAAoB,SAAS;EAIrC,MAAM,aAAa,GAAG;GAQpB,MAAM;GACN,UAAU,EACR,OAAO;IACL,SAAS;IACT,WAAW;IACX,OAAO;IACP,SAAS;IACT,MAAM;IACN,SAAS;GACX,EACF;EACF,CAAC;EAED,MAAM,kBAAkB,eAAwB,QAAA,SAAS,KAAA,CAAS;EAClE,MAAM,KAAK,eAAuB,WAAW,EAAE,OAAI,QAAA,MAAE,CAAC,CAAC;EAUvD,MAAM,YAAY,eAAmD;GACnE,IAAI,CAAC,IAAI,eAAe,GACtB,OAAO,KAAA;GACT,MAAM,MAAM,OAAO,QAAA,IAAI;GAEvB,OAAO,EAAE,mBADK,kBAAkB,KAAK,GAAG,IAAI,GAAG,IAAI,MAAM,IACvB;EACpC,CAAC;EAED,MAAM,SAAS,eAAwB,QAAA,KAAK,SAAS,OAAO,CAAC;EAQ7D,MAAM,aAAa,eAA2C;GAC5D,MAAM,QAAQ,gBAAgB,QAAA;GAE9B,IAAI,CAAC,OACH,QAAQ,MACN,UAAU,QAAA,KAAK,qFACjB;GAEF,OAAO;EACT,CAAC;;uBAIC,mBAqBM,OAAA;IApBJ,eAAY;IACZ,OAAK,eAAA,CAAC,YACE,MAAA,EAAA,CAAE,CAAA;IACT,OAAK,eAAE,MAAA,SAAA,CAAS;IACjB,SAAQ;IACR,OAAM;yBAEN,mBAYE,UAAA,MAAA,WAV6B,MAAA,UAAA,IAArB,WAAW,UAAK;wBAF1B,YAYE,wBAXK,UAAS,EAAA,GADhB,WAYE,EATC,KAAK,MAAK,GAAA,EAAA,SAAA,KAAA,GACH,UAAS,IAAA;KAChB,MAAI,CAAG,MAAA,MAAA,IAAM,SAAA;KACb,QAAM,CAAG,MAAA,MAAA,IAAM,iBAAA;KAChB,gBAAa;KACb,kBAAe;KACf,mBAAgB;KAChB,aAAU;KACV,aAAU"}
1
+ {"version":3,"file":"RuiIcon.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"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":";;;;;;;;;;;;;;;EAuBA,MAAM,EAAE,oBAAoB,SAAS;EAIrC,MAAM,aAAa,GAAG;GAQpB,MAAM;GACN,UAAU,EACR,OAAO;IACL,SAAS;IACT,WAAW;IACX,OAAO;IACP,SAAS;IACT,MAAM;IACN,SAAS;GACX,EACF;EACF,CAAC;EAED,MAAM,kBAAkB,eAAwB,QAAA,SAAS,KAAA,CAAS;EAElE,SAAS,GAAG,YAAgC;GAC1C,OAAO,WAAW;IAAE,OAAI,QAAA;IAAG,OAAO,GAAG,UAAU;GAAE,CAAC;EACpD;EAUA,MAAM,YAAY,eAAmD;GACnE,IAAI,CAAC,IAAI,eAAe,GACtB,OAAO,KAAA;GACT,MAAM,MAAM,OAAO,QAAA,IAAI;GAEvB,OAAO,EAAE,mBADK,kBAAkB,KAAK,GAAG,IAAI,GAAG,IAAI,MAAM,IACvB;EACpC,CAAC;EAED,MAAM,SAAS,eAAwB,QAAA,KAAK,SAAS,OAAO,CAAC;EAQ7D,MAAM,aAAa,eAA2C;GAC5D,MAAM,QAAQ,gBAAgB,QAAA;GAE9B,IAAI,CAAC,OACH,QAAQ,MACN,UAAU,QAAA,KAAK,qFACjB;GAEF,OAAO;EACT,CAAC;;uBAIC,mBAsBM,OAtBN,WAsBM;IArBJ,eAAY;IACZ,OAAK,CAAC,YACE,GAAGA,KAAAA,OAAO,KAAK,CAAA;IACtB,OAAO,MAAA,SAAA;IACR,SAAQ;IACR,OAAM;MACE,MAAA,UAAA,CAAU,CAACA,KAAAA,QAAM,CAAA,OAAA,CAAA,CAAA,GAAA,EAAA,UAAA,IAAA,GAEzB,mBAYE,UAAA,MAAA,WAV6B,MAAA,UAAA,IAArB,WAAW,UAAK;wBAF1B,YAYE,wBAXK,UAAS,EAAA,GADhB,WAYE,EATC,KAAK,MAAK,GAAA,EAAA,SAAA,KAAA,GACH,UAAS,IAAA;KAChB,MAAI,CAAG,MAAA,MAAA,IAAM,SAAA;KACb,QAAM,CAAG,MAAA,MAAA,IAAM,iBAAA;KAChB,gBAAa;KACb,kBAAe;KACf,mBAAgB;KAChB,aAAU;KACV,aAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNavigationDrawer.js","names":[],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\nconst ui = computed<string>(() => drawer({ position, visible: modelValue.value, mini: miniVariant, withOverlay: overlay }));\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounce prevents activator click from immediately triggering close\n// (click bubbles to body → onClickOutside fires in the same tick)\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"[\n ui,\n temporary && modelValue && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n ]\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs)\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiNavigationDrawer.js","names":[],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounce prevents activator click from immediately triggering close\n// (click bubbles to body → onClickOutside fires in the same tick)\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
@@ -1,4 +1,4 @@
1
- import { tv } from "../../../utils/tv.js";
1
+ import { cn, tv } from "../../../utils/tv.js";
2
2
  import { useTimeoutManager } from "../../../composables/timeout-manager.js";
3
3
  import { getRootAttrs, transformPropsUnit } from "../../../utils/helpers.js";
4
4
  import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, defineComponent, guardReactiveProps, mergeModels, mergeProps, normalizeProps, openBlock, ref, renderSlot, unref, useModel, useTemplateRef, watch, withCtx, withModifiers } from "vue";
@@ -102,12 +102,26 @@ var RuiNavigationDrawer_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
102
102
  withOverlay: false
103
103
  }
104
104
  });
105
- const ui = computed(() => drawer({
106
- position: __props.position,
107
- visible: modelValue.value,
108
- mini: __props.miniVariant,
109
- withOverlay: __props.overlay
110
- }));
105
+ /**
106
+ * Consumer classes go through `drawer()` rather than alongside it, so
107
+ * tailwind-variants' twMerge resolves conflicts in the consumer's favour.
108
+ * Passed as an argument instead of read off `$attrs` here, so the template
109
+ * keeps using `$attrs` directly.
110
+ */
111
+ function rootClass(attrsClass) {
112
+ return drawer({
113
+ position: __props.position,
114
+ visible: modelValue.value,
115
+ mini: __props.miniVariant,
116
+ withOverlay: __props.overlay,
117
+ class: cn([
118
+ __props.temporary && modelValue.value && "shadow-5",
119
+ __props.classNames?.content ?? __props.contentClass,
120
+ __props.classNames?.root,
121
+ attrsClass
122
+ ])
123
+ });
124
+ }
111
125
  function toggle() {
112
126
  set$1(modelValue, !get$1(modelValue));
113
127
  }
@@ -159,15 +173,10 @@ var RuiNavigationDrawer_vue_vue_type_script_setup_true_lang_default = /*@__PURE_
159
173
  "data-visible": modelValue.value || void 0,
160
174
  "data-position": __props.position,
161
175
  "data-mini": __props.miniVariant || void 0,
162
- class: [
163
- unref(ui),
164
- __props.temporary && modelValue.value && "shadow-5",
165
- __props.classNames?.content ?? __props.contentClass,
166
- __props.classNames?.root
167
- ],
176
+ class: rootClass(_ctx.$attrs.class),
168
177
  "aria-label": __props.ariaLabel,
169
178
  "aria-hidden": __props.miniVariant && !modelValue.value ? "true" : void 0
170
- }, unref(getRootAttrs)(_ctx.$attrs)), [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps({
179
+ }, unref(getRootAttrs)(_ctx.$attrs, [])), [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps({
171
180
  attrs: activatorAttrs,
172
181
  close
173
182
  })))], 16, _hoisted_1)) : createCommentVNode("", true)]))]);
@@ -1 +1 @@
1
- {"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\nconst ui = computed<string>(() => drawer({ position, visible: modelValue.value, mini: miniVariant, withOverlay: overlay }));\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounce prevents activator click from immediately triggering close\n// (click bubbles to body → onClickOutside fires in the same tick)\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"[\n ui,\n temporary && modelValue && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n ]\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs)\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BA,MAAM,aAAa,SAAoB,SAAA,YAAmB;EAc1D,MAAM,OAAO;EASb,MAAM,gBAAgB,IAAa,KAAK;EACxC,MAAM,UAAU,eAA6B,SAAS;EACtD,MAAM,eAAe,kBAAkB;EACvC,MAAM,sBAAsB,kBAAkB;EAE9C,MAAM,QAAQ,eAAwB,MAAI,UAAU,KAAK,MAAI,aAAa,KAAK,QAAA,WAAW;EAE1F,MAAM,QAAQ,gBAA+C,EAC3D,OAAO,mBAAmB,QAAA,KAAK,EACjC,EAAE;EAEF,MAAM,iBAA0C,EAC9C,SAAS,OACX;EAEA,MAAM,SAAS,GAAG;GAChB,MAAM;GACN,UAAU;IACR,UAAU;KACR,MAAM;KACN,OAAO;IACT;IACA,SAAS;KACP,MAAM;KACN,OAAO;IACT;IACA,MAAM;KACJ,MAAM;KACN,OAAO;IACT;IACA,aAAa;KACX,MAAM;KACN,OAAO;IACT;GACF;GACA,kBAAkB;IAChB;KAAE,UAAU;KAAQ,SAAS;KAAO,MAAM;KAAO,OAAO;IAAoB;IAC5E;KAAE,UAAU;KAAS,SAAS;KAAO,MAAM;KAAO,OAAO;IAAmB;IAC5E;KAAE,MAAM;KAAM,SAAS;KAAO,OAAO;IAAQ;GAC/C;GACA,iBAAiB;IAAE,UAAU;IAAQ,SAAS;IAAO,MAAM;IAAO,aAAa;GAAM;EACvF,CAAC;EAED,MAAM,KAAK,eAAuB,OAAO;GAAE,UAAO,QAAA;GAAG,SAAS,WAAW;GAAO,MAAM,QAAA;GAAa,aAAa,QAAA;EAAQ,CAAC,CAAC;EAE1H,SAAS,SAAe;GACtB,MAAI,YAAY,CAAC,MAAI,UAAU,CAAC;EAClC;EAEA,SAAS,QAAc;GACrB,MAAI,YAAY,KAAK;EACvB;EAEA,SAAS,kBAAwB;GAC/B,aAAa,MAAM;GACnB,IAAI,MAAI,aAAa,GAAG;IACtB,MAAI,eAAe,KAAK;IACxB,KAAK,QAAQ;GACf;EACF;EAEA,MAAM,aAAa,UAAU;GAC3B,IAAI,CAAC,OAAO;IACV,MAAI,eAAe,IAAI;IAEvB,aAAa,OAAO,iBAAiB,GAAG;GAC1C;EACF,CAAC;EAID,eAAe,eAAe;GAC5B,IAAI,MAAI,UAAU,KAAK,QAAA,aAAa,CAAC,QAAA,WACnC,oBAAoB,OAAO,OAAO,EAAE;EAExC,CAAC;;uBAIC,mBA2CM,OAAA,MAAA,CA1CJ,WAGE,KAAA,QAAA,aAAA,eAAA,mBAAA;IAAA,MADgB,WAAA;IAAU,OAAS;GAAc,CAAA,CAAA,CAAA,IAAA,UAAA,GAEnD,YAqCW,UAAA,EArCD,IAAG,OAAM,GAAA,CAET,QAAA,WAAA,UAAA,GADR,YAea,YAAA;;IAbX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;;2BAOb,CAJM,WAAA,SAAA,UAAA,GADR,mBAKE,OAAA;;KAHA,WAAQ;KACR,OAAM;KACL,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,MAAK,GAAA,CAAA,MAAA,CAAA;;;uCAId,MAAA,KAAA,KAAA,UAAA,GADR,mBAmBQ,SAnBR,WAmBQ;;aAjBF;IAAJ,KAAI;IACJ,WAAQ;IACP,OAAO,MAAA,KAAA;IACP,gBAAc,WAAA,SAAc,KAAA;IAC5B,iBAAe,QAAA;IACf,aAAW,QAAA,eAAe,KAAA;IAC1B,OAAK;KAAc,MAAA,EAAA;KAAc,QAAA,aAAa,WAAA,SAAU;KAA0B,QAAA,YAAY,WAAW,QAAA;KAAwB,QAAA,YAAY;;IAM7I,cAAY,QAAA;IACZ,eAAa,QAAA,eAAW,CAAK,WAAA,QAAU,SAAY,KAAA;MAC5C,MAAA,YAAA,CAAY,CAACA,KAAAA,MAAM,CAAA,GAAA,CAE3B,WAAkD,KAAA,QAAA,WAAA,eAAA,mBAAA;IAAA,OAA3B;IAAgB;GAAK,CAAA,CAAA,CAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounce prevents activator click from immediately triggering close\n// (click bubbles to body → onClickOutside fires in the same tick)\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RuiProgress.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * @example - 0 <= value <= 100\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * @example - 0 <= value <= 100\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n label: 'dark:text-white',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4' } },\n // Circular label (overlays the circle)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center text-[0.6rem] leading-none' } },\n ],\n compoundSlots: [\n // Rail background (track behind the bar)\n { slots: ['rail', 'bufferDots'], color: 'primary', class: 'bg-rui-primary/20 border-rui-primary/20' },\n { slots: ['rail', 'bufferDots'], color: 'secondary', class: 'bg-rui-secondary/20 border-rui-secondary/20' },\n { slots: ['rail', 'bufferDots'], color: 'error', class: 'bg-rui-error/20 border-rui-error/20' },\n { slots: ['rail', 'bufferDots'], color: 'warning', class: 'bg-rui-warning/20 border-rui-warning/20' },\n { slots: ['rail', 'bufferDots'], color: 'info', class: 'bg-rui-info/20 border-rui-info/20' },\n { slots: ['rail', 'bufferDots'], color: 'success', class: 'bg-rui-success/20 border-rui-success/20' },\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n transition: 'stroke-dashoffset 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"value\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"value\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiProgress.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * @example - 0 <= value <= 100\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * @example - 0 <= value <= 100\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** approximate width of `100%` in ems */\nconst LABEL_WIDTH_EM = 2.5;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.85;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: 'stroke-current opacity-20',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Rail background (track behind the bar)\n { slots: ['rail', 'bufferDots'], color: 'primary', class: 'bg-rui-primary/20 border-rui-primary/20' },\n { slots: ['rail', 'bufferDots'], color: 'secondary', class: 'bg-rui-secondary/20 border-rui-secondary/20' },\n { slots: ['rail', 'bufferDots'], color: 'error', class: 'bg-rui-error/20 border-rui-error/20' },\n { slots: ['rail', 'bufferDots'], color: 'warning', class: 'bg-rui-warning/20 border-rui-warning/20' },\n { slots: ['rail', 'bufferDots'], color: 'info', class: 'bg-rui-info/20 border-rui-info/20' },\n { slots: ['rail', 'bufferDots'], color: 'success', class: 'bg-rui-success/20 border-rui-success/20' },\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The circular label lives inside the ring, so it scales with both `size` and `thickness`.\n * `fit` solves for the widest label (`100%`) fitting the chord it spans, always computed\n * for that widest label so the text does not resize as the value climbs. It is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n const fit = (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n return { fontSize: `${Math.min(fit, +size * 0.15 + 6)}px` };\n});\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n transition: 'stroke-dashoffset 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"value\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"value\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -10,12 +10,16 @@ var _hoisted_1 = [
10
10
  ];
11
11
  var _hoisted_2 = ["viewBox"];
12
12
  var _hoisted_3 = ["stroke-width"];
13
- var _hoisted_4 = [
13
+ var _hoisted_4 = ["stroke-width"];
14
+ var _hoisted_5 = [
14
15
  "aria-valuenow",
15
16
  "data-variant",
16
17
  "data-color"
17
18
  ];
18
19
  var CIRCLE_RADIUS = 20;
20
+ var LABEL_WIDTH_EM = 2.5;
21
+ /** keeps the label off the stroke rather than merely inside it */
22
+ var LABEL_BREATHING_ROOM = .85;
19
23
  var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
20
24
  name: "RuiProgress",
21
25
  __name: "RuiProgress",
@@ -37,6 +41,7 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
37
41
  },
38
42
  setup(__props) {
39
43
  const CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS;
44
+ /** approximate width of `100%` in ems */
40
45
  function clampPercent(val) {
41
46
  return Math.max(0, Math.min(val ?? 100, 100));
42
47
  }
@@ -52,7 +57,8 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
52
57
  circularContainer: "inline-block relative",
53
58
  svg: "block",
54
59
  circle: "stroke-current",
55
- label: "dark:text-white"
60
+ circleTrack: "stroke-current opacity-20",
61
+ label: "text-rui-text"
56
62
  },
57
63
  variants: {
58
64
  color: {
@@ -85,7 +91,7 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
85
91
  }, {
86
92
  circular: true,
87
93
  hasLabel: true,
88
- class: { label: "absolute inset-0 flex items-center justify-center text-[0.6rem] leading-none" }
94
+ class: { label: "absolute inset-0 flex items-center justify-center leading-none tabular-nums whitespace-nowrap" }
89
95
  }],
90
96
  compoundSlots: [
91
97
  {
@@ -184,6 +190,17 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
184
190
  viewSize: 40 + scaledThickness
185
191
  };
186
192
  });
193
+ /**
194
+ * The circular label lives inside the ring, so it scales with both `size` and `thickness`.
195
+ * `fit` solves for the widest label (`100%`) fitting the chord it spans, always computed
196
+ * for that widest label so the text does not resize as the value climbs. It is capped by
197
+ * a sublinear curve so large rings do not end up with an oversized number in the middle.
198
+ */
199
+ const circularLabelStyle = computed(() => {
200
+ const innerRadius = Math.max((+__props.size - 2 * +__props.thickness) / 2, 0);
201
+ const fit = LABEL_BREATHING_ROOM * 2 * innerRadius / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);
202
+ return { fontSize: `${Math.min(fit, +__props.size * .15 + 6)}px` };
203
+ });
187
204
  const circularStrokeStyle = computed(() => ({
188
205
  strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,
189
206
  strokeDashoffset: `${get(progress) / 100 * -CIRCLE_CIRCUMFERENCE}`,
@@ -203,7 +220,15 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
203
220
  }, [(openBlock(), createElementBlock("svg", {
204
221
  class: normalizeClass(unref(ui).svg()),
205
222
  viewBox: `0 0 ${unref(circularGeometry).viewSize} ${unref(circularGeometry).viewSize}`
206
- }, [createElementVNode("circle", {
223
+ }, [__props.variant === unref(ProgressVariant).determinate ? (openBlock(), createElementBlock("circle", {
224
+ key: 0,
225
+ cx: "50%",
226
+ cy: "50%",
227
+ fill: "none",
228
+ r: CIRCLE_RADIUS,
229
+ class: normalizeClass(unref(ui).circleTrack()),
230
+ "stroke-width": unref(circularGeometry).scaledThickness
231
+ }, null, 10, _hoisted_3)) : createCommentVNode("", true), createElementVNode("circle", {
207
232
  cx: "50%",
208
233
  cy: "50%",
209
234
  fill: "none",
@@ -211,10 +236,12 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
211
236
  class: normalizeClass(unref(ui).circle()),
212
237
  style: normalizeStyle(__props.variant === unref(ProgressVariant).determinate ? unref(circularStrokeStyle) : void 0),
213
238
  "stroke-width": unref(circularGeometry).scaledThickness
214
- }, null, 14, _hoisted_3)], 10, _hoisted_2)), unref(hasLabel) ? (openBlock(), createElementBlock("div", {
239
+ }, null, 14, _hoisted_4)], 10, _hoisted_2)), unref(hasLabel) ? (openBlock(), createElementBlock("div", {
215
240
  key: 0,
216
- class: normalizeClass(unref(ui).label())
217
- }, toDisplayString(unref(label)), 3)) : createCommentVNode("", true)], 14, _hoisted_1)) : (openBlock(), createElementBlock("div", {
241
+ class: normalizeClass(unref(ui).label()),
242
+ style: normalizeStyle(unref(circularLabelStyle)),
243
+ "aria-hidden": "true"
244
+ }, toDisplayString(unref(label)), 7)) : createCommentVNode("", true)], 14, _hoisted_1)) : (openBlock(), createElementBlock("div", {
218
245
  key: 1,
219
246
  "aria-valuenow": __props.value,
220
247
  class: normalizeClass(unref(ui).progressbar()),
@@ -241,7 +268,7 @@ var RuiProgress_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defi
241
268
  class: normalizeClass(unref(ui).bar()),
242
269
  style: normalizeStyle(unref(barStyle))
243
270
  }, null, 6))
244
- ], 14, _hoisted_4)), unref(hasLabel) && !__props.circular ? (openBlock(), createElementBlock("div", {
271
+ ], 14, _hoisted_5)), unref(hasLabel) && !__props.circular ? (openBlock(), createElementBlock("div", {
245
272
  key: 2,
246
273
  class: normalizeClass(unref(ui).label())
247
274
  }, toDisplayString(unref(label)), 3)) : createCommentVNode("", true)], 2);
@@ -1 +1 @@
1
- {"version":3,"file":"RuiProgress.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * @example - 0 <= value <= 100\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * @example - 0 <= value <= 100\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n label: 'dark:text-white',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4' } },\n // Circular label (overlays the circle)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center text-[0.6rem] leading-none' } },\n ],\n compoundSlots: [\n // Rail background (track behind the bar)\n { slots: ['rail', 'bufferDots'], color: 'primary', class: 'bg-rui-primary/20 border-rui-primary/20' },\n { slots: ['rail', 'bufferDots'], color: 'secondary', class: 'bg-rui-secondary/20 border-rui-secondary/20' },\n { slots: ['rail', 'bufferDots'], color: 'error', class: 'bg-rui-error/20 border-rui-error/20' },\n { slots: ['rail', 'bufferDots'], color: 'warning', class: 'bg-rui-warning/20 border-rui-warning/20' },\n { slots: ['rail', 'bufferDots'], color: 'info', class: 'bg-rui-info/20 border-rui-info/20' },\n { slots: ['rail', 'bufferDots'], color: 'success', class: 'bg-rui-success/20 border-rui-success/20' },\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n transition: 'stroke-dashoffset 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"value\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"value\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiProgress.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * @example - 0 <= value <= 100\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * @example - 0 <= value <= 100\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** approximate width of `100%` in ems */\nconst LABEL_WIDTH_EM = 2.5;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.85;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: 'stroke-current opacity-20',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Rail background (track behind the bar)\n { slots: ['rail', 'bufferDots'], color: 'primary', class: 'bg-rui-primary/20 border-rui-primary/20' },\n { slots: ['rail', 'bufferDots'], color: 'secondary', class: 'bg-rui-secondary/20 border-rui-secondary/20' },\n { slots: ['rail', 'bufferDots'], color: 'error', class: 'bg-rui-error/20 border-rui-error/20' },\n { slots: ['rail', 'bufferDots'], color: 'warning', class: 'bg-rui-warning/20 border-rui-warning/20' },\n { slots: ['rail', 'bufferDots'], color: 'info', class: 'bg-rui-info/20 border-rui-info/20' },\n { slots: ['rail', 'bufferDots'], color: 'success', class: 'bg-rui-success/20 border-rui-success/20' },\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The circular label lives inside the ring, so it scales with both `size` and `thickness`.\n * `fit` solves for the widest label (`100%`) fitting the chord it spans, always computed\n * for that widest label so the text does not resize as the value climbs. It is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n const fit = (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n return { fontSize: `${Math.min(fit, +size * 0.15 + 6)}px` };\n});\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n transition: 'stroke-dashoffset 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"value\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"value\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
package/dist/style.css CHANGED
@@ -3256,6 +3256,11 @@ html[data-theme="dark"], html.dark {
3256
3256
  .outline-transparent {
3257
3257
  outline-color: transparent;
3258
3258
  }
3259
+ .ring {
3260
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
3261
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
3262
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
3263
+ }
3259
3264
  .ring-2 {
3260
3265
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
3261
3266
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json.schemastore.org/web-types",
3
3
  "framework": "vue",
4
4
  "name": "@rotki/ui-library",
5
- "version": "2.23.3",
5
+ "version": "2.23.4",
6
6
  "js-types-syntax": "typescript",
7
7
  "description-markup": "markdown",
8
8
  "contributions": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotki/ui-library",
3
- "version": "2.23.3",
3
+ "version": "2.23.4",
4
4
  "description": "A vue design system and component library for rotki",
5
5
  "type": "module",
6
6
  "keywords": [