@prestack/thread-ui 0.0.1 → 0.1.0

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 (279) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/dist/ui/animations/anm_appear.ts +13 -0
  3. package/dist/ui/animations/anm_blur_in.ts +19 -0
  4. package/dist/ui/animations/anm_blur_out.ts +18 -0
  5. package/dist/ui/animations/anm_dismiss.ts +18 -0
  6. package/dist/ui/animations/anm_drop.ts +19 -0
  7. package/dist/ui/animations/anm_fall.ts +18 -0
  8. package/dist/ui/animations/anm_flash.ts +18 -0
  9. package/dist/ui/animations/anm_glow.ts +16 -0
  10. package/dist/ui/animations/anm_lift.ts +16 -0
  11. package/dist/ui/animations/anm_nudge.ts +16 -0
  12. package/dist/ui/animations/anm_pop_in.ts +23 -0
  13. package/dist/ui/animations/anm_pop_out.ts +22 -0
  14. package/dist/ui/animations/anm_press.ts +12 -0
  15. package/dist/ui/animations/anm_pulse.ts +13 -0
  16. package/dist/ui/animations/anm_rise.ts +19 -0
  17. package/dist/ui/animations/anm_shake.ts +13 -0
  18. package/dist/ui/animations/anm_slide_in_left.ts +19 -0
  19. package/dist/ui/animations/anm_slide_in_right.ts +19 -0
  20. package/dist/ui/animations/anm_slide_out_left.ts +18 -0
  21. package/dist/ui/animations/anm_slide_out_right.ts +18 -0
  22. package/dist/ui/animations/anm_spin.ts +12 -0
  23. package/dist/ui/animations/anm_swell.ts +16 -0
  24. package/dist/ui/animations/anm_wobble.ts +24 -0
  25. package/dist/ui/animations/anm_zoom_in.ts +19 -0
  26. package/dist/ui/animations/anm_zoom_out.ts +18 -0
  27. package/dist/ui/animations.js +2 -3
  28. package/dist/ui/animations.ts +316 -0
  29. package/dist/ui/attach.js +13 -10
  30. package/dist/ui/attach.ts +607 -0
  31. package/dist/ui/charts.tsx +74 -0
  32. package/dist/ui/checked.d.ts +2 -2
  33. package/dist/ui/checked.ts +32 -0
  34. package/dist/ui/collector.ts +140 -0
  35. package/dist/ui/compositions.d.ts +11 -2
  36. package/dist/ui/compositions.js +283 -59
  37. package/dist/ui/compositions.ts +633 -0
  38. package/dist/ui/consent.ts +55 -0
  39. package/dist/ui/content.tsx +39 -0
  40. package/dist/ui/contrast.ts +27 -0
  41. package/dist/ui/controls.tsx +30 -0
  42. package/dist/ui/disclosure.tsx +22 -0
  43. package/dist/ui/dismiss-layer.ts +87 -0
  44. package/dist/ui/door.ts +140 -0
  45. package/dist/ui/drag.ts +316 -0
  46. package/dist/ui/elements/accordion.js +2 -2
  47. package/dist/ui/elements/accordion.tsx +47 -0
  48. package/dist/ui/elements/accordion.works.ts +66 -0
  49. package/dist/ui/elements/aspect-ratio.js +1 -1
  50. package/dist/ui/elements/aspect-ratio.tsx +30 -0
  51. package/dist/ui/elements/aspect-ratio.works.ts +5 -0
  52. package/dist/ui/elements/avatar.js +1 -1
  53. package/dist/ui/elements/avatar.tsx +33 -0
  54. package/dist/ui/elements/avatar.works.ts +16 -0
  55. package/dist/ui/elements/badge.js +1 -1
  56. package/dist/ui/elements/badge.tsx +32 -0
  57. package/dist/ui/elements/badge.works.ts +9 -0
  58. package/dist/ui/elements/bars.js +2 -2
  59. package/dist/ui/elements/bars.tsx +49 -0
  60. package/dist/ui/elements/bars.works.ts +29 -0
  61. package/dist/ui/elements/box.js +3 -2
  62. package/dist/ui/elements/box.tsx +35 -0
  63. package/dist/ui/elements/breadcrumb.js +2 -2
  64. package/dist/ui/elements/breadcrumb.tsx +37 -0
  65. package/dist/ui/elements/breadcrumb.works.ts +24 -0
  66. package/dist/ui/elements/button.js +1 -1
  67. package/dist/ui/elements/button.tsx +45 -0
  68. package/dist/ui/elements/button.works.tsx +52 -0
  69. package/dist/ui/elements/column.js +1 -1
  70. package/dist/ui/elements/column.tsx +28 -0
  71. package/dist/ui/elements/consent.js +2 -2
  72. package/dist/ui/elements/consent.tsx +70 -0
  73. package/dist/ui/elements/consent.works.tsx +132 -0
  74. package/dist/ui/elements/donut.js +2 -2
  75. package/dist/ui/elements/donut.tsx +44 -0
  76. package/dist/ui/elements/donut.works.ts +42 -0
  77. package/dist/ui/elements/each.js +1 -1
  78. package/dist/ui/elements/each.tsx +33 -0
  79. package/dist/ui/elements/each.works.tsx +82 -0
  80. package/dist/ui/elements/empty.js +1 -1
  81. package/dist/ui/elements/empty.tsx +32 -0
  82. package/dist/ui/elements/field.js +1 -1
  83. package/dist/ui/elements/field.tsx +44 -0
  84. package/dist/ui/elements/field.works.ts +65 -0
  85. package/dist/ui/elements/funnel.js +2 -2
  86. package/dist/ui/elements/funnel.tsx +49 -0
  87. package/dist/ui/elements/funnel.works.ts +37 -0
  88. package/dist/ui/elements/gauge.js +1 -1
  89. package/dist/ui/elements/gauge.tsx +39 -0
  90. package/dist/ui/elements/gauge.works.ts +42 -0
  91. package/dist/ui/elements/glyph.js +1 -1
  92. package/dist/ui/elements/glyph.tsx +29 -0
  93. package/dist/ui/elements/glyph.works.tsx +42 -0
  94. package/dist/ui/elements/grid.js +1 -1
  95. package/dist/ui/elements/grid.tsx +28 -0
  96. package/dist/ui/elements/heatmap.js +2 -2
  97. package/dist/ui/elements/heatmap.tsx +47 -0
  98. package/dist/ui/elements/heatmap.works.ts +24 -0
  99. package/dist/ui/elements/hit-box.js +1 -1
  100. package/dist/ui/elements/hit-box.tsx +46 -0
  101. package/dist/ui/elements/hit-box.works.tsx +576 -0
  102. package/dist/ui/elements/image.js +1 -1
  103. package/dist/ui/elements/image.tsx +28 -0
  104. package/dist/ui/elements/line-chart.js +2 -2
  105. package/dist/ui/elements/line-chart.tsx +44 -0
  106. package/dist/ui/elements/line-chart.works.ts +41 -0
  107. package/dist/ui/elements/link.js +1 -1
  108. package/dist/ui/elements/link.tsx +37 -0
  109. package/dist/ui/elements/link.works.ts +25 -0
  110. package/dist/ui/elements/media.js +1 -1
  111. package/dist/ui/elements/media.tsx +56 -0
  112. package/dist/ui/elements/menu.js +2 -2
  113. package/dist/ui/elements/menu.tsx +50 -0
  114. package/dist/ui/elements/menu.works.tsx +153 -0
  115. package/dist/ui/elements/money.js +1 -1
  116. package/dist/ui/elements/money.tsx +28 -0
  117. package/dist/ui/elements/money.works.ts +9 -0
  118. package/dist/ui/elements/pagination.js +2 -2
  119. package/dist/ui/elements/pagination.tsx +38 -0
  120. package/dist/ui/elements/pagination.works.ts +20 -0
  121. package/dist/ui/elements/progress.js +1 -1
  122. package/dist/ui/elements/progress.tsx +33 -0
  123. package/dist/ui/elements/progress.works.ts +8 -0
  124. package/dist/ui/elements/radio-group.js +2 -2
  125. package/dist/ui/elements/radio-group.tsx +49 -0
  126. package/dist/ui/elements/radio-group.works.ts +33 -0
  127. package/dist/ui/elements/row.js +1 -1
  128. package/dist/ui/elements/row.tsx +28 -0
  129. package/dist/ui/elements/scatter.js +1 -1
  130. package/dist/ui/elements/scatter.tsx +41 -0
  131. package/dist/ui/elements/scatter.works.ts +38 -0
  132. package/dist/ui/elements/select.js +2 -2
  133. package/dist/ui/elements/select.tsx +42 -0
  134. package/dist/ui/elements/select.works.ts +5 -0
  135. package/dist/ui/elements/separator.js +1 -1
  136. package/dist/ui/elements/separator.tsx +30 -0
  137. package/dist/ui/elements/skeleton.js +1 -1
  138. package/dist/ui/elements/skeleton.tsx +30 -0
  139. package/dist/ui/elements/slider.js +1 -1
  140. package/dist/ui/elements/slider.tsx +33 -0
  141. package/dist/ui/elements/slider.works.ts +5 -0
  142. package/dist/ui/elements/sparkline.js +1 -1
  143. package/dist/ui/elements/sparkline.tsx +36 -0
  144. package/dist/ui/elements/sparkline.works.ts +32 -0
  145. package/dist/ui/elements/spinner.js +1 -1
  146. package/dist/ui/elements/spinner.tsx +32 -0
  147. package/dist/ui/elements/stack.js +1 -1
  148. package/dist/ui/elements/stack.tsx +28 -0
  149. package/dist/ui/elements/stat.js +1 -1
  150. package/dist/ui/elements/stat.tsx +35 -0
  151. package/dist/ui/elements/stat.works.ts +14 -0
  152. package/dist/ui/elements/surface.js +1 -1
  153. package/dist/ui/elements/surface.tsx +35 -0
  154. package/dist/ui/elements/surface.works.ts +9 -0
  155. package/dist/ui/elements/table.js +2 -2
  156. package/dist/ui/elements/table.tsx +61 -0
  157. package/dist/ui/elements/table.works.ts +30 -0
  158. package/dist/ui/elements/tabs.js +2 -2
  159. package/dist/ui/elements/tabs.tsx +47 -0
  160. package/dist/ui/elements/tabs.works.ts +84 -0
  161. package/dist/ui/elements/text.js +1 -1
  162. package/dist/ui/elements/text.tsx +32 -0
  163. package/dist/ui/elements/textarea.js +1 -1
  164. package/dist/ui/elements/textarea.tsx +37 -0
  165. package/dist/ui/elements/textarea.works.ts +5 -0
  166. package/dist/ui/elements/time.js +1 -1
  167. package/dist/ui/elements/time.tsx +34 -0
  168. package/dist/ui/elements/time.works.ts +25 -0
  169. package/dist/ui/elements/toggle.js +1 -1
  170. package/dist/ui/elements/toggle.tsx +33 -0
  171. package/dist/ui/elements/toggle.works.ts +5 -0
  172. package/dist/ui/elements/tooltip.js +1 -1
  173. package/dist/ui/elements/tooltip.tsx +39 -0
  174. package/dist/ui/elements/tooltip.works.ts +77 -0
  175. package/dist/ui/elements/value.js +1 -1
  176. package/dist/ui/elements/value.tsx +30 -0
  177. package/dist/ui/elements/value.works.ts +9 -0
  178. package/dist/ui/elements.ts +127 -0
  179. package/dist/ui/focus-scope.ts +121 -0
  180. package/dist/ui/fonts.ts +355 -0
  181. package/dist/ui/generators/dev.js +2 -1
  182. package/dist/ui/generators/dev.ts +80 -0
  183. package/dist/ui/generators/elements.d.ts +1 -11
  184. package/dist/ui/generators/elements.js +44 -14
  185. package/dist/ui/generators/elements.ts +794 -0
  186. package/dist/ui/generators/i18n.js +2 -3
  187. package/dist/ui/generators/i18n.ts +300 -0
  188. package/dist/ui/generators/icons.js +3 -12
  189. package/dist/ui/generators/icons.ts +214 -0
  190. package/dist/ui/generators/react.js +13 -5
  191. package/dist/ui/generators/react.ts +269 -0
  192. package/dist/ui/generators/routes.d.ts +1 -0
  193. package/dist/ui/generators/routes.js +99 -83
  194. package/dist/ui/generators/routes.ts +743 -0
  195. package/dist/ui/generators/show.js +4 -12
  196. package/dist/ui/generators/show.ts +260 -0
  197. package/dist/ui/generators/styles.js +3 -4
  198. package/dist/ui/generators/styles.ts +669 -0
  199. package/dist/ui/generators/variants.js +2 -3
  200. package/dist/ui/generators/variants.ts +204 -0
  201. package/dist/ui/i18n/catalogs/en.ts +191 -0
  202. package/dist/ui/i18n/format.ts +221 -0
  203. package/dist/ui/i18n/locales.ts +33 -0
  204. package/dist/ui/i18n/parse.ts +315 -0
  205. package/dist/ui/i18n/translator.ts +31 -0
  206. package/dist/ui/i18n/types.ts +96 -0
  207. package/dist/ui/icons.ts +331 -0
  208. package/dist/ui/islands/map.ts +58 -0
  209. package/dist/ui/localizations.ts +75 -0
  210. package/dist/ui/material.ts +236 -0
  211. package/dist/ui/materials/mat_bordered.ts +13 -0
  212. package/dist/ui/materials/mat_ceramic.ts +13 -0
  213. package/dist/ui/materials/mat_clay.ts +13 -0
  214. package/dist/ui/materials/mat_elevated.ts +24 -0
  215. package/dist/ui/materials/mat_flat.ts +34 -0
  216. package/dist/ui/materials/mat_glass.ts +20 -0
  217. package/dist/ui/materials/mat_lit.ts +13 -0
  218. package/dist/ui/materials/mat_moulded.ts +11 -0
  219. package/dist/ui/materials.js +2 -3
  220. package/dist/ui/materials.ts +205 -0
  221. package/dist/ui/modes.ts +44 -0
  222. package/dist/ui/navigation.tsx +32 -0
  223. package/dist/ui/positioning.ts +90 -0
  224. package/dist/ui/presented.tsx +119 -0
  225. package/dist/ui/provider.d.ts +2 -0
  226. package/dist/ui/provider.js +7 -1
  227. package/dist/ui/provider.tsx +182 -0
  228. package/dist/ui/render-loop.ts +133 -0
  229. package/dist/ui/roving-focus.ts +161 -0
  230. package/dist/ui/screens.js +22 -22
  231. package/dist/ui/screens.ts +141 -0
  232. package/dist/ui/scroll-lock.ts +28 -0
  233. package/dist/ui/series.ts +97 -0
  234. package/dist/ui/signals.ts +386 -0
  235. package/dist/ui/styleguide.ts +231 -0
  236. package/dist/ui/styleguides.ts +374 -0
  237. package/dist/ui/themes.ts +22 -0
  238. package/dist/ui/token.js +1 -1
  239. package/dist/ui/token.ts +78 -0
  240. package/dist/ui/tokens/shadow.ts +25 -0
  241. package/dist/ui/tokens.js +1 -2
  242. package/dist/ui/tokens.ts +234 -0
  243. package/dist/ui/validators.ts +232 -0
  244. package/dist/ui/variant.d.ts +1 -0
  245. package/dist/ui/variant.js +3 -0
  246. package/dist/ui/variant.ts +352 -0
  247. package/dist/ui/variants/var_avatar-round.ts +14 -0
  248. package/dist/ui/variants/var_bubble-me.ts +14 -0
  249. package/dist/ui/variants/var_bubble-them.ts +13 -0
  250. package/dist/ui/variants/var_button-border.ts +76 -0
  251. package/dist/ui/variants/var_button-cta.ts +76 -0
  252. package/dist/ui/variants/var_button-destructive-ghost.ts +72 -0
  253. package/dist/ui/variants/var_button-destructive.ts +76 -0
  254. package/dist/ui/variants/var_button-fill.ts +76 -0
  255. package/dist/ui/variants/var_button-ghost.ts +72 -0
  256. package/dist/ui/variants/var_button-glass.ts +55 -0
  257. package/dist/ui/variants/var_button-normal.ts +76 -0
  258. package/dist/ui/variants/var_button-quiet.ts +74 -0
  259. package/dist/ui/variants/var_card.ts +17 -0
  260. package/dist/ui/variants/var_chip.ts +13 -0
  261. package/dist/ui/variants/var_choice.ts +15 -0
  262. package/dist/ui/variants/var_framed.ts +10 -0
  263. package/dist/ui/variants/var_glyph-plain.ts +11 -0
  264. package/dist/ui/variants/var_input.ts +43 -0
  265. package/dist/ui/variants/var_link-inline.ts +29 -0
  266. package/dist/ui/variants/var_list-row.ts +34 -0
  267. package/dist/ui/variants/var_rule.ts +10 -0
  268. package/dist/ui/variants/var_skeleton-block.ts +12 -0
  269. package/dist/ui/variants/var_spinner-turning.ts +12 -0
  270. package/dist/ui/variants/var_stat-tile.ts +13 -0
  271. package/dist/ui/variants/var_tab-bar.ts +15 -0
  272. package/dist/ui/variants/var_tap-target.ts +25 -0
  273. package/dist/ui/variants.ts +64 -0
  274. package/dist/ui/wrappers.d.ts +4 -1
  275. package/dist/ui/wrappers.js +60 -20
  276. package/dist/ui/wrappers.tsx +426 -0
  277. package/package.json +8 -2
  278. package/dist/ui/makers/message.d.ts +0 -1
  279. package/dist/ui/makers/message.js +0 -230
