@rotki/ui-library 3.0.0-beta.1 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +3 -3
  2. package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js +1 -1
  4. package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js +1 -1
  5. package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/components/buttons/button/RuiButton.js.map +1 -1
  7. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +10 -10
  8. package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/buttons/button/button-styles.js +10 -2
  10. package/dist/components/buttons/button/button-styles.js.map +1 -1
  11. package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  12. package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js +1 -1
  13. package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +1 -1
  14. package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  16. package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +1 -1
  17. package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/components/color-picker/RuiColorDisplay.vue_vue_type_script_setup_true_lang.js +1 -1
  19. package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js +1 -1
  20. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +9 -10
  21. package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js +3 -4
  23. package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +33 -33
  25. package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  26. package/dist/components/date-time-picker/use-date-bounds.js +1 -1
  27. package/dist/components/date-time-picker/use-date-time-selection.js +65 -66
  28. package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
  29. package/dist/components/date-time-picker/use-input-handler.js +1 -1
  30. package/dist/components/date-time-picker/use-keyboard-handler.js +29 -30
  31. package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
  32. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +24 -24
  33. package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +49 -49
  35. package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
  37. package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  38. package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
  39. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +19 -17
  40. package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +1 -1
  42. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +11 -11
  43. package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +17 -17
  45. package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  46. package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
  47. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +21 -21
  48. package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/forms/text-field/RuiTextField.js.map +1 -1
  50. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +2 -0
  51. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +24 -20
  52. package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
  54. package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +11 -1
  55. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +3 -3
  56. package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +1 -1
  58. package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js +1 -1
  59. package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js +1 -1
  60. package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js +1 -1
  61. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +17 -17
  62. package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
  64. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js +9 -9
  65. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js +3 -4
  67. package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js +1 -1
  69. package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js +1 -1
  70. package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +1 -1
  71. package/dist/components/steppers/RuiStepper.js.map +1 -1
  72. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js +13 -8
  73. package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +27 -27
  75. package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -1
  77. package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +1 -1
  78. package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +1 -1
  79. package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js +1 -1
  80. package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +1 -1
  81. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +23 -23
  82. package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/components/tables/use-pagination-navigation.js +1 -1
  84. package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js +1 -1
  85. package/dist/components/tabs/tab/use-tab-link.js +1 -1
  86. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +6 -6
  87. package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +11 -12
  89. package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/tabs/tabs/use-tab-indicator.js +7 -7
  91. package/dist/components/tabs/tabs/use-tab-indicator.js.map +1 -1
  92. package/dist/components/tabs/tabs/use-tab-keyboard.js +1 -1
  93. package/dist/components/tabs/tabs/use-tab-scroll.js +15 -15
  94. package/dist/components/tabs/tabs/use-tab-scroll.js.map +1 -1
  95. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +60 -61
  96. package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/composables/breakpoint.js +3 -3
  98. package/dist/composables/breakpoint.js.map +1 -1
  99. package/dist/composables/dropdown-menu.d.ts +9 -9
  100. package/dist/composables/dropdown-menu.js +32 -32
  101. package/dist/composables/dropdown-menu.js.map +1 -1
  102. package/dist/composables/floating.d.ts +1 -1
  103. package/dist/composables/floating.js +11 -11
  104. package/dist/composables/floating.js.map +1 -1
  105. package/dist/composables/forms/auto-complete/focus.js +16 -17
  106. package/dist/composables/forms/auto-complete/focus.js.map +1 -1
  107. package/dist/composables/forms/auto-complete/keyboard-navigation.js +1 -1
  108. package/dist/composables/forms/auto-complete/search.js +6 -7
  109. package/dist/composables/forms/auto-complete/search.js.map +1 -1
  110. package/dist/composables/forms/auto-complete/selection.js +1 -1
  111. package/dist/composables/forms/auto-complete/value.js +1 -1
  112. package/dist/composables/forms/category-picker/use-category-picker.js +1 -1
  113. package/dist/composables/forms/use-prepend-append-width.js +6 -6
  114. package/dist/composables/forms/use-prepend-append-width.js.map +1 -1
  115. package/dist/composables/keyboard-scroll.js +5 -5
  116. package/dist/composables/keyboard-scroll.js.map +1 -1
  117. package/dist/composables/overlay-stack.js +1 -1
  118. package/dist/composables/sticky-header.js +8 -8
  119. package/dist/composables/sticky-header.js.map +1 -1
  120. package/dist/composables/tables/data-table/columns.js +1 -1
  121. package/dist/composables/tables/data-table/expansion.js +1 -1
  122. package/dist/composables/tables/data-table/grouping.js +27 -28
  123. package/dist/composables/tables/data-table/grouping.js.map +1 -1
  124. package/dist/composables/tables/data-table/page-scroll.d.ts +7 -5
  125. package/dist/composables/tables/data-table/page-scroll.js +48 -17
  126. package/dist/composables/tables/data-table/page-scroll.js.map +1 -1
  127. package/dist/composables/tables/data-table/pagination.js +1 -1
  128. package/dist/composables/tables/data-table/selection.js +37 -38
  129. package/dist/composables/tables/data-table/selection.js.map +1 -1
  130. package/dist/composables/tables/data-table/sort.js +1 -1
  131. package/dist/composables/theme.js +12 -12
  132. package/dist/composables/theme.js.map +1 -1
  133. package/dist/composables/timeout-manager.js +1 -1
  134. package/dist/index.d.ts +2 -2
  135. package/dist/index.js +2 -2
  136. package/dist/index.js.map +1 -1
  137. package/dist/style.css +2 -18
  138. package/dist/types/dom.d.ts +9 -0
  139. package/dist/types/theme.d.ts +2 -3
  140. package/dist/types/theme.js.map +1 -1
  141. package/dist/utils/form-text-detail.js +1 -1
  142. package/dist/utils/helpers.js +1 -1
  143. package/dist/vendor/@vueuse/core/dist/index.js +1577 -0
  144. package/dist/vendor/@vueuse/core/dist/index.js.map +1 -0
  145. package/dist/vendor/@vueuse/shared/dist/index.js +563 -0
  146. package/dist/vendor/@vueuse/shared/dist/index.js.map +1 -0
  147. package/dist/vite-plugin/index.js +5 -6
  148. package/dist/vite-plugin/index.js.map +1 -1
  149. package/dist/web-types.json +9 -2
  150. package/package.json +5 -4
