@estiva-app/ui 0.32.0 → 0.34.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 (103) hide show
  1. package/README.md +13 -1
  2. package/dist/AttachmentCard.d.ts.map +1 -1
  3. package/dist/Button.d.ts.map +1 -1
  4. package/dist/Card.d.ts.map +1 -1
  5. package/dist/Chip.d.ts.map +1 -1
  6. package/dist/ChipInput.d.ts.map +1 -1
  7. package/dist/CommandPalette.d.ts.map +1 -1
  8. package/dist/DialogShell.d.ts.map +1 -1
  9. package/dist/Lightbox.d.ts.map +1 -1
  10. package/dist/Menu.d.ts.map +1 -1
  11. package/dist/NavItem.d.ts.map +1 -1
  12. package/dist/PersonTrigger.d.ts.map +1 -1
  13. package/dist/Reaction.d.ts.map +1 -1
  14. package/dist/SearchInput.d.ts.map +1 -1
  15. package/dist/SectionLabel.d.ts +9 -2
  16. package/dist/SectionLabel.d.ts.map +1 -1
  17. package/dist/Select.d.ts.map +1 -1
  18. package/dist/TextInput.d.ts.map +1 -1
  19. package/dist/Textarea.d.ts.map +1 -1
  20. package/dist/Tooltip.d.ts.map +1 -1
  21. package/dist/eslint/index.d.ts +4 -0
  22. package/dist/eslint/index.d.ts.map +1 -1
  23. package/dist/eslint/index.js +449 -28
  24. package/dist/eslint/index.js.map +4 -4
  25. package/dist/eslint/looks-of.d.ts +54 -0
  26. package/dist/eslint/looks-of.d.ts.map +1 -0
  27. package/dist/eslint/no-copied-look.d.ts +3 -0
  28. package/dist/eslint/no-copied-look.d.ts.map +1 -0
  29. package/dist/eslint/no-native-title.d.ts +31 -0
  30. package/dist/eslint/no-native-title.d.ts.map +1 -0
  31. package/dist/gates/index.js +1 -1
  32. package/dist/gates/index.js.map +2 -2
  33. package/dist/index.js +171 -133
  34. package/dist/index.js.map +3 -3
  35. package/dist/looks.d.ts +34 -0
  36. package/dist/looks.d.ts.map +1 -0
  37. package/dist/registry/app-3ALZE6XO.js +10 -0
  38. package/dist/registry/app.d.ts.map +1 -1
  39. package/dist/registry/{build-LGFCCOLR.js → build-NDXMVFQ5.js} +3 -3
  40. package/dist/registry/build.d.ts.map +1 -1
  41. package/dist/registry/{chunk-XCBN2EKW.js → chunk-3WJ7ZZ7Z.js} +8 -4
  42. package/dist/registry/chunk-3WJ7ZZ7Z.js.map +7 -0
  43. package/dist/registry/{chunk-E4JNV7PC.js → chunk-PZO4BVV3.js} +2 -1
  44. package/dist/registry/chunk-PZO4BVV3.js.map +7 -0
  45. package/dist/registry/chunk-XVII7P6G.js +595 -0
  46. package/dist/registry/chunk-XVII7P6G.js.map +7 -0
  47. package/dist/registry/cli.js +3 -3
  48. package/dist/registry/index.js +3 -3
  49. package/dist/registry/schema.d.ts +8 -0
  50. package/dist/registry/schema.d.ts.map +1 -1
  51. package/package.json +1 -1
  52. package/registry.json +347 -90
  53. package/src/AttachmentCard.tsx +2 -0
  54. package/src/Button.tsx +1 -0
  55. package/src/Card.stories.tsx +2 -2
  56. package/src/Card.tsx +1 -0
  57. package/src/Chip.tsx +2 -1
  58. package/src/ChipInput.tsx +4 -2
  59. package/src/CommandPalette.tsx +2 -0
  60. package/src/ContainerHeader.stories.tsx +2 -1
  61. package/src/DialogShell.tsx +1 -0
  62. package/src/Divider.stories.tsx +12 -10
  63. package/src/Lightbox.tsx +1 -0
  64. package/src/Link.stories.tsx +5 -4
  65. package/src/Menu.tsx +3 -1
  66. package/src/NavItem.tsx +1 -0
  67. package/src/PersonTrigger.tsx +1 -0
  68. package/src/Reaction.tsx +3 -1
  69. package/src/ReactionPicker.stories.tsx +3 -2
  70. package/src/ScrollArea.stories.tsx +13 -12
  71. package/src/SearchInput.tsx +5 -4
  72. package/src/SectionLabel.mdx +4 -2
  73. package/src/SectionLabel.stories.tsx +13 -0
  74. package/src/SectionLabel.tsx +19 -2
  75. package/src/Select.tsx +6 -4
  76. package/src/TextInput.tsx +6 -6
  77. package/src/Textarea.tsx +6 -4
  78. package/src/Tooltip.mdx +1 -0
  79. package/src/Tooltip.stories.tsx +3 -2
  80. package/src/Tooltip.tsx +2 -1
  81. package/src/eslint/index.test.ts +16 -9
  82. package/src/eslint/index.ts +19 -6
  83. package/src/eslint/looks-of.ts +302 -0
  84. package/src/eslint/no-copied-look.test.ts +155 -0
  85. package/src/eslint/no-copied-look.ts +203 -0
  86. package/src/eslint/no-native-title.test.ts +67 -0
  87. package/src/eslint/no-native-title.ts +72 -0
  88. package/src/eslint/no-restyled-part.ts +1 -1
  89. package/src/gates/app-checks.ts +1 -1
  90. package/src/gates/create-app.test.ts +1 -1
  91. package/src/gates/gates.test.ts +1 -1
  92. package/src/looks.ts +42 -0
  93. package/src/registry/app.ts +3 -0
  94. package/src/registry/build.ts +8 -0
  95. package/src/registry/registry.test.ts +1 -1
  96. package/src/registry/schema.ts +9 -0
  97. package/dist/registry/app-FXN4EI34.js +0 -10
  98. package/dist/registry/chunk-E4JNV7PC.js.map +0 -7
  99. package/dist/registry/chunk-NJN4MQAM.js +0 -397
  100. package/dist/registry/chunk-NJN4MQAM.js.map +0 -7
  101. package/dist/registry/chunk-XCBN2EKW.js.map +0 -7
  102. /package/dist/registry/{app-FXN4EI34.js.map → app-3ALZE6XO.js.map} +0 -0
  103. /package/dist/registry/{build-LGFCCOLR.js.map → build-NDXMVFQ5.js.map} +0 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Looks two or more parts share, written once (UIG-25).
3
+ *
4
+ * A look typed again by hand draws the same today and drifts the day one of
5
+ * them changes: nothing fails, one screen just looks slightly off. So a look
6
+ * more than one part wears lives here, and each part takes it from here. The
7
+ * lint that finds a copied look reads a class list wherever it is written; a
8
+ * constant of classes ends in `_CLASSES`, so it is read as one.
9
+ *
10
+ * Only looks — colour, text, border, corner, shadow. Where a part sits and how
11
+ * much room it takes stay in the part.
12
+ */
13
+ /** A field's box: TextInput and Textarea. The hairline strengthens on hover; focus comes after it, so a focused field keeps its colour under the pointer. */
14
+ export declare const FIELD_BOX_CLASSES = "bg-bg-inset border border-border-default hover:border-border-strong focus:border-border-focus rounded-lg";
15
+ /** What a field's words look like, typed or waiting: TextInput, Textarea and Select. */
16
+ export declare const FIELD_TEXT_CLASSES = "text-text-primary placeholder:text-text-muted";
17
+ /** A field that cannot be used: TextInput, Textarea and Select. */
18
+ export declare const FIELD_DISABLED_CLASSES = "disabled:pointer-events-none disabled:bg-bg-disabled disabled:text-text-disabled";
19
+ /** The ring a focused field wears in Signal: TextInput and Textarea. */
20
+ export declare const FIELD_FOCUS_RING_CLASSES = "signal:transition-shadow signal:focus:shadow-focus-ring";
21
+ /** A field's two sizes, its padding and its words: TextInput, Textarea (default only) and Select. The small one is the small Select's trigger. */
22
+ export declare const FIELD_SIZE_CLASSES: {
23
+ readonly default: "px-3 py-2 text-input-value";
24
+ readonly small: "h-6 min-h-6 px-2 text-caption";
25
+ };
26
+ /** The box around an input that sits inside it, before its focus look: SearchInput and ChipInput. */
27
+ export declare const FIELD_SHELL_CLASSES = "bg-bg-inset border border-border-default hover:border-border-strong rounded-lg transition-colors";
28
+ /** A panel that floats over the page: Menu's panel and Tooltip. */
29
+ export declare const FLOATING_SURFACE_CLASSES = "rounded-lg border border-border-default bg-bg-elevated shadow-lg";
30
+ /** A chip's words: Chip's label and Reaction's count. */
31
+ export declare const CHIP_TEXT_CLASSES = "text-chip signal:font-mono signal:text-small signal:font-semibold signal:tabular-nums";
32
+ /** Words typed straight into an input with no box of its own: SearchInput and ChipInput. */
33
+ export declare const BARE_INPUT_CLASSES = "bg-transparent text-text-primary placeholder:text-text-muted outline-none";
34
+ //# sourceMappingURL=looks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"looks.d.ts","sourceRoot":"","sources":["../src/looks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,6JAA6J;AAC7J,eAAO,MAAM,iBAAiB,6GAA6G,CAAA;AAE3I,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,kDAAkD,CAAA;AAEjF,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,qFAAqF,CAAA;AAExH,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,4DAA4D,CAAA;AAEjG,kJAAkJ;AAClJ,eAAO,MAAM,kBAAkB;;;CAGrB,CAAA;AAEV,qGAAqG;AACrG,eAAO,MAAM,mBAAmB,qGAAqG,CAAA;AAErI,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,qEAAqE,CAAA;AAE1G,yDAAyD;AACzD,eAAO,MAAM,iBAAiB,0FAA0F,CAAA;AAExH,4FAA4F;AAC5F,eAAO,MAAM,kBAAkB,8EAA8E,CAAA"}
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ buildAppRegistry
4
+ } from "./chunk-3WJ7ZZ7Z.js";
5
+ import "./chunk-XVII7P6G.js";
6
+ import "./chunk-PZO4BVV3.js";
7
+ export {
8
+ buildAppRegistry
9
+ };
10
+ //# sourceMappingURL=app-3ALZE6XO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/registry/app.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAwE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAElI,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gIAAgI;IAChI,eAAe,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACjC,gIAAgI;IAChI,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC/B;AAwQD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,IAAoB,EAAE,IAAI,EAAE,eAAe,EAAE,mBAAmB,EAAE,GAAE,eAAoB,GAAG,QAAQ,CAuhBrI"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/registry/app.ts"],"names":[],"mappings":"AAwCA,OAAO,EAAwE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAElI,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gIAAgI;IAChI,eAAe,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IACjC,gIAAgI;IAChI,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC/B;AAwQD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,IAAoB,EAAE,IAAI,EAAE,eAAe,EAAE,mBAAmB,EAAE,GAAE,eAAoB,GAAG,QAAQ,CAyhBrI"}
@@ -10,8 +10,8 @@ import {
10
10
  sanitize,
11
11
  serializeRegistry,
12
12
  toId
13
- } from "./chunk-NJN4MQAM.js";
14
- import "./chunk-E4JNV7PC.js";
13
+ } from "./chunk-XVII7P6G.js";
14
+ import "./chunk-PZO4BVV3.js";
15
15
  export {
16
16
  PACKAGE_IMPORT,
17
17
  buildRegistry,
@@ -24,4 +24,4 @@ export {
24
24
  serializeRegistry,
25
25
  toId
26
26
  };
27
- //# sourceMappingURL=build-LGFCCOLR.js.map
27
+ //# sourceMappingURL=build-NDXMVFQ5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/registry/build.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,EAAuD,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAEpJ,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yCAAyC;AACzC,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,uEAAuE;AACvE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAA;CACxB;AAED,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAE9C;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7C;AAsBD,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAAiE,CAAA;AAEjH,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAa5D;AAgCD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAanD;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB/C;AAwCD,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAA;AAEnF,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAyB,EAAE,EAAE,gBAAuB,EAAE,GAAE,WAAgB;;;yBAuQ9F,EAAE,CAAC,QAAQ,GAAG,SAAS,KAAG,QAAQ;wBAOwD,MAAM;EAC7H;AAYD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAuBvF;AAeD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAoB,EAAE,IAAkB,EAAE,GAAE,YAAiB,GAAG,QAAQ,CAqGvG;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE5D"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/registry/build.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,MAAM,YAAY,CAAA;AAG3B,OAAO,EAAuD,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAEpJ,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yCAAyC;AACzC,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,uEAAuE;AACvE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAA;CACxB;AAED,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAE9C;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7C;AAsBD,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAAiE,CAAA;AAEjH,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAa5D;AAgCD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAanD;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB/C;AAwCD,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAA;AAEnF,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAyB,EAAE,EAAE,gBAAuB,EAAE,GAAE,WAAgB;;;yBAuQ9F,EAAE,CAAC,QAAQ,GAAG,SAAS,KAAG,QAAQ;wBAOwD,MAAM;EAC7H;AAYD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAuBvF;AAeD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAoB,EAAE,IAAkB,EAAE,GAAE,YAAiB,GAAG,QAAQ,CA4GvG;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE5D"}
@@ -2,14 +2,16 @@
2
2
  import {
3
3
  PACKAGE_IMPORT,
4
4
  firstSentence,
5
+ looksOf,
5
6
  pageOpening,
7
+ parseForLooks,
6
8
  readModule,
7
9
  sanitize,
8
10
  toId
9
- } from "./chunk-NJN4MQAM.js";
11
+ } from "./chunk-XVII7P6G.js";
10
12
  import {
11
13
  SCHEMA_VERSION
12
- } from "./chunk-E4JNV7PC.js";
14
+ } from "./chunk-PZO4BVV3.js";
13
15
 
14
16
  // src/registry/app.ts
15
17
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
@@ -609,7 +611,9 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
609
611
  docsId,
610
612
  storyId,
611
613
  docPage: pageText ? page : null,
612
- app: facts_
614
+ app: facts_,
615
+ // A part handed on from the package looks like the package's (UIG-25).
616
+ looks: pass ? [] : looksOf(parseForLooks(join(root, p.file), facts.get(p.file).source), [p.name]).get(p.name) ?? []
613
617
  });
614
618
  }
615
619
  if (problems.length) throw new Error(`the catalogue of ${repoName} cannot be built:
@@ -646,4 +650,4 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
646
650
  export {
647
651
  buildAppRegistry
648
652
  };
649
- //# sourceMappingURL=chunk-XCBN2EKW.js.map
653
+ //# sourceMappingURL=chunk-3WJ7ZZ7Z.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/registry/app.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\n/**\n * An app's catalogue (UIG-13): every part in an app's own code, what it is for,\n * where it is used, and which of four kinds it is.\n *\n * **Built fresh, never committed** (Katerina, 18 September 2026). The package is\n * public and Peek and Ship are private, so an app's catalogue lives nowhere but\n * in its own code: `estiva-ui find` and `estiva-ui check` build it each time,\n * which takes about a second, and `estiva-ui build` writes it to a file only\n * when asked. A file that is never kept can never drift.\n *\n * **A file is not a part, and a folder says nothing.** Peek's `components/ui`\n * holds one-line pass-ons beside 187-line components, one file can hold six\n * parts, and a part can draw nothing at all (a provider, a listener). So the\n * target set is every name an app's `.tsx` files export that is a part: a\n * function that draws, or a name drawn as a tag somewhere in the app. The kind\n * is read from the code, and only from the code:\n *\n * - **re-export** \u2014 its file only hands a package part on.\n * - **one-off** \u2014 one file of the app uses it.\n * - **reusable** \u2014 two or more do.\n * - **promote-candidate** \u2014 two or more do, and everything it uses is already in\n * the package, so it could move there as it is. Katerina rules on each.\n * - **unused** \u2014 no file of the app uses it; its stories or tests may.\n *\n * Where the count is wrong \u2014 a general part only one screen uses yet \u2014 a person\n * writes the kind beside the part, with the reason, and the catalogue shows it:\n *\n * /**\n * * A timeline of what happened to a thing.\n * * @registry reusable: general; one screen uses it so far\n * *\\/\n *\n * TypeScript is the app's own install, as it is for the package's builder.\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { basename, dirname, extname, join, relative, resolve, sep } from 'node:path'\nimport ts from 'typescript'\nimport { firstSentence, pageOpening, readModule, sanitize, toId, PACKAGE_IMPORT, type Resolved } from './build'\nimport { looksOf, parseForLooks } from '../eslint/looks-of'\nimport { SCHEMA_VERSION, type AppFacts, type EntryClass, type FileWithoutPart, type Registry, type RegistryEntry } from './schema'\n\nexport interface AppBuildOptions {\n /** The app's folder: where its `package.json` and `src/` are. Ship's is `web`. */\n root?: string\n /** The name its entries are recorded under \u2014 `peek`, `ship`. Defaults to the app's package name. */\n repo?: string\n /** The package's own catalogue, for the parts an app part shares a name with. Defaults to the one this builder ships beside. */\n packageRegistry?: Registry | null\n /** The packages the package itself depends on. An import of one never ties a part to its app. Defaults to the package's own. */\n packageDependencies?: string[]\n}\n\n/** The kinds a person may write beside a part. A pass-on is a fact about its file; so is being used nowhere. */\nconst WRITABLE: EntryClass[] = ['reusable', 'one-off', 'promote-candidate']\nconst WRITTEN = /^@registry\\s+([a-z-]+)\\s*:\\s*(.+)$/m\n\nconst isStory = (file: string) => /\\.stories\\.[cm]?[jt]sx?$/.test(file)\nconst isTest = (file: string) => /\\.(test|spec)\\.[cm]?[jt]sx?$/.test(file) || /(^|\\/)__(tests|mocks)__\\//.test(file)\nconst isPascal = (name: string) => /^[A-Z][A-Za-z0-9]*$/.test(name) && !/^[A-Z0-9_]+$/.test(name)\n/**\n * What a dynamic `import('./x')` takes from its file. Written as\n * `import('./Settings').then((m) => ({ default: m.SettingsPage }))`, only the names\n * read off the module; otherwise the whole module (`*`), whose default a caller\n * then takes.\n */\nfunction pickedFrom(call: ts.CallExpression): { imported: string; local: string }[] {\n const then = call.parent\n const invoked = then?.parent\n if (then && ts.isPropertyAccessExpression(then) && then.name.text === 'then' && invoked && ts.isCallExpression(invoked)) {\n const callback = invoked.arguments[0]\n const param = callback && (ts.isArrowFunction(callback) || ts.isFunctionExpression(callback)) ? callback.parameters[0]?.name : undefined\n if (param && ts.isIdentifier(param)) {\n const names = new Set<string>()\n const visit = (n: ts.Node) => {\n if (ts.isPropertyAccessExpression(n) && ts.isIdentifier(n.expression) && n.expression.text === param.text) names.add(n.name.text)\n ts.forEachChild(n, visit)\n }\n visit(callback)\n if (names.size) return [...names].map((imported) => ({ imported, local: '(dynamic)' }))\n }\n }\n return [{ imported: '*', local: '(dynamic)' }]\n}\n\n/**\n * `export default memo(TopicRow)`: the default is TopicRow, wrapped. A call on\n * a name, with no function written into it, hands that name out, so the export\n * is read as if it named it \u2014 one part, whose comment and props are its own.\n */\nfunction unwrapDefault<T extends { isDefault: boolean; local: string | null; node: ts.Node | null }>(ex: T): T {\n if (!ex.isDefault || ex.local || !ex.node || !ts.isExpression(ex.node)) return ex\n const name = handedOut(ex.node)\n return name ? { ...ex, local: name, node: null } : ex\n}\n\n/**\n * The name an `export default \u2026` hands out, under whatever it is wrapped in:\n * `memo(forwardRef(Row))`, `Row as ComponentType`, `Row satisfies FC`,\n * `styled(Row)\\`\u2026\\``. `null` when what is exported is written right there.\n */\nfunction handedOut(expression: ts.Expression): string | null {\n let e: ts.Expression = expression\n for (;;) {\n if (ts.isIdentifier(e)) return e.text\n if (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isSatisfiesExpression(e) || ts.isNonNullExpression(e) || ts.isTypeAssertionExpression(e)) e = e.expression\n else if (ts.isTaggedTemplateExpression(e)) e = e.tag\n else if (ts.isCallExpression(e) && e.arguments[0] && !e.arguments.some((a) => ts.isArrowFunction(a) || ts.isFunctionExpression(a))) e = e.arguments[0]\n else return null\n }\n}\n\n/** `memo-page` \u2192 `MemoPage`, `topic_view` \u2192 `TopicView`. */\nconst pascalOf = (stem: string) => stem.split(/[^A-Za-z0-9]+/).filter(Boolean).map((word) => word[0].toUpperCase() + word.slice(1)).join('')\n/** A default with no name of its own takes its file's \u2014 or, for `settings/index.tsx`, its folder's. */\nconst defaultNameOf = (file: string) => {\n const stem = basename(file, extname(file))\n return pascalOf(stem === 'index' ? basename(dirname(file)) : stem)\n}\nconst CODE = ['.tsx', '.ts', '.jsx', '.js', '.mts', '.cts']\n\n/** `@scope/name/sub` \u2192 `@scope/name`; `name/sub` \u2192 `name`. */\nfunction packageOf(specifier: string): string {\n const parts = specifier.split('/')\n return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]\n}\n\n/** What the package this builder belongs to depends on, and its catalogue. Read from beside the builder. */\nfunction packageSelf(): { dependencies: string[]; registry: Registry | null } {\n const at = (rel: string) => new URL(rel, import.meta.url)\n const manifest = JSON.parse(readFileSync(at('../../package.json'), 'utf8')) as { name: string; dependencies?: Record<string, string>; peerDependencies?: Record<string, string> }\n const registryUrl = at('../../registry.json')\n const registry = existsSync(registryUrl) ? (JSON.parse(readFileSync(registryUrl, 'utf8')) as Registry) : null\n return { dependencies: [manifest.name, ...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.peerDependencies ?? {})], registry }\n}\n\n/**\n * The import aliases an app's `tsconfig*.json` files declare \u2014 `@/*` \u2192\n * `<root>/src/*` \u2014 and the `baseUrl` folders a bare `src/Card` is read from.\n */\nfunction readAliases(root: string): { aliases: { prefix: string; target: string }[]; bases: string[] } {\n const aliases: { prefix: string; target: string }[] = []\n const bases: string[] = []\n for (const name of readdirSync(root).filter((file) => /^tsconfig.*\\.json$/.test(file)).sort()) {\n const read = ts.readConfigFile(join(root, name), ts.sys.readFile)\n const options = (read.config?.compilerOptions ?? {}) as { paths?: Record<string, string[]>; baseUrl?: string }\n const base = resolve(root, options.baseUrl ?? '.')\n if (options.baseUrl !== undefined && !bases.includes(base)) bases.push(base)\n for (const [pattern, targets] of Object.entries(options.paths ?? {})) {\n if (!pattern.endsWith('/*') || !targets[0]?.endsWith('/*')) continue\n const prefix = pattern.slice(0, -1)\n if (!aliases.some((alias) => alias.prefix === prefix)) aliases.push({ prefix, target: resolve(base, targets[0].slice(0, -2)) })\n }\n }\n return { aliases, bases }\n}\n\nfunction walk(dir: string): string[] {\n return readdirSync(dir).flatMap((name) => {\n if (name === 'node_modules' || name.startsWith('.')) return []\n const path = join(dir, name)\n return statSync(path).isDirectory() ? walk(path) : [path]\n })\n}\n\n/** One import, re-export or dynamic import of a file, resolved. */\ninterface Link {\n specifier: string\n /** An app code file, relative to the app; `null` for a package; `'?'` for anything else. */\n target: string | null\n /** `imported` name \u2192 local name; `*` for a namespace or a dynamic import. Type-only names are left out. */\n names: { imported: string; local: string }[]\n typeOnly: boolean\n kind: 'import' | 're-export' | 'dynamic'\n}\n\n/** A part a file exports, before anything is known about its use. */\ninterface Found {\n file: string\n /** The name it is exported as; a default export takes its own name, or the file's. */\n name: string\n /** The name it has inside its file, where it has one. */\n local: string | null\n defaultExport: boolean\n /** A pass-on: the package and the name it hands on. */\n from: { specifier: string; name: string } | null\n}\n\n/** Everything one file says, read once. */\ninterface FileFacts {\n file: string\n source: string\n sf: ts.SourceFile\n links: Link[]\n /** `exported name` \u2192 local name, and whether it is the default. */\n exports: { name: string; local: string | null; isDefault: boolean; node: ts.Node | null }[]\n /** Pass-ons and barrel entries: `export { A } from '\u2026'`. */\n reexports: { name: string; source: string; specifier: string; target: string | null }[]\n starFrom: { specifier: string; target: string | null }[]\n /** `export * as Parts from './parts'`: a name that stands for another file's parts. */\n namespaces: { name: string; target: string | null }[]\n /** Every name drawn as a JSX tag in this file. */\n tags: Set<string>\n /** Each imported value name \u2192 where it came from, for `import { X } from '\u2026'` then `export { X }`. */\n bindings: Map<string, { specifier: string; imported: string; target: string | null }>\n}\n\n/** Whether a node draws: JSX, or `createElement` / `createPortal`. */\nfunction draws(node: ts.Node): boolean {\n let found = false\n const visit = (n: ts.Node) => {\n if (found) return\n if (ts.isJsxElement(n) || ts.isJsxSelfClosingElement(n) || ts.isJsxFragment(n)) {\n found = true\n return\n }\n if (ts.isCallExpression(n)) {\n const callee = ts.isPropertyAccessExpression(n.expression) ? n.expression.name.text : ts.isIdentifier(n.expression) ? n.expression.text : ''\n if (callee === 'createElement' || callee === 'createPortal') {\n found = true\n return\n }\n }\n ts.forEachChild(n, visit)\n }\n visit(node)\n return found\n}\n\n/**\n * Whether a file names `local` anywhere but in `home` (its own declaration), its\n * imports and its export lines \u2014 as a tag, a value, or passed along. A property\n * name, an attribute name and a type are not uses of the part.\n */\nfunction mentions(sf: ts.SourceFile, local: string, home: ts.Node | null): boolean {\n let named = false\n const visit = (n: ts.Node) => {\n if (named) return\n if (ts.isIdentifier(n) && n.text === local) {\n const parent = n.parent\n // The name of something else that happens to be spelled the same \u2014 a\n // property of a type or a class, a member, another declaration \u2014 is not the part.\n const declares = (ts.isPropertySignature(parent) || ts.isPropertyDeclaration(parent) || ts.isMethodDeclaration(parent) || ts.isMethodSignature(parent) || ts.isGetAccessorDeclaration(parent) || ts.isSetAccessorDeclaration(parent) || ts.isEnumMember(parent) || ts.isVariableDeclaration(parent) || ts.isFunctionDeclaration(parent) || ts.isClassDeclaration(parent) || ts.isParameter(parent) || ts.isBindingElement(parent)) && (parent as { name?: ts.Node }).name === n\n const bindingKey = ts.isBindingElement(parent) && parent.propertyName === n\n const isName = declares || bindingKey || (ts.isPropertyAccessExpression(parent) && parent.name === n) || (ts.isPropertyAssignment(parent) && parent.name === n) || ts.isJsxAttribute(parent) || ts.isExportSpecifier(parent) || ts.isImportSpecifier(parent) || ts.isJsxClosingElement(parent)\n // `SlashMenu.displayName = 'SlashMenu'` sets something on the part; it does not use it.\n const configures = ts.isPropertyAccessExpression(parent) && parent.expression === n && ts.isBinaryExpression(parent.parent) && parent.parent.left === parent && parent.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken\n if (configures) {\n ts.forEachChild(n, visit)\n return\n }\n let inType = false\n for (let a: ts.Node | undefined = parent; a && a !== sf; a = a.parent) if (ts.isTypeNode(a)) inType = true\n if (!isName && !inType && !shadowed(n, local, sf)) named = true\n }\n ts.forEachChild(n, visit)\n }\n for (const s of sf.statements) {\n if (s === home || ts.isExportDeclaration(s) || ts.isImportDeclaration(s)) continue\n // `export default Row`, `memo(forwardRef(Row))`, `Row as ComponentType` hand the\n // part out; they do not use it. Anything else written into the default is code.\n if (ts.isExportAssignment(s) && handedOut(s.expression)) continue\n visit(s)\n }\n return named\n}\n\n/** Whether a binding name \u2014 `Icon`, `{ icon: Icon }`, `[Icon]` \u2014 binds `local`. */\nfunction binds(name: ts.BindingName | undefined, local: string): boolean {\n if (!name) return false\n if (ts.isIdentifier(name)) return name.text === local\n return name.elements.some((element) => !ts.isOmittedExpression(element) && binds(element.name, local))\n}\n\n/**\n * Whether `n` means something declared closer than the file: a parameter\n * (`Item({ icon: Icon }) { return <Icon /> }`), or a constant, function or class\n * of an enclosing block. That `Icon` is not the file's part called Icon.\n */\nfunction shadowed(n: ts.Node, local: string, sf: ts.SourceFile): boolean {\n for (let a: ts.Node | undefined = n.parent; a && a !== sf; a = a.parent) {\n if (ts.isFunctionLike(a)) {\n if (a.parameters.some((p) => binds(p.name, local))) return true\n if ((ts.isFunctionExpression(a) || ts.isClassExpression(a)) && a.name?.text === local) return true\n }\n if (ts.isCatchClause(a) && binds(a.variableDeclaration?.name, local)) return true\n if (ts.isBlock(a) || ts.isModuleBlock(a) || ts.isCaseClause(a) || ts.isDefaultClause(a)) {\n for (const s of a.statements) {\n if (ts.isVariableStatement(s) && s.declarationList.declarations.some((d) => binds(d.name, local))) return true\n if ((ts.isFunctionDeclaration(s) || ts.isClassDeclaration(s)) && s.name?.text === local) return true\n }\n }\n if ((ts.isForStatement(a) || ts.isForOfStatement(a) || ts.isForInStatement(a)) && a.initializer && ts.isVariableDeclarationList(a.initializer) && a.initializer.declarations.some((d) => binds(d.name, local))) return true\n }\n return false\n}\n\n/**\n * The thing a declaration holds, if it is a function, a class, or a call that\n * wraps one (`forwardRef`, `memo`) \u2014 as a constant, or written straight into\n * `export default \u2026`.\n */\nfunction drawingBody(node: ts.Node): ts.Node | null {\n if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) return node\n const init = ts.isVariableDeclaration(node) ? node.initializer : ts.isExpression(node) ? node : undefined\n if (!init) return null\n if (ts.isArrowFunction(init) || ts.isFunctionExpression(init) || ts.isClassExpression(init)) return init\n if (ts.isCallExpression(init)) {\n const callee = init.expression.getText()\n if (/(^|\\.)createContext$/.test(callee)) return null\n if (init.arguments.some((a) => ts.isArrowFunction(a) || ts.isFunctionExpression(a))) return init\n }\n return null\n}\n\n/**\n * Read one app and return its catalogue.\n *\n * Throws on anything it cannot explain, with every problem at once: a part with\n * no purpose, a written kind it does not know. A catalogue that quietly drops\n * what it could not read would answer \"we have nothing for that\" when the\n * truth is \"the builder gave up\".\n */\nexport function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, packageDependencies }: AppBuildOptions = {}): Registry {\n const app = resolve(root)\n const src = join(app, 'src')\n if (!existsSync(src)) throw new Error(`${app} has no src/ folder: estiva-ui reads an app's parts from src/`)\n const manifest = JSON.parse(readFileSync(join(app, 'package.json'), 'utf8')) as { name?: string; version?: string; scripts?: Record<string, string> }\n const self = packageRegistry === undefined || packageDependencies === undefined ? packageSelf() : null\n const theRegistry = packageRegistry === undefined ? (self?.registry ?? null) : packageRegistry\n const allowed = new Set(packageDependencies ?? self?.dependencies ?? [])\n const repoName = repo ?? manifest.name ?? basename(app)\n const { aliases, bases } = readAliases(app)\n const rel = (abs: string) => relative(app, abs).split(sep).join('/')\n\n const files = walk(src)\n .filter((path) => CODE.includes(extname(path)) && !path.endsWith('.d.ts'))\n .map(rel)\n .sort()\n const known = new Set(files)\n\n /** Where an import points: an app code file, a package (`null`), or something else (`'?'`). */\n const resolveSpecifier = (from: string, specifier: string): string | null => {\n let base: string | null = null\n if (specifier.startsWith('.')) base = resolve(app, dirname(from), specifier)\n else {\n const alias = aliases.find((a) => specifier.startsWith(a.prefix))\n if (alias) base = join(alias.target, specifier.slice(alias.prefix.length))\n }\n const lookUp = (at: string): string | null => {\n const stem = at.replace(/\\.(js|jsx)$/, '')\n for (const candidate of [at, ...CODE.map((e) => stem + e), ...CODE.map((e) => join(at, `index${e}`))]) {\n const r = rel(candidate)\n if (known.has(r)) return r\n }\n return null\n }\n if (base === null) {\n // A bare `src/Card` is the app's own when its tsconfig's baseUrl says so; otherwise a package.\n for (const folder of bases) {\n const hit = lookUp(join(folder, specifier))\n if (hit) return hit\n }\n return null\n }\n return lookUp(base) ?? '?'\n }\n\n // \u2500\u2500 Read every file once \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const facts = new Map<string, FileFacts>()\n for (const file of files) {\n const source = readFileSync(join(app, file), 'utf8')\n const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, /x$/.test(file) ? ts.ScriptKind.TSX : ts.ScriptKind.TS)\n const links: Link[] = []\n const exports: FileFacts['exports'] = []\n const reexports: FileFacts['reexports'] = []\n const starFrom: FileFacts['starFrom'] = []\n const namespaces: FileFacts['namespaces'] = []\n for (const statement of sf.statements) {\n if (ts.isImportDeclaration(statement)) {\n if (!ts.isStringLiteral(statement.moduleSpecifier)) continue\n const specifier = statement.moduleSpecifier.text\n const clause = statement.importClause\n const names: Link['names'] = []\n if (clause && !clause.isTypeOnly) {\n if (clause.name) names.push({ imported: 'default', local: clause.name.text })\n const bindings = clause.namedBindings\n if (bindings && ts.isNamedImports(bindings)) for (const e of bindings.elements) if (!e.isTypeOnly) names.push({ imported: (e.propertyName ?? e.name).text, local: e.name.text })\n if (bindings && ts.isNamespaceImport(bindings)) names.push({ imported: '*', local: bindings.name.text })\n }\n links.push({ specifier, target: resolveSpecifier(file, specifier), names, typeOnly: !!clause?.isTypeOnly || (clause !== undefined && names.length === 0 && !!clause.namedBindings), kind: 'import' })\n continue\n }\n if (ts.isExportDeclaration(statement)) {\n const specifier = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null\n if (specifier === null) {\n if (!statement.isTypeOnly && statement.exportClause && ts.isNamedExports(statement.exportClause)) {\n // `export { Page as default }` is the file's default, named Page.\n for (const e of statement.exportClause.elements) if (!e.isTypeOnly) exports.push({ name: e.name.text, local: (e.propertyName ?? e.name).text, isDefault: e.name.text === 'default', node: null })\n }\n continue\n }\n const target = resolveSpecifier(file, specifier)\n links.push({ specifier, target, names: [], typeOnly: statement.isTypeOnly, kind: 're-export' })\n if (statement.isTypeOnly) continue\n if (!statement.exportClause) starFrom.push({ specifier, target })\n else if (ts.isNamedExports(statement.exportClause)) {\n for (const e of statement.exportClause.elements) if (!e.isTypeOnly) reexports.push({ name: e.name.text, source: (e.propertyName ?? e.name).text, specifier, target })\n } else if (ts.isNamespaceExport(statement.exportClause)) {\n // `export * as Parts from './parts'`: a caller's `Parts.Card` is the parts file's Card.\n namespaces.push({ name: statement.exportClause.name.text, target })\n }\n continue\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n const e = statement.expression\n exports.push({ name: 'default', local: ts.isIdentifier(e) ? e.text : null, isDefault: true, node: ts.isIdentifier(e) ? null : e })\n continue\n }\n const mods = ts.canHaveModifiers(statement) ? (ts.getModifiers(statement) ?? []) : []\n if (!mods.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) continue\n const isDefault = mods.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)\n // An overload's signature is not a part of its own: the part is the one with a body.\n if (ts.isFunctionDeclaration(statement) && !statement.body) continue\n if (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) {\n exports.push({ name: isDefault ? 'default' : (statement.name?.text ?? 'default'), local: statement.name?.text ?? null, isDefault, node: statement })\n } else if (ts.isVariableStatement(statement)) {\n for (const d of statement.declarationList.declarations) if (ts.isIdentifier(d.name)) exports.push({ name: d.name.text, local: d.name.text, isDefault: false, node: d })\n }\n }\n const tags = new Set<string>()\n const visit = (n: ts.Node) => {\n if (ts.isCallExpression(n) && n.expression.kind === ts.SyntaxKind.ImportKeyword && n.arguments[0] && ts.isStringLiteralLike(n.arguments[0])) {\n const specifier = n.arguments[0].text\n links.push({ specifier, target: resolveSpecifier(file, specifier), names: pickedFrom(n), typeOnly: false, kind: 'dynamic' })\n }\n if ((ts.isJsxOpeningElement(n) || ts.isJsxSelfClosingElement(n)) && ts.isIdentifier(n.tagName)) tags.add(n.tagName.text)\n ts.forEachChild(n, visit)\n }\n visit(sf)\n const bindings: FileFacts['bindings'] = new Map()\n for (const link of links) if (link.kind === 'import') for (const n of link.names) if (n.imported !== '*') bindings.set(n.local, { specifier: link.specifier, imported: n.imported, target: link.target })\n facts.set(file, { file, source, sf, links, exports, reexports, starFrom, namespaces, tags, bindings })\n }\n\n const drawnAnywhere = new Set<string>()\n for (const f of facts.values()) for (const tag of f.tags) drawnAnywhere.add(tag)\n\n /** A top-level declaration of a file, by its local name. */\n const declarationOf = (f: FileFacts, local: string): ts.Node | null => {\n for (const s of f.sf.statements) {\n // Past an overload's signature, to the function with a body.\n if (ts.isFunctionDeclaration(s) && s.name?.text === local && !s.body) continue\n if ((ts.isFunctionDeclaration(s) || ts.isClassDeclaration(s)) && s.name?.text === local) return s\n if (ts.isVariableStatement(s)) for (const d of s.declarationList.declarations) if (ts.isIdentifier(d.name) && d.name.text === local) return d\n }\n return null\n }\n\n // \u2500\u2500 The parts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const problems: string[] = []\n const found: Found[] = []\n const targets = files.filter((file) => file.endsWith('.tsx') && !isStory(file) && !isTest(file))\n for (const file of targets) {\n const f = facts.get(file)!\n for (const written of f.exports) {\n const ex = unwrapDefault(written)\n // `export default memo(Avatar)` with Avatar imported: not Avatar handed on, but a\n // new part of this file that wraps it, named after the file.\n // Only a name that is a part's: `createBrowserRouter(routes)` hands out no part.\n if (ex !== written && ex.local && isPascal(ex.local) && !declarationOf(f, ex.local) && f.bindings.has(ex.local)) {\n found.push({ file, name: defaultNameOf(file), local: null, defaultExport: true, from: null })\n continue\n }\n // `export function App` and `export default App` \u2014 or `export default memo(App)`: one part, not two.\n if (ex.isDefault && ex.local && f.exports.some((other) => !other.isDefault && other.local === ex.local)) continue\n const node = ex.node ?? (ex.local ? declarationOf(f, ex.local) : null)\n // A default with no name of its own takes its file's, as a name: `memo-page.tsx` \u2192 MemoPage.\n const own = ex.local ?? (ex.isDefault ? defaultNameOf(file) : ex.name)\n const name = ex.isDefault ? own : ex.name\n if (!isPascal(name)) continue\n // `import { SkeletonBar } from '@estiva-app/ui'` and later `export { SkeletonBar }`:\n // handed on, exactly as `export { SkeletonBar } from '@estiva-app/ui'` is.\n // From another file of the app it is a barrel, and the part is listed there.\n const bound = node === null && ex.local ? f.bindings.get(ex.local) : undefined\n if (bound) {\n if (bound.target === null) found.push({ file, name, local: null, defaultExport: ex.isDefault, from: { specifier: bound.specifier, name: bound.imported } })\n continue\n }\n // `export const SkeletonSidebarList = SkeletonList`, SkeletonList imported: the\n // package's part under a second name, handed on. From an app file, a barrel.\n const alias = node && ts.isVariableDeclaration(node) && node.initializer && ts.isIdentifier(node.initializer) ? f.bindings.get(node.initializer.text) : undefined\n if (alias) {\n if (alias.target === null) found.push({ file, name, local: null, defaultExport: ex.isDefault, from: { specifier: alias.specifier, name: alias.imported } })\n continue\n }\n const body = node ? drawingBody(node) : null\n const isPart = (body !== null && draws(body)) || drawnAnywhere.has(ex.local ?? name)\n if (isPart) found.push({ file, name, local: ex.local, defaultExport: ex.isDefault, from: null })\n }\n for (const re of f.reexports) {\n // Handing on another file of the app is a barrel: the part is listed where it is written.\n if (re.target !== null || !isPascal(re.name)) continue\n found.push({ file, name: re.name, local: null, defaultExport: false, from: { specifier: re.specifier, name: re.source } })\n }\n for (const star of f.starFrom) {\n if (star.target === null) problems.push(`${file} hands on everything from '${star.specifier}' with export *: name the parts it hands on, so the catalogue can list them`)\n }\n }\n\n // \u2500\u2500 Where each is used \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const key = (file: string, name: string) => `${file}#${name}`\n const byKey = new Map(found.map((p) => [key(p.file, p.name), p]))\n const partsIn = (file: string) => found.filter((p) => p.file === file)\n /** The part a file's default export is, however it was written. */\n const defaultPartOf = (file: string): Found | null => {\n const written = facts.get(file)?.exports.find((e) => e.isDefault)\n if (!written) return null\n const d = unwrapDefault(written)\n return partsIn(file).find((p) => p.defaultExport || (d.local !== null && p.local === d.local)) ?? null\n }\n\n /** What `name`, imported from `file`, really is: follows barrels to the file that writes it. */\n const origin = (file: string, name: string, seen = new Set<string>()): Found | null => {\n if (seen.has(key(file, name))) return null\n seen.add(key(file, name))\n const direct = byKey.get(key(file, name))\n if (direct) return direct\n const f = facts.get(file)\n if (!f) return null\n // `export default Foo` elsewhere in the file: the default is Foo's part.\n if (name === 'default') {\n const d = defaultPartOf(file)\n if (d) return d\n }\n const re = f.reexports.find((r) => r.name === name)\n if (re && re.target && re.target !== '?') return origin(re.target, re.source, seen)\n // `import { X } from './X'` and `export { X }`: a barrel written in two lines.\n const ex = f.exports.find((e) => (name === 'default' ? e.isDefault : e.name === name && !e.isDefault))\n const renamed = ex?.node && ts.isVariableDeclaration(ex.node) && ex.node.initializer && ts.isIdentifier(ex.node.initializer) ? f.bindings.get(ex.node.initializer.text) : undefined\n const bound = (ex?.local && !ex.node && !declarationOf(f, ex.local) ? f.bindings.get(ex.local) : undefined) ?? renamed\n if (bound?.target && bound.target !== '?') return origin(bound.target, bound.imported, seen)\n for (const star of f.starFrom) if (star.target && star.target !== '?') {\n const hit = origin(star.target, name, seen)\n if (hit) return hit\n }\n return null\n }\n /** Every part a file hands out, through its barrels too. */\n const everyPartOf = (file: string, seen = new Set<string>()): Found[] => {\n if (seen.has(file)) return []\n seen.add(file)\n const f = facts.get(file)\n if (!f) return []\n const out = [...partsIn(file)]\n for (const re of f.reexports) if (re.target && re.target !== '?') { const o = origin(re.target, re.source); if (o) out.push(o) }\n for (const star of f.starFrom) if (star.target && star.target !== '?') out.push(...everyPartOf(star.target, seen))\n for (const ns of f.namespaces) if (ns.target && ns.target !== '?') out.push(...everyPartOf(ns.target, seen))\n return out\n }\n /** The parts a namespace export stands for, followed through barrels. */\n const namespaceParts = (file: string, name: string, seen = new Set<string>()): Found[] => {\n if (seen.has(`${file}#${name}`)) return []\n seen.add(`${file}#${name}`)\n const f = facts.get(file)\n if (!f) return []\n const ns = f.namespaces.find((x) => x.name === name)\n if (ns) return ns.target && ns.target !== '?' ? everyPartOf(ns.target) : []\n const re = f.reexports.find((r) => r.name === name)\n if (re?.target && re.target !== '?') return namespaceParts(re.target, re.source, seen)\n return f.starFrom.flatMap((star) => (star.target && star.target !== '?' ? namespaceParts(star.target, name, seen) : []))\n }\n\n const users = new Map<string, { app: Set<string>; stories: Set<string>; tests: Set<string> }>()\n for (const p of found) users.set(key(p.file, p.name), { app: new Set(), stories: new Set(), tests: new Set() })\n for (const f of facts.values()) {\n const bucket = (p: Found) => {\n const u = users.get(key(p.file, p.name))!\n return isStory(f.file) ? u.stories : isTest(f.file) ? u.tests : u.app\n }\n for (const link of f.links) {\n if (link.kind === 're-export' || link.typeOnly || !link.target || link.target === '?') continue\n for (const n of link.names) {\n if (n.imported === '*') {\n // `lazy(() => import('./Page'))` loads the default; a namespace may use any.\n const theDefault = link.kind === 'dynamic' ? defaultPartOf(link.target) : null\n const chosen = theDefault ? [theDefault] : everyPartOf(link.target)\n for (const p of chosen) if (p.file !== f.file) bucket(p).add(f.file)\n continue\n }\n const p = origin(link.target, n.imported)\n // A file that imports a part only to export it again hands it on; it does not use it.\n const handsOn = f.exports.some((e) => e.local === n.local && e.node === null) && !mentions(f.sf, n.local, null)\n if (handsOn) continue\n if (p) {\n if (p.file !== f.file) bucket(p).add(f.file)\n continue\n }\n // `import { Parts } from './barrel'`, where the barrel says `export * as Parts from './parts'`.\n for (const part of namespaceParts(link.target, n.imported)) if (part.file !== f.file) bucket(part).add(f.file)\n }\n }\n }\n // Its own file uses it when something there, other than its own declaration and\n // the export line, names it \u2014 a card drawn by the list beside it.\n for (const p of found) {\n if (p.from || !p.local) continue\n const f = facts.get(p.file)!\n const decl = declarationOf(f, p.local)\n const home = decl ? (ts.isVariableDeclaration(decl) ? decl.parent.parent : decl) : null\n if (mentions(f.sf, p.local, home)) users.get(key(p.file, p.name))!.app.add(p.file)\n }\n\n // \u2500\u2500 What ties each file to the app \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // A file is tied when it imports a package the package does not itself depend\n // on, something that is not code, or an app file that is tied. Types count: a\n // part typed by Peek's data is Peek's.\n const directTies = new Map<string, string[]>()\n const appDeps = new Map<string, string[]>()\n for (const f of facts.values()) {\n const ties: string[] = []\n const deps: string[] = []\n for (const link of f.links) {\n if (link.target === null) {\n const tie = link.specifier.startsWith('node:') ? link.specifier : allowed.has(packageOf(link.specifier)) ? null : packageOf(link.specifier)\n if (tie && !ties.includes(tie)) ties.push(tie)\n } else if (link.target === '?') {\n if (!ties.includes(link.specifier)) ties.push(link.specifier)\n } else if (link.target !== f.file && !deps.includes(link.target)) deps.push(link.target)\n }\n directTies.set(f.file, ties)\n appDeps.set(f.file, deps)\n }\n const tied = new Set([...directTies].filter(([, t]) => t.length > 0).map(([file]) => file))\n for (let changed = true; changed; ) {\n changed = false\n for (const [file, deps] of appDeps) if (!tied.has(file) && deps.some((d) => tied.has(d))) (tied.add(file), (changed = true))\n }\n const tiesOf = (file: string) => [...directTies.get(file)!, ...appDeps.get(file)!.filter((d) => tied.has(d))].sort()\n\n // \u2500\u2500 Stories: which one shows a part \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const stories = files.filter(isStory).map((file) => {\n const f = facts.get(file)!\n let title: string | null = null\n let component: string | null = null\n let noDocs = false\n const names: string[] = []\n for (const s of f.sf.statements) {\n if (!ts.isVariableStatement(s)) continue\n const exported = (ts.getModifiers(s) ?? []).some((m) => m.kind === ts.SyntaxKind.ExportKeyword)\n for (const d of s.declarationList.declarations) {\n if (!ts.isIdentifier(d.name)) continue\n if (d.name.text === 'meta') {\n let init = d.initializer\n while (init && (ts.isSatisfiesExpression(init) || ts.isAsExpression(init) || ts.isParenthesizedExpression(init))) init = init.expression\n if (init && ts.isObjectLiteralExpression(init)) {\n for (const prop of init.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue\n if (prop.name.text === 'title' && ts.isStringLiteralLike(prop.initializer)) title = prop.initializer.text\n if (prop.name.text === 'component' && ts.isIdentifier(prop.initializer)) component = prop.initializer.text\n if (prop.name.text === 'tags' && ts.isArrayLiteralExpression(prop.initializer)) noDocs = prop.initializer.elements.some((e) => ts.isStringLiteralLike(e) && e.text === '!autodocs')\n }\n }\n } else if (exported) names.push(d.name.text)\n }\n }\n // Which part each local name is, through the imports.\n const imported = new Map<string, Found>()\n for (const link of f.links) {\n if (!link.target || link.target === '?') continue\n for (const n of link.names) {\n if (n.imported === '*') continue\n const p = origin(link.target, n.imported)\n if (p) imported.set(n.local, p)\n }\n }\n return { file, title, component: component ? (imported.get(component) ?? null) : null, noDocs, names, imports: [...imported.values()] }\n })\n const storyOf = (p: Found) => {\n const stem = (file: string) => basename(file).replace(/\\.stories\\.[cm]?[jt]sx?$/, '')\n const own = basename(p.file, extname(p.file))\n // A story file named after the part draws it even when its stories are of a\n // presentational half in the same file \u2014 `FilesPanel.stories.tsx` drawing\n // `FilesPanelView` is FilesPanel's picture, and its page attaches there (UIG-19).\n const sameFile = (s: (typeof stories)[number]) => s.imports.some((q) => q.file === p.file)\n const candidates = stories.filter((s) => s.title && s.names.length && (s.component === p || (s.imports.includes(p) && (stem(s.file) === p.name || stem(s.file) === own)) || (stem(s.file) === p.name && sameFile(s))))\n candidates.sort((a, b) => Number(b.component === p) - Number(a.component === p) || a.file.localeCompare(b.file))\n const s = candidates[0]\n if (!s || !s.title) return { docsId: null, storyId: null }\n return { docsId: s.noDocs ? null : `${sanitize(s.title)}--docs`, storyId: toId(s.title, s.names.includes(p.name) ? p.name : s.names[0]) }\n }\n\n // \u2500\u2500 Props, read the way the package's are \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n type Module = ReturnType<typeof readModule>\n const modules = new Map<string, Module>()\n const moduleAt = (file: string): Module => {\n const held = modules.get(file)\n if (held) return held\n const read = readModule(facts.get(file)!.source, (specifier, typeName): Resolved | undefined => {\n // A wrapper typed by the package's own props takes what the package's part\n // takes. The package names every part's props type after the part \u2014\n // `SearchInputProps` is `SearchInput`'s, all 65 of them \u2014 so its entry answers.\n if (specifier === PACKAGE_IMPORT) {\n const part = typeName.endsWith('Props') ? theRegistry?.entries.find((entry) => entry.name === typeName.slice(0, -'Props'.length)) : undefined\n return part ? { props: part.props, variants: part.variants } : undefined\n }\n const target = resolveSpecifier(file, specifier)\n return target && target !== '?' ? moduleAt(target).resolveName(typeName) : undefined\n // A comment directly above a part is that part's, first in its file or not.\n }, { lendFirstComment: false })\n modules.set(file, read)\n return read\n }\n\n // \u2500\u2500 The entries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const namesakes = new Set((theRegistry?.entries ?? []).map((e) => e.name))\n const importPathOf = (file: string) => {\n const abs = join(app, file)\n const alias = aliases.find((a) => abs.startsWith(a.target + sep))\n const stem = file.replace(/\\.[cm]?[jt]sx?$/, '').replace(/\\/index$/, '')\n return alias ? `${alias.prefix}${relative(alias.target, join(app, stem)).split(sep).join('/')}` : stem\n }\n const port = /(?:-p|--port)[\\s=]+(\\d+)/.exec(manifest.scripts?.storybook ?? '')?.[1] ?? '6006'\n\n const entries: RegistryEntry[] = []\n for (const p of found) {\n const u = users.get(key(p.file, p.name))!\n const usedIn = [...u.app].sort()\n const pass = p.from\n const onePart = partsIn(p.file).filter((q) => !q.from).length === 1\n const module = pass ? null : moduleAt(p.file)\n // A default written as an expression has no name in its file: the builder keeps it as `default`.\n const declared = pass ? undefined : module!.declarations.get(p.local ?? 'default')\n const header = module?.headerDoc ?? ''\n // The file's default may carry its comment on `export default memo(Row)` rather than on Row.\n const doc = declared?.doc || (defaultPartOf(p.file) === p ? (module?.declarations.get('default')?.doc ?? '') : '')\n\n // Purpose: its page, else its own comment, else \u2014 for a file of one part \u2014\n // the file's. A pass-on says whose it is.\n const page = pass ? null : join(dirname(p.file), `${p.name}.mdx`).split(sep).join('/')\n const pageText = page && existsSync(join(app, page)) ? pageOpening(readFileSync(join(app, page), 'utf8')) : ''\n let purpose = ''\n let purposeFrom: RegistryEntry['purposeFrom'] = 'comment'\n if (pass) {\n const as = pass.name === p.name ? '' : ` as ${p.name}`\n purpose = pass.specifier === PACKAGE_IMPORT ? `The package's ${pass.name}, handed on${as} so the app can import it from ${importPathOf(p.file)}.` : `${pass.name} from ${pass.specifier}, handed on${as} so the app can import it from ${importPathOf(p.file)}.`\n purposeFrom = 'package'\n } else if (firstSentence(pageText)) {\n purpose = firstSentence(pageText)\n purposeFrom = 'page'\n } else if (firstSentence(doc)) {\n purpose = firstSentence(doc)\n } else if (onePart && firstSentence(header)) {\n purpose = firstSentence(header)\n purposeFrom = 'file'\n }\n if (!purpose) {\n problems.push(`${p.name} in ${p.file} has no one-line description. Write one as a /** \u2026 */ comment directly above it${onePart ? ', or at the top of the file' : ''}.`)\n continue\n }\n\n // Its kind: written beside it, or read from the evidence.\n const writtenLine = WRITTEN.exec(doc) ?? (onePart ? WRITTEN.exec(header) : null)\n const ties = pass ? [] : tiesOf(p.file)\n let cls: EntryClass\n let reason: string\n let written = false\n if (pass) {\n cls = 're-export'\n reason = `Its file only hands on ${pass.specifier === PACKAGE_IMPORT ? `the package's ${pass.name}` : `${pass.name} from ${pass.specifier}`}.`\n if (writtenLine) problems.push(`${p.name} in ${p.file} is a pass-on, so its kind is read from the file: remove \"@registry ${writtenLine[1]}\"`)\n } else if (writtenLine) {\n const said = writtenLine[1] as EntryClass\n if (!WRITABLE.includes(said)) {\n problems.push(`${p.name} in ${p.file} says \"@registry ${writtenLine[1]}\": the kinds a person may write are ${WRITABLE.join(', ')}`)\n continue\n }\n cls = said\n reason = writtenLine[2].trim()\n written = true\n } else if (usedIn.length === 0) {\n cls = 'unused'\n reason = u.stories.size ? 'No file of the app uses it; only its stories do.' : u.tests.size ? 'No file of the app uses it; only its tests do.' : 'Nothing uses it.'\n } else if (usedIn.length === 1) {\n cls = 'one-off'\n reason = `Used in one place: ${usedIn[0]}.`\n } else if (ties.length) {\n cls = 'reusable'\n reason = `Used in ${usedIn.length} places, and tied to the app by ${ties[0]}${ties.length > 1 ? ` and ${ties.length - 1} more` : ''}.`\n } else {\n cls = 'promote-candidate'\n reason = `Used in ${usedIn.length} places, and everything it uses is already in the package.`\n }\n\n const shape: Resolved = declared ? module!.resolve(declared.propsType) : { props: [], variants: [] }\n const facts_: AppFacts = {\n class: cls,\n reason,\n written,\n handsOn: pass ? (pass.specifier === PACKAGE_IMPORT ? pass.name : `${pass.name} from ${pass.specifier}`) : null,\n usedIn,\n tiedTo: ties,\n packageNamesake: namesakes.has(p.name) && !(pass && pass.specifier === PACKAGE_IMPORT && pass.name === p.name) ? p.name : null,\n defaultExport: p.defaultExport,\n }\n const { docsId, storyId } = pass ? { docsId: null, storyId: null } : storyOf(p)\n entries.push({\n name: p.name,\n repo: repoName,\n kind: 'component',\n importPath: importPathOf(p.file),\n sourceFile: p.file,\n purpose,\n purposeFrom,\n props: shape.props,\n variants: shape.variants,\n ownsBehaviours: [],\n status: declared?.deprecated ? 'deprecated' : 'stable',\n migrationStage: null,\n docsId,\n storyId,\n docPage: pageText ? page : null,\n app: facts_,\n // A part handed on from the package looks like the package's (UIG-25).\n looks: pass ? [] : (looksOf(parseForLooks(join(root, p.file), facts.get(p.file)!.source), [p.name]).get(p.name) ?? []),\n })\n }\n\n if (problems.length) throw new Error(`the catalogue of ${repoName} cannot be built:\\n ${problems.join('\\n ')}`)\n\n entries.sort((a, b) => a.name.localeCompare(b.name) || a.sourceFile.localeCompare(b.sourceFile))\n const withParts = new Set(found.map((p) => p.file))\n const filesWithoutParts: FileWithoutPart[] = targets\n .filter((file) => !withParts.has(file))\n .map((file) => {\n const f = facts.get(file)!\n const names = [...f.exports.map((e) => (e.isDefault ? (e.local ?? 'a default') : e.name)), ...f.reexports.map((r) => r.name)]\n return { file, reason: names.length ? `It exports no part, only ${names.join(', ')}.` : 'It exports nothing.' }\n })\n\n return {\n schemaVersion: SCHEMA_VERSION,\n builtFrom: {\n kind: 'app',\n repo: repoName,\n package: manifest.name ?? repoName,\n packageVersion: manifest.version ?? '0.0.0',\n exports: found.length,\n typeExports: 0,\n files: targets.length,\n },\n storybook: {\n docsPath: '/?path=/docs/{docsId}',\n storyPath: '/?path=/story/{storyId}',\n devUrl: `http://localhost:${port}`,\n },\n entries,\n excluded: [],\n filesWithoutParts,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["bindings", "p", "s"]
7
+ }
@@ -83,6 +83,7 @@ function validateRegistry(value) {
83
83
  else for (const behaviour of entry.ownsBehaviours) {
84
84
  if (!isFilledString(behaviour?.id) || !isFilledString(behaviour?.behaviour)) fail(at("ownsBehaviours") + " has a malformed entry");
85
85
  }
86
+ if (entry.looks !== void 0 && !(Array.isArray(entry.looks) && entry.looks.every(isFilledString))) fail(at("looks") + " is not a list of class lists");
86
87
  for (const key2 of ["docsId", "storyId", "docPage"]) {
87
88
  const held = entry[key2];
88
89
  if (!(held === null || isFilledString(held))) fail(at(key2) + " is neither a string nor null");
@@ -152,4 +153,4 @@ export {
152
153
  CLASSES,
153
154
  validateRegistry
154
155
  };
155
- //# sourceMappingURL=chunk-E4JNV7PC.js.map
156
+ //# sourceMappingURL=chunk-PZO4BVV3.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/registry/schema.ts"],
4
+ "sourcesContent": ["/**\n * The catalogue's shape (UIG-12, seam S2 in docs/GATES.md \u00A716).\n *\n * A **data source read by machines first** and rendered second \u2014 not a\n * documentation generator. The skill (UIG-20), the copy detector (UIG-25) and\n * the merged search (UIG-19) all read this and nothing else, so the field\n * names are the contract and `schemaVersion` is what makes a change to them\n * detectable.\n *\n * Names are plain and ours. Open-sourcing is far off; when it comes, a\n * renaming pass is one version bump, and guessing at a public vocabulary now\n * would cost every reader between here and there.\n */\n\n/**\n * Raise this whenever a field is added, removed or given a new meaning. A\n * reader that knows version N and is handed N+1 must be able to say so rather\n * than silently read a field that moved.\n */\nexport const SCHEMA_VERSION = 2\n\n/** What a name is, which decides how a reader offers it. */\nexport type EntryKind =\n /** Draws something. Used in JSX. */\n | 'component'\n /** A React hook: `use\u2026`, callable only inside a component. */\n | 'hook'\n /** A function or a constant. Neither of the above. */\n | 'helper'\n\n/** Where an entry's one-line purpose was read from. */\nexport type PurposeSource =\n /** The `.mdx` page's opening paragraph \u2014 the name has a page of its own. */\n | 'page'\n /** The doc comment above the export \u2014 the name is documented on a sibling's page. */\n | 'comment'\n /** An app's file that holds this one part: the comment at the top of the file (UIG-13). */\n | 'file'\n /** An app's pass-on: the part is the package's, and says so (UIG-13). */\n | 'package'\n\n/**\n * Which of four kinds an app's part is (UIG-13), or that nothing uses it.\n *\n * Worked out from the code, never from the folder a file sits in: Peek's\n * `components/ui` holds one-line pass-ons beside 187-line components.\n */\nexport type EntryClass =\n /** Its file only hands a package part on, so the app keeps its own import path. */\n | 're-export'\n /** Used in two or more places in the app. Gets a usage page (UIG-17, UIG-18). */\n | 'reusable'\n /** Used in one place. Needs only its purpose line. */\n | 'one-off'\n /** Reusable, and everything it uses is already in the package: it could move there. Katerina rules. */\n | 'promote-candidate'\n /** No file of the app uses it: only its stories or tests, or nothing. Listed, never deleted by the catalogue. */\n | 'unused'\n\n/**\n * What the catalogue knows about a part that lives in an app (UIG-13). `null`\n * on the package's own entries.\n */\nexport interface AppFacts {\n class: EntryClass\n /** Why it has that class, in words: the evidence, or the written reason. */\n reason: string\n /**\n * `true` when the class is written beside the part (`@registry <class>: <reason>`\n * in its comment) rather than worked out \u2014 \"general, though one screen uses it yet\".\n */\n written: boolean\n /** A pass-on's part, as `Name` for the package's and `Name from <package>` for another's. `null` otherwise. */\n handsOn: string | null\n /**\n * The app's files that use it, relative to the app: every file that imports it,\n * and its own file when something else there draws it. Stories and tests are not\n * uses \u2014 a part only they reach is unused.\n */\n usedIn: string[]\n /**\n * What ties it to this app: each import that is neither in the package's own\n * dependencies nor an app file that is itself untied. Empty means it could\n * live in the package as it is.\n */\n tiedTo: string[]\n /** The package part with the same name, when there is one: the reader should see both. */\n packageNamesake: string | null\n /** Imported as `import X from \u2026` rather than `import { X } from \u2026`. */\n defaultExport: boolean\n}\n\n/** A file in an app's target set that holds no part, and why, in words. */\nexport interface FileWithoutPart {\n file: string\n reason: string\n}\n\nexport type EntryStatus = 'stable' | 'migrating' | 'deprecated'\n\n/** A prop that takes one of a known set of words, and the set. */\nexport interface EntryVariant {\n prop: string\n values: string[]\n}\n\n/**\n * One prop a component declares itself.\n *\n * **Itself**, not what it inherits: a component that extends\n * `ComponentPropsWithRef<'div'>` would otherwise drag in every DOM attribute,\n * which is noise in a catalogue whose whole point is a short answer.\n */\nexport interface EntryProp {\n name: string\n /**\n * What it takes, in a word a person reads: `true/false`, `number`, `text`,\n * `anything`, `a handler`, the words themselves for a set (`left | right`),\n * or the type as written where none of those fit.\n */\n takes: string\n required: boolean\n /** The first sentence of the prop's own comment, where it has one. */\n note: string | null\n}\n\n/** A behaviour this component owns, from UIG-8's enumeration. */\nexport interface EntryBehaviour {\n /** `OwnedBehaviour.id` \u2014 `portal`, `walking`, `scroll`\u2026 */\n id: string\n /** What a person notices it doing, in words. */\n behaviour: string\n}\n\nexport interface RegistryEntry {\n /** The exported name, exactly as `index.ts` exports it. */\n name: string\n /** Which library it came from: `estiva-ui`, or the app that owns it. */\n repo: string\n kind: EntryKind\n /** What a caller actually types. */\n importPath: string\n /** The file the name is declared in, relative to the repo. Several names share one file. */\n sourceFile: string\n /** One line: what it is for. Never empty \u2014 the build fails instead. */\n purpose: string\n purposeFrom: PurposeSource\n /**\n * Every prop it declares itself \u2014 what it can do. This is the field a reader\n * asks \"does it already do X?\" of, before writing X by hand.\n */\n props: EntryProp[]\n /**\n * The subset of `props` that takes one of a known set of words, structured.\n * Kept beside `props` because it is what a search ranks well on, and what a\n * caller most often needs named back at them.\n */\n variants: EntryVariant[]\n /** What it owns, so a caller never rebuilds it (UIG-8). Empty for most. */\n ownsBehaviours: EntryBehaviour[]\n status: EntryStatus\n /**\n * Which migration stage plans to change it.\n *\n * Always `null` here. The migration's plan lives in `K:/Estiva/migration\n * docs`, which is not in this repo and is not in CI \u2014 and a copy kept here by\n * hand is the drifting list this whole project exists to remove. The field\n * stays in the schema because a later ticket may have a source a build can\n * read; until then a reader gets an honest `null` rather than a stale number.\n */\n migrationStage: number | null\n /** The `.mdx` page's Storybook id, or `null` where the name has no page of its own. */\n docsId: string | null\n /** A story that shows it, by Storybook id. `null` where nothing renders it alone. */\n storyId: string | null\n /** The `.mdx` path, relative to the repo, or `null`. */\n docPage: string | null\n /** An app's part: its class and the evidence for it (UIG-13). `null` on the package's own entries. */\n app: AppFacts | null\n /**\n * What it looks like: each class list it writes, as its look words\n * (colour, text, border, corner, shadow \u2014 never placement), those with four\n * or more (UIG-25). What `estiva/no-copied-look` compares a hand-typed list\n * against. Empty for a part that only places others; absent in a catalogue\n * built before 0.34.0.\n */\n looks?: string[]\n}\n\n/** A name that is exported and deliberately not an entry. Empty today; the count still has to reconcile. */\nexport interface RegistryExclusion {\n name: string\n reason: string\n}\n\nexport interface Registry {\n schemaVersion: number\n builtFrom: {\n /**\n * `package`: the package's catalogue, committed and shipped. `app`: one app's,\n * built fresh from its code each time and never committed \u2014 Peek and Ship are\n * private, the package is public (Katerina, 18 September 2026).\n */\n kind: 'package' | 'app'\n repo: string\n /** The package the entries are imported from, or the app's own name. */\n package: string\n packageVersion: string\n /**\n * The package: value exports counted in `index.ts`. An app: parts found in its\n * files. `entries + excluded` must equal it.\n */\n exports: number\n /** Type-only exports, which are not entries. Recorded so the count reconciles. `0` for an app. */\n typeExports: number\n /**\n * An app only: its `.tsx` files outside stories and tests. Each one either holds\n * an entry or is in `filesWithoutParts`. `null` for the package.\n */\n files: number | null\n }\n /**\n * How to turn an id into a link. There is no Storybook on the internet yet\n * (UIG-19), so an absolute URL committed here would resolve nowhere: the\n * reader joins its own base to these.\n */\n storybook: {\n docsPath: string\n storyPath: string\n devUrl: string\n }\n entries: RegistryEntry[]\n excluded: RegistryExclusion[]\n /** An app's `.tsx` files that hold no part, each with its reason. Empty for the package. */\n filesWithoutParts: FileWithoutPart[]\n}\n\nconst KINDS: EntryKind[] = ['component', 'hook', 'helper']\nconst STATUSES: EntryStatus[] = ['stable', 'migrating', 'deprecated']\nconst SOURCES: PurposeSource[] = ['page', 'comment', 'file', 'package']\nexport const CLASSES: EntryClass[] = ['re-export', 'reusable', 'one-off', 'promote-candidate', 'unused']\n\nconst isString = (v: unknown): v is string => typeof v === 'string'\nconst isFilledString = (v: unknown): v is string => isString(v) && v.trim().length > 0\n\n/**\n * Check a registry against this schema. Returns every problem, not the first:\n * a build that reports one missing purpose per run costs one run per entry.\n *\n * An empty list is the only pass. CI runs this on the committed file.\n */\nexport function validateRegistry(value: unknown): string[] {\n const problems: string[] = []\n const fail = (message: string) => problems.push(message)\n\n if (typeof value !== 'object' || value === null) return ['the registry is not an object']\n const registry = value as Partial<Registry>\n\n if (registry.schemaVersion !== SCHEMA_VERSION) fail(`schemaVersion is ${String(registry.schemaVersion)}, expected ${SCHEMA_VERSION}`)\n\n const built = registry.builtFrom\n let isApp = false\n if (typeof built !== 'object' || built === null) fail('builtFrom is missing')\n else {\n if (built.kind !== 'package' && built.kind !== 'app') fail(`builtFrom.kind is ${String(built.kind)}, expected package or app`)\n isApp = built.kind === 'app'\n if (!isFilledString(built.repo)) fail('builtFrom.repo is missing')\n if (!isFilledString(built.package)) fail('builtFrom.package is missing')\n if (!isFilledString(built.packageVersion)) fail('builtFrom.packageVersion is missing')\n if (typeof built.exports !== 'number') fail('builtFrom.exports is not a number')\n if (typeof built.typeExports !== 'number') fail('builtFrom.typeExports is not a number')\n if (isApp ? typeof built.files !== 'number' : built.files !== null) fail(`builtFrom.files is ${String(built.files)}: a number for an app, null for the package`)\n }\n\n const book = registry.storybook\n if (typeof book !== 'object' || book === null) fail('storybook is missing')\n else {\n for (const key of ['docsPath', 'storyPath', 'devUrl'] as const) {\n if (!isFilledString(book[key])) fail(`storybook.${key} is missing`)\n }\n if (isString(book.docsPath) && !book.docsPath.includes('{docsId}')) fail('storybook.docsPath does not carry {docsId}')\n if (isString(book.storyPath) && !book.storyPath.includes('{storyId}')) fail('storybook.storyPath does not carry {storyId}')\n }\n\n const entries = registry.entries\n const excluded = registry.excluded\n const withoutParts = registry.filesWithoutParts\n if (!Array.isArray(entries)) return [...problems, 'entries is not an array']\n if (!Array.isArray(excluded)) return [...problems, 'excluded is not an array']\n if (!Array.isArray(withoutParts)) return [...problems, 'filesWithoutParts is not an array']\n // An app with no part of its own yet is still an app: only the package must have entries.\n if (entries.length === 0 && !isApp) fail('entries is empty')\n\n // The package's names are unique; an app may have two parts of one name in two\n // files, and the catalogue says which is which rather than refusing the app.\n const seen = new Set<string>()\n const seenNames = new Set<string>()\n for (const [i, raw] of entries.entries()) {\n const at = (field: string) => `entries[${i}] (${isString((raw as RegistryEntry)?.name) ? (raw as RegistryEntry).name : '?'}).${field}`\n if (typeof raw !== 'object' || raw === null) {\n fail(`entries[${i}] is not an object`)\n continue\n }\n const entry = raw as Partial<RegistryEntry>\n const key = isApp ? `${String(entry.sourceFile)}#${String(entry.name)}` : String(entry.name)\n if (!isFilledString(entry.name)) fail(at('name') + ' is missing')\n else if (seen.has(key)) fail(`${entry.name} appears twice${isApp ? ` in ${String(entry.sourceFile)}` : ''}`)\n else {\n seen.add(key)\n seenNames.add(entry.name)\n }\n\n if (!isFilledString(entry.repo)) fail(at('repo') + ' is missing')\n if (!isFilledString(entry.importPath)) fail(at('importPath') + ' is missing')\n if (!isFilledString(entry.sourceFile)) fail(at('sourceFile') + ' is missing')\n // The reason this schema exists: an entry with no purpose is an entry the\n // search cannot find and the skill cannot quote.\n if (!isFilledString(entry.purpose)) fail(at('purpose') + ' is empty')\n if (!KINDS.includes(entry.kind as EntryKind)) fail(at('kind') + ` is ${String(entry.kind)}`)\n if (!SOURCES.includes(entry.purposeFrom as PurposeSource)) fail(at('purposeFrom') + ` is ${String(entry.purposeFrom)}`)\n if (!STATUSES.includes(entry.status as EntryStatus)) fail(at('status') + ` is ${String(entry.status)}`)\n if (!(entry.migrationStage === null || typeof entry.migrationStage === 'number')) fail(at('migrationStage') + ' is neither a number nor null')\n if (!Array.isArray(entry.props)) fail(at('props') + ' is not an array')\n else\n for (const prop of entry.props) {\n if (!isFilledString(prop?.name) || !isFilledString(prop?.takes) || typeof prop?.required !== 'boolean') fail(at('props') + ' has a malformed entry')\n else if (!(prop.note === null || isFilledString(prop.note))) fail(at('props') + `.${prop.name}.note is neither a string nor null`)\n }\n if (!Array.isArray(entry.variants)) fail(at('variants') + ' is not an array')\n else\n for (const variant of entry.variants) {\n if (!isFilledString(variant?.prop) || !Array.isArray(variant?.values) || variant.values.length === 0) fail(at('variants') + ' has a malformed entry')\n // variants is a view of props, never a second source that can disagree.\n else if (Array.isArray(entry.props) && !entry.props.some((prop) => prop?.name === variant.prop)) fail(at('variants') + `.${variant.prop} is not one of its props`)\n }\n if (!Array.isArray(entry.ownsBehaviours)) fail(at('ownsBehaviours') + ' is not an array')\n else for (const behaviour of entry.ownsBehaviours) {\n if (!isFilledString(behaviour?.id) || !isFilledString(behaviour?.behaviour)) fail(at('ownsBehaviours') + ' has a malformed entry')\n }\n if (entry.looks !== undefined && !(Array.isArray(entry.looks) && entry.looks.every(isFilledString))) fail(at('looks') + ' is not a list of class lists')\n for (const key of ['docsId', 'storyId', 'docPage'] as const) {\n const held = entry[key]\n if (!(held === null || isFilledString(held))) fail(at(key) + ' is neither a string nor null')\n }\n // \"Every storyUrl resolves, or is recorded as absent with a reason\" \u2014 the\n // reason is enforced rather than written down: only something that draws\n // nothing may have nowhere to be looked at. A component with no story is\n // already an error of UIG-5's component-has-a-story; this stops the\n // catalogue quietly carrying one.\n //\n // The package only. An app's parts are described before they are drawn:\n // absence of a story says nothing about whether a part is reused, and UIG-19\n // is where a reusable one must have one.\n if (!isApp && entry.kind === 'component' && (entry.docsId === null || entry.storyId === null)) {\n fail(at('docsId') + ' is null, and only a helper or a hook may have no page or story')\n }\n\n if (!isApp) {\n if (entry.app !== null) fail(at('app') + ' is set on a package entry')\n } else {\n problems.push(...validateAppFacts(entry, at))\n }\n }\n\n for (const [i, raw] of excluded.entries()) {\n const gap = raw as Partial<RegistryExclusion>\n if (!isFilledString(gap?.name)) fail(`excluded[${i}].name is missing`)\n if (!isFilledString(gap?.reason)) fail(`excluded[${i}].reason is missing`)\n if (!isApp && isString(gap?.name) && seenNames.has(gap.name)) fail(`${gap.name} is both an entry and excluded`)\n }\n\n // Completeness (the ticket's acceptance): every value export is either an\n // entry or an exclusion with a reason. Averaging the difference away is the\n // failure this check exists to make impossible.\n const counted = entries.length + excluded.length\n if (typeof built === 'object' && built !== null && typeof built.exports === 'number' && counted !== built.exports) {\n fail(`${entries.length} entries + ${excluded.length} excluded = ${counted}, but ${isApp ? 'the app has' : 'index.ts exports'} ${built.exports} ${isApp ? 'parts' : 'values'}`)\n }\n\n // And an app's files: every one either holds a part or says why it does not.\n const fileProblems: string[] = []\n const withParts = new Set(entries.map((entry) => (entry as RegistryEntry).sourceFile))\n for (const [i, raw] of withoutParts.entries()) {\n const gap = raw as Partial<FileWithoutPart>\n if (!isFilledString(gap?.file)) fileProblems.push(`filesWithoutParts[${i}].file is missing`)\n else if (withParts.has(gap.file)) fileProblems.push(`${gap.file} holds a part and is listed as holding none`)\n if (!isFilledString(gap?.reason)) fileProblems.push(`filesWithoutParts[${i}].reason is missing`)\n }\n if (!isApp && withoutParts.length) fileProblems.push('filesWithoutParts is for an app; the package lists its exports instead')\n if (isApp && typeof built === 'object' && built !== null && typeof built.files === 'number' && withParts.size + withoutParts.length !== built.files) {\n fileProblems.push(`${withParts.size} files hold a part + ${withoutParts.length} hold none = ${withParts.size + withoutParts.length}, but the app has ${built.files} files`)\n }\n problems.push(...fileProblems)\n\n return problems\n}\n\n/**\n * An app entry's class must be what its own evidence says, unless it is written\n * beside the part with a reason. A pass-on is a fact about the file, so it can\n * never be written, and only a pass-on hands a part on.\n */\nfunction validateAppFacts(entry: Partial<RegistryEntry>, at: (field: string) => string): string[] {\n const problems: string[] = []\n const fail = (message: string) => problems.push(message)\n const facts = entry.app\n if (typeof facts !== 'object' || facts === null) return [at('app') + ' is missing on an app entry']\n if (!CLASSES.includes(facts.class)) fail(at('app.class') + ` is ${String(facts.class)}`)\n if (!isFilledString(facts.reason)) fail(at('app.reason') + ' is empty')\n if (typeof facts.written !== 'boolean') fail(at('app.written') + ' is not true/false')\n if (typeof facts.defaultExport !== 'boolean') fail(at('app.defaultExport') + ' is not true/false')\n if (!Array.isArray(facts.usedIn) || !facts.usedIn.every(isFilledString)) fail(at('app.usedIn') + ' is not a list of files')\n if (!Array.isArray(facts.tiedTo) || !facts.tiedTo.every(isFilledString)) fail(at('app.tiedTo') + ' is not a list')\n if (!(facts.handsOn === null || isFilledString(facts.handsOn))) fail(at('app.handsOn') + ' is neither a name nor null')\n if (!(facts.packageNamesake === null || isFilledString(facts.packageNamesake))) fail(at('app.packageNamesake') + ' is neither a name nor null')\n if (problems.length) return problems\n\n const passOn = facts.class === 're-export'\n if (passOn !== (facts.handsOn !== null)) fail(at('app.handsOn') + (passOn ? ' is missing on a pass-on' : ' is set on a part that is not a pass-on'))\n if (passOn !== (entry.purposeFrom === 'package')) fail(at('purposeFrom') + (passOn ? ' must be package on a pass-on' : ' is package on a part that is not a pass-on'))\n if (passOn && facts.written) fail(at('app.written') + ': a pass-on is read from the file, never written')\n if (!facts.written && !passOn) {\n const uses = facts.usedIn.length\n const expected: EntryClass = uses === 0 ? 'unused' : uses === 1 ? 'one-off' : facts.tiedTo.length ? 'reusable' : 'promote-candidate'\n if (facts.class !== expected) fail(at('app.class') + ` is ${facts.class}, but its evidence (${uses} uses, ${facts.tiedTo.length} ties) says ${expected}`)\n }\n return problems\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["key"]
7
+ }