@astryxdesign/cli 0.1.4-canary.9ed1797 → 0.1.4-canary.a30efd1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/cli",
3
- "version": "0.1.4-canary.9ed1797",
3
+ "version": "0.1.4-canary.a30efd1",
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",
@@ -75,12 +75,16 @@
75
75
  "zod": "^4.4.3"
76
76
  },
77
77
  "peerDependencies": {
78
- "@astryxdesign/core": "0.1.4-canary.9ed1797",
79
- "@astryxdesign/lab": "0.1.4-canary.9ed1797",
80
- "@astryxdesign/theme-neutral": "0.1.4-canary.9ed1797",
81
- "gpt-tokenizer": "^2.0.0"
78
+ "@astryxdesign/charts": "0.1.4-canary.a30efd1",
79
+ "@astryxdesign/core": "0.1.4-canary.a30efd1",
80
+ "@astryxdesign/lab": "0.1.4-canary.a30efd1",
81
+ "@astryxdesign/theme-neutral": "0.1.4-canary.a30efd1",
82
+ "gpt-tokenizer": "^3.4.0"
82
83
  },
83
84
  "peerDependenciesMeta": {
85
+ "@astryxdesign/charts": {
86
+ "optional": true
87
+ },
84
88
  "@astryxdesign/core": {
85
89
  "optional": true
86
90
  },
@@ -92,10 +96,11 @@
92
96
  }
93
97
  },
94
98
  "devDependencies": {
95
- "@astryxdesign/core": "0.1.4-canary.9ed1797",
96
- "@astryxdesign/lab": "0.1.4-canary.9ed1797",
97
- "@astryxdesign/theme-neutral": "0.1.4-canary.9ed1797",
98
- "gpt-tokenizer": "^2.0.0"
99
+ "@astryxdesign/charts": "0.1.4-canary.a30efd1",
100
+ "@astryxdesign/core": "0.1.4-canary.a30efd1",
101
+ "@astryxdesign/lab": "0.1.4-canary.a30efd1",
102
+ "@astryxdesign/theme-neutral": "0.1.4-canary.a30efd1",
103
+ "gpt-tokenizer": "^3.4.0"
99
104
  },
100
105
  "scripts": {
101
106
  "astryx": "node bin/astryx.mjs",
@@ -115,10 +115,21 @@ function findThemePackages(cwd) {
115
115
  return found;
116
116
  }
117
117
  for (const entry of entries) {
118
- if (!entry.isDirectory()) continue;
119
118
  if (!entry.name.startsWith('theme-')) continue;
119
+ const dir = path.join(scopeDir, entry.name);
120
+ // pnpm installs packages as symlinks into node_modules/.pnpm, and a
121
+ // symlink dirent reports isDirectory() as false — stat the target instead.
122
+ let isDir = entry.isDirectory();
123
+ if (!isDir && entry.isSymbolicLink()) {
124
+ try {
125
+ isDir = fs.statSync(dir).isDirectory();
126
+ } catch {
127
+ isDir = false;
128
+ }
129
+ }
130
+ if (!isDir) continue;
120
131
  const name = `@astryxdesign/${entry.name}`;
121
- found.push({name, version: pkgVersion(path.join(scopeDir, entry.name))});
132
+ found.push({name, version: pkgVersion(dir)});
122
133
  }
123
134
  return found;
124
135
  }
@@ -63,6 +63,33 @@ function installPkg(name, version = '1.0.0') {
63
63
  return dir;
64
64
  }
65
65
 
66
+ /**
67
+ * Mirror pnpm's layout: the real package lives under node_modules/.pnpm and
68
+ * the entry in the scope directory is a symlink to it.
69
+ */
70
+ function installPkgPnpmStyle(name, version = '1.0.0') {
71
+ const realDir = path.join(
72
+ tmpDir,
73
+ 'node_modules',
74
+ '.pnpm',
75
+ `${name.replace('/', '+')}@${version}`,
76
+ 'node_modules',
77
+ ...name.split('/'),
78
+ );
79
+ fs.mkdirSync(realDir, {recursive: true});
80
+ fs.writeFileSync(
81
+ path.join(realDir, 'package.json'),
82
+ JSON.stringify({name, version, main: 'index.js'}),
83
+ );
84
+ fs.writeFileSync(path.join(realDir, 'index.js'), 'module.exports = {};');
85
+ const linkPath = path.join(tmpDir, 'node_modules', ...name.split('/'));
86
+ fs.mkdirSync(path.dirname(linkPath), {recursive: true});
87
+ // 'junction' keeps this working on Windows without elevated permissions;
88
+ // it is ignored on posix.
89
+ fs.symlinkSync(realDir, linkPath, 'junction');
90
+ return linkPath;
91
+ }
92
+
66
93
  function find(checks, id) {
67
94
  return checks.find(c => c.id === id);
68
95
  }
@@ -119,6 +146,13 @@ describe('doctor — individual checks', () => {
119
146
  expect(res.status).toBe('pass');
120
147
  });
121
148
 
149
+ it('themes: detects pnpm-style symlinked theme packages (#3530)', () => {
150
+ installPkgPnpmStyle('@astryxdesign/theme-neutral', '0.1.2');
151
+ const res = checkThemes({cwd: tmpDir, configTheme: 'default'});
152
+ expect(res.status).toBe('pass');
153
+ expect(res.message).toContain('@astryxdesign/theme-neutral');
154
+ });
155
+
122
156
  it('config: INFO when no astryx.config.mjs', async () => {
123
157
  const res = await checkConfig({cwd: tmpDir, configPath: null});
124
158
  expect(res.status).toBe('info');
@@ -0,0 +1,13 @@
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: 'Collapsible',
7
+ name: 'Collapsible — Divided Accordion',
8
+ displayName: 'Collapsible — Divided Accordion',
9
+ description: 'FAQ-style accordion using the dividers prop on CollapsibleGroup: built-in row hairlines and density padding with zero custom CSS. Use for FAQs, settings lists, and nav sections.',
10
+ isReady: true,
11
+ aspectRatio: 4 / 3,
12
+ componentsUsed: ['Collapsible', 'CollapsibleGroup', 'Text'],
13
+ };
@@ -0,0 +1,33 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ import {Collapsible, CollapsibleGroup} from '@astryxdesign/core/Collapsible';
6
+ import {Text} from '@astryxdesign/core/Text';
7
+
8
+ export default function CollapsibleDividedAccordion() {
9
+ return (
10
+ <div style={{width: '100%', maxWidth: 400}}>
11
+ <CollapsibleGroup type="single" dividers="between" defaultValue="reset">
12
+ <Collapsible trigger="How do I reset my password?" value="reset">
13
+ <Text type="body">
14
+ Go to Settings → Security → Change Password. You'll receive a
15
+ confirmation email within a few minutes.
16
+ </Text>
17
+ </Collapsible>
18
+ <Collapsible trigger="Can I change my username?" value="username">
19
+ <Text type="body">
20
+ Usernames can be changed once every 30 days from your profile
21
+ settings.
22
+ </Text>
23
+ </Collapsible>
24
+ <Collapsible trigger="How do I delete my account?" value="delete">
25
+ <Text type="body">
26
+ Account deletion is permanent. Your data will be removed within 30
27
+ days.
28
+ </Text>
29
+ </Collapsible>
30
+ </CollapsibleGroup>
31
+ </div>
32
+ );
33
+ }
@@ -25,21 +25,23 @@ function AppIcon() {
25
25
 
26
26
  export default function NavHeadingMenuShowcase() {
27
27
  return (
28
- <SideNav
29
- header={
30
- <SideNavHeading
31
- heading="Acme Platform"
32
- icon={<AppIcon />}
33
- menu={
34
- <NavHeadingMenu size="lg">
35
- <NavHeadingMenuItem label="Dashboard" href="/dashboard" />
36
- <NavHeadingMenuItem label="Analytics" href="/analytics" />
37
- <NavHeadingMenuItem label="Settings" href="/settings" />
38
- </NavHeadingMenu>
39
- }
40
- />
41
- }>
42
- {null}
43
- </SideNav>
28
+ <div style={{height: 100}}>
29
+ <SideNav
30
+ header={
31
+ <SideNavHeading
32
+ heading="Acme Platform"
33
+ icon={<AppIcon />}
34
+ menu={
35
+ <NavHeadingMenu size="lg">
36
+ <NavHeadingMenuItem label="Dashboard" href="/dashboard" />
37
+ <NavHeadingMenuItem label="Analytics" href="/analytics" />
38
+ <NavHeadingMenuItem label="Settings" href="/settings" />
39
+ </NavHeadingMenu>
40
+ }
41
+ />
42
+ }>
43
+ {null}
44
+ </SideNav>
45
+ </div>
44
46
  );
45
47
  }
@@ -19,13 +19,7 @@ import {Link} from '@astryxdesign/core/Link';
19
19
  import {Thumbnail} from '@astryxdesign/core/Thumbnail';
20
20
  import {Table, proportional, pixel} from '@astryxdesign/core/Table';
21
21
  import type {TableColumn} from '@astryxdesign/core/Table';
22
- import {
23
- ChartV2 as Chart,
24
- ChartGrid,
25
- ChartAxis,
26
- area,
27
- line,
28
- } from '@astryxdesign/lab';
22
+ import {Chart, ChartGrid, ChartAxis, area, line} from '@astryxdesign/charts';
29
23
  import {
30
24
  FunnelIcon,
31
25
  ArrowDownTrayIcon,
@@ -481,17 +475,13 @@ const columns: TableColumn<OrderRow>[] = [
481
475
  key: 'amount',
482
476
  header: 'Amount',
483
477
  width: pixel(90),
484
- renderCell: (item: OrderRow) => (
485
- <Text type="body">${item.amount}</Text>
486
- ),
478
+ renderCell: (item: OrderRow) => <Text type="body">${item.amount}</Text>,
487
479
  },
488
480
  {
489
481
  key: 'customer',
490
482
  header: 'Customer',
491
483
  width: proportional(2),
492
- renderCell: (item: OrderRow) => (
493
- <Text type="body">{item.customer}</Text>
494
- ),
484
+ renderCell: (item: OrderRow) => <Text type="body">{item.customer}</Text>,
495
485
  },
496
486
  {
497
487
  key: 'email',
@@ -19,13 +19,7 @@ import {Link} from '@astryxdesign/core/Link';
19
19
  import {Thumbnail} from '@astryxdesign/core/Thumbnail';
20
20
  import {Table, proportional, pixel} from '@astryxdesign/core/Table';
21
21
  import type {TableColumn} from '@astryxdesign/core/Table';
22
- import {
23
- ChartV2 as Chart,
24
- ChartGrid,
25
- ChartAxis,
26
- area,
27
- line,
28
- } from '@astryxdesign/lab';
22
+ import {Chart, ChartGrid, ChartAxis, area, line} from '@astryxdesign/charts';
29
23
  import {
30
24
  FunnelIcon,
31
25
  ArrowDownTrayIcon,
@@ -35,11 +29,7 @@ import {
35
29
  // ============= DATA =============
36
30
 
37
31
  type ProductCategory =
38
- | 'Running'
39
- | 'Lifestyle'
40
- | 'Basketball'
41
- | 'Training'
42
- | 'Skateboarding';
32
+ 'Running' | 'Lifestyle' | 'Basketball' | 'Training' | 'Skateboarding';
43
33
 
44
34
  function shoeSvg(bg: string, accent: string) {
45
35
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="12" fill="${bg}"/><g transform="translate(22.5, 22.5) scale(2.29)" fill="none" stroke="${accent}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m15 10.42 4.8-5.07"/><path d="M19 18h3"/><path d="M9.5 22 21.414 9.415A2 2 0 0 0 21.2 6.4l-5.61-4.208A1 1 0 0 0 14 3v2a2 2 0 0 1-1.394 1.906L8.677 8.053A1 1 0 0 0 8 9c-.155 6.393-2.082 9-4 9a2 2 0 0 0 0 4h14"/></g></svg>`;
@@ -839,17 +829,13 @@ const columns: TableColumn<OrderRow>[] = [
839
829
  key: 'amount',
840
830
  header: 'Amount',
841
831
  width: pixel(90),
842
- renderCell: (item: OrderRow) => (
843
- <Text type="body">${item.amount}</Text>
844
- ),
832
+ renderCell: (item: OrderRow) => <Text type="body">${item.amount}</Text>,
845
833
  },
846
834
  {
847
835
  key: 'customer',
848
836
  header: 'Customer',
849
837
  width: proportional(2),
850
- renderCell: (item: OrderRow) => (
851
- <Text type="body">{item.customer}</Text>
852
- ),
838
+ renderCell: (item: OrderRow) => <Text type="body">{item.customer}</Text>,
853
839
  },
854
840
  {
855
841
  key: 'email',