@@ -0,0 +1,80 @@
1
+ import { spawnSync } from 'node:child_process'
2
+ import { writeSync } from 'node:fs'
3
+ import { basename, join } from 'node:path'
4
+ import { argv } from 'node:process'
5
+
6
+ import { generators, settling } from '@prestack/thread/core/chain'
7
+ import { existsSync, readFileSync } from '@prestack/thread/core/files'
8
+ import { exit, invoked } from '@prestack/thread/core/invoked'
9
+ import { named } from '@prestack/thread/core/scope'
10
+ import { findTree } from '@prestack/thread/core/tree'
11
+
12
+ const MANIFEST = 'package.json'
13
+
14
+ const SHIP = '--ship'
15
+
16
+ const ENTRY = 'dev'
17
+
18
+ const SHIPPED = 'build'
19
+
20
+ const say = (line: string): void => {
21
+ writeSync(1, line)
22
+ }
23
+
24
+ interface Manifest {
25
+ readonly scripts?: Record<string, string>
26
+ }
27
+
28
+ export function declared(at: string, entry: string, read: (where: string) => string | undefined): string | undefined {
29
+ const source = read(join(at, MANIFEST))
30
+ if (source === undefined) return undefined
31
+ return (JSON.parse(source) as Manifest).scripts?.[entry]
32
+ }
33
+
34
+ export function unrunnable(entry: string, said: string | undefined): string | undefined {
35
+ if (said !== undefined) return undefined
36
+ return (
37
+ `this app's ${MANIFEST} declares no \`${entry}\` script, so there is nothing here to run. ` +
38
+ `\`thread attach ${named('integrity')}\` is what writes it, along with the \`thread gate\` hook that ` +
39
+ 'stands in front of it — run the attach and try again.'
40
+ )
41
+ }
42
+
43
+ async function run(): Promise<number> {
44
+ const tree = findTree()
45
+ const shipping = argv.includes(SHIP)
46
+ const entry = shipping ? SHIPPED : ENTRY
47
+ const read = (where: string): string | undefined => (existsSync(where) ? readFileSync(where, 'utf8') : undefined)
48
+
49
+ const refused = unrunnable(entry, declared(tree.at, entry, read))
50
+ if (refused !== undefined) {
51
+ say(`thread: ${refused}\n`)
52
+ return 1
53
+ }
54
+
55
+ const settled = settling(tree.at, await generators(tree))
56
+ for (const said of settled.ran) if (said.trim() !== '') say(`${said}\n`)
57
+
58
+ if (settled.unsettled.length > 0) {
59
+ say(
60
+ `thread: ${settled.unsettled.join(', ')} would not settle after ${String(settled.rounds)} rounds, ` +
61
+ 'so what this tree declares and what is written from it still disagree. Nothing is served over that.\n',
62
+ )
63
+ return 1
64
+ }
65
+
66
+ say(`thread: ${basename(tree.at)} settled in ${String(settled.rounds)} round(s); running \`${entry}\`\n`)
67
+
68
+ const extra = argv.slice(2).filter((one) => one !== SHIP)
69
+ const held = spawnSync('npm', ['run', entry, ...(extra.length === 0 ? [] : ['--', ...extra])], {
70
+ cwd: tree.at,
71
+ stdio: 'inherit',
72
+ })
73
+ if (held.error !== undefined) {
74
+ say(`thread: could not start \`npm run ${entry}\` — ${held.error.message}\n`)
75
+ return 1
76
+ }
77
+ return held.status ?? 1
78
+ }
79
+
80
+ if (invoked(import.meta.url)) exit(await run())
@@ -17,15 +17,5 @@ export declare function translated(name: string, tag: string | Readonly<Record<s
17
17
  }, carries?: Readonly<Record<string, string>>, always?: readonly string[], places?: Readonly<Record<string, Readonly<Record<string, string>>>>, works?: string, measures?: readonly string[], reads?: string, gives?: readonly string[], keeps?: boolean, animates?: boolean, says?: string, called?: string, wires?: string, dresses?: string): string;
