@ternent/core 0.0.1

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 (313) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +17 -0
  3. package/.github/workflows/deploy-armour.yml +42 -0
  4. package/.github/workflows/deploy-identity.yml +42 -0
  5. package/.github/workflows/deploy-seal.yml +42 -0
  6. package/.github/workflows/deploy-ui.yml +42 -0
  7. package/.github/workflows/deploy-utils.yml +42 -0
  8. package/.github/workflows/release-create.yml +59 -0
  9. package/.github/workflows/release-publish.yml +54 -0
  10. package/.nvmrc +1 -0
  11. package/.ops/publish.mjs +31 -0
  12. package/package.json +16 -0
  13. package/packages/README.md +0 -0
  14. package/packages/armour/CHANGELOG.md +66 -0
  15. package/packages/armour/CLAUDE.md +8 -0
  16. package/packages/armour/README.md +103 -0
  17. package/packages/armour/SPEC.md +92 -0
  18. package/packages/armour/package.json +45 -0
  19. package/packages/armour/src/constants.ts +5 -0
  20. package/packages/armour/src/deps.d.ts +56 -0
  21. package/packages/armour/src/errors.ts +172 -0
  22. package/packages/armour/src/files.ts +73 -0
  23. package/packages/armour/src/identity.ts +72 -0
  24. package/packages/armour/src/index.ts +56 -0
  25. package/packages/armour/src/init.ts +10 -0
  26. package/packages/armour/src/passphrase.ts +33 -0
  27. package/packages/armour/src/recipients.ts +73 -0
  28. package/packages/armour/src/text.ts +68 -0
  29. package/packages/armour/src/types.ts +93 -0
  30. package/packages/armour/test/armour.test.ts +270 -0
  31. package/packages/armour/tsconfig.build.json +12 -0
  32. package/packages/armour/tsconfig.json +12 -0
  33. package/packages/armour/vite.config.ts +29 -0
  34. package/packages/concord/CHANGELOG.md +83 -0
  35. package/packages/concord/CLAUDE.md +9 -0
  36. package/packages/concord/README.md +146 -0
  37. package/packages/concord/SPEC.md +287 -0
  38. package/packages/concord/package.json +51 -0
  39. package/packages/concord/src/app.ts +717 -0
  40. package/packages/concord/src/errors.ts +9 -0
  41. package/packages/concord/src/index.ts +20 -0
  42. package/packages/concord/src/types.ts +127 -0
  43. package/packages/concord/test/concord.test.ts +978 -0
  44. package/packages/concord/tsconfig.json +12 -0
  45. package/packages/concord/vite.browser.config.ts +27 -0
  46. package/packages/concord/vite.config.ts +35 -0
  47. package/packages/concord/vite.config.ts.timestamp-1774262297922-ffd76e35ea668.mjs +83 -0
  48. package/packages/identity/CHANGELOG.md +47 -0
  49. package/packages/identity/README.md +236 -0
  50. package/packages/identity/package.json +41 -0
  51. package/packages/identity/src/index.ts +538 -0
  52. package/packages/identity/test/identity.test.ts +172 -0
  53. package/packages/identity/tsconfig.build.json +12 -0
  54. package/packages/identity/vite.config.ts +17 -0
  55. package/packages/ledger/CHANGELOG.md +69 -0
  56. package/packages/ledger/CLAUDE.md +9 -0
  57. package/packages/ledger/SPEC.md +304 -0
  58. package/packages/ledger/package.json +48 -0
  59. package/packages/ledger/src/index.ts +2 -0
  60. package/packages/ledger/src/ledger.ts +1286 -0
  61. package/packages/ledger/src/seal-cli.d.ts +25 -0
  62. package/packages/ledger/src/types.ts +294 -0
  63. package/packages/ledger/test/ledger.test.ts +838 -0
  64. package/packages/ledger/tsconfig.json +12 -0
  65. package/packages/ledger/vite.browser.config.ts +27 -0
  66. package/packages/ledger/vite.config.ts +39 -0
  67. package/packages/seal/CHANGELOG.md +137 -0
  68. package/packages/seal/CLAUDE.md +8 -0
  69. package/packages/seal/README.md +258 -0
  70. package/packages/seal/bin/seal +6 -0
  71. package/packages/seal/package.json +59 -0
  72. package/packages/seal/src/artifact.ts +380 -0
  73. package/packages/seal/src/cli.ts +372 -0
  74. package/packages/seal/src/commands/identity.ts +52 -0
  75. package/packages/seal/src/commands/manifest.ts +71 -0
  76. package/packages/seal/src/commands/publicKey.ts +7 -0
  77. package/packages/seal/src/commands/sign.ts +56 -0
  78. package/packages/seal/src/commands/verify.ts +54 -0
  79. package/packages/seal/src/crypto.ts +85 -0
  80. package/packages/seal/src/errors.ts +88 -0
  81. package/packages/seal/src/index.ts +5 -0
  82. package/packages/seal/src/manifest.ts +114 -0
  83. package/packages/seal/src/node.ts +18 -0
  84. package/packages/seal/src/proof.ts +344 -0
  85. package/packages/seal/test/artifact.test.ts +86 -0
  86. package/packages/seal/test/cli.test.ts +208 -0
  87. package/packages/seal/test/crypto.test.ts +21 -0
  88. package/packages/seal/test/manifest.test.ts +32 -0
  89. package/packages/seal/test/proof.test.ts +60 -0
  90. package/packages/seal/tsconfig.json +12 -0
  91. package/packages/seal/vite.config.ts +54 -0
  92. package/packages/ui/CHANGELOG.md +393 -0
  93. package/packages/ui/README.md +57 -0
  94. package/packages/ui/jsconfig.json +19 -0
  95. package/packages/ui/package.json +64 -0
  96. package/packages/ui/scripts/check-tokens.js +56 -0
  97. package/packages/ui/scripts/generate-theme-css.mjs +85 -0
  98. package/packages/ui/src/design-system/base.css +8 -0
  99. package/packages/ui/src/design-system/docs/ACCESSIBILITY_RULES.md +186 -0
  100. package/packages/ui/src/design-system/docs/AI_SYSTEM.md +281 -0
  101. package/packages/ui/src/design-system/docs/PATTERN_RULES.md +83 -0
  102. package/packages/ui/src/design-system/docs/PRIMITIVE_RULES.md +258 -0
  103. package/packages/ui/src/design-system/docs/TOKEN_RULES.md +235 -0
  104. package/packages/ui/src/design-system/docs/VISUAL_DIRECTION.md +68 -0
  105. package/packages/ui/src/design-system/foundation.js +420 -0
  106. package/packages/ui/src/design-system/tokens.css +140 -0
  107. package/packages/ui/src/design-system/tokens.js +327 -0
  108. package/packages/ui/src/design-system/utils.js +246 -0
  109. package/packages/ui/src/main.js +4 -0
  110. package/packages/ui/src/patterns/FeatureCard/FeatureCard.spec.md +24 -0
  111. package/packages/ui/src/patterns/FeatureCard/FeatureCard.types.ts +8 -0
  112. package/packages/ui/src/patterns/FeatureCard/FeatureCard.vue +175 -0
  113. package/packages/ui/src/patterns/FormField/FormField.spec.md +65 -0
  114. package/packages/ui/src/patterns/FormField/FormField.types.ts +11 -0
  115. package/packages/ui/src/patterns/FormField/FormField.vue +87 -0
  116. package/packages/ui/src/patterns/IdentityGlyph/IdentityGlyph.vue +61 -0
  117. package/packages/ui/src/patterns/IdentityGlyph/IdentityHandle.vue +58 -0
  118. package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.types.ts +36 -0
  119. package/packages/ui/src/patterns/IdentityGlyph/identityGlyph.utils.ts +585 -0
  120. package/packages/ui/src/patterns/IdentityGlyph/index.ts +5 -0
  121. package/packages/ui/src/patterns/KeyValueList/KeyValueList.spec.md +28 -0
  122. package/packages/ui/src/patterns/KeyValueList/KeyValueList.types.ts +16 -0
  123. package/packages/ui/src/patterns/KeyValueList/KeyValueList.vue +50 -0
  124. package/packages/ui/src/patterns/LandingPage/LandingIcon.vue +90 -0
  125. package/packages/ui/src/patterns/LandingPage/LandingPage.spec.md +24 -0
  126. package/packages/ui/src/patterns/LandingPage/LandingPage.types.ts +212 -0
  127. package/packages/ui/src/patterns/LandingPage/LandingPage.vue +599 -0
  128. package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.test.ts +33 -0
  129. package/packages/ui/src/patterns/ListWorkspaceLayout/ListWorkspaceLayout.vue +44 -0
  130. package/packages/ui/src/patterns/Logo/Logo.spec.md +22 -0
  131. package/packages/ui/src/patterns/Logo/Logo.vue +160 -0
  132. package/packages/ui/src/patterns/PageSurface/PageSurface.spec.md +15 -0
  133. package/packages/ui/src/patterns/PageSurface/PageSurface.vue +85 -0
  134. package/packages/ui/src/patterns/PanelChrome/PanelChrome.spec.md +39 -0
  135. package/packages/ui/src/patterns/PanelChrome/PanelChrome.types.ts +1 -0
  136. package/packages/ui/src/patterns/PanelChrome/PanelChrome.vue +187 -0
  137. package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.spec.md +31 -0
  138. package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.types.ts +23 -0
  139. package/packages/ui/src/patterns/PreviewPanel/PreviewPanel.vue +354 -0
  140. package/packages/ui/src/patterns/RecordList/RecordList.spec.md +35 -0
  141. package/packages/ui/src/patterns/RecordList/RecordList.test.ts +42 -0
  142. package/packages/ui/src/patterns/RecordList/RecordList.types.ts +9 -0
  143. package/packages/ui/src/patterns/RecordList/RecordList.utils.ts +5 -0
  144. package/packages/ui/src/patterns/RecordList/RecordList.vue +134 -0
  145. package/packages/ui/src/patterns/SectionClarifier/SectionClarifier.vue +85 -0
  146. package/packages/ui/src/patterns/SectionIntro/SectionIntro.spec.md +25 -0
  147. package/packages/ui/src/patterns/SectionIntro/SectionIntro.types.ts +7 -0
  148. package/packages/ui/src/patterns/SectionIntro/SectionIntro.vue +141 -0
  149. package/packages/ui/src/patterns/SidebarNav/SidebarNav.spec.md +34 -0
  150. package/packages/ui/src/patterns/SidebarNav/SidebarNav.types.ts +17 -0
  151. package/packages/ui/src/patterns/SidebarNav/SidebarNav.vue +110 -0
  152. package/packages/ui/src/patterns/SplitView/SplitView.spec.md +28 -0
  153. package/packages/ui/src/patterns/SplitView/SplitView.test.ts +22 -0
  154. package/packages/ui/src/patterns/SplitView/SplitView.types.ts +3 -0
  155. package/packages/ui/src/patterns/SplitView/SplitView.utils.ts +13 -0
  156. package/packages/ui/src/patterns/SplitView/SplitView.vue +39 -0
  157. package/packages/ui/src/patterns/StepList/StepList.spec.md +15 -0
  158. package/packages/ui/src/patterns/StepList/StepList.types.ts +4 -0
  159. package/packages/ui/src/patterns/StepList/StepList.vue +91 -0
  160. package/packages/ui/src/patterns/Verification/VerificationBadge.vue +97 -0
  161. package/packages/ui/src/patterns/Verification/VerificationComponents.test.ts +153 -0
  162. package/packages/ui/src/patterns/Verification/VerificationDetailsPanel.vue +270 -0
  163. package/packages/ui/src/patterns/Verification/VerificationSummary.vue +171 -0
  164. package/packages/ui/src/patterns/Verification/index.ts +6 -0
  165. package/packages/ui/src/patterns/Verification/verification.types.ts +8 -0
  166. package/packages/ui/src/patterns/Verification/verification.utils.test.ts +37 -0
  167. package/packages/ui/src/patterns/Verification/verification.utils.ts +75 -0
  168. package/packages/ui/src/patterns/index.ts +25 -0
  169. package/packages/ui/src/primitives/Accordian/Accordian.vue +11 -0
  170. package/packages/ui/src/primitives/Accordian/AccordianItem.vue +14 -0
  171. package/packages/ui/src/primitives/Accordion/Accordion.props.ts +21 -0
  172. package/packages/ui/src/primitives/Accordion/Accordion.spec.md +50 -0
  173. package/packages/ui/src/primitives/Accordion/Accordion.types.ts +4 -0
  174. package/packages/ui/src/primitives/Accordion/Accordion.variants.ts +12 -0
  175. package/packages/ui/src/primitives/Accordion/Accordion.vue +71 -0
  176. package/packages/ui/src/primitives/Accordion/AccordionItem.props.ts +14 -0
  177. package/packages/ui/src/primitives/Accordion/AccordionItem.vue +40 -0
  178. package/packages/ui/src/primitives/Badge/Badge.props.ts +17 -0
  179. package/packages/ui/src/primitives/Badge/Badge.spec.md +17 -0
  180. package/packages/ui/src/primitives/Badge/Badge.types.ts +15 -0
  181. package/packages/ui/src/primitives/Badge/Badge.variants.ts +48 -0
  182. package/packages/ui/src/primitives/Badge/Badge.vue +31 -0
  183. package/packages/ui/src/primitives/Button/Button.props.ts +29 -0
  184. package/packages/ui/src/primitives/Button/Button.spec.md +139 -0
  185. package/packages/ui/src/primitives/Button/Button.types.ts +19 -0
  186. package/packages/ui/src/primitives/Button/Button.variants.ts +72 -0
  187. package/packages/ui/src/primitives/Button/Button.vue +90 -0
  188. package/packages/ui/src/primitives/Card/Card.props.ts +17 -0
  189. package/packages/ui/src/primitives/Card/Card.spec.md +29 -0
  190. package/packages/ui/src/primitives/Card/Card.types.ts +12 -0
  191. package/packages/ui/src/primitives/Card/Card.variants.ts +27 -0
  192. package/packages/ui/src/primitives/Card/Card.vue +37 -0
  193. package/packages/ui/src/primitives/Checkbox/Checkbox.props.ts +21 -0
  194. package/packages/ui/src/primitives/Checkbox/Checkbox.spec.md +51 -0
  195. package/packages/ui/src/primitives/Checkbox/Checkbox.types.ts +4 -0
  196. package/packages/ui/src/primitives/Checkbox/Checkbox.variants.ts +34 -0
  197. package/packages/ui/src/primitives/Checkbox/Checkbox.vue +92 -0
  198. package/packages/ui/src/primitives/Dialog/Dialog.props.ts +29 -0
  199. package/packages/ui/src/primitives/Dialog/Dialog.spec.md +52 -0
  200. package/packages/ui/src/primitives/Dialog/Dialog.types.ts +3 -0
  201. package/packages/ui/src/primitives/Dialog/Dialog.variants.ts +27 -0
  202. package/packages/ui/src/primitives/Dialog/Dialog.vue +78 -0
  203. package/packages/ui/src/primitives/Drawer/Drawer.props.ts +33 -0
  204. package/packages/ui/src/primitives/Drawer/Drawer.spec.md +50 -0
  205. package/packages/ui/src/primitives/Drawer/Drawer.types.ts +5 -0
  206. package/packages/ui/src/primitives/Drawer/Drawer.variants.ts +35 -0
  207. package/packages/ui/src/primitives/Drawer/Drawer.vue +88 -0
  208. package/packages/ui/src/primitives/FieldMessage/FieldMessage.props.ts +17 -0
  209. package/packages/ui/src/primitives/FieldMessage/FieldMessage.spec.md +35 -0
  210. package/packages/ui/src/primitives/FieldMessage/FieldMessage.types.ts +5 -0
  211. package/packages/ui/src/primitives/FieldMessage/FieldMessage.variants.ts +14 -0
  212. package/packages/ui/src/primitives/FieldMessage/FieldMessage.vue +40 -0
  213. package/packages/ui/src/primitives/FileInput/FileInput.props.ts +41 -0
  214. package/packages/ui/src/primitives/FileInput/FileInput.types.ts +6 -0
  215. package/packages/ui/src/primitives/FileInput/FileInput.variants.ts +46 -0
  216. package/packages/ui/src/primitives/FileInput/FileInput.vue +163 -0
  217. package/packages/ui/src/primitives/Input/Input.props.ts +29 -0
  218. package/packages/ui/src/primitives/Input/Input.spec.md +79 -0
  219. package/packages/ui/src/primitives/Input/Input.types.ts +13 -0
  220. package/packages/ui/src/primitives/Input/Input.variants.ts +54 -0
  221. package/packages/ui/src/primitives/Input/Input.vue +99 -0
  222. package/packages/ui/src/primitives/Label/Label.props.ts +25 -0
  223. package/packages/ui/src/primitives/Label/Label.spec.md +31 -0
  224. package/packages/ui/src/primitives/Label/Label.types.ts +3 -0
  225. package/packages/ui/src/primitives/Label/Label.variants.ts +17 -0
  226. package/packages/ui/src/primitives/Label/Label.vue +38 -0
  227. package/packages/ui/src/primitives/Menu/Menu.props.ts +17 -0
  228. package/packages/ui/src/primitives/Menu/Menu.spec.md +38 -0
  229. package/packages/ui/src/primitives/Menu/Menu.types.ts +10 -0
  230. package/packages/ui/src/primitives/Menu/Menu.variants.ts +10 -0
  231. package/packages/ui/src/primitives/Menu/Menu.vue +57 -0
  232. package/packages/ui/src/primitives/Popover/Popover.props.ts +25 -0
  233. package/packages/ui/src/primitives/Popover/Popover.spec.md +49 -0
  234. package/packages/ui/src/primitives/Popover/Popover.types.ts +3 -0
  235. package/packages/ui/src/primitives/Popover/Popover.variants.ts +18 -0
  236. package/packages/ui/src/primitives/Popover/Popover.vue +74 -0
  237. package/packages/ui/src/primitives/RadioGroup/RadioGroup.props.ts +29 -0
  238. package/packages/ui/src/primitives/RadioGroup/RadioGroup.spec.md +50 -0
  239. package/packages/ui/src/primitives/RadioGroup/RadioGroup.types.ts +12 -0
  240. package/packages/ui/src/primitives/RadioGroup/RadioGroup.variants.ts +48 -0
  241. package/packages/ui/src/primitives/RadioGroup/RadioGroup.vue +87 -0
  242. package/packages/ui/src/primitives/Separator/Separator.props.ts +9 -0
  243. package/packages/ui/src/primitives/Separator/Separator.spec.md +15 -0
  244. package/packages/ui/src/primitives/Separator/Separator.types.ts +3 -0
  245. package/packages/ui/src/primitives/Separator/Separator.variants.ts +8 -0
  246. package/packages/ui/src/primitives/Separator/Separator.vue +23 -0
  247. package/packages/ui/src/primitives/Skeleton/Skeleton.props.ts +21 -0
  248. package/packages/ui/src/primitives/Skeleton/Skeleton.spec.md +18 -0
  249. package/packages/ui/src/primitives/Skeleton/Skeleton.types.ts +5 -0
  250. package/packages/ui/src/primitives/Skeleton/Skeleton.variants.ts +18 -0
  251. package/packages/ui/src/primitives/Skeleton/Skeleton.vue +37 -0
  252. package/packages/ui/src/primitives/Spinner/Spinner.props.ts +13 -0
  253. package/packages/ui/src/primitives/Spinner/Spinner.spec.md +16 -0
  254. package/packages/ui/src/primitives/Spinner/Spinner.types.ts +5 -0
  255. package/packages/ui/src/primitives/Spinner/Spinner.variants.ts +15 -0
  256. package/packages/ui/src/primitives/Spinner/Spinner.vue +33 -0
  257. package/packages/ui/src/primitives/SplitButton/SplitButton.vue +108 -0
  258. package/packages/ui/src/primitives/Switch/Switch.props.ts +21 -0
  259. package/packages/ui/src/primitives/Switch/Switch.spec.md +49 -0
  260. package/packages/ui/src/primitives/Switch/Switch.types.ts +3 -0
  261. package/packages/ui/src/primitives/Switch/Switch.variants.ts +34 -0
  262. package/packages/ui/src/primitives/Switch/Switch.vue +71 -0
  263. package/packages/ui/src/primitives/Tabs/Tabs.props.ts +25 -0
  264. package/packages/ui/src/primitives/Tabs/Tabs.spec.md +48 -0
  265. package/packages/ui/src/primitives/Tabs/Tabs.types.ts +11 -0
  266. package/packages/ui/src/primitives/Tabs/Tabs.variants.ts +28 -0
  267. package/packages/ui/src/primitives/Tabs/Tabs.vue +59 -0
  268. package/packages/ui/src/primitives/Textarea/Textarea.props.ts +33 -0
  269. package/packages/ui/src/primitives/Textarea/Textarea.spec.md +59 -0
  270. package/packages/ui/src/primitives/Textarea/Textarea.types.ts +5 -0
  271. package/packages/ui/src/primitives/Textarea/Textarea.variants.ts +27 -0
  272. package/packages/ui/src/primitives/Textarea/Textarea.vue +74 -0
  273. package/packages/ui/src/primitives/Tooltip/Tooltip.props.ts +21 -0
  274. package/packages/ui/src/primitives/Tooltip/Tooltip.spec.md +45 -0
  275. package/packages/ui/src/primitives/Tooltip/Tooltip.types.ts +3 -0
  276. package/packages/ui/src/primitives/Tooltip/Tooltip.variants.ts +4 -0
  277. package/packages/ui/src/primitives/Tooltip/Tooltip.vue +31 -0
  278. package/packages/ui/src/primitives/TreeView/TreeView.types.ts +10 -0
  279. package/packages/ui/src/primitives/TreeView/TreeView.vue +113 -0
  280. package/packages/ui/src/primitives/TreeView/TreeViewNode.vue +190 -0
  281. package/packages/ui/src/primitives/index.ts +29 -0
  282. package/packages/ui/src/style.css +7 -0
  283. package/packages/ui/src/style.js +1 -0
  284. package/packages/ui/src/themes/armour.css +147 -0
  285. package/packages/ui/src/themes/aurora.css +147 -0
  286. package/packages/ui/src/themes/citrine-ash.css +147 -0
  287. package/packages/ui/src/themes/concord.css +147 -0
  288. package/packages/ui/src/themes/garnet-honey.css +147 -0
  289. package/packages/ui/src/themes/harbor-rose.css +147 -0
  290. package/packages/ui/src/themes/ledger.css +147 -0
  291. package/packages/ui/src/themes/neon-noir.css +74 -0
  292. package/packages/ui/src/themes/obsidian-iris.css +147 -0
  293. package/packages/ui/src/themes/pixpax.css +147 -0
  294. package/packages/ui/src/themes/print.css +147 -0
  295. package/packages/ui/src/themes/prism.css +147 -0
  296. package/packages/ui/src/themes/proof.css +145 -0
  297. package/packages/ui/src/themes/semanticThemeContract.js +2256 -0
  298. package/packages/ui/src/themes/spruce-ink.css +147 -0
  299. package/packages/ui/src/themes/sunset.css +147 -0
  300. package/packages/ui/tailwind.config.js +64 -0
  301. package/packages/ui/vite.config.js +35 -0
  302. package/packages/ui/vite.config.js.timestamp-1780697224943-89fbc929987bc.mjs +38 -0
  303. package/packages/utils/CHANGELOG.md +111 -0
  304. package/packages/utils/README.md +3 -0
  305. package/packages/utils/package.json +46 -0
  306. package/packages/utils/src/index.test.js +39 -0
  307. package/packages/utils/src/index.ts +289 -0
  308. package/packages/utils/tsconfig.build.json +12 -0
  309. package/packages/utils/vite.config.js +28 -0
  310. package/pnpm-workspace.yaml +8 -0
  311. package/scripts/vite/package-lib-config.ts +59 -0
  312. package/tsconfig.json +24 -0
  313. package/tsconfig.node.json +9 -0
@@ -0,0 +1,78 @@
1
+ <script setup lang="ts">
2
+ import { Dialog as ArkDialog } from "@ark-ui/vue/dialog";
3
+ import { computed, useSlots } from "vue";
4
+ import { dialogProps } from "./Dialog.props";
5
+ import {
6
+ dialogBackdropClass,
7
+ dialogBodyClass,
8
+ dialogCloseClass,
9
+ dialogContentBaseClass,
10
+ dialogContentSizeClasses,
11
+ dialogDescriptionClass,
12
+ dialogFooterClass,
13
+ dialogHeaderClass,
14
+ dialogPositionerClass,
15
+ dialogTitleClass,
16
+ } from "./Dialog.variants";
17
+
18
+ const open = defineModel<boolean>("open", { default: false });
19
+ const props = defineProps(dialogProps);
20
+ const slots = useSlots();
21
+
22
+ const hasHeader = computed(() =>
23
+ Boolean(props.title || props.description || slots.header || props.showClose),
24
+ );
25
+ </script>
26
+
27
+ <template>
28
+ <ArkDialog.Root
29
+ v-model:open="open"
30
+ :close-on-escape="props.closeOnEscape"
31
+ :close-on-interact-outside="props.closeOnInteractOutside"
32
+ lazy-mount
33
+ unmount-on-exit
34
+ >
35
+ <ArkDialog.Trigger v-if="$slots.trigger" as-child>
36
+ <slot name="trigger" />
37
+ </ArkDialog.Trigger>
38
+ <ArkDialog.Backdrop :class="dialogBackdropClass" />
39
+ <ArkDialog.Positioner :class="dialogPositionerClass">
40
+ <ArkDialog.Content :class="[dialogContentBaseClass, dialogContentSizeClasses[props.size]]">
41
+ <div v-if="hasHeader" :class="dialogHeaderClass">
42
+ <slot name="header">
43
+ <div class="min-w-0 flex-1">
44
+ <ArkDialog.Title v-if="props.title" :class="dialogTitleClass">
45
+ {{ props.title }}
46
+ </ArkDialog.Title>
47
+ <ArkDialog.Description v-if="props.description" :class="dialogDescriptionClass">
48
+ {{ props.description }}
49
+ </ArkDialog.Description>
50
+ </div>
51
+ </slot>
52
+ <ArkDialog.CloseTrigger
53
+ v-if="props.showClose"
54
+ :class="dialogCloseClass"
55
+ aria-label="Close dialog"
56
+ >
57
+ <svg viewBox="0 0 24 24" fill="none" class="size-4" aria-hidden="true">
58
+ <path
59
+ d="M6 6l12 12M18 6 6 18"
60
+ stroke="currentColor"
61
+ stroke-width="1.75"
62
+ stroke-linecap="round"
63
+ />
64
+ </svg>
65
+ </ArkDialog.CloseTrigger>
66
+ </div>
67
+
68
+ <div :class="dialogBodyClass">
69
+ <slot />
70
+ </div>
71
+
72
+ <div v-if="$slots.footer" :class="dialogFooterClass">
73
+ <slot name="footer" />
74
+ </div>
75
+ </ArkDialog.Content>
76
+ </ArkDialog.Positioner>
77
+ </ArkDialog.Root>
78
+ </template>
@@ -0,0 +1,33 @@
1
+ import type { PropType } from "vue";
2
+ import type { DrawerSide, DrawerSize } from "./Drawer.types";
3
+
4
+ export const drawerProps = {
5
+ title: {
6
+ type: String,
7
+ default: undefined,
8
+ },
9
+ description: {
10
+ type: String,
11
+ default: undefined,
12
+ },
13
+ side: {
14
+ type: String as PropType<DrawerSide>,
15
+ default: "right",
16
+ },
17
+ size: {
18
+ type: String as PropType<DrawerSize>,
19
+ default: "md",
20
+ },
21
+ showClose: {
22
+ type: Boolean,
23
+ default: true,
24
+ },
25
+ closeOnEscape: {
26
+ type: Boolean,
27
+ default: true,
28
+ },
29
+ closeOnInteractOutside: {
30
+ type: Boolean,
31
+ default: true,
32
+ },
33
+ };
@@ -0,0 +1,50 @@
1
+ # Drawer
2
+
3
+ ## Purpose
4
+
5
+ Side-sheet overlay primitive for longer workflows or contextual panels.
6
+
7
+ ## Category
8
+
9
+ Primitive
10
+
11
+ ## Public API
12
+
13
+ Props:
14
+
15
+ - `open` via `v-model:open`
16
+ - `title`
17
+ - `description`
18
+ - `side`: `left | right`
19
+ - `size`: `sm | md | lg`
20
+ - `showClose`
21
+ - `closeOnEscape`
22
+ - `closeOnInteractOutside`
23
+
24
+ Slots:
25
+
26
+ - `trigger`
27
+ - `header`
28
+ - default content
29
+ - `footer`
30
+
31
+ ## Accessibility
32
+
33
+ - built on Ark dialog semantics
34
+ - traps focus while open
35
+ - behaves like a modal side sheet rather than a resizable app-specific panel
36
+
37
+ ## Keyboard behavior
38
+
39
+ - focus moves into the drawer on open
40
+ - Escape closes when enabled
41
+
42
+ ## Example
43
+
44
+ ```vue
45
+ <Drawer v-model:open="open" title="Filters" side="right">
46
+ <template #trigger>
47
+ <Button variant="secondary">Open filters</Button>
48
+ </template>
49
+ </Drawer>
50
+ ```
@@ -0,0 +1,5 @@
1
+ export const drawerSideValues = ["left", "right"] as const;
2
+ export const drawerSizeValues = ["sm", "md", "lg"] as const;
3
+
4
+ export type DrawerSide = (typeof drawerSideValues)[number];
5
+ export type DrawerSize = (typeof drawerSizeValues)[number];
@@ -0,0 +1,35 @@
1
+ import type { DrawerSide, DrawerSize } from "./Drawer.types";
2
+
3
+ export const drawerBackdropClass = "fixed inset-0 z-40 bg-[var(--ui-fg)]/40 backdrop-blur-sm";
4
+ export const drawerPositionerBaseClass = "fixed inset-0 z-50 flex";
5
+ export const drawerPositionerSideClasses: Record<DrawerSide, string> = {
6
+ left: "justify-start",
7
+ right: "justify-end",
8
+ };
9
+
10
+ export const drawerContentBaseClass =
11
+ "flex h-full w-full max-w-full flex-col overflow-hidden border-[var(--ui-border)] bg-[var(--ui-surface)] text-[var(--ui-fg)] shadow-[var(--ui-shadow-md)]";
12
+
13
+ export const drawerContentSideClasses: Record<DrawerSide, string> = {
14
+ left: "border-r",
15
+ right: "border-l",
16
+ };
17
+
18
+ export const drawerContentSizeClasses: Record<DrawerSize, string> = {
19
+ sm: "max-w-md",
20
+ md: "max-w-lg",
21
+ lg: "max-w-2xl",
22
+ };
23
+
24
+ export const drawerHeaderClass =
25
+ "flex items-start justify-between gap-4 border-b border-[var(--ui-border)] px-4 py-3";
26
+ export const drawerTitleClass = "text-base font-semibold text-[var(--ui-fg)]";
27
+ export const drawerDescriptionClass = "mt-1 text-sm text-[var(--ui-fg-muted)]";
28
+ export const drawerBodyClass = "flex-1 overflow-auto px-4 py-4";
29
+ export const drawerFooterClass =
30
+ "flex items-center justify-end gap-3 border-t border-[var(--ui-border)] px-4 py-3";
31
+ export const drawerCloseClass =
32
+ "inline-flex size-9 items-center justify-center rounded-[var(--ui-radius-sm)] border border-[var(--ui-border)] " +
33
+ "text-[var(--ui-fg-muted)] transition-[border-color,background-color,color] duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] " +
34
+ "hover:border-[var(--ui-primary-muted)] hover:bg-[var(--ui-tonal-secondary)] hover:text-[var(--ui-fg)] " +
35
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-ring)]";
@@ -0,0 +1,88 @@
1
+ <script setup lang="ts">
2
+ import { Dialog as ArkDialog } from "@ark-ui/vue/dialog";
3
+ import { computed, useSlots } from "vue";
4
+ import { drawerProps } from "./Drawer.props";
5
+ import {
6
+ drawerBackdropClass,
7
+ drawerBodyClass,
8
+ drawerCloseClass,
9
+ drawerContentBaseClass,
10
+ drawerContentSideClasses,
11
+ drawerContentSizeClasses,
12
+ drawerDescriptionClass,
13
+ drawerFooterClass,
14
+ drawerHeaderClass,
15
+ drawerPositionerBaseClass,
16
+ drawerPositionerSideClasses,
17
+ drawerTitleClass,
18
+ } from "./Drawer.variants";
19
+
20
+ const open = defineModel<boolean>("open", { default: false });
21
+ const props = defineProps(drawerProps);
22
+ const slots = useSlots();
23
+
24
+ const hasHeader = computed(() =>
25
+ Boolean(props.title || props.description || slots.header || props.showClose),
26
+ );
27
+ </script>
28
+
29
+ <template>
30
+ <ArkDialog.Root
31
+ v-model:open="open"
32
+ :close-on-escape="props.closeOnEscape"
33
+ :close-on-interact-outside="props.closeOnInteractOutside"
34
+ lazy-mount
35
+ unmount-on-exit
36
+ >
37
+ <ArkDialog.Trigger v-if="$slots.trigger" as-child>
38
+ <slot name="trigger" />
39
+ </ArkDialog.Trigger>
40
+ <ArkDialog.Backdrop :class="drawerBackdropClass" />
41
+ <ArkDialog.Positioner
42
+ :class="[drawerPositionerBaseClass, drawerPositionerSideClasses[props.side]]"
43
+ >
44
+ <ArkDialog.Content
45
+ :class="[
46
+ drawerContentBaseClass,
47
+ drawerContentSideClasses[props.side],
48
+ drawerContentSizeClasses[props.size],
49
+ ]"
50
+ >
51
+ <div v-if="hasHeader" :class="drawerHeaderClass">
52
+ <slot name="header">
53
+ <div class="min-w-0 flex-1">
54
+ <ArkDialog.Title v-if="props.title" :class="drawerTitleClass">
55
+ {{ props.title }}
56
+ </ArkDialog.Title>
57
+ <ArkDialog.Description v-if="props.description" :class="drawerDescriptionClass">
58
+ {{ props.description }}
59
+ </ArkDialog.Description>
60
+ </div>
61
+ </slot>
62
+ <ArkDialog.CloseTrigger
63
+ v-if="props.showClose"
64
+ :class="drawerCloseClass"
65
+ aria-label="Close drawer"
66
+ >
67
+ <svg viewBox="0 0 24 24" fill="none" class="size-4" aria-hidden="true">
68
+ <path
69
+ d="M6 6l12 12M18 6 6 18"
70
+ stroke="currentColor"
71
+ stroke-width="1.75"
72
+ stroke-linecap="round"
73
+ />
74
+ </svg>
75
+ </ArkDialog.CloseTrigger>
76
+ </div>
77
+
78
+ <div :class="drawerBodyClass">
79
+ <slot />
80
+ </div>
81
+
82
+ <div v-if="$slots.footer" :class="drawerFooterClass">
83
+ <slot name="footer" />
84
+ </div>
85
+ </ArkDialog.Content>
86
+ </ArkDialog.Positioner>
87
+ </ArkDialog.Root>
88
+ </template>
@@ -0,0 +1,17 @@
1
+ import type { PropType } from "vue";
2
+ import type { FieldMessageSize, FieldMessageTone } from "./FieldMessage.types";
3
+
4
+ export const fieldMessageProps = {
5
+ id: {
6
+ type: String,
7
+ default: undefined,
8
+ },
9
+ size: {
10
+ type: String as PropType<FieldMessageSize>,
11
+ default: "md",
12
+ },
13
+ tone: {
14
+ type: String as PropType<FieldMessageTone>,
15
+ default: "muted",
16
+ },
17
+ };
@@ -0,0 +1,35 @@
1
+ # FieldMessage
2
+
3
+ ## Purpose
4
+
5
+ Supporting field copy primitive for descriptions, hints, and validation messages.
6
+
7
+ ## Category
8
+
9
+ Primitive
10
+
11
+ ## Public API
12
+
13
+ Props:
14
+
15
+ - `id`: string
16
+ - `size`: `sm | md | lg`
17
+ - `tone`: `muted | critical`
18
+
19
+ ## Accessibility
20
+
21
+ - uses a simple text container
22
+ - critical messages use `role="alert"`
23
+ - designed to be referenced from controls via `aria-describedby`
24
+
25
+ ## Examples
26
+
27
+ ```vue
28
+ <FieldMessage id="email-help">We will never share your email.</FieldMessage>
29
+ ```
30
+
31
+ ```vue
32
+ <FieldMessage id="email-error" tone="critical">
33
+ Enter a valid email address.
34
+ </FieldMessage>
35
+ ```
@@ -0,0 +1,5 @@
1
+ export const fieldMessageSizeValues = ["sm", "md", "lg"] as const;
2
+ export const fieldMessageToneValues = ["muted", "critical"] as const;
3
+
4
+ export type FieldMessageSize = (typeof fieldMessageSizeValues)[number];
5
+ export type FieldMessageTone = (typeof fieldMessageToneValues)[number];
@@ -0,0 +1,14 @@
1
+ import type { FieldMessageSize, FieldMessageTone } from "./FieldMessage.types";
2
+
3
+ export const fieldMessageBaseClass = "text-[var(--ui-fg-muted)]";
4
+
5
+ export const fieldMessageSizeClasses: Record<FieldMessageSize, string> = {
6
+ sm: "text-xs",
7
+ md: "text-sm",
8
+ lg: "text-base",
9
+ };
10
+
11
+ export const fieldMessageToneClasses: Record<FieldMessageTone, string> = {
12
+ muted: "text-[var(--ui-fg-muted)]",
13
+ critical: "text-[var(--ui-critical)]",
14
+ };
@@ -0,0 +1,40 @@
1
+ <script setup lang="ts">
2
+ import { computed, normalizeClass, useAttrs } from "vue";
3
+ import { twMerge } from "tailwind-merge";
4
+ import { fieldMessageProps } from "./FieldMessage.props";
5
+ import {
6
+ fieldMessageBaseClass,
7
+ fieldMessageSizeClasses,
8
+ fieldMessageToneClasses,
9
+ } from "./FieldMessage.variants";
10
+
11
+ defineOptions({ inheritAttrs: false });
12
+
13
+ const attrs = useAttrs();
14
+ const props = defineProps(fieldMessageProps);
15
+
16
+ const classes = computed(() =>
17
+ twMerge(
18
+ fieldMessageBaseClass,
19
+ fieldMessageSizeClasses[props.size],
20
+ fieldMessageToneClasses[props.tone],
21
+ normalizeClass(attrs.class),
22
+ ),
23
+ );
24
+
25
+ const fieldMessageAttrs = computed(() => {
26
+ const { class: _class, role: _role, ...rest } = attrs;
27
+ return rest;
28
+ });
29
+ </script>
30
+
31
+ <template>
32
+ <p
33
+ :id="props.id"
34
+ :class="classes"
35
+ :role="props.tone === 'critical' ? 'alert' : undefined"
36
+ v-bind="fieldMessageAttrs"
37
+ >
38
+ <slot />
39
+ </p>
40
+ </template>
@@ -0,0 +1,41 @@
1
+ import type { PropType } from "vue";
2
+ import type { FileInputSize, FileInputValue, FileInputVariant } from "./FileInput.types";
3
+
4
+ export const fileInputProps = {
5
+ modelValue: {
6
+ type: [Object, Array, null] as PropType<FileInputValue>,
7
+ default: null,
8
+ },
9
+ accept: {
10
+ type: String,
11
+ default: undefined,
12
+ },
13
+ multiple: {
14
+ type: Boolean,
15
+ default: false,
16
+ },
17
+ disabled: {
18
+ type: Boolean,
19
+ default: false,
20
+ },
21
+ invalid: {
22
+ type: Boolean,
23
+ default: false,
24
+ },
25
+ size: {
26
+ type: String as PropType<FileInputSize>,
27
+ default: "md",
28
+ },
29
+ variant: {
30
+ type: String as PropType<FileInputVariant>,
31
+ default: "default",
32
+ },
33
+ placeholder: {
34
+ type: String,
35
+ default: "Choose file",
36
+ },
37
+ dropzoneTitle: {
38
+ type: String,
39
+ default: "Drop files here or click to browse",
40
+ },
41
+ };
@@ -0,0 +1,6 @@
1
+ export const fileInputVariantValues = ["default", "dropzone"] as const;
2
+ export const fileInputSizeValues = ["sm", "md", "lg"] as const;
3
+
4
+ export type FileInputVariant = (typeof fileInputVariantValues)[number];
5
+ export type FileInputSize = (typeof fileInputSizeValues)[number];
6
+ export type FileInputValue = File | File[] | null;
@@ -0,0 +1,46 @@
1
+ import type { FileInputSize } from "./FileInput.types";
2
+
3
+ export const fileInputRootClass = "flex w-full flex-col gap-3";
4
+
5
+ export const fileInputButtonBaseClass =
6
+ "inline-flex w-full items-center gap-3 rounded-[var(--ui-radius-md)] border bg-[var(--ui-surface)] " +
7
+ "text-left text-[var(--ui-fg)] transition-[background-color,border-color,box-shadow,color] " +
8
+ "duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] " +
9
+ "border-[var(--ui-border)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-ring)] focus-visible:border-[var(--ui-primary)]";
10
+
11
+ export const fileInputButtonStateClasses = {
12
+ default: "hover:border-[var(--ui-primary-muted)] hover:bg-[var(--ui-surface-hover)]",
13
+ invalid:
14
+ "border-[var(--ui-critical)] focus-visible:border-[var(--ui-critical)] focus-visible:ring-[var(--ui-critical-muted)]",
15
+ disabled: "pointer-events-none cursor-not-allowed opacity-50",
16
+ } as const;
17
+
18
+ export const fileInputButtonSizeClasses: Record<FileInputSize, string> = {
19
+ sm: "min-h-10 px-3 py-2 text-sm",
20
+ md: "min-h-11 px-4 py-3 text-sm",
21
+ lg: "min-h-12 px-4 py-3 text-base",
22
+ };
23
+
24
+ export const fileInputTextMutedClass = "text-[var(--ui-fg-muted)]";
25
+ export const fileInputTextStrongClass = "font-medium text-[var(--ui-fg)]";
26
+ export const fileInputIconClass =
27
+ "inline-flex size-10 shrink-0 items-center justify-center rounded-[var(--ui-radius-md)] border border-[var(--ui-border)] bg-[var(--ui-tonal-secondary)] text-[var(--ui-primary)]";
28
+
29
+ export const fileInputDropzoneBaseClass =
30
+ "flex w-full flex-col items-center justify-center rounded-[var(--ui-radius-lg)] border border-dashed " +
31
+ "border-[var(--ui-border)] bg-[var(--ui-tonal-tertiary)] text-center transition-[background-color,border-color,box-shadow,color] " +
32
+ "duration-[var(--ui-duration-normal)] ease-[var(--ui-ease-out)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-ring)] focus-visible:border-[var(--ui-primary)]";
33
+
34
+ export const fileInputDropzoneStateClasses = {
35
+ default: "hover:border-[var(--ui-primary-muted)] hover:bg-[var(--ui-tonal-secondary)]",
36
+ drag: "border-[var(--ui-primary)] bg-[var(--ui-primary-muted)]",
37
+ invalid:
38
+ "border-[var(--ui-critical)] focus-visible:border-[var(--ui-critical)] focus-visible:ring-[var(--ui-critical-muted)]",
39
+ disabled: "pointer-events-none cursor-not-allowed opacity-50",
40
+ } as const;
41
+
42
+ export const fileInputDropzoneSizeClasses: Record<FileInputSize, string> = {
43
+ sm: "min-h-36 px-4 py-5",
44
+ md: "min-h-44 px-6 py-6",
45
+ lg: "min-h-52 px-8 py-8",
46
+ };
@@ -0,0 +1,163 @@
1
+ <script setup lang="ts">
2
+ import { computed, normalizeClass, ref, useAttrs, useId } from "vue";
3
+ import { twMerge } from "tailwind-merge";
4
+ import { fileInputProps } from "./FileInput.props";
5
+ import {
6
+ fileInputButtonBaseClass,
7
+ fileInputButtonSizeClasses,
8
+ fileInputButtonStateClasses,
9
+ fileInputDropzoneBaseClass,
10
+ fileInputDropzoneSizeClasses,
11
+ fileInputDropzoneStateClasses,
12
+ fileInputIconClass,
13
+ fileInputRootClass,
14
+ fileInputTextMutedClass,
15
+ fileInputTextStrongClass,
16
+ } from "./FileInput.variants";
17
+ import type { FileInputValue } from "./FileInput.types";
18
+
19
+ defineOptions({ inheritAttrs: false });
20
+
21
+ const emit = defineEmits<{
22
+ "update:modelValue": [value: FileInputValue];
23
+ "update:filename": [value: string];
24
+ }>();
25
+
26
+ const attrs = useAttrs();
27
+ const props = defineProps(fileInputProps);
28
+
29
+ const inputId = useId();
30
+ const isDragOver = ref(false);
31
+
32
+ const rootClass = computed(() => twMerge(fileInputRootClass, normalizeClass(attrs.class)));
33
+
34
+ const rootAttrs = computed(() => {
35
+ const { class: _class, ...rest } = attrs;
36
+ return rest;
37
+ });
38
+
39
+ const selectedLabel = computed(() => {
40
+ const value = props.modelValue;
41
+
42
+ if (Array.isArray(value)) {
43
+ return value.length ? value.map((item) => item.name).join(", ") : props.placeholder;
44
+ }
45
+
46
+ return value?.name || props.placeholder;
47
+ });
48
+
49
+ const defaultButtonClass = computed(() =>
50
+ twMerge(
51
+ fileInputButtonBaseClass,
52
+ fileInputButtonSizeClasses[props.size],
53
+ props.invalid ? fileInputButtonStateClasses.invalid : fileInputButtonStateClasses.default,
54
+ props.disabled ? fileInputButtonStateClasses.disabled : "",
55
+ ),
56
+ );
57
+
58
+ const dropzoneClass = computed(() =>
59
+ twMerge(
60
+ fileInputDropzoneBaseClass,
61
+ fileInputDropzoneSizeClasses[props.size],
62
+ props.invalid ? fileInputDropzoneStateClasses.invalid : fileInputDropzoneStateClasses.default,
63
+ isDragOver.value ? fileInputDropzoneStateClasses.drag : "",
64
+ props.disabled ? fileInputDropzoneStateClasses.disabled : "",
65
+ ),
66
+ );
67
+
68
+ function emitFiles(fileList: FileList | File[]) {
69
+ const files = Array.from(fileList);
70
+
71
+ if (!files.length) {
72
+ emit("update:modelValue", null);
73
+ emit("update:filename", "");
74
+ return;
75
+ }
76
+
77
+ if (props.multiple) {
78
+ emit("update:modelValue", files);
79
+ emit("update:filename", files.map((file) => file.name).join(", "));
80
+ return;
81
+ }
82
+
83
+ emit("update:modelValue", files[0] ?? null);
84
+ emit("update:filename", files[0]?.name ?? "");
85
+ }
86
+
87
+ function handleInput(event: Event) {
88
+ const target = event.target as HTMLInputElement;
89
+ emitFiles(target.files ?? []);
90
+ }
91
+
92
+ function handleDragOver(event: DragEvent) {
93
+ if (props.disabled) return;
94
+ event.preventDefault();
95
+ isDragOver.value = true;
96
+ }
97
+
98
+ function handleDragLeave() {
99
+ isDragOver.value = false;
100
+ }
101
+
102
+ function handleDrop(event: DragEvent) {
103
+ if (props.disabled) return;
104
+ event.preventDefault();
105
+ isDragOver.value = false;
106
+ emitFiles(event.dataTransfer?.files ?? []);
107
+ }
108
+ </script>
109
+
110
+ <template>
111
+ <div :class="rootClass" v-bind="rootAttrs">
112
+ <input
113
+ :id="inputId"
114
+ class="sr-only"
115
+ type="file"
116
+ :accept="props.accept"
117
+ :multiple="props.multiple"
118
+ :disabled="props.disabled"
119
+ @change="handleInput"
120
+ />
121
+
122
+ <label
123
+ v-if="props.variant === 'dropzone'"
124
+ :for="inputId"
125
+ :class="dropzoneClass"
126
+ @dragover="handleDragOver"
127
+ @dragleave="handleDragLeave"
128
+ @drop="handleDrop"
129
+ >
130
+ <span :class="fileInputIconClass" aria-hidden="true">
131
+ <svg viewBox="0 0 24 24" fill="none" class="size-5">
132
+ <path
133
+ d="M12 16.5V9.75m0 0 3 3m-3-3-3 3M6.75 19.5a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.233-2.33 3 3 0 0 1 3.758 3.848A3.752 3.752 0 0 1 18 19.5H6.75Z"
134
+ stroke="currentColor"
135
+ stroke-width="1.5"
136
+ stroke-linecap="round"
137
+ stroke-linejoin="round"
138
+ />
139
+ </svg>
140
+ </span>
141
+ <span :class="fileInputTextStrongClass">{{ props.dropzoneTitle }}</span>
142
+ <span :class="fileInputTextMutedClass">{{ selectedLabel }}</span>
143
+ </label>
144
+
145
+ <label v-else :for="inputId" :class="defaultButtonClass">
146
+ <span :class="fileInputIconClass" aria-hidden="true">
147
+ <svg viewBox="0 0 24 24" fill="none" class="size-5">
148
+ <path
149
+ d="M12 16.5V9.75m0 0 3 3m-3-3-3 3M6.75 19.5a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.233-2.33 3 3 0 0 1 3.758 3.848A3.752 3.752 0 0 1 18 19.5H6.75Z"
150
+ stroke="currentColor"
151
+ stroke-width="1.5"
152
+ stroke-linecap="round"
153
+ stroke-linejoin="round"
154
+ />
155
+ </svg>
156
+ </span>
157
+ <span class="min-w-0">
158
+ <span :class="fileInputTextStrongClass">Upload file</span>
159
+ <span class="block truncate" :class="fileInputTextMutedClass">{{ selectedLabel }}</span>
160
+ </span>
161
+ </label>
162
+ </div>
163
+ </template>