@prestack/thread-ui 0.0.1 → 0.0.2

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 (269) hide show
  1. package/dist/ui/animations/anm_appear.ts +13 -0
  2. package/dist/ui/animations/anm_blur_in.ts +19 -0
  3. package/dist/ui/animations/anm_blur_out.ts +18 -0
  4. package/dist/ui/animations/anm_dismiss.ts +18 -0
  5. package/dist/ui/animations/anm_drop.ts +19 -0
  6. package/dist/ui/animations/anm_fall.ts +18 -0
  7. package/dist/ui/animations/anm_flash.ts +18 -0
  8. package/dist/ui/animations/anm_glow.ts +16 -0
  9. package/dist/ui/animations/anm_lift.ts +16 -0
  10. package/dist/ui/animations/anm_nudge.ts +16 -0
  11. package/dist/ui/animations/anm_pop_in.ts +23 -0
  12. package/dist/ui/animations/anm_pop_out.ts +22 -0
  13. package/dist/ui/animations/anm_press.ts +12 -0
  14. package/dist/ui/animations/anm_pulse.ts +13 -0
  15. package/dist/ui/animations/anm_rise.ts +19 -0
  16. package/dist/ui/animations/anm_shake.ts +13 -0
  17. package/dist/ui/animations/anm_slide_in_left.ts +19 -0
  18. package/dist/ui/animations/anm_slide_in_right.ts +19 -0
  19. package/dist/ui/animations/anm_slide_out_left.ts +18 -0
  20. package/dist/ui/animations/anm_slide_out_right.ts +18 -0
  21. package/dist/ui/animations/anm_spin.ts +12 -0
  22. package/dist/ui/animations/anm_swell.ts +16 -0
  23. package/dist/ui/animations/anm_wobble.ts +24 -0
  24. package/dist/ui/animations/anm_zoom_in.ts +19 -0
  25. package/dist/ui/animations/anm_zoom_out.ts +18 -0
  26. package/dist/ui/animations.ts +317 -0
  27. package/dist/ui/attach.js +13 -4
  28. package/dist/ui/attach.ts +613 -0
  29. package/dist/ui/charts.tsx +74 -0
  30. package/dist/ui/checked.d.ts +2 -2
  31. package/dist/ui/checked.ts +32 -0
  32. package/dist/ui/collector.ts +140 -0
  33. package/dist/ui/compositions.d.ts +10 -1
  34. package/dist/ui/compositions.js +262 -23
  35. package/dist/ui/compositions.ts +640 -0
  36. package/dist/ui/consent.ts +55 -0
  37. package/dist/ui/content.tsx +39 -0
  38. package/dist/ui/contrast.ts +27 -0
  39. package/dist/ui/controls.tsx +30 -0
  40. package/dist/ui/disclosure.tsx +22 -0
  41. package/dist/ui/dismiss-layer.ts +87 -0
  42. package/dist/ui/door.ts +140 -0
  43. package/dist/ui/drag.ts +316 -0
  44. package/dist/ui/elements/accordion.js +2 -2
  45. package/dist/ui/elements/accordion.tsx +47 -0
  46. package/dist/ui/elements/accordion.works.ts +66 -0
  47. package/dist/ui/elements/aspect-ratio.js +1 -1
  48. package/dist/ui/elements/aspect-ratio.tsx +30 -0
  49. package/dist/ui/elements/aspect-ratio.works.ts +5 -0
  50. package/dist/ui/elements/avatar.js +1 -1
  51. package/dist/ui/elements/avatar.tsx +33 -0
  52. package/dist/ui/elements/avatar.works.ts +16 -0
  53. package/dist/ui/elements/badge.js +1 -1
  54. package/dist/ui/elements/badge.tsx +32 -0
  55. package/dist/ui/elements/badge.works.ts +9 -0
  56. package/dist/ui/elements/bars.js +2 -2
  57. package/dist/ui/elements/bars.tsx +49 -0
  58. package/dist/ui/elements/bars.works.ts +29 -0
  59. package/dist/ui/elements/box.js +3 -2
  60. package/dist/ui/elements/box.tsx +35 -0
  61. package/dist/ui/elements/breadcrumb.js +2 -2
  62. package/dist/ui/elements/breadcrumb.tsx +37 -0
  63. package/dist/ui/elements/breadcrumb.works.ts +24 -0
  64. package/dist/ui/elements/button.js +1 -1
  65. package/dist/ui/elements/button.tsx +45 -0
  66. package/dist/ui/elements/button.works.tsx +52 -0
  67. package/dist/ui/elements/column.js +1 -1
  68. package/dist/ui/elements/column.tsx +28 -0
  69. package/dist/ui/elements/consent.js +2 -2
  70. package/dist/ui/elements/consent.tsx +70 -0
  71. package/dist/ui/elements/consent.works.tsx +132 -0
  72. package/dist/ui/elements/donut.js +2 -2
  73. package/dist/ui/elements/donut.tsx +44 -0
  74. package/dist/ui/elements/donut.works.ts +42 -0
  75. package/dist/ui/elements/each.js +1 -1
  76. package/dist/ui/elements/each.tsx +33 -0
  77. package/dist/ui/elements/each.works.tsx +82 -0
  78. package/dist/ui/elements/empty.js +1 -1
  79. package/dist/ui/elements/empty.tsx +32 -0
  80. package/dist/ui/elements/field.js +1 -1
  81. package/dist/ui/elements/field.tsx +44 -0
  82. package/dist/ui/elements/field.works.ts +65 -0
  83. package/dist/ui/elements/funnel.js +2 -2
  84. package/dist/ui/elements/funnel.tsx +49 -0
  85. package/dist/ui/elements/funnel.works.ts +37 -0
  86. package/dist/ui/elements/gauge.js +1 -1
  87. package/dist/ui/elements/gauge.tsx +39 -0
  88. package/dist/ui/elements/gauge.works.ts +42 -0
  89. package/dist/ui/elements/glyph.js +1 -1
  90. package/dist/ui/elements/glyph.tsx +29 -0
  91. package/dist/ui/elements/glyph.works.tsx +42 -0
  92. package/dist/ui/elements/grid.js +1 -1
  93. package/dist/ui/elements/grid.tsx +28 -0
  94. package/dist/ui/elements/heatmap.js +2 -2
  95. package/dist/ui/elements/heatmap.tsx +47 -0
  96. package/dist/ui/elements/heatmap.works.ts +24 -0
  97. package/dist/ui/elements/hit-box.js +1 -1
  98. package/dist/ui/elements/hit-box.tsx +46 -0
  99. package/dist/ui/elements/hit-box.works.tsx +576 -0
  100. package/dist/ui/elements/image.js +1 -1
  101. package/dist/ui/elements/image.tsx +28 -0
  102. package/dist/ui/elements/line-chart.js +2 -2
  103. package/dist/ui/elements/line-chart.tsx +44 -0
  104. package/dist/ui/elements/line-chart.works.ts +41 -0
  105. package/dist/ui/elements/link.js +1 -1
  106. package/dist/ui/elements/link.tsx +37 -0
  107. package/dist/ui/elements/link.works.ts +25 -0
  108. package/dist/ui/elements/media.js +1 -1
  109. package/dist/ui/elements/media.tsx +56 -0
  110. package/dist/ui/elements/menu.js +2 -2
  111. package/dist/ui/elements/menu.tsx +50 -0
  112. package/dist/ui/elements/menu.works.tsx +153 -0
  113. package/dist/ui/elements/money.js +1 -1
  114. package/dist/ui/elements/money.tsx +28 -0
  115. package/dist/ui/elements/money.works.ts +9 -0
  116. package/dist/ui/elements/pagination.js +2 -2
  117. package/dist/ui/elements/pagination.tsx +38 -0
  118. package/dist/ui/elements/pagination.works.ts +20 -0
  119. package/dist/ui/elements/progress.js +1 -1
  120. package/dist/ui/elements/progress.tsx +33 -0
  121. package/dist/ui/elements/progress.works.ts +8 -0
  122. package/dist/ui/elements/radio-group.js +2 -2
  123. package/dist/ui/elements/radio-group.tsx +49 -0
  124. package/dist/ui/elements/radio-group.works.ts +33 -0
  125. package/dist/ui/elements/row.js +1 -1
  126. package/dist/ui/elements/row.tsx +28 -0
  127. package/dist/ui/elements/scatter.js +1 -1
  128. package/dist/ui/elements/scatter.tsx +41 -0
  129. package/dist/ui/elements/scatter.works.ts +38 -0
  130. package/dist/ui/elements/select.js +2 -2
  131. package/dist/ui/elements/select.tsx +42 -0
  132. package/dist/ui/elements/select.works.ts +5 -0
  133. package/dist/ui/elements/separator.js +1 -1
  134. package/dist/ui/elements/separator.tsx +30 -0
  135. package/dist/ui/elements/skeleton.js +1 -1
  136. package/dist/ui/elements/skeleton.tsx +30 -0
  137. package/dist/ui/elements/slider.js +1 -1
  138. package/dist/ui/elements/slider.tsx +33 -0
  139. package/dist/ui/elements/slider.works.ts +5 -0
  140. package/dist/ui/elements/sparkline.js +1 -1
  141. package/dist/ui/elements/sparkline.tsx +36 -0
  142. package/dist/ui/elements/sparkline.works.ts +32 -0
  143. package/dist/ui/elements/spinner.js +1 -1
  144. package/dist/ui/elements/spinner.tsx +32 -0
  145. package/dist/ui/elements/stack.js +1 -1
  146. package/dist/ui/elements/stack.tsx +28 -0
  147. package/dist/ui/elements/stat.js +1 -1
  148. package/dist/ui/elements/stat.tsx +35 -0
  149. package/dist/ui/elements/stat.works.ts +14 -0
  150. package/dist/ui/elements/surface.js +1 -1
  151. package/dist/ui/elements/surface.tsx +35 -0
  152. package/dist/ui/elements/surface.works.ts +9 -0
  153. package/dist/ui/elements/table.js +2 -2
  154. package/dist/ui/elements/table.tsx +61 -0
  155. package/dist/ui/elements/table.works.ts +30 -0
  156. package/dist/ui/elements/tabs.js +2 -2
  157. package/dist/ui/elements/tabs.tsx +47 -0
  158. package/dist/ui/elements/tabs.works.ts +84 -0
  159. package/dist/ui/elements/text.js +1 -1
  160. package/dist/ui/elements/text.tsx +32 -0
  161. package/dist/ui/elements/textarea.js +1 -1
  162. package/dist/ui/elements/textarea.tsx +37 -0
  163. package/dist/ui/elements/textarea.works.ts +5 -0
  164. package/dist/ui/elements/time.js +1 -1
  165. package/dist/ui/elements/time.tsx +34 -0
  166. package/dist/ui/elements/time.works.ts +25 -0
  167. package/dist/ui/elements/toggle.js +1 -1
  168. package/dist/ui/elements/toggle.tsx +33 -0
  169. package/dist/ui/elements/toggle.works.ts +5 -0
  170. package/dist/ui/elements/tooltip.js +1 -1
  171. package/dist/ui/elements/tooltip.tsx +39 -0
  172. package/dist/ui/elements/tooltip.works.ts +77 -0
  173. package/dist/ui/elements/value.js +1 -1
  174. package/dist/ui/elements/value.tsx +30 -0
  175. package/dist/ui/elements/value.works.ts +9 -0
  176. package/dist/ui/elements.ts +127 -0
  177. package/dist/ui/focus-scope.ts +121 -0
  178. package/dist/ui/fonts.ts +355 -0
  179. package/dist/ui/generators/dev.ts +79 -0
  180. package/dist/ui/generators/elements.d.ts +1 -11
  181. package/dist/ui/generators/elements.js +43 -13
  182. package/dist/ui/generators/elements.ts +794 -0
  183. package/dist/ui/generators/i18n.ts +301 -0
  184. package/dist/ui/generators/icons.ts +214 -0
  185. package/dist/ui/generators/react.js +10 -3
  186. package/dist/ui/generators/react.ts +268 -0
  187. package/dist/ui/generators/routes.d.ts +1 -0
  188. package/dist/ui/generators/routes.js +89 -69
  189. package/dist/ui/generators/routes.ts +739 -0
  190. package/dist/ui/generators/show.ts +259 -0
  191. package/dist/ui/generators/styles.js +1 -1
  192. package/dist/ui/generators/styles.ts +670 -0
  193. package/dist/ui/generators/variants.ts +205 -0
  194. package/dist/ui/i18n/catalogs/en.ts +191 -0
  195. package/dist/ui/i18n/format.ts +221 -0
  196. package/dist/ui/i18n/locales.ts +33 -0
  197. package/dist/ui/i18n/parse.ts +315 -0
  198. package/dist/ui/i18n/translator.ts +31 -0
  199. package/dist/ui/i18n/types.ts +96 -0
  200. package/dist/ui/icons.ts +331 -0
  201. package/dist/ui/islands/map.ts +58 -0
  202. package/dist/ui/localizations.ts +75 -0
  203. package/dist/ui/makers/message.ts +292 -0
  204. package/dist/ui/material.ts +236 -0
  205. package/dist/ui/materials/mat_bordered.ts +13 -0
  206. package/dist/ui/materials/mat_ceramic.ts +13 -0
  207. package/dist/ui/materials/mat_clay.ts +13 -0
  208. package/dist/ui/materials/mat_elevated.ts +24 -0
  209. package/dist/ui/materials/mat_flat.ts +34 -0
  210. package/dist/ui/materials/mat_glass.ts +20 -0
  211. package/dist/ui/materials/mat_lit.ts +13 -0
  212. package/dist/ui/materials/mat_moulded.ts +11 -0
  213. package/dist/ui/materials.ts +206 -0
  214. package/dist/ui/modes.ts +44 -0
  215. package/dist/ui/navigation.tsx +32 -0
  216. package/dist/ui/positioning.ts +90 -0
  217. package/dist/ui/presented.tsx +119 -0
  218. package/dist/ui/provider.d.ts +2 -0
  219. package/dist/ui/provider.js +7 -1
  220. package/dist/ui/provider.tsx +182 -0
  221. package/dist/ui/render-loop.ts +133 -0
  222. package/dist/ui/roving-focus.ts +161 -0
  223. package/dist/ui/screens.js +17 -8
  224. package/dist/ui/screens.ts +142 -0
  225. package/dist/ui/scroll-lock.ts +28 -0
  226. package/dist/ui/series.ts +97 -0
  227. package/dist/ui/signals.ts +386 -0
  228. package/dist/ui/styleguide.ts +231 -0
  229. package/dist/ui/styleguides.ts +374 -0
  230. package/dist/ui/themes.ts +22 -0
  231. package/dist/ui/token.js +1 -1
  232. package/dist/ui/token.ts +78 -0
  233. package/dist/ui/tokens/shadow.ts +25 -0
  234. package/dist/ui/tokens.ts +235 -0
  235. package/dist/ui/validators.ts +232 -0
  236. package/dist/ui/variant.d.ts +1 -0
  237. package/dist/ui/variant.js +3 -0
  238. package/dist/ui/variant.ts +352 -0
  239. package/dist/ui/variants/var_avatar-round.ts +14 -0
  240. package/dist/ui/variants/var_bubble-me.ts +14 -0
  241. package/dist/ui/variants/var_bubble-them.ts +13 -0
  242. package/dist/ui/variants/var_button-border.ts +76 -0
  243. package/dist/ui/variants/var_button-cta.ts +76 -0
  244. package/dist/ui/variants/var_button-destructive-ghost.ts +72 -0
  245. package/dist/ui/variants/var_button-destructive.ts +76 -0
  246. package/dist/ui/variants/var_button-fill.ts +76 -0
  247. package/dist/ui/variants/var_button-ghost.ts +72 -0
  248. package/dist/ui/variants/var_button-glass.ts +55 -0
  249. package/dist/ui/variants/var_button-normal.ts +76 -0
  250. package/dist/ui/variants/var_button-quiet.ts +74 -0
  251. package/dist/ui/variants/var_card.ts +17 -0
  252. package/dist/ui/variants/var_chip.ts +13 -0
  253. package/dist/ui/variants/var_choice.ts +15 -0
  254. package/dist/ui/variants/var_framed.ts +10 -0
  255. package/dist/ui/variants/var_glyph-plain.ts +11 -0
  256. package/dist/ui/variants/var_input.ts +43 -0
  257. package/dist/ui/variants/var_link-inline.ts +29 -0
  258. package/dist/ui/variants/var_list-row.ts +34 -0
  259. package/dist/ui/variants/var_rule.ts +10 -0
  260. package/dist/ui/variants/var_skeleton-block.ts +12 -0
  261. package/dist/ui/variants/var_spinner-turning.ts +12 -0
  262. package/dist/ui/variants/var_stat-tile.ts +13 -0
  263. package/dist/ui/variants/var_tab-bar.ts +15 -0
  264. package/dist/ui/variants/var_tap-target.ts +25 -0
  265. package/dist/ui/variants.ts +64 -0
  266. package/dist/ui/wrappers.d.ts +4 -1
  267. package/dist/ui/wrappers.js +60 -20
  268. package/dist/ui/wrappers.tsx +426 -0
  269. package/package.json +8 -2