18
18
  export declare const CARRIES: readonly string[];
19
19
  export declare const READINGS: readonly string[];
20
- export declare const APP: {
21
- readonly wrappers: `${string}/wrappers`;
22
- readonly content: `${string}/content`;
23
- readonly rows: `${string}/charts`;
24
- readonly validators: `${string}/validators`;
25
- readonly fonts: `${string}/fonts`;
26
- readonly map: `${string}/islands/map`;
27
- readonly parts: `${string}/disclosure`;
28
- readonly consent: `${string}/consent`;
29
- readonly drag: `${string}/drag`;
30
- };
31
20
  export declare const declared: Set<string>;
21
+ export declare const wears: Map<string, Readonly<Record<string, string>>>;
@@ -6,14 +6,13 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
6
6
  }
7
7
  return path;
8
8
  };
9
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
9
+ import { existsSync, readFileSync, writeFileSync } from "@prestack/thread/core/files";
10
10
  import { join, resolve } from 'node:path';
11
11
  import { argv, stdout } from 'node:process';
12
12
  import { fileURLToPath, pathToFileURL } from 'node:url';
13
13
  import { exit, invoked } from "@prestack/thread/core/invoked";
14
- import { named as packageOf } from "@prestack/thread/core/scope";
15
14
  import { findTree, inTree } from "@prestack/thread/core/tree";
