@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,175 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import Card from "../../primitives/Card/Card.vue";
4
+ import type { FeatureCardSize, FeatureCardSurface, FeatureCardTone } from "./FeatureCard.types.js";
5
+
6
+ const props = withDefaults(
7
+ defineProps<{
8
+ description?: string;
9
+ size?: FeatureCardSize;
10
+ surface?: FeatureCardSurface;
11
+ title: string;
12
+ tone?: FeatureCardTone;
13
+ }>(),
14
+ {
15
+ description: undefined,
16
+ size: "md",
17
+ surface: "elevated",
18
+ tone: "primary",
19
+ },
20
+ );
21
+
22
+ const rootClass = computed(() => [
23
+ "ui-feature-card",
24
+ `ui-feature-card--${props.size}`,
25
+ `ui-feature-card--${props.surface}`,
26
+ ]);
27
+ const iconClass = computed(() => ["ui-feature-card__icon", `ui-feature-card__icon--${props.tone}`]);
28
+ const cardVariant = computed(() => {
29
+ if (props.surface === "panel") {
30
+ return "panel";
31
+ }
32
+
33
+ if (props.surface === "subtle") {
34
+ return "subtle";
35
+ }
36
+
37
+ return "elevated";
38
+ });
39
+ </script>
40
+
41
+ <template>
42
+ <Card :padding="props.size === 'sm' ? 'sm' : 'md'" :variant="cardVariant" :class="rootClass">
43
+ <div v-if="$slots.icon" :class="iconClass" aria-hidden="true">
44
+ <slot name="icon" />
45
+ </div>
46
+ <div class="ui-feature-card__body">
47
+ <h3 class="ui-feature-card__title">{{ props.title }}</h3>
48
+ <p v-if="props.description" class="ui-feature-card__description">
49
+ {{ props.description }}
50
+ </p>
51
+ <div v-if="$slots.default" class="ui-feature-card__content">
52
+ <slot />
53
+ </div>
54
+ </div>
55
+ </Card>
56
+ </template>
57
+
58
+ <style scoped>
59
+ .ui-feature-card {
60
+ position: relative;
61
+ display: flex;
62
+ height: 100%;
63
+ flex-direction: column;
64
+ gap: 1.25rem;
65
+ overflow: hidden;
66
+ }
67
+
68
+ .ui-feature-card::after {
69
+ position: absolute;
70
+ inset: auto 0 0 0;
71
+ height: 1px;
72
+ content: "";
73
+ background: linear-gradient(
74
+ 90deg,
75
+ transparent,
76
+ color-mix(in srgb, var(--ui-primary-muted) 64%, transparent),
77
+ transparent
78
+ );
79
+ }
80
+
81
+ .ui-feature-card--panel::after {
82
+ background: linear-gradient(
83
+ 90deg,
84
+ transparent,
85
+ color-mix(in srgb, var(--ui-accent-muted) 54%, transparent),
86
+ transparent
87
+ );
88
+ }
89
+
90
+ .ui-feature-card--subtle::after {
91
+ background: linear-gradient(
92
+ 90deg,
93
+ transparent,
94
+ color-mix(in srgb, var(--ui-border) 92%, transparent),
95
+ transparent
96
+ );
97
+ }
98
+
99
+ .ui-feature-card--sm {
100
+ gap: 1rem;
101
+ }
102
+
103
+ .ui-feature-card__icon {
104
+ display: inline-flex;
105
+ width: 2.75rem;
106
+ height: 2.75rem;
107
+ align-items: center;
108
+ justify-content: center;
109
+ border: 1px solid color-mix(in srgb, currentColor 24%, transparent);
110
+ border-radius: var(--ui-radius-md);
111
+ background: color-mix(in srgb, currentColor 10%, transparent);
112
+ }
113
+
114
+ .ui-feature-card__icon--primary {
115
+ color: var(--ui-primary);
116
+ }
117
+
118
+ .ui-feature-card__icon--secondary {
119
+ color: var(--ui-secondary);
120
+ }
121
+
122
+ .ui-feature-card__icon--accent {
123
+ color: var(--ui-accent);
124
+ }
125
+
126
+ .ui-feature-card__icon--success {
127
+ color: var(--ui-success);
128
+ }
129
+
130
+ .ui-feature-card__icon--info {
131
+ color: var(--ui-info);
132
+ }
133
+
134
+ .ui-feature-card__body {
135
+ display: flex;
136
+ flex: 1;
137
+ flex-direction: column;
138
+ gap: 0.75rem;
139
+ }
140
+
141
+ .ui-feature-card--subtle .ui-feature-card__body {
142
+ gap: 0.625rem;
143
+ }
144
+
145
+ .ui-feature-card__title {
146
+ margin: 0;
147
+ color: var(--ui-fg);
148
+ font-size: 1.5rem;
149
+ font-weight: 500;
150
+ letter-spacing: -0.03em;
151
+ line-height: 1.15;
152
+ }
153
+
154
+ .ui-feature-card--sm .ui-feature-card__title {
155
+ font-size: 1.1rem;
156
+ }
157
+
158
+ .ui-feature-card__description,
159
+ .ui-feature-card__content {
160
+ margin: 0;
161
+ color: var(--ui-fg-muted);
162
+ font-size: 1rem;
163
+ line-height: 1.65;
164
+ }
165
+
166
+ .ui-feature-card--subtle .ui-feature-card__description,
167
+ .ui-feature-card--subtle .ui-feature-card__content {
168
+ color: color-mix(in srgb, var(--ui-fg-muted) 88%, var(--ui-fg) 12%);
169
+ }
170
+
171
+ .ui-feature-card--sm .ui-feature-card__description,
172
+ .ui-feature-card--sm .ui-feature-card__content {
173
+ font-size: 0.95rem;
174
+ }
175
+ </style>
@@ -0,0 +1,65 @@
1
+ # FormField
2
+
3
+ ## Purpose
4
+
5
+ Composable field pattern that binds label, control, description, and message content without turning `Input` or `Textarea` into one-off wrappers.
6
+
7
+ ## Category
8
+
9
+ Pattern
10
+
11
+ ## Public API
12
+
13
+ Props:
14
+
15
+ - `id`: explicit base id for the field
16
+ - `label`: string
17
+ - `description`: string
18
+ - `message`: string
19
+ - `invalid`: boolean
20
+ - `disabled`: boolean
21
+ - `required`: boolean
22
+ - `size`: `sm | md | lg`
23
+
24
+ Default slot props:
25
+
26
+ - `id`
27
+ - `describedBy`
28
+ - `invalid`
29
+ - `disabled`
30
+ - `required`
31
+
32
+ Named slots:
33
+
34
+ - `label`
35
+ - `description`
36
+ - `message`
37
+
38
+ ## Behavior
39
+
40
+ - generates a stable fallback id when one is not provided
41
+ - composes `Label` and `FieldMessage` primitives
42
+ - exposes `describedBy` so the control can wire `aria-describedby`
43
+ - uses `critical` tone for the message when `invalid` is true
44
+
45
+ ## Example
46
+
47
+ ```vue
48
+ <FormField
49
+ id="email"
50
+ label="Email"
51
+ description="We will never share your email."
52
+ :message="emailError"
53
+ :invalid="Boolean(emailError)"
54
+ >
55
+ <template #default="{ id, describedBy, invalid }">
56
+ <Input
57
+ :id="id"
58
+ v-model="email"
59
+ type="email"
60
+ :invalid="invalid"
61
+ :aria-describedby="describedBy"
62
+ />
63
+ </template>
64
+ </FormField>
65
+ ```
@@ -0,0 +1,11 @@
1
+ export const formFieldSizeValues = ["sm", "md", "lg"] as const;
2
+
3
+ export type FormFieldSize = (typeof formFieldSizeValues)[number];
4
+
5
+ export type FormFieldSlotProps = {
6
+ describedBy?: string;
7
+ disabled: boolean;
8
+ id: string;
9
+ invalid: boolean;
10
+ required: boolean;
11
+ };
@@ -0,0 +1,87 @@
1
+ <script setup lang="ts">
2
+ import { computed, getCurrentInstance, useSlots } from "vue";
3
+ import FieldMessage from "../../primitives/FieldMessage/FieldMessage.vue";
4
+ import Label from "../../primitives/Label/Label.vue";
5
+ import type { FormFieldSlotProps } from "./FormField.types.js";
6
+
7
+ const props = withDefaults(
8
+ defineProps<{
9
+ description?: string;
10
+ disabled?: boolean;
11
+ id?: string;
12
+ invalid?: boolean;
13
+ label?: string;
14
+ message?: string;
15
+ required?: boolean;
16
+ size?: "sm" | "md" | "lg";
17
+ }>(),
18
+ {
19
+ description: undefined,
20
+ disabled: false,
21
+ id: undefined,
22
+ invalid: false,
23
+ label: undefined,
24
+ message: undefined,
25
+ required: false,
26
+ size: "md",
27
+ },
28
+ );
29
+
30
+ const slots = useSlots();
31
+ const instance = getCurrentInstance();
32
+
33
+ const fieldId = computed(() => props.id ?? `ui-field-${instance?.uid ?? "x"}`);
34
+
35
+ const hasDescription = computed(() => Boolean(props.description || slots.description));
36
+ const hasMessage = computed(() => Boolean(props.message || slots.message));
37
+
38
+ const descriptionId = computed(() =>
39
+ hasDescription.value ? `${fieldId.value}-description` : undefined,
40
+ );
41
+ const messageId = computed(() => (hasMessage.value ? `${fieldId.value}-message` : undefined));
42
+ const describedBy = computed(
43
+ () => [descriptionId.value, messageId.value].filter(Boolean).join(" ") || undefined,
44
+ );
45
+
46
+ const slotProps = computed<FormFieldSlotProps>(() => ({
47
+ describedBy: describedBy.value,
48
+ disabled: props.disabled,
49
+ id: fieldId.value,
50
+ invalid: props.invalid,
51
+ required: props.required,
52
+ }));
53
+ </script>
54
+
55
+ <template>
56
+ <div class="flex w-full flex-col gap-2">
57
+ <Label
58
+ v-if="props.label || $slots.label"
59
+ :for="fieldId"
60
+ :size="props.size"
61
+ :required="props.required"
62
+ :disabled="props.disabled"
63
+ :invalid="props.invalid"
64
+ >
65
+ <slot name="label">{{ props.label }}</slot>
66
+ </Label>
67
+
68
+ <slot v-bind="slotProps" />
69
+
70
+ <FieldMessage
71
+ v-if="props.description || $slots.description"
72
+ :id="descriptionId"
73
+ :size="props.size"
74
+ >
75
+ <slot name="description">{{ props.description }}</slot>
76
+ </FieldMessage>
77
+
78
+ <FieldMessage
79
+ v-if="props.message || $slots.message"
80
+ :id="messageId"
81
+ :size="props.size"
82
+ :tone="props.invalid ? 'critical' : 'muted'"
83
+ >
84
+ <slot name="message">{{ props.message }}</slot>
85
+ </FieldMessage>
86
+ </div>
87
+ </template>
@@ -0,0 +1,61 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import type {
4
+ IdentityGlyphAlgorithm,
5
+ IdentityGlyphInput,
6
+ IdentityGlyphSize,
7
+ } from "./identityGlyph.types";
8
+ import {
9
+ createIdentityGlyphModel,
10
+ getIdentityGlyphPaletteValues,
11
+ resolveIdentityGlyphSize,
12
+ } from "./identityGlyph.utils";
13
+
14
+ const props = withDefaults(
15
+ defineProps<{
16
+ algorithm?: IdentityGlyphAlgorithm;
17
+ identity: IdentityGlyphInput;
18
+ size?: number | IdentityGlyphSize;
19
+ title?: string;
20
+ }>(),
21
+ {
22
+ algorithm: "glyph:v1",
23
+ size: "sm",
24
+ title: undefined,
25
+ },
26
+ );
27
+
28
+ const pixelSize = computed(() => resolveIdentityGlyphSize(props.size));
29
+ const model = computed(() => createIdentityGlyphModel(props.identity, props.algorithm));
30
+ const paletteValues = computed(() => getIdentityGlyphPaletteValues(model.value.palette));
31
+ const accessibleTitle = computed(
32
+ () => props.title ?? `Identity glyph ${model.value.shortIdentity}`,
33
+ );
34
+ </script>
35
+
36
+ <template>
37
+ <svg
38
+ :width="pixelSize"
39
+ :height="pixelSize"
40
+ :viewBox="`0 0 ${model.grid.length} ${model.grid.length}`"
41
+ xmlns="http://www.w3.org/2000/svg"
42
+ shape-rendering="crispEdges"
43
+ role="img"
44
+ :aria-label="accessibleTitle"
45
+ :data-glyph-algorithm="model.algorithm"
46
+ :data-glyph-fallback="String(model.fallback)"
47
+ >
48
+ <title>{{ accessibleTitle }}</title>
49
+ <template v-for="(row, y) in model.grid" :key="`glyph-row-${y}`">
50
+ <rect
51
+ v-for="(cell, x) in row"
52
+ :key="`glyph-cell-${x}-${y}`"
53
+ :x="x"
54
+ :y="y"
55
+ width="1"
56
+ height="1"
57
+ :fill="paletteValues[cell] ?? model.palette.background"
58
+ />
59
+ </template>
60
+ </svg>
61
+ </template>
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import IdentityGlyph from "./IdentityGlyph.vue";
4
+ import type { IdentityGlyphAlgorithm, IdentityGlyphInput } from "./identityGlyph.types";
5
+ import { resolveIdentityGlyphInput } from "./identityGlyph.utils";
6
+
7
+ const props = withDefaults(
8
+ defineProps<{
9
+ algorithm?: IdentityGlyphAlgorithm;
10
+ identity: IdentityGlyphInput;
11
+ identityText?: string;
12
+ label?: string;
13
+ size?: "sm" | "md";
14
+ }>(),
15
+ {
16
+ algorithm: "glyph:v1",
17
+ identityText: undefined,
18
+ label: undefined,
19
+ size: "sm",
20
+ },
21
+ );
22
+
23
+ const resolvedIdentity = computed(() => resolveIdentityGlyphInput(props.identity));
24
+ const glyphSize = computed(() => (props.size === "md" ? 40 : 32));
25
+ const displayLabel = computed(() => props.label ?? "Identity");
26
+ const displayIdentity = computed(() => props.identityText ?? resolvedIdentity.value.shortIdentity);
27
+ const labelClass = computed(() =>
28
+ props.size === "md"
29
+ ? "text-sm font-medium text-[var(--ui-fg)]"
30
+ : "text-sm font-medium text-[var(--ui-fg)]",
31
+ );
32
+ const metaClass = computed(() =>
33
+ props.size === "md" ? "text-xs text-[var(--ui-fg-muted)]" : "text-xs text-[var(--ui-fg-muted)]",
34
+ );
35
+ </script>
36
+
37
+ <template>
38
+ <div class="flex min-w-0 items-center gap-2" data-test="identity-handle">
39
+ <IdentityGlyph
40
+ :identity="props.identity"
41
+ :algorithm="props.algorithm"
42
+ :size="glyphSize"
43
+ :title="`Identity glyph ${displayIdentity}`"
44
+ class="shrink-0"
45
+ />
46
+ <div class="min-w-0">
47
+ <p class="m-0 truncate" :class="labelClass">
48
+ {{ displayLabel }}
49
+ </p>
50
+ <div class="mt-0.5 flex min-w-0 items-center gap-2">
51
+ <p class="m-0 truncate font-mono" :class="metaClass">
52
+ {{ displayIdentity }}
53
+ </p>
54
+ <slot name="status" />
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </template>
@@ -0,0 +1,36 @@
1
+ import type { SerializedIdentity } from "@ternent/identity";
2
+
3
+ export type IdentityGlyphAlgorithm = "glyph:v1";
4
+
5
+ export type IdentityGlyphInput =
6
+ | string
7
+ | SerializedIdentity
8
+ | { publicKey: string }
9
+ | { identityKey: string }
10
+ | {
11
+ identity: SerializedIdentity | { publicKey: string } | { identityKey: string };
12
+ };
13
+
14
+ export type IdentityGlyphSize = "xs" | "sm" | "md" | "lg";
15
+
16
+ export type IdentityGlyphPalette = {
17
+ background: string;
18
+ primary: string;
19
+ secondary: string;
20
+ accent: string;
21
+ };
22
+
23
+ export type IdentityGlyphModel = {
24
+ algorithm: IdentityGlyphAlgorithm;
25
+ canonicalIdentity: string;
26
+ shortIdentity: string;
27
+ fallback: boolean;
28
+ grid: number[][];
29
+ palette: IdentityGlyphPalette;
30
+ };
31
+
32
+ export type ResolvedIdentityGlyphInput = {
33
+ canonicalIdentity: string;
34
+ shortIdentity: string;
35
+ fallback: boolean;
36
+ };