@treeui/vue 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/dist/components/TAppShell.cjs.map +1 -1
  2. package/dist/components/TAppShell.js.map +1 -1
  3. package/dist/components/TAppShell.vue.d.ts +25 -0
  4. package/dist/components/TAppShell.vue.d.ts.map +1 -1
  5. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs +1 -1
  6. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  7. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js +166 -104
  8. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/TButton.cjs.map +1 -1
  10. package/dist/components/TButton.js.map +1 -1
  11. package/dist/components/TButton.vue.d.ts +8 -2
  12. package/dist/components/TButton.vue.d.ts.map +1 -1
  13. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs +1 -1
  14. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  15. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js +12 -3
  16. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/TChart.cjs.map +1 -1
  18. package/dist/components/TChart.js.map +1 -1
  19. package/dist/components/TChart.vue.d.ts.map +1 -1
  20. package/dist/components/TChart.vue_vue_type_script_setup_true_lang.cjs +1 -1
  21. package/dist/components/TChart.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  22. package/dist/components/TChart.vue_vue_type_script_setup_true_lang.js +58 -58
  23. package/dist/components/TChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/TColorSwatch.cjs +2 -0
  25. package/dist/components/TColorSwatch.cjs.map +1 -0
  26. package/dist/components/TColorSwatch.js +7 -0
  27. package/dist/components/TColorSwatch.js.map +1 -0
  28. package/dist/components/TColorSwatch.vue.d.ts +33 -0
  29. package/dist/components/TColorSwatch.vue.d.ts.map +1 -0
  30. package/dist/components/TColorSwatch.vue_vue_type_script_setup_true_lang.cjs +2 -0
  31. package/dist/components/TColorSwatch.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  32. package/dist/components/TColorSwatch.vue_vue_type_script_setup_true_lang.js +63 -0
  33. package/dist/components/TColorSwatch.vue_vue_type_script_setup_true_lang.js.map +1 -0
  34. package/dist/components/TDropdown.vue.d.ts +1 -1
  35. package/dist/components/TDropdown.vue.d.ts.map +1 -1
  36. package/dist/components/TFileUpload.cjs.map +1 -1
  37. package/dist/components/TFileUpload.js.map +1 -1
  38. package/dist/components/TFileUpload.vue.d.ts +77 -10
  39. package/dist/components/TFileUpload.vue.d.ts.map +1 -1
  40. package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.cjs +1 -1
  41. package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  42. package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.js +393 -144
  43. package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/TInput.cjs.map +1 -1
  45. package/dist/components/TInput.js.map +1 -1
  46. package/dist/components/TInput.vue.d.ts +4 -1
  47. package/dist/components/TInput.vue.d.ts.map +1 -1
  48. package/dist/components/TInput.vue_vue_type_script_setup_true_lang.cjs +1 -1
  49. package/dist/components/TInput.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  50. package/dist/components/TInput.vue_vue_type_script_setup_true_lang.js +2 -0
  51. package/dist/components/TInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  52. package/dist/components/TKbd.cjs +2 -0
  53. package/dist/components/TKbd.cjs.map +1 -0
  54. package/dist/components/TKbd.js +7 -0
  55. package/dist/components/TKbd.js.map +1 -0
  56. package/dist/components/TKbd.vue.d.ts +18 -0
  57. package/dist/components/TKbd.vue.d.ts.map +1 -0
  58. package/dist/components/TKbd.vue_vue_type_script_setup_true_lang.cjs +2 -0
  59. package/dist/components/TKbd.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  60. package/dist/components/TKbd.vue_vue_type_script_setup_true_lang.js +12 -0
  61. package/dist/components/TKbd.vue_vue_type_script_setup_true_lang.js.map +1 -0
  62. package/dist/components/TNavMenu.cjs.map +1 -1
  63. package/dist/components/TNavMenu.js.map +1 -1
  64. package/dist/components/TNavMenu.vue.d.ts +9 -0
  65. package/dist/components/TNavMenu.vue.d.ts.map +1 -1
  66. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs +1 -1
  67. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  68. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js +67 -55
  69. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/TPage.cjs +2 -0
  71. package/dist/components/TPage.cjs.map +1 -0
  72. package/dist/components/TPage.js +7 -0
  73. package/dist/components/TPage.js.map +1 -0
  74. package/dist/components/TPage.vue.d.ts +35 -0
  75. package/dist/components/TPage.vue.d.ts.map +1 -0
  76. package/dist/components/TPage.vue_vue_type_script_setup_true_lang.cjs +2 -0
  77. package/dist/components/TPage.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  78. package/dist/components/TPage.vue_vue_type_script_setup_true_lang.js +49 -0
  79. package/dist/components/TPage.vue_vue_type_script_setup_true_lang.js.map +1 -0
  80. package/dist/components/TPageHeader.cjs +2 -0
  81. package/dist/components/TPageHeader.cjs.map +1 -0
  82. package/dist/components/TPageHeader.js +7 -0
  83. package/dist/components/TPageHeader.js.map +1 -0
  84. package/dist/components/TPageHeader.vue.d.ts +40 -0
  85. package/dist/components/TPageHeader.vue.d.ts.map +1 -0
  86. package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.cjs +2 -0
  87. package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  88. package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.js +54 -0
  89. package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  90. package/dist/components/TPopover.vue.d.ts +1 -1
  91. package/dist/components/TPopover.vue.d.ts.map +1 -1
  92. package/dist/components/TSelect.cjs.map +1 -1
  93. package/dist/components/TSelect.js.map +1 -1
  94. package/dist/components/TSelect.vue.d.ts +4 -1
  95. package/dist/components/TSelect.vue.d.ts.map +1 -1
  96. package/dist/components/TSelect.vue_vue_type_script_setup_true_lang.cjs +1 -1
  97. package/dist/components/TSelect.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  98. package/dist/components/TSelect.vue_vue_type_script_setup_true_lang.js +2 -0
  99. package/dist/components/TSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  100. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs +1 -1
  101. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  102. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js +1 -4
  103. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  104. package/dist/components/TSpacer.cjs +2 -0
  105. package/dist/components/TSpacer.cjs.map +1 -0
  106. package/dist/components/TSpacer.js +7 -0
  107. package/dist/components/TSpacer.js.map +1 -0
  108. package/dist/components/TSpacer.vue.d.ts +8 -0
  109. package/dist/components/TSpacer.vue.d.ts.map +1 -0
  110. package/dist/components/TSpacer.vue_vue_type_script_setup_true_lang.cjs +2 -0
  111. package/dist/components/TSpacer.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  112. package/dist/components/TSpacer.vue_vue_type_script_setup_true_lang.js +16 -0
  113. package/dist/components/TSpacer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  114. package/dist/components/TSplit.cjs +2 -0
  115. package/dist/components/TSplit.cjs.map +1 -0
  116. package/dist/components/TSplit.js +7 -0
  117. package/dist/components/TSplit.js.map +1 -0
  118. package/dist/components/TSplit.vue.d.ts +38 -0
  119. package/dist/components/TSplit.vue.d.ts.map +1 -0
  120. package/dist/components/TSplit.vue_vue_type_script_setup_true_lang.cjs +2 -0
  121. package/dist/components/TSplit.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  122. package/dist/components/TSplit.vue_vue_type_script_setup_true_lang.js +43 -0
  123. package/dist/components/TSplit.vue_vue_type_script_setup_true_lang.js.map +1 -0
  124. package/dist/components/TStack.cjs.map +1 -1
  125. package/dist/components/TStack.js.map +1 -1
  126. package/dist/components/TStack.vue.d.ts +3 -0
  127. package/dist/components/TStack.vue.d.ts.map +1 -1
  128. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.cjs +1 -1
  129. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  130. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.js +6 -1
  131. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.js.map +1 -1
  132. package/dist/components/TStackItem.cjs +2 -0
  133. package/dist/components/TStackItem.cjs.map +1 -0
  134. package/dist/components/TStackItem.js +7 -0
  135. package/dist/components/TStackItem.js.map +1 -0
  136. package/dist/components/TStackItem.vue.d.ts +38 -0
  137. package/dist/components/TStackItem.vue.d.ts.map +1 -0
  138. package/dist/components/TStackItem.vue_vue_type_script_setup_true_lang.cjs +2 -0
  139. package/dist/components/TStackItem.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  140. package/dist/components/TStackItem.vue_vue_type_script_setup_true_lang.js +45 -0
  141. package/dist/components/TStackItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  142. package/dist/components/TText.cjs +2 -0
  143. package/dist/components/TText.cjs.map +1 -0
  144. package/dist/components/TText.js +7 -0
  145. package/dist/components/TText.js.map +1 -0
  146. package/dist/components/TText.vue.d.ts +39 -0
  147. package/dist/components/TText.vue.d.ts.map +1 -0
  148. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs +2 -0
  149. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  150. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js +32 -0
  151. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js.map +1 -0
  152. package/dist/components/TTextarea.cjs.map +1 -1
  153. package/dist/components/TTextarea.js.map +1 -1
  154. package/dist/components/TTextarea.vue.d.ts +4 -1
  155. package/dist/components/TTextarea.vue.d.ts.map +1 -1
  156. package/dist/components/TTextarea.vue_vue_type_script_setup_true_lang.cjs +1 -1
  157. package/dist/components/TTextarea.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  158. package/dist/components/TTextarea.vue_vue_type_script_setup_true_lang.js +2 -0
  159. package/dist/components/TTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  160. package/dist/components/index.d.ts +12 -1
  161. package/dist/components/index.d.ts.map +1 -1
  162. package/dist/composables/useTheme.cjs +2 -0
  163. package/dist/composables/useTheme.cjs.map +1 -0
  164. package/dist/composables/useTheme.d.ts +38 -0
  165. package/dist/composables/useTheme.d.ts.map +1 -0
  166. package/dist/composables/useTheme.js +54 -0
  167. package/dist/composables/useTheme.js.map +1 -0
  168. package/dist/index.cjs +1 -1
  169. package/dist/index.d.ts +2 -0
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +64 -55
  172. package/dist/plugin.cjs +1 -1
  173. package/dist/plugin.cjs.map +1 -1
  174. package/dist/plugin.d.ts.map +1 -1
  175. package/dist/plugin.js +113 -97
  176. package/dist/plugin.js.map +1 -1
  177. package/dist/style.css +1 -1
  178. package/dist/types/contracts.cjs +1 -1
  179. package/dist/types/contracts.cjs.map +1 -1
  180. package/dist/types/contracts.d.ts +8 -1
  181. package/dist/types/contracts.d.ts.map +1 -1
  182. package/dist/types/contracts.js +8 -2
  183. package/dist/types/contracts.js.map +1 -1
  184. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"TFileUpload.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TFileUploadRejection {\n file: File;\n reason: TFileUploadRejectionReason;\n message: string;\n}\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: {\n file: File;\n index: number;\n removeFile: () => void;\n }) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TFileUploadRejection[]];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\n\nconst uploadId = createId('t-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isUnavailable = computed(() => props.disabled || props.loading);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 't-file-upload',\n `t-file-upload--${props.size}`,\n {\n 'is-disabled': isUnavailable.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst fileKey = (file: File, index: number) =>\n `${file.name}-${file.size}-${file.lastModified}-${index}`;\n\nconst matchesAccept = (file: File) => {\n if (!props.accept.trim()) {\n return true;\n }\n\n const tokens = props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean);\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return tokens.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isUnavailable.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isUnavailable.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst removeFile = (index: number) => {\n if (isUnavailable.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isUnavailable.value || !hasFiles.value) {\n return;\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isUnavailable.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isUnavailable.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isUnavailable.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"t-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isUnavailable\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"t-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isUnavailable || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isUnavailable ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"t-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"t-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"t-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"t-file-upload__label\">\n {{ label }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"t-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"t-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"t-file-upload__files\"\n >\n <div class=\"t-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"t-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"t-file-upload__clear\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"t-file-upload__list\">\n <li\n v-for=\"(file, index) in modelValue\"\n :key=\"fileKey(file, index)\"\n class=\"t-file-upload__file\"\n >\n <slot\n name=\"file\"\n :file=\"file\"\n :index=\"index\"\n :remove-file=\"() => removeFile(index)\"\n >\n <div class=\"t-file-upload__file-copy\">\n <p class=\"t-file-upload__file-name\">\n {{ file.name }}\n </p>\n <p class=\"t-file-upload__file-meta\">\n {{ formatFileSize(file.size) }}\n </p>\n </div>\n\n <button\n class=\"t-file-upload__remove\"\n type=\"button\"\n :disabled=\"isUnavailable\"\n :aria-label=\"`Remove ${file.name}`\"\n @click=\"removeFile(index)\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TFileUpload.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { createId, isActivationKey } from '@treeui/utils';\nimport { computed, onBeforeUnmount, onMounted, ref, useAttrs, watch } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TProgress from './TProgress.vue';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport type TFileUploadRejectionReason =\n | 'file-invalid-type'\n | 'file-too-large'\n | 'too-many-files';\n\nexport interface TFileUploadRejection {\n file: File;\n reason: TFileUploadRejectionReason;\n message: string;\n}\n\nexport type TFileUploadStatus =\n | 'pending'\n | 'uploading'\n | 'paused'\n | 'error'\n | 'success';\n\nexport interface TFileUploadState {\n status: TFileUploadStatus;\n progress?: number;\n uploadedBytes?: number;\n remainingMs?: number;\n remainingLabel?: string;\n error?: string;\n resumable?: boolean;\n retryable?: boolean;\n thumbnailUrl?: string;\n meta?: string;\n}\n\nexport type TFileUploadStateSource =\n | ReadonlyMap<File, TFileUploadState>\n | ((file: File, index: number) => TFileUploadState | undefined);\n\nexport interface TFileUploadRetryPayload {\n file: File;\n index: number;\n fileKey: string;\n mode: 'resume' | 'restart';\n state: TFileUploadState;\n}\n\nexport interface TFileUploadCancelPayload {\n file: File;\n index: number;\n fileKey: string;\n state: TFileUploadState;\n reason: 'remove' | 'clear';\n}\n\nexport interface TFileUploadFileSlotProps {\n file: File;\n index: number;\n fileKey: string;\n state: TFileUploadState | undefined;\n thumbnailUrl: string | undefined;\n sizeLabel: string;\n typeLabel: string;\n dimensionsLabel: string | undefined;\n progressLabel: string | undefined;\n remainingLabel: string | undefined;\n uploadedLabel: string | undefined;\n statusLabel: string | undefined;\n actionLabel: string | undefined;\n canRetry: boolean;\n retryMode: 'resume' | 'restart';\n isDragActive: boolean;\n isDragReject: boolean;\n removeFile: () => void;\n retryFile: () => void;\n}\n\ninterface ThumbEntry {\n url: string;\n width: number | null;\n height: number | null;\n}\n\ninterface FileRow {\n slotProps: TFileUploadFileSlotProps;\n rowClass: string | undefined;\n metaText: string;\n statusText: string;\n errorText: string | undefined;\n errorId: string | undefined;\n showProgress: boolean;\n progressValue: number | undefined;\n progressAriaLabel: string;\n isBusy: boolean;\n isSuccess: boolean;\n}\n\nconst DEFAULT_STATUS_LABELS: Record<TFileUploadStatus, string> = {\n pending: 'Waiting',\n uploading: 'Uploading',\n paused: 'Paused',\n error: 'Upload failed',\n success: 'Uploaded',\n};\n\n// The status log keeps a bounded history of announcements. Old entries are\n// trimmed rather than replaced in place so that each terminal transition\n// inserts a brand new node: `aria-relevant` defaults to \"additions text\", so\n// assistive tech announces the insertion and ignores the trim.\nconst STATUS_LOG_LIMIT = 5;\n\ntype StatusLogEntry = {\n id: number;\n text: string;\n};\n\nconst slots = defineSlots<{\n icon?: () => unknown;\n default?: (props: {\n files: File[];\n isDragActive: boolean;\n isDragReject: boolean;\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n file?: (props: TFileUploadFileSlotProps) => unknown;\n 'file-status'?: (props: TFileUploadFileSlotProps) => unknown;\n actions?: (props: {\n files: File[];\n openFileDialog: () => void;\n clearFiles: () => void;\n }) => unknown;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: File[];\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n accept?: string;\n multiple?: boolean;\n maxFiles?: number | null;\n maxFileSize?: number | null;\n label?: string;\n description?: string;\n buttonLabel?: string;\n filesLabel?: string;\n paste?: boolean;\n drop?: boolean;\n showFileList?: boolean;\n uploadState?: TFileUploadStateSource;\n dragLabel?: string;\n dragRejectLabel?: string;\n thumbnails?: boolean;\n maxThumbnailSize?: number | null;\n retryLabel?: string;\n resumeLabel?: (percent: number) => string;\n remainingTimeFormat?: (remainingMs: number) => string;\n statusLabels?: Partial<Record<TFileUploadStatus, string>>;\n }>(),\n {\n modelValue: () => [],\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n accept: '',\n multiple: true,\n label: 'Drop files here',\n description: 'Click to browse, drag and drop, or paste with Ctrl+V.',\n buttonLabel: 'Browse files',\n filesLabel: 'Selected files',\n maxFiles: null,\n maxFileSize: null,\n paste: true,\n drop: true,\n showFileList: true,\n uploadState: undefined,\n dragLabel: 'Release to upload',\n dragRejectLabel: 'This file type is not accepted',\n thumbnails: true,\n maxThumbnailSize: 10 * 1024 * 1024,\n retryLabel: 'Retry',\n resumeLabel: (percent: number) => `Resume from ${percent}%`,\n remainingTimeFormat: (remainingMs: number) => {\n if (remainingMs < 5000) {\n return 'Less than 5s left';\n }\n\n const seconds = Math.round(remainingMs / 1000);\n\n if (seconds < 60) {\n return `About ${seconds}s left`;\n }\n\n const minutes = Math.round(seconds / 60);\n\n if (minutes < 60) {\n return `About ${minutes} min left`;\n }\n\n return `About ${Math.round(minutes / 60)}h left`;\n },\n statusLabels: () => ({}),\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [files: File[]];\n 'files-accepted': [files: File[]];\n 'files-rejected': [rejections: TFileUploadRejection[]];\n retry: [payload: TFileUploadRetryPayload];\n cancel: [payload: TFileUploadCancelPayload];\n}>();\n\nconst attrs = useAttrs();\nconst rootRef = ref<HTMLElement | null>(null);\nconst inputRef = ref<HTMLInputElement | null>(null);\nconst isDragActive = ref(false);\nconst isDragReject = ref(false);\nconst isFocusedWithin = ref(false);\nconst dragDepth = ref(0);\nconst feedbackMessages = ref<string[]>([]);\nconst statusLog = ref<StatusLogEntry[]>([]);\nlet statusLogId = 0;\nconst retryFocusKey = ref<string | null>(null);\nconst thumbs = ref(new Map<File, ThumbEntry>());\n\nconst uploadId = createId('t-file-upload');\nconst descriptionId = `${uploadId}-description`;\nconst feedbackId = `${uploadId}-feedback`;\nconst filesId = `${uploadId}-files`;\n\nconst isDisabled = computed(() => props.disabled);\nconst hasFiles = computed(() => props.modelValue.length > 0);\nconst hasCustomBody = computed(() => Boolean(slots.default));\n\nconst resolvedStatusLabels = computed(() => ({\n ...DEFAULT_STATUS_LABELS,\n ...props.statusLabels,\n}));\n\nconst effectiveMaxFiles = computed(() => {\n if (!props.multiple) {\n return 1;\n }\n\n if (typeof props.maxFiles !== 'number') {\n return Number.POSITIVE_INFINITY;\n }\n\n return Math.max(props.maxFiles, 0);\n});\n\nconst rootClasses = computed(() => [\n 't-file-upload',\n `t-file-upload--${props.size}`,\n {\n 'is-disabled': isDisabled.value,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-drag-active': isDragActive.value,\n 'is-drag-reject': isDragReject.value,\n 'has-files': hasFiles.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst describedBy = computed(() => {\n const ids: string[] = [];\n\n if (props.description && !hasCustomBody.value) {\n ids.push(descriptionId);\n }\n\n if (feedbackMessages.value.length > 0) {\n ids.push(feedbackId);\n }\n\n if (props.showFileList && hasFiles.value) {\n ids.push(filesId);\n }\n\n return ids.length > 0 ? ids.join(' ') : undefined;\n});\n\nconst selectedFilesLabel = computed(() => `${props.filesLabel} (${props.modelValue.length})`);\n\nconst dropzoneLabel = computed(() => {\n if (isDragReject.value) {\n return props.dragRejectLabel;\n }\n\n return isDragActive.value ? props.dragLabel : props.label;\n});\n\nconst formatFileSize = (size: number) => {\n if (size < 1024) {\n return `${size} B`;\n }\n\n const units = ['KB', 'MB', 'GB'];\n let value = size / 1024;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n\n const roundedValue = value >= 10 || Number.isInteger(value)\n ? Math.round(value)\n : Number(value.toFixed(1));\n\n return `${roundedValue} ${units[unitIndex]}`;\n};\n\nconst formatFileType = (file: File) => {\n const dotIndex = file.name.lastIndexOf('.');\n const extension = dotIndex > 0 && dotIndex < file.name.length - 1\n ? file.name.slice(dotIndex + 1).toUpperCase()\n : '';\n\n if (extension && extension.length <= 5) {\n return extension;\n }\n\n const subtype = file.type.includes('/') ? file.type.split('/')[1] : '';\n\n return subtype ? subtype.toUpperCase() : 'FILE';\n};\n\nlet keySeq = 0;\nconst keyCache = new WeakMap<File, string>();\n\nconst fileKeyFor = (file: File) => {\n let key = keyCache.get(file);\n\n if (!key) {\n keySeq += 1;\n key = `${uploadId}-f${keySeq}`;\n keyCache.set(file, key);\n }\n\n return key;\n};\n\nconst acceptTokens = computed(() =>\n props.accept\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter(Boolean),\n);\n\nconst matchesAccept = (file: File) => {\n if (acceptTokens.value.length === 0) {\n return true;\n }\n\n const fileName = file.name.toLowerCase();\n const fileType = file.type.toLowerCase();\n\n return acceptTokens.value.some((token) => {\n if (token.startsWith('.')) {\n return fileName.endsWith(token);\n }\n\n if (token.endsWith('/*')) {\n return fileType.startsWith(token.slice(0, -1));\n }\n\n return fileType === token;\n });\n};\n\nconst canDetectDragReject = computed(() =>\n acceptTokens.value.length > 0 && acceptTokens.value.every((token) => token.includes('/')),\n);\n\nconst matchesAcceptType = (type: string) => {\n const fileType = type.toLowerCase();\n\n if (!fileType) {\n return true;\n }\n\n return acceptTokens.value.some((token) =>\n token.endsWith('/*') ? fileType.startsWith(token.slice(0, -1)) : fileType === token,\n );\n};\n\nconst detectDragReject = (dataTransfer?: DataTransfer | null) => {\n if (!canDetectDragReject.value || !dataTransfer) {\n return false;\n }\n\n const items = dataTransfer.items;\n\n if (!items || items.length === 0) {\n return false;\n }\n\n const fileItems = Array.from(items).filter((item) => item.kind === 'file');\n\n if (fileItems.length === 0) {\n return false;\n }\n\n return fileItems.every((item) => !matchesAcceptType(item.type));\n};\n\nconst resolveState = (file: File, index: number) => {\n const source = props.uploadState;\n\n if (!source) {\n return undefined;\n }\n\n return typeof source === 'function' ? source(file, index) : source.get(file);\n};\n\nconst resolvedStates = computed(() => props.modelValue.map(resolveState));\n\nconst canUseObjectUrl = () =>\n typeof window !== 'undefined' &&\n typeof URL !== 'undefined' &&\n typeof URL.createObjectURL === 'function' &&\n typeof URL.revokeObjectURL === 'function';\n\nconst isThumbnailable = (file: File) =>\n file.type.startsWith('image/') &&\n (props.maxThumbnailSize === null || file.size <= props.maxThumbnailSize);\n\nconst releaseAllThumbnails = () => {\n if (canUseObjectUrl()) {\n for (const entry of thumbs.value.values()) {\n URL.revokeObjectURL(entry.url);\n }\n }\n\n thumbs.value.clear();\n};\n\nconst syncThumbnails = () => {\n if (!props.thumbnails || !canUseObjectUrl()) {\n releaseAllThumbnails();\n return;\n }\n\n const live = new Set(props.modelValue);\n\n for (const [file, entry] of [...thumbs.value]) {\n if (!live.has(file)) {\n URL.revokeObjectURL(entry.url);\n thumbs.value.delete(file);\n }\n }\n\n for (const file of props.modelValue) {\n if (thumbs.value.has(file) || !isThumbnailable(file)) {\n continue;\n }\n\n const url = URL.createObjectURL(file);\n thumbs.value.set(file, { url, width: null, height: null });\n\n const image = new Image();\n\n image.onload = () => {\n const current = thumbs.value.get(file);\n\n if (!current || current.url !== url) {\n return;\n }\n\n thumbs.value.set(file, { url, width: image.naturalWidth, height: image.naturalHeight });\n };\n\n image.src = url;\n }\n};\n\nconst buildRejectionMessage = (\n file: File,\n reason: TFileUploadRejectionReason,\n) => {\n switch (reason) {\n case 'file-invalid-type':\n return `${file.name} is not an accepted file type.`;\n case 'file-too-large':\n return `${file.name} exceeds the ${formatFileSize(props.maxFileSize ?? 0)} limit.`;\n case 'too-many-files':\n return `You can only add up to ${effectiveMaxFiles.value} file${effectiveMaxFiles.value === 1 ? '' : 's'}.`;\n default:\n return `${file.name} could not be added.`;\n }\n};\n\nconst resetInputValue = () => {\n if (inputRef.value) {\n inputRef.value.value = '';\n }\n};\n\nconst openFileDialog = () => {\n if (isDisabled.value) {\n return;\n }\n\n inputRef.value?.click();\n};\n\nconst emitFiles = (\n nextFiles: File[],\n acceptedFiles: File[],\n rejections: TFileUploadRejection[],\n) => {\n feedbackMessages.value = rejections.map((rejection) => rejection.message);\n\n if (rejections.length > 0) {\n emit('files-rejected', rejections);\n }\n\n if (acceptedFiles.length > 0) {\n emit('update:modelValue', nextFiles);\n emit('files-accepted', acceptedFiles);\n }\n};\n\nconst processFiles = (incomingFiles: File[]) => {\n if (isDisabled.value || incomingFiles.length === 0) {\n return;\n }\n\n const nextFiles = props.multiple ? [...props.modelValue] : [];\n const acceptedFiles: File[] = [];\n const rejections: TFileUploadRejection[] = [];\n let remainingSlots = Number.isFinite(effectiveMaxFiles.value)\n ? Math.max(effectiveMaxFiles.value - nextFiles.length, 0)\n : Number.POSITIVE_INFINITY;\n\n for (const file of incomingFiles) {\n if (remainingSlots <= 0) {\n rejections.push({\n file,\n reason: 'too-many-files',\n message: buildRejectionMessage(file, 'too-many-files'),\n });\n continue;\n }\n\n if (!matchesAccept(file)) {\n rejections.push({\n file,\n reason: 'file-invalid-type',\n message: buildRejectionMessage(file, 'file-invalid-type'),\n });\n continue;\n }\n\n if (\n typeof props.maxFileSize === 'number' &&\n props.maxFileSize > 0 &&\n file.size > props.maxFileSize\n ) {\n rejections.push({\n file,\n reason: 'file-too-large',\n message: buildRejectionMessage(file, 'file-too-large'),\n });\n continue;\n }\n\n acceptedFiles.push(file);\n nextFiles.push(file);\n\n if (Number.isFinite(remainingSlots)) {\n remainingSlots -= 1;\n }\n }\n\n emitFiles(nextFiles, acceptedFiles, rejections);\n};\n\nconst emitCancel = (file: File, index: number, reason: 'remove' | 'clear') => {\n const state = resolvedStates.value[index];\n\n if (!state || (state.status !== 'uploading' && state.status !== 'paused')) {\n return;\n }\n\n emit('cancel', { file, index, fileKey: fileKeyFor(file), state, reason });\n};\n\nconst removeFile = (index: number) => {\n if (isDisabled.value) {\n return;\n }\n\n const file = props.modelValue[index];\n\n if (file) {\n emitCancel(file, index, 'remove');\n }\n\n feedbackMessages.value = [];\n emit('update:modelValue', props.modelValue.filter((_, fileIndex) => fileIndex !== index));\n};\n\nconst clearFiles = () => {\n if (isDisabled.value || !hasFiles.value) {\n return;\n }\n\n props.modelValue.forEach((file, index) => {\n emitCancel(file, index, 'clear');\n });\n\n feedbackMessages.value = [];\n emit('update:modelValue', []);\n};\n\nconst rows = computed<FileRow[]>(() =>\n props.modelValue.map((file, index) => {\n const state = resolvedStates.value[index];\n const status = state?.status;\n const thumb = thumbs.value.get(file);\n const key = fileKeyFor(file);\n\n const progress = state?.progress;\n const percent = typeof progress === 'number' ? Math.round(progress) : undefined;\n const isResumable = state?.resumable === true;\n\n const canRetry = Boolean(\n state && (status === 'error' || status === 'paused') && state.retryable !== false,\n );\n const retryMode: 'resume' | 'restart' = isResumable ? 'resume' : 'restart';\n\n const sizeLabel = formatFileSize(file.size);\n const typeLabel = formatFileType(file);\n const dimensionsLabel = thumb && thumb.width !== null && thumb.height !== null\n ? `${thumb.width} × ${thumb.height}`\n : undefined;\n\n const progressLabel = status === 'uploading' && percent !== undefined\n ? `${percent}%`\n : undefined;\n\n let remainingLabel: string | undefined;\n\n if (status === 'uploading') {\n if (state?.remainingLabel) {\n remainingLabel = state.remainingLabel;\n } else if (\n typeof state?.remainingMs === 'number' &&\n Number.isFinite(state.remainingMs) &&\n state.remainingMs >= 0\n ) {\n remainingLabel = props.remainingTimeFormat(state.remainingMs);\n }\n }\n\n const uploadedLabel = (status === 'error' || status === 'paused') &&\n typeof state?.uploadedBytes === 'number'\n ? `${formatFileSize(state.uploadedBytes)} of ${sizeLabel} uploaded`\n : undefined;\n\n const statusLabel = status ? resolvedStatusLabels.value[status] : undefined;\n\n let actionLabel: string | undefined;\n\n if (canRetry) {\n actionLabel = isResumable && percent !== undefined\n ? props.resumeLabel(percent)\n : props.retryLabel;\n }\n\n const errorText = status === 'error' ? state?.error : undefined;\n\n const slotProps: TFileUploadFileSlotProps = {\n file,\n index,\n fileKey: key,\n state,\n thumbnailUrl: state?.thumbnailUrl ?? thumb?.url,\n sizeLabel,\n typeLabel,\n dimensionsLabel,\n progressLabel,\n remainingLabel,\n uploadedLabel,\n statusLabel,\n actionLabel,\n canRetry,\n retryMode,\n isDragActive: isDragActive.value,\n isDragReject: isDragReject.value,\n removeFile: () => removeFile(index),\n retryFile: () => {\n if (!canRetry || isDisabled.value || !state) {\n return;\n }\n\n emit('retry', { file, index, fileKey: key, mode: retryMode, state });\n },\n };\n\n return {\n slotProps,\n rowClass: status ? `is-${status}` : undefined,\n metaText: [typeLabel, sizeLabel, dimensionsLabel, state?.meta].filter(Boolean).join(' · '),\n statusText: [statusLabel, progressLabel, remainingLabel, uploadedLabel]\n .filter(Boolean)\n .join(' · '),\n errorText,\n errorId: errorText ? `${key}-error` : undefined,\n showProgress: Boolean(\n state &&\n (status === 'uploading' ||\n status === 'paused' ||\n status === 'error' ||\n (status === 'success' && percent !== undefined)),\n ),\n progressValue: status === 'uploading' ? progress : (progress ?? 0),\n progressAriaLabel: `${statusLabel ?? ''} ${file.name}`.trim(),\n isBusy: status === 'uploading',\n isSuccess: status === 'success',\n };\n }),\n);\n\nconst hasTransferFiles = (dataTransfer?: DataTransfer | null) => {\n if (!dataTransfer) {\n return false;\n }\n\n return dataTransfer.files.length > 0 || Array.from(dataTransfer.types).includes('Files');\n};\n\nconst getClipboardFiles = (\n clipboardData?: Pick<DataTransfer, 'items'> | null,\n) => {\n if (!clipboardData?.items) {\n return [];\n }\n\n return Array.from(clipboardData.items)\n .map((item) => item.getAsFile?.() ?? null)\n .filter((file): file is File => file instanceof File);\n};\n\nconst onInputChange = (event: Event) => {\n const target = event.target as HTMLInputElement;\n processFiles(Array.from(target.files ?? []));\n resetInputValue();\n};\n\nconst onDropzoneKeydown = (event: KeyboardEvent) => {\n if (!isActivationKey(event) || isDisabled.value) {\n return;\n }\n\n event.preventDefault();\n openFileDialog();\n};\n\nconst onFocusIn = () => {\n isFocusedWithin.value = true;\n};\n\nconst onFocusOut = (event: FocusEvent) => {\n const nextTarget = event.relatedTarget as Node | null;\n\n if (nextTarget && rootRef.value?.contains(nextTarget)) {\n return;\n }\n\n isFocusedWithin.value = false;\n};\n\nconst onRetryFocus = (key: string) => {\n retryFocusKey.value = key;\n};\n\nconst onRetryBlur = (key: string) => {\n if (retryFocusKey.value === key) {\n retryFocusKey.value = null;\n }\n};\n\nconst onPaste = (event: ClipboardEvent) => {\n if (!props.paste || isDisabled.value) {\n return;\n }\n\n const clipboardFiles = getClipboardFiles(event.clipboardData);\n\n if (clipboardFiles.length === 0) {\n return;\n }\n\n event.preventDefault();\n processFiles(clipboardFiles);\n};\n\nconst onDocumentPaste = (event: Event) => {\n if (!isFocusedWithin.value || event.defaultPrevented) {\n return;\n }\n\n onPaste(event as ClipboardEvent);\n};\n\nconst onDragEnter = (event: DragEvent) => {\n if (!props.drop || isDisabled.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value += 1;\n isDragActive.value = true;\n isDragReject.value = detectDragReject(event.dataTransfer);\n};\n\nconst onDragOver = (event: DragEvent) => {\n if (!props.drop || isDisabled.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n\n isDragActive.value = true;\n isDragReject.value = detectDragReject(event.dataTransfer);\n};\n\nconst onDragLeave = (event: DragEvent) => {\n if (!props.drop || isDisabled.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n\n if (dragDepth.value === 0) {\n isDragActive.value = false;\n isDragReject.value = false;\n }\n};\n\nconst onDrop = (event: DragEvent) => {\n if (!props.drop || isDisabled.value || !hasTransferFiles(event.dataTransfer)) {\n return;\n }\n\n event.preventDefault();\n dragDepth.value = 0;\n isDragActive.value = false;\n isDragReject.value = false;\n processFiles(Array.from(event.dataTransfer?.files ?? []));\n};\n\nconst previousStatuses = new Map<File, TFileUploadStatus>();\n\nwatch(\n resolvedStates,\n (states) => {\n const messages: string[] = [];\n const live = new Set<File>();\n\n props.modelValue.forEach((file, index) => {\n live.add(file);\n\n const status = states[index]?.status;\n\n if (!status) {\n return;\n }\n\n const previous = previousStatuses.get(file);\n\n if (previous === status) {\n return;\n }\n\n previousStatuses.set(file, status);\n\n if (previous === undefined) {\n return;\n }\n\n if (status === 'success') {\n messages.push(`${file.name} uploaded.`);\n } else if (status === 'error') {\n messages.push(`${file.name} failed. ${states[index]?.error ?? ''}`.trim());\n }\n });\n\n for (const file of [...previousStatuses.keys()]) {\n if (!live.has(file)) {\n previousStatuses.delete(file);\n }\n }\n\n if (messages.length > 0) {\n // Append instead of overwriting a single string: two identical messages\n // in a row (a retry that fails with the same error) would otherwise write\n // a byte-identical value, which `Object.is` suppresses — no DOM mutation,\n // so `aria-live` never fires and the repeat failure is announced as silence.\n statusLogId += 1;\n statusLog.value = [\n ...statusLog.value,\n { id: statusLogId, text: messages.join(' ') },\n ].slice(-STATUS_LOG_LIMIT);\n }\n },\n { flush: 'post', immediate: true },\n);\n\nwatch(\n resolvedStates,\n () => {\n const key = retryFocusKey.value;\n const root = rootRef.value;\n\n if (!key || !root) {\n return;\n }\n\n if (document.activeElement && document.activeElement !== document.body) {\n return;\n }\n\n if (root.querySelector(`[data-t-retry=\"${key}\"]`)) {\n return;\n }\n\n retryFocusKey.value = null;\n\n const fallback = root.querySelector<HTMLElement>(`[data-t-remove=\"${key}\"]`) ??\n root.querySelector<HTMLElement>('.t-file-upload__dropzone');\n\n fallback?.focus();\n },\n { flush: 'post' },\n);\n\nwatch(() => props.modelValue, syncThumbnails);\nwatch(() => props.thumbnails, syncThumbnails);\n\nonMounted(() => {\n document.addEventListener('paste', onDocumentPaste);\n syncThumbnails();\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('paste', onDocumentPaste);\n releaseAllThumbnails();\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n @paste=\"onPaste\"\n >\n <input\n :id=\"uploadId\"\n ref=\"inputRef\"\n class=\"t-visually-hidden\"\n type=\"file\"\n :accept=\"accept || undefined\"\n :multiple=\"multiple\"\n :disabled=\"isDisabled\"\n @change=\"onInputChange\"\n >\n\n <div\n class=\"t-file-upload__dropzone\"\n :aria-busy=\"loading || undefined\"\n :aria-controls=\"showFileList && hasFiles ? filesId : undefined\"\n :aria-describedby=\"describedBy\"\n :aria-disabled=\"isDisabled || undefined\"\n :aria-invalid=\"invalid || undefined\"\n role=\"button\"\n :tabindex=\"isDisabled ? -1 : 0\"\n @click=\"openFileDialog\"\n @keydown=\"onDropzoneKeydown\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <div\n v-if=\"$slots.icon || !$slots.default\"\n class=\"t-file-upload__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\">\n <span class=\"t-file-upload__icon-mark\">+</span>\n </slot>\n </div>\n\n <div class=\"t-file-upload__content\">\n <slot\n :files=\"modelValue\"\n :is-drag-active=\"isDragActive\"\n :is-drag-reject=\"isDragReject\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n >\n <p class=\"t-file-upload__label\">\n {{ dropzoneLabel }}\n </p>\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-file-upload__description\"\n >\n {{ description }}\n </p>\n <span class=\"t-file-upload__browse\">\n {{ buttonLabel }}\n </span>\n </slot>\n </div>\n\n <TSpinner\n v-if=\"loading\"\n class=\"t-file-upload__spinner\"\n size=\"sm\"\n label=\"Uploading files\"\n />\n </div>\n\n <ul\n v-if=\"feedbackMessages.length > 0\"\n :id=\"feedbackId\"\n class=\"t-file-upload__feedback\"\n aria-live=\"polite\"\n >\n <li\n v-for=\"message in feedbackMessages\"\n :key=\"message\"\n >\n {{ message }}\n </li>\n </ul>\n\n <div\n class=\"t-file-upload__status-log t-visually-hidden\"\n role=\"log\"\n aria-live=\"polite\"\n >\n <p\n v-for=\"entry in statusLog\"\n :key=\"entry.id\"\n class=\"t-file-upload__status-log-entry\"\n >\n {{ entry.text }}\n </p>\n </div>\n\n <div\n v-if=\"showFileList && hasFiles\"\n class=\"t-file-upload__files\"\n >\n <div class=\"t-file-upload__files-header\">\n <p\n :id=\"filesId\"\n class=\"t-file-upload__files-label\"\n >\n {{ selectedFilesLabel }}\n </p>\n\n <button\n class=\"t-file-upload__clear\"\n type=\"button\"\n :disabled=\"isDisabled\"\n @click=\"clearFiles\"\n >\n Clear all\n </button>\n </div>\n\n <ul class=\"t-file-upload__list\">\n <li\n v-for=\"row in rows\"\n :key=\"row.slotProps.fileKey\"\n class=\"t-file-upload__file\"\n :class=\"row.rowClass\"\n :aria-busy=\"row.isBusy || undefined\"\n >\n <slot\n name=\"file\"\n v-bind=\"row.slotProps\"\n >\n <span\n class=\"t-file-upload__thumb\"\n aria-hidden=\"true\"\n >\n <img\n v-if=\"row.slotProps.thumbnailUrl\"\n class=\"t-file-upload__thumb-image\"\n :src=\"row.slotProps.thumbnailUrl\"\n alt=\"\"\n >\n <span\n v-else\n class=\"t-file-upload__thumb-fallback\"\n >\n {{ row.slotProps.typeLabel }}\n </span>\n </span>\n\n <div class=\"t-file-upload__file-copy\">\n <p class=\"t-file-upload__file-name\">\n {{ row.slotProps.file.name }}\n </p>\n <p class=\"t-file-upload__file-meta\">\n {{ row.metaText }}\n </p>\n\n <slot\n name=\"file-status\"\n v-bind=\"row.slotProps\"\n >\n <div\n v-if=\"row.showProgress\"\n class=\"t-file-upload__file-progress\"\n >\n <TProgress\n size=\"sm\"\n :value=\"row.progressValue\"\n :label=\"row.progressAriaLabel\"\n />\n </div>\n\n <p\n v-if=\"row.statusText\"\n class=\"t-file-upload__file-status\"\n >\n <span\n v-if=\"row.isSuccess\"\n class=\"t-file-upload__proof\"\n aria-hidden=\"true\"\n >✓</span>{{ row.statusText }}\n </p>\n\n <p\n v-if=\"row.errorText\"\n :id=\"row.errorId\"\n class=\"t-file-upload__file-error\"\n >\n {{ row.errorText }}\n </p>\n </slot>\n </div>\n\n <button\n v-if=\"row.slotProps.canRetry\"\n class=\"t-file-upload__retry\"\n type=\"button\"\n :data-t-retry=\"row.slotProps.fileKey\"\n :disabled=\"isDisabled\"\n :aria-describedby=\"row.errorId\"\n @focus=\"onRetryFocus(row.slotProps.fileKey)\"\n @blur=\"onRetryBlur(row.slotProps.fileKey)\"\n @click=\"row.slotProps.retryFile()\"\n >\n {{ row.slotProps.actionLabel }}\n </button>\n\n <button\n class=\"t-file-upload__remove\"\n type=\"button\"\n :data-t-remove=\"row.slotProps.fileKey\"\n :disabled=\"isDisabled\"\n :aria-label=\"`Remove ${row.slotProps.file.name}`\"\n @click=\"row.slotProps.removeFile()\"\n >\n Remove\n </button>\n </slot>\n </li>\n </ul>\n </div>\n\n <div\n v-if=\"$slots.actions\"\n class=\"t-file-upload__actions\"\n >\n <slot\n name=\"actions\"\n :files=\"modelValue\"\n :open-file-dialog=\"openFileDialog\"\n :clear-files=\"clearFiles\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TInput.cjs","names":[],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TInput.cjs","names":[],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TFieldWidth, TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n /** Inline-size cap. Fluid (`full`) by default. */\n width?: TFieldWidth;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n width: 'full',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n props.width !== 'full' ? `t-field-width--${props.width}` : null,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"TInput.js","names":[],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TInput.js","names":[],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TFieldWidth, TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n /** Inline-size cap. Fluid (`full`) by default. */\n width?: TFieldWidth;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n width: 'full',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n props.width !== 'full' ? `t-field-width--${props.width}` : null,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":""}
