@astryxdesign/cli 0.1.8-canary.3bb5896 → 0.1.8-canary.4a7ce02
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/docs/elevation.doc.mjs +1 -79
- package/package.json +10 -11
- package/src/api/error.mjs +2 -2
- package/src/commands/swizzle.mjs +1 -1
- package/src/lib/cli-error.mjs +2 -2
- package/src/lib/json-shim.mjs +1 -1
- package/src/lib/json.mjs +3 -3
- package/src/types/api.d.ts +9 -4
- package/src/types/base.d.ts +3 -24
- package/src/types/index.d.ts +0 -1
- package/src/types/swizzle.d.ts +0 -4
- package/src/utils/package-manager.mjs +4 -30
- package/src/utils/update-check.mjs +3 -3
- package/src/utils/update-check.test.mjs +3 -3
- package/src/types/build.d.ts +0 -23
- package/templates/blocks/components/Banner/BannerFloating.doc.mjs +0 -14
- package/templates/blocks/components/Banner/BannerFloating.tsx +0 -16
- package/templates/blocks/components/Button/ButtonFloating.doc.mjs +0 -14
- package/templates/blocks/components/Button/ButtonFloating.tsx +0 -37
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +0 -14
- package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +0 -23
- package/templates/blocks/components/Card/CardElevations.doc.mjs +0 -14
- package/templates/blocks/components/Card/CardElevations.tsx +0 -32
- package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +0 -14
- package/templates/blocks/components/Card/ClickableCardElevated.tsx +0 -21
- package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +0 -14
- package/templates/blocks/components/Card/SelectableCardElevated.tsx +0 -37
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +0 -14
- package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +0 -75
- package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +0 -14
- package/templates/blocks/components/IconButton/IconButtonFloating.tsx +0 -37
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +0 -14
- package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +0 -39
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +0 -14
- package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +0 -44
- package/templates/blocks/components/Thumbnail/ThumbnailElevated.doc.mjs +0 -14
- package/templates/blocks/components/Thumbnail/ThumbnailElevated.tsx +0 -31
package/docs/elevation.doc.mjs
CHANGED
|
@@ -36,85 +36,10 @@ export const docs = {
|
|
|
36
36
|
},
|
|
37
37
|
],
|
|
38
38
|
},
|
|
39
|
-
{
|
|
40
|
-
title: 'Choosing a level',
|
|
41
|
-
category: 'foundations',
|
|
42
|
-
content: [
|
|
43
|
-
{
|
|
44
|
-
type: 'prose',
|
|
45
|
-
text: 'Pick the level by how far the surface sits from the page, not by how much shadow you want. Elevation encodes stacking order: a higher level means the surface is layered over more of the UI. Use exactly one level per surface, and only raise a surface above `none` when it actually sits above other content.',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
type: 'table',
|
|
49
|
-
headers: ['Level', 'When to use', 'Examples'],
|
|
50
|
-
rows: [
|
|
51
|
-
[
|
|
52
|
-
'none',
|
|
53
|
-
'The component is flat and embedded in the surface — it is part of the page, not layered above it. This is the default for every surface except ChatComposer.',
|
|
54
|
-
'A Card in a grid, an inline Banner, a standard Button',
|
|
55
|
-
],
|
|
56
|
-
[
|
|
57
|
-
'low',
|
|
58
|
-
'The component is in the normal page flow but should read as distinct from the background. Use for emphasis or to separate the component from the surface behind it — the component still sits on the page, it is not floating over other content.',
|
|
59
|
-
'A raised Card that needs emphasis, a ChatComposer, a resting Thumbnail',
|
|
60
|
-
],
|
|
61
|
-
[
|
|
62
|
-
'med',
|
|
63
|
-
'The component sits over other content on the same page — it floats above nearby elements but not the whole screen.',
|
|
64
|
-
'A Popover, a floating Banner, a floating action Button',
|
|
65
|
-
],
|
|
66
|
-
[
|
|
67
|
-
'high',
|
|
68
|
-
'The component is placed over the entire UI — it is the topmost layer and typically has a backdrop or takes focus from everything else.',
|
|
69
|
-
'A modal Dialog, a full-screen overlay surface',
|
|
70
|
-
],
|
|
71
|
-
],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
type: 'prose',
|
|
75
|
-
text: 'If two surfaces overlap, the one on top takes the higher level. If a surface does not overlap anything, it is `none` or `low` — never `med` or `high`.',
|
|
76
|
-
},
|
|
77
|
-
],
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
title: 'The elevation prop',
|
|
81
|
-
category: 'foundations',
|
|
82
|
-
content: [
|
|
83
|
-
{
|
|
84
|
-
type: 'prose',
|
|
85
|
-
text: 'Configurable surfaces expose a single `elevation` prop instead of asking consumers to hand-write a box-shadow. It takes the graded enum `none | low | med | high`, narrowed per component to the steps that surface needs: Card, ClickableCard, SelectableCard, Button, IconButton, ButtonGroup, Thumbnail, and Banner expose the full scale, while ChatComposer exposes only `none | low`. `none` is a flat literal (`box-shadow: none`); the other levels map to the `--shadow-*` tokens above, so a surface stays theme-agnostic.',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
type: 'prose',
|
|
89
|
-
text: 'Prop defaults preserve current appearance: every surface defaults to `none` except ChatComposer, which defaults to `low` to keep its raised look. Set `elevation="none"` to flatten it — the flat composer draws a border with the same rest / hover / focus treatment as a text input. Thumbnail keeps its existing hover-only shadow at the `none` default.',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
type: 'code',
|
|
93
|
-
lang: 'tsx',
|
|
94
|
-
label: 'Raising a surface with the elevation prop',
|
|
95
|
-
code: `// Flat by default — raise only when the surface needs to float.
|
|
96
|
-
<Card elevation="low">Raised card</Card>
|
|
97
|
-
|
|
98
|
-
// A floating action button.
|
|
99
|
-
<IconButton icon={<Icon icon="add" />} label="New" variant="primary" elevation="med" />
|
|
100
|
-
|
|
101
|
-
// Flatten the composer (defaults to 'low').
|
|
102
|
-
<ChatComposer elevation="none" onSubmit={handleSubmit} />`,
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
type: 'prose',
|
|
106
|
-
text: 'Always float — no prop: intrinsic overlays (Dialog, Popover, Tooltip, Toast, HoverCard, DropdownMenu, and the components that compose them) bake their elevation in and never expose the prop. Flow content (inputs, Text, layout) is never elevated; input fields use inset rings, which are a separate concept from elevation.',
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
39
|
{
|
|
111
40
|
title: 'Usage',
|
|
112
41
|
category: 'foundations',
|
|
113
42
|
content: [
|
|
114
|
-
{
|
|
115
|
-
type: 'prose',
|
|
116
|
-
text: 'When building a custom surface, read elevation from the token scale rather than a hand-rolled shadow — the same tokens the elevation prop resolves to.',
|
|
117
|
-
},
|
|
118
43
|
{
|
|
119
44
|
type: 'code',
|
|
120
45
|
lang: 'tsx',
|
|
@@ -143,8 +68,7 @@ const styles = stylex.create({
|
|
|
143
68
|
type: 'list',
|
|
144
69
|
style: 'do',
|
|
145
70
|
items: [
|
|
146
|
-
'
|
|
147
|
-
'Choose the level by how far the surface sits from the page: `none` when flat/embedded, `low` when in-flow but distinct, `med` when over page content, `high` when over the whole UI. See "Choosing a level".',
|
|
71
|
+
'Match elevation to interaction context: low for tooltips, med for dropdowns, high for dialogs.',
|
|
148
72
|
'Use inset shadows for input focus/selection states; they compose better than outlines.',
|
|
149
73
|
],
|
|
150
74
|
},
|
|
@@ -152,8 +76,6 @@ const styles = stylex.create({
|
|
|
152
76
|
type: 'list',
|
|
153
77
|
style: 'dont',
|
|
154
78
|
items: [
|
|
155
|
-
'Hand-write a `box-shadow` in app code — set the `elevation` prop or read `shadowVars` instead.',
|
|
156
|
-
'Raise a surface that does not sit above other content — a non-overlapping surface is `none` or `low`, never `med` or `high`.',
|
|
157
79
|
'Stack multiple elevation levels on the same element.',
|
|
158
80
|
'Use elevation shadows for decorative borders. Use --color-border tokens instead.',
|
|
159
81
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.8-canary.
|
|
3
|
+
"version": "0.1.8-canary.4a7ce02",
|
|
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",
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
"zod": "^4.4.3"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
|
-
"@astryxdesign/charts": "0.1.8-canary.
|
|
83
|
-
"@astryxdesign/core": "0.1.8-canary.
|
|
84
|
-
"@astryxdesign/lab": "0.1.8-canary.
|
|
85
|
-
"@astryxdesign/theme-neutral": "0.1.8-canary.
|
|
82
|
+
"@astryxdesign/charts": "0.1.8-canary.4a7ce02",
|
|
83
|
+
"@astryxdesign/core": "0.1.8-canary.4a7ce02",
|
|
84
|
+
"@astryxdesign/lab": "0.1.8-canary.4a7ce02",
|
|
85
|
+
"@astryxdesign/theme-neutral": "0.1.8-canary.4a7ce02",
|
|
86
86
|
"gpt-tokenizer": "^3.4.0"
|
|
87
87
|
},
|
|
88
88
|
"peerDependenciesMeta": {
|
|
@@ -100,17 +100,16 @@
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@astryxdesign/charts": "0.1.8-canary.
|
|
104
|
-
"@astryxdesign/core": "0.1.8-canary.
|
|
105
|
-
"@astryxdesign/lab": "0.1.8-canary.
|
|
106
|
-
"@astryxdesign/theme-neutral": "0.1.8-canary.
|
|
103
|
+
"@astryxdesign/charts": "0.1.8-canary.4a7ce02",
|
|
104
|
+
"@astryxdesign/core": "0.1.8-canary.4a7ce02",
|
|
105
|
+
"@astryxdesign/lab": "0.1.8-canary.4a7ce02",
|
|
106
|
+
"@astryxdesign/theme-neutral": "0.1.8-canary.4a7ce02",
|
|
107
107
|
"gpt-tokenizer": "^3.4.0"
|
|
108
108
|
},
|
|
109
109
|
"scripts": {
|
|
110
110
|
"astryx": "node bin/astryx.mjs",
|
|
111
111
|
"postinstall": "node scripts/postinstall.mjs",
|
|
112
112
|
"typecheck:template-docs": "tsc --project tsconfig.template-docs.json",
|
|
113
|
-
"typecheck:json-api": "tsc --project tsconfig.json-api.json && tsc --project tsconfig.api-contract.json"
|
|
114
|
-
"typecheck:strict": "tsc --project tsconfig.strict.json"
|
|
113
|
+
"typecheck:json-api": "tsc --project tsconfig.json-api.json && tsc --project tsconfig.api-contract.json"
|
|
115
114
|
}
|
|
116
115
|
}
|
package/src/api/error.mjs
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import {ERROR_CODES} from '../lib/error-codes.mjs';
|
|
15
15
|
|
|
16
16
|
export class AstryxError extends Error {
|
|
17
|
-
/** @type {
|
|
17
|
+
/** @type {Array<{name: string, reason: string}> | undefined} */
|
|
18
18
|
suggestions;
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -26,7 +26,7 @@ export class AstryxError extends Error {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* @param {string} message
|
|
29
|
-
* @param {
|
|
29
|
+
* @param {Array<{name: string, reason: string}>} [suggestions]
|
|
30
30
|
* @param {string} [code] - Stable error code. Defaults to ERR_UNKNOWN.
|
|
31
31
|
*/
|
|
32
32
|
constructor(message, suggestions, code) {
|
package/src/commands/swizzle.mjs
CHANGED
|
@@ -358,7 +358,7 @@ export function registerSwizzle(program) {
|
|
|
358
358
|
const feedback = buildFeedback(dirName, owner.issuesUrl);
|
|
359
359
|
|
|
360
360
|
if (json) {
|
|
361
|
-
/** @type {
|
|
361
|
+
/** @type {Record<string, unknown>} */
|
|
362
362
|
const payload = {
|
|
363
363
|
component: dirName,
|
|
364
364
|
package: owner.package,
|
package/src/lib/cli-error.mjs
CHANGED
|
@@ -55,8 +55,8 @@ import {ERROR_CODES} from './error-codes.mjs';
|
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Suggestion object — matches the shape used by API errors and the JSON
|
|
58
|
-
* envelope's `suggestions` field.
|
|
59
|
-
* @typedef {
|
|
58
|
+
* envelope's `suggestions` field.
|
|
59
|
+
* @typedef {{name: string, reason?: string}} Suggestion
|
|
60
60
|
*/
|
|
61
61
|
|
|
62
62
|
/**
|
package/src/lib/json-shim.mjs
CHANGED
|
@@ -102,7 +102,7 @@ export function buildHelpEnvelope(cmd) {
|
|
|
102
102
|
* for both success and error).
|
|
103
103
|
*
|
|
104
104
|
* @param {string} message
|
|
105
|
-
* @param {
|
|
105
|
+
* @param {Array<{name: string, reason: string}>} [suggestions]
|
|
106
106
|
* @param {string} [code] - Stable machine-readable error code (error-codes.mjs).
|
|
107
107
|
*/
|
|
108
108
|
function emitJsonError(message, suggestions, code) {
|
package/src/lib/json.mjs
CHANGED
|
@@ -112,10 +112,10 @@ export function jsonOut(type, data, meta) {
|
|
|
112
112
|
* consumers can branch on it unconditionally.
|
|
113
113
|
*
|
|
114
114
|
* @param {unknown} err
|
|
115
|
-
* @param {
|
|
115
|
+
* @param {Array<{name: string, reason: string}>} [suggestions]
|
|
116
116
|
* @param {string} [code] - Explicit stable error code. Overrides any code
|
|
117
117
|
* carried on a thrown Error.
|
|
118
|
-
* @returns {{apiVersion: number, error: string, code: string, suggestions?:
|
|
118
|
+
* @returns {{apiVersion: number, error: string, code: string, suggestions?: Array<{name: string, reason: string}>}}
|
|
119
119
|
*/
|
|
120
120
|
export function toErrorEnvelope(err, suggestions, code) {
|
|
121
121
|
const message =
|
|
@@ -136,7 +136,7 @@ export function toErrorEnvelope(err, suggestions, code) {
|
|
|
136
136
|
/**
|
|
137
137
|
* Output a structured JSON error and exit.
|
|
138
138
|
* @param {string} message
|
|
139
|
-
* @param {
|
|
139
|
+
* @param {Array<{name: string, reason: string}>} [suggestions]
|
|
140
140
|
* @param {string} [code] - Stable machine-readable error code (error-codes.mjs).
|
|
141
141
|
*/
|
|
142
142
|
export function jsonError(message, suggestions, code) {
|
package/src/types/api.d.ts
CHANGED
|
@@ -44,14 +44,17 @@ import type {
|
|
|
44
44
|
import type {SearchResponse, SearchDomain} from './search';
|
|
45
45
|
import type {ErrorCode} from './error-codes';
|
|
46
46
|
import type {DoctorResponse} from './doctor';
|
|
47
|
-
import type {Suggestion} from './base';
|
|
48
47
|
|
|
49
48
|
/** Structured API error with a stable machine-readable code. */
|
|
50
49
|
export declare class AstryxError extends Error {
|
|
51
50
|
/** Stable error code; consumers branch on this, never the message. */
|
|
52
51
|
code: ErrorCode;
|
|
53
|
-
suggestions?:
|
|
54
|
-
constructor(
|
|
52
|
+
suggestions?: Array<{name: string; reason: string}>;
|
|
53
|
+
constructor(
|
|
54
|
+
message: string,
|
|
55
|
+
suggestions?: Array<{name: string; reason: string}>,
|
|
56
|
+
code?: ErrorCode,
|
|
57
|
+
);
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
// ── Component ────────────────────────────────────────────────────────
|
|
@@ -97,7 +100,9 @@ export interface DocsOptions {
|
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
type DocsResult =
|
|
100
|
-
|
|
103
|
+
| DocsListResponse
|
|
104
|
+
| DocsDetailResponse
|
|
105
|
+
| DocsDetailSectionResponse;
|
|
101
106
|
|
|
102
107
|
export declare function docs(
|
|
103
108
|
topic?: string,
|
package/src/types/base.d.ts
CHANGED
|
@@ -11,12 +11,10 @@
|
|
|
11
11
|
import type {
|
|
12
12
|
ComponentListResponse,
|
|
13
13
|
ComponentBriefResponse,
|
|
14
|
-
ComponentFullResponse,
|
|
15
14
|
ComponentDetailResponse,
|
|
16
15
|
ComponentDetailPropsResponse,
|
|
17
16
|
ComponentDetailSourceResponse,
|
|
18
17
|
ComponentDetailShowcaseResponse,
|
|
19
|
-
ComponentDetailBlocksResponse,
|
|
20
18
|
} from './component';
|
|
21
19
|
import type {
|
|
22
20
|
DiscoverListResponse,
|
|
@@ -44,28 +42,13 @@ import type {
|
|
|
44
42
|
} from './hook';
|
|
45
43
|
import type {SwizzleListResponse, SwizzleCopyResponse} from './swizzle';
|
|
46
44
|
import type {ThemeBuildResponse} from './theme';
|
|
47
|
-
import type {
|
|
48
|
-
UpgradeListResponse,
|
|
49
|
-
UpgradeRunResponse,
|
|
50
|
-
UpgradeStatusResponse,
|
|
51
|
-
} from './upgrade';
|
|
45
|
+
import type {UpgradeListResponse, UpgradeRunResponse} from './upgrade';
|
|
52
46
|
import type {SearchResponse} from './search';
|
|
53
|
-
import type {BuildHelpResponse} from './build';
|
|
54
47
|
import type {ErrorCode} from './error-codes';
|
|
55
48
|
import type {ManifestResponse} from './manifest';
|
|
56
49
|
import type {DoctorResponse} from './doctor';
|
|
57
50
|
import type {ValidateIntegrationResponse} from './validate-integration';
|
|
58
51
|
|
|
59
|
-
/**
|
|
60
|
-
* A "did you mean…" suggestion attached to an error. `reason` is optional:
|
|
61
|
-
* some call sites emit bare `{name}` (e.g. a list of candidate component names)
|
|
62
|
-
* with no per-item explanation.
|
|
63
|
-
*/
|
|
64
|
-
export interface Suggestion {
|
|
65
|
-
name: string;
|
|
66
|
-
reason?: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
52
|
/**
|
|
70
53
|
* Structured error. Check `'error' in result` to discriminate.
|
|
71
54
|
*
|
|
@@ -75,7 +58,7 @@ export interface Suggestion {
|
|
|
75
58
|
export interface CLIError {
|
|
76
59
|
error: string;
|
|
77
60
|
code: ErrorCode;
|
|
78
|
-
suggestions?:
|
|
61
|
+
suggestions?: Array<{name: string; reason: string}>;
|
|
79
62
|
}
|
|
80
63
|
|
|
81
64
|
/** Returned by the fallback hook for commands without --json support. */
|
|
@@ -91,12 +74,10 @@ export type CLIResult<T> = T | CLIError | CLIUnsupportedError;
|
|
|
91
74
|
export type CLIAnyResponse =
|
|
92
75
|
| ComponentListResponse
|
|
93
76
|
| ComponentBriefResponse
|
|
94
|
-
| ComponentFullResponse
|
|
95
77
|
| ComponentDetailResponse
|
|
96
78
|
| ComponentDetailPropsResponse
|
|
97
79
|
| ComponentDetailSourceResponse
|
|
98
80
|
| ComponentDetailShowcaseResponse
|
|
99
|
-
| ComponentDetailBlocksResponse
|
|
100
81
|
| DiscoverListResponse
|
|
101
82
|
| DiscoverDetailResponse
|
|
102
83
|
| DiscoverDetailDocResponse
|
|
@@ -118,9 +99,7 @@ export type CLIAnyResponse =
|
|
|
118
99
|
| ThemeBuildResponse
|
|
119
100
|
| UpgradeListResponse
|
|
120
101
|
| UpgradeRunResponse
|
|
121
|
-
| UpgradeStatusResponse
|
|
122
102
|
| SearchResponse
|
|
123
|
-
| BuildHelpResponse
|
|
124
103
|
| ManifestResponse
|
|
125
104
|
| DoctorResponse
|
|
126
105
|
| ValidateIntegrationResponse;
|
|
@@ -150,7 +129,7 @@ export function jsonOut<T extends CLIResponseType>(
|
|
|
150
129
|
*/
|
|
151
130
|
export function jsonError(
|
|
152
131
|
message: string,
|
|
153
|
-
suggestions?:
|
|
132
|
+
suggestions?: Array<{name: string; reason: string}>,
|
|
154
133
|
code?: ErrorCode,
|
|
155
134
|
): never;
|
|
156
135
|
|
package/src/types/index.d.ts
CHANGED
package/src/types/swizzle.d.ts
CHANGED
|
@@ -29,13 +29,9 @@ export interface SwizzleCopyResponse {
|
|
|
29
29
|
type: 'swizzle.copy';
|
|
30
30
|
data: {
|
|
31
31
|
component: string;
|
|
32
|
-
/** Owner package the component source was copied from. */
|
|
33
|
-
package: string;
|
|
34
32
|
outputDir: string;
|
|
35
33
|
filesCopied: number;
|
|
36
34
|
files: string[];
|
|
37
|
-
/** Whether any copied file uses StyleX (requires build-time setup). */
|
|
38
|
-
usesStyleX: boolean;
|
|
39
35
|
feedback?: SwizzleFeedback;
|
|
40
36
|
};
|
|
41
37
|
}
|
|
@@ -10,41 +10,15 @@
|
|
|
10
10
|
import * as fs from 'node:fs';
|
|
11
11
|
import * as path from 'node:path';
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* A package manager we can install with and run binaries through.
|
|
15
|
-
* @typedef {'yarn' | 'pnpm' | 'bun' | 'npm'} PackageManager
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Result of package-manager detection. `'npx'` is the sentinel for "nothing
|
|
20
|
-
* detected" — no lockfile, no `packageManager` field, no runner user-agent —
|
|
21
|
-
* so callers fall back to npm/npx. It is a distinct value from {@link PackageManager}
|
|
22
|
-
* because it means "undetected", not "npm was chosen".
|
|
23
|
-
* @typedef {PackageManager | 'npx'} DetectedPackageManager
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/** @type {readonly PackageManager[]} */
|
|
27
|
-
const KNOWN_PMS = ['yarn', 'pnpm', 'bun', 'npm'];
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Narrow an arbitrary string to a known {@link PackageManager}.
|
|
31
|
-
* @param {string} name
|
|
32
|
-
* @returns {name is PackageManager}
|
|
33
|
-
*/
|
|
34
|
-
function isKnownPackageManager(name) {
|
|
35
|
-
return /** @type {readonly string[]} */ (KNOWN_PMS).includes(name);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
13
|
/**
|
|
39
14
|
* Detect the package manager used in a project directory.
|
|
40
15
|
* Walks up from targetDir looking for lockfiles.
|
|
41
16
|
*
|
|
42
|
-
* Returns `'npx'` when nothing can be detected — see {@link DetectedPackageManager}.
|
|
43
|
-
*
|
|
44
17
|
* @param {string} [targetDir=process.cwd()]
|
|
45
|
-
* @returns {
|
|
18
|
+
* @returns {'yarn'|'pnpm'|'bun'|'npm'}
|
|
46
19
|
*/
|
|
47
20
|
export function detectPackageManager(targetDir = process.cwd()) {
|
|
21
|
+
const KNOWN_PMS = new Set(['yarn', 'pnpm', 'bun', 'npm']);
|
|
48
22
|
let dir = path.resolve(targetDir);
|
|
49
23
|
const root = path.parse(dir).root;
|
|
50
24
|
|
|
@@ -62,7 +36,7 @@ export function detectPackageManager(targetDir = process.cwd()) {
|
|
|
62
36
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
63
37
|
if (pkg.packageManager) {
|
|
64
38
|
const name = pkg.packageManager.split('@')[0];
|
|
65
|
-
if (
|
|
39
|
+
if (KNOWN_PMS.has(name)) return name;
|
|
66
40
|
}
|
|
67
41
|
} catch {
|
|
68
42
|
// Best-effort: unreadable/invalid package.json — keep walking up.
|
|
@@ -76,7 +50,7 @@ export function detectPackageManager(targetDir = process.cwd()) {
|
|
|
76
50
|
const ua = process.env.npm_config_user_agent;
|
|
77
51
|
if (ua) {
|
|
78
52
|
const name = ua.split('/')[0];
|
|
79
|
-
if (
|
|
53
|
+
if (KNOWN_PMS.has(name)) return name;
|
|
80
54
|
}
|
|
81
55
|
|
|
82
56
|
return 'npx';
|
|
@@ -18,9 +18,9 @@ import {getCliInvocation} from './package-manager.mjs';
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Read the latest available version from local signals.
|
|
21
|
-
* No network calls — purely
|
|
22
|
-
* so it takes no arguments.
|
|
21
|
+
* No network calls — purely filesystem and env var checks.
|
|
23
22
|
*
|
|
23
|
+
* @param {string} [cwd] - Project directory (default: process.cwd())
|
|
24
24
|
* @returns {string|null} Latest version string, or null if unknown
|
|
25
25
|
*/
|
|
26
26
|
export function getLatestVersion() {
|
|
@@ -64,7 +64,7 @@ export function getInstalledVersion(cwd = process.cwd()) {
|
|
|
64
64
|
* @returns {string|null} FYI hint string, or null if up to date / unknown
|
|
65
65
|
*/
|
|
66
66
|
export function checkForUpdate(cwd = process.cwd()) {
|
|
67
|
-
const latest = getLatestVersion();
|
|
67
|
+
const latest = getLatestVersion(cwd);
|
|
68
68
|
if (!latest) return null;
|
|
69
69
|
|
|
70
70
|
// Persist for subsequent commands in this shell session
|
|
@@ -33,12 +33,12 @@ afterEach(() => {
|
|
|
33
33
|
describe('getLatestVersion', () => {
|
|
34
34
|
it('reads from ASTRYX_LATEST_VERSION env var', () => {
|
|
35
35
|
process.env.ASTRYX_LATEST_VERSION = '0.0.8';
|
|
36
|
-
expect(getLatestVersion()).toBe('0.0.8');
|
|
36
|
+
expect(getLatestVersion(tmpDir)).toBe('0.0.8');
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
it('ignores invalid env var values', () => {
|
|
40
40
|
process.env.ASTRYX_LATEST_VERSION = 'not-a-version';
|
|
41
|
-
expect(getLatestVersion()).toBeNull();
|
|
41
|
+
expect(getLatestVersion(tmpDir)).toBeNull();
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
it('returns null when no signals exist', () => {
|
|
@@ -46,7 +46,7 @@ describe('getLatestVersion', () => {
|
|
|
46
46
|
path.join(tmpDir, 'package.json'),
|
|
47
47
|
JSON.stringify({name: 'test'}),
|
|
48
48
|
);
|
|
49
|
-
expect(getLatestVersion()).toBeNull();
|
|
49
|
+
expect(getLatestVersion(tmpDir)).toBeNull();
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
|
package/src/types/build.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Build command JSON responses.
|
|
5
|
-
*
|
|
6
|
-
* `astryx build` is the "assemble a page" verb. With no query it emits the
|
|
7
|
-
* workflow playbook; with a query it delegates to the search pipeline and
|
|
8
|
-
* emits a `search` response (see search.d.ts).
|
|
9
|
-
*
|
|
10
|
-
* Invocation -> type discriminator
|
|
11
|
-
* ---------------------------------------------------
|
|
12
|
-
* xds --json build -> build.help
|
|
13
|
-
* xds --json build "<idea>" -> search
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** xds --json build (no query) — the "how to build a page" playbook signal. */
|
|
17
|
-
export interface BuildHelpResponse {
|
|
18
|
-
type: 'build.help';
|
|
19
|
-
data: {
|
|
20
|
-
/** Always true; marks this envelope as the playbook rather than a result set. */
|
|
21
|
-
playbook: true;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'Banner',
|
|
7
|
-
name: 'Banner — Floating',
|
|
8
|
-
displayName: 'Banner — Floating',
|
|
9
|
-
description:
|
|
10
|
-
'A floating banner raised with `elevation="med"`. Banners are inline by default; raise one when it should read as an overlay above content.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['Banner'],
|
|
14
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {Banner} from '@astryxdesign/core/Banner';
|
|
6
|
-
|
|
7
|
-
export default function BannerFloating() {
|
|
8
|
-
return (
|
|
9
|
-
<Banner
|
|
10
|
-
status="info"
|
|
11
|
-
title="You have unsaved changes"
|
|
12
|
-
description="A raised banner reads as an overlay floating above the page."
|
|
13
|
-
elevation="med"
|
|
14
|
-
/>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'Button',
|
|
7
|
-
name: 'Button — Floating',
|
|
8
|
-
displayName: 'Button — Floating',
|
|
9
|
-
description:
|
|
10
|
-
'A floating action button raised with `elevation="med"`. Use elevation for buttons that hover above content, like a FAB.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['Button', 'Icon', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {Button} from '@astryxdesign/core/Button';
|
|
6
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
7
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
8
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
9
|
-
import {PlusIcon} from '@heroicons/react/24/outline';
|
|
10
|
-
|
|
11
|
-
const VARIANTS = [
|
|
12
|
-
{variant: 'primary' as const, label: 'Primary'},
|
|
13
|
-
{variant: 'secondary' as const, label: 'Secondary'},
|
|
14
|
-
{variant: 'ghost' as const, label: 'Ghost'},
|
|
15
|
-
{variant: 'destructive' as const, label: 'Destructive'},
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
export default function ButtonFloating() {
|
|
19
|
-
return (
|
|
20
|
-
<Stack direction="vertical" gap={4}>
|
|
21
|
-
<Text type="supporting" color="secondary">
|
|
22
|
-
Floating action buttons — raised above content with `elevation="med"`
|
|
23
|
-
</Text>
|
|
24
|
-
<Stack direction="horizontal" gap={3} vAlign="center">
|
|
25
|
-
{VARIANTS.map(({variant, label}) => (
|
|
26
|
-
<Button
|
|
27
|
-
key={variant}
|
|
28
|
-
label={label}
|
|
29
|
-
variant={variant}
|
|
30
|
-
icon={<Icon icon={PlusIcon} />}
|
|
31
|
-
elevation="med"
|
|
32
|
-
/>
|
|
33
|
-
))}
|
|
34
|
-
</Stack>
|
|
35
|
-
</Stack>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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 — Floating',
|
|
8
|
-
displayName: 'ButtonGroup — Floating',
|
|
9
|
-
description:
|
|
10
|
-
'A grouped action bar raised with `elevation="med"`. The connected buttons share one surface, so the shadow lifts them as a unit.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['ButtonGroup', 'Button', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
8
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
9
|
-
|
|
10
|
-
export default function ButtonGroupFloating() {
|
|
11
|
-
return (
|
|
12
|
-
<Stack direction="vertical" gap={3} hAlign="start">
|
|
13
|
-
<Text type="supporting" color="secondary">
|
|
14
|
-
The whole group shares one raised surface — a floating action bar
|
|
15
|
-
</Text>
|
|
16
|
-
<ButtonGroup label="Zoom controls" elevation="med">
|
|
17
|
-
<Button label="Zoom out" />
|
|
18
|
-
<Button label="Reset" />
|
|
19
|
-
<Button label="Zoom in" />
|
|
20
|
-
</ButtonGroup>
|
|
21
|
-
</Stack>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'Card',
|
|
7
|
-
name: 'Card — Elevations',
|
|
8
|
-
displayName: 'Card — Elevations',
|
|
9
|
-
description:
|
|
10
|
-
'The four elevation levels side by side. Cards are flat by default; raise a card with `elevation` only when it needs to float above surrounding content.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['Card', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {Card} from '@astryxdesign/core/Card';
|
|
6
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
7
|
-
import {Grid} from '@astryxdesign/core/Grid';
|
|
8
|
-
import {Text, Heading} from '@astryxdesign/core/Text';
|
|
9
|
-
|
|
10
|
-
const LEVELS = [
|
|
11
|
-
{elevation: 'none' as const, caption: 'Flat — sits on the page (default)'},
|
|
12
|
-
{elevation: 'low' as const, caption: 'Low — lifts off slightly'},
|
|
13
|
-
{elevation: 'med' as const, caption: 'Med — clearly raised'},
|
|
14
|
-
{elevation: 'high' as const, caption: 'High — floats well above'},
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
export default function CardElevations() {
|
|
18
|
-
return (
|
|
19
|
-
<Grid columns={2} gap={4} width={520}>
|
|
20
|
-
{LEVELS.map(({elevation, caption}) => (
|
|
21
|
-
<Card key={elevation} elevation={elevation}>
|
|
22
|
-
<Stack direction="vertical" gap={1}>
|
|
23
|
-
<Heading level={4}>elevation="{elevation}"</Heading>
|
|
24
|
-
<Text type="supporting" color="secondary">
|
|
25
|
-
{caption}
|
|
26
|
-
</Text>
|
|
27
|
-
</Stack>
|
|
28
|
-
</Card>
|
|
29
|
-
))}
|
|
30
|
-
</Grid>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'ClickableCard',
|
|
7
|
-
name: 'ClickableCard — Elevated',
|
|
8
|
-
displayName: 'Clickable Card — Elevated',
|
|
9
|
-
description:
|
|
10
|
-
'A clickable card raised with `elevation="med"` so the shadow signals the whole surface is interactive.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 1,
|
|
13
|
-
componentsUsed: ['ClickableCard', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {ClickableCard} from '@astryxdesign/core/ClickableCard';
|
|
6
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
7
|
-
import {Text, Heading} from '@astryxdesign/core/Text';
|
|
8
|
-
|
|
9
|
-
export default function ClickableCardElevated() {
|
|
10
|
-
return (
|
|
11
|
-
<ClickableCard label="Open report" href="#" elevation="med" width={320}>
|
|
12
|
-
<Stack direction="vertical" gap={2}>
|
|
13
|
-
<Heading level={4}>Quarterly report</Heading>
|
|
14
|
-
<Text type="body" color="secondary">
|
|
15
|
-
A raised shadow signals the whole card is clickable, lifting it above
|
|
16
|
-
the surrounding content.
|
|
17
|
-
</Text>
|
|
18
|
-
</Stack>
|
|
19
|
-
</ClickableCard>
|
|
20
|
-
);
|
|
21
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'SelectableCard',
|
|
7
|
-
name: 'SelectableCard — Elevated',
|
|
8
|
-
displayName: 'Selectable Card — Elevated',
|
|
9
|
-
description:
|
|
10
|
-
'Raised selectable cards with `elevation="low"`. The inset selection ring composes on top of the shadow, so a selected card keeps its elevation.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 2,
|
|
13
|
-
componentsUsed: ['SelectableCard', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {useState} from 'react';
|
|
6
|
-
import {SelectableCard} from '@astryxdesign/core/SelectableCard';
|
|
7
|
-
import {Grid} from '@astryxdesign/core/Grid';
|
|
8
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
9
|
-
|
|
10
|
-
const PLANS = [
|
|
11
|
-
{id: 'starter', name: 'Starter'},
|
|
12
|
-
{id: 'pro', name: 'Pro'},
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
export default function SelectableCardElevated() {
|
|
16
|
-
const [selected, setSelected] = useState('pro');
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<Grid columns={2} gap={3} width={420}>
|
|
20
|
-
{PLANS.map(plan => (
|
|
21
|
-
<SelectableCard
|
|
22
|
-
key={plan.id}
|
|
23
|
-
label={plan.name}
|
|
24
|
-
isSelected={selected === plan.id}
|
|
25
|
-
onChange={() => setSelected(plan.id)}
|
|
26
|
-
elevation="low">
|
|
27
|
-
<Text type="body" weight="bold">
|
|
28
|
-
{plan.name}
|
|
29
|
-
</Text>
|
|
30
|
-
<Text type="supporting" color="secondary">
|
|
31
|
-
The resting shadow stays put — the selection ring layers on top.
|
|
32
|
-
</Text>
|
|
33
|
-
</SelectableCard>
|
|
34
|
-
))}
|
|
35
|
-
</Grid>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'ChatComposer',
|
|
7
|
-
name: 'ChatComposer — Flat',
|
|
8
|
-
displayName: 'ChatComposer — Flat',
|
|
9
|
-
description:
|
|
10
|
-
'The composer is raised by default (`elevation="low"`). Set `elevation="none"` to flatten it — it then draws a border with the same rest / hover / focus treatment as a text input.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['ChatComposer', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {ChatComposer} from '@astryxdesign/core/Chat';
|
|
6
|
-
import {Button} from '@astryxdesign/core/Button';
|
|
7
|
-
import {DropdownMenu} from '@astryxdesign/core/DropdownMenu';
|
|
8
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
9
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
10
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
11
|
-
import {
|
|
12
|
-
Cog6ToothIcon,
|
|
13
|
-
MicrophoneIcon,
|
|
14
|
-
SparklesIcon,
|
|
15
|
-
} from '@heroicons/react/24/outline';
|
|
16
|
-
|
|
17
|
-
export default function ChatComposerFlat() {
|
|
18
|
-
return (
|
|
19
|
-
<Stack direction="vertical" gap={2} style={{width: '100%', maxWidth: 450}}>
|
|
20
|
-
<Text type="supporting" color="secondary">
|
|
21
|
-
elevation="none" — flat, with a text-input-style border and
|
|
22
|
-
focus ring
|
|
23
|
-
</Text>
|
|
24
|
-
<ChatComposer
|
|
25
|
-
elevation="none"
|
|
26
|
-
onSubmit={value => {
|
|
27
|
-
console.log('Sent:', value);
|
|
28
|
-
}}
|
|
29
|
-
footerActions={
|
|
30
|
-
<>
|
|
31
|
-
<DropdownMenu
|
|
32
|
-
button={{
|
|
33
|
-
label: 'Auto',
|
|
34
|
-
variant: 'ghost',
|
|
35
|
-
size: 'md',
|
|
36
|
-
icon: <Icon icon={SparklesIcon} size="sm" />,
|
|
37
|
-
children: 'Auto',
|
|
38
|
-
}}
|
|
39
|
-
menuWidth={200}
|
|
40
|
-
items={[
|
|
41
|
-
{label: 'Auto', onClick: () => {}},
|
|
42
|
-
{label: 'Model A', onClick: () => {}},
|
|
43
|
-
{label: 'Model B', onClick: () => {}},
|
|
44
|
-
]}
|
|
45
|
-
/>
|
|
46
|
-
<DropdownMenu
|
|
47
|
-
button={{
|
|
48
|
-
label: 'Settings',
|
|
49
|
-
variant: 'ghost',
|
|
50
|
-
size: 'md',
|
|
51
|
-
icon: <Icon icon={Cog6ToothIcon} size="sm" />,
|
|
52
|
-
children: 'Settings',
|
|
53
|
-
}}
|
|
54
|
-
menuWidth={200}
|
|
55
|
-
items={[
|
|
56
|
-
{label: 'Preferences', onClick: () => {}},
|
|
57
|
-
{label: 'Keyboard shortcuts', onClick: () => {}},
|
|
58
|
-
{label: 'About', onClick: () => {}},
|
|
59
|
-
]}
|
|
60
|
-
/>
|
|
61
|
-
</>
|
|
62
|
-
}
|
|
63
|
-
sendActions={
|
|
64
|
-
<Button
|
|
65
|
-
label="Microphone"
|
|
66
|
-
variant="ghost"
|
|
67
|
-
size="md"
|
|
68
|
-
icon={<Icon icon={MicrophoneIcon} />}
|
|
69
|
-
isIconOnly
|
|
70
|
-
/>
|
|
71
|
-
}
|
|
72
|
-
/>
|
|
73
|
-
</Stack>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'IconButton',
|
|
7
|
-
name: 'IconButton — Floating',
|
|
8
|
-
displayName: 'IconButton — Floating',
|
|
9
|
-
description:
|
|
10
|
-
'A floating action button (FAB) — the most common floating-button shape is icon-only. Raised here with `elevation="high"`.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 4 / 3,
|
|
13
|
-
componentsUsed: ['IconButton', 'Icon', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {IconButton} from '@astryxdesign/core/IconButton';
|
|
6
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
7
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
8
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
9
|
-
import {PlusIcon} from '@heroicons/react/24/outline';
|
|
10
|
-
|
|
11
|
-
const VARIANTS = [
|
|
12
|
-
{variant: 'primary' as const, label: 'Primary'},
|
|
13
|
-
{variant: 'secondary' as const, label: 'Secondary'},
|
|
14
|
-
{variant: 'ghost' as const, label: 'Ghost'},
|
|
15
|
-
{variant: 'destructive' as const, label: 'Destructive'},
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
export default function IconButtonFloating() {
|
|
19
|
-
return (
|
|
20
|
-
<Stack direction="vertical" gap={4}>
|
|
21
|
-
<Text type="supporting" color="secondary">
|
|
22
|
-
FABs are usually icon-only — raise one with `elevation="high"`
|
|
23
|
-
</Text>
|
|
24
|
-
<Stack direction="horizontal" gap={3} vAlign="center">
|
|
25
|
-
{VARIANTS.map(({variant, label}) => (
|
|
26
|
-
<IconButton
|
|
27
|
-
key={variant}
|
|
28
|
-
label={label}
|
|
29
|
-
variant={variant}
|
|
30
|
-
icon={<Icon icon={PlusIcon} />}
|
|
31
|
-
elevation="high"
|
|
32
|
-
/>
|
|
33
|
-
))}
|
|
34
|
-
</Stack>
|
|
35
|
-
</Stack>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'OverflowList',
|
|
7
|
-
name: 'OverflowList — Capped Toolbar',
|
|
8
|
-
displayName: 'OverflowList — Capped Toolbar',
|
|
9
|
-
description:
|
|
10
|
-
'maxVisibleItems caps the row at three actions even when more would fit; the rest move to a dropdown',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 4 / 3,
|
|
13
|
-
componentsUsed: ['OverflowList', 'Button', 'DropdownMenu', 'Card', 'Center'],
|
|
14
|
-
};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {OverflowList} from '@astryxdesign/core/OverflowList';
|
|
6
|
-
import {Button} from '@astryxdesign/core/Button';
|
|
7
|
-
import {DropdownMenu} from '@astryxdesign/core/DropdownMenu';
|
|
8
|
-
import {Card} from '@astryxdesign/core/Card';
|
|
9
|
-
import {Center} from '@astryxdesign/core/Center';
|
|
10
|
-
|
|
11
|
-
const actions = ['Save', 'Edit', 'Duplicate', 'Share', 'Archive', 'Delete'];
|
|
12
|
-
|
|
13
|
-
export default function OverflowListCappedToolbar() {
|
|
14
|
-
return (
|
|
15
|
-
<Center width={420}>
|
|
16
|
-
<Card padding={2}>
|
|
17
|
-
<OverflowList
|
|
18
|
-
gap={2}
|
|
19
|
-
maxVisibleItems={3}
|
|
20
|
-
overflowRenderer={overflowItems => (
|
|
21
|
-
<DropdownMenu
|
|
22
|
-
button={{
|
|
23
|
-
label: `+${overflowItems.length}`,
|
|
24
|
-
variant: 'ghost',
|
|
25
|
-
size: 'sm',
|
|
26
|
-
}}
|
|
27
|
-
items={overflowItems.map(({index}) => ({
|
|
28
|
-
label: actions[index],
|
|
29
|
-
}))}
|
|
30
|
-
/>
|
|
31
|
-
)}>
|
|
32
|
-
{actions.map(action => (
|
|
33
|
-
<Button key={action} label={action} size="sm" />
|
|
34
|
-
))}
|
|
35
|
-
</OverflowList>
|
|
36
|
-
</Card>
|
|
37
|
-
</Center>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'OverflowList',
|
|
7
|
-
name: 'OverflowList — Multi-row Tags',
|
|
8
|
-
displayName: 'OverflowList — Multi-row Tags',
|
|
9
|
-
description:
|
|
10
|
-
'Tags wrap onto up to two rows with maxRows, then collapse the rest into a count badge',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 4 / 3,
|
|
13
|
-
componentsUsed: ['OverflowList', 'Badge', 'Card'],
|
|
14
|
-
};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {OverflowList} from '@astryxdesign/core/OverflowList';
|
|
6
|
-
import {Badge} from '@astryxdesign/core/Badge';
|
|
7
|
-
import {Card} from '@astryxdesign/core/Card';
|
|
8
|
-
|
|
9
|
-
const tags = [
|
|
10
|
-
'React',
|
|
11
|
-
'TypeScript',
|
|
12
|
-
'StyleX',
|
|
13
|
-
'Storybook',
|
|
14
|
-
'Vitest',
|
|
15
|
-
'Playwright',
|
|
16
|
-
'ESLint',
|
|
17
|
-
'Prettier',
|
|
18
|
-
'Vite',
|
|
19
|
-
'pnpm',
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
export default function OverflowListMultiRowTags() {
|
|
23
|
-
return (
|
|
24
|
-
<Card
|
|
25
|
-
padding={2}
|
|
26
|
-
style={{
|
|
27
|
-
resize: 'horizontal',
|
|
28
|
-
overflow: 'hidden',
|
|
29
|
-
minWidth: 120,
|
|
30
|
-
width: 260,
|
|
31
|
-
}}>
|
|
32
|
-
<OverflowList
|
|
33
|
-
gap={1}
|
|
34
|
-
maxRows={2}
|
|
35
|
-
overflowRenderer={overflowItems => (
|
|
36
|
-
<Badge variant="neutral" label={`+${overflowItems.length}`} />
|
|
37
|
-
)}>
|
|
38
|
-
{tags.map(tag => (
|
|
39
|
-
<Badge key={tag} variant="info" label={tag} />
|
|
40
|
-
))}
|
|
41
|
-
</OverflowList>
|
|
42
|
-
</Card>
|
|
43
|
-
);
|
|
44
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
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: 'Thumbnail',
|
|
7
|
-
name: 'Thumbnail — Elevated',
|
|
8
|
-
displayName: 'Thumbnail — Elevated',
|
|
9
|
-
description:
|
|
10
|
-
'Image tiles raised at rest with `elevation`. The default keeps the existing hover-only shadow; a set level lifts the tile off the page.',
|
|
11
|
-
isReady: true,
|
|
12
|
-
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['Thumbnail', 'Layout', 'Text'],
|
|
14
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
import {Thumbnail} from '@astryxdesign/core/Thumbnail';
|
|
6
|
-
import {Stack} from '@astryxdesign/core/Layout';
|
|
7
|
-
import {Text} from '@astryxdesign/core/Text';
|
|
8
|
-
|
|
9
|
-
// Demo imagery is inlined as same-origin data URIs so the example is
|
|
10
|
-
// self-contained. Thumbnail's remove-button overlay uses useImageMode, which
|
|
11
|
-
// FETCHES the image to sample pixels (APCA) for contrast — a cross-origin CDN
|
|
12
|
-
// URL without CORS headers cannot be sampled, so contrast detection fails
|
|
13
|
-
// silently in hosted previews.
|
|
14
|
-
const NIGHT_FOREST =
|
|
15
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEX18+H08uDy8d/y8N/v7t/m5NXl49Tk4tPc3NDX1cnW1cnW1cjW1MjV1MjV1MfR0cXIyLzEw7m8vLC3t68wM0QvM0MvM0IvMkIuMkEtMEErLz8iJjkhJTggJTcgJDcfJDYfIzYeIjUcITMbHzIWHiwYGzIXGjEWGjAWGTAVGS8VGC8UGC4UGC0UFy4TFy0TFywTFi0SFiwRFSsQFSkNFR4QFCoPFCkPFCgPEykOEygOEigNEicNEScMESYIDw8ECgr+gzZIAAABqElEQVR42uWQ61aCQBRGD5GylNBMKS9FZgNdNE0cyUvB+79VM8MoF9Fgplau2j/8nO8c9hqAD0ngDwjeJYH1lrfBWoCtYDboNu/Zv7qQYNap1bpCN1gxFh1dNe5WAsCScWqoWttbChAKvHZZ0W6XQoIFpW8ooFmLCG2Rl1BgaZAU5Ac8yg0RlC9nngCRQDFuhQRzinWmkCuYk3lxQoFrlskVqlcTMcEFvYIKoFbNfmEFuIypWaGGkt66tqZuEbjAHZl6SQVF1WqNvpDAHVktXTvR9JbgDZii1+tZI7cYMJXkCASvksB4L5VxHmAsibzgRRIYbjgfCgFDSeBZkh8W1HMIniSBR0mOQPCQA3RgBk4M5DhNZwdEcbKgLXy5iDiZg5gApRYbqTql2FZgMxAKeEWSNUFYx3s2SfU28HPWItrpySSwE2cEdqrYtxgmxgHGScFmHrAGk8SxczIxZnNC1McFOGshShyb4yxB9sI3CXDGnH0MLsD7F5LvvptEgH12Zg1Pn2WuHsjvrwt8308t+nwxT38sgiAE8/RTeagH+vx/F8SeF0Ja8Ak14ia/LgmpZQAAAABJRU5ErkJggg==';
|
|
16
|
-
const GOLDEN_SUNSET =
|
|
17
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAkFBMVEX/+uv/7sj6tFr3sVn1r1nzrVjxq1jvqVftp1frpVbpo1bnoVXln1XjnVThm1TfmVPdl1PblVLZk1LXkVLVj1HTjVHRi1DPiVDNh0/LhU/Jg07HgU7Ff03DfU3Be0y/eUy9d0u7dUu5c0u2cEq0bkqybEmwakmuaEisZkiqZEeoYkemYEakXkaiXEVgLjQ8HCjaJlMkAAABI0lEQVR42u3Mx3qDMBSE0Z/03nsvdhxjcnn/twsYjISR5MUkO5+V9N2ZYUPEpogtEdsidkTsitgTsS/iQMShiCMRxyJORJyKOBNxLuJCxKWIKxHXIm5E3Iq4E3Ev4kHEo4gnEc8iXkS8inhLymrJBO8J2UIiw0dc5sRDfEbVRWr1o/pbMMWox9yz6zcLIzMbBTD2VaHu7fr1gjXGA3w5baj5+H0w6x09TDpdaP7rDZhn0sd3y89Y9fcHbPnoYdroZ2w6dQNmg6OHfG4QyrsBC8gdZpVQxtqF4M1mjepFURThTLNgMYsePxaX2WqY6D8GSm2grK2slbGBciHZ9hOE2smNpTuxenhieCdeH06E7qTqvYnImWTbbUSPlKL1wHrgTwZ+AWq+3H5MpRkwAAAAAElFTkSuQmCC';
|
|
18
|
-
|
|
19
|
-
export default function ThumbnailElevated() {
|
|
20
|
-
return (
|
|
21
|
-
<Stack direction="vertical" gap={3}>
|
|
22
|
-
<Text type="supporting" color="secondary">
|
|
23
|
-
Raised tiles — `elevation` lifts an image off the page at rest
|
|
24
|
-
</Text>
|
|
25
|
-
<Stack direction="horizontal" gap={3} vAlign="center">
|
|
26
|
-
<Thumbnail src={NIGHT_FOREST} alt="Forest at night" elevation="low" />
|
|
27
|
-
<Thumbnail src={GOLDEN_SUNSET} alt="Golden sunset" elevation="high" />
|
|
28
|
-
</Stack>
|
|
29
|
-
</Stack>
|
|
30
|
-
);
|
|
31
|
-
}
|