@@ -0,0 +1,259 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs'
2
+ import { join, resolve } from 'node:path'
3
+ import { argv, stdout } from 'node:process'
4
+ import { pathToFileURL } from 'node:url'
5
+
6
+ import { exit, invoked } from '@prestack/thread/core/invoked'
7
+ import { named as packageOf } from '@prestack/thread/core/scope'
8
+ import { findTree, inTree } from '@prestack/thread/core/tree'
9
+
10
+ interface Row {
11
+ readonly id: string
12
+ readonly at?: string
13
+ readonly is?: string
14
+ readonly token?: string
15
+ readonly sets?: Readonly<Record<string, string>>
16
+ readonly places?: Readonly<Record<string, Readonly<Record<string, string>>>>
17
+ readonly wears?: readonly string[]
18
+ readonly plays?: { readonly in?: string; readonly out?: string }
19
+ }
20
+
21
+ interface Node {
22
+ readonly declares?: readonly Row[]
23
+ readonly holds?: readonly Row[]
24
+ }
25
+
26
+ function inside(node: Node): readonly Row[] {
27
+ return [...(node.holds ?? []), ...(node.declares ?? [])]
28
+ }
29
+
30
+ const compare = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)
31
+
32
+ const exported = (id: string): string => id.replace(/-/g, '_').toUpperCase()
33
+
34
+ function pascal(id: string): string {
35
+ return id
36
+ .split('-')
37
+ .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
38
+ .join('')
39
+ }
40
+
41
+ async function node(file: string, name: string): Promise<Node> {
42
+ const held = (await import(pathToFileURL(inTree(findTree(), file)).href)) as Record<string, unknown>
43
+ const one = held[name]
44
+ if (one === undefined) return {}
45
+ return one as Node
46
+ }
47
+
48
+ const LOADABLE = /\.(js|mjs|cjs|ts|mts)$/
49
+
50
+ async function fileFor(root: string, at: string, id: string): Promise<Record<string, unknown> | undefined> {
51
+ const path = resolve(root, at)
52
+ if (!existsSync(path) || !LOADABLE.test(path)) return undefined
53
+ try {
54
+ const held = (await import(pathToFileURL(path).href)) as Record<string, unknown>
55
+ return held[exported(id)] as Record<string, unknown> | undefined
56
+ } catch (wrong) {
57
+
58
+ throw new Error(
59
+ `${at} is there but will not load, so what it names cannot be read. A guard that cannot read is ` +
60
+ `not a guard that passed.\n ${String(wrong instanceof Error ? wrong.message : wrong)}`,
61
+ )
62
+ }
63
+ }
64
+
65
+ const NAMED = /var\(\s*--([a-z0-9-]+)\s*\)/g
66
+
67
+ const PACKAGES = 'node_modules'
68
+
69
+ const INSTALLED = `${PACKAGES}/${packageOf('ui')}/dist/elements`
70
+
71
+ function referenced(value: unknown, named: ReadonlySet<string>, into: Set<string>): void {
72
+ if (typeof value === 'string') {
73
+ for (const one of value.matchAll(NAMED)) into.add(one[1] ?? '')
74
+ if (named.has(value)) into.add(value)
75
+ return
76
+ }
77
+ if (Array.isArray(value)) {
78
+ for (const one of value) referenced(one, named, into)
79
+ return
80
+ }
81
+ if (typeof value === 'object' && value !== null) {
82
+ for (const one of Object.values(value)) referenced(one, named, into)
83
+ }
84
+ }
85
+
86
+ function raising(files: readonly string[]): {
87
+ readonly still: ReadonlyMap<string, readonly string[]>
88
+ readonly moving: readonly string[]
89
+ } {
90
+ const still = new Map<string, string[]>()
91
+ const moving: string[] = []
92
+ for (const path of files) {
93
+ const one = path.slice(path.lastIndexOf('/') + 1)
94
+ let text = ''
95
+ try {
96
+ text = readFileSync(path, 'utf8')
97
+ } catch {
98
+ continue
99
+ }
100
+
101
+ const code = text.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '')
102
+ const at = code.indexOf('holds:')
103
+ if (at === -1) continue
104
+ const opens = code.indexOf('[', at)
105
+ if (opens === -1 || opens > at + 40) continue
106
+ let depth = 0
107
+ let shut = opens
108
+ for (; shut < code.length; shut += 1) {
109
+ const ch = code[shut]
110
+ if (ch === '[') depth += 1
111
+ else if (ch === ']') {
112
+ depth -= 1
113
+ if (depth === 0) break
114
+ }
115
+ }
116
+ const held = code.slice(opens, shut + 1)
117
+ const found = [...held.matchAll(/'([a-zA-Z]+)'/g)].map((each) => each[1] ?? '')
118
+ const element = pascal(one.replace(/\.tsx$/, ''))
119
+ if (/\.filter\(|\.map\(/.test(held)) moving.push(element)
120
+ if (found.length > 0) still.set(element, [...new Set(found)].sort(compare))
121
+ }
122
+ return { still, moving }
123
+ }
124
+
125
+ function listed(what: string, held: readonly string[], good: string): readonly string[] {
126
+ if (held.length === 0) return [` ${what}: ${good}`]
127
+ return [` ${what}: ${String(held.length)}`, ...held.map((one) => ` ${one}`)]
128
+ }
129
+
130
+ export async function namedBy(id: string): Promise<readonly string[]> {
131
+ const root = findTree().at
132
+ const found: string[] = []
133
+
134
+ const looks = async (file: string, name: string, what: string): Promise<void> => {
135
+ for (const one of inside(await node(file, name))) {
136
+
137
+ if (one.id === id) continue
138
+ if (one.at === undefined) {
139
+ const held = new Set<string>()
140
+ referenced(one, new Set([id]), held)
141
+ if (held.has(id)) found.push(`the ${what} \`${one.id}\``)
142
+ continue
143
+ }
144
+ const shape = await fileFor(root, one.at, one.id)
145
+ const held = new Set<string>()
146
+ referenced(shape, new Set([id]), held)
147
+ if (held.has(id)) found.push(`the ${what} \`${one.id}\``)
148
+ }
149
+ }
150
+
151
+ await looks(`styleguides.${'ts'}`, 'STYLEGUIDE', 'value')
152
+ await looks(`variants.${'ts'}`, 'VARIANT', 'variant')
153
+ await looks(`materials.${'ts'}`, 'MATERIAL', 'material')
154
+ await looks(`animations.${'ts'}`, 'ANIMATION', 'animation')
155
+ await looks(`compositions.${'ts'}`, 'COMPOSITION', 'composition')
156
+ await looks(`screens.${'ts'}`, 'SCREEN', 'screen')
157
+ await looks(`fonts.${'ts'}`, 'FONT', 'font role')
158
+
159
+ return [...new Set(found)].sort(compare)
160
+ }
161
+
162
+ async function run(): Promise<number> {
163
+ const tree = findTree()
164
+ const root = tree.at
165
+
166
+ const guide = inside(await node('styleguides.ts', 'STYLEGUIDE'))
167
+ const variants = inside(await node('variants.ts', 'VARIANT'))
168
+ const elements = inside(await node('elements.ts', 'ELEMENT'))
169
+ const signals = inside(await node('signals.ts', 'SIGNAL'))
170
+ const materials = inside(await node('materials.ts', 'MATERIAL'))
171
+ const animations = inside(await node('animations.ts', 'ANIMATION'))
172
+ const compositions = inside(await node('compositions.ts', 'COMPOSITION'))
173
+ const screens = inside(await node('screens.ts', 'SCREEN'))
174
+ const fonts = inside(await node('fonts.ts', 'FONT'))
175
+
176
+ const named = new Set(guide.map((row) => row.id))
177
+ const used = new Set<string>()
178
+
179
+ for (const row of [...variants, ...materials, ...animations]) {
180
+ if (row.at === undefined) continue
181
+ referenced(await fileFor(root, row.at, row.id), named, used)
182
+ }
183
+ for (const row of [...compositions, ...screens, ...fonts]) referenced(row, named, used)
184
+
185
+ const unused = [...named].filter((one) => !used.has(one)).sort(compare)
186
+
187
+ const worn = new Set(variants.flatMap((row) => row.wears ?? []))
188
+ const known = new Set(elements.map((row) => pascal(row.id)))
189
+ const bare = [...known].filter((one) => !worn.has(one)).sort(compare)
190
+ const unworn = variants.filter((row) => (row.wears ?? []).every((one) => !known.has(one))).map((row) => row.id).sort(compare)
191
+
192
+ const shipped = ((): readonly string[] => {
193
+ const dir = join(root, INSTALLED)
194
+ try {
195
+ return readdirSync(dir)
196
+ .filter((one) => one.endsWith('.tsx'))
197
+ .map((one) => join(dir, one))
198
+ } catch {
199
+ return []
200
+ }
201
+ })()
202
+ const ours = elements
203
+ .map((row) => row.at ?? '')
204
+ .filter((one) => one !== '' && !one.startsWith(PACKAGES))
205
+ .map((one) => resolve(root, one))
206
+ .filter((one) => existsSync(one))
207
+ const { still, moving } = raising([...shipped, ...ours])
208
+ const raised = new Set([...still.values()].flat())
209
+ const reacted = new Set<string>()
210
+ for (const row of variants) {
211
+ if (row.at === undefined) continue
212
+ const held = (await fileFor(root, row.at, row.id)) as { readonly reacts?: readonly string[] } | undefined
213
+ for (const one of held?.reacts ?? []) reacted.add(one)
214
+ }
215
+ const declaredSignals = signals.map((row) => row.id)
216
+ const unraisable = declaredSignals
217
+ .filter((one) => !raised.has(one) && !/^(hover|active|focus|disabled|invalid)$/.test(one))
218
+ .sort(compare)
219
+ const answered = declaredSignals.filter((one) => reacted.has(one)).length
220
+
221
+ stdout.write(`show: ${tree.name}\n\n`)
222
+ stdout.write(
223
+ [
224
+ `declared: ${String(guide.length)} values · ${String(variants.length)} variants · ${String(elements.length)} elements · ` +
225
+ `${String(signals.length)} signals · ${String(materials.length)} materials · ${String(animations.length)} animations`,
226
+ '',
227
+ ...listed('style guide rows nothing names', unused, 'none — every value is reached'),
228
+ '',
229
+ ...listed('variants no declared element accepts', unworn, 'none — every variant is worn'),
230
+ '',
231
+ ...listed('elements wearing no variant', bare, 'none — every element is dressed'),
232
+ '',
233
+ ...listed(
234
+ 'signals no element is seen to raise',
235
+ unraisable,
236
+ 'none — every declared signal is raised somewhere',
237
+ ),
238
+ moving.length === 0
239
+ ? ''
240
+ : ` (${moving.join(', ')} ${moving.length === 1 ? 'works its' : 'work theirs'} out at run time, from the gesture it is bound to, so it cannot be read from source)`,
241
+ '',
242
+ ` signals answered by some variant: ${String(answered)} of ${String(signals.length)}`,
243
+ ].join('\n'),
244
+ )
245
+ stdout.write('\n')
246
+
247
+ if (argv.includes('--check')) {
248
+ const wrong = unused.length + unworn.length + unraisable.length
249
+ if (wrong > 0) {
250
+ stdout.write(
251
+ `\nshow: ${String(wrong)} declared thing(s) nothing reaches. This is a report, not a refusal — ` +
252
+ 'reaching them, or retiring them, is a decision.\n',
253
+ )
254
+ }
255
+ }
256
+ return 0
257
+ }
258
+
259
+ if (invoked(import.meta.url)) exit(await run())
@@ -458,7 +458,7 @@ async function run() {
458
458
  '}',
459
459
  '',
460
460
  'export const ASKING = [',
461
- ...asking.map((one) => ` { id: '${String(one.id)}', selector: '${one.selector ?? `[data-${String(one.id)}]`}' },`),
461
+ ...asking.map((one) => ` { id: '${String(one.id)}', selector: '${one.selector ?? `[data-${String(one.id)}]`}'${typeof one.when === 'string' ? `, when: '${one.when}'` : ''} },`),
462
462
  '] as const',
463
463
  '',
464
464
  ].join('\n');