@@ -1,7 +1,9 @@
1
- import { TSize } from '../types/contracts';
1
+ import { TFieldWidth, TSize } from '../types/contracts';
2
2
  type __VLS_Props = {
3
3
  modelValue?: string | number;
4
4
  size?: TSize;
5
+ /** Inline-size cap. Fluid (`full`) by default. */
6
+ width?: TFieldWidth;
5
7
  disabled?: boolean;
6
8
  loading?: boolean;
7
9
  invalid?: boolean;
@@ -27,6 +29,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
27
29
  modelValue: string | number;
28
30
  disabled: boolean;
29
31
  size: TSize;
32
+ width: TFieldWidth;
30
33
  loading: boolean;
31
34
  invalid: boolean;
32
35
  placeholder: string;
@@ -1 +1 @@
1
- {"version":3,"file":"TInput.vue.d.ts","sourceRoot":"","sources":["../../src/components/TInput.vue"],"names":[],"mappings":"AAkGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAOhD,KAAK,WAAW,GAAG;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAwDJ,iBAAS,cAAc;WA6DT,OAAO,IAA6B;;wBAXtB,GAAG;wBACH,GAAG;;;;EAe9B;AAgBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;UA7IV,MAAM;gBALA,MAAM,GAAG,MAAM;cAEjB,OAAO;UADX,KAAK;aAEF,OAAO;aACP,OAAO;iBAEH,MAAM;6EAoJtB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"TInput.vue.d.ts","sourceRoot":"","sources":["../../src/components/TInput.vue"],"names":[],"mappings":"AAsGA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAO7D,KAAK,WAAW,GAAG;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,kDAAkD;IAClD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AA2DJ,iBAAS,cAAc;WA6DT,OAAO,IAA6B;;wBAXtB,GAAG;wBACH,GAAG;;;;EAe9B;AAgBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;UAhJV,MAAM;gBAPA,MAAM,GAAG,MAAM;cAIjB,OAAO;UAHX,KAAK;WAEJ,WAAW;aAET,OAAO;aACP,OAAO;iBAEH,MAAM;6EAuJtB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1,2 +1,2 @@
1
- const e=require("./TSpinner.cjs");let t=require("vue");var n={key:0,class:`t-input__slot t-input__slot--prefix`},r=[`type`,`value`,`placeholder`,`disabled`,`aria-invalid`],i={key:2,class:`t-input__slot t-input__slot--suffix`},a=(0,t.defineComponent)({inheritAttrs:!1,__name:`TInput`,props:{modelValue:{default:``},size:{default:`md`},disabled:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},invalid:{type:Boolean,default:!1},type:{default:`text`},placeholder:{default:``}},emits:[`update:modelValue`],setup(a,{emit:o}){let s=a,c=o,l=(0,t.useAttrs)(),u=(0,t.computed)(()=>[`t-input`,`t-input--${s.size}`,{"is-disabled":s.disabled,"is-invalid":s.invalid,"is-loading":s.loading},l.class]),d=(0,t.computed)(()=>l.style),f=(0,t.computed)(()=>{let{class:e,style:t,...n}=l;return n}),p=(0,t.computed)(()=>`${s.modelValue??``}`),m=e=>{c(`update:modelValue`,e.target.value)};return(o,s)=>((0,t.openBlock)(),(0,t.createElementBlock)(`label`,{class:(0,t.normalizeClass)(u.value),style:(0,t.normalizeStyle)(d.value)},[o.$slots.prefix?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,n,[(0,t.renderSlot)(o.$slots,`prefix`)])):(0,t.createCommentVNode)(``,!0),(0,t.createElementVNode)(`input`,(0,t.mergeProps)(f.value,{class:`t-input__field`,type:a.type,value:p.value,placeholder:a.placeholder,disabled:a.disabled,"aria-invalid":a.invalid||void 0,onInput:m}),null,16,r),a.loading?((0,t.openBlock)(),(0,t.createBlock)(e.default,{key:1,size:`sm`,label:`Loading`})):(0,t.createCommentVNode)(``,!0),o.$slots.suffix?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,[(0,t.renderSlot)(o.$slots,`suffix`)])):(0,t.createCommentVNode)(``,!0)],6))}});exports.default=a;
1
+ const e=require("./TSpinner.cjs");let t=require("vue");var n={key:0,class:`t-input__slot t-input__slot--prefix`},r=[`type`,`value`,`placeholder`,`disabled`,`aria-invalid`],i={key:2,class:`t-input__slot t-input__slot--suffix`},a=(0,t.defineComponent)({inheritAttrs:!1,__name:`TInput`,props:{modelValue:{default:``},size:{default:`md`},width:{default:`full`},disabled:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},invalid:{type:Boolean,default:!1},type:{default:`text`},placeholder:{default:``}},emits:[`update:modelValue`],setup(a,{emit:o}){let s=a,c=o,l=(0,t.useAttrs)(),u=(0,t.computed)(()=>[`t-input`,`t-input--${s.size}`,s.width===`full`?null:`t-field-width--${s.width}`,{"is-disabled":s.disabled,"is-invalid":s.invalid,"is-loading":s.loading},l.class]),d=(0,t.computed)(()=>l.style),f=(0,t.computed)(()=>{let{class:e,style:t,...n}=l;return n}),p=(0,t.computed)(()=>`${s.modelValue??``}`),m=e=>{c(`update:modelValue`,e.target.value)};return(o,s)=>((0,t.openBlock)(),(0,t.createElementBlock)(`label`,{class:(0,t.normalizeClass)(u.value),style:(0,t.normalizeStyle)(d.value)},[o.$slots.prefix?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,n,[(0,t.renderSlot)(o.$slots,`prefix`)])):(0,t.createCommentVNode)(``,!0),(0,t.createElementVNode)(`input`,(0,t.mergeProps)(f.value,{class:`t-input__field`,type:a.type,value:p.value,placeholder:a.placeholder,disabled:a.disabled,"aria-invalid":a.invalid||void 0,onInput:m}),null,16,r),a.loading?((0,t.openBlock)(),(0,t.createBlock)(e.default,{key:1,size:`sm`,label:`Loading`})):(0,t.createCommentVNode)(``,!0),o.$slots.suffix?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,[(0,t.renderSlot)(o.$slots,`suffix`)])):(0,t.createCommentVNode)(``,!0)],6))}});exports.default=a;
2
2
  //# sourceMappingURL=TInput.vue_vue_type_script_setup_true_lang.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TInput.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":"mhBASA,IAAM,EAAQ,EAqBR,EAAO,EAIP,GAAA,EAAA,EAAA,SAAA,CAAiB,EAEjB,GAAA,EAAA,EAAA,SAAA,KAA6B,CACjC,UACA,YAAY,EAAM,OAClB,CACE,cAAe,EAAM,SACrB,aAAc,EAAM,QACpB,aAAc,EAAM,OACtB,EACA,EAAM,KACR,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAA2B,EAAM,KAAK,EAEtC,GAAA,EAAA,EAAA,SAAA,KAA4B,CAChC,GAAM,CAAE,MAAO,EAAQ,MAAO,EAAQ,GAAG,GAAS,EAClD,OAAO,CACT,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAA6B,GAAG,EAAM,YAAc,IAAI,EAExD,EAAW,GAAiB,CAChC,EAAK,oBAAsB,EAAM,OAA4B,KAAK,CACpE,2DAmCU,QAAA,CA9BL,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAW,EAClB,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAS,IAGTA,EAAAA,OAAO,SAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIR,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADiB,EAAA,OAAA,QAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,2BAWvB,SAAA,EAAA,EAAA,WAAA,CARS,EAQT,MARmB,CAClB,MAAM,iBACL,KAAM,EAAA,KACN,MAAO,EAAA,MACP,YAAa,EAAA,YACb,SAAU,EAAA,SACV,eAAc,EAAA,SAAW,IAAA,GAClB,uBAGF,EAAA,UAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,YAAA,CAGN,EAAA,QAAA,OAFA,KAAK,KACL,MAAM,6CAGAA,EAAAA,OAAO,SAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIR,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADiB,EAAA,OAAA,QAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA"}