@@ -1,10 +1,10 @@
1
+ import { get, objectPick, set } from "../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import { useFormTextDetail } from "../../../utils/form-text-detail.js";
2
3
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
3
4
  import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
4
5
  import { RuiCheckboxGroupContextKey } from "./checkbox-group/context.js";
5
6
  import { checkControlStyles } from "../check-control-styles.js";
6
7
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, guardReactiveProps, inject, isRef, mergeModels, mergeProps, normalizeClass, normalizeProps, openBlock, renderSlot, toDisplayString, toValue, unref, useModel, useTemplateRef, vModelCheckbox, watch, withDirectives } from "vue";
7
- import { get, objectPick, set } from "@vueuse/shared";
8
8
  //#region src/components/forms/checkbox/RuiCheckbox.vue?vue&type=script&setup=true&lang.ts
9
9
  var _hoisted_1 = [
10
10
  "data-disabled",
@@ -1,7 +1,7 @@
1
+ import { get, set } from "../../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import RuiFormTextDetail_default from "../../../helpers/RuiFormTextDetail.js";
2
3
  import { RuiCheckboxGroupContextKey } from "./context.js";
3
4
  import { createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, mergeModels, mergeProps, normalizeClass, openBlock, provide, renderSlot, toDisplayString, useModel } from "vue";
4
- import { get, set } from "@vueuse/shared";
5
5
  //#region src/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue?vue&type=script&setup=true&lang.ts
6
6
  var _hoisted_1 = {
7
7
  key: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"RuiFileUpload.js","names":[],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { RuiIcons } from '@/icons';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or \\{button\\}\" copy. With `noDrop` the default is empty, so only the button shows. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = undefined,\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\n// a click-only dropzone does not offer dragging\nconst resolvedUploadText = computed<string>(() => uploadText ?? (noDrop ? '' : 'Drag and drop or'));\n\ntype WellTone = 'primary' | 'error' | 'success';\n\n// the icon well follows the dropzone's state, like its border\nconst wellTone = computed<WellTone>(() => {\n if (get(hasError))\n return 'error';\n if (uploaded)\n return 'success';\n return 'primary';\n});\n\nconst wellIcon = computed<RuiIcons>(() => {\n const tone = get(wellTone);\n if (tone === 'error')\n return 'lu-circle-alert';\n if (tone === 'success')\n return 'lu-circle-check';\n return 'lu-file-up';\n});\n\n// the 10% tint vanishes on a dark page, so dark doubles it\nconst wellClasses: Record<WellTone, string> = {\n primary: 'bg-rui-primary-soft dark:bg-rui-primary/20',\n error: 'bg-rui-error-soft dark:bg-rui-error/20',\n success: 'bg-rui-success-soft dark:bg-rui-success/20',\n};\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (!target?.files)\n return;\n setFiles(Array.from(target.files));\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-outline dark:border-rui-neutral-400 rounded-rui-panel w-full relative border-dashed transition\"\n :class=\"{\n 'border-rui-primary! bg-rui-primary-subtle': isOverDropZone && !disabled && !noDrop,\n 'border-rui-error! border-solid! bg-rui-error-subtle': hasError,\n 'border-rui-success! border-solid! bg-rui-success-subtle': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary-soft dark:bg-rui-primary/20 rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-hover transition focus-visible:focus-ring outline-hidden\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"wellClasses[wellTone]\"\n data-id=\"icon-well\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"wellIcon\"\n :color=\"wellTone\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span v-if=\"resolvedUploadText\">{{ resolvedUploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :class=\"{ 'first-letter:uppercase': !resolvedUploadText }\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RuiFileUpload.js","names":[],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { RuiIcons } from '@/icons';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or \\{button\\}\" copy. With `noDrop` the default is empty, so only the button shows. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = undefined,\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\n// a click-only dropzone does not offer dragging\nconst resolvedUploadText = computed<string>(() => uploadText ?? (noDrop ? '' : 'Drag and drop or'));\n\ntype WellTone = 'primary' | 'error' | 'success';\n\n// the icon well follows the dropzone's state, like its border\nconst wellTone = computed<WellTone>(() => {\n if (get(hasError))\n return 'error';\n if (uploaded)\n return 'success';\n return 'primary';\n});\n\nconst wellIcon = computed<RuiIcons>(() => {\n const tone = get(wellTone);\n if (tone === 'error')\n return 'lu-circle-alert';\n if (tone === 'success')\n return 'lu-circle-check';\n return 'lu-file-up';\n});\n\n// the 10% tint vanishes on a dark page, so dark doubles it\nconst wellClasses: Record<WellTone, string> = {\n primary: 'bg-rui-primary-soft dark:bg-rui-primary/20',\n error: 'bg-rui-error-soft dark:bg-rui-error/20',\n success: 'bg-rui-success-soft dark:bg-rui-success/20',\n};\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement) || !target.files)\n return;\n const picked = Array.from(target.files);\n // the model owns the selection; a cleared input fires `change` for the same file again\n target.value = '';\n setFiles(picked);\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-outline dark:border-rui-neutral-400 rounded-rui-panel w-full relative border-dashed transition\"\n :class=\"{\n 'border-rui-primary! bg-rui-primary-subtle': isOverDropZone && !disabled && !noDrop,\n 'border-rui-error! border-solid! bg-rui-error-subtle': hasError,\n 'border-rui-success! border-solid! bg-rui-success-subtle': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary-soft dark:bg-rui-primary/20 rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-hover transition focus-visible:focus-ring outline-hidden\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"wellClasses[wellTone]\"\n data-id=\"icon-well\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"wellIcon\"\n :color=\"wellTone\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span v-if=\"resolvedUploadText\">{{ resolvedUploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :class=\"{ 'first-letter:uppercase': !resolvedUploadText }\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1,11 +1,11 @@
1
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
+ import { useDropZone } from "../../../vendor/@vueuse/core/dist/index.js";
1
3
  import RuiIcon_default from "../../icons/RuiIcon.js";
2
4
  import RuiProgress_default from "../../progress/RuiProgress.js";
3
5
  import { useFormTextDetail } from "../../../utils/form-text-detail.js";
4
6
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
5
7
  import { formatFileSize, getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
6
8
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, guardReactiveProps, mergeModels, mergeProps, normalizeClass, normalizeProps, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useModel, useTemplateRef, watch } from "vue";
7
- import { useDropZone } from "@vueuse/core";
8
- import { get as get$1, set as set$1 } from "@vueuse/shared";
9
9
  //#region src/components/forms/file-upload/RuiFileUpload.vue?vue&type=script&setup=true&lang.ts
10
10
  var _hoisted_1 = [
11
11
  "data-disabled",
@@ -90,29 +90,29 @@ var RuiFileUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
90
90
  const input = useTemplateRef("input");
91
91
  const internalError = ref("");
92
92
  const files = computed(() => {
93
- const value = get$1(modelValue);
93
+ const value = get(modelValue);
94
94
  if (!value) return [];
95
95
  return Array.isArray(value) ? value : [value];
96
96
  });
97
- const hasFiles = computed(() => get$1(files).length > 0);
97
+ const hasFiles = computed(() => get(files).length > 0);
98
98
  const progressLabel = computed(() => {
99
99
  const value = __props.progress;
100
100
  return value === void 0 ? void 0 : `${Math.round(value)}%`;
101
101
  });
102
102
  const combinedErrorMessages = computed(() => {
103
103
  const external = Array.isArray(__props.errorMessages) ? __props.errorMessages : [__props.errorMessages];
104
- const internal = get$1(internalError);
104
+ const internal = get(internalError);
105
105
  return [...external.filter(Boolean), ...internal ? [internal] : []];
106
106
  });
107
107
  const { hasError } = useFormTextDetail(combinedErrorMessages, () => []);
108
108
  const resolvedUploadText = computed(() => __props.uploadText ?? (__props.noDrop ? "" : "Drag and drop or"));
109
109
  const wellTone = computed(() => {
110
- if (get$1(hasError)) return "error";
110
+ if (get(hasError)) return "error";
111
111
  if (__props.uploaded) return "success";
112
112
  return "primary";
113
113
  });
114
114
  const wellIcon = computed(() => {
115
- const tone = get$1(wellTone);
115
+ const tone = get(wellTone);
116
116
  if (tone === "error") return "lu-circle-alert";
117
117
  if (tone === "success") return "lu-circle-check";
118
118
  return "lu-file-up";
@@ -134,11 +134,11 @@ var RuiFileUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
134
134
  });
135
135
  }
136
136
  function reportError(message) {
137
- set$1(internalError, message);
137
+ set(internalError, message);
138
138
  emit("error", message);
139
139
  }
140
140
  function clearInternalError() {
141
- set$1(internalError, "");
141
+ set(internalError, "");
142
142
  }
143
143
  function validate(candidates) {
144
144
  if (candidates.length === 0) return void 0;
@@ -162,23 +162,25 @@ var RuiFileUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
162
162
  const validated = validate(candidates);
163
163
  if (!validated) return;
164
164
  clearInternalError();
165
- set$1(modelValue, __props.multiple ? validated : validated[0]);
165
+ set(modelValue, __props.multiple ? validated : validated[0]);
166
166
  }
167
167
  function removeFile(target) {
168
168
  clearInternalError();
169
- const inputEl = get$1(input);
169
+ const inputEl = get(input);
170
170
  if (inputEl) inputEl.value = "";
171
171
  if (!target || !__props.multiple) {
172
- set$1(modelValue, __props.multiple ? [] : void 0);
172
+ set(modelValue, __props.multiple ? [] : void 0);
173
173
  return;
174
174
  }
175
- const remaining = get$1(files).filter((file) => file !== target);
176
- set$1(modelValue, remaining);
175
+ const remaining = get(files).filter((file) => file !== target);
176
+ set(modelValue, remaining);
177
177
  }
178
178
  function onSelect(event) {
179
179
  const target = event.target;
180
- if (!target?.files) return;
181
- setFiles(Array.from(target.files));
180
+ if (!(target instanceof HTMLInputElement) || !target.files) return;
181
+ const picked = Array.from(target.files);
182
+ target.value = "";
183
+ setFiles(picked);
182
184
  }
183
185
  function onDrop(dropped) {
184
186
  if (__props.disabled || __props.noDrop || !dropped || dropped.length === 0) return;
@@ -187,7 +189,7 @@ var RuiFileUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
187
189
  const { isOverDropZone } = useDropZone(wrapper, { onDrop });
188
190
  function openPicker() {
189
191
  if (__props.disabled) return;
190
- get$1(input)?.click();
192
+ get(input)?.click();
191
193
  }
192
194
  watch(() => __props.errorMessages, () => clearInternalError());
193
195
  __expose({
@@ -1 +1 @@
1
- {"version":3,"file":"RuiFileUpload.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { RuiIcons } from '@/icons';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or \\{button\\}\" copy. With `noDrop` the default is empty, so only the button shows. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = undefined,\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\n// a click-only dropzone does not offer dragging\nconst resolvedUploadText = computed<string>(() => uploadText ?? (noDrop ? '' : 'Drag and drop or'));\n\ntype WellTone = 'primary' | 'error' | 'success';\n\n// the icon well follows the dropzone's state, like its border\nconst wellTone = computed<WellTone>(() => {\n if (get(hasError))\n return 'error';\n if (uploaded)\n return 'success';\n return 'primary';\n});\n\nconst wellIcon = computed<RuiIcons>(() => {\n const tone = get(wellTone);\n if (tone === 'error')\n return 'lu-circle-alert';\n if (tone === 'success')\n return 'lu-circle-check';\n return 'lu-file-up';\n});\n\n// the 10% tint vanishes on a dark page, so dark doubles it\nconst wellClasses: Record<WellTone, string> = {\n primary: 'bg-rui-primary-soft dark:bg-rui-primary/20',\n error: 'bg-rui-error-soft dark:bg-rui-error/20',\n success: 'bg-rui-success-soft dark:bg-rui-success/20',\n};\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (!target?.files)\n return;\n setFiles(Array.from(target.files));\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-outline dark:border-rui-neutral-400 rounded-rui-panel w-full relative border-dashed transition\"\n :class=\"{\n 'border-rui-primary! bg-rui-primary-subtle': isOverDropZone && !disabled && !noDrop,\n 'border-rui-error! border-solid! bg-rui-error-subtle': hasError,\n 'border-rui-success! border-solid! bg-rui-success-subtle': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary-soft dark:bg-rui-primary/20 rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-hover transition focus-visible:focus-ring outline-hidden\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"wellClasses[wellTone]\"\n data-id=\"icon-well\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"wellIcon\"\n :color=\"wellTone\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span v-if=\"resolvedUploadText\">{{ resolvedUploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :class=\"{ 'first-letter:uppercase': !resolvedUploadText }\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RuiFileUpload.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { RuiIcons } from '@/icons';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or \\{button\\}\" copy. With `noDrop` the default is empty, so only the button shows. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = undefined,\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\n// a click-only dropzone does not offer dragging\nconst resolvedUploadText = computed<string>(() => uploadText ?? (noDrop ? '' : 'Drag and drop or'));\n\ntype WellTone = 'primary' | 'error' | 'success';\n\n// the icon well follows the dropzone's state, like its border\nconst wellTone = computed<WellTone>(() => {\n if (get(hasError))\n return 'error';\n if (uploaded)\n return 'success';\n return 'primary';\n});\n\nconst wellIcon = computed<RuiIcons>(() => {\n const tone = get(wellTone);\n if (tone === 'error')\n return 'lu-circle-alert';\n if (tone === 'success')\n return 'lu-circle-check';\n return 'lu-file-up';\n});\n\n// the 10% tint vanishes on a dark page, so dark doubles it\nconst wellClasses: Record<WellTone, string> = {\n primary: 'bg-rui-primary-soft dark:bg-rui-primary/20',\n error: 'bg-rui-error-soft dark:bg-rui-error/20',\n success: 'bg-rui-success-soft dark:bg-rui-success/20',\n};\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement) || !target.files)\n return;\n const picked = Array.from(target.files);\n // the model owns the selection; a cleared input fires `change` for the same file again\n target.value = '';\n setFiles(picked);\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-outline dark:border-rui-neutral-400 rounded-rui-panel w-full relative border-dashed transition\"\n :class=\"{\n 'border-rui-primary! bg-rui-primary-subtle': isOverDropZone && !disabled && !noDrop,\n 'border-rui-error! border-solid! bg-rui-error-subtle': hasError,\n 'border-rui-success! border-solid! bg-rui-success-subtle': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary-soft dark:bg-rui-primary/20 rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-hover transition focus-visible:focus-ring outline-hidden\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"wellClasses[wellTone]\"\n data-id=\"icon-well\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"wellIcon\"\n :color=\"wellTone\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span v-if=\"resolvedUploadText\">{{ resolvedUploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :class=\"{ 'first-letter:uppercase': !resolvedUploadText }\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
+ import { get, set } from "../../../../vendor/@vueuse/shared/dist/index.js";
1
2
  import { useFormTextDetail } from "../../../../utils/form-text-detail.js";
2
3
  import RuiFormTextDetail_default from "../../../helpers/RuiFormTextDetail.js";
3
4
  import { getNonRootAttrs, getRootAttrs } from "../../../../utils/helpers.js";
4
5
  import { checkControlStyles } from "../../check-control-styles.js";
5
6
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, guardReactiveProps, mergeModels, mergeProps, normalizeClass, normalizeProps, openBlock, renderSlot, toDisplayString, unref, useModel } from "vue";
6
- import { get, set } from "@vueuse/shared";
7
7
  //#region src/components/forms/radio-button/radio/RuiRadio.vue?vue&type=script&setup=true&lang.ts
8
8
  var _hoisted_1 = [
9
9
  "data-disabled",
@@ -1,4 +1,6 @@
1
1
  import { useLabelPlacement } from "../../../composables/defaults/field.js";
2
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
3
+ import { useFocus } from "../../../vendor/@vueuse/core/dist/index.js";
2
4
  import { cn } from "../../../utils/tv.js";
3
5
  import RuiIcon_default from "../../icons/RuiIcon.js";
4
6
  import RuiProgress_default from "../../progress/RuiProgress.js";
@@ -11,8 +13,6 @@ import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
11
13
  import { getOptionHeight, useDropdownMenu } from "../../../composables/dropdown-menu.js";
12
14
  import { menuSelectStyles } from "./menu-select-styles.js";
13
15
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, guardReactiveProps, isRef, mergeModels, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useModel, useTemplateRef, withCtx, withKeys, withModifiers } from "vue";
14
- import { useFocus } from "@vueuse/core";
15
- import { get as get$1, set as set$1 } from "@vueuse/shared";
16
16
  //#region src/components/forms/select/RuiMenuSelect.vue?vue&type=script&setup=true&lang.ts
17
17
  var _hoisted_1 = [
18
18
  "disabled",
@@ -98,18 +98,18 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
98
98
  const { hasError, hasSuccess } = useFormTextDetail(() => __props.errorMessages, () => __props.successMessages);
99
99
  const value = computed({
100
100
  get: () => {
101
- const value = get$1(modelValue);
101
+ const value = get(modelValue);
102
102
  if (__props.keyAttr) return __props.options.find((option) => option[__props.keyAttr] === value);
103
103
  return value;
104
104
  },
105
105
  set: (selected) => {
106
106
  const selection = __props.keyAttr && selected ? selected[__props.keyAttr] : selected;
107
- set$1(modelValue, selection);
107
+ set(modelValue, selection);
108
108
  }
109
109
  });
110
110
  function setValue(val) {
111
- set$1(value, val);
112
- set$1(focused, true);
111
+ set(value, val);
112
+ set(focused, true);
113
113
  }
114
114
  const { containerProps, wrapperProps, renderedData, isOpen, menuWidth, getText, getIdentifier, isActiveItem, modelHighlightedIndex, moveHighlight, applyHighlighted, valueKey } = useDropdownMenu({
115
115
  itemHeight: __props.itemHeight ?? getOptionHeight(__props.dense),
@@ -126,17 +126,17 @@ var RuiMenuSelect_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
126
126
  appendWidth: __props.appendWidth
127
127
  });
128
128
  const ui = computed(() => menuSelectStyles({
129
- opened: get$1(isOpen),
130
- hovered: get$1(isHovered),
129
+ opened: get(isOpen),
130
+ hovered: get(isHovered),
131
131
  dense: __props.dense,
132
132
  disabled: __props.disabled,
133
133
  readonly: __props.readOnly,
134
- hasError: get$1(hasError),
135
- hasSuccess: get$1(hasSuccess) && !get$1(hasError)
134
+ hasError: get(hasError),
135
+ hasSuccess: get(hasSuccess) && !get(hasError)
136
136
  }));
137
137
  const highlightedClass = menuSelectStyles({}).highlighted();
138
138
  function clear() {
139
- set$1(modelValue, void 0);
139
+ set(modelValue, void 0);
140
140
  }
141
141
  const menuFloatingOptions = computed(() => ({
142
142
  placement: Placement.bottomStart,
@@ -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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { menuSelectStyles } 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 LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { getOptionHeight, 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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\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 labelPlacement = undefined,\n menuOptions,\n classNames,\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n prependWidth,\n appendWidth,\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 readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => 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);\nconst labelId = useId();\n\nconst placement = useLabelPlacement(() => labelPlacement);\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 modelHighlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? getOptionHeight(dense),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n prependWidth,\n appendWidth,\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\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 :class-names=\"{ ...menuOptions?.classNames, details: ['px-0', cn(menuOptions?.classNames?.details) ?? ''] }\"\n :options=\"menuFloatingOptions\"\n close-on-content-click\n full-width\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 role=\"listbox\"\n >\n <template\n v-if=\"label\"\n #label\n >\n <RuiFieldLabel\n :id=\"labelId\"\n :text=\"label\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <!-- a select-only combobox: the button opens a listbox of options, and carries the field's state -->\n <button\n ref=\"activator\"\n role=\"combobox\"\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 :aria-labelledby=\"label ? labelId : undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) })\"\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=\"modelHighlightedIndex = 0\"\n @keydown.end.prevent=\"modelHighlightedIndex = options.length - 1\"\n >\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 && !readOnly\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && 'visible!', { 'mr-2': !dense }]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"2\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset :class=\"ui.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) })\"\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 role=\"option\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"modelHighlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && modelHighlightedIndex === _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\"\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 RuiFieldLabel from '@/components/forms/field-label/RuiFieldLabel.vue';\nimport { menuSelectStyles } 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 LabelPlacement, useLabelPlacement } from '@/composables/defaults/field';\nimport { getOptionHeight, 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 /** Where the label shows; falls back to the nearest `RuiFieldDefaults`, then the app default, then `top`. */\n labelPlacement?: LabelPlacement;\n menuOptions?: MenuProps;\n classNames?: RuiMenuSelectClassNames;\n prependWidth?: number;\n appendWidth?: number;\n itemHeight?: number;\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 labelPlacement = undefined,\n menuOptions,\n classNames,\n hint,\n keyAttr,\n textAttr,\n itemHeight,\n prependWidth,\n appendWidth,\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 readOnly: boolean;\n attrs: Record<string, unknown>;\n open: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => 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);\nconst labelId = useId();\n\nconst placement = useLabelPlacement(() => labelPlacement);\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 modelHighlightedIndex,\n moveHighlight,\n applyHighlighted,\n valueKey,\n} = useDropdownMenu<TValue, TItem>({\n itemHeight: itemHeight ?? getOptionHeight(dense),\n keyAttr,\n textAttr,\n options: () => options,\n dense: () => dense,\n value,\n menuRef,\n disabled: () => disabled,\n autoSelectFirst,\n setValue,\n prependWidth,\n appendWidth,\n});\n\nconst ui = computed<ReturnType<typeof menuSelectStyles>>(() => menuSelectStyles({\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 :class-names=\"{ ...menuOptions?.classNames, details: ['px-0', cn(menuOptions?.classNames?.details) ?? ''] }\"\n :options=\"menuFloatingOptions\"\n close-on-content-click\n full-width\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 role=\"listbox\"\n >\n <template\n v-if=\"label\"\n #label\n >\n <RuiFieldLabel\n :id=\"labelId\"\n :text=\"label\"\n :hidden=\"placement === 'hidden'\"\n :required=\"required\"\n :disabled=\"disabled\"\n />\n </template>\n <template #activator=\"{ attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\">\n <slot\n name=\"activator\"\n v-bind=\"{ disabled, value, readOnly, attrs, open, hasError: slotHasError, hasSuccess: slotHasSuccess }\"\n >\n <!-- a select-only combobox: the button opens a listbox of options, and carries the field's state -->\n <button\n ref=\"activator\"\n role=\"combobox\"\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 :aria-labelledby=\"label ? labelId : undefined\"\n type=\"button\"\n :tabindex=\"disabled || readOnly ? -1 : 0\"\n :class=\"ui.activator({ class: cn(classNames?.label) })\"\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=\"modelHighlightedIndex = 0\"\n @keydown.end.prevent=\"modelHighlightedIndex = options.length - 1\"\n >\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 && !readOnly\"\n data-id=\"clear\"\n :class=\"[ui.clear(), focused && 'visible!', { 'mr-2': !dense }]\"\n @click.stop.prevent=\"clear()\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </span>\n\n <span :class=\"ui.iconWrapper()\">\n <RuiIcon\n :class=\"ui.icon()\"\n :size=\"dense ? 16 : 20\"\n name=\"lu-chevron-down\"\n />\n </span>\n\n <RuiProgress\n v-if=\"loading\"\n :class=\"ui.progress()\"\n color=\"primary\"\n thickness=\"2\"\n variant=\"indeterminate\"\n />\n </button>\n <fieldset :class=\"ui.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) })\"\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 role=\"option\"\n :aria-selected=\"isActiveItem(item)\"\n :size=\"dense ? 'sm' : undefined\"\n variant=\"list\"\n :data-highlighted=\"modelHighlightedIndex === _index\"\n :class=\"{\n [highlightedClass]: !isActiveItem(item) && modelHighlightedIndex === _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\"\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,3 +1,5 @@
1
+ import { get, set } from "../../../vendor/@vueuse/shared/dist/index.js";
2
+ import { useElementBounding, useEventListener } from "../../../vendor/@vueuse/core/dist/index.js";
1
3
  import { cn } from "../../../utils/tv.js";
2
4
  import { useFormTextDetail } from "../../../utils/form-text-detail.js";
3
5
  import RuiFormTextDetail_default from "../../helpers/RuiFormTextDetail.js";
@@ -6,8 +8,6 @@ import { getNonRootAttrs, getRootAttrs } from "../../../utils/helpers.js";
6
8
  import RuiSliderTicks_default from "./RuiSliderTicks.js";
7
9
  import { HIGHLIGHT_COLOR_MAP, HIGHLIGHT_DEFAULT, SliderInteraction, sliderStyles } from "./slider-styles.js";
8
10
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeModels, mergeProps, normalizeClass, normalizeStyle, openBlock, ref, toDisplayString, unref, useAttrs, useId, useModel, useTemplateRef, vModelText, withDirectives } from "vue";
9
- import { useElementBounding, useEventListener } from "@vueuse/core";
10
- import { get as get$1, set as set$1 } from "@vueuse/shared";
11
11
  //#region src/components/forms/slider/RuiSlider.vue?vue&type=script&setup=true&lang.ts
12
12
  var _hoisted_1 = ["data-error"];
13
13
  var _hoisted_2 = [
@@ -84,36 +84,36 @@ var RuiSlider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
84
84
  });
85
85
  const { width, height } = useElementBounding(outer);
86
86
  const bigTick = computed(() => __props.tickSize > BIG_TICK_THRESHOLD);
87
- useEventListener(document, "mouseup", () => set$1(isActive, false));
87
+ useEventListener(document, "mouseup", () => set(isActive, false));
88
88
  const interaction = computed(() => {
89
89
  if (__props.disabled) return SliderInteraction.idle;
90
- if (get$1(isActive)) return SliderInteraction.active;
91
- if (get$1(isFocused)) return SliderInteraction.focus;
92
- if (get$1(isHovered)) return SliderInteraction.hover;
90
+ if (get(isActive)) return SliderInteraction.active;
91
+ if (get(isFocused)) return SliderInteraction.focus;
92
+ if (get(isHovered)) return SliderInteraction.hover;
93
93
  return SliderInteraction.idle;
94
94
  });
95
95
  const ui = computed(() => sliderStyles({
96
96
  disabled: __props.disabled,
97
97
  vertical: __props.vertical,
98
98
  color: __props.color,
99
- bigTick: get$1(bigTick),
99
+ bigTick: get(bigTick),
100
100
  hasLabel: !!__props.label
101
101
  }));
102
102
  const trackUi = computed(() => sliderStyles({
103
103
  disabled: __props.disabled,
104
104
  vertical: __props.vertical,
105
- interaction: get$1(interaction),
105
+ interaction: get(interaction),
106
106
  color: __props.color,
107
- bigTick: get$1(bigTick)
107
+ bigTick: get(bigTick)
108
108
  }));
109
109
  const totalTicks = computed(() => (__props.max - __props.min) / __props.step);
110
- const currentTick = computed(() => Math.round((get$1(modelValue) - __props.min) / __props.step));
110
+ const currentTick = computed(() => Math.round((get(modelValue) - __props.min) / __props.step));
111
111
  const trackWidth = computed(() => {
112
- return `${Math.min(100, Math.max(0, Math.round(get$1(currentTick) / get$1(totalTicks) * 100)))}%`;
112
+ return `${Math.min(100, Math.max(0, Math.round(get(currentTick) / get(totalTicks) * 100)))}%`;
113
113
  });
114
114
  const innerStyle = computed(() => {
115
- const w = `${get$1(width)}px`;
116
- const h = `${get$1(height)}px`;
115
+ const w = `${get(width)}px`;
116
+ const h = `${get(height)}px`;
117
117
  const style = {
118
118
  width: __props.vertical ? h : w,
119
119
  height: __props.vertical ? w : h
@@ -126,23 +126,23 @@ var RuiSlider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
126
126
  });
127
127
  const tickSizePx = computed(() => `${__props.tickSize}px`);
128
128
  const ticksStyle = computed(() => {
129
- const size = get$1(tickSizePx);
129
+ const size = get(tickSizePx);
130
130
  return {
131
131
  margin: `0 calc(${size} / -2)`,
132
132
  width: `calc(100% + ${size})`
133
133
  };
134
134
  });
135
135
  const tickStyle = computed(() => {
136
- const size = get$1(tickSizePx);
136
+ const size = get(tickSizePx);
137
137
  return {
138
138
  width: size,
139
139
  height: size
140
140
  };
141
141
  });
142
- const highlightClass = computed(() => get$1(bigTick) ? HIGHLIGHT_COLOR_MAP[__props.color] : HIGHLIGHT_DEFAULT);
142
+ const highlightClass = computed(() => get(bigTick) ? HIGHLIGHT_COLOR_MAP[__props.color] : HIGHLIGHT_DEFAULT);
143
143
  const tickClassOverride = computed(() => cn(__props.classNames?.tick));
144
144
  function isHighlightedTick(index) {
145
- return index <= get$1(currentTick);
145
+ return index <= get(currentTick);
146
146
  }
147
147
  return (_ctx, _cache) => {
148
148
  return openBlock(), createElementBlock("div", mergeProps(unref(getRootAttrs)(_ctx.$attrs), { class: unref(ui).root() }), [