16
- import { classOfElement, looking } from "../variant.js";
15
+ import { camel, classOf, classOfElement, looking } from "../variant.js";
17
16
  const idOf = (name) => name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
18
17
  export function pascal(id) {
19
18
  return id
@@ -39,6 +38,10 @@ export function owned(body, rows) {
39
38
  }
40
39
  export function translated(name, tag, arranges, raises, from, carries = {}, always = [], places = {}, works, measures = [], reads, gives = [], keeps = false, animates = false, says, called, wires, dresses) {
41
40
  const made = pascal(name);
41
+ const dressing = wears.get(name);
42
+ if (dressing === undefined) {
43
+ throw new Error(`\`${name}\` is written before the variant rows that wear it were read, so it would ship wearing none of them`);
44
+ }
42
45
  const invoking = [
43
46
  ...(carries['dispatch'] === undefined ? [' readonly dispatch?: string'] : []),
44
47
  ...(carries['input'] === undefined ? [' readonly input?: Readonly<Record<string, unknown>>'] : []),
@@ -184,7 +187,7 @@ export function translated(name, tag, arranges, raises, from, carries = {}, alwa
184
187
  'reorders. Name the field with `by`, or state `keyed: \'position\'` where position IS identity.');
185
188
  }
186
189
  return (`${pad}{props.${over}.map((${`each${String(rows.length)}`}, at) => (\n` +
187
- `${region(place, depth + 2, [...rows, `each${String(rows.length)}`], true).replace(`<${(places[place] ?? {})['tag'] ?? 'span'}`, `<${(places[place] ?? {})['tag'] ?? 'span'} key={at}`)}\n` +
190
+ `${region(place, depth + 2, [...rows, `each${String(rows.length)}`], true).replace(`<${as}`, `<${as} key={at}`)}\n` +
188
191
  `${pad}))}`);
189
192
  }
190
193
  return (`${pad}<Each rows={${carries[over] === undefined ? `${over}(props${keeps ? ', kept' : ''})` : `props.${over}`}} by={${carries[by] === undefined ? `'${by}'` : `props.${by}`}}>\n` +
@@ -290,9 +293,8 @@ export function translated(name, tag, arranges, raises, from, carries = {}, alwa
290
293
  ...always.map((one) => ` '${one}' as const,`),
291
294
  ...raises.map((one) => ` ...(props.${one} === true ? ['${one}' as const] : []),`),
292
295
  ...(keeps ? [' ...(kept.holds ?? []),'] : []),
293
- ].join('\n')}\n ],`;
294
- return `/* GENERATED by thread — do not edit. Change the row and run \`thread elements\`. */
295
- 'use client'
296
+ ].join('\n')}\n ],${raises.length === 0 ? '' : `\n raises: [${raises.map((one) => `'${one}' as const`).join(', ')}],`}`;
297
+ return `'use client'
296
298
 
297
299
  ${[
298
300
  ...(arranges || stated.some(([, kind]) => KINDS[kind]?.from === 'react' || KINDS[kind]?.from === 'both')
@@ -334,6 +336,7 @@ ${keeps ? ' const kept = uses(props)\n' : ''} const surface = useSurface({
334
336
  )
335
337
  },
336
338
  '${classOfElement(name)}',
339
+ ${JSON.stringify(dressing)},
337
340
  )
338
341
  `;
339
342
  }
@@ -424,17 +427,30 @@ const READS = {
424
427
  };
425
428
  export const CARRIES = Object.keys(KINDS);
426
429
  export const READINGS = Object.keys(READS);
427
- const UI = packageOf('ui');
428
- export const APP = { wrappers: `${UI}/wrappers`, content: `${UI}/content`, rows: `${UI}/charts`, validators: `${UI}/validators`, fonts: `${UI}/fonts`, map: `${UI}/islands/map`, parts: `${UI}/disclosure`, consent: `${UI}/consent`, drag: `${UI}/drag` };
429
- const OWN = { wrappers: '../wrappers.tsx', content: '../content.tsx', rows: '../charts.tsx', validators: '../validators.ts', fonts: '../fonts.ts', map: '../islands/map.ts', parts: '../disclosure.tsx', consent: '../consent.ts', drag: '../drag.ts' };
430
+ const BESIDE = { wrappers: '../wrappers.tsx', content: '../content.tsx', rows: '../charts.tsx', validators: '../validators.ts', fonts: '../fonts.ts', map: '../islands/map.ts', parts: '../disclosure.tsx', consent: '../consent.ts', drag: '../drag.ts' };
430
431
  export const declared = new Set();
432
+ export const wears = new Map();
431
433
  const SHEET = `elements.${'ts'}`;
432
434
  const BY = 'thread elements';
433
435
  const INSTALLED = 'node_' + 'modules/';
434
436
  function derived(row, own) {
437
+ if (typeof row.at !== 'string' || row.at.startsWith(INSTALLED))
438
+ return false;
435
439
  if ((row.derives ?? []).some((one) => one.by === BY && one.at === row.at))
436
440
  return true;
437
- return !own && typeof row.at === 'string' && !row.at.startsWith(INSTALLED);
441
+ return own ? row.by === BY : true;
442
+ }
443
+ const VARIANTS_SHEET = `variants.${'ts'}`;
444
+ async function variants(own) {
445
+ if (own) {
446
+ const held = (await import(__rewriteRelativeImportExtension(pathToFileURL(resolve(fileURLToPath(import.meta.url), '../..', VARIANTS_SHEET)).href)));
447
+ return held.VARIANTS?.declares ?? [];
448
+ }
449
+ const at = inTree(findTree(), VARIANTS_SHEET);
450
+ if (!existsSync(at))
451
+ return [];
452
+ const held = (await import(__rewriteRelativeImportExtension(pathToFileURL(at).href)));
453
+ return held.VARIANT?.declares ?? [];
438
454
  }
439
455
  async function run() {
440
456
  const own = argv.includes('--own');
@@ -442,19 +458,33 @@ async function run() {
442
458
  ? (await import(__rewriteRelativeImportExtension(pathToFileURL(resolve(fileURLToPath(import.meta.url), '../../elements.ts')).href)))
443
459
  : undefined;
444
460
  const tree = own ? undefined : findTree();
461
+ if (tree !== undefined && !existsSync(inTree(tree, SHEET))) {
462
+ stdout.write(`thread: this tree has no ${tree.name}/${SHEET}, so it declares no element and there is nothing to write or check.\n`);
463
+ return 0;
464
+ }
445
465
  const sheet = tree === undefined
446
466
  ? { ELEMENT: held?.ELEMENTS }
447
467
  : (await import(__rewriteRelativeImportExtension(pathToFileURL(inTree(tree, SHEET)).href)));
448
468
  if (sheet.ELEMENT === undefined) {
449
469
  stdout.write(own
450
- ? 'elements: packages/ui/src/elements.ts exports no `ELEMENTS`.\n'
470
+ ? 'elements: thread/ui/elements.ts exports no `ELEMENTS`.\n'
451
471
  : `thread: ${String(tree?.name)}/${SHEET} exports no \`ELEMENT\`, so nothing declares an element here.\n`);
452
472
  return 1;
453
473
  }
454
- const root = own ? resolve(fileURLToPath(import.meta.url), '../../../../..') : (tree?.at ?? '');
455
- const from = own ? OWN : APP;
474
+ const root = findTree().at;
475
+ const from = BESIDE;
456
476
  for (const one of sheet.ELEMENT.declares ?? [])
457
477
  declared.add(one.id);
478
+ const dressed = await variants(own);
479
+ for (const one of sheet.ELEMENT.declares ?? []) {
480
+ const held = {};
481
+ for (const row of dressed) {
482
+ if (!row.wears.includes(pascal(one.id)))
483
+ continue;
484
+ held[camel(row.id)] = classOf(row.id);
485
+ }
486
+ wears.set(one.id, held);
487
+ }
458
488
  const rows = (sheet.ELEMENT.declares ?? []).filter((row) => derived(row, own));
459
489
  const checking = argv.includes('--check');
460
490
  for (const row of rows) {