@astryxdesign/cli 0.1.1 → 0.1.2-canary.2149fa3
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/CHANGELOG.md +50 -0
- package/docs/theme.doc.mjs +2 -2
- package/docs/working-with-ai.doc.mjs +6 -6
- package/package.json +19 -8
- package/src/api/discover.mjs +78 -26
- package/src/api/index.mjs +1 -0
- package/src/api/layout.mjs +301 -0
- package/src/api/layout.test.mjs +238 -0
- package/src/api/template.mjs +191 -50
- package/src/api/template.test.mjs +2 -0
- package/src/api/theme-add.mjs +182 -0
- package/src/codemods/__tests__/registry.test.mjs +1 -0
- package/src/codemods/registry.mjs +1 -0
- package/src/codemods/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +120 -0
- package/src/codemods/transforms/v0.1.2/index.mjs +19 -0
- package/src/codemods/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +136 -0
- package/src/commands/build-theme.import-path.test.mjs +22 -2
- package/src/commands/build-theme.mjs +185 -16
- package/src/commands/gap-report.mjs +17 -9
- package/src/commands/gap-report.test.mjs +21 -16
- package/src/commands/init.mjs +34 -8
- package/src/commands/init.next-steps.test.mjs +46 -0
- package/src/commands/layout.mjs +139 -0
- package/src/commands/swizzle.mjs +51 -23
- package/src/commands/upgrade.mjs +2 -71
- package/src/config.mjs +31 -0
- package/src/config.test.mjs +24 -0
- package/src/index.mjs +6 -0
- package/src/lib/config-schema.mjs +119 -0
- package/src/lib/config.mjs +34 -7
- package/src/lib/config.test.mjs +51 -2
- package/src/lib/error-codes.mjs +11 -0
- package/src/lib/integrations.mjs +155 -0
- package/src/lib/integrations.test.mjs +154 -0
- package/src/lib/levenshtein.mjs +29 -0
- package/src/lib/manifest.mjs +10 -0
- package/src/lib/package-scanner.mjs +31 -7
- package/src/lib/string-utils.mjs +5 -14
- package/src/lib/xle/browser.d.ts +100 -0
- package/src/lib/xle/browser.mjs +120 -0
- package/src/lib/xle/expand.mjs +622 -0
- package/src/lib/xle/parse.mjs +581 -0
- package/src/lib/xle/print.mjs +174 -0
- package/src/lib/xle/registry-core.mjs +170 -0
- package/src/lib/xle/registry.mjs +237 -0
- package/src/lib/xle/splice.mjs +137 -0
- package/src/lib/xle/validate.mjs +356 -0
- package/src/lib/xle/xle.test.mjs +333 -0
- package/src/types/config.d.ts +99 -0
- package/src/utils/github.mjs +12 -27
- package/templates/blocks/components/Card/ClickableCardWithNestedButton.doc.mjs +1 -1
- package/templates/blocks/components/Card/SelectableCardMulti.doc.mjs +1 -1
- package/templates/blocks/components/ChatComposerDrawer/ChatComposerDrawerWithProgress.tsx +1 -1
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonShowcase.tsx +3 -3
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyShowcase.doc.mjs +15 -0
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyShowcase.tsx +26 -0
- package/templates/blocks/components/DateInput/DateInputDateRange.doc.mjs +2 -2
- package/templates/blocks/components/FileInput/FileInputShowcase.tsx +4 -2
- package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.doc.mjs +14 -0
- package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.tsx +43 -0
- package/templates/blocks/components/MultiSelector/MultiSelectorShowcase.tsx +6 -2
- package/templates/blocks/components/NumberInput/NumberInputShowcase.tsx +6 -2
- package/templates/blocks/components/Outline/OutlineShowcase.doc.mjs +15 -0
- package/templates/blocks/components/Outline/OutlineShowcase.tsx +22 -0
- package/templates/blocks/components/RadioList/RadioListShowcase.tsx +8 -1
- package/templates/blocks/components/SegmentedControl/SegmentedControlShowcase.tsx +3 -1
- package/templates/blocks/components/Selector/SelectorShowcase.tsx +4 -1
- package/templates/blocks/components/Slider/SliderShowcase.tsx +10 -1
- package/templates/blocks/components/Tab/TabShowcase.tsx +3 -1
- package/templates/blocks/components/TabList/TabListShowcase.tsx +3 -1
- package/templates/blocks/components/TabMenu/TabMenuShowcase.tsx +3 -1
- package/templates/blocks/components/Table/ColumnResizeHookUsage.doc.mjs +14 -0
- package/templates/blocks/components/Table/ColumnResizeHookUsage.tsx +59 -0
- package/templates/blocks/components/Table/StickyColumnsHookUsage.doc.mjs +14 -0
- package/templates/blocks/components/Table/StickyColumnsHookUsage.tsx +104 -0
- package/templates/blocks/components/Text/TextColors.tsx +20 -5
- package/templates/blocks/components/TextArea/TextAreaShowcase.tsx +4 -2
- package/templates/blocks/components/TextInput/TextInputShowcase.tsx +4 -2
- package/templates/blocks/components/Thumbnail/ThumbnailDisabled.tsx +11 -6
- package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +43 -7
- package/templates/blocks/components/Thumbnail/ThumbnailRemovable.tsx +40 -3
- package/templates/blocks/components/Thumbnail/ThumbnailShowcase.tsx +6 -5
- package/templates/blocks/components/Thumbnail/ThumbnailStates.tsx +11 -6
- package/templates/blocks/components/Timestamp/TimestampColors.tsx +2 -2
- package/templates/blocks/components/ToggleButton/ToggleButtonGroup.doc.mjs +1 -1
- package/templates/blocks/components/Tokenizer/TokenizerShowcase.tsx +8 -6
- package/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +2 -2
- package/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +23 -14
- package/templates/blocks/components/Typeahead/TypeaheadShowcase.tsx +6 -2
- package/templates/pages/shell-nav/page.tsx +321 -0
- package/templates/pages/shell-nav/template.doc.mjs +12 -0
- package/templates/pages/shell-side-nav/page.tsx +242 -0
- package/templates/pages/shell-side-nav/template.doc.mjs +12 -0
- package/templates/pages/shell-top-nav/page.tsx +224 -0
- package/templates/pages/shell-top-nav/template.doc.mjs +12 -0
- package/templates/pages/theme-showcase/page.tsx +8 -19
- package/templates/themes/butter/butterTheme.ts +916 -0
- package/templates/themes/butter/icons.tsx +77 -0
- package/templates/themes/chocolate/chocolateTheme.ts +230 -0
- package/templates/themes/chocolate/icons.tsx +77 -0
- package/templates/themes/gothic/gothicTheme.ts +657 -0
- package/templates/themes/gothic/icons.tsx +77 -0
- package/templates/themes/manifest.json +90 -0
- package/templates/themes/matcha/icons.tsx +67 -0
- package/templates/themes/matcha/matchaTheme.ts +247 -0
- package/templates/themes/neutral/icons.tsx +77 -0
- package/templates/themes/neutral/neutralTheme.ts +603 -0
- package/templates/themes/stone/icons.tsx +77 -0
- package/templates/themes/stone/stoneTheme.ts +652 -0
- package/templates/themes/y2k/icons.tsx +67 -0
- package/templates/themes/y2k/y2kTheme.ts +617 -0
- package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.doc.mjs +0 -14
- package/templates/blocks/components/MoreMenu/MoreMenuInToolbar.tsx +0 -57
|
@@ -7,10 +7,47 @@ import {Thumbnail} from '@astryxdesign/core/Thumbnail';
|
|
|
7
7
|
import {Stack} from '@astryxdesign/core/Layout';
|
|
8
8
|
import {Text} from '@astryxdesign/core/Text';
|
|
9
9
|
|
|
10
|
+
// Demo imagery is inlined as same-origin data URIs so the example is
|
|
11
|
+
// self-contained. Thumbnail's remove-button overlay uses useImageMode, which
|
|
12
|
+
// FETCHES the image to sample pixels (APCA) for contrast — a cross-origin CDN
|
|
13
|
+
// URL without CORS headers cannot be fetched/sampled, so contrast detection
|
|
14
|
+
// fails silently in hosted previews. These scenes are shared verbatim across
|
|
15
|
+
// the Thumbnail examples and span a luminance ramp (night → snow) so the
|
|
16
|
+
// overlay's contrast adaptation is visible.
|
|
17
|
+
const NIGHT_FOREST =
|
|
18
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEX18+H08uDy8d/y8N/v7t/m5NXl49Tk4tPc3NDX1cnW1cnW1cjW1MjV1MjV1MfR0cXIyLzEw7m8vLC3t68wM0QvM0MvM0IvMkIuMkEtMEErLz8iJjkhJTggJTcgJDcfJDYfIzYeIjUcITMbHzIWHiwYGzIXGjEWGjAWGTAVGS8VGC8UGC4UGC0UFy4TFy0TFywTFi0SFiwRFSsQFSkNFR4QFCoPFCkPFCgPEykOEygOEigNEicNEScMESYIDw8ECgr+gzZIAAABqElEQVR42uWQ61aCQBRGD5GylNBMKS9FZgNdNE0cyUvB+79VM8MoF9Fgplau2j/8nO8c9hqAD0ngDwjeJYH1lrfBWoCtYDboNu/Zv7qQYNap1bpCN1gxFh1dNe5WAsCScWqoWttbChAKvHZZ0W6XQoIFpW8ooFmLCG2Rl1BgaZAU5Ac8yg0RlC9nngCRQDFuhQRzinWmkCuYk3lxQoFrlskVqlcTMcEFvYIKoFbNfmEFuIypWaGGkt66tqZuEbjAHZl6SQVF1WqNvpDAHVktXTvR9JbgDZii1+tZI7cYMJXkCASvksB4L5VxHmAsibzgRRIYbjgfCgFDSeBZkh8W1HMIniSBR0mOQPCQA3RgBk4M5DhNZwdEcbKgLXy5iDiZg5gApRYbqTql2FZgMxAKeEWSNUFYx3s2SfU28HPWItrpySSwE2cEdqrYtxgmxgHGScFmHrAGk8SxczIxZnNC1McFOGshShyb4yxB9sI3CXDGnH0MLsD7F5LvvptEgH12Zg1Pn2WuHsjvrwt8308t+nwxT38sgiAE8/RTeagH+vx/F8SeF0Ja8Ak14ia/LgmpZQAAAABJRU5ErkJggg==';
|
|
19
|
+
const MISTY_VALLEY =
|
|
20
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEWPnaqJmKSIlaKHlaGGlaKGk6CEkp6Ckp+Cj5uAj51/jZp6i5h8ipd7iZZ4hpR1g5FzhpdzhJN0g5FuhZdsgpVqgZRpgJNpf5JmfpFufYxufYtlfJBpe4tke49neo1ieo5kd4tndoZidopheY1geIxfd4tmdYVddYpcdIlbc4hgcoNebn5ZcodYcYZXb4VVboRUbYNTbIJaantWaXxRa4FQaYBPaH9NZ35UZXZQY3dMZn1LZXxKZHxMYHRKXnIoOEh3WzsBAAABeElEQVR42u3T11oCQQyG4R9FEREFqVJEgh17xbZ7/3cl29gpmQGeeOh7OF+Ss8G3EL6E8CmEdyG8CeFVCC9CeBTCgxDuhXAnhFsh3AjhSgiXQrgQwtlayHrB6TqIyHzCREMTH4rpbxip5nnkRintEUNF0oc8yqnP6Oey3ueQSnlHN6P0ro0Mi4BOSu8dA1mygnbC7G0NMdKEVszuLQXx4oZmhO3NDLlEEY05R280PDGbgD0RaBeI/Bdg7weBMkDLwF4PtBOcwH0gCJZf0DPYdd8Jo8K177hgZbjW+RN2hWffusBVnMR+XE5yfMRx5MPtOOOI0Xd+9ot/rTOiVrtepuabwcDwNFgP6przSH0dqKiOUhUfvaKcO8yVncyM0sK+psSyK4qpPUvRwlUUYrusgoaviG27YMFXNz38I0nc8PNPAFtC2BFClRFWV4cDU5g4WEE0hJ4q1PU8sgmMF0LOmKN2TBOh21RjRsxms3C5WYwrCIX+D/zBgV8HCFv4gVKf1AAAAABJRU5ErkJggg==';
|
|
21
|
+
const GOLDEN_SUNSET =
|
|
22
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAkFBMVEX/+uv/7sj6tFr3sVn1r1nzrVjxq1jvqVftp1frpVbpo1bnoVXln1XjnVThm1TfmVPdl1PblVLZk1LXkVLVj1HTjVHRi1DPiVDNh0/LhU/Jg07HgU7Ff03DfU3Be0y/eUy9d0u7dUu5c0u2cEq0bkqybEmwakmuaEisZkiqZEeoYkemYEakXkaiXEVgLjQ8HCjaJlMkAAABI0lEQVR42u3Mx3qDMBSE0Z/03nsvdhxjcnn/twsYjISR5MUkO5+V9N2ZYUPEpogtEdsidkTsitgTsS/iQMShiCMRxyJORJyKOBNxLuJCxKWIKxHXIm5E3Iq4E3Ev4kHEo4gnEc8iXkS8inhLymrJBO8J2UIiw0dc5sRDfEbVRWr1o/pbMMWox9yz6zcLIzMbBTD2VaHu7fr1gjXGA3w5baj5+H0w6x09TDpdaP7rDZhn0sd3y89Y9fcHbPnoYdroZ2w6dQNmg6OHfG4QyrsBC8gdZpVQxtqF4M1mjepFURThTLNgMYsePxaX2WqY6D8GSm2grK2slbGBciHZ9hOE2smNpTuxenhieCdeH06E7qTqvYnImWTbbUSPlKL1wHrgTwZ+AWq+3H5MpRkwAAAAAElFTkSuQmCC';
|
|
23
|
+
const SNOWY_PEAKS =
|
|
24
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEX////6/P/4+//g7vjf7fbf7fTe7fje7fTe7PTd7Pjc7Pfd7PTc6/Xc6/Pb6/fb6/Xb6vTa6/fa6/Xa6vfZ6vfZ6vba6vTZ6fXY6vfY6vbY6ffY6fXX6fbX6fTW6fbX6PXW6PbW6PTV6PbV6PXU6PbV5/XU5/bU5/TU5vXT5/bS5/XT5vTS5vXS5vTR5vXR5fXQ5fXP5fXP5PXO5PXO5PTN5PTN4/TM4/TL4/TM4vTL4vTK4vTO3OqqvtKbrsFcfGgMVnjaAAAC7klEQVR42u2Ta3eaQBCGp0kbTbBBMWDMoiCWEOsFtV4SdcP//1edYQUWwSye9kNOT58POVlm3mdmUWG/3+9et5vVYj6bjoMgGE9n88Vqs33d7SsBcX67WmI+EKBhudpWNcBu94bzlyGO9weEj0uES9zhbVcFSPMYdxzmOKi4xACbNa0/DgY91rGIDusNgjFdY72tAKzXq0U4pTyGm80m/iXDNFys1psqApwf4nwc32x+J9DRYbhDuMRrqIF5vD+zKK0R5LBYfIvFcqUEBZPRsNex9IaW0NCtTm84mqDglxIIQ3z/uEBDqydoDVrBH4d4CyUwowUsA+fXa4I67mBYtAJeQglM4jeg0wLfBLSCLt5COFcC4xffYVZ8gVSABos5/sskVAOjYNjvWrqWxGOFplvd/jD4OZkpgSAYiA1yAtpgGIzGEyW0wYCZeqOeGer1hm6yQUXBD8+1uySofU2okaBre97zSA34nuswk74GqYC+CCZzXM9/VgO+77o2M+LPUcTpUzSYXS3/DB7m4ztomrhEjb7LeAPbdb0KgOe5fTIY6Y8B51O+Xynvgeu6js2Yaep6Q6DrpsmY7biVABthXdPEFfRj3sBTl9nl8JNzLMANSGEahm5QGuNn8/zEAE8xD0g7hrfbdHgqhxO5J/B4BEMtBOv43+M5YkHuCTxk0HwuDGfgvNAAbZljQ/sMnEOhAVoSPKFVCuYBThvgXiKdcF8GlwRZB+Tz8IEhLhca4C6F8yusH0TDXYFjPjEkj+E2gecm8NsT+IkgaQBVQ6F80gA3Ai4uANkl+I0ElYlDjNwAhXyp4Zg/Cg4FAS+dwAsLiPq7PAGuEc5LJ3B+LUjLSf2Q1aGk4V1uyJVTQdYAqgZ5v7T+nu0IuXwmkAwf1yE3IJuQjZDLkiBpAK5o4BUEV6UNh5J8SR1y9VzDoZgvqasFV2frByFQNCgFX/6Q/4J/SxDJTy84/DVBFEmlSw6fRhBFUumiw2cRRJFUuuzwG+qew9oBo+n5AAAAAElFTkSuQmCC';
|
|
25
|
+
|
|
10
26
|
const IMAGES = [
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
{
|
|
28
|
+
id: 1,
|
|
29
|
+
src: NIGHT_FOREST,
|
|
30
|
+
alt: 'Forest at night under a crescent moon',
|
|
31
|
+
label: 'forest-night.jpg',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 2,
|
|
35
|
+
src: MISTY_VALLEY,
|
|
36
|
+
alt: 'Misty mountain valley',
|
|
37
|
+
label: 'misty-valley.jpg',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 3,
|
|
41
|
+
src: GOLDEN_SUNSET,
|
|
42
|
+
alt: 'Golden sunset over mountains',
|
|
43
|
+
label: 'golden-sunset.jpg',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 4,
|
|
47
|
+
src: SNOWY_PEAKS,
|
|
48
|
+
alt: 'Snowy mountain peaks',
|
|
49
|
+
label: 'snowy-peaks.jpg',
|
|
50
|
+
},
|
|
14
51
|
];
|
|
15
52
|
|
|
16
53
|
export default function ThumbnailRemovable() {
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import {Thumbnail} from '@astryxdesign/core/Thumbnail';
|
|
6
6
|
|
|
7
|
+
// Inline same-origin data URI so the example is self-contained — see
|
|
8
|
+
// ThumbnailRemovable for why image-backed Thumbnails avoid cross-origin URLs.
|
|
9
|
+
const SNOWY_PEAKS =
|
|
10
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEX////6/P/4+//g7vjf7fbf7fTe7fje7fTe7PTd7Pjc7Pfd7PTc6/Xc6/Pb6/fb6/Xb6vTa6/fa6/Xa6vfZ6vfZ6vba6vTZ6fXY6vfY6vbY6ffY6fXX6fbX6fTW6fbX6PXW6PbW6PTV6PbV6PXU6PbV5/XU5/bU5/TU5vXT5/bS5/XT5vTS5vXS5vTR5vXR5fXQ5fXP5fXP5PXO5PXO5PTN5PTN4/TM4/TL4/TM4vTL4vTK4vTO3OqqvtKbrsFcfGgMVnjaAAAC7klEQVR42u2Ta3eaQBCGp0kbTbBBMWDMoiCWEOsFtV4SdcP//1edYQUWwSye9kNOT58POVlm3mdmUWG/3+9et5vVYj6bjoMgGE9n88Vqs33d7SsBcX67WmI+EKBhudpWNcBu94bzlyGO9weEj0uES9zhbVcFSPMYdxzmOKi4xACbNa0/DgY91rGIDusNgjFdY72tAKzXq0U4pTyGm80m/iXDNFys1psqApwf4nwc32x+J9DRYbhDuMRrqIF5vD+zKK0R5LBYfIvFcqUEBZPRsNex9IaW0NCtTm84mqDglxIIQ3z/uEBDqydoDVrBH4d4CyUwowUsA+fXa4I67mBYtAJeQglM4jeg0wLfBLSCLt5COFcC4xffYVZ8gVSABos5/sskVAOjYNjvWrqWxGOFplvd/jD4OZkpgSAYiA1yAtpgGIzGEyW0wYCZeqOeGer1hm6yQUXBD8+1uySofU2okaBre97zSA34nuswk74GqYC+CCZzXM9/VgO+77o2M+LPUcTpUzSYXS3/DB7m4ztomrhEjb7LeAPbdb0KgOe5fTIY6Y8B51O+Xynvgeu6js2Yaep6Q6DrpsmY7biVABthXdPEFfRj3sBTl9nl8JNzLMANSGEahm5QGuNn8/zEAE8xD0g7hrfbdHgqhxO5J/B4BEMtBOv43+M5YkHuCTxk0HwuDGfgvNAAbZljQ/sMnEOhAVoSPKFVCuYBThvgXiKdcF8GlwRZB+Tz8IEhLhca4C6F8yusH0TDXYFjPjEkj+E2gecm8NsT+IkgaQBVQ6F80gA3Ai4uANkl+I0ElYlDjNwAhXyp4Zg/Cg4FAS+dwAsLiPq7PAGuEc5LJ3B+LUjLSf2Q1aGk4V1uyJVTQdYAqgZ5v7T+nu0IuXwmkAwf1yE3IJuQjZDLkiBpAK5o4BUEV6UNh5J8SR1y9VzDoZgvqasFV2frByFQNCgFX/6Q/4J/SxDJTy84/DVBFEmlSw6fRhBFUumiw2cRRJFUuuzwG+qew9oBo+n5AAAAAElFTkSuQmCC';
|
|
11
|
+
|
|
7
12
|
export default function ThumbnailShowcase() {
|
|
8
13
|
return (
|
|
9
|
-
<Thumbnail
|
|
10
|
-
src="https://lookaside.facebook.com/assets/astryx/moody-scene-vertical-2.png"
|
|
11
|
-
alt="Sample image"
|
|
12
|
-
label="photo.jpg"
|
|
13
|
-
/>
|
|
14
|
+
<Thumbnail src={SNOWY_PEAKS} alt="Snowy mountain peaks" label="snowy-peaks.jpg" />
|
|
14
15
|
);
|
|
15
16
|
}
|
|
@@ -6,6 +6,11 @@ import {Thumbnail} from '@astryxdesign/core/Thumbnail';
|
|
|
6
6
|
import {Stack} from '@astryxdesign/core/Layout';
|
|
7
7
|
import {Text} from '@astryxdesign/core/Text';
|
|
8
8
|
|
|
9
|
+
// Inline same-origin data URI so the example is self-contained — see
|
|
10
|
+
// ThumbnailRemovable for why image-backed Thumbnails avoid cross-origin URLs.
|
|
11
|
+
const MISTY_VALLEY =
|
|
12
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAwFBMVEWPnaqJmKSIlaKHlaGGlaKGk6CEkp6Ckp+Cj5uAj51/jZp6i5h8ipd7iZZ4hpR1g5FzhpdzhJN0g5FuhZdsgpVqgZRpgJNpf5JmfpFufYxufYtlfJBpe4tke49neo1ieo5kd4tndoZidopheY1geIxfd4tmdYVddYpcdIlbc4hgcoNebn5ZcodYcYZXb4VVboRUbYNTbIJaantWaXxRa4FQaYBPaH9NZ35UZXZQY3dMZn1LZXxKZHxMYHRKXnIoOEh3WzsBAAABeElEQVR42u3T11oCQQyG4R9FEREFqVJEgh17xbZ7/3cl29gpmQGeeOh7OF+Ss8G3EL6E8CmEdyG8CeFVCC9CeBTCgxDuhXAnhFsh3AjhSgiXQrgQwtlayHrB6TqIyHzCREMTH4rpbxip5nnkRintEUNF0oc8yqnP6Oey3ueQSnlHN6P0ro0Mi4BOSu8dA1mygnbC7G0NMdKEVszuLQXx4oZmhO3NDLlEEY05R280PDGbgD0RaBeI/Bdg7weBMkDLwF4PtBOcwH0gCJZf0DPYdd8Jo8K177hgZbjW+RN2hWffusBVnMR+XE5yfMRx5MPtOOOI0Xd+9ot/rTOiVrtepuabwcDwNFgP6przSH0dqKiOUhUfvaKcO8yVncyM0sK+psSyK4qpPUvRwlUUYrusgoaviG27YMFXNz38I0nc8PNPAFtC2BFClRFWV4cDU5g4WEE0hJ4q1PU8sgmMF0LOmKN2TBOh21RjRsxms3C5WYwrCIX+D/zBgV8HCFv4gVKf1AAAAABJRU5ErkJggg==';
|
|
13
|
+
|
|
9
14
|
export default function ThumbnailStates() {
|
|
10
15
|
return (
|
|
11
16
|
<Stack direction="vertical" gap={4}>
|
|
@@ -28,10 +33,10 @@ export default function ThumbnailStates() {
|
|
|
28
33
|
</Stack>
|
|
29
34
|
<Stack direction="vertical" gap={1} hAlign="center">
|
|
30
35
|
<Thumbnail
|
|
31
|
-
src=
|
|
32
|
-
alt="
|
|
36
|
+
src={MISTY_VALLEY}
|
|
37
|
+
alt="Misty mountain valley"
|
|
33
38
|
isLoading
|
|
34
|
-
label="
|
|
39
|
+
label="misty-valley.jpg"
|
|
35
40
|
/>
|
|
36
41
|
<Text type="supporting" color="secondary">
|
|
37
42
|
Uploading
|
|
@@ -39,9 +44,9 @@ export default function ThumbnailStates() {
|
|
|
39
44
|
</Stack>
|
|
40
45
|
<Stack direction="vertical" gap={1} hAlign="center">
|
|
41
46
|
<Thumbnail
|
|
42
|
-
src=
|
|
43
|
-
alt="
|
|
44
|
-
label="
|
|
47
|
+
src={MISTY_VALLEY}
|
|
48
|
+
alt="Misty mountain valley"
|
|
49
|
+
label="misty-valley.jpg"
|
|
45
50
|
/>
|
|
46
51
|
<Text type="supporting" color="secondary">
|
|
47
52
|
Loaded
|
|
@@ -31,9 +31,9 @@ export default function TimestampColors() {
|
|
|
31
31
|
</Stack>
|
|
32
32
|
<Stack direction="vertical" gap={1}>
|
|
33
33
|
<Text type="supporting" color="secondary">
|
|
34
|
-
|
|
34
|
+
Accent
|
|
35
35
|
</Text>
|
|
36
|
-
<Timestamp value={DATE} format="date_time" color="
|
|
36
|
+
<Timestamp value={DATE} format="date_time" color="accent" />
|
|
37
37
|
</Stack>
|
|
38
38
|
</Stack>
|
|
39
39
|
);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/** @type {import('../../../../../core/src/docs-types').TemplateDoc} */
|
|
4
4
|
export const doc = {
|
|
5
5
|
type: 'block',
|
|
6
|
-
exampleFor: '
|
|
6
|
+
exampleFor: 'ToggleButtonGroup',
|
|
7
7
|
name: 'ToggleButton — Group',
|
|
8
8
|
displayName: 'ToggleButton — Group',
|
|
9
9
|
description: 'Toggle button groups in single-select and multi-select modes. Single selection acts as a view mode switcher; multiple selection forms a formatting toolbar.',
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
+
import {useState} from 'react';
|
|
5
6
|
import {Tokenizer} from '@astryxdesign/core/Tokenizer';
|
|
6
|
-
import type {SearchSource} from '@astryxdesign/core/Typeahead';
|
|
7
|
+
import type {SearchableItem, SearchSource} from '@astryxdesign/core/Typeahead';
|
|
7
8
|
|
|
8
9
|
const source: SearchSource = {
|
|
9
10
|
search: () => [],
|
|
@@ -11,16 +12,17 @@ const source: SearchSource = {
|
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export default function TokenizerShowcase() {
|
|
15
|
+
const [value, setValue] = useState<SearchableItem[]>([
|
|
16
|
+
{id: '1', label: 'Design'},
|
|
17
|
+
{id: '2', label: 'Engineering'},
|
|
18
|
+
]);
|
|
14
19
|
return (
|
|
15
20
|
<Tokenizer
|
|
16
21
|
label="Tags"
|
|
17
22
|
placeholder="Search..."
|
|
18
23
|
searchSource={source}
|
|
19
|
-
value={
|
|
20
|
-
|
|
21
|
-
{id: '2', label: 'Engineering'},
|
|
22
|
-
]}
|
|
23
|
-
onChange={() => {}}
|
|
24
|
+
value={value}
|
|
25
|
+
onChange={setValue}
|
|
24
26
|
style={{width: 400}}
|
|
25
27
|
/>
|
|
26
28
|
);
|
|
@@ -7,8 +7,8 @@ export const doc = {
|
|
|
7
7
|
name: 'Toolbar — Table Filter',
|
|
8
8
|
displayName: 'Toolbar — Table Filter',
|
|
9
9
|
description:
|
|
10
|
-
'A compact toolbar with a search input, filter
|
|
10
|
+
'A compact toolbar with a search input, Status and Priority filter selectors, and an overflow menu. Use above a data table to let users search, filter, and access view options.',
|
|
11
11
|
isReady: true,
|
|
12
12
|
aspectRatio: 16 / 9,
|
|
13
|
-
componentsUsed: ['Toolbar', '
|
|
13
|
+
componentsUsed: ['Toolbar', 'Selector', 'TextInput', 'MoreMenu', 'Layout', 'Table'],
|
|
14
14
|
};
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
+
import {useState} from 'react';
|
|
5
6
|
import {Toolbar} from '@astryxdesign/core/Toolbar';
|
|
6
|
-
import {
|
|
7
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
7
|
+
import {Selector} from '@astryxdesign/core/Selector';
|
|
8
8
|
import {TextInput} from '@astryxdesign/core/TextInput';
|
|
9
9
|
import {MoreMenu} from '@astryxdesign/core/MoreMenu';
|
|
10
10
|
import {Stack} from '@astryxdesign/core/Layout';
|
|
11
11
|
import {Table} from '@astryxdesign/core/Table';
|
|
12
|
-
import {
|
|
13
|
-
MagnifyingGlassIcon,
|
|
14
|
-
ChevronDownIcon,
|
|
15
|
-
} from '@heroicons/react/24/outline';
|
|
12
|
+
import {MagnifyingGlassIcon} from '@heroicons/react/24/outline';
|
|
16
13
|
|
|
17
14
|
export default function ToolbarTableFilter() {
|
|
15
|
+
const [search, setSearch] = useState('');
|
|
16
|
+
const [status, setStatus] = useState<string | null>(null);
|
|
17
|
+
const [priority, setPriority] = useState<string | null>(null);
|
|
18
|
+
|
|
18
19
|
return (
|
|
19
20
|
<Stack direction="vertical" style={{width: '100%'}}>
|
|
20
21
|
<Toolbar
|
|
@@ -27,19 +28,27 @@ export default function ToolbarTableFilter() {
|
|
|
27
28
|
label="Search"
|
|
28
29
|
isLabelHidden
|
|
29
30
|
placeholder="Search..."
|
|
30
|
-
value=
|
|
31
|
-
onChange={
|
|
31
|
+
value={search}
|
|
32
|
+
onChange={setSearch}
|
|
32
33
|
startIcon={MagnifyingGlassIcon}
|
|
33
34
|
/>
|
|
34
|
-
<
|
|
35
|
+
<Selector
|
|
35
36
|
label="Status"
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
isLabelHidden
|
|
38
|
+
placeholder="Status"
|
|
39
|
+
hasClear
|
|
40
|
+
value={status}
|
|
41
|
+
onChange={setStatus}
|
|
42
|
+
options={['Open', 'In progress', 'Done']}
|
|
38
43
|
/>
|
|
39
|
-
<
|
|
44
|
+
<Selector
|
|
40
45
|
label="Priority"
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
isLabelHidden
|
|
47
|
+
placeholder="Priority"
|
|
48
|
+
hasClear
|
|
49
|
+
value={priority}
|
|
50
|
+
onChange={setPriority}
|
|
51
|
+
options={['High', 'Medium', 'Low']}
|
|
43
52
|
/>
|
|
44
53
|
</>
|
|
45
54
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
3
6
|
import {Typeahead} from '@astryxdesign/core/Typeahead';
|
|
4
7
|
import type {SearchableItem, SearchSource} from '@astryxdesign/core/Typeahead';
|
|
5
8
|
|
|
@@ -21,14 +24,15 @@ const fruitSource: SearchSource = {
|
|
|
21
24
|
};
|
|
22
25
|
|
|
23
26
|
export default function TypeaheadShowcase() {
|
|
27
|
+
const [value, setValue] = useState<SearchableItem | null>(null);
|
|
24
28
|
return (
|
|
25
29
|
<div style={{width: 320}}>
|
|
26
30
|
<Typeahead
|
|
27
31
|
label="Fruit"
|
|
28
32
|
placeholder="Search fruits..."
|
|
29
33
|
searchSource={fruitSource}
|
|
30
|
-
value={
|
|
31
|
-
onChange={
|
|
34
|
+
value={value}
|
|
35
|
+
onChange={setValue}
|
|
32
36
|
/>
|
|
33
37
|
</div>
|
|
34
38
|
);
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {Fragment, useState, useMemo, useEffect} from 'react';
|
|
6
|
+
import {AppShell} from '@astryxdesign/core/AppShell';
|
|
7
|
+
import {Layout, LayoutHeader, LayoutContent} from '@astryxdesign/core/Layout';
|
|
8
|
+
import {TopNav} from '@astryxdesign/core/TopNav';
|
|
9
|
+
import {DropdownMenu, DropdownMenuItem} from '@astryxdesign/core/DropdownMenu';
|
|
10
|
+
import {CommandPalette} from '@astryxdesign/core/CommandPalette';
|
|
11
|
+
import {createStaticSource} from '@astryxdesign/core/Typeahead';
|
|
12
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
13
|
+
import {Kbd} from '@astryxdesign/core/Kbd';
|
|
14
|
+
import {SideNav} from '@astryxdesign/core/SideNav';
|
|
15
|
+
import {TreeList} from '@astryxdesign/core/TreeList';
|
|
16
|
+
import type {TreeListItemData} from '@astryxdesign/core/TreeList';
|
|
17
|
+
import {Icon} from '@astryxdesign/core/Icon';
|
|
18
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
19
|
+
import {IconButton} from '@astryxdesign/core/IconButton';
|
|
20
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
21
|
+
import {TextInput} from '@astryxdesign/core/TextInput';
|
|
22
|
+
import {Card} from '@astryxdesign/core/Card';
|
|
23
|
+
import {Stack, VStack, HStack} from '@astryxdesign/core/Stack';
|
|
24
|
+
import {
|
|
25
|
+
PlayIcon,
|
|
26
|
+
MagnifyingGlassIcon,
|
|
27
|
+
FolderIcon,
|
|
28
|
+
DocumentTextIcon,
|
|
29
|
+
} from '@heroicons/react/24/outline';
|
|
30
|
+
|
|
31
|
+
const noop = () => {};
|
|
32
|
+
|
|
33
|
+
const folder = (
|
|
34
|
+
id: string,
|
|
35
|
+
children: TreeListItemData[],
|
|
36
|
+
isExpanded = true,
|
|
37
|
+
): TreeListItemData => ({
|
|
38
|
+
id,
|
|
39
|
+
label: <Text maxLines={1}>{id}</Text>,
|
|
40
|
+
startContent: <Icon icon={FolderIcon} size="xsm" />,
|
|
41
|
+
isExpanded,
|
|
42
|
+
children,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const file = (id: string, isSelected = false): TreeListItemData => ({
|
|
46
|
+
id,
|
|
47
|
+
label: <Text maxLines={1}>{id}</Text>,
|
|
48
|
+
startContent: <Icon icon={DocumentTextIcon} size="xsm" />,
|
|
49
|
+
isSelected,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const FILE_TREE: TreeListItemData[] = [
|
|
53
|
+
folder('src', [
|
|
54
|
+
folder('components', [
|
|
55
|
+
file('AppShell.tsx', true),
|
|
56
|
+
file('TopNav.tsx'),
|
|
57
|
+
file('SideNav.tsx'),
|
|
58
|
+
]),
|
|
59
|
+
folder('hooks', [file('useTheme.ts'), file('useResizable.ts')]),
|
|
60
|
+
file('index.tsx'),
|
|
61
|
+
file('App.tsx'),
|
|
62
|
+
]),
|
|
63
|
+
folder('public', [file('favicon.ico'), file('robots.txt')], false),
|
|
64
|
+
file('package.json'),
|
|
65
|
+
file('tsconfig.json'),
|
|
66
|
+
file('README.md'),
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// Each menu is split into groups; groups are separated by a divider.
|
|
70
|
+
// `[label, shortcut]` — the shortcut renders as a single combined Kbd
|
|
71
|
+
// (e.g. ⌘N); an empty shortcut renders no Kbd.
|
|
72
|
+
type MenuEntry = [label: string, shortcut: string];
|
|
73
|
+
|
|
74
|
+
const MENU_WIDTH = 280;
|
|
75
|
+
|
|
76
|
+
const MENUS: {label: string; groups: MenuEntry[][]}[] = [
|
|
77
|
+
{
|
|
78
|
+
label: 'File',
|
|
79
|
+
groups: [
|
|
80
|
+
[
|
|
81
|
+
['New File', '⌘N'],
|
|
82
|
+
['New Window', '⇧⌘N'],
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
['Open...', '⌘O'],
|
|
86
|
+
['Save', '⌘S'],
|
|
87
|
+
['Save As...', '⇧⌘S'],
|
|
88
|
+
],
|
|
89
|
+
[['Close Editor', '⌘W']],
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: 'Edit',
|
|
94
|
+
groups: [
|
|
95
|
+
[
|
|
96
|
+
['Undo', '⌘Z'],
|
|
97
|
+
['Redo', '⇧⌘Z'],
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
['Cut', '⌘X'],
|
|
101
|
+
['Copy', '⌘C'],
|
|
102
|
+
['Paste', '⌘V'],
|
|
103
|
+
],
|
|
104
|
+
[['Find', '⌘F']],
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
label: 'View',
|
|
109
|
+
groups: [
|
|
110
|
+
[['Command Palette', '⇧⌘P']],
|
|
111
|
+
[
|
|
112
|
+
['Explorer', '⇧⌘E'],
|
|
113
|
+
['Search', '⇧⌘F'],
|
|
114
|
+
],
|
|
115
|
+
[
|
|
116
|
+
['Toggle Terminal', '⌃`'],
|
|
117
|
+
['Zen Mode', '⌘K'],
|
|
118
|
+
],
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
label: 'Window',
|
|
123
|
+
groups: [
|
|
124
|
+
[
|
|
125
|
+
['Minimize', '⌘M'],
|
|
126
|
+
['Zoom', ''],
|
|
127
|
+
],
|
|
128
|
+
[
|
|
129
|
+
['Next Tab', '⌃⇥'],
|
|
130
|
+
['Previous Tab', '⌃⇧⇥'],
|
|
131
|
+
],
|
|
132
|
+
[['Bring All to Front', '']],
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: 'Help',
|
|
137
|
+
groups: [
|
|
138
|
+
[
|
|
139
|
+
['Documentation', ''],
|
|
140
|
+
['Release Notes', ''],
|
|
141
|
+
['Report Issue', ''],
|
|
142
|
+
['About', ''],
|
|
143
|
+
],
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
const CODE_LINES = [
|
|
149
|
+
'38%',
|
|
150
|
+
'62%',
|
|
151
|
+
'54%',
|
|
152
|
+
'0%',
|
|
153
|
+
'46%',
|
|
154
|
+
'70%',
|
|
155
|
+
'58%',
|
|
156
|
+
'34%',
|
|
157
|
+
'0%',
|
|
158
|
+
'50%',
|
|
159
|
+
'66%',
|
|
160
|
+
'42%',
|
|
161
|
+
'60%',
|
|
162
|
+
'28%',
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
const EDITOR_TABS = ['AppShell.tsx', 'TopNav.tsx', 'theme.ts'];
|
|
166
|
+
|
|
167
|
+
const COMMANDS = [
|
|
168
|
+
{id: 'new-file', label: 'New File'},
|
|
169
|
+
{id: 'open-file', label: 'Open File…'},
|
|
170
|
+
{id: 'save-all', label: 'Save All'},
|
|
171
|
+
{id: 'find-in-files', label: 'Find in Files'},
|
|
172
|
+
{id: 'toggle-terminal', label: 'Toggle Terminal'},
|
|
173
|
+
{id: 'go-to-symbol', label: 'Go to Symbol…'},
|
|
174
|
+
{id: 'appshell', label: 'AppShell.tsx'},
|
|
175
|
+
{id: 'topnav', label: 'TopNav.tsx'},
|
|
176
|
+
{id: 'sidenav', label: 'SideNav.tsx'},
|
|
177
|
+
{id: 'use-theme', label: 'useTheme.ts'},
|
|
178
|
+
{id: 'theme', label: 'theme.ts'},
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
export default function ShellNav() {
|
|
182
|
+
const [isPaletteOpen, setIsPaletteOpen] = useState(false);
|
|
183
|
+
const searchSource = useMemo(() => createStaticSource(COMMANDS), []);
|
|
184
|
+
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
187
|
+
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
|
|
188
|
+
e.preventDefault();
|
|
189
|
+
setIsPaletteOpen(true);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
193
|
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
194
|
+
}, []);
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<>
|
|
198
|
+
<AppShell
|
|
199
|
+
contentPadding={0}
|
|
200
|
+
topNav={
|
|
201
|
+
<TopNav
|
|
202
|
+
label="Astryx Studio menu bar"
|
|
203
|
+
startContent={
|
|
204
|
+
<>
|
|
205
|
+
{MENUS.map(menu => (
|
|
206
|
+
<DropdownMenu
|
|
207
|
+
key={menu.label}
|
|
208
|
+
button={{label: menu.label, variant: 'ghost', size: 'sm'}}
|
|
209
|
+
hasChevron={false}
|
|
210
|
+
menuWidth={MENU_WIDTH}>
|
|
211
|
+
{menu.groups.map((group, gi) => (
|
|
212
|
+
<Fragment key={gi}>
|
|
213
|
+
{gi > 0 && <Divider />}
|
|
214
|
+
{group.map(([label, shortcut]) => (
|
|
215
|
+
<DropdownMenuItem
|
|
216
|
+
key={label}
|
|
217
|
+
label={label}
|
|
218
|
+
onClick={noop}
|
|
219
|
+
endContent={
|
|
220
|
+
shortcut ? <Kbd keys={shortcut} /> : undefined
|
|
221
|
+
}
|
|
222
|
+
/>
|
|
223
|
+
))}
|
|
224
|
+
</Fragment>
|
|
225
|
+
))}
|
|
226
|
+
</DropdownMenu>
|
|
227
|
+
))}
|
|
228
|
+
</>
|
|
229
|
+
}
|
|
230
|
+
endContent={
|
|
231
|
+
<>
|
|
232
|
+
<Stack onClick={() => setIsPaletteOpen(true)}>
|
|
233
|
+
<TextInput
|
|
234
|
+
label="Search files and commands"
|
|
235
|
+
isLabelHidden
|
|
236
|
+
size="sm"
|
|
237
|
+
width={240}
|
|
238
|
+
startIcon={MagnifyingGlassIcon}
|
|
239
|
+
placeholder="Search files and commands…"
|
|
240
|
+
value=""
|
|
241
|
+
onChange={() => {}}
|
|
242
|
+
/>
|
|
243
|
+
</Stack>
|
|
244
|
+
<IconButton
|
|
245
|
+
label="Run project"
|
|
246
|
+
tooltip="Run"
|
|
247
|
+
variant="ghost"
|
|
248
|
+
icon={<Icon icon={PlayIcon} size="sm" />}
|
|
249
|
+
/>
|
|
250
|
+
<Button label="Share" variant="secondary" />
|
|
251
|
+
</>
|
|
252
|
+
}
|
|
253
|
+
/>
|
|
254
|
+
}
|
|
255
|
+
sideNav={
|
|
256
|
+
<SideNav
|
|
257
|
+
resizable={{defaultWidth: 240, minWidth: 180, maxWidth: 400}}>
|
|
258
|
+
<TreeList items={FILE_TREE} density="compact" />
|
|
259
|
+
</SideNav>
|
|
260
|
+
}>
|
|
261
|
+
<Layout
|
|
262
|
+
height="fill"
|
|
263
|
+
header={
|
|
264
|
+
<LayoutHeader hasDivider padding={6}>
|
|
265
|
+
<HStack gap={2}>
|
|
266
|
+
{EDITOR_TABS.map(tab => (
|
|
267
|
+
<Card
|
|
268
|
+
key={tab}
|
|
269
|
+
variant="muted"
|
|
270
|
+
padding={0}
|
|
271
|
+
width={132}
|
|
272
|
+
height={36}
|
|
273
|
+
/>
|
|
274
|
+
))}
|
|
275
|
+
</HStack>
|
|
276
|
+
</LayoutHeader>
|
|
277
|
+
}
|
|
278
|
+
content={
|
|
279
|
+
<LayoutContent padding={6}>
|
|
280
|
+
<VStack gap={2}>
|
|
281
|
+
{CODE_LINES.map((width, i) =>
|
|
282
|
+
width === '0%' ? (
|
|
283
|
+
<Card
|
|
284
|
+
key={i}
|
|
285
|
+
variant="muted"
|
|
286
|
+
padding={0}
|
|
287
|
+
width={1}
|
|
288
|
+
height={14}
|
|
289
|
+
/>
|
|
290
|
+
) : (
|
|
291
|
+
<HStack key={i} gap={3} vAlign="center">
|
|
292
|
+
<Card
|
|
293
|
+
variant="muted"
|
|
294
|
+
padding={0}
|
|
295
|
+
width={20}
|
|
296
|
+
height={14}
|
|
297
|
+
/>
|
|
298
|
+
<Card
|
|
299
|
+
variant="muted"
|
|
300
|
+
padding={0}
|
|
301
|
+
width={width}
|
|
302
|
+
height={14}
|
|
303
|
+
/>
|
|
304
|
+
</HStack>
|
|
305
|
+
),
|
|
306
|
+
)}
|
|
307
|
+
</VStack>
|
|
308
|
+
</LayoutContent>
|
|
309
|
+
}
|
|
310
|
+
/>
|
|
311
|
+
</AppShell>
|
|
312
|
+
<CommandPalette
|
|
313
|
+
isOpen={isPaletteOpen}
|
|
314
|
+
onOpenChange={setIsPaletteOpen}
|
|
315
|
+
searchSource={searchSource}
|
|
316
|
+
label="Search files and commands"
|
|
317
|
+
onValueChange={() => setIsPaletteOpen(false)}
|
|
318
|
+
/>
|
|
319
|
+
</>
|
|
320
|
+
);
|
|
321
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../../../../core/src/docs-types').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'page',
|
|
6
|
+
name: 'Shell Nav',
|
|
7
|
+
displayName: 'Shell Nav',
|
|
8
|
+
description:
|
|
9
|
+
'A top + side nav app shell with a File/Edit/View/Window/Help menu bar plus command-palette search, a resizable file-tree SideNav, and a static grey-card tabbed code editor.',
|
|
10
|
+
isReady: true,
|
|
11
|
+
category: 'Shell - Top Nav + Left Sidebar',
|
|
12
|
+
};
|