1
+ {"version":3,"file":"TInput.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TFieldWidth, TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n /** Inline-size cap. Fluid (`full`) by default. */\n width?: TFieldWidth;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n width: 'full',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n props.width !== 'full' ? `t-field-width--${props.width}` : null,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":"0iBASA,IAAM,EAAQ,EAwBR,EAAO,EAIP,GAAA,EAAA,EAAA,SAAA,CAAiB,EAEjB,GAAA,EAAA,EAAA,SAAA,KAA6B,CACjC,UACA,YAAY,EAAM,OAClB,EAAM,QAAU,OAA2C,KAAlC,kBAAkB,EAAM,QACjD,CACE,cAAe,EAAM,SACrB,aAAc,EAAM,QACpB,aAAc,EAAM,OACtB,EACA,EAAM,KACR,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAA2B,EAAM,KAAK,EAEtC,GAAA,EAAA,EAAA,SAAA,KAA4B,CAChC,GAAM,CAAE,MAAO,EAAQ,MAAO,EAAQ,GAAG,GAAS,EAClD,OAAO,CACT,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAA6B,GAAG,EAAM,YAAc,IAAI,EAExD,EAAW,GAAiB,CAChC,EAAK,oBAAsB,EAAM,OAA4B,KAAK,CACpE,2DAmCU,QAAA,CA9BL,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAW,EAClB,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAS,IAGTA,EAAAA,OAAO,SAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIR,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADiB,EAAA,OAAA,QAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,2BAWvB,SAAA,EAAA,EAAA,WAAA,CARS,EAQT,MARmB,CAClB,MAAM,iBACL,KAAM,EAAA,KACN,MAAO,EAAA,MACP,YAAa,EAAA,YACb,SAAU,EAAA,SACV,eAAc,EAAA,SAAW,IAAA,GAClB,uBAGF,EAAA,UAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,YAAA,CAGN,EAAA,QAAA,OAFA,KAAK,KACL,MAAM,6CAGAA,EAAAA,OAAO,SAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIR,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADiB,EAAA,OAAA,QAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA"}
@@ -19,6 +19,7 @@ var p = {
19
19
  props: {
20
20
  modelValue: { default: "" },
21
21
  size: { default: "md" },
22
+ width: { default: "full" },
22
23
  disabled: {
23
24
  type: Boolean,
24
25
  default: !1
@@ -39,6 +40,7 @@ var p = {
39
40
  let _ = o, v = g, y = f(), b = t(() => [
40
41
  "t-input",
41
42
  `t-input--${_.size}`,
43
+ _.width === "full" ? null : `t-field-width--${_.width}`,
42
44
  {
43
45
  "is-disabled": _.disabled,
44
46
  "is-invalid": _.invalid,
@@ -1 +1 @@
1
- {"version":3,"file":"TInput.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASA,IAAM,IAAQ,GAqBR,IAAO,GAIP,IAAQ,EAAS,GAEjB,IAAc,QAAe;GACjC;GACA,YAAY,EAAM;GAClB;IACE,eAAe,EAAM;IACrB,cAAc,EAAM;IACpB,cAAc,EAAM;GACtB;GACA,EAAM;EACR,CAAC,GAEK,IAAY,QAAe,EAAM,KAAK,GAEtC,IAAa,QAAe;GAChC,IAAM,EAAE,OAAO,GAAQ,OAAO,GAAQ,GAAG,MAAS;GAClD,OAAO;EACT,CAAC,GAEK,IAAc,QAAe,GAAG,EAAM,cAAc,IAAI,GAExD,KAAW,MAAiB;GAChC,EAAK,qBAAsB,EAAM,OAA4B,KAAK;EACpE;yBAIE,EA+BQ,SAAA;GA9BL,OAAK,EAAE,EAAA,KAAW;GAClB,OAAK,EAAE,EAAA,KAAS;;GAGTA,EAAAA,OAAO,UAAA,EAAA,GADf,EAKO,QALP,GAKO,CADL,EAAsB,EAAA,QAAA,QAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAExB,EASC,SATD,EACU,EAQT,OARmB;IAClB,OAAM;IACL,MAAM,EAAA;IACN,OAAO,EAAA;IACP,aAAa,EAAA;IACb,UAAU,EAAA;IACV,gBAAc,EAAA,WAAW,KAAA;IAClB;;GAGF,EAAA,WAAA,EAAA,GADR,EAIE,GAAA;;IAFA,MAAK;IACL,OAAM;;GAGAA,EAAAA,OAAO,UAAA,EAAA,GADf,EAKO,QALP,GAKO,CADL,EAAsB,EAAA,QAAA,QAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"TInput.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { TFieldWidth, TSize } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | number;\n size?: TSize;\n /** Inline-size cap. Fluid (`full`) by default. */\n width?: TFieldWidth;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n type?: string;\n placeholder?: string;\n }>(),\n {\n modelValue: '',\n size: 'md',\n width: 'full',\n disabled: false,\n loading: false,\n invalid: false,\n type: 'text',\n placeholder: '',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n}>();\n\nconst attrs = useAttrs();\n\nconst rootClasses = computed(() => [\n 't-input',\n `t-input--${props.size}`,\n props.width !== 'full' ? `t-field-width--${props.width}` : null,\n {\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst inputAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst stringValue = computed(() => `${props.modelValue ?? ''}`);\n\nconst onInput = (event: Event) => {\n emit('update:modelValue', (event.target as HTMLInputElement).value);\n};\n</script>\n\n<template>\n <label\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-input__slot t-input__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <input\n v-bind=\"inputAttrs\"\n class=\"t-input__field\"\n :type=\"type\"\n :value=\"stringValue\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n @input=\"onInput\"\n >\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <span\n v-if=\"$slots.suffix\"\n class=\"t-input__slot t-input__slot--suffix\"\n >\n <slot name=\"suffix\" />\n </span>\n </label>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASA,IAAM,IAAQ,GAwBR,IAAO,GAIP,IAAQ,EAAS,GAEjB,IAAc,QAAe;GACjC;GACA,YAAY,EAAM;GAClB,EAAM,UAAU,SAA2C,OAAlC,kBAAkB,EAAM;GACjD;IACE,eAAe,EAAM;IACrB,cAAc,EAAM;IACpB,cAAc,EAAM;GACtB;GACA,EAAM;EACR,CAAC,GAEK,IAAY,QAAe,EAAM,KAAK,GAEtC,IAAa,QAAe;GAChC,IAAM,EAAE,OAAO,GAAQ,OAAO,GAAQ,GAAG,MAAS;GAClD,OAAO;EACT,CAAC,GAEK,IAAc,QAAe,GAAG,EAAM,cAAc,IAAI,GAExD,KAAW,MAAiB;GAChC,EAAK,qBAAsB,EAAM,OAA4B,KAAK;EACpE;yBAIE,EA+BQ,SAAA;GA9BL,OAAK,EAAE,EAAA,KAAW;GAClB,OAAK,EAAE,EAAA,KAAS;;GAGTA,EAAAA,OAAO,UAAA,EAAA,GADf,EAKO,QALP,GAKO,CADL,EAAsB,EAAA,QAAA,QAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAExB,EASC,SATD,EACU,EAQT,OARmB;IAClB,OAAM;IACL,MAAM,EAAA;IACN,OAAO,EAAA;IACP,aAAa,EAAA;IACb,UAAU,EAAA;IACV,gBAAc,EAAA,WAAW,KAAA;IAClB;;GAGF,EAAA,WAAA,EAAA,GADR,EAIE,GAAA;;IAFA,MAAK;IACL,OAAM;;GAGAA,EAAAA,OAAO,UAAA,EAAA,GADf,EAKO,QALP,GAKO,CADL,EAAsB,EAAA,QAAA,QAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
@@ -0,0 +1,2 @@
1
+ var e=require("./TKbd.vue_vue_type_script_setup_true_lang.cjs").default;exports.default=e;
2
+ //# sourceMappingURL=TKbd.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TKbd.cjs","names":[],"sources":["../../src/components/TKbd.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// A keyboard-key hint (e.g. ⌘K, Esc, Ctrl). Renders a native <kbd> with the\n// library's monospaced, bordered chip styling.\n</script>\n\n<template>\n <kbd class=\"t-kbd\">\n <slot />\n </kbd>\n</template>\n"],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import e from "./TKbd.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/TKbd.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=TKbd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TKbd.js","names":[],"sources":["../../src/components/TKbd.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// A keyboard-key hint (e.g. ⌘K, Esc, Ctrl). Renders a native <kbd> with the\n// library's monospaced, bordered chip styling.\n</script>\n\n<template>\n <kbd class=\"t-kbd\">\n <slot />\n </kbd>\n</template>\n"],"mappings":""}
@@ -0,0 +1,18 @@
1
+ declare function __VLS_template(): {
2
+ attrs: Partial<{}>;
3
+ slots: {
4
+ default?(_: {}): any;
5
+ };
6
+ refs: {};
7
+ rootEl: HTMLElement;
8
+ };
9
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
10
+ declare const __VLS_component: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLElement>;
11
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
12
+ export default _default;
13
+ type __VLS_WithTemplateSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };
18
+ //# sourceMappingURL=TKbd.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TKbd.vue.d.ts","sourceRoot":"","sources":["../../src/components/TKbd.vue"],"names":[],"mappings":"AAiBA,iBAAS,cAAc;WAwBT,OAAO,IAA6B;;yBAVrB,GAAG;;;;EAe/B;AAOD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe,uRAMnB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAEpG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -0,0 +1,2 @@
1
+ let e=require("vue");var t={class:`t-kbd`},n=(0,e.defineComponent)({__name:`TKbd`,setup(n){return(n,r)=>((0,e.openBlock)(),(0,e.createElementBlock)(`kbd`,t,[(0,e.renderSlot)(n.$slots,`default`)]))}});exports.default=n;
2
+ //# sourceMappingURL=TKbd.vue_vue_type_script_setup_true_lang.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TKbd.vue_vue_type_script_setup_true_lang.cjs","names":[],"sources":["../../src/components/TKbd.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// A keyboard-key hint (e.g. ⌘K, Esc, Ctrl). Renders a native <kbd> with the\n// library's monospaced, bordered chip styling.\n</script>\n\n<template>\n <kbd class=\"t-kbd\">\n <slot />\n </kbd>\n</template>\n"],"mappings":"oJAQQ,MAFN,EAEM,EAAA,EAAA,EAAA,WAAA,CADI,EAAA,OAAA,SAAA,CAAA,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { createElementBlock as e, defineComponent as t, openBlock as n, renderSlot as r } from "vue";
2
+ //#region src/components/TKbd.vue?vue&type=script&setup=true&lang.ts
3
+ var i = { class: "t-kbd" }, a = /*@__PURE__*/ t({
4
+ __name: "TKbd",
5
+ setup(t) {
6
+ return (t, a) => (n(), e("kbd", i, [r(t.$slots, "default")]));
7
+ }
8
+ });
9
+ //#endregion
10
+ export { a as default };
11
+
12
+ //# sourceMappingURL=TKbd.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TKbd.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../src/components/TKbd.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// A keyboard-key hint (e.g. ⌘K, Esc, Ctrl). Renders a native <kbd> with the\n// library's monospaced, bordered chip styling.\n</script>\n\n<template>\n <kbd class=\"t-kbd\">\n <slot />\n </kbd>\n</template>\n"],"mappings":";;;;;yBAME,EAEM,OAFN,GAEM,CADJ,EAAQ,EAAA,QAAA,SAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"TNavMenu.cjs","names":[],"sources":["../../src/components/TNavMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TNavMenu.cjs","names":[],"sources":["../../src/components/TNavMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n /**\n * When the item renders as a router link, controls whether an inclusive\n * (prefix) route match also marks it active. Defaults to the menu-level\n * `exact` prop. Set to `false` for section roots that should stay active on\n * nested routes.\n */\n exact?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n exact?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n exact: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst isRouterLinkItem = (item: TNavMenuItem) =>\n Boolean(item.to) && routerLinkComponent.value !== null;\n\n// Keep the active highlight deterministic when items render as router links.\n// Vue Router's default `router-link-active` uses inclusive (prefix) matching,\n// so several links can appear active at once. We map the router's active\n// classes onto TreeUI's own `is-selected`:\n// - Controlled menus (explicit `modelValue`) own selection, so the router adds\n// no class of its own — only the bound `is-selected` shows.\n// - Uncontrolled menus let the current route drive selection, using exact\n// matching by default (opt out per item, or menu-wide, via `exact`).\nconst routerActiveClass = (item: TNavMenuItem) => {\n if (!isRouterLinkItem(item)) {\n return undefined;\n }\n\n if (props.modelValue !== undefined) {\n return '';\n }\n\n return (item.exact ?? props.exact) ? '' : 'is-selected';\n};\n\nconst routerExactActiveClass = (item: TNavMenuItem) => {\n if (!isRouterLinkItem(item)) {\n return undefined;\n }\n\n return props.modelValue !== undefined ? '' : 'is-selected';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :active-class=\"routerActiveClass(item)\"\n :exact-active-class=\"routerExactActiveClass(item)\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"TNavMenu.js","names":[],"sources":["../../src/components/TNavMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TNavMenu.js","names":[],"sources":["../../src/components/TNavMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getNextEnabledIndex, isActivationKey } from '@treeui/utils';\nimport { computed, getCurrentInstance, inject, nextTick, ref, useAttrs, watch, type Component, type ComponentPublicInstance } from 'vue';\nimport type { TSize } from '../types/contracts';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nexport interface TNavMenuItem {\n label: string;\n value: string;\n shortLabel?: string;\n description?: string;\n icon?: Component;\n to?: string | Record<string, unknown>;\n badge?: string | number;\n disabled?: boolean;\n /**\n * When the item renders as a router link, controls whether an inclusive\n * (prefix) route match also marks it active. Defaults to the menu-level\n * `exact` prop. Set to `false` for section roots that should stay active on\n * nested routes.\n */\n exact?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n defaultValue?: string;\n items?: TNavMenuItem[];\n size?: TSize;\n collapsed?: boolean;\n disabled?: boolean;\n exact?: boolean;\n }>(),\n {\n modelValue: undefined,\n defaultValue: '',\n items: () => [],\n size: 'md',\n collapsed: undefined,\n disabled: false,\n exact: true,\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n select: [value: string, item: TNavMenuItem];\n}>();\n\ndefineSlots<{\n item?: (props: {\n item: TNavMenuItem;\n selected: boolean;\n focused: boolean;\n collapsed: boolean;\n }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebar = inject(treeSidebarInjectionKey, null);\nconst internalValue = ref(props.defaultValue);\nconst itemRefs = ref<Map<string, HTMLElement>>(new Map());\nconst instance = getCurrentInstance();\n\nconst selectedValue = computed(() => props.modelValue ?? internalValue.value);\nconst resolvedCollapsed = computed(() => props.collapsed ?? sidebar?.collapsed.value ?? false);\n\nconst routerLinkComponent = computed<Component | null>(() => (\n (instance?.appContext.components.RouterLink as Component | undefined) ?? null\n));\n\nconst itemTag = (item: TNavMenuItem) => {\n if (item.to && routerLinkComponent.value) {\n return routerLinkComponent.value;\n }\n return 'button';\n};\n\nconst isRouterLinkItem = (item: TNavMenuItem) =>\n Boolean(item.to) && routerLinkComponent.value !== null;\n\n// Keep the active highlight deterministic when items render as router links.\n// Vue Router's default `router-link-active` uses inclusive (prefix) matching,\n// so several links can appear active at once. We map the router's active\n// classes onto TreeUI's own `is-selected`:\n// - Controlled menus (explicit `modelValue`) own selection, so the router adds\n// no class of its own — only the bound `is-selected` shows.\n// - Uncontrolled menus let the current route drive selection, using exact\n// matching by default (opt out per item, or menu-wide, via `exact`).\nconst routerActiveClass = (item: TNavMenuItem) => {\n if (!isRouterLinkItem(item)) {\n return undefined;\n }\n\n if (props.modelValue !== undefined) {\n return '';\n }\n\n return (item.exact ?? props.exact) ? '' : 'is-selected';\n};\n\nconst routerExactActiveClass = (item: TNavMenuItem) => {\n if (!isRouterLinkItem(item)) {\n return undefined;\n }\n\n return props.modelValue !== undefined ? '' : 'is-selected';\n};\n\nconst getInitialFocusedIndex = () => {\n const selectedIndex = props.items.findIndex((item) =>\n item.value === selectedValue.value && !item.disabled,\n );\n\n if (selectedIndex >= 0) {\n return selectedIndex;\n }\n\n return props.items.findIndex((item) => !item.disabled);\n};\n\nconst focusedIndex = ref(getInitialFocusedIndex());\n\nconst rootClasses = computed(() => [\n 't-nav-menu',\n `t-nav-menu--${props.size}`,\n {\n 'is-collapsed': resolvedCollapsed.value,\n 'is-disabled': props.disabled,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => attrs.style);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst isSelected = (value: string) => selectedValue.value === value;\n\nconst setItemRef = (element: Element | ComponentPublicInstance | null, value: string) => {\n const resolvedElement =\n element instanceof HTMLElement\n ? element\n : element && '$el' in element && element.$el instanceof HTMLElement\n ? element.$el\n : null;\n\n if (resolvedElement) {\n itemRefs.value.set(value, resolvedElement);\n } else {\n itemRefs.value.delete(value);\n }\n};\n\nconst focusItem = (index: number) => {\n const item = props.items[index];\n\n if (!item) {\n return;\n }\n\n focusedIndex.value = index;\n nextTick(() => itemRefs.value.get(item.value)?.focus());\n};\n\nconst selectItem = (item: TNavMenuItem) => {\n if (props.disabled || item.disabled) {\n return;\n }\n\n if (props.modelValue === undefined) {\n internalValue.value = item.value;\n }\n\n emit('update:modelValue', item.value);\n emit('select', item.value, item);\n};\n\nconst onItemKeydown = (event: KeyboardEvent, index: number) => {\n if (props.disabled) {\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n const firstIndex = props.items.findIndex((item) => !item.disabled);\n\n if (firstIndex >= 0) {\n focusItem(firstIndex);\n }\n\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n const lastIndex = [...props.items].reverse().findIndex((item) => !item.disabled);\n\n if (lastIndex >= 0) {\n focusItem(props.items.length - 1 - lastIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {\n event.preventDefault();\n const nextIndex = getNextEnabledIndex(index, props.items, 1);\n\n if (nextIndex >= 0) {\n focusItem(nextIndex);\n }\n\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {\n event.preventDefault();\n const previousIndex = getNextEnabledIndex(index, props.items, -1);\n\n if (previousIndex >= 0) {\n focusItem(previousIndex);\n }\n\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectItem(props.items[index]);\n }\n};\n\nconst getTabIndex = (index: number) => (focusedIndex.value === index ? 0 : -1);\n\nwatch(\n () => [props.items, props.modelValue] as const,\n () => {\n const nextIndex = getInitialFocusedIndex();\n focusedIndex.value = nextIndex >= 0 ? nextIndex : -1;\n },\n { deep: true },\n);\n</script>\n\n<template>\n <nav\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n >\n <ul\n v-if=\"items.length > 0\"\n class=\"t-nav-menu__list\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"item.value\"\n class=\"t-nav-menu__entry\"\n >\n <component\n :is=\"itemTag(item)\"\n :ref=\"(element: Element | ComponentPublicInstance | null) => setItemRef(element, item.value)\"\n :type=\"item.to ? undefined : 'button'\"\n :to=\"item.to || undefined\"\n class=\"t-nav-menu__item\"\n :class=\"{\n 'is-selected': isSelected(item.value),\n 'is-disabled': disabled || item.disabled,\n }\"\n :active-class=\"routerActiveClass(item)\"\n :exact-active-class=\"routerExactActiveClass(item)\"\n :disabled=\"(!item.to && (disabled || item.disabled)) || undefined\"\n :aria-disabled=\"(item.to && (disabled || item.disabled)) || undefined\"\n :aria-current=\"isSelected(item.value) ? 'page' : undefined\"\n :tabindex=\"disabled || item.disabled ? -1 : getTabIndex(index)\"\n :title=\"resolvedCollapsed ? item.label : undefined\"\n @click=\"selectItem(item)\"\n @keydown=\"onItemKeydown($event, index)\"\n @focus=\"focusedIndex = index\"\n >\n <slot\n name=\"item\"\n :item=\"item\"\n :selected=\"isSelected(item.value)\"\n :focused=\"focusedIndex === index\"\n :collapsed=\"resolvedCollapsed\"\n >\n <component\n :is=\"item.icon\"\n v-if=\"item.icon\"\n class=\"t-nav-menu__icon\"\n aria-hidden=\"true\"\n />\n <span\n v-else\n class=\"t-nav-menu__marker\"\n aria-hidden=\"true\"\n >\n {{ (item.shortLabel ?? item.label.charAt(0)).toUpperCase() }}\n </span>\n\n <span class=\"t-nav-menu__copy\">\n <span class=\"t-nav-menu__label\">{{ item.label }}</span>\n <span\n v-if=\"item.description\"\n class=\"t-nav-menu__description\"\n >\n {{ item.description }}\n </span>\n </span>\n\n <span\n v-if=\"item.badge !== undefined && item.badge !== null\"\n class=\"t-nav-menu__badge\"\n >\n {{ item.badge }}\n </span>\n </slot>\n </component>\n </li>\n </ul>\n\n <div\n v-else\n class=\"t-nav-menu__empty\"\n >\n <slot name=\"empty\">\n No navigation items.\n </slot>\n </div>\n </nav>\n</template>\n"],"mappings":""}
@@ -9,6 +9,13 @@ export interface TNavMenuItem {
9
9
  to?: string | Record<string, unknown>;
10
10
  badge?: string | number;
11
11
  disabled?: boolean;
12
+ /**
13
+ * When the item renders as a router link, controls whether an inclusive
14
+ * (prefix) route match also marks it active. Defaults to the menu-level
15
+ * `exact` prop. Set to `false` for section roots that should stay active on
16
+ * nested routes.
17
+ */
18
+ exact?: boolean;
12
19
  }
13
20
  type __VLS_Props = {
14
21
  modelValue?: string;
@@ -17,6 +24,7 @@ type __VLS_Props = {
17
24
  size?: TSize;
18
25
  collapsed?: boolean;
19
26
  disabled?: boolean;
27
+ exact?: boolean;
20
28
  };
21
29
  declare function __VLS_template(): {
22
30
  attrs: Partial<{}>;
@@ -53,6 +61,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
53
61
  disabled: boolean;
54
62
  size: TSize;
55
63
  items: TNavMenuItem[];
64
+ exact: boolean;
56
65
  collapsed: boolean;
57
66
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
58
67
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
@@ -1 +1 @@
1
- {"version":3,"file":"TNavMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/TNavMenu.vue"],"names":[],"mappings":"AA+SA,OAAO,EAAwE,KAAK,SAAS,EAAgC,MAAM,KAAK,CAAC;AACzI,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAOhD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,KAAK,WAAW,GAAG;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAqMJ,iBAAS,cAAc;WA8IT,OAAO,IAA6B;;eA/TzC,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,YAAY,CAAC;YACnB,QAAQ,EAAE,OAAO,CAAC;YAClB,OAAO,EAAE,OAAO,CAAC;YACjB,SAAS,EAAE,OAAO,CAAC;SACpB,KAAK,OAAO;gBACL,MAAM,OAAO;;eANd,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,YAAY,CAAC;YACnB,QAAQ,EAAE,OAAO,CAAC;YAClB,OAAO,EAAE,OAAO,CAAC;YACjB,SAAS,EAAE,OAAO,CAAC;SACpB,KAAK,OAAO;gBACL,MAAM,OAAO;;;;EA8TtB;AAqBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;;;gBApXJ,MAAM;kBACJ,MAAM;cAIV,OAAO;UAFX,KAAK;WADJ,YAAY,EAAE;eAEV,OAAO;6EAwXrB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"TNavMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/TNavMenu.vue"],"names":[],"mappings":"AAyVA,OAAO,EAAwE,KAAK,SAAS,EAAgC,MAAM,KAAK,CAAC;AACzI,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAOhD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,KAAK,WAAW,GAAG;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAsOJ,iBAAS,cAAc;WAkJT,OAAO,IAA6B;;eAnWzC,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,YAAY,CAAC;YACnB,QAAQ,EAAE,OAAO,CAAC;YAClB,OAAO,EAAE,OAAO,CAAC;YACjB,SAAS,EAAE,OAAO,CAAC;SACpB,KAAK,OAAO;gBACL,MAAM,OAAO;;eANd,CAAC,KAAK,EAAE;YACb,IAAI,EAAE,YAAY,CAAC;YACnB,QAAQ,EAAE,OAAO,CAAC;YAClB,OAAO,EAAE,OAAO,CAAC;YACjB,SAAS,EAAE,OAAO,CAAC;SACpB,KAAK,OAAO;gBACL,MAAM,OAAO;;;;EAkWtB;AAuBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;;;gBA5ZJ,MAAM;kBACJ,MAAM;cAIV,OAAO;UAFX,KAAK;WADJ,YAAY,EAAE;WAId,OAAO;eAFH,OAAO;6EAgarB,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1,2 +1,2 @@
1
- const e=require("./sidebar.cjs");let t=require("vue"),n=require("@treeui/utils");var r={key:0,class:`t-nav-menu__list`},i={key:1,class:`t-nav-menu__marker`,"aria-hidden":`true`},a={class:`t-nav-menu__copy`},o={class:`t-nav-menu__label`},s={key:0,class:`t-nav-menu__description`},c={key:2,class:`t-nav-menu__badge`},l={key:1,class:`t-nav-menu__empty`},u=(0,t.defineComponent)({inheritAttrs:!1,__name:`TNavMenu`,props:{modelValue:{default:void 0},defaultValue:{default:``},items:{default:()=>[]},size:{default:`md`},collapsed:{type:Boolean,default:void 0},disabled:{type:Boolean,default:!1}},emits:[`update:modelValue`,`select`],setup(u,{emit:d}){let f=u,p=d,m=(0,t.useAttrs)(),h=(0,t.inject)(e.treeSidebarInjectionKey,null),g=(0,t.ref)(f.defaultValue),_=(0,t.ref)(new Map),v=(0,t.getCurrentInstance)(),y=(0,t.computed)(()=>f.modelValue??g.value),b=(0,t.computed)(()=>f.collapsed??h?.collapsed.value??!1),x=(0,t.computed)(()=>v?.appContext.components.RouterLink??null),S=e=>e.to&&x.value?x.value:`button`,C=()=>{let e=f.items.findIndex(e=>e.value===y.value&&!e.disabled);return e>=0?e:f.items.findIndex(e=>!e.disabled)},w=(0,t.ref)(C()),T=(0,t.computed)(()=>[`t-nav-menu`,`t-nav-menu--${f.size}`,{"is-collapsed":b.value,"is-disabled":f.disabled},m.class]),E=(0,t.computed)(()=>m.style),D=(0,t.computed)(()=>{let{class:e,style:t,...n}=m;return n}),O=e=>y.value===e,k=(e,t)=>{let n=e instanceof HTMLElement?e:e&&`$el`in e&&e.$el instanceof HTMLElement?e.$el:null;n?_.value.set(t,n):_.value.delete(t)},A=e=>{let n=f.items[e];n&&(w.value=e,(0,t.nextTick)(()=>_.value.get(n.value)?.focus()))},j=e=>{f.disabled||e.disabled||(f.modelValue===void 0&&(g.value=e.value),p(`update:modelValue`,e.value),p(`select`,e.value,e))},M=(e,t)=>{if(!f.disabled){if(e.key===`Home`){e.preventDefault();let t=f.items.findIndex(e=>!e.disabled);t>=0&&A(t);return}if(e.key===`End`){e.preventDefault();let t=[...f.items].reverse().findIndex(e=>!e.disabled);t>=0&&A(f.items.length-1-t);return}if(e.key===`ArrowDown`||e.key===`ArrowRight`){e.preventDefault();let r=(0,n.getNextEnabledIndex)(t,f.items,1);r>=0&&A(r);return}if(e.key===`ArrowUp`||e.key===`ArrowLeft`){e.preventDefault();let r=(0,n.getNextEnabledIndex)(t,f.items,-1);r>=0&&A(r);return}(0,n.isActivationKey)(e)&&(e.preventDefault(),j(f.items[t]))}},N=e=>w.value===e?0:-1;return(0,t.watch)(()=>[f.items,f.modelValue],()=>{let e=C();w.value=e>=0?e:-1},{deep:!0}),(e,n)=>((0,t.openBlock)(),(0,t.createElementBlock)(`nav`,(0,t.mergeProps)(D.value,{class:T.value,style:E.value}),[u.items.length>0?((0,t.openBlock)(),(0,t.createElementBlock)(`ul`,r,[((0,t.openBlock)(!0),(0,t.createElementBlock)(t.Fragment,null,(0,t.renderList)(u.items,(n,r)=>((0,t.openBlock)(),(0,t.createElementBlock)(`li`,{key:n.value,class:`t-nav-menu__entry`},[((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(S(n)),{ref_for:!0,ref:e=>k(e,n.value),type:n.to?void 0:`button`,to:n.to||void 0,class:(0,t.normalizeClass)([`t-nav-menu__item`,{"is-selected":O(n.value),"is-disabled":u.disabled||n.disabled}]),disabled:!n.to&&(u.disabled||n.disabled)||void 0,"aria-disabled":n.to&&(u.disabled||n.disabled)||void 0,"aria-current":O(n.value)?`page`:void 0,tabindex:u.disabled||n.disabled?-1:N(r),title:b.value?n.label:void 0,onClick:e=>j(n),onKeydown:e=>M(e,r),onFocus:e=>w.value=r},{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`item`,{item:n,selected:O(n.value),focused:w.value===r,collapsed:b.value},()=>[n.icon?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(n.icon),{key:0,class:`t-nav-menu__icon`,"aria-hidden":`true`})):((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,(0,t.toDisplayString)((n.shortLabel??n.label.charAt(0)).toUpperCase()),1)),(0,t.createElementVNode)(`span`,a,[(0,t.createElementVNode)(`span`,o,(0,t.toDisplayString)(n.label),1),n.description?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,s,(0,t.toDisplayString)(n.description),1)):(0,t.createCommentVNode)(``,!0)]),n.badge!==void 0&&n.badge!==null?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,c,(0,t.toDisplayString)(n.badge),1)):(0,t.createCommentVNode)(``,!0)])]),_:2},1064,[`type`,`to`,`class`,`disabled`,`aria-disabled`,`aria-current`,`tabindex`,`title`,`onClick`,`onKeydown`,`onFocus`]))]))),128))])):((0,t.openBlock)(),(0,t.createElementBlock)(`div`,l,[(0,t.renderSlot)(e.$slots,`empty`,{},()=>[n[0]||=(0,t.createTextVNode)(` No navigation items. `,-1)])]))],16))}});exports.default=u;
1
+ const e=require("./sidebar.cjs");let t=require("vue"),n=require("@treeui/utils");var r={key:0,class:`t-nav-menu__list`},i={key:1,class:`t-nav-menu__marker`,"aria-hidden":`true`},a={class:`t-nav-menu__copy`},o={class:`t-nav-menu__label`},s={key:0,class:`t-nav-menu__description`},c={key:2,class:`t-nav-menu__badge`},l={key:1,class:`t-nav-menu__empty`},u=(0,t.defineComponent)({inheritAttrs:!1,__name:`TNavMenu`,props:{modelValue:{default:void 0},defaultValue:{default:``},items:{default:()=>[]},size:{default:`md`},collapsed:{type:Boolean,default:void 0},disabled:{type:Boolean,default:!1},exact:{type:Boolean,default:!0}},emits:[`update:modelValue`,`select`],setup(u,{emit:d}){let f=u,p=d,m=(0,t.useAttrs)(),h=(0,t.inject)(e.treeSidebarInjectionKey,null),g=(0,t.ref)(f.defaultValue),_=(0,t.ref)(new Map),v=(0,t.getCurrentInstance)(),y=(0,t.computed)(()=>f.modelValue??g.value),b=(0,t.computed)(()=>f.collapsed??h?.collapsed.value??!1),x=(0,t.computed)(()=>v?.appContext.components.RouterLink??null),S=e=>e.to&&x.value?x.value:`button`,C=e=>!!e.to&&x.value!==null,w=e=>{if(C(e))return f.modelValue===void 0?e.exact??f.exact?``:`is-selected`:``},T=e=>{if(C(e))return f.modelValue===void 0?`is-selected`:``},E=()=>{let e=f.items.findIndex(e=>e.value===y.value&&!e.disabled);return e>=0?e:f.items.findIndex(e=>!e.disabled)},D=(0,t.ref)(E()),O=(0,t.computed)(()=>[`t-nav-menu`,`t-nav-menu--${f.size}`,{"is-collapsed":b.value,"is-disabled":f.disabled},m.class]),k=(0,t.computed)(()=>m.style),A=(0,t.computed)(()=>{let{class:e,style:t,...n}=m;return n}),j=e=>y.value===e,M=(e,t)=>{let n=e instanceof HTMLElement?e:e&&`$el`in e&&e.$el instanceof HTMLElement?e.$el:null;n?_.value.set(t,n):_.value.delete(t)},N=e=>{let n=f.items[e];n&&(D.value=e,(0,t.nextTick)(()=>_.value.get(n.value)?.focus()))},P=e=>{f.disabled||e.disabled||(f.modelValue===void 0&&(g.value=e.value),p(`update:modelValue`,e.value),p(`select`,e.value,e))},F=(e,t)=>{if(!f.disabled){if(e.key===`Home`){e.preventDefault();let t=f.items.findIndex(e=>!e.disabled);t>=0&&N(t);return}if(e.key===`End`){e.preventDefault();let t=[...f.items].reverse().findIndex(e=>!e.disabled);t>=0&&N(f.items.length-1-t);return}if(e.key===`ArrowDown`||e.key===`ArrowRight`){e.preventDefault();let r=(0,n.getNextEnabledIndex)(t,f.items,1);r>=0&&N(r);return}if(e.key===`ArrowUp`||e.key===`ArrowLeft`){e.preventDefault();let r=(0,n.getNextEnabledIndex)(t,f.items,-1);r>=0&&N(r);return}(0,n.isActivationKey)(e)&&(e.preventDefault(),P(f.items[t]))}},I=e=>D.value===e?0:-1;return(0,t.watch)(()=>[f.items,f.modelValue],()=>{let e=E();D.value=e>=0?e:-1},{deep:!0}),(e,n)=>((0,t.openBlock)(),(0,t.createElementBlock)(`nav`,(0,t.mergeProps)(A.value,{class:O.value,style:k.value}),[u.items.length>0?((0,t.openBlock)(),(0,t.createElementBlock)(`ul`,r,[((0,t.openBlock)(!0),(0,t.createElementBlock)(t.Fragment,null,(0,t.renderList)(u.items,(n,r)=>((0,t.openBlock)(),(0,t.createElementBlock)(`li`,{key:n.value,class:`t-nav-menu__entry`},[((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(S(n)),{ref_for:!0,ref:e=>M(e,n.value),type:n.to?void 0:`button`,to:n.to||void 0,class:(0,t.normalizeClass)([`t-nav-menu__item`,{"is-selected":j(n.value),"is-disabled":u.disabled||n.disabled}]),"active-class":w(n),"exact-active-class":T(n),disabled:!n.to&&(u.disabled||n.disabled)||void 0,"aria-disabled":n.to&&(u.disabled||n.disabled)||void 0,"aria-current":j(n.value)?`page`:void 0,tabindex:u.disabled||n.disabled?-1:I(r),title:b.value?n.label:void 0,onClick:e=>P(n),onKeydown:e=>F(e,r),onFocus:e=>D.value=r},{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`item`,{item:n,selected:j(n.value),focused:D.value===r,collapsed:b.value},()=>[n.icon?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(n.icon),{key:0,class:`t-nav-menu__icon`,"aria-hidden":`true`})):((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,(0,t.toDisplayString)((n.shortLabel??n.label.charAt(0)).toUpperCase()),1)),(0,t.createElementVNode)(`span`,a,[(0,t.createElementVNode)(`span`,o,(0,t.toDisplayString)(n.label),1),n.description?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,s,(0,t.toDisplayString)(n.description),1)):(0,t.createCommentVNode)(``,!0)]),n.badge!==void 0&&n.badge!==null?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,c,(0,t.toDisplayString)(n.badge),1)):(0,t.createCommentVNode)(``,!0)])]),_:2},1064,[`type`,`to`,`class`,`active-class`,`exact-active-class`,`disabled`,`aria-disabled`,`aria-current`,`tabindex`,`title`,`onClick`,`onKeydown`,`onFocus`]))]))),128))])):((0,t.openBlock)(),(0,t.createElementBlock)(`div`,l,[(0,t.renderSlot)(e.$slots,`empty`,{},()=>[n[0]||=(0,t.createTextVNode)(` No navigation items. `,-1)])]))],16))}});exports.default=u;
2
2
  //# sourceMappingURL=TNavMenu.vue_vue_type_script_setup_true_lang.cjs.map