@astryxdesign/cli 0.1.2 → 0.1.3

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 (238) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/README.md +49 -55
  3. package/docs/layout.doc.dense.mjs +90 -0
  4. package/docs/layout.doc.mjs +160 -0
  5. package/docs/principles.doc.dense.mjs +2 -2
  6. package/docs/principles.doc.mjs +4 -0
  7. package/docs/principles.doc.zh.mjs +2 -2
  8. package/docs/theme.doc.mjs +2 -2
  9. package/package.json +13 -1
  10. package/src/api/blog.mjs +192 -0
  11. package/src/api/blog.test.mjs +144 -0
  12. package/src/api/component.mjs +253 -12
  13. package/src/api/discover.mjs +14 -7
  14. package/src/api/doctor.mjs +10 -25
  15. package/src/api/index.mjs +1 -0
  16. package/src/api/layout.mjs +11 -10
  17. package/src/api/layout.test.mjs +4 -1
  18. package/src/api/template-integration.test.mjs +225 -0
  19. package/src/api/template.mjs +242 -84
  20. package/src/api/validate-integration.mjs +370 -0
  21. package/src/api/validate-integration.test.mjs +222 -0
  22. package/src/codemod.mjs +93 -0
  23. package/src/codemod.test.mjs +134 -0
  24. package/src/codemods/__tests__/registry.test.mjs +1 -0
  25. package/src/codemods/__tests__/runner.test.mjs +103 -0
  26. package/src/codemods/integration-discovery.mjs +168 -0
  27. package/src/codemods/integration-discovery.test.mjs +234 -0
  28. package/src/codemods/integration-runner.mjs +109 -0
  29. package/src/codemods/registry.mjs +1 -0
  30. package/src/codemods/run-codemod.mjs +207 -0
  31. package/src/codemods/runner.mjs +73 -96
  32. package/src/codemods/transforms/v0.0.15/index.mjs +0 -13
  33. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +67 -0
  34. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +61 -0
  35. package/src/codemods/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +104 -0
  36. package/src/codemods/transforms/{v0.0.15 → v0.1.0}/drop-xds-prefix-imports.mjs +15 -4
  37. package/src/codemods/transforms/v0.1.0/index.mjs +43 -6
  38. package/src/codemods/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +77 -0
  39. package/src/codemods/transforms/v0.1.0/migrate-xds-declare-module.mjs +78 -0
  40. package/src/codemods/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +360 -0
  41. package/src/codemods/transforms/v0.1.3/index.mjs +19 -0
  42. package/src/codemods/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +260 -0
  43. package/src/commands/agent-docs.mjs +4 -1
  44. package/src/commands/blog.mjs +60 -0
  45. package/src/commands/build-theme.import-path.test.mjs +2 -12
  46. package/src/commands/build-theme.mjs +117 -0
  47. package/src/commands/build-theme.prose.test.mjs +5 -15
  48. package/src/commands/build-theme.watch.test.mjs +149 -0
  49. package/src/commands/component/index.mjs +44 -10
  50. package/src/commands/component-ownership.test.mjs +227 -0
  51. package/src/commands/discover.mjs +5 -16
  52. package/src/commands/doctor.test.mjs +3 -3
  53. package/src/commands/ensure-core-built.mjs +120 -0
  54. package/src/commands/json-contract.test.mjs +0 -32
  55. package/src/commands/swizzle.mjs +224 -235
  56. package/src/commands/swizzle.path-safety.test.mjs +3 -3
  57. package/src/commands/swizzle.routing.test.mjs +279 -0
  58. package/src/commands/template.mjs +33 -37
  59. package/src/commands/upgrade.config-ordering.test.mjs +273 -0
  60. package/src/commands/upgrade.integration-policy.test.mjs +204 -0
  61. package/src/commands/upgrade.mjs +349 -170
  62. package/src/commands/validate-integration.mjs +110 -0
  63. package/src/commands/validate-integration.test.mjs +124 -0
  64. package/src/config.mjs +7 -20
  65. package/src/config.test.mjs +89 -13
  66. package/src/index.mjs +8 -3
  67. package/src/integration.mjs +19 -0
  68. package/src/lib/component-discovery.mjs +177 -0
  69. package/src/lib/config-cache.mjs +91 -0
  70. package/src/lib/config-cache.test.mjs +83 -0
  71. package/src/lib/config-schema.mjs +41 -55
  72. package/src/lib/error-codes.mjs +15 -12
  73. package/src/lib/integration-warnings.mjs +62 -0
  74. package/src/lib/integration-warnings.test.mjs +102 -0
  75. package/src/lib/integrations.mjs +92 -115
  76. package/src/lib/integrations.test.mjs +88 -107
  77. package/src/lib/manifest.mjs +5 -2
  78. package/src/lib/module-loader.mjs +80 -0
  79. package/src/lib/module-loader.test.mjs +106 -0
  80. package/src/lib/project.mjs +502 -0
  81. package/src/lib/project.test.mjs +308 -0
  82. package/src/lib/site.mjs +20 -0
  83. package/src/template.mjs +73 -0
  84. package/src/template.test.mjs +127 -0
  85. package/src/types/api.d.ts +2 -6
  86. package/src/types/base.d.ts +3 -9
  87. package/src/types/codemod.d.ts +81 -0
  88. package/src/types/component.d.ts +27 -2
  89. package/src/types/config.d.ts +56 -85
  90. package/src/types/error-codes.d.ts +5 -3
  91. package/src/types/index.d.ts +0 -1
  92. package/src/types/integration.d.ts +29 -0
  93. package/src/types/swizzle.d.ts +9 -2
  94. package/src/types/template-api.d.ts +54 -0
  95. package/src/types/template.d.ts +10 -7
  96. package/src/types/upgrade.d.ts +29 -0
  97. package/src/types/validate-integration.d.ts +24 -0
  98. package/src/utils/github.mjs +0 -237
  99. package/src/utils/interactive.mjs +2 -2
  100. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.doc.mjs +14 -0
  101. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +28 -0
  102. package/templates/blocks/components/Blockquote/BlockquoteTestimonials.doc.mjs +14 -0
  103. package/templates/blocks/components/Blockquote/BlockquoteTestimonials.tsx +34 -0
  104. package/templates/blocks/components/Blockquote/BlockquoteWithCite.doc.mjs +14 -0
  105. package/templates/blocks/components/Blockquote/BlockquoteWithCite.tsx +21 -0
  106. package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.doc.mjs +14 -0
  107. package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.tsx +15 -0
  108. package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.doc.mjs +14 -0
  109. package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.tsx +16 -0
  110. package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.doc.mjs +19 -0
  111. package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.tsx +34 -0
  112. package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.doc.mjs +14 -0
  113. package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.tsx +30 -0
  114. package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.doc.mjs +14 -0
  115. package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.tsx +31 -0
  116. package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.doc.mjs +14 -0
  117. package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.tsx +26 -0
  118. package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.doc.mjs +14 -0
  119. package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.tsx +32 -0
  120. package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.doc.mjs +18 -0
  121. package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.tsx +32 -0
  122. package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.doc.mjs +14 -0
  123. package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.tsx +27 -0
  124. package/templates/blocks/components/ContextMenu/ContextMenuBasic.doc.mjs +14 -0
  125. package/templates/blocks/components/ContextMenu/ContextMenuBasic.tsx +32 -0
  126. package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.doc.mjs +14 -0
  127. package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.tsx +46 -0
  128. package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.doc.mjs +14 -0
  129. package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.tsx +52 -0
  130. package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.doc.mjs +14 -0
  131. package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.tsx +43 -0
  132. package/templates/blocks/components/DialogHeader/DialogHeaderBasic.doc.mjs +14 -0
  133. package/templates/blocks/components/DialogHeader/DialogHeaderBasic.tsx +30 -0
  134. package/templates/blocks/components/DropdownMenu/DropdownMenuShowcase.tsx +0 -6
  135. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.doc.mjs +14 -0
  136. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.tsx +27 -0
  137. package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemShowcase.tsx +1 -5
  138. package/templates/blocks/components/FieldLabel/FieldLabelBasic.doc.mjs +14 -0
  139. package/templates/blocks/components/FieldLabel/FieldLabelBasic.tsx +20 -0
  140. package/templates/blocks/components/FieldStatus/FieldStatusBasic.doc.mjs +14 -0
  141. package/templates/blocks/components/FieldStatus/FieldStatusBasic.tsx +23 -0
  142. package/templates/blocks/components/FileInput/FileInputBasic.doc.mjs +14 -0
  143. package/templates/blocks/components/FileInput/FileInputBasic.tsx +22 -0
  144. package/templates/blocks/components/GridSpan/GridSpanColumns.doc.mjs +14 -0
  145. package/templates/blocks/components/GridSpan/GridSpanColumns.tsx +38 -0
  146. package/templates/blocks/components/HStack/HStackBasic.doc.mjs +14 -0
  147. package/templates/blocks/components/HStack/HStackBasic.tsx +16 -0
  148. package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.doc.mjs +14 -0
  149. package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.tsx +57 -0
  150. package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.doc.mjs +1 -1
  151. package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +9 -4
  152. package/templates/blocks/components/InputGroup/InputGroupBasic.doc.mjs +14 -0
  153. package/templates/blocks/components/InputGroup/InputGroupBasic.tsx +27 -0
  154. package/templates/blocks/components/LayoutContent/LayoutContentBasic.doc.mjs +23 -0
  155. package/templates/blocks/components/LayoutContent/LayoutContentBasic.tsx +40 -0
  156. package/templates/blocks/components/LayoutFooter/LayoutFooterActions.doc.mjs +22 -0
  157. package/templates/blocks/components/LayoutFooter/LayoutFooterActions.tsx +41 -0
  158. package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.doc.mjs +23 -0
  159. package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.tsx +40 -0
  160. package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.doc.mjs +22 -0
  161. package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.tsx +37 -0
  162. package/templates/blocks/components/Lightbox/LightboxGallery.doc.mjs +14 -0
  163. package/templates/blocks/components/Lightbox/LightboxGallery.tsx +53 -0
  164. package/templates/blocks/components/Lightbox/LightboxShowcase.tsx +4 -3
  165. package/templates/blocks/components/Lightbox/LightboxVideo.doc.mjs +14 -0
  166. package/templates/blocks/components/Lightbox/LightboxVideo.tsx +27 -0
  167. package/templates/blocks/components/Lightbox/LightboxZoom.doc.mjs +14 -0
  168. package/templates/blocks/components/Lightbox/LightboxZoom.tsx +33 -0
  169. package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.doc.mjs +1 -1
  170. package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.doc.mjs +14 -0
  171. package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.tsx +19 -0
  172. package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.doc.mjs +23 -0
  173. package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.tsx +42 -0
  174. package/templates/blocks/components/MoreMenu/MoreMenuShowcase.tsx +0 -6
  175. package/templates/blocks/components/NavIcon/NavIconBasic.doc.mjs +14 -0
  176. package/templates/blocks/components/NavIcon/NavIconBasic.tsx +16 -0
  177. package/templates/blocks/components/RadioListItem/RadioListItemBasic.doc.mjs +14 -0
  178. package/templates/blocks/components/RadioListItem/RadioListItemBasic.tsx +30 -0
  179. package/templates/blocks/components/Resizable/ResizableSidebar.doc.mjs +25 -0
  180. package/templates/blocks/components/Resizable/ResizableSidebar.tsx +67 -0
  181. package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.doc.mjs +14 -0
  182. package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.tsx +21 -0
  183. package/templates/blocks/components/SelectorOption/SelectorOptionBasic.doc.mjs +14 -0
  184. package/templates/blocks/components/SelectorOption/SelectorOptionBasic.tsx +39 -0
  185. package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.doc.mjs +14 -0
  186. package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.tsx +55 -0
  187. package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.doc.mjs +14 -0
  188. package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.tsx +38 -0
  189. package/templates/blocks/components/SideNavItem/SideNavItemBasic.doc.mjs +14 -0
  190. package/templates/blocks/components/SideNavItem/SideNavItemBasic.tsx +49 -0
  191. package/templates/blocks/components/SideNavSection/SideNavSectionBasic.doc.mjs +14 -0
  192. package/templates/blocks/components/SideNavSection/SideNavSectionBasic.tsx +71 -0
  193. package/templates/blocks/components/StackItem/StackItemFill.doc.mjs +14 -0
  194. package/templates/blocks/components/StackItem/StackItemFill.tsx +28 -0
  195. package/templates/blocks/components/Tab/TabWithSelectedIcon.doc.mjs +13 -0
  196. package/templates/blocks/components/Tab/TabWithSelectedIcon.tsx +39 -0
  197. package/templates/blocks/components/TabMenu/TabMenuBasic.doc.mjs +14 -0
  198. package/templates/blocks/components/TabMenu/TabMenuBasic.tsx +23 -0
  199. package/templates/blocks/components/Table/StickyColumnsHookUsage.doc.mjs +1 -1
  200. package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.doc.mjs +14 -0
  201. package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.tsx +47 -0
  202. package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.doc.mjs +14 -0
  203. package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.tsx +22 -0
  204. package/templates/blocks/components/TopNavItem/TopNavItemBasic.doc.mjs +14 -0
  205. package/templates/blocks/components/TopNavItem/TopNavItemBasic.tsx +21 -0
  206. package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.doc.mjs +20 -0
  207. package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.tsx +46 -0
  208. package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.doc.mjs +14 -0
  209. package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.tsx +16 -0
  210. package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.doc.mjs +14 -0
  211. package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.tsx +26 -0
  212. package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.doc.mjs +14 -0
  213. package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.tsx +43 -0
  214. package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.doc.mjs +14 -0
  215. package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.tsx +43 -0
  216. package/templates/blocks/components/VStack/VStackBasic.doc.mjs +14 -0
  217. package/templates/blocks/components/VStack/VStackBasic.tsx +20 -0
  218. package/templates/pages/kanban-board/page.tsx +729 -0
  219. package/templates/pages/kanban-board/template.doc.mjs +12 -0
  220. package/templates/pages/shell-nav/page.tsx +321 -0
  221. package/templates/pages/shell-nav/template.doc.mjs +12 -0
  222. package/templates/pages/shell-side-nav/page.tsx +241 -0
  223. package/templates/pages/shell-side-nav/template.doc.mjs +12 -0
  224. package/templates/pages/shell-top-nav/page.tsx +224 -0
  225. package/templates/pages/shell-top-nav/template.doc.mjs +12 -0
  226. package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-config-surfaces.test.mjs +0 -116
  227. package/src/codemods/transforms/v0.1.0/migrate-xds-config-surfaces.mjs +0 -230
  228. package/src/commands/gap-report.mjs +0 -464
  229. package/src/commands/gap-report.test.mjs +0 -168
  230. package/src/commands/swizzle-gap-safety.test.mjs +0 -273
  231. package/src/lib/config.mjs +0 -113
  232. package/src/lib/config.test.mjs +0 -91
  233. package/src/types/gap-report.d.ts +0 -29
  234. package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.doc.mjs +0 -14
  235. package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.tsx +0 -64
  236. package/templates/blocks/components/TreeListItem/TreeListItemShowcase.doc.mjs +0 -14
  237. package/templates/blocks/components/TreeListItem/TreeListItemShowcase.tsx +0 -60
  238. /package/src/codemods/transforms/{v0.0.15 → v0.1.0}/__tests__/drop-xds-prefix-imports.test.mjs +0 -0
@@ -4,69 +4,9 @@
4
4
  * @file GitHub utilities for Astryx CLI
5
5
  *
6
6
  * Shared helpers for interacting with the GitHub CLI (`gh`).
7
- * Used by gap-report and swizzle commands.
8
- *
9
- * Gap reporting can be configured via astryx.config.mjs:
10
- * gapReport: false — disable entirely
11
- * gapReport: { command: './scripts/report-gap.sh' } — run custom script (receives JSON on stdin)
12
- *
13
- * Or via environment variable:
14
- * ASTRYX_GAP_REPORT=off — disable entirely
15
- * ASTRYX_GAP_REPORT=./scripts/report-gap.sh — run custom script
16
7
  */
17
8
 
18
9
  import {execFileSync} from 'node:child_process';
19
- import * as path from 'node:path';
20
- import {loadConfig} from '../lib/config.mjs';
21
-
22
- /** Default target repository for gap report issues. */
23
- const DEFAULT_REPO = 'facebookexperimental/xds';
24
-
25
- /** Gap report category options. */
26
- export const GAP_CATEGORIES = [
27
- {value: 'missing_component', label: 'Missing component'},
28
- {value: 'missing_variant', label: 'Missing variant or prop'},
29
- {value: 'layout_gap', label: 'Layout gap'},
30
- {value: 'styling_gap', label: 'Styling gap'},
31
- {value: 'a11y_gap', label: 'Accessibility gap'},
32
- {value: 'api_friction', label: 'API friction'},
33
- {value: 'docs_gap', label: 'Documentation gap'},
34
- {value: 'other', label: 'Other'},
35
- ];
36
-
37
- /**
38
- * Load gap report configuration.
39
- *
40
- * Priority: env var > astryx.config.mjs > default (GitHub issue)
41
- *
42
- * Returns { enabled: boolean, command?: string }
43
- * - enabled: false → gap reporting disabled
44
- * - command: string → run this script instead of creating a GitHub issue
45
- * - neither → default behavior (GitHub issue to facebookexperimental/xds)
46
- */
47
- export async function loadGapReportConfig() {
48
- // 1. Check environment variable
49
- const envVar = process.env.ASTRYX_GAP_REPORT;
50
- if (envVar) {
51
- if (envVar === 'off' || envVar === 'false' || envVar === '0') {
52
- return {enabled: false};
53
- }
54
- // Treat as custom command
55
- return {enabled: true, command: envVar};
56
- }
57
-
58
- // 2. Check astryx.config.mjs + integration manifests
59
- const config = await loadConfig(process.cwd());
60
- if (config.gapReport !== undefined) {
61
- if (config.gapReport === false) return {enabled: false};
62
- if (config.gapReport?.command) {
63
- return {enabled: true, command: config.gapReport.command};
64
- }
65
- }
66
-
67
- // 3. Default
68
- return {enabled: true};
69
- }
70
10
 
71
11
  /**
72
12
  * Check if `gh` CLI is installed and authenticated.
@@ -80,180 +20,3 @@ export function checkGhCli() {
80
20
  return false;
81
21
  }
82
22
  }
83
-
84
- /**
85
- * Idempotently create the `gap-report` and `gap-analysis` labels.
86
- * Uses `--force` to avoid errors if labels already exist.
87
- */
88
- function ensureGapReportLabel() {
89
- try {
90
- execFileSync(
91
- 'gh',
92
- [
93
- 'label',
94
- 'create',
95
- 'gap-report',
96
- '--repo',
97
- DEFAULT_REPO,
98
- '--color',
99
- 'D4C5F9',
100
- '--description',
101
- 'Auto-filed gap report from swizzle/gap-report CLI',
102
- '--force',
103
- ],
104
- {stdio: 'ignore'},
105
- );
106
- execFileSync(
107
- 'gh',
108
- [
109
- 'label',
110
- 'create',
111
- 'gap-analysis',
112
- '--repo',
113
- DEFAULT_REPO,
114
- '--color',
115
- '0E8A16',
116
- '--description',
117
- 'Curated gap analysis summary',
118
- '--force',
119
- ],
120
- {stdio: 'ignore'},
121
- );
122
- } catch {
123
- // Best-effort — labels may already exist or user may lack permissions
124
- }
125
- }
126
-
127
- /**
128
- * Run a custom gap report command, piping report data as JSON to stdin.
129
- *
130
- * @param {string} command Script path to execute
131
- * @param {object} report Report data (component, category, intention, detail, source)
132
- * @returns {string} stdout from the command
133
- */
134
- function runCustomCommand(command, report) {
135
- const resolved = path.resolve(process.cwd(), command);
136
- const json = JSON.stringify(report, null, 2);
137
-
138
- const result = execFileSync(resolved, [], {
139
- input: json,
140
- encoding: 'utf-8',
141
- });
142
-
143
- return result.trim();
144
- }
145
-
146
- /**
147
- * Build the report payload + rendered title/body for a gap report.
148
- * Pure function — no side effects, never calls `gh` or external scripts.
149
- *
150
- * @returns {{
151
- * enabled: boolean,
152
- * mode: 'disabled' | 'custom' | 'github',
153
- * command?: string,
154
- * report: object,
155
- * title: string,
156
- * body: string,
157
- * repo: string,
158
- * }}
159
- */
160
- export async function buildGapReportPreview({
161
- component,
162
- category,
163
- intention,
164
- detail,
165
- source = 'cli',
166
- }) {
167
- const config = await loadGapReportConfig();
168
- const categoryLabel =
169
- GAP_CATEGORIES.find(c => c.value === category)?.label ?? category;
170
-
171
- const report = {
172
- component,
173
- category,
174
- categoryLabel,
175
- intention,
176
- detail: detail || null,
177
- source,
178
- timestamp: new Date().toISOString(),
179
- };
180
-
181
- const title = `[gap] ${component}: ${intention.slice(0, 70)}`;
182
- const body = [
183
- '| Field | Value |',
184
- '|-------|-------|',
185
- `| **Component** | ${component} |`,
186
- `| **Category** | ${categoryLabel} |`,
187
- `| **Source** | ${source} |`,
188
- `| **Timestamp** | ${report.timestamp} |`,
189
- '',
190
- '## User Intention',
191
- '',
192
- intention,
193
- ...(detail ? ['', '## Additional Context', '', detail] : []),
194
- ].join('\n');
195
-
196
- let mode = 'github';
197
- if (!config.enabled) mode = 'disabled';
198
- else if (config.command) mode = 'custom';
199
-
200
- return {
201
- enabled: config.enabled,
202
- mode,
203
- command: config.command,
204
- report,
205
- title,
206
- body,
207
- repo: DEFAULT_REPO,
208
- };
209
- }
210
-
211
- /**
212
- * Create a gap report — either via GitHub issue or custom command.
213
- *
214
- * SAFETY: This actually invokes `gh issue create` (or runs the custom command).
215
- * Callers MUST gate this behind explicit user confirmation or a `--commit`-style
216
- * flag in non-interactive contexts. Use `buildGapReportPreview` for dry-run.
217
- *
218
- * @param {object} opts
219
- * @param {string} opts.component Component name (e.g. "Button")
220
- * @param {string} opts.category One of GAP_CATEGORIES values
221
- * @param {string} opts.intention What the user was trying to achieve
222
- * @param {string} [opts.detail] Additional context
223
- * @param {string} [opts.source] Who filed it: "interactive", "llm-auto", "cli"
224
- * @returns {string|null} URL of the created issue (or custom command output), null if disabled
225
- */
226
- export async function createGapReport(opts) {
227
- const preview = await buildGapReportPreview(opts);
228
-
229
- if (!preview.enabled) {
230
- return null;
231
- }
232
-
233
- // Custom command mode — pipe JSON to the script
234
- if (preview.mode === 'custom') {
235
- return runCustomCommand(preview.command, preview.report);
236
- }
237
-
238
- // Default mode — create GitHub issue
239
- ensureGapReportLabel();
240
-
241
- const result = execFileSync(
242
- 'gh',
243
- [
244
- 'issue',
245
- 'create',
246
- '--repo',
247
- preview.repo,
248
- '--title',
249
- preview.title,
250
- '--body',
251
- preview.body,
252
- '--label',
253
- 'gap-report',
254
- ],
255
- {encoding: 'utf-8'},
256
- );
257
-
258
- return result.trim();
259
- }
@@ -18,8 +18,8 @@
18
18
  * fail fast (exit 1) with actionable, non-interactive guidance.
19
19
  *
20
20
  * - `isInteractive()` — for commands with an OPTIONAL secondary prompt
21
- * (e.g. swizzle's post-copy "report a gap?"). The primary work already
22
- * succeeded; callers use this to skip the prompt gracefully.
21
+ * that runs after the primary work has already succeeded; callers use
22
+ * this to skip the prompt gracefully in non-interactive contexts.
23
23
  */
24
24
 
25
25
  /**
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'AvatarStatusDot',
7
+ name: 'AvatarStatusDot — Variants',
8
+ displayName: 'AvatarStatusDot — Variants',
9
+ description:
10
+ 'Presence dots on Avatars using the success, neutral, and error variants. Pass an AvatarStatusDot to the Avatar status prop; the dot sizes itself to match the Avatar.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['Avatar', 'AvatarStatusDot', 'HStack'],
14
+ };
@@ -0,0 +1,28 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Avatar, AvatarStatusDot} from '@astryxdesign/core/Avatar';
6
+ import {HStack} from '@astryxdesign/core/Layout';
7
+
8
+ export default function AvatarStatusDotVariants() {
9
+ return (
10
+ <HStack gap={4} vAlign="center">
11
+ <Avatar
12
+ name="Ana Silva"
13
+ size="large"
14
+ status={<AvatarStatusDot variant="success" label="Online" />}
15
+ />
16
+ <Avatar
17
+ name="Ben Okafor"
18
+ size="large"
19
+ status={<AvatarStatusDot variant="neutral" label="Away" />}
20
+ />
21
+ <Avatar
22
+ name="Cleo Marsh"
23
+ size="large"
24
+ status={<AvatarStatusDot variant="error" label="Do not disturb" />}
25
+ />
26
+ </HStack>
27
+ );
28
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'Blockquote',
7
+ name: 'Blockquote — Testimonials',
8
+ displayName: 'Blockquote — Testimonials',
9
+ description:
10
+ 'Multiple quotes arranged in a card grid for a testimonials section. Combine with Card and Grid to create social-proof layouts.',
11
+ isReady: true,
12
+ aspectRatio: 4 / 3,
13
+ componentsUsed: ['Blockquote', 'Card', 'Grid', 'GridSpan'],
14
+ };
@@ -0,0 +1,34 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Blockquote} from '@astryxdesign/core/Blockquote';
6
+ import {Grid, GridSpan} from '@astryxdesign/core/Grid';
7
+ import {Card} from '@astryxdesign/core/Card';
8
+
9
+ export default function BlockquoteTestimonials() {
10
+ return (
11
+ <Grid columns={2} gap={3} style={{maxWidth: 600}}>
12
+ <Card padding={4}>
13
+ <Blockquote cite="Sarah K., Lead Engineer">
14
+ Shipping UI has never been this fast. Our team went from design to
15
+ production in a single afternoon.
16
+ </Blockquote>
17
+ </Card>
18
+ <Card padding={4}>
19
+ <Blockquote cite="Marcus T., Product Designer">
20
+ The token system means every new screen just looks right — no manual
21
+ color or spacing decisions.
22
+ </Blockquote>
23
+ </Card>
24
+ <GridSpan columns={2}>
25
+ <Card padding={4}>
26
+ <Blockquote cite="Priya L., Engineering Manager">
27
+ Onboarding a new engineer used to take a week of design review. Now
28
+ they're shipping accessible, polished components on day one.
29
+ </Blockquote>
30
+ </Card>
31
+ </GridSpan>
32
+ </Grid>
33
+ );
34
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'Blockquote',
7
+ name: 'Blockquote — With Attribution',
8
+ displayName: 'Blockquote — With Attribution',
9
+ description:
10
+ 'A plain quote and a quote with a cite attribution. Use cite to credit the original author or source.',
11
+ isReady: true,
12
+ aspectRatio: 4 / 3,
13
+ componentsUsed: ['Blockquote', 'Layout'],
14
+ };
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Blockquote} from '@astryxdesign/core/Blockquote';
6
+ import {VStack} from '@astryxdesign/core/Layout';
7
+
8
+ export default function BlockquoteWithCite() {
9
+ return (
10
+ <VStack gap={4} style={{maxWidth: 500}}>
11
+ <Blockquote>
12
+ Design is not just what it looks like and feels like. Design is how it
13
+ works.
14
+ </Blockquote>
15
+ <Blockquote cite="Steve Jobs">
16
+ The people who are crazy enough to think they can change the world are
17
+ the ones who do.
18
+ </Blockquote>
19
+ </VStack>
20
+ );
21
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'BreadcrumbItem',
7
+ name: 'BreadcrumbItem — Basic',
8
+ displayName: 'BreadcrumbItem — Basic',
9
+ description:
10
+ 'Breadcrumb links inside a Breadcrumbs trail. Ancestor pages get an href; mark the last item with isCurrent to render it as plain text for the current page.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['Breadcrumbs', 'BreadcrumbItem'],
14
+ };
@@ -0,0 +1,15 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Breadcrumbs, BreadcrumbItem} from '@astryxdesign/core/Breadcrumbs';
6
+
7
+ export default function BreadcrumbItemBasic() {
8
+ return (
9
+ <Breadcrumbs>
10
+ <BreadcrumbItem href="/">Home</BreadcrumbItem>
11
+ <BreadcrumbItem href="/settings">Settings</BreadcrumbItem>
12
+ <BreadcrumbItem isCurrent>Profile</BreadcrumbItem>
13
+ </Breadcrumbs>
14
+ );
15
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'ButtonGroup',
7
+ name: 'ButtonGroup — Basic',
8
+ displayName: 'ButtonGroup — Basic',
9
+ description:
10
+ 'Three related actions joined into a single connected control. Provide a group label for accessibility and keep all buttons the same variant so they read as one unit.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['ButtonGroup', 'Button'],
14
+ };
@@ -0,0 +1,16 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {ButtonGroup} from '@astryxdesign/core/ButtonGroup';
6
+ import {Button} from '@astryxdesign/core/Button';
7
+
8
+ export default function ButtonGroupBasic() {
9
+ return (
10
+ <ButtonGroup label="Text editing actions">
11
+ <Button label="Copy" />
12
+ <Button label="Cut" />
13
+ <Button label="Paste" />
14
+ </ButtonGroup>
15
+ );
16
+ }
@@ -0,0 +1,19 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'ChatDictationButton',
7
+ name: 'ChatDictationButton — Basic',
8
+ displayName: 'ChatDictationButton — Basic',
9
+ description:
10
+ 'A dictation button wired to useChatDictation and placed in the sendActions slot of a ChatComposer. Click the microphone to transcribe speech into the input.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: [
14
+ 'Chat',
15
+ 'ChatDictationButton',
16
+ 'ChatComposer',
17
+ 'ChatComposerInput',
18
+ ],
19
+ };
@@ -0,0 +1,34 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {useRef} from 'react';
6
+ import {
7
+ ChatDictationButton,
8
+ ChatComposer,
9
+ ChatComposerInput,
10
+ useChatDictation,
11
+ } from '@astryxdesign/core/Chat';
12
+ import type {ChatComposerInputHandle} from '@astryxdesign/core/Chat';
13
+ import {Stack} from '@astryxdesign/core/Layout';
14
+
15
+ export default function ChatDictationButtonBasic() {
16
+ const inputRef = useRef<ChatComposerInputHandle>(null);
17
+
18
+ const dictation = useChatDictation({
19
+ inputRef,
20
+ onResult: text => {
21
+ console.log('Dictation result:', text);
22
+ },
23
+ });
24
+
25
+ return (
26
+ <Stack direction="vertical" width="100%" style={{maxWidth: 450}}>
27
+ <ChatComposer
28
+ onSubmit={value => console.log('Submit:', value)}
29
+ input={<ChatComposerInput handleRef={inputRef} />}
30
+ sendActions={<ChatDictationButton dictation={dictation} />}
31
+ />
32
+ </Stack>
33
+ );
34
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'CheckboxListItem',
7
+ name: 'CheckboxListItem — Basic',
8
+ displayName: 'CheckboxListItem — Basic',
9
+ description:
10
+ 'Checkbox items with labels and descriptions inside a controlled CheckboxList. Use for multi-select option groups like notification preferences.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['CheckboxList', 'CheckboxListItem'],
14
+ };
@@ -0,0 +1,30 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {useState} from 'react';
6
+ import {CheckboxList, CheckboxListItem} from '@astryxdesign/core/CheckboxList';
7
+
8
+ export default function CheckboxListItemBasic() {
9
+ const [value, setValue] = useState<string[]>(['updates']);
10
+
11
+ return (
12
+ <CheckboxList label="Email preferences" value={value} onChange={setValue}>
13
+ <CheckboxListItem
14
+ label="Product updates"
15
+ value="updates"
16
+ description="New features and improvements"
17
+ />
18
+ <CheckboxListItem
19
+ label="Security alerts"
20
+ value="security"
21
+ description="Important account security notifications"
22
+ />
23
+ <CheckboxListItem
24
+ label="Marketing"
25
+ value="marketing"
26
+ description="Tips, offers, and promotions"
27
+ />
28
+ </CheckboxList>
29
+ );
30
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'CollapsibleGroup',
7
+ name: 'CollapsibleGroup — Accordion',
8
+ displayName: 'CollapsibleGroup — Accordion',
9
+ description:
10
+ 'An accordion built with type="single": opening one Collapsible automatically closes the others. Use defaultValue to pre-expand the most important section.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['CollapsibleGroup', 'Collapsible', 'VStack', 'Text'],
14
+ };
@@ -0,0 +1,31 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Collapsible, CollapsibleGroup} from '@astryxdesign/core/Collapsible';
6
+ import {VStack} from '@astryxdesign/core/Layout';
7
+ import {Text} from '@astryxdesign/core/Text';
8
+
9
+ export default function CollapsibleGroupAccordion() {
10
+ return (
11
+ <CollapsibleGroup type="single" defaultValue="account">
12
+ <VStack gap={2} width="100%">
13
+ <Collapsible trigger="Account" value="account">
14
+ <Text type="body" color="secondary">
15
+ Manage your profile details, email address, and password.
16
+ </Text>
17
+ </Collapsible>
18
+ <Collapsible trigger="Notifications" value="notifications">
19
+ <Text type="body" color="secondary">
20
+ Choose which activity triggers email and push notifications.
21
+ </Text>
22
+ </Collapsible>
23
+ <Collapsible trigger="Billing" value="billing">
24
+ <Text type="body" color="secondary">
25
+ View invoices and update your payment method.
26
+ </Text>
27
+ </Collapsible>
28
+ </VStack>
29
+ </CollapsibleGroup>
30
+ );
31
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'CommandPaletteEmpty',
7
+ name: 'CommandPaletteEmpty — Basic',
8
+ displayName: 'CommandPaletteEmpty — Basic',
9
+ description:
10
+ 'A command palette with no results, showing a custom empty message via emptyBootstrapText. Use to explain why the palette is empty and what the user can do next.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['CommandPalette', 'CommandPaletteEmpty', 'Text'],
14
+ };
@@ -0,0 +1,26 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {useMemo} from 'react';
6
+ import {CommandPalette} from '@astryxdesign/core/CommandPalette';
7
+ import {Text} from '@astryxdesign/core/Text';
8
+ import {createStaticSource} from '@astryxdesign/core/Typeahead';
9
+
10
+ export default function CommandPaletteEmptyBasic() {
11
+ const emptySource = useMemo(() => createStaticSource([]), []);
12
+
13
+ return (
14
+ <CommandPalette
15
+ isOpen
16
+ isInline
17
+ onOpenChange={() => {}}
18
+ searchSource={emptySource}
19
+ emptyBootstrapText={
20
+ <Text type="supporting" color="secondary">
21
+ No commands available
22
+ </Text>
23
+ }
24
+ />
25
+ );
26
+ }
@@ -0,0 +1,14 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
4
+ export const doc = {
5
+ type: 'block',
6
+ exampleFor: 'CommandPaletteFooter',
7
+ name: 'CommandPaletteFooter — Basic',
8
+ displayName: 'CommandPaletteFooter — Basic',
9
+ description:
10
+ 'A command palette footer with no children, rendering the built-in keyboard navigation hints. Use CommandPaletteFooter without content to get the default arrow-key, Enter, and Esc hints below the results list.',
11
+ isReady: true,
12
+ aspectRatio: 16 / 9,
13
+ componentsUsed: ['CommandPalette', 'CommandPaletteFooter'],
14
+ };