@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,354 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import Badge from "../../primitives/Badge/Badge.vue";
4
+ import Card from "../../primitives/Card/Card.vue";
5
+ import type {
6
+ PreviewPanelBadgeMode,
7
+ PreviewPanelEmphasis,
8
+ PreviewPanelRow,
9
+ PreviewPanelTone,
10
+ } from "./PreviewPanel.types.js";
11
+
12
+ const props = withDefaults(
13
+ defineProps<{
14
+ activeTab?: string;
15
+ badgeMode?: PreviewPanelBadgeMode;
16
+ code?: string;
17
+ emphasis?: PreviewPanelEmphasis;
18
+ footerLabel?: string;
19
+ footerText?: string;
20
+ footerTone?: PreviewPanelTone;
21
+ meta?: string;
22
+ rows?: readonly PreviewPanelRow[];
23
+ statusLabel?: string;
24
+ statusTone?: PreviewPanelTone;
25
+ tabs?: readonly string[];
26
+ title?: string;
27
+ }>(),
28
+ {
29
+ activeTab: undefined,
30
+ badgeMode: "default",
31
+ code: undefined,
32
+ emphasis: "default",
33
+ footerLabel: undefined,
34
+ footerText: undefined,
35
+ footerTone: "neutral",
36
+ meta: undefined,
37
+ rows: undefined,
38
+ statusLabel: undefined,
39
+ statusTone: "neutral",
40
+ tabs: undefined,
41
+ title: undefined,
42
+ },
43
+ );
44
+
45
+ const hasFooter = computed(() => Boolean(props.footerLabel || props.footerText));
46
+ const toneClass = (tone?: PreviewPanelTone) =>
47
+ tone ? `ui-preview-panel__value--${tone}` : undefined;
48
+ const rootClass = computed(() => ["ui-preview-panel", `ui-preview-panel--${props.emphasis}`]);
49
+ const badgeVariant = computed(() => (props.badgeMode === "quiet" ? "outline" : "soft"));
50
+ const badgeTone = (tone?: PreviewPanelTone) => (tone === "info" ? "primary" : tone);
51
+ </script>
52
+
53
+ <template>
54
+ <Card :class="rootClass" variant="panel" padding="md">
55
+ <div v-if="props.tabs?.length" class="ui-preview-panel__tabs" aria-hidden="true">
56
+ <span
57
+ v-for="tab in props.tabs"
58
+ :key="tab"
59
+ class="ui-preview-panel__tab"
60
+ :data-active="tab === props.activeTab"
61
+ >
62
+ {{ tab }}
63
+ </span>
64
+ </div>
65
+
66
+ <div v-if="props.title || props.statusLabel || props.meta" class="ui-preview-panel__header">
67
+ <div class="ui-preview-panel__heading">
68
+ <h3 v-if="props.title" class="ui-preview-panel__title">{{ props.title }}</h3>
69
+ </div>
70
+ <Badge
71
+ v-if="props.statusLabel"
72
+ :tone="badgeTone(props.statusTone)"
73
+ :variant="badgeVariant"
74
+ size="sm"
75
+ >
76
+ {{ props.statusLabel }}
77
+ </Badge>
78
+ <span v-else-if="props.meta" class="ui-preview-panel__meta">{{ props.meta }}</span>
79
+ </div>
80
+
81
+ <div class="ui-preview-panel__body">
82
+ <dl v-if="props.rows?.length" class="ui-preview-panel__rows">
83
+ <div v-for="row in props.rows" :key="row.label" class="ui-preview-panel__row">
84
+ <dt class="ui-preview-panel__label">{{ row.label }}</dt>
85
+ <dd class="ui-preview-panel__value" :class="toneClass(row.valueTone)">
86
+ {{ row.value }}
87
+ </dd>
88
+ </div>
89
+ </dl>
90
+
91
+ <pre v-else-if="props.code" class="ui-preview-panel__code"><code>{{ props.code }}</code></pre>
92
+
93
+ <div v-else class="ui-preview-panel__slot">
94
+ <slot />
95
+ </div>
96
+ </div>
97
+
98
+ <div v-if="hasFooter" class="ui-preview-panel__footer">
99
+ <Badge
100
+ v-if="props.footerLabel"
101
+ :tone="badgeTone(props.footerTone)"
102
+ :variant="badgeVariant"
103
+ size="sm"
104
+ >
105
+ {{ props.footerLabel }}
106
+ </Badge>
107
+ <p v-if="props.footerText" class="ui-preview-panel__footer-text">
108
+ {{ props.footerText }}
109
+ </p>
110
+ </div>
111
+ </Card>
112
+ </template>
113
+
114
+ <style scoped>
115
+ .ui-preview-panel {
116
+ position: relative;
117
+ width: 100%;
118
+ max-width: 100%;
119
+ overflow: hidden;
120
+ }
121
+
122
+ .ui-preview-panel::before {
123
+ position: absolute;
124
+ inset: 0;
125
+ content: "";
126
+ background:
127
+ linear-gradient(
128
+ 180deg,
129
+ color-mix(in srgb, var(--ui-tonal-tertiary) 78%, transparent),
130
+ transparent 28%
131
+ ),
132
+ radial-gradient(
133
+ circle at top right,
134
+ color-mix(in srgb, var(--ui-primary-muted) 38%, transparent),
135
+ transparent 38%
136
+ );
137
+ opacity: 0.42;
138
+ pointer-events: none;
139
+ }
140
+
141
+ .ui-preview-panel--subtle::before {
142
+ opacity: 0.22;
143
+ }
144
+
145
+ .ui-preview-panel--strong::before {
146
+ opacity: 0.34;
147
+ }
148
+
149
+ .ui-preview-panel::after {
150
+ position: absolute;
151
+ inset: 0;
152
+ content: "";
153
+ border-radius: inherit;
154
+ background-image:
155
+ linear-gradient(color-mix(in srgb, var(--ui-border) 72%, transparent) 1px, transparent 1px),
156
+ linear-gradient(
157
+ 90deg,
158
+ color-mix(in srgb, var(--ui-border) 72%, transparent) 1px,
159
+ transparent 1px
160
+ );
161
+ background-position: center;
162
+ background-size: 2.25rem 2.25rem;
163
+ mask-image: radial-gradient(circle at center, black, transparent 78%);
164
+ opacity: 0.12;
165
+ pointer-events: none;
166
+ }
167
+
168
+ .ui-preview-panel--subtle::after {
169
+ opacity: 0.12;
170
+ }
171
+
172
+ .ui-preview-panel--strong::after {
173
+ opacity: 0.18;
174
+ }
175
+
176
+ .ui-preview-panel--strong {
177
+ box-shadow:
178
+ inset 0 0 0 1px color-mix(in srgb, var(--ui-border) 84%, transparent),
179
+ 0 14px 30px color-mix(in srgb, var(--ui-bg) 55%, transparent);
180
+ }
181
+
182
+ .ui-preview-panel > * {
183
+ position: relative;
184
+ z-index: 1;
185
+ }
186
+
187
+ .ui-preview-panel__tabs {
188
+ display: inline-flex;
189
+ align-items: center;
190
+ gap: 0.375rem;
191
+ margin-bottom: 1rem;
192
+ padding: 0.25rem;
193
+ border: 1px solid var(--ui-border);
194
+ border-radius: calc(var(--ui-radius-md) + 4px);
195
+ background: color-mix(in srgb, var(--ui-surface) 72%, transparent);
196
+ }
197
+
198
+ .ui-preview-panel--strong .ui-preview-panel__tabs {
199
+ background: color-mix(in srgb, var(--ui-surface) 86%, transparent);
200
+ }
201
+
202
+ .ui-preview-panel__tab {
203
+ padding: 0.375rem 0.75rem;
204
+ border-radius: calc(var(--ui-radius-sm) + 2px);
205
+ color: var(--ui-fg-muted);
206
+ font-size: 0.875rem;
207
+ font-weight: 500;
208
+ }
209
+
210
+ .ui-preview-panel__tab[data-active="true"] {
211
+ background: var(--ui-surface);
212
+ color: var(--ui-fg);
213
+ box-shadow: var(--ui-shadow-sm);
214
+ }
215
+
216
+ .ui-preview-panel--strong .ui-preview-panel__tab[data-active="true"] {
217
+ box-shadow:
218
+ inset 0 0 0 1px color-mix(in srgb, var(--ui-border) 86%, transparent),
219
+ var(--ui-shadow-sm);
220
+ }
221
+
222
+ .ui-preview-panel__header {
223
+ display: flex;
224
+ align-items: center;
225
+ justify-content: space-between;
226
+ gap: 1rem;
227
+ margin-bottom: 1rem;
228
+ }
229
+
230
+ .ui-preview-panel__title {
231
+ margin: 0;
232
+ color: var(--ui-fg);
233
+ font-size: 1.125rem;
234
+ font-weight: 500;
235
+ letter-spacing: -0.02em;
236
+ }
237
+
238
+ .ui-preview-panel--strong .ui-preview-panel__title {
239
+ font-size: 1.2rem;
240
+ }
241
+
242
+ .ui-preview-panel__meta {
243
+ color: var(--ui-fg-muted);
244
+ font-size: 0.8rem;
245
+ letter-spacing: 0.08em;
246
+ text-transform: uppercase;
247
+ }
248
+
249
+ .ui-preview-panel__body {
250
+ display: flex;
251
+ flex-direction: column;
252
+ gap: 1rem;
253
+ min-width: 0;
254
+ }
255
+
256
+ .ui-preview-panel__rows {
257
+ display: flex;
258
+ flex-direction: column;
259
+ gap: 0.875rem;
260
+ margin: 0;
261
+ }
262
+
263
+ .ui-preview-panel__row {
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: space-between;
267
+ gap: 1rem;
268
+ padding-bottom: 0.75rem;
269
+ border-bottom: 1px solid color-mix(in srgb, var(--ui-border) 72%, transparent);
270
+ }
271
+
272
+ .ui-preview-panel--strong .ui-preview-panel__row {
273
+ border-bottom-color: color-mix(in srgb, var(--ui-border) 88%, transparent);
274
+ }
275
+
276
+ .ui-preview-panel__row:last-child {
277
+ padding-bottom: 0;
278
+ border-bottom: 0;
279
+ }
280
+
281
+ .ui-preview-panel__label {
282
+ color: var(--ui-fg-muted);
283
+ font-size: 0.875rem;
284
+ }
285
+
286
+ .ui-preview-panel__value {
287
+ margin: 0;
288
+ color: var(--ui-fg);
289
+ font-size: 0.95rem;
290
+ font-weight: 500;
291
+ text-align: right;
292
+ }
293
+
294
+ .ui-preview-panel__value--primary,
295
+ .ui-preview-panel__value--info {
296
+ color: var(--ui-primary);
297
+ }
298
+
299
+ .ui-preview-panel__value--secondary {
300
+ color: var(--ui-secondary);
301
+ }
302
+
303
+ .ui-preview-panel__value--accent,
304
+ .ui-preview-panel__value--warning {
305
+ color: var(--ui-accent);
306
+ }
307
+
308
+ .ui-preview-panel__value--success {
309
+ color: var(--ui-success);
310
+ }
311
+
312
+ .ui-preview-panel__value--critical {
313
+ color: var(--ui-critical);
314
+ }
315
+
316
+ .ui-preview-panel__code {
317
+ margin: 0;
318
+ min-width: 0;
319
+ max-width: 100%;
320
+ padding: 1rem 1.125rem;
321
+ overflow-x: auto;
322
+ border: 1px solid color-mix(in srgb, var(--ui-border) 72%, transparent);
323
+ border-radius: var(--ui-radius-md);
324
+ background: color-mix(in srgb, var(--ui-bg) 55%, var(--ui-surface));
325
+ color: var(--ui-fg);
326
+ font-size: 0.92rem;
327
+ line-height: 1.8;
328
+ }
329
+
330
+ .ui-preview-panel--subtle .ui-preview-panel__code {
331
+ background: color-mix(in srgb, var(--ui-surface) 88%, var(--ui-bg));
332
+ }
333
+
334
+ .ui-preview-panel__slot {
335
+ display: flex;
336
+ flex-direction: column;
337
+ gap: 1rem;
338
+ min-width: 0;
339
+ }
340
+
341
+ .ui-preview-panel__footer {
342
+ display: flex;
343
+ flex-wrap: wrap;
344
+ align-items: center;
345
+ gap: 0.75rem;
346
+ margin-top: 1.25rem;
347
+ }
348
+
349
+ .ui-preview-panel__footer-text {
350
+ margin: 0;
351
+ color: var(--ui-fg-muted);
352
+ font-size: 0.95rem;
353
+ }
354
+ </style>
@@ -0,0 +1,35 @@
1
+ # RecordList
2
+
3
+ ## Purpose
4
+
5
+ Reusable selectable list composition for entity navigation and lightweight grouped records.
6
+
7
+ ## Category
8
+
9
+ Pattern
10
+
11
+ ## Public API
12
+
13
+ Props:
14
+
15
+ - `items`: `RecordListItem[]`
16
+ - `title`: optional section title
17
+ - `emptyLabel`: empty-state copy (`No records yet.` default)
18
+ - `defaultActionLabel`: optional fallback row action label
19
+ - `surface`: `card | plain` (`card` default)
20
+
21
+ Slots:
22
+
23
+ - `item-action` scoped slot (`item`)
24
+
25
+ Events:
26
+
27
+ - `select(item, event)` when an item row is selected
28
+ - `action(item, event)` default action button event
29
+
30
+ ## Behavior
31
+
32
+ - composes `Card`, `Button`, and `Separator` primitives
33
+ - highlights active item with secondary button treatment
34
+ - supports per-item disabled behavior
35
+ - renders explicit empty state when no items are available
@@ -0,0 +1,42 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { describe, expect, it } from "vitest";
4
+ import type { RecordListItem } from "./RecordList.types";
5
+ import { resolveRecordListSecondaryText } from "./RecordList.utils";
6
+
7
+ describe("RecordList", () => {
8
+ it("resolves row secondary text from meta then description", () => {
9
+ const withMeta: RecordListItem = {
10
+ id: "one",
11
+ title: "One",
12
+ meta: "1 member",
13
+ description: "fallback",
14
+ };
15
+
16
+ const withDescription: RecordListItem = {
17
+ id: "two",
18
+ title: "Two",
19
+ description: "Description only",
20
+ };
21
+
22
+ const withNone: RecordListItem = {
23
+ id: "three",
24
+ title: "Three",
25
+ };
26
+
27
+ expect(resolveRecordListSecondaryText(withMeta)).toBe("1 member");
28
+ expect(resolveRecordListSecondaryText(withDescription)).toBe("Description only");
29
+ expect(resolveRecordListSecondaryText(withNone)).toBeNull();
30
+ });
31
+
32
+ it("declares item-action slot and empty-state affordance", () => {
33
+ const source = readFileSync(
34
+ resolve(process.cwd(), "src/patterns/RecordList/RecordList.vue"),
35
+ "utf8",
36
+ );
37
+
38
+ expect(source).toContain('<slot name="item-leading" :item="item" />');
39
+ expect(source).toContain('<slot name="item-action" :item="item">');
40
+ expect(source).toContain('data-test="record-list-empty"');
41
+ });
42
+ });
@@ -0,0 +1,9 @@
1
+ export type RecordListItem = {
2
+ active?: boolean;
3
+ dataTest?: string;
4
+ description?: string;
5
+ disabled?: boolean;
6
+ id: string;
7
+ meta?: string;
8
+ title: string;
9
+ };
@@ -0,0 +1,5 @@
1
+ import type { RecordListItem } from "./RecordList.types";
2
+
3
+ export function resolveRecordListSecondaryText(item: RecordListItem): string | null {
4
+ return item.meta ?? item.description ?? null;
5
+ }
@@ -0,0 +1,134 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import Button from "../../primitives/Button/Button.vue";
4
+ import Card from "../../primitives/Card/Card.vue";
5
+ import Separator from "../../primitives/Separator/Separator.vue";
6
+ import type { RecordListItem } from "./RecordList.types";
7
+ import { resolveRecordListSecondaryText } from "./RecordList.utils";
8
+
9
+ const emit = defineEmits<{
10
+ action: [item: RecordListItem, event: MouseEvent];
11
+ select: [item: RecordListItem, event: MouseEvent];
12
+ }>();
13
+
14
+ const props = withDefaults(
15
+ defineProps<{
16
+ defaultActionLabel?: string;
17
+ emptyLabel?: string;
18
+ items: RecordListItem[];
19
+ surface?: "card" | "plain";
20
+ title?: string;
21
+ }>(),
22
+ {
23
+ defaultActionLabel: undefined,
24
+ emptyLabel: "No records yet.",
25
+ surface: "card",
26
+ title: undefined,
27
+ },
28
+ );
29
+
30
+ const normalizedItems = computed(() => props.items);
31
+
32
+ function handleSelect(item: RecordListItem, event: MouseEvent): void {
33
+ if (item.disabled) {
34
+ event.preventDefault();
35
+ event.stopPropagation();
36
+ return;
37
+ }
38
+
39
+ emit("select", item, event);
40
+ }
41
+
42
+ function handleAction(item: RecordListItem, event: MouseEvent): void {
43
+ if (item.disabled) {
44
+ event.preventDefault();
45
+ event.stopPropagation();
46
+ return;
47
+ }
48
+
49
+ emit("action", item, event);
50
+ }
51
+
52
+ const wrapperClass = computed(() =>
53
+ props.surface === "card"
54
+ ? "flex h-full min-h-0 flex-col gap-2"
55
+ : "flex h-full min-h-0 flex-col gap-2 px-1",
56
+ );
57
+ </script>
58
+
59
+ <template>
60
+ <component
61
+ :is="props.surface === 'card' ? Card : 'div'"
62
+ :variant="props.surface === 'card' ? 'outline' : undefined"
63
+ :padding="props.surface === 'card' ? 'sm' : undefined"
64
+ :class="wrapperClass"
65
+ >
66
+ <p
67
+ v-if="props.title"
68
+ class="m-0 px-1 text-xs uppercase tracking-[0.12em] text-[var(--ui-fg-muted)]"
69
+ >
70
+ {{ props.title }}
71
+ </p>
72
+
73
+ <div
74
+ v-if="normalizedItems.length === 0"
75
+ class="px-2 py-3 text-sm text-[var(--ui-fg-muted)]"
76
+ data-test="record-list-empty"
77
+ >
78
+ {{ props.emptyLabel }}
79
+ </div>
80
+
81
+ <ul
82
+ v-else
83
+ class="m-0 flex min-h-0 list-none flex-col gap-1 overflow-auto p-0"
84
+ data-test="record-list-items"
85
+ >
86
+ <li v-for="(item, index) in normalizedItems" :key="item.id" :data-test="item.dataTest">
87
+ <div class="flex items-center gap-2">
88
+ <Button
89
+ type="button"
90
+ size="sm"
91
+ :variant="item.active ? 'secondary' : 'plain-secondary'"
92
+ class="min-w-0 flex-1 justify-start"
93
+ :disabled="Boolean(item.disabled)"
94
+ :aria-current="item.active ? 'true' : undefined"
95
+ @click="handleSelect(item, $event)"
96
+ >
97
+ <span class="flex min-w-0 items-center gap-2 text-left">
98
+ <slot name="item-leading" :item="item" />
99
+ <span class="min-w-0">
100
+ <span class="block truncate text-sm">{{ item.title }}</span>
101
+ <span
102
+ v-if="resolveRecordListSecondaryText(item)"
103
+ class="block truncate text-xs text-[var(--ui-fg-muted)]"
104
+ >
105
+ {{ resolveRecordListSecondaryText(item) }}
106
+ </span>
107
+ </span>
108
+ </span>
109
+ </Button>
110
+
111
+ <slot name="item-action" :item="item">
112
+ <Button
113
+ v-if="props.defaultActionLabel"
114
+ type="button"
115
+ variant="plain-secondary"
116
+ size="xs"
117
+ :disabled="Boolean(item.disabled)"
118
+ aria-label="Row action"
119
+ @click="handleAction(item, $event)"
120
+ >
121
+ {{ props.defaultActionLabel }}
122
+ </Button>
123
+ </slot>
124
+ </div>
125
+
126
+ <Separator
127
+ v-if="index < normalizedItems.length - 1"
128
+ orientation="horizontal"
129
+ class="my-2"
130
+ />
131
+ </li>
132
+ </ul>
133
+ </component>
134
+ </template>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ withDefaults(
3
+ defineProps<{
4
+ eyebrow?: string;
5
+ title: string;
6
+ titleTag?: "h2" | "h3";
7
+ }>(),
8
+ {
9
+ eyebrow: undefined,
10
+ titleTag: "h2",
11
+ },
12
+ );
13
+ </script>
14
+
15
+ <template>
16
+ <section class="ui-section-clarifier">
17
+ <div class="ui-section-clarifier__header">
18
+ <p v-if="eyebrow" class="ui-section-clarifier__eyebrow">
19
+ {{ eyebrow }}
20
+ </p>
21
+ <component :is="titleTag" class="ui-section-clarifier__title">
22
+ {{ title }}
23
+ </component>
24
+ </div>
25
+
26
+ <div class="ui-section-clarifier__frame">
27
+ <div class="ui-section-clarifier__content">
28
+ <slot />
29
+ </div>
30
+ </div>
31
+ </section>
32
+ </template>
33
+
34
+ <style scoped>
35
+ .ui-section-clarifier {
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 1.25rem;
39
+ width: 100%;
40
+ margin-inline: auto;
41
+ }
42
+
43
+ .ui-section-clarifier__header {
44
+ display: flex;
45
+ flex-direction: column;
46
+ gap: 0.375rem;
47
+ }
48
+
49
+ .ui-section-clarifier__eyebrow {
50
+ margin: 0;
51
+ color: var(--ui-fg-muted);
52
+ font-size: 0.75rem;
53
+ font-weight: 600;
54
+ letter-spacing: 0.24em;
55
+ text-transform: uppercase;
56
+ }
57
+
58
+ .ui-section-clarifier__title {
59
+ margin: 0;
60
+ max-width: 30rem;
61
+ color: var(--ui-fg);
62
+ font-size: clamp(1.25rem, 1.8vw, 1.5rem);
63
+ font-weight: 500;
64
+ letter-spacing: -0.025em;
65
+ line-height: 1.16;
66
+ text-wrap: balance;
67
+ }
68
+
69
+ .ui-section-clarifier__frame {
70
+ border-top: 1px solid color-mix(in srgb, var(--ui-border) 82%, transparent);
71
+ border-bottom: 1px solid color-mix(in srgb, var(--ui-border) 82%, transparent);
72
+ background-color: color-mix(in srgb, var(--ui-bg) 84%, var(--ui-tonal-secondary) 16%);
73
+ }
74
+
75
+ .ui-section-clarifier__content {
76
+ min-width: 0;
77
+ padding: 1.5rem;
78
+ }
79
+
80
+ @media (min-width: 768px) {
81
+ .ui-section-clarifier__content {
82
+ padding: 1.75rem 2rem;
83
+ }
84
+ }
85
+ </style>
@@ -0,0 +1,25 @@
1
+ # SectionIntro
2
+
3
+ ## Purpose
4
+
5
+ Shared heading block for hero, section, and supporting narrative copy.
6
+
7
+ ## Category
8
+
9
+ Pattern
10
+
11
+ ## Public API
12
+
13
+ Props:
14
+
15
+ - `eyebrow`
16
+ - `title`
17
+ - `description`
18
+ - `align`: `start | center`
19
+ - `size`: `hero | section | compact`
20
+ - `titleTag`: `h1 | h2 | h3`
21
+
22
+ Slots:
23
+
24
+ - default: additional content below the description
25
+ - `actions`: action row for buttons or supporting controls
@@ -0,0 +1,7 @@
1
+ export const sectionIntroAlignValues = ["start", "center"] as const;
2
+ export const sectionIntroSizeValues = ["hero", "section", "compact"] as const;
3
+ export const sectionIntroTitleTagValues = ["h1", "h2", "h3"] as const;
4
+
5
+ export type SectionIntroAlign = (typeof sectionIntroAlignValues)[number];
6
+ export type SectionIntroSize = (typeof sectionIntroSizeValues)[number];
7
+ export type SectionIntroTitleTag = (typeof sectionIntroTitleTagValues)[number];