@milesroxas/design-hub 0.0.0-stage → 0.1.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 (217) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -2
  3. package/client.d.ts +6 -0
  4. package/configs/biome/biome.json +64 -0
  5. package/configs/tsconfig.project.json +17 -0
  6. package/core/bytes.test.ts +14 -0
  7. package/core/bytes.ts +14 -0
  8. package/core/catalog.test.ts +44 -0
  9. package/core/catalog.ts +43 -0
  10. package/core/checks.test.ts +23 -0
  11. package/core/checks.ts +72 -0
  12. package/core/contacts.test.ts +31 -0
  13. package/core/contacts.ts +38 -0
  14. package/core/doc.ts +4 -0
  15. package/core/feature.ts +6 -0
  16. package/core/fixtures.test.ts +33 -0
  17. package/core/fixtures.ts +69 -0
  18. package/core/frontmatter.ts +15 -0
  19. package/core/html.ts +3 -0
  20. package/core/image.test.ts +22 -0
  21. package/core/image.ts +37 -0
  22. package/core/jev.test.ts +66 -0
  23. package/core/jev.ts +77 -0
  24. package/core/review/model.ts +189 -0
  25. package/core/review/policy.ts +26 -0
  26. package/core/review/service.test.ts +163 -0
  27. package/core/review/service.ts +309 -0
  28. package/core/review/store.ts +51 -0
  29. package/core/review/triage.test.ts +41 -0
  30. package/core/review/triage.ts +58 -0
  31. package/core/states.test.ts +36 -0
  32. package/core/states.ts +34 -0
  33. package/dist/core/bytes.d.ts +5 -0
  34. package/dist/core/bytes.js +9 -0
  35. package/dist/core/catalog.d.ts +17 -0
  36. package/dist/core/catalog.js +24 -0
  37. package/dist/core/checks.d.ts +41 -0
  38. package/dist/core/checks.js +53 -0
  39. package/dist/core/contacts.d.ts +9 -0
  40. package/dist/core/contacts.js +34 -0
  41. package/dist/core/doc.d.ts +11 -0
  42. package/dist/core/doc.js +1 -0
  43. package/dist/core/feature.d.ts +3 -0
  44. package/dist/core/feature.js +4 -0
  45. package/dist/core/fixtures.d.ts +19 -0
  46. package/dist/core/fixtures.js +52 -0
  47. package/dist/core/frontmatter.d.ts +4 -0
  48. package/dist/core/frontmatter.js +15 -0
  49. package/dist/core/html.d.ts +2 -0
  50. package/dist/core/html.js +2 -0
  51. package/dist/core/image.d.ts +6 -0
  52. package/dist/core/image.js +34 -0
  53. package/dist/core/jev.d.ts +54 -0
  54. package/dist/core/jev.js +52 -0
  55. package/dist/core/review/model.d.ts +85 -0
  56. package/dist/core/review/model.js +112 -0
  57. package/dist/core/review/policy.d.ts +3 -0
  58. package/dist/core/review/policy.js +19 -0
  59. package/dist/core/review/service.d.ts +79 -0
  60. package/dist/core/review/service.js +245 -0
  61. package/dist/core/review/store.d.ts +20 -0
  62. package/dist/core/review/store.js +37 -0
  63. package/dist/core/review/triage.d.ts +6 -0
  64. package/dist/core/review/triage.js +45 -0
  65. package/dist/core/states.d.ts +6 -0
  66. package/dist/core/states.js +29 -0
  67. package/dist/scripts/bootstrap.d.ts +51 -0
  68. package/dist/scripts/bootstrap.js +278 -0
  69. package/dist/scripts/calibrate.d.ts +127 -0
  70. package/dist/scripts/calibrate.js +164 -0
  71. package/dist/scripts/check.d.ts +25 -0
  72. package/dist/scripts/check.js +30 -0
  73. package/dist/scripts/cli.d.ts +2 -0
  74. package/dist/scripts/cli.js +73 -0
  75. package/dist/scripts/commands.d.ts +25 -0
  76. package/dist/scripts/commands.js +49 -0
  77. package/dist/scripts/comments.d.ts +63 -0
  78. package/dist/scripts/comments.js +152 -0
  79. package/dist/scripts/dev.d.ts +46 -0
  80. package/dist/scripts/dev.js +84 -0
  81. package/dist/scripts/elyx.d.ts +61 -0
  82. package/dist/scripts/elyx.js +195 -0
  83. package/dist/scripts/fixtures-pull.d.ts +60 -0
  84. package/dist/scripts/fixtures-pull.js +121 -0
  85. package/dist/scripts/guard.d.ts +58 -0
  86. package/dist/scripts/guard.js +201 -0
  87. package/dist/scripts/hook.d.ts +18 -0
  88. package/dist/scripts/hook.js +46 -0
  89. package/dist/scripts/lib/bin.d.ts +4 -0
  90. package/dist/scripts/lib/bin.js +20 -0
  91. package/dist/scripts/lib/catalog.d.ts +7 -0
  92. package/dist/scripts/lib/catalog.js +18 -0
  93. package/dist/scripts/lib/cli.d.ts +75 -0
  94. package/dist/scripts/lib/cli.js +88 -0
  95. package/dist/scripts/lib/css-tokens.d.ts +13 -0
  96. package/dist/scripts/lib/css-tokens.js +67 -0
  97. package/dist/scripts/lib/judge.d.ts +24 -0
  98. package/dist/scripts/lib/judge.js +60 -0
  99. package/dist/scripts/lib/ports.d.ts +35 -0
  100. package/dist/scripts/lib/ports.js +113 -0
  101. package/dist/scripts/lib/review.d.ts +7 -0
  102. package/dist/scripts/lib/review.js +22 -0
  103. package/dist/scripts/lib/rules.d.ts +12 -0
  104. package/dist/scripts/lib/rules.js +20 -0
  105. package/dist/scripts/lib/vercel.d.ts +17 -0
  106. package/dist/scripts/lib/vercel.js +53 -0
  107. package/dist/scripts/new.d.ts +47 -0
  108. package/dist/scripts/new.js +113 -0
  109. package/dist/scripts/people.d.ts +59 -0
  110. package/dist/scripts/people.js +73 -0
  111. package/dist/scripts/preflight.d.ts +35 -0
  112. package/dist/scripts/preflight.js +251 -0
  113. package/dist/scripts/release-check.d.ts +19 -0
  114. package/dist/scripts/release-check.js +39 -0
  115. package/dist/scripts/skill-hint.d.ts +32 -0
  116. package/dist/scripts/skill-hint.js +103 -0
  117. package/dist/scripts/skills.d.ts +13 -0
  118. package/dist/scripts/skills.js +34 -0
  119. package/dist/scripts/visual-match.d.ts +46 -0
  120. package/dist/scripts/visual-match.js +93 -0
  121. package/dist/server/api.d.ts +22 -0
  122. package/dist/server/api.js +143 -0
  123. package/dist/server/checks.d.ts +4 -0
  124. package/dist/server/checks.js +22 -0
  125. package/dist/server/dev.d.ts +2 -0
  126. package/dist/server/dev.js +54 -0
  127. package/dist/server/env.d.ts +8 -0
  128. package/dist/server/env.js +57 -0
  129. package/dist/server/fake-upstash.d.ts +1 -0
  130. package/dist/server/fake-upstash.js +37 -0
  131. package/dist/server/file-kv.d.ts +2 -0
  132. package/dist/server/file-kv.js +24 -0
  133. package/dist/server/local.d.ts +4 -0
  134. package/dist/server/local.js +25 -0
  135. package/dist/server/paths.d.ts +22 -0
  136. package/dist/server/paths.js +81 -0
  137. package/dist/server/session.d.ts +22 -0
  138. package/dist/server/session.js +110 -0
  139. package/dist/server/upstash.d.ts +7 -0
  140. package/dist/server/upstash.js +41 -0
  141. package/dist/vercel/index.d.ts +5 -0
  142. package/dist/vercel/index.js +12 -0
  143. package/dist/vercel/proxy.d.ts +11 -0
  144. package/dist/vercel/proxy.js +238 -0
  145. package/dist/vite/kit.d.ts +4 -0
  146. package/dist/vite/kit.js +35 -0
  147. package/dist/vite/markdown.d.ts +2 -0
  148. package/dist/vite/markdown.js +212 -0
  149. package/dist/vite/plugin.d.ts +15 -0
  150. package/dist/vite/plugin.js +84 -0
  151. package/dist/vite/registry.d.ts +7 -0
  152. package/dist/vite/registry.js +70 -0
  153. package/kit/Icon.tsx +39 -0
  154. package/kit/Space.tsx +25 -0
  155. package/kit/Variants.tsx +134 -0
  156. package/kit/ViewTools.tsx +34 -0
  157. package/kit/base.css +27 -0
  158. package/kit/dials.css +98 -0
  159. package/kit/dials.tsx +322 -0
  160. package/kit/fixtures.ts +3 -0
  161. package/kit/format.ts +13 -0
  162. package/kit/harness.css +99 -0
  163. package/kit/hooks.ts +35 -0
  164. package/kit/icons.ts +329 -0
  165. package/kit/motion.ts +18 -0
  166. package/kit/prefs.ts +111 -0
  167. package/kit/space.css +12 -0
  168. package/kit/ui/Button.tsx +135 -0
  169. package/kit/ui/Menu.tsx +386 -0
  170. package/kit/ui/Overlay.tsx +300 -0
  171. package/kit/ui/Toast.tsx +187 -0
  172. package/kit/ui/index.ts +13 -0
  173. package/kit/ui/layer.ts +51 -0
  174. package/kit/ui/ui.css +238 -0
  175. package/package.json +87 -3
  176. package/shell/Guide.tsx +160 -0
  177. package/shell/Index.tsx +301 -0
  178. package/shell/Notice.tsx +27 -0
  179. package/shell/Prototype.tsx +31 -0
  180. package/shell/a11y.ts +50 -0
  181. package/shell/doc.d.ts +7 -0
  182. package/shell/doc.ts +3 -0
  183. package/shell/guide.css +133 -0
  184. package/shell/index.html +17 -0
  185. package/shell/main.tsx +53 -0
  186. package/shell/public/favicon.svg +1 -0
  187. package/shell/registry.ts +21 -0
  188. package/shell/registry.virtual.d.ts +10 -0
  189. package/shell/review/Review.tsx +989 -0
  190. package/shell/review/anchor.ts +132 -0
  191. package/shell/review/client.ts +165 -0
  192. package/shell/review/mount.tsx +12 -0
  193. package/shell/review/review.css +296 -0
  194. package/shell/shell.css +160 -0
  195. package/shell/system.css +238 -0
  196. package/skills/miles-conductor/SKILL.md +37 -0
  197. package/skills/miles-deploy/SKILL.md +67 -0
  198. package/skills/miles-design-hub/SKILL.md +62 -0
  199. package/skills/miles-get-hostile/SKILL.md +61 -0
  200. package/skills/miles-new-feature/SKILL.md +40 -0
  201. package/skills/miles-paper-to-prototype/SKILL.md +46 -0
  202. package/skills/miles-port/SKILL.md +59 -0
  203. package/skills/miles-port/references/astro.md +35 -0
  204. package/skills/miles-port/references/next.md +36 -0
  205. package/skills/miles-prototype/SKILL.md +83 -0
  206. package/skills/miles-prototype/references/accessibility.md +48 -0
  207. package/skills/miles-prototype/references/motion.md +59 -0
  208. package/skills/miles-prototype/references/performance.md +45 -0
  209. package/skills/miles-review/SKILL.md +39 -0
  210. package/templates/app/README.md +41 -0
  211. package/templates/app/index.tsx +32 -0
  212. package/templates/app/styles.css +1 -0
  213. package/templates/conductor/settings.toml +29 -0
  214. package/templates/guide.md +38 -0
  215. package/templates/space/README.md +37 -0
  216. package/templates/space/index.tsx +43 -0
  217. package/templates/space/styles.css +13 -0
@@ -0,0 +1,133 @@
1
+ /* The walkthrough: a long read in the shell's own voice, not the product's.
2
+ Prose keeps a 680px measure (about 75 characters at 16px); screenshots
3
+ and tables take the full 960px column, because a 1440px app at 680px is
4
+ unreadable. The contents sit in a rail at the left on a wide screen and
5
+ above the text on a narrow one. */
6
+
7
+ .doc { width: min(1208px, 100% - 32px); margin: 0 auto; padding: 64px 0 128px; }
8
+ .doc-layout { display: grid; grid-template-columns: 200px minmax(0, 960px); column-gap: 48px; align-items: start; }
9
+ .doc-head, .doc-body, .doc-foot { grid-column: 2; }
10
+ .doc-toc { grid-column: 1; grid-row: 2; }
11
+
12
+ /* Head */
13
+ .doc-head { display: flex; flex-direction: column; gap: 24px; margin-bottom: 48px; }
14
+ .doc-back { display: inline-flex; align-items: center; gap: 4px; align-self: flex-start; font-size: 14px; line-height: 20px; font-weight: 600; color: var(--text-tertiary); text-decoration: none; border-radius: var(--radius-xs); transition: color var(--dur-hover) var(--ease-hover); }
15
+ .doc-back:hover { color: var(--text-secondary); }
16
+ .doc-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px 24px; flex-wrap: wrap; }
17
+ .doc-head-text { display: flex; flex-direction: column; gap: 4px; max-width: 680px; }
18
+ .doc-kicker { font-size: 12px; line-height: 18px; color: var(--text-quaternary); }
19
+ .doc-title { font-size: 24px; line-height: 32px; font-weight: 600; text-wrap: balance; }
20
+ .doc-head .btn { gap: 6px; }
21
+
22
+ /* Contents */
23
+ .doc-toc { position: sticky; top: 32px; max-height: calc(100dvh - 64px); overflow-y: auto; overscroll-behavior: contain; font-size: 13px; line-height: 20px; }
24
+ .doc-toc-label { font-weight: 600; color: var(--text-tertiary); margin-bottom: 8px; }
25
+ .doc-toc ol { list-style: none; padding: 0; margin: 0; }
26
+ .doc-toc a { display: block; padding: 4px 0 4px 12px; border-inline-start: 2px solid transparent; color: var(--text-tertiary); text-decoration: none; text-wrap: pretty; transition: color var(--dur-hover) var(--ease-hover), border-color var(--dur-hover) var(--ease-hover); }
27
+ .doc-toc .is-sub a { padding-inline-start: 24px; }
28
+ .doc-toc a:hover { color: var(--text-primary); }
29
+ .doc-toc a[aria-current] { color: var(--text-primary); border-color: var(--fg-primary); }
30
+
31
+ /* Body */
32
+ .doc-body { font-size: 16px; line-height: 1.6; color: var(--text-primary); }
33
+ .doc-body > * { max-width: 680px; }
34
+ .doc-body > :is(.doc-figure, .doc-table) { max-width: none; }
35
+ .doc-body > * + * { margin-top: 24px; }
36
+ .doc-body > h2 { margin-top: 56px; font-size: 20px; line-height: 28px; font-weight: 600; text-wrap: balance; }
37
+ .doc-body > h3 { margin-top: 40px; font-size: 16px; line-height: 24px; font-weight: 600; text-wrap: balance; }
38
+ .doc-body > :is(h2, h3) + * { margin-top: 12px; }
39
+ .doc-body > h3 + * { margin-top: 8px; }
40
+ .doc-body :is(h2, h3) { scroll-margin-top: 24px; }
41
+ .doc-body p { text-wrap: pretty; }
42
+ .doc-body strong { font-weight: 600; }
43
+ .doc-body a { color: var(--text-brand-secondary); overflow-wrap: anywhere; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: color-mix(in oklch, currentColor 40%, transparent); transition: text-decoration-color var(--dur-hover) var(--ease-hover); }
44
+ .doc-body a:hover { text-decoration-color: currentColor; }
45
+ .doc-body code { font: 14px/1 var(--sys-font-mono); padding: 2px 5px; border-radius: var(--radius-xs); background: var(--bg-tertiary); color: var(--text-secondary); box-decoration-break: clone; -webkit-box-decoration-break: clone; }
46
+ .doc-body :is(ul, ol) { padding-inline-start: 24px; }
47
+ .doc-body li + li { margin-top: 8px; }
48
+ .doc-body li::marker { color: var(--text-tertiary); }
49
+ .doc-body li > :is(ul, ol) { margin-top: 8px; }
50
+
51
+ /* A click path is the order of presses in Controls, drawn in the panel's own
52
+ dark material so it reads as the prototype and not as a product control.
53
+ The first step is the round button itself. The chevron is the order; the
54
+ last chip is the one you set or press. */
55
+ .doc-body .doc-path { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 0; margin: 0; padding: 0; list-style: none; }
56
+ .doc-body > * + .doc-path, .doc-callout > * + .doc-path { margin-top: 12px; }
57
+ .doc-body > h3 + .doc-path, .doc-body li > .doc-path, .doc-body > .doc-path + .doc-path { margin-top: 8px; }
58
+ .doc-body .doc-path li { display: inline-flex; align-items: center; }
59
+ .doc-body .doc-path li + li { margin-top: 0; }
60
+ .doc-body .doc-path li + li::before { content: ""; width: 6px; height: 6px; margin-inline: 8px 6px; border-right: 1.5px solid var(--text-quaternary); border-bottom: 1.5px solid var(--text-quaternary); transform: rotate(-45deg) translateY(-1px); flex: none; }
61
+ .doc-body .doc-path > li > span { display: inline-flex; align-items: center; min-height: 28px; padding: 4px 10px; border-radius: var(--radius-sm); background: var(--harness-bg); color: var(--harness-fg-muted); box-shadow: inset 0 0 0 1px var(--harness-border); font-size: 13px; line-height: 18px; font-weight: 500; white-space: nowrap; }
62
+ .doc-body .doc-path > li:first-child > span { width: 32px; height: 32px; min-height: 32px; padding: 0; border-radius: 50%; justify-content: center; color: oklch(1 0 0); }
63
+ .doc-body .doc-path > li:last-child > span { color: var(--harness-fg); font-weight: 600; }
64
+ .doc-path-open svg { display: block; }
65
+ .doc-path-name { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
66
+ .doc-body .doc-path-follow { margin: 8px 0 0; }
67
+
68
+ /* Figures: a screenshot wears a 1px inset outline at 10%, black on light
69
+ and white on dark, never a tinted line. The caption is the alt text the
70
+ Markdown carries, so it is read once, under the picture. */
71
+ .doc-figure { margin-top: 24px; }
72
+ .doc-figure img { display: block; width: 100%; height: auto; border-radius: var(--radius-md); outline: 1px solid oklch(0 0 0 / 0.1); outline-offset: -1px; background: var(--bg-secondary); }
73
+ .dark-mode .doc-figure img { outline-color: oklch(1 0 0 / 0.1); }
74
+ .doc-figure figcaption { max-width: 680px; margin-top: 8px; font-size: 13px; line-height: 20px; color: var(--text-tertiary); text-wrap: pretty; }
75
+ .doc-figure figcaption a { color: inherit; margin-inline-start: 4px; white-space: nowrap; }
76
+
77
+ /* Callouts: a quiet well with a labelled dot, so the kind is a word and a
78
+ colour, never a colour alone. Note stays neutral; Iris is kept for the
79
+ one action on the page. */
80
+ .doc-callout { padding: 16px 20px; border-radius: var(--radius-md); background: var(--bg-secondary); box-shadow: inset 0 0 0 1px oklch(0 0 0 / 0.06); }
81
+ .dark-mode .doc-callout { box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08); }
82
+ .doc-callout-kind { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; font-size: 12px; line-height: 18px; font-weight: 600; color: var(--text-tertiary); }
83
+ .doc-callout-kind::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--fg-quinary); }
84
+ .doc-callout[data-kind="tip"] .doc-callout-kind::before { background: var(--fg-success-primary); }
85
+ .doc-callout[data-kind="important"] .doc-callout-kind::before { background: var(--fg-warning-primary); }
86
+ .doc-callout[data-kind="warning"] .doc-callout-kind::before, .doc-callout[data-kind="caution"] .doc-callout-kind::before { background: var(--fg-error-primary); }
87
+ .doc-callout > * + * { margin-top: 12px; }
88
+
89
+ /* Tables: hairlines do the separating, the first column names the row. */
90
+ .doc-table { overflow-x: auto; }
91
+ .doc-table table { width: 100%; border-collapse: collapse; font-size: 14px; line-height: 20px; }
92
+ .doc-table th { padding: 0 12px 8px; text-align: start; font-size: 13px; font-weight: 600; color: var(--text-tertiary); border-bottom: 1px solid var(--border-primary); white-space: nowrap; }
93
+ .doc-table td { padding: 10px 12px; vertical-align: top; border-bottom: 1px solid var(--border-secondary); }
94
+ .doc-table :is(th, td):first-child { padding-inline-start: 0; }
95
+ .doc-table :is(th, td):last-child { padding-inline-end: 0; }
96
+ .doc-table td:first-child { font-weight: 500; }
97
+
98
+ /* Foot */
99
+ .doc-foot { margin-top: 64px; padding-top: 16px; border-top: 1px solid var(--border-secondary); font-size: 14px; line-height: 20px; }
100
+ .doc-foot a { font-weight: 600; color: var(--text-tertiary); text-decoration: none; transition: color var(--dur-hover) var(--ease-hover); }
101
+ .doc-foot a:hover { color: var(--text-secondary); }
102
+
103
+ /* Arrival: one fade, as the index does. */
104
+ .doc-layout { animation: doc-fade 200ms var(--ease-out) backwards; }
105
+ @keyframes doc-fade { from { opacity: 0; } }
106
+ :root:has(.doc) { scroll-behavior: smooth; }
107
+ :root[data-motion="reduce"]:has(.doc) { scroll-behavior: auto; }
108
+
109
+ @media (max-width: 1119px) {
110
+ .doc-layout { grid-template-columns: minmax(0, 1fr); }
111
+ .doc-head, .doc-body, .doc-foot, .doc-toc { grid-column: 1; grid-row: auto; }
112
+ .doc-toc { position: static; max-height: none; overflow: visible; margin-bottom: 48px; max-width: 680px; }
113
+ .doc-toc ol { columns: 2; column-gap: 24px; }
114
+ .doc-toc li { break-inside: avoid; }
115
+ .doc-toc .is-sub { display: none; }
116
+ }
117
+
118
+ @media (max-width: 640px) {
119
+ .doc { width: min(1208px, 100% - 32px); padding-top: 32px; }
120
+ .doc-toc ol { columns: 1; }
121
+ .doc-head .btn { width: 100%; }
122
+ .doc-body .doc-path > li > span { white-space: normal; }
123
+ }
124
+
125
+ @media print {
126
+ .doc { width: auto; padding: 0; }
127
+ .doc-toc, .doc-back, .doc-head .btn, .doc-foot, .doc-figure figcaption a { display: none; }
128
+ /* Print drops the chip fill, so the ink is set or the light type and icon would disappear. */
129
+ .doc-body .doc-path > li > span,
130
+ .doc-body .doc-path > li:first-child > span { background: none; color: oklch(0.205 0 0); box-shadow: inset 0 0 0 1px oklch(0.87 0 0); }
131
+ .doc-body > * { max-width: none; }
132
+ .doc-figure { break-inside: avoid; }
133
+ }
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
+ <meta name="theme-color" content="#ffffff" />
7
+ <title>Prototypes</title>
8
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
9
+ <script type="speculationrules">
10
+ { "prefetch": [{ "where": { "selector_matches": ".index-row" }, "eagerness": "moderate" }] }
11
+ </script>
12
+ </head>
13
+ <body>
14
+ <div id="root"></div>
15
+ <script type="module" src="./main.tsx"></script>
16
+ </body>
17
+ </html>
package/shell/main.tsx ADDED
@@ -0,0 +1,53 @@
1
+ import { setGuide } from '@kit/dials';
2
+ import '@kit/tokens.css';
3
+ import '@kit/base.css';
4
+ import './system.css';
5
+ import { attachLapse } from '@kit/prefs';
6
+ import { lazy, type ReactNode, StrictMode, Suspense } from 'react';
7
+ import { createRoot } from 'react-dom/client';
8
+ import { guideHref } from '../core/feature';
9
+ import { Index } from './Index';
10
+ import { Prototype } from './Prototype';
11
+ import { findEntry, guides } from './registry';
12
+
13
+ const params = new URLSearchParams(location.search);
14
+
15
+ // Lapse patches the clocks, so it lands before any prototype (and Motion) loads.
16
+ if (import.meta.env.DEV && params.has('lapse')) {
17
+ // Opaque specifier: the package is optional and absent on Vercel, so Rollup must not resolve it.
18
+ const panel = '@aiforui/lapse/panel';
19
+ const { mountLapse } = await import(/* @vite-ignore */ panel);
20
+ attachLapse(mountLapse({ position: 'bottom-left' }));
21
+ }
22
+
23
+ if (import.meta.env.DEV && params.get('a11y') !== '0') {
24
+ import('./a11y').then((m) => m.watchA11y());
25
+ }
26
+
27
+ // /<slug>/ is a prototype; /guide/<feature>/ is that feature's walkthrough.
28
+ // The slug `guide` belongs to the shell (new.ts refuses it).
29
+ const [slug, sub] = location.pathname.split('/').filter(Boolean);
30
+ const Guide = lazy(() => import('./Guide'));
31
+
32
+ let page: ReactNode;
33
+ // Hub pages wear the neutral system look; a prototype keeps the project's tokens.
34
+ if (!slug || slug === 'guide') document.documentElement.classList.add('sys');
35
+ if (slug === 'guide') {
36
+ page = (
37
+ <Suspense fallback={null}>
38
+ <Guide feature={sub} />
39
+ </Suspense>
40
+ );
41
+ } else if (slug) {
42
+ const entry = findEntry(slug);
43
+ if (entry?.feature && guides.has(entry.feature)) setGuide(guideHref(entry.feature));
44
+ page = <Prototype slug={slug} entry={entry} />;
45
+ if (entry) {
46
+ const { mountReview } = await import('./review/mount');
47
+ mountReview({ prototype: slug, feature: entry.feature, states: (entry.states ?? []).map((s) => s.name) });
48
+ }
49
+ } else {
50
+ page = <Index />;
51
+ }
52
+
53
+ createRoot(document.getElementById('root')!).render(<StrictMode>{page}</StrictMode>);
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="7" fill="#101828"/><path d="M16 7 7 11.5l9 4.5 9-4.5L16 7Z" fill="#fff"/><path d="m7 20.5 9 4.5 9-4.5M7 16l9 4.5 9-4.5" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
@@ -0,0 +1,21 @@
1
+ import { guideDocs, modules, readmes } from 'virtual:design-hub/registry';
2
+ import type { ComponentType } from 'react';
3
+ import { byIndexOrder, type Meta, readMeta } from '../core/catalog';
4
+ import type { Doc } from './doc';
5
+
6
+ export type Entry = Meta & { load?: () => Promise<{ default: ComponentType }> };
7
+
8
+ // The registry module is written by the Vite plugin (vite/registry.ts) from
9
+ // the project's prototypes/ and docs/sprints/ folders.
10
+ export const entries: Entry[] = Object.entries(readmes)
11
+ .map(([slug, md]): Entry => ({ ...readMeta(slug, md), load: modules[slug] }))
12
+ .sort(byIndexOrder);
13
+
14
+ export const findEntry = (slug: string) => entries.find((e) => e.slug === slug);
15
+
16
+ export const guides = new Map<string, () => Promise<Doc>>(Object.entries(guideDocs));
17
+
18
+ // The prototype a feature's walkthrough opens: the sprint itself, else the first one listed.
19
+ export const featureEntry = (feature: string) =>
20
+ entries.find((e) => e.feature === feature && e.kind === 'sprint') ??
21
+ entries.find((e) => e.feature === feature);
@@ -0,0 +1,10 @@
1
+ declare module 'virtual:design-hub/registry' {
2
+ import type { ComponentType } from 'react';
3
+ import type { Doc } from './doc';
4
+ /** Each prototype's README text, by slug. */
5
+ export const readmes: Record<string, string>;
6
+ /** Each prototype's module loader, by slug; absent when the folder has no index.tsx. */
7
+ export const modules: Record<string, () => Promise<{ default: ComponentType }>>;
8
+ /** Each feature's compiled walkthrough loader, by feature. */
9
+ export const guideDocs: Record<string, () => Promise<Doc>>;
10
+ }