@astryxdesign/cli 0.4.3-canary.72e38c1 → 0.4.3-canary.773ff16
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/README.md +1 -0
- package/api/discover/_adapter.d.mts +5 -3
- package/api/discover/_adapter.mjs +6 -4
- package/api/theme/theme.type.d.mts +16 -0
- package/api/theme/theme.type.mjs +11 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetHeights.doc.mjs +21 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetHeights.tsx +46 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetMobileKeyboard.doc.mjs +23 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetMobileKeyboard.tsx +100 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetNoScrim.doc.mjs +22 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetNoScrim.tsx +47 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetShowcase.doc.mjs +22 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetShowcase.tsx +51 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetSwitcherShowcase.doc.mjs +26 -0
- package/assets/templates/blocks/components/BottomSheet/BottomSheetSwitcherShowcase.tsx +221 -0
- package/authoring/doctypes/base/type.ts +9 -0
- package/clients/cli/commands/build-theme.mjs +154 -65
- package/clients/cli/commands/build-theme.multi.test.mjs +148 -0
- package/clients/cli/commands/build-theme.watch.test.mjs +67 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +112 -0
- package/clients/cli/commands/discover.mjs +12 -0
- package/clients/cli/commands/search.mjs +9 -0
- package/clients/cli/commands/theme-build.doc.mjs +11 -5
- package/clients/cli/lib/json-shim.test.mjs +1 -1
- package/clients/cli/lib/manifest.mjs +1 -1
- package/clients/cli/lib/manifest.test.mjs +4 -2
- package/foundation/integrations/integration-warnings.test.mjs +17 -0
- package/foundation/integrations/validate-contributions.mjs +7 -0
- package/foundation/response/response-types.doc.mjs +5 -0
- package/package.json +12 -9
- package/assets/templates/pages/table-page-chart/page.tsx +0 -577
- package/assets/templates/pages/table-page-chart/template.doc.mjs +0 -13
- package/assets/templates/pages/table-page-heatmap-status/page.tsx +0 -467
- package/assets/templates/pages/table-page-heatmap-status/template.doc.mjs +0 -13
- package/assets/templates/pages/table-page-shoe-store-heatmap/page.tsx +0 -931
- package/assets/templates/pages/table-page-shoe-store-heatmap/template.doc.mjs +0 -13
package/README.md
CHANGED
|
@@ -415,6 +415,7 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
415
415
|
| `hook.detail.params` | Just one hook's parameters table (HookParamDoc[]). |
|
|
416
416
|
| `theme.build` | A theme build receipt: name, token- and component-override counts, output size, the written outputs {css, js, dts, and variantsDts when applicable}, and any validation warnings. |
|
|
417
417
|
| `theme.build.check` | The --check receipt: theme name, an upToDate flag, the stale outputs (each {path, reason: missing \| outdated}), and the full list of checked paths. Writes nothing. |
|
|
418
|
+
| `theme.build.batch` | Several themes built in one invocation: `count` plus one {file, receipt} per theme in argument order, where receipt is that theme's theme.build (or theme.build.check) envelope, or null when it produced no CSS. |
|
|
418
419
|
| `theme.list` | Every bundled theme as a ThemeListEntry[]: each with slug, displayName, description, and a maintained flag. |
|
|
419
420
|
| `theme.add` | A scaffold receipt: resolved slug, displayName, maintained flag, outputDir (relative to cwd), the theme entry file, its exportName, and the files written. |
|
|
420
421
|
| `theme.template` | A write receipt for the annotated theme template: the path (relative to cwd), whether it was written, and the reason it was not — `exists` when a file was already there, which is a success. |
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* External packages come from configured integrations that declare a components
|
|
8
8
|
* root; each becomes a scannable package keyed by its docsDir. `configured`
|
|
9
|
-
* reports whether
|
|
10
|
-
*
|
|
11
|
-
* nothing
|
|
9
|
+
* reports whether the project configured ANY integration — including one whose
|
|
10
|
+
* manifest failed to load, which contributes nothing but is emphatically not
|
|
11
|
+
* "nothing configured". It lets an empty result distinguish "nothing
|
|
12
|
+
* configured" (`false`) from "configured but nothing discovered" (`true`),
|
|
13
|
+
* which the list leaf surfaces as `meta`.
|
|
12
14
|
*
|
|
13
15
|
* @returns {Promise<{packages: ScannedPackage[], configured: boolean}>}
|
|
14
16
|
*/
|
|
@@ -62,9 +62,11 @@ function validateDocs(docs) {
|
|
|
62
62
|
*
|
|
63
63
|
* External packages come from configured integrations that declare a components
|
|
64
64
|
* root; each becomes a scannable package keyed by its docsDir. `configured`
|
|
65
|
-
* reports whether
|
|
66
|
-
*
|
|
67
|
-
* nothing
|
|
65
|
+
* reports whether the project configured ANY integration — including one whose
|
|
66
|
+
* manifest failed to load, which contributes nothing but is emphatically not
|
|
67
|
+
* "nothing configured". It lets an empty result distinguish "nothing
|
|
68
|
+
* configured" (`false`) from "configured but nothing discovered" (`true`),
|
|
69
|
+
* which the list leaf surfaces as `meta`.
|
|
68
70
|
*
|
|
69
71
|
* @returns {Promise<{packages: ScannedPackage[], configured: boolean}>}
|
|
70
72
|
*/
|
|
@@ -84,7 +86,7 @@ export async function discoverPackages() {
|
|
|
84
86
|
docsDir: integration.components,
|
|
85
87
|
}));
|
|
86
88
|
if (explicitPackages.length === 0) {
|
|
87
|
-
return {packages: [], configured:
|
|
89
|
+
return {packages: [], configured: loadedIntegrations.length > 0};
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
const packages = scanAllPackages(
|
|
@@ -41,6 +41,22 @@ export type ThemeBuildCheckResponse = {
|
|
|
41
41
|
checked: string[];
|
|
42
42
|
};
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* xds --json theme build <a> <b> … — several themes in one invocation. Each
|
|
46
|
+
* result carries the file as it was passed and the receipt a single-file build
|
|
47
|
+
* would have returned (null when that theme produced no CSS). One file still
|
|
48
|
+
* returns the bare theme.build / theme.build.check envelope.
|
|
49
|
+
*/
|
|
50
|
+
export type ThemeBuildBatchResponse = {
|
|
51
|
+
type: "theme.build.batch";
|
|
52
|
+
data: {
|
|
53
|
+
count: number;
|
|
54
|
+
results: Array<{
|
|
55
|
+
file: string;
|
|
56
|
+
receipt: ThemeBuildResponse | ThemeBuildCheckResponse | null;
|
|
57
|
+
}>;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
44
60
|
/**
|
|
45
61
|
* A single theme entry as surfaced by `theme list`.
|
|
46
62
|
*/
|
package/api/theme/theme.type.mjs
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* ------------------------------------------------------------------
|
|
11
11
|
* xds --json theme build <file> -> theme.build
|
|
12
12
|
* xds --json theme build <file> --check -> theme.build.check
|
|
13
|
+
* xds --json theme build <a> <b> … -> theme.build.batch
|
|
13
14
|
* xds --json theme list -> theme.list
|
|
14
15
|
* xds --json theme add <slug> -> theme.add
|
|
15
16
|
* xds --json theme template -> theme.template
|
|
@@ -35,6 +36,16 @@
|
|
|
35
36
|
* @property {{name: string, upToDate: boolean, stale: Array<{path: string, reason: 'missing' | 'outdated'}>, checked: string[]}} data
|
|
36
37
|
*/
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* xds --json theme build <a> <b> … — several themes in one invocation. Each
|
|
41
|
+
* result carries the file as it was passed and the receipt a single-file build
|
|
42
|
+
* would have returned (null when that theme produced no CSS). One file still
|
|
43
|
+
* returns the bare theme.build / theme.build.check envelope.
|
|
44
|
+
* @typedef {object} ThemeBuildBatchResponse
|
|
45
|
+
* @property {'theme.build.batch'} type
|
|
46
|
+
* @property {{count: number, results: Array<{file: string, receipt: ThemeBuildResponse | ThemeBuildCheckResponse | null}>}} data
|
|
47
|
+
*/
|
|
48
|
+
|
|
38
49
|
/**
|
|
39
50
|
* A single theme entry as surfaced by `theme list`.
|
|
40
51
|
* @typedef {object} ThemeListEntry
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'BottomSheet',
|
|
7
|
+
name: 'Bottom Sheet — Height variants',
|
|
8
|
+
displayName: 'Bottom Sheet — Height variants',
|
|
9
|
+
description:
|
|
10
|
+
'Compares hug, capped, and tall starting heights for different amounts of content.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 3 / 4,
|
|
13
|
+
componentsUsed: [
|
|
14
|
+
'BottomSheet',
|
|
15
|
+
'Button',
|
|
16
|
+
'Divider',
|
|
17
|
+
'Heading',
|
|
18
|
+
'Stack',
|
|
19
|
+
'Text',
|
|
20
|
+
],
|
|
21
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {
|
|
7
|
+
BottomSheet,
|
|
8
|
+
type BottomSheetHeight,
|
|
9
|
+
} from '@astryxdesign/core/BottomSheet';
|
|
10
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
11
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
12
|
+
import {Heading} from '@astryxdesign/core/Heading';
|
|
13
|
+
import {HStack, VStack} from '@astryxdesign/core/Stack';
|
|
14
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
15
|
+
|
|
16
|
+
const descriptions: Record<BottomSheetHeight, string> = {
|
|
17
|
+
hug: 'Hug fits short, bounded content.',
|
|
18
|
+
capped: 'Capped starts at a comfortable mid-height for lists and filters.',
|
|
19
|
+
tall: 'Tall reserves most of the viewport for long or changing content.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function BottomSheetHeights() {
|
|
23
|
+
const [height, setHeight] = useState<BottomSheetHeight | null>(null);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<HStack gap={2} wrap="wrap">
|
|
28
|
+
<Button label="Open hug" onClick={() => setHeight('hug')} />
|
|
29
|
+
<Button label="Open capped" onClick={() => setHeight('capped')} />
|
|
30
|
+
<Button label="Open tall" onClick={() => setHeight('tall')} />
|
|
31
|
+
</HStack>
|
|
32
|
+
<BottomSheet
|
|
33
|
+
isOpen={height != null}
|
|
34
|
+
onOpenChange={isOpen => !isOpen && setHeight(null)}
|
|
35
|
+
label={`${height ?? 'Hug'} height`}
|
|
36
|
+
height={height ?? 'hug'}>
|
|
37
|
+
<VStack gap={4} style={{padding: 'var(--spacing-4)'}}>
|
|
38
|
+
<Heading level={3}>{height ?? 'Hug'} height</Heading>
|
|
39
|
+
<Divider />
|
|
40
|
+
<Text type="body">{descriptions[height ?? 'hug']}</Text>
|
|
41
|
+
<Button label="Close" onClick={() => setHeight(null)} />
|
|
42
|
+
</VStack>
|
|
43
|
+
</BottomSheet>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'BottomSheet',
|
|
7
|
+
name: 'Bottom Sheet — Mobile keyboard',
|
|
8
|
+
displayName: 'Bottom Sheet — Mobile keyboard',
|
|
9
|
+
description:
|
|
10
|
+
'Uses a tall, scrollable form that keeps focused controls visible above the mobile keyboard.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 3 / 4,
|
|
13
|
+
componentsUsed: [
|
|
14
|
+
'BottomSheet',
|
|
15
|
+
'Button',
|
|
16
|
+
'Divider',
|
|
17
|
+
'Heading',
|
|
18
|
+
'Stack',
|
|
19
|
+
'Text',
|
|
20
|
+
'TextArea',
|
|
21
|
+
'TextInput',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {BottomSheet} from '@astryxdesign/core/BottomSheet';
|
|
7
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
8
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
9
|
+
import {Heading} from '@astryxdesign/core/Heading';
|
|
10
|
+
import {VStack} from '@astryxdesign/core/Stack';
|
|
11
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
12
|
+
import {TextArea} from '@astryxdesign/core/TextArea';
|
|
13
|
+
import {TextInput} from '@astryxdesign/core/TextInput';
|
|
14
|
+
|
|
15
|
+
interface ProfileFormValues {
|
|
16
|
+
name: string;
|
|
17
|
+
email: string;
|
|
18
|
+
company: string;
|
|
19
|
+
role: string;
|
|
20
|
+
bio: string;
|
|
21
|
+
notes: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const initialValues: ProfileFormValues = {
|
|
25
|
+
name: '',
|
|
26
|
+
email: '',
|
|
27
|
+
company: '',
|
|
28
|
+
role: '',
|
|
29
|
+
bio: '',
|
|
30
|
+
notes: '',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default function BottomSheetMobileKeyboard() {
|
|
34
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
35
|
+
const [values, setValues] = useState(initialValues);
|
|
36
|
+
const update =
|
|
37
|
+
(field: keyof ProfileFormValues) =>
|
|
38
|
+
(value: string): void =>
|
|
39
|
+
setValues(current => ({...current, [field]: value}));
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<Button label="Edit profile" onClick={() => setIsOpen(true)} />
|
|
44
|
+
<BottomSheet
|
|
45
|
+
isOpen={isOpen}
|
|
46
|
+
onOpenChange={setIsOpen}
|
|
47
|
+
label="Edit profile"
|
|
48
|
+
height="tall">
|
|
49
|
+
<form
|
|
50
|
+
onSubmit={event => {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
setIsOpen(false);
|
|
53
|
+
}}>
|
|
54
|
+
<VStack gap={4} style={{padding: 'var(--spacing-4)'}}>
|
|
55
|
+
<Heading level={3}>Edit profile</Heading>
|
|
56
|
+
<Divider />
|
|
57
|
+
<Text type="supporting" color="secondary">
|
|
58
|
+
Focus fields throughout the form to see them remain visible above
|
|
59
|
+
the mobile keyboard.
|
|
60
|
+
</Text>
|
|
61
|
+
<TextInput
|
|
62
|
+
label="Name"
|
|
63
|
+
value={values.name}
|
|
64
|
+
onChange={update('name')}
|
|
65
|
+
/>
|
|
66
|
+
<TextInput
|
|
67
|
+
label="Email"
|
|
68
|
+
type="email"
|
|
69
|
+
value={values.email}
|
|
70
|
+
onChange={update('email')}
|
|
71
|
+
/>
|
|
72
|
+
<TextInput
|
|
73
|
+
label="Company"
|
|
74
|
+
value={values.company}
|
|
75
|
+
onChange={update('company')}
|
|
76
|
+
/>
|
|
77
|
+
<TextInput
|
|
78
|
+
label="Role"
|
|
79
|
+
value={values.role}
|
|
80
|
+
onChange={update('role')}
|
|
81
|
+
/>
|
|
82
|
+
<TextArea
|
|
83
|
+
label="Bio"
|
|
84
|
+
rows={5}
|
|
85
|
+
value={values.bio}
|
|
86
|
+
onChange={update('bio')}
|
|
87
|
+
/>
|
|
88
|
+
<TextArea
|
|
89
|
+
label="Notes"
|
|
90
|
+
rows={5}
|
|
91
|
+
value={values.notes}
|
|
92
|
+
onChange={update('notes')}
|
|
93
|
+
/>
|
|
94
|
+
<Button label="Save profile" type="submit" />
|
|
95
|
+
</VStack>
|
|
96
|
+
</form>
|
|
97
|
+
</BottomSheet>
|
|
98
|
+
</>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'BottomSheet',
|
|
7
|
+
name: 'Bottom Sheet — No scrim',
|
|
8
|
+
displayName: 'Bottom Sheet — No scrim',
|
|
9
|
+
description:
|
|
10
|
+
'Keeps the page visible and interactive behind a non-modal bottom sheet.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 3 / 4,
|
|
13
|
+
componentsUsed: [
|
|
14
|
+
'BottomSheet',
|
|
15
|
+
'Button',
|
|
16
|
+
'Divider',
|
|
17
|
+
'Heading',
|
|
18
|
+
'Section',
|
|
19
|
+
'Stack',
|
|
20
|
+
'Text',
|
|
21
|
+
],
|
|
22
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {BottomSheet} from '@astryxdesign/core/BottomSheet';
|
|
7
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
8
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
9
|
+
import {Heading} from '@astryxdesign/core/Heading';
|
|
10
|
+
import {Section} from '@astryxdesign/core/Section';
|
|
11
|
+
import {VStack} from '@astryxdesign/core/Stack';
|
|
12
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
13
|
+
|
|
14
|
+
export default function BottomSheetNoScrim() {
|
|
15
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
16
|
+
const [backgroundClicks, setBackgroundClicks] = useState(0);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Section padding={4}>
|
|
20
|
+
<VStack gap={3}>
|
|
21
|
+
<Heading level={3}>Nearby places</Heading>
|
|
22
|
+
<Text type="body">Background interactions: {backgroundClicks}</Text>
|
|
23
|
+
<Button
|
|
24
|
+
label="Interact with page"
|
|
25
|
+
variant="secondary"
|
|
26
|
+
onClick={() => setBackgroundClicks(count => count + 1)}
|
|
27
|
+
/>
|
|
28
|
+
<Button label="Show place details" onClick={() => setIsOpen(true)} />
|
|
29
|
+
</VStack>
|
|
30
|
+
<BottomSheet
|
|
31
|
+
isOpen={isOpen}
|
|
32
|
+
onOpenChange={setIsOpen}
|
|
33
|
+
label="Place details"
|
|
34
|
+
height="hug"
|
|
35
|
+
hasScrim={false}>
|
|
36
|
+
<VStack gap={4} style={{padding: 'var(--spacing-4)'}}>
|
|
37
|
+
<Heading level={3}>Central Park</Heading>
|
|
38
|
+
<Divider />
|
|
39
|
+
<Text type="body">
|
|
40
|
+
The page remains visible and interactive behind this sheet.
|
|
41
|
+
</Text>
|
|
42
|
+
<Button label="Close details" onClick={() => setIsOpen(false)} />
|
|
43
|
+
</VStack>
|
|
44
|
+
</BottomSheet>
|
|
45
|
+
</Section>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'BottomSheet',
|
|
7
|
+
name: 'Bottom Sheet',
|
|
8
|
+
displayName: 'Bottom Sheet',
|
|
9
|
+
description: 'A mobile filter surface that rises from the bottom edge.',
|
|
10
|
+
isReady: true,
|
|
11
|
+
isShowcase: true,
|
|
12
|
+
aspectRatio: 3 / 4,
|
|
13
|
+
componentsUsed: [
|
|
14
|
+
'BottomSheet',
|
|
15
|
+
'Button',
|
|
16
|
+
'CheckboxInput',
|
|
17
|
+
'Divider',
|
|
18
|
+
'Heading',
|
|
19
|
+
'Section',
|
|
20
|
+
'Stack',
|
|
21
|
+
],
|
|
22
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {BottomSheet} from '@astryxdesign/core/BottomSheet';
|
|
7
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
8
|
+
import {CheckboxInput} from '@astryxdesign/core/CheckboxInput';
|
|
9
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
10
|
+
import {Heading} from '@astryxdesign/core/Heading';
|
|
11
|
+
import {Section} from '@astryxdesign/core/Section';
|
|
12
|
+
import {VStack} from '@astryxdesign/core/Stack';
|
|
13
|
+
|
|
14
|
+
export default function BottomSheetShowcase() {
|
|
15
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
16
|
+
const [inStock, setInStock] = useState(false);
|
|
17
|
+
const [onSale, setOnSale] = useState(false);
|
|
18
|
+
const [freeShipping, setFreeShipping] = useState(false);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<Button label="Open sheet" onClick={() => setIsOpen(true)} />
|
|
23
|
+
<BottomSheet isOpen={isOpen} onOpenChange={setIsOpen} label="Filters">
|
|
24
|
+
<Section padding={4}>
|
|
25
|
+
<VStack gap={4}>
|
|
26
|
+
<Heading level={3}>Filters</Heading>
|
|
27
|
+
<Divider />
|
|
28
|
+
<VStack gap={2}>
|
|
29
|
+
<CheckboxInput
|
|
30
|
+
label="In stock"
|
|
31
|
+
value={inStock}
|
|
32
|
+
onChange={setInStock}
|
|
33
|
+
/>
|
|
34
|
+
<CheckboxInput
|
|
35
|
+
label="On sale"
|
|
36
|
+
value={onSale}
|
|
37
|
+
onChange={setOnSale}
|
|
38
|
+
/>
|
|
39
|
+
<CheckboxInput
|
|
40
|
+
label="Free shipping"
|
|
41
|
+
value={freeShipping}
|
|
42
|
+
onChange={setFreeShipping}
|
|
43
|
+
/>
|
|
44
|
+
</VStack>
|
|
45
|
+
<Button label="Apply" onClick={() => setIsOpen(false)} />
|
|
46
|
+
</VStack>
|
|
47
|
+
</Section>
|
|
48
|
+
</BottomSheet>
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
exampleFor: 'BottomSheetSwitcher',
|
|
7
|
+
name: 'Bottom Sheet Switcher',
|
|
8
|
+
displayName: 'Bottom Sheet Switcher',
|
|
9
|
+
description:
|
|
10
|
+
'A three-step flow that transitions between content-hugging sheets of different heights inside one shared dialog.',
|
|
11
|
+
isReady: true,
|
|
12
|
+
isShowcase: true,
|
|
13
|
+
aspectRatio: 3 / 4,
|
|
14
|
+
componentsUsed: [
|
|
15
|
+
'BottomSheet',
|
|
16
|
+
'BottomSheetSwitcher',
|
|
17
|
+
'Button',
|
|
18
|
+
'CheckboxInput',
|
|
19
|
+
'Divider',
|
|
20
|
+
'Heading',
|
|
21
|
+
'RadioList',
|
|
22
|
+
'Section',
|
|
23
|
+
'Stack',
|
|
24
|
+
'Text',
|
|
25
|
+
],
|
|
26
|
+
};
|