@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # @xds/cli
2
2
 
3
+ # 0.1.3
4
+
5
+ #### New Features
6
+
7
+ - Add a hidden `astryx blog` command that reads the blog over the site's RSS feed and prints a post's plaintext (`.txt`) variant. The command is not shown in `--help` or the manifest and always reads from the canonical site origin.
8
+ - Component discovery is now package-ownership aware: --package scoping, source resolution for integration components, and package-qualified JSON listings.
9
+ - Strict config + integration v1 schema (integrations, issuesUrl, hooks.postCodemod) and new @astryxdesign/cli/integration export.
10
+ - File-based codemod API (createCodemod/createConfigCodemod) with the @astryxdesign/cli/codemod export and integration codemod discovery in upgrade.
11
+ - component, template, and upgrade now print a one-line non-blocking warning when a configured integration has validation issues, pointing to validate-integration.
12
+ - Add a Kanban Board page template: color-coded status columns, draggable task cards with priority tags, and board toolbar.
13
+ - Add frame-first layout guidance: new `astryx docs layout` topic (shell choice, region budgets, app archetypes, cards-vs-rows policy, responsive contracts), layout rules in the generated agent cheat sheet, and layout anti-patterns in `docs principles`.
14
+ - Add a v0.1.3 config codemod that migrates astryx.config layout.components to experimental.xle.components.
15
+ - Add v0.1.0 codemods for migrating `declare module "@xds/core/..."` type augmentations and `.xds-*` / `[data-xds-theme]` / `@layer xds-theme` CSS surfaces to their `@astryxdesign`/`astryx-*` equivalents.
16
+ - Introduce the Project configuration API as the single entry point for reading resolved project config, components, templates, codemods, and issue routing, replacing loadConfig. Misconfigured integrations are now skipped with a warning during upgrade instead of hard-failing, and a new --skip-codemod flag lets you re-run past a failed codemod.
17
+ - Add a Shell page-template category to the CLI: Top Nav, Side Nav, and Shell Nav app-shell scaffolds (#3245, #3246, #3247)
18
+ - Static template authoring API (createPageTemplate/createBlockTemplate) with the @astryxdesign/cli/template export and type-driven, package-scoped template discovery.
19
+ - Swizzle can now copy integration-owned components, rewrites escaping imports to the owning package, and routes maintainer feedback through config and integration issue URLs.
20
+ - `astryx theme build --watch`: rebuild a theme automatically whenever the source file changes, until interrupted with Ctrl-C. Removes the manual re-run step (and the stale-CSS confusion that comes with forgetting it) from the theme-authoring loop. Each rebuild runs in a child process so a build error is contained and the watcher keeps running. Not supported with `--json`. (#3375)
21
+ - Add the validate-integration command and integration issue model for checking an Astryx integration package's manifest and contributions.
22
+ - XLE app-component registration moved into validated config under experimental.xle.components (object form), replacing the unvalidated layout.components read.
23
+
24
+ #### Fixes
25
+
26
+ - Align the CLI error-code type declarations with the runtime error codes (add the missing ERR_AMBIGUOUS_TEMPLATE declaration).
27
+ - Correct the `doctor` theme-wiring hint to reference the real `astryx.theme` config field (was `xds.theme`) and update the agent-docs check wording to say "Astryx".
28
+ - Update the API/CLI parity harness for the package-qualified `component --list` shape, and make the component API reject a non-string name with a clean error instead of throwing.
29
+ - The XDS-prefix drop codemod now runs as a mandatory v0.1.0 upgrade step, so upgrading from 0.0.x rewrites prefixed imports (useXDSTheme, XDSButton, XDSIconRegistry, ...) to their bare names alongside the @xds/_ → @astryxdesign/_ scope rename.
30
+ - upgrade now runs core codemods before loading config, so a config codemod can repair an otherwise-invalid config; dry-run reports a fixable config and suggests the command to apply it.
31
+
32
+ #### Documentation
33
+
34
+ - Blockquote: add "With Attribution" and "Testimonials" examples (#3385)
35
+ - DateTimeInput and DateRangeInput: add example blocks so their docs pages have populated Examples sections and playground links (#2724)
36
+ - Add copyable example blocks to 46 component docs pages that previously showed only a hero visual and an empty Examples section (#3481)
37
+ - HoverCard: give the "Link Preview" example an interactive `Link` trigger so there is something to hover over (#2728)
38
+ - Lightbox: add Gallery, Video, and Zoom examples and fix the playground preview (#3301)
39
+ - Remove lingering references to the removed gap-report feature and swizzle gap flags; docs now reflect swizzle's maintainer feedback link.
40
+ - Tab: add an interactive example showing `icon` and `selectedIcon` on the Tab docs page (#2765)
41
+ - ToggleButtonGroup: add a vertical example block showing orientation="vertical" with single- and multi-select groups (#2707)
42
+
43
+ #### Other Changes
44
+
45
+ - Integration codemod and template-doc loading now use the shared module-loader util instead of duplicating the jiti/import logic.
46
+ - Extract the shared module-loading + conventional-file-discovery helpers used by config and integration loading into one internal util (no behavior change).
47
+ - Remove the standalone gap-report command. Swizzle now prints a short maintainer feedback link instead of filing issues.
48
+ - Load and validate user-authored config, integration, codemod, and template modules through one shared module loader; create\* factories are now type-only and validation happens at load.
49
+ - Remove the obsolete xds config-surface migration codemod and unify config codemod execution on the shared (file, api) runner used by integration codemods.
50
+
51
+ #### Contributors
52
+
53
+ Thanks to everyone who contributed to this release:
54
+
55
+ - @AKnassa
56
+ - @ejhammond
57
+ - @ernestt
58
+ - @harshavardhan194
59
+ - @josephfarina
60
+ - @kentonquatman
61
+ - @mohitWeb-lab
62
+ - @pollychen-lab
63
+ - @thedjpetersen
64
+
65
+ ---
66
+
3
67
  # 0.1.2
4
68
 
5
69
  #### Breaking Changes
@@ -110,7 +174,6 @@ Thanks to everyone who contributed to this release:
110
174
  Thanks to everyone who contributed to this release:
111
175
 
112
176
  - @ejhammond
113
- - @joeyfarina
114
177
  - @josephfarina
115
178
  - @nynexman4464
116
179
 
package/README.md CHANGED
@@ -62,8 +62,7 @@ Options:
62
62
  | `upgrade` | Run codemods to migrate between versions |
63
63
  | `theme build` | Compile a defineTheme file to production CSS and JS |
64
64
  | `discover` | Discover external packages and components |
65
- | `gap-report` | Report a gap when a component doesn't meet your needs |
66
- | `doctor` | Diagnose your XDS setup and report problems with fixes (CI-friendly via exit code) |
65
+ | `doctor` | Diagnose your Astryx setup and report problems with fixes (CI-friendly via exit code) |
67
66
 
68
67
  ### Global options
69
68
 
@@ -161,7 +160,6 @@ if (isError(result)) {
161
160
  | `ERR_INVALID_VERSION` | A `--from`/`--to` value was not a valid semver string. |
162
161
  | `ERR_DEP_MISSING` | A required external dependency (e.g. jscodeshift) is missing. |
163
162
  | `ERR_GH_CLI` | GitHub CLI (`gh`) is not installed or not authenticated. |
164
- | `ERR_GAP_REPORT_FAILED` | Filing a gap report failed (disabled, or the integration errored). |
165
163
 
166
164
  ## Capability manifest (agent discovery)
167
165
 
@@ -172,7 +170,7 @@ discriminators each command can emit. Think of it as an OpenAPI spec for the CLI
172
170
 
173
171
  ```bash
174
172
  astryx manifest --json # dedicated surface — type: "manifest"
175
- xds --json # bare invocation — embeds the same payload under data.manifest
173
+ astryx --json # bare invocation — embeds the same payload under data.manifest
176
174
  ```
177
175
 
178
176
  Shape:
@@ -182,7 +180,7 @@ Shape:
182
180
  "apiVersion": 1,
183
181
  "type": "manifest",
184
182
  "data": {
185
- "name": "xds",
183
+ "name": "astryx",
186
184
  "version": "0.0.14",
187
185
  "description": "Design system CLI — components, themes, and tooling",
188
186
  "globalOptions": [
@@ -249,14 +247,14 @@ the `JSON_SUPPORTED` allowlist and a small declarative `RESPONSE_TYPES` map in
249
247
  `src/lib/manifest.mjs`, guarded by a drift test (`manifest.test.mjs`) so adding a
250
248
  command without describing it fails CI.
251
249
 
252
- **Backwards-compat:** the bare `xds --json` envelope keeps `type: "help"` and its
250
+ **Backwards-compat:** the bare `astryx --json` envelope keeps `type: "help"` and its
253
251
  original shallow fields (`name`, `version`, `commands` as a `string[]` of names,
254
252
  `jsonSupported`); the full structured manifest is additive under `data.manifest`.
255
253
  For the standalone manifest envelope (`type: "manifest"`), use `astryx manifest --json`.
256
254
 
257
255
  ## Programmatic API
258
256
 
259
- The same logic that powers `xds --json` is available as importable, type-safe functions:
257
+ The same logic that powers `astryx --json` is available as importable, type-safe functions:
260
258
 
261
259
  ```typescript
262
260
  import {
@@ -269,20 +267,20 @@ import {
269
267
  AstryxError,
270
268
  } from '@astryxdesign/cli/api';
271
269
 
272
- // Same result as: xds --json component Button
270
+ // Same result as: astryx --json component Button
273
271
  const btn = await component('Button');
274
272
  btn.type; // 'component.detail'
275
273
  btn.data.name; // 'Button' (typed as ComponentDoc)
276
274
 
277
- // Same result as: xds --json component --list
275
+ // Same result as: astryx --json component --list
278
276
  const list = await component(undefined, {list: true});
279
277
  list.data; // Record<string, string[]>
280
278
 
281
- // Same result as: xds --json docs principles
279
+ // Same result as: astryx --json docs principles
282
280
  const principles = await docs('principles');
283
- principles.data.title; // 'XDS Principles'
281
+ principles.data.title; // 'Principles'
284
282
 
285
- // Same result as: xds --json hook useMediaQuery
283
+ // Same result as: astryx --json hook useMediaQuery
286
284
  const useMediaQuery = await hook('useMediaQuery');
287
285
  useMediaQuery.data.params; // typed as HookParamDoc[]
288
286
 
@@ -296,7 +294,7 @@ try {
296
294
  }
297
295
  ```
298
296
 
299
- The CLI command handlers are thin wrappers around these functions: they parse args, call the API, then format the output (JSON or text). This guarantees that `@astryxdesign/cli/api` and `xds --json` always return identical data.
297
+ The CLI command handlers are thin wrappers around these functions: they parse args, call the API, then format the output (JSON or text). This guarantees that `@astryxdesign/cli/api` and `astryx --json` always return identical data.
300
298
 
301
299
  ### Consumer utilities
302
300
 
@@ -326,43 +324,41 @@ detail.data.name; // already narrowed
326
324
 
327
325
  Every response has a `type` string that uniquely identifies it:
328
326
 
329
- | Command | Type | Response |
330
- | ---------------------------------------------- | --------------------------- | --------------------------------- |
331
- | `xds --json component [--list]` | `component.list` | `ComponentListResponse` |
332
- | `xds --json component --list --detail compact` | `component.brief` | `ComponentBriefResponse` |
333
- | `xds --json component --list --detail full` | `component.full` | `ComponentFullResponse` |
334
- | `xds --json component <name>` | `component.detail` | `ComponentDetailResponse` |
335
- | `xds --json component <name> --props` | `component.detail.props` | `ComponentDetailPropsResponse` |
336
- | `xds --json component <name> --source` | `component.detail.source` | `ComponentDetailSourceResponse` |
337
- | `xds --json component <name> --showcase` | `component.detail.showcase` | `ComponentDetailShowcaseResponse` |
338
- | `xds --json component <name> --blocks` | `component.detail.blocks` | `ComponentDetailBlocksResponse` |
339
- | `xds --json discover` | `discover.list` | `DiscoverListResponse` |
340
- | `xds --json discover @scope/name` | `discover.detail` | `DiscoverDetailResponse` |
341
- | `xds --json discover @scope/name/Comp` | `discover.detail.doc` | `DiscoverDetailDocResponse` |
342
- | `xds --json discover <search>` | `discover.search` | `DiscoverSearchResponse` |
343
- | `xds --json docs` | `docs.list` | `DocsListResponse` |
344
- | `xds --json docs <topic>` | `docs.detail` | `DocsDetailResponse` |
345
- | `xds --json docs <topic> <section>` | `docs.detail.section` | `DocsDetailSectionResponse` |
346
- | `xds --json template [--list]` | `template.list` | `TemplateListResponse` |
347
- | `xds --json template <name>` | `template.show` | `TemplateShowResponse` |
348
- | `xds --json template <name> --skeleton` | `template.skeleton` | `TemplateSkeletonResponse` |
349
- | `xds --json template <name> [path]` | `template.copy` | `TemplateCopyResponse` |
350
- | `xds --json hook [--list]` | `hook.list` | `HookListResponse` |
351
- | `xds --json hook --list --detail compact` | `hook.brief` | `HookBriefResponse` |
352
- | `xds --json hook --list --detail full` | `hook.full` | `HookFullResponse` |
353
- | `xds --json hook <name>` | `hook.detail` | `HookDetailResponse` |
354
- | `xds --json hook <name> --params` | `hook.detail.params` | `HookDetailParamsResponse` |
355
- | `xds --json search <query>` | `search` | `SearchResponse` |
356
- | `xds --json swizzle [--list]` | `swizzle.list` | `SwizzleListResponse` |
357
- | `xds --json swizzle <component>` | `swizzle.copy` | `SwizzleCopyResponse` |
358
- | `xds --json theme build <file>` | `theme.build` | `ThemeBuildResponse` |
359
- | `xds --json upgrade --list` | `upgrade.list` | `UpgradeListResponse` |
360
- | `xds --json upgrade [--apply]` | `upgrade.run` | `UpgradeRunResponse` |
361
- | `xds --json gap-report --list-categories` | `gap-report.categories` | `GapReportCategoriesResponse` |
362
- | `xds --json gap-report --component X ...` | `gap-report.file` | `GapReportFileResponse` |
363
- | `xds --json doctor` | `doctor` | `DoctorResponse` |
364
- | any error | — | `CLIError` |
365
- | unsupported command | — | `CLIUnsupportedError` |
327
+ | Command | Type | Response |
328
+ | ------------------------------------------------- | --------------------------- | --------------------------------- |
329
+ | `astryx --json component [--list]` | `component.list` | `ComponentListResponse` |
330
+ | `astryx --json component --list --detail compact` | `component.brief` | `ComponentBriefResponse` |
331
+ | `astryx --json component --list --detail full` | `component.full` | `ComponentFullResponse` |
332
+ | `astryx --json component <name>` | `component.detail` | `ComponentDetailResponse` |
333
+ | `astryx --json component <name> --props` | `component.detail.props` | `ComponentDetailPropsResponse` |
334
+ | `astryx --json component <name> --source` | `component.detail.source` | `ComponentDetailSourceResponse` |
335
+ | `astryx --json component <name> --showcase` | `component.detail.showcase` | `ComponentDetailShowcaseResponse` |
336
+ | `astryx --json component <name> --blocks` | `component.detail.blocks` | `ComponentDetailBlocksResponse` |
337
+ | `astryx --json discover` | `discover.list` | `DiscoverListResponse` |
338
+ | `astryx --json discover @scope/name` | `discover.detail` | `DiscoverDetailResponse` |
339
+ | `astryx --json discover @scope/name/Comp` | `discover.detail.doc` | `DiscoverDetailDocResponse` |
340
+ | `astryx --json discover <search>` | `discover.search` | `DiscoverSearchResponse` |
341
+ | `astryx --json docs` | `docs.list` | `DocsListResponse` |
342
+ | `astryx --json docs <topic>` | `docs.detail` | `DocsDetailResponse` |
343
+ | `astryx --json docs <topic> <section>` | `docs.detail.section` | `DocsDetailSectionResponse` |
344
+ | `astryx --json template [--list]` | `template.list` | `TemplateListResponse` |
345
+ | `astryx --json template <name>` | `template.show` | `TemplateShowResponse` |
346
+ | `astryx --json template <name> --skeleton` | `template.skeleton` | `TemplateSkeletonResponse` |
347
+ | `astryx --json template <name> [path]` | `template.copy` | `TemplateCopyResponse` |
348
+ | `astryx --json hook [--list]` | `hook.list` | `HookListResponse` |
349
+ | `astryx --json hook --list --detail compact` | `hook.brief` | `HookBriefResponse` |
350
+ | `astryx --json hook --list --detail full` | `hook.full` | `HookFullResponse` |
351
+ | `astryx --json hook <name>` | `hook.detail` | `HookDetailResponse` |
352
+ | `astryx --json hook <name> --params` | `hook.detail.params` | `HookDetailParamsResponse` |
353
+ | `astryx --json search <query>` | `search` | `SearchResponse` |
354
+ | `astryx --json swizzle [--list]` | `swizzle.list` | `SwizzleListResponse` |
355
+ | `astryx --json swizzle <component>` | `swizzle.copy` | `SwizzleCopyResponse` |
356
+ | `astryx --json theme build <file>` | `theme.build` | `ThemeBuildResponse` |
357
+ | `astryx --json upgrade --list` | `upgrade.list` | `UpgradeListResponse` |
358
+ | `astryx --json upgrade [--apply]` | `upgrade.run` | `UpgradeRunResponse` |
359
+ | `astryx --json doctor` | `doctor` | `DoctorResponse` |
360
+ | any error | | `CLIError` |
361
+ | unsupported command | | `CLIUnsupportedError` |
366
362
 
367
363
  ## Doctor
368
364
 
@@ -383,7 +379,7 @@ astryx doctor — diagnosing your setup
383
379
  @astryxdesign/core v0.0.14 is in step with @astryxdesign/cli v0.0.14.
384
380
  ⚠ Theme packages
385
381
  No @astryxdesign/theme-* packages are installed.
386
- → fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set xds.theme.
382
+ → fix: Install a theme, e.g. `npm install @astryxdesign/theme-neutral`, then import its CSS or set astryx.theme.
387
383
  ℹ astryx.config.mjs
388
384
  No astryx.config.mjs found — using defaults.
389
385
  ℹ AI agent docs
@@ -408,7 +404,7 @@ No failures — but review the ⚠ warnings above when you can.
408
404
  | Version alignment | pass / warn / info | Installed `@astryxdesign/core` is in step with `@astryxdesign/cli` |
409
405
  | Theme packages | pass / warn | An `@astryxdesign/theme-*` package is installed and a theme is wired |
410
406
  | astryx.config.mjs | pass / fail / info | Config (if present) loads cleanly with a valid shape |
411
- | AI agent docs | pass / warn / info | Agent docs exist and contain the XDS section markers |
407
+ | AI agent docs | pass / warn / info | Agent docs exist and contain the Astryx section markers |
412
408
  | Peer dependencies | pass / warn / info | `@astryxdesign/core`'s peer deps (react, …) are installed |
413
409
  | Package manager | info | Reports the detected package manager |
414
410
 
@@ -434,8 +430,6 @@ export default {
434
430
  templates: {
435
431
  get: async id => fetchTemplateFromAPI(id),
436
432
  },
437
- gapReport: {
438
- url: 'https://your-api.com/gaps',
439
- },
433
+ issuesUrl: 'https://github.com/your-org/your-repo/issues',
440
434
  };
441
435
  ```
@@ -0,0 +1,90 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../core/src/docs-types').ReferenceTranslationDoc} */
4
+
5
+ export const docsDense = {
6
+ description:
7
+ 'frame-first app layout: shell choice, region budgets, cards vs rows',
8
+ sections: [
9
+ {
10
+ title: 'Frame First',
11
+ content: [
12
+ {
13
+ type: 'prose',
14
+ text: 'decide frame before content. content-first (Card-wrapped sections in a scroll column) = prototype look.',
15
+ },
16
+ {
17
+ type: 'list',
18
+ items: [
19
+ 'pick frame: AppShell (nav apps) | Layout+LayoutPanel+LayoutContent (multi-pane tools) | plain column (docs/forms)',
20
+ 'budget regions in px first: side nav 240-280, rail 64-72, inspector 340-420, facet rail 220-260',
21
+ 'container policy per region: dense data = rows; dashboards/galleries = card grids',
22
+ 'write responsive contract up front',
23
+ ],
24
+ },
25
+ null,
26
+ ],
27
+ },
28
+ {
29
+ title: 'App Archetypes',
30
+ content: [
31
+ {
32
+ type: 'prose',
33
+ text: 'container choice tracks archetype, not preference.',
34
+ },
35
+ null,
36
+ {
37
+ type: 'prose',
38
+ text: 'start from matching template (astryx template --list), study with --skeleton.',
39
+ },
40
+ ],
41
+ },
42
+ {
43
+ title: 'Cards vs Rows',
44
+ content: [
45
+ {
46
+ type: 'prose',
47
+ text: 'Card = widget container, NOT list-item wrapper. dense/scannable/selectable data = rows: Table (columnar) or List/Item (single-line), edge-to-edge, 32-40px rows, dividers.',
48
+ },
49
+ {
50
+ type: 'list',
51
+ items: [
52
+ 'Table+plugins: hosts, deployments, monitors, users',
53
+ 'List/Item rows: issues, files, conversations',
54
+ 'Card: KPI tiles, chart panels, gallery entries, settings groups',
55
+ 'EmptyState for zero-match',
56
+ ],
57
+ },
58
+ {
59
+ type: 'list',
60
+ items: [
61
+ 'no Card-wrapped list items (card soup)',
62
+ 'no stacked full-width Cards as page structure',
63
+ 'no Cards in Cards',
64
+ 'no decorative Badge — counts/enums only; StatusDot/Token for status',
65
+ ],
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ title: 'Panels and Inspectors',
71
+ content: [
72
+ {
73
+ type: 'prose',
74
+ text: 'master-detail: row select opens fixed-width inspector (LayoutPanel end slot + width budget + resizable/useResizable). overlay content <=1024px, do not compress.',
75
+ },
76
+ null,
77
+ ],
78
+ },
79
+ {
80
+ title: 'Responsive Contract',
81
+ content: [
82
+ {
83
+ type: 'prose',
84
+ text: 'declare breakpoint behavior as comment at frame root: which regions collapse/overlay/drop at which widths.',
85
+ },
86
+ null,
87
+ ],
88
+ },
89
+ ],
90
+ };
@@ -0,0 +1,160 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('../../core/src/docs-types').ReferenceDoc} */
4
+
5
+ export const docs = {
6
+ name: 'layout',
7
+ title: 'Layout',
8
+ category: 'guide',
9
+ description:
10
+ 'Frame-first app layout: choosing a shell, budgeting regions, and when to use cards vs rows.',
11
+
12
+ sections: [
13
+ {
14
+ title: 'Frame First',
15
+ content: [
16
+ {
17
+ type: 'prose',
18
+ text: 'Decide the frame before writing any content. Real applications are built top-down: pick the shell, name its regions, give each region an explicit size budget, then fill regions with content. Content-first layout (writing sections and wrapping each one in a Card) produces a padded scroll column that reads as a prototype, not a product.',
19
+ },
20
+ {
21
+ type: 'list',
22
+ style: 'ordered',
23
+ items: [
24
+ 'Pick the frame: AppShell (top nav and/or side nav apps), Layout + LayoutPanel + LayoutContent (multi-pane tools like explorers and consoles), or a plain content column (documents, marketing, forms)',
25
+ 'Budget regions in px before filling them: side nav 240–280, icon rail 64–72, detail/inspector panel 340–420, filter/facet rail 220–260',
26
+ 'Decide the container policy per region: dense data renders as rows; widget dashboards and galleries render as card grids (see Cards vs Rows)',
27
+ 'Write the responsive contract up front: which regions collapse, overlay, or drop at which breakpoints (see Responsive Contract)',
28
+ ],
29
+ },
30
+ {
31
+ type: 'code',
32
+ lang: 'tsx',
33
+ label: 'A three-region tool frame',
34
+ code: `// Frame: nav 256 | content flex | inspector 380 (resizable)
35
+ <AppShell sideNav={<SideNav>{/* nav items */}</SideNav>} contentPadding={0}>
36
+ <Layout>
37
+ <LayoutContent>{/* dense list or table, edge-to-edge */}</LayoutContent>
38
+ <LayoutPanel width={380} resizable={{minSizePx: 320, maxSizePx: 480}} hasDivider>
39
+ {/* inspector for the selected row */}
40
+ </LayoutPanel>
41
+ </Layout>
42
+ </AppShell>`,
43
+ },
44
+ ],
45
+ },
46
+ {
47
+ title: 'App Archetypes',
48
+ content: [
49
+ {
50
+ type: 'prose',
51
+ text: 'Match the frame and container policy to the kind of app you are building. These recipes are distilled from product-scale apps built with the design system; container choice tracks the archetype, not personal preference.',
52
+ },
53
+ {
54
+ type: 'table',
55
+ headers: ['Archetype', 'Frame', 'Container policy'],
56
+ rows: [
57
+ [
58
+ 'Tracker / work tool (issues, tickets, CRM)',
59
+ 'AppShell + SideNav; inspector LayoutPanel on select',
60
+ 'Rows only. Grouped edge-to-edge lists, zero cards',
61
+ ],
62
+ [
63
+ 'Console / observability (metrics, logs, deploys)',
64
+ 'AppShell + SideNav or TopNav + TabList',
65
+ 'Card grid for dashboard widgets; Table for everything else',
66
+ ],
67
+ [
68
+ 'Messaging / feed',
69
+ 'Column frame: rail + sidebar + stream + panel',
70
+ 'Rows and bubbles. No cards in the stream',
71
+ ],
72
+ [
73
+ 'Media library / gallery',
74
+ 'AppShell + TopNav; grid content',
75
+ 'Card grid (ClickableCard) with dense metadata rows in detail views',
76
+ ],
77
+ [
78
+ 'Settings / forms',
79
+ 'AppShell + SideNav or settings template',
80
+ 'Sections with FormLayout; Card only to group dangerous or billing actions',
81
+ ],
82
+ ],
83
+ },
84
+ {
85
+ type: 'prose',
86
+ text: 'Start from a template that matches the archetype (`npx astryx template --list`), then study its structure with `--skeleton` before customizing.',
87
+ },
88
+ ],
89
+ },
90
+ {
91
+ title: 'Cards vs Rows',
92
+ content: [
93
+ {
94
+ type: 'prose',
95
+ text: 'Card is a widget container, not a list-item wrapper. The fastest way to make an app look like a generic AI prototype is to wrap every record in a Card with a Badge. Dense data — anything the user scans, filters, or selects — belongs in rows: Table for columnar data, List/Item for single-line records, edge-to-edge with dividers and 32–40px row height.',
96
+ },
97
+ {
98
+ type: 'list',
99
+ style: 'do',
100
+ items: [
101
+ 'Table (with selection/sorting plugins) for columnar records: hosts, deployments, monitors, users',
102
+ 'List/Item rows for scannable single-line records: issues, files, conversations',
103
+ 'Card for self-contained widgets: KPI tiles, chart panels, gallery entries, settings groups',
104
+ 'EmptyState inside the region when a filter matches nothing',
105
+ ],
106
+ },
107
+ {
108
+ type: 'list',
109
+ style: 'dont',
110
+ items: [
111
+ 'Wrapping each list item in a Card (card soup)',
112
+ 'Stacking full-width Cards as a substitute for page structure',
113
+ 'Nesting Cards inside Cards',
114
+ 'Using Badge as decoration — reserve it for counts and enumerated states; use StatusDot or Token for status and metadata',
115
+ ],
116
+ },
117
+ ],
118
+ },
119
+ {
120
+ title: 'Panels and Inspectors',
121
+ content: [
122
+ {
123
+ type: 'prose',
124
+ text: 'Master-detail is the backbone of tool UIs: selecting a row opens a fixed-width inspector panel rather than navigating away. Use LayoutPanel in the end slot with an explicit width budget; add resizable (useResizable) for user control, and let the panel overlay the content region below ~1024px instead of compressing it.',
125
+ },
126
+ {
127
+ type: 'code',
128
+ lang: 'tsx',
129
+ label: 'Inspector that overlays at narrow widths',
130
+ code: `<LayoutPanel
131
+ width={380}
132
+ hasDivider
133
+ isScrollable
134
+ label="Details"
135
+ resizable={{minSizePx: 320, maxSizePx: 480, autoSaveId: 'inspector'}}>
136
+ {selected ? <DetailFields item={selected} /> : <EmptyState title="Nothing selected" />}
137
+ </LayoutPanel>`,
138
+ },
139
+ ],
140
+ },
141
+ {
142
+ title: 'Responsive Contract',
143
+ content: [
144
+ {
145
+ type: 'prose',
146
+ text: 'Declare breakpoint behavior as a contract before building, and keep it in a comment at the frame root. A typical contract: full frame above 1024px; inspector panels overlay the content column at 1024px and below; the side nav collapses into MobileNav at 768px and below. Deciding this up front keeps every region change intentional instead of emergent.',
147
+ },
148
+ {
149
+ type: 'code',
150
+ lang: 'tsx',
151
+ label: 'Contract comment at the frame root',
152
+ code: `// Responsive contract:
153
+ // > 1024px nav 256 | content | inspector 380
154
+ // <= 1024px inspector overlays content (position: absolute, end-aligned)
155
+ // <= 768px nav collapses into MobileNav drawer; toolbar actions wrap`,
156
+ },
157
+ ],
158
+ },
159
+ ],
160
+ };
@@ -6,9 +6,9 @@ export const docsDense = {
6
6
  description: 'core design principles + rules for the design system',
7
7
  sections: [
8
8
  { title: 'Philosophy', content: [{ type: 'list', items: ['components over primitives', 'semantic tokens over hardcoded values', 'theme-agnostic code', 'open internals'] }] },
9
- { title: 'Rules', content: [{ type: 'list', items: ['use components', 'StyleX or Tailwind for styling', 'semantic tokens only', 'CSS vars for colors', 'controlled form inputs', 'useLinkComponent() for navigation'] }] },
9
+ { title: 'Rules', content: [{ type: 'list', items: ['use components', 'frame-first layout: shell + region budgets before content (astryx docs layout)', 'dense data = rows (Table, List/Item) not Cards; Card = widgets/galleries/settings groups', 'StyleX or Tailwind for styling', 'semantic tokens only', 'CSS vars for colors', 'controlled form inputs', 'useLinkComponent() for navigation'] }] },
10
10
  { title: 'Styling', content: [{ type: 'prose', text: 'xstyle prop for component overrides. StyleX or Tailwind for layout. See astryx docs styling.' }] },
11
- { title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', 'read docs before inventing props'] }] },
11
+ { title: 'Anti-Patterns', content: [{ type: 'list', items: ['no inline styles on raw elements', 'no hardcoded colors — use tokens or Tailwind semantic classes', 'no hardcoded spacing', 'no hardcoded <a> — use useLinkComponent()', 'no Card-wrapped list items — frame first, rows for dense data (astryx docs layout)', 'no decorative Badge — StatusDot/Token for status', 'read docs before inventing props'] }] },
12
12
  { title: 'Tokens', content: [{ type: 'prose', text: 'run npx astryx docs tokens for full reference' }] },
13
13
  ],
14
14
  };
@@ -39,6 +39,8 @@ export const docs = {
39
39
  style: 'ordered',
40
40
  items: [
41
41
  'Use components for everything they cover',
42
+ 'Layout is frame-first: pick the shell and budget regions before writing content (see \`npx astryx docs layout\`)',
43
+ 'Dense data renders as rows (Table, List/Item), edge-to-edge with dividers; Card is for widgets, galleries, and settings groups',
42
44
  'StyleX or Tailwind for custom styling; both are first-class (see \`npx astryx docs styling\`)',
43
45
  'Semantic tokens, not hardcoded values (see \`npx astryx docs tokens\`)',
44
46
  'CSS custom properties for colors, not hex values',
@@ -74,6 +76,8 @@ export const docs = {
74
76
  'Hardcoded colors (#fff). Use var(--color-*) or Tailwind semantic classes (text-primary, bg-surface)',
75
77
  'Hardcoded spacing (16px). Use spacing tokens or Tailwind spacing utilities',
76
78
  'Hardcoded <a> elements. Use useLinkComponent() so consumers can swap in their framework router via LinkProvider',
79
+ 'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`npx astryx docs layout\`)',
80
+ 'Badge as decoration. Reserve Badge for counts and enumerated states; use StatusDot or Token for status',
77
81
  'Inventing props. Read component docs first',
78
82
  ],
79
83
  },
@@ -6,9 +6,9 @@ export const docsZh = {
6
6
  description: 'XDS 核心设计原则和规则。',
7
7
  sections: [
8
8
  { title: '设计哲学', content: [{ type: 'list', items: ['组件优于原始元素 — 优先使用 XDS 组件', '语义化令牌优于硬编码值', '主题无关的代码 — 深色模式自动生效', '开放的内部机制 — 所有基础组件均可导出和组合'] }] },
9
- { title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '使用 StyleX 或 Tailwind 进行样式设置', '使用语义化令牌,不使用硬编码值', '使用 CSS 变量设置颜色,不使用十六进制值', '表单输入为受控组件(value + onChange)', '使用 useLinkComponent() 进行导航'] }] },
9
+ { title: '规则', content: [{ type: 'list', items: ['所有支持的场景都使用 XDS 组件', '布局采用框架优先:先选定外壳并规划区域尺寸,再编写内容(见 astryx docs layout)', '密集数据使用行(Table、List/Item)通栏渲染;Card 用于小部件、画廊和设置分组', '使用 StyleX 或 Tailwind 进行样式设置', '使用语义化令牌,不使用硬编码值', '使用 CSS 变量设置颜色,不使用十六进制值', '表单输入为受控组件(value + onChange)', '使用 useLinkComponent() 进行导航'] }] },
10
10
  { title: '样式方法', content: [{ type: 'prose', text: '组件覆盖使用 xstyle 属性。布局使用 StyleX 或 Tailwind。详见 astryx docs styling。' }] },
11
- { title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '不要自创属性。先阅读组件文档'] }] },
11
+ { title: '反模式', content: [{ type: 'list', items: ['不要在原始元素上使用内联样式', '不要硬编码颜色 — 使用令牌或 Tailwind 语义类', '不要硬编码间距', '不要硬编码 <a> 元素 — 使用 useLinkComponent()', '不要把每个列表项都包在 Card 里 — 先定框架,密集数据用行渲染(见 astryx docs layout)', '不要把 Badge 当装饰 — 状态请使用 StatusDot 或 Token', '不要自创属性。先阅读组件文档'] }] },
12
12
  { title: '设计令牌', content: [{ type: 'prose', text: '运行 npx astryx docs tokens 查看完整参考' }] },
13
13
  ],
14
14
  };
@@ -53,7 +53,7 @@ function App() {
53
53
  },
54
54
  {
55
55
  type: 'prose',
56
- text: 'Each theme ships as its own npm package. Install the one you want, then wrap your app in `<Theme>` the same pattern works for every theme; just swap the package and import name.',
56
+ text: 'Each theme ships as its own npm package. Install the one you want, then wrap your app in `<Theme>`. The same pattern works for every theme; just swap the package and import name.',
57
57
  },
58
58
  {
59
59
  type: 'prose',
@@ -261,7 +261,7 @@ const brandTheme = defineTheme({
261
261
  content: [
262
262
  {
263
263
  type: 'prose',
264
- text: 'The `components` field in defineTheme uses semantic component keys and style keys not raw CSS selectors. Use `base` for all instances, `variant:value` or `stateName` for specific props/states, and let the theme pipeline choose the underlying selector. For raw external CSS escape hatches, prefer the data-attribute selector surface documented in `astryx docs styling`.',
264
+ text: 'The `components` field in defineTheme uses semantic component keys and style keys, not raw CSS selectors. Use `base` for all instances, `variant:value` or `stateName` for specific props/states, and let the theme pipeline choose the underlying selector. For raw external CSS escape hatches, prefer the data-attribute selector surface documented in `astryx docs styling`.',
265
265
  },
266
266
  {
267
267
  type: 'code',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "displayName": "CLI",
5
5
  "description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
6
6
  "author": "Meta Open Source",
@@ -43,6 +43,18 @@
43
43
  "types": "./src/types/config.d.ts",
44
44
  "import": "./src/config.mjs"
45
45
  },
46
+ "./integration": {
47
+ "types": "./src/types/integration.d.ts",
48
+ "import": "./src/integration.mjs"
49
+ },
50
+ "./template": {
51
+ "types": "./src/types/template-api.d.ts",
52
+ "import": "./src/template.mjs"
53
+ },
54
+ "./codemod": {
55
+ "types": "./src/types/codemod.d.ts",
56
+ "import": "./src/codemod.mjs"
57
+ },
46
58
  "./xle": {
47
59
  "types": "./src/lib/xle/browser.d.ts",
48
60
  "import": "./src/lib/xle/browser.mjs"