@astryxdesign/cli 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -1
- package/README.md +49 -55
- package/docs/layout.doc.dense.mjs +90 -0
- package/docs/layout.doc.mjs +160 -0
- package/docs/principles.doc.dense.mjs +2 -2
- package/docs/principles.doc.mjs +4 -0
- package/docs/principles.doc.zh.mjs +2 -2
- package/docs/theme.doc.mjs +2 -2
- package/package.json +13 -1
- package/src/api/blog.mjs +192 -0
- package/src/api/blog.test.mjs +144 -0
- package/src/api/component.mjs +253 -12
- package/src/api/discover.mjs +14 -7
- package/src/api/doctor.mjs +10 -25
- package/src/api/index.mjs +1 -0
- package/src/api/layout.mjs +11 -10
- package/src/api/layout.test.mjs +4 -1
- package/src/api/template-integration.test.mjs +225 -0
- package/src/api/template.mjs +242 -84
- package/src/api/validate-integration.mjs +370 -0
- package/src/api/validate-integration.test.mjs +222 -0
- package/src/codemod.mjs +93 -0
- package/src/codemod.test.mjs +134 -0
- package/src/codemods/__tests__/registry.test.mjs +1 -0
- package/src/codemods/__tests__/runner.test.mjs +103 -0
- package/src/codemods/integration-discovery.mjs +168 -0
- package/src/codemods/integration-discovery.test.mjs +234 -0
- package/src/codemods/integration-runner.mjs +109 -0
- package/src/codemods/registry.mjs +1 -0
- package/src/codemods/run-codemod.mjs +207 -0
- package/src/codemods/runner.mjs +73 -96
- package/src/codemods/transforms/v0.0.15/index.mjs +0 -13
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +67 -0
- package/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +61 -0
- package/src/codemods/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +104 -0
- package/src/codemods/transforms/{v0.0.15 → v0.1.0}/drop-xds-prefix-imports.mjs +15 -4
- package/src/codemods/transforms/v0.1.0/index.mjs +43 -6
- package/src/codemods/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +77 -0
- package/src/codemods/transforms/v0.1.0/migrate-xds-declare-module.mjs +78 -0
- package/src/codemods/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +360 -0
- package/src/codemods/transforms/v0.1.3/index.mjs +19 -0
- package/src/codemods/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +260 -0
- package/src/commands/agent-docs.mjs +4 -1
- package/src/commands/blog.mjs +60 -0
- package/src/commands/build-theme.import-path.test.mjs +2 -12
- package/src/commands/build-theme.mjs +117 -0
- package/src/commands/build-theme.prose.test.mjs +5 -15
- package/src/commands/build-theme.watch.test.mjs +149 -0
- package/src/commands/component/index.mjs +44 -10
- package/src/commands/component-ownership.test.mjs +227 -0
- package/src/commands/discover.mjs +5 -16
- package/src/commands/doctor.test.mjs +3 -3
- package/src/commands/ensure-core-built.mjs +120 -0
- package/src/commands/json-contract.test.mjs +0 -32
- package/src/commands/swizzle.mjs +224 -235
- package/src/commands/swizzle.path-safety.test.mjs +3 -3
- package/src/commands/swizzle.routing.test.mjs +279 -0
- package/src/commands/template.mjs +33 -37
- package/src/commands/upgrade.config-ordering.test.mjs +273 -0
- package/src/commands/upgrade.integration-policy.test.mjs +204 -0
- package/src/commands/upgrade.mjs +349 -170
- package/src/commands/validate-integration.mjs +110 -0
- package/src/commands/validate-integration.test.mjs +124 -0
- package/src/config.mjs +7 -20
- package/src/config.test.mjs +89 -13
- package/src/index.mjs +8 -3
- package/src/integration.mjs +19 -0
- package/src/lib/component-discovery.mjs +177 -0
- package/src/lib/config-cache.mjs +91 -0
- package/src/lib/config-cache.test.mjs +83 -0
- package/src/lib/config-schema.mjs +41 -55
- package/src/lib/error-codes.mjs +15 -12
- package/src/lib/integration-warnings.mjs +62 -0
- package/src/lib/integration-warnings.test.mjs +102 -0
- package/src/lib/integrations.mjs +92 -115
- package/src/lib/integrations.test.mjs +88 -107
- package/src/lib/manifest.mjs +5 -2
- package/src/lib/module-loader.mjs +80 -0
- package/src/lib/module-loader.test.mjs +106 -0
- package/src/lib/project.mjs +502 -0
- package/src/lib/project.test.mjs +308 -0
- package/src/lib/site.mjs +20 -0
- package/src/template.mjs +73 -0
- package/src/template.test.mjs +127 -0
- package/src/types/api.d.ts +2 -6
- package/src/types/base.d.ts +3 -9
- package/src/types/codemod.d.ts +81 -0
- package/src/types/component.d.ts +27 -2
- package/src/types/config.d.ts +56 -85
- package/src/types/error-codes.d.ts +5 -3
- package/src/types/index.d.ts +0 -1
- package/src/types/integration.d.ts +29 -0
- package/src/types/swizzle.d.ts +9 -2
- package/src/types/template-api.d.ts +54 -0
- package/src/types/template.d.ts +10 -7
- package/src/types/upgrade.d.ts +29 -0
- package/src/types/validate-integration.d.ts +24 -0
- package/src/utils/github.mjs +0 -237
- package/src/utils/interactive.mjs +2 -2
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.doc.mjs +14 -0
- package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +28 -0
- package/templates/blocks/components/Blockquote/BlockquoteTestimonials.doc.mjs +14 -0
- package/templates/blocks/components/Blockquote/BlockquoteTestimonials.tsx +34 -0
- package/templates/blocks/components/Blockquote/BlockquoteWithCite.doc.mjs +14 -0
- package/templates/blocks/components/Blockquote/BlockquoteWithCite.tsx +21 -0
- package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/BreadcrumbItem/BreadcrumbItemBasic.tsx +15 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.doc.mjs +14 -0
- package/templates/blocks/components/ButtonGroup/ButtonGroupBasic.tsx +16 -0
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.doc.mjs +19 -0
- package/templates/blocks/components/ChatDictationButton/ChatDictationButtonBasic.tsx +34 -0
- package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/CheckboxListItem/CheckboxListItemBasic.tsx +30 -0
- package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.doc.mjs +14 -0
- package/templates/blocks/components/CollapsibleGroup/CollapsibleGroupAccordion.tsx +31 -0
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.doc.mjs +14 -0
- package/templates/blocks/components/CommandPaletteEmpty/CommandPaletteEmptyBasic.tsx +26 -0
- package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.doc.mjs +14 -0
- package/templates/blocks/components/CommandPaletteFooter/CommandPaletteFooterBasic.tsx +32 -0
- package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.doc.mjs +18 -0
- package/templates/blocks/components/CommandPaletteGroup/CommandPaletteGroupBasic.tsx +32 -0
- package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/CommandPaletteItem/CommandPaletteItemBasic.tsx +27 -0
- package/templates/blocks/components/ContextMenu/ContextMenuBasic.doc.mjs +14 -0
- package/templates/blocks/components/ContextMenu/ContextMenuBasic.tsx +32 -0
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.doc.mjs +14 -0
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithPresets.tsx +46 -0
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.doc.mjs +14 -0
- package/templates/blocks/components/DateRangeInput/DateRangeInputWithValidation.tsx +52 -0
- package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.doc.mjs +14 -0
- package/templates/blocks/components/DateTimeInput/DateTimeInputWithValidation.tsx +43 -0
- package/templates/blocks/components/DialogHeader/DialogHeaderBasic.doc.mjs +14 -0
- package/templates/blocks/components/DialogHeader/DialogHeaderBasic.tsx +30 -0
- package/templates/blocks/components/DropdownMenu/DropdownMenuShowcase.tsx +0 -6
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemBasic.tsx +27 -0
- package/templates/blocks/components/DropdownMenuItem/DropdownMenuItemShowcase.tsx +1 -5
- package/templates/blocks/components/FieldLabel/FieldLabelBasic.doc.mjs +14 -0
- package/templates/blocks/components/FieldLabel/FieldLabelBasic.tsx +20 -0
- package/templates/blocks/components/FieldStatus/FieldStatusBasic.doc.mjs +14 -0
- package/templates/blocks/components/FieldStatus/FieldStatusBasic.tsx +23 -0
- package/templates/blocks/components/FileInput/FileInputBasic.doc.mjs +14 -0
- package/templates/blocks/components/FileInput/FileInputBasic.tsx +22 -0
- package/templates/blocks/components/GridSpan/GridSpanColumns.doc.mjs +14 -0
- package/templates/blocks/components/GridSpan/GridSpanColumns.tsx +38 -0
- package/templates/blocks/components/HStack/HStackBasic.doc.mjs +14 -0
- package/templates/blocks/components/HStack/HStackBasic.tsx +16 -0
- package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.doc.mjs +14 -0
- package/templates/blocks/components/Hooks/useKeyboardHintHookUsage.tsx +57 -0
- package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.doc.mjs +1 -1
- package/templates/blocks/components/HoverCard/HoverCardInteractiveContent.tsx +9 -4
- package/templates/blocks/components/InputGroup/InputGroupBasic.doc.mjs +14 -0
- package/templates/blocks/components/InputGroup/InputGroupBasic.tsx +27 -0
- package/templates/blocks/components/LayoutContent/LayoutContentBasic.doc.mjs +23 -0
- package/templates/blocks/components/LayoutContent/LayoutContentBasic.tsx +40 -0
- package/templates/blocks/components/LayoutFooter/LayoutFooterActions.doc.mjs +22 -0
- package/templates/blocks/components/LayoutFooter/LayoutFooterActions.tsx +41 -0
- package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.doc.mjs +23 -0
- package/templates/blocks/components/LayoutHeader/LayoutHeaderWithActions.tsx +40 -0
- package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.doc.mjs +22 -0
- package/templates/blocks/components/LayoutPanel/LayoutPanelNavigation.tsx +37 -0
- package/templates/blocks/components/Lightbox/LightboxGallery.doc.mjs +14 -0
- package/templates/blocks/components/Lightbox/LightboxGallery.tsx +53 -0
- package/templates/blocks/components/Lightbox/LightboxShowcase.tsx +4 -3
- package/templates/blocks/components/Lightbox/LightboxVideo.doc.mjs +14 -0
- package/templates/blocks/components/Lightbox/LightboxVideo.tsx +27 -0
- package/templates/blocks/components/Lightbox/LightboxZoom.doc.mjs +14 -0
- package/templates/blocks/components/Lightbox/LightboxZoom.tsx +33 -0
- package/templates/blocks/components/LinkProvider/LinkProviderCustomLink.doc.mjs +1 -1
- package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/MetadataListItem/MetadataListItemBasic.tsx +19 -0
- package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.doc.mjs +23 -0
- package/templates/blocks/components/MobileNavToggle/MobileNavToggleBasic.tsx +42 -0
- package/templates/blocks/components/MoreMenu/MoreMenuShowcase.tsx +0 -6
- package/templates/blocks/components/NavIcon/NavIconBasic.doc.mjs +14 -0
- package/templates/blocks/components/NavIcon/NavIconBasic.tsx +16 -0
- package/templates/blocks/components/RadioListItem/RadioListItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/RadioListItem/RadioListItemBasic.tsx +30 -0
- package/templates/blocks/components/Resizable/ResizableSidebar.doc.mjs +25 -0
- package/templates/blocks/components/Resizable/ResizableSidebar.tsx +67 -0
- package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/SegmentedControlItem/SegmentedControlItemBasic.tsx +21 -0
- package/templates/blocks/components/SelectorOption/SelectorOptionBasic.doc.mjs +14 -0
- package/templates/blocks/components/SelectorOption/SelectorOptionBasic.tsx +39 -0
- package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.doc.mjs +14 -0
- package/templates/blocks/components/SideNavCollapseButton/SideNavCollapseButtonBasic.tsx +55 -0
- package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.doc.mjs +14 -0
- package/templates/blocks/components/SideNavHeading/SideNavHeadingBasic.tsx +38 -0
- package/templates/blocks/components/SideNavItem/SideNavItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/SideNavItem/SideNavItemBasic.tsx +49 -0
- package/templates/blocks/components/SideNavSection/SideNavSectionBasic.doc.mjs +14 -0
- package/templates/blocks/components/SideNavSection/SideNavSectionBasic.tsx +71 -0
- package/templates/blocks/components/StackItem/StackItemFill.doc.mjs +14 -0
- package/templates/blocks/components/StackItem/StackItemFill.tsx +28 -0
- package/templates/blocks/components/Tab/TabWithSelectedIcon.doc.mjs +13 -0
- package/templates/blocks/components/Tab/TabWithSelectedIcon.tsx +39 -0
- package/templates/blocks/components/TabMenu/TabMenuBasic.doc.mjs +14 -0
- package/templates/blocks/components/TabMenu/TabMenuBasic.tsx +23 -0
- package/templates/blocks/components/Table/StickyColumnsHookUsage.doc.mjs +1 -1
- package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.doc.mjs +14 -0
- package/templates/blocks/components/ToggleButtonGroup/ToggleButtonGroupVertical.tsx +47 -0
- package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.doc.mjs +14 -0
- package/templates/blocks/components/TopNavHeading/TopNavHeadingBasic.tsx +22 -0
- package/templates/blocks/components/TopNavItem/TopNavItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/TopNavItem/TopNavItemBasic.tsx +21 -0
- package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.doc.mjs +20 -0
- package/templates/blocks/components/TopNavMegaMenu/TopNavMegaMenuBasic.tsx +46 -0
- package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.doc.mjs +14 -0
- package/templates/blocks/components/TopNavMegaMenuFeaturedCard/TopNavMegaMenuFeaturedCardBasic.tsx +16 -0
- package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/TopNavMegaMenuItem/TopNavMegaMenuItemBasic.tsx +26 -0
- package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.doc.mjs +14 -0
- package/templates/blocks/components/TopNavMenu/TopNavMenuBasic.tsx +43 -0
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.doc.mjs +14 -0
- package/templates/blocks/components/TypeaheadItem/TypeaheadItemBasic.tsx +43 -0
- package/templates/blocks/components/VStack/VStackBasic.doc.mjs +14 -0
- package/templates/blocks/components/VStack/VStackBasic.tsx +20 -0
- package/templates/pages/kanban-board/page.tsx +729 -0
- package/templates/pages/kanban-board/template.doc.mjs +12 -0
- 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 +241 -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/src/codemods/transforms/v0.1.0/__tests__/migrate-xds-config-surfaces.test.mjs +0 -116
- package/src/codemods/transforms/v0.1.0/migrate-xds-config-surfaces.mjs +0 -230
- package/src/commands/gap-report.mjs +0 -464
- package/src/commands/gap-report.test.mjs +0 -168
- package/src/commands/swizzle-gap-safety.test.mjs +0 -273
- package/src/lib/config.mjs +0 -113
- package/src/lib/config.test.mjs +0 -91
- package/src/types/gap-report.d.ts +0 -29
- package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.doc.mjs +0 -14
- package/templates/blocks/components/TreeListBranches/TreeListBranchesShowcase.tsx +0 -64
- package/templates/blocks/components/TreeListItem/TreeListItemShowcase.doc.mjs +0 -14
- package/templates/blocks/components/TreeListItem/TreeListItemShowcase.tsx +0 -60
- /package/src/codemods/transforms/{v0.0.15 → v0.1.0}/__tests__/drop-xds-prefix-imports.test.mjs +0 -0
|
@@ -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: 'Kanban Board',
|
|
7
|
+
displayName: 'Kanban Board',
|
|
8
|
+
description:
|
|
9
|
+
'Task board with color-coded status columns, draggable task cards, priority tags, and metadata',
|
|
10
|
+
isReady: true,
|
|
11
|
+
category: 'Tools - Kanban Board',
|
|
12
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
import {useState} from 'react';
|
|
6
|
+
import {AppShell} from '@astryxdesign/core/AppShell';
|
|
7
|
+
import {Divider} from '@astryxdesign/core/Divider';
|
|
8
|
+
import {Layout, LayoutContent, LayoutFooter} from '@astryxdesign/core/Layout';
|
|
9
|
+
import {
|
|
10
|
+
SideNav,
|
|
11
|
+
SideNavHeading,
|
|
12
|
+
SideNavItem,
|
|
13
|
+
SideNavSection,
|
|
14
|
+
} from '@astryxdesign/core/SideNav';
|
|
15
|
+
import {NavIcon} from '@astryxdesign/core/NavIcon';
|
|
16
|
+
import {Icon} from '@astryxdesign/core/Icon';
|
|
17
|
+
import type {IconType} from '@astryxdesign/core/Icon';
|
|
18
|
+
import {MoreMenu} from '@astryxdesign/core/MoreMenu';
|
|
19
|
+
import {StatusDot} from '@astryxdesign/core/StatusDot';
|
|
20
|
+
import type {StatusDotVariant} from '@astryxdesign/core/StatusDot';
|
|
21
|
+
import {Card} from '@astryxdesign/core/Card';
|
|
22
|
+
import {Stack, VStack, HStack} from '@astryxdesign/core/Stack';
|
|
23
|
+
import {
|
|
24
|
+
SparklesIcon,
|
|
25
|
+
PlusIcon,
|
|
26
|
+
MagnifyingGlassIcon,
|
|
27
|
+
BookOpenIcon,
|
|
28
|
+
Cog6ToothIcon,
|
|
29
|
+
UserCircleIcon,
|
|
30
|
+
UserIcon,
|
|
31
|
+
BuildingOffice2Icon,
|
|
32
|
+
CodeBracketIcon,
|
|
33
|
+
} from '@heroicons/react/24/outline';
|
|
34
|
+
|
|
35
|
+
type Conversation = {
|
|
36
|
+
label: string;
|
|
37
|
+
status: StatusDotVariant;
|
|
38
|
+
statusLabel: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type Workspace = {
|
|
42
|
+
name: string;
|
|
43
|
+
icon: IconType;
|
|
44
|
+
chats: Conversation[];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const WORKSPACES: Workspace[] = [
|
|
48
|
+
{
|
|
49
|
+
name: 'Personal',
|
|
50
|
+
icon: UserIcon,
|
|
51
|
+
chats: [
|
|
52
|
+
{
|
|
53
|
+
label: 'Weekend trip planning',
|
|
54
|
+
status: 'success',
|
|
55
|
+
statusLabel: 'Active',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: 'Recipe ideas for the week',
|
|
59
|
+
status: 'neutral',
|
|
60
|
+
statusLabel: 'Idle',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: 'Book recommendations',
|
|
64
|
+
status: 'warning',
|
|
65
|
+
statusLabel: 'Needs review',
|
|
66
|
+
},
|
|
67
|
+
{label: 'Home workout plan', status: 'neutral', statusLabel: 'Idle'},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Acme Corp',
|
|
72
|
+
icon: BuildingOffice2Icon,
|
|
73
|
+
chats: [
|
|
74
|
+
{label: 'Q3 roadmap draft', status: 'accent', statusLabel: 'In progress'},
|
|
75
|
+
{
|
|
76
|
+
label: 'Customer onboarding flow',
|
|
77
|
+
status: 'success',
|
|
78
|
+
statusLabel: 'Active',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
label: 'Pricing strategy review',
|
|
82
|
+
status: 'warning',
|
|
83
|
+
statusLabel: 'Needs review',
|
|
84
|
+
},
|
|
85
|
+
{label: 'Standup summary', status: 'neutral', statusLabel: 'Idle'},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'Open Source',
|
|
90
|
+
icon: CodeBracketIcon,
|
|
91
|
+
chats: [
|
|
92
|
+
{
|
|
93
|
+
label: 'StyleX migration notes',
|
|
94
|
+
status: 'accent',
|
|
95
|
+
statusLabel: 'In progress',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
label: 'Skeleton loading states',
|
|
99
|
+
status: 'success',
|
|
100
|
+
statusLabel: 'Active',
|
|
101
|
+
},
|
|
102
|
+
{label: 'Accessibility audit', status: 'error', statusLabel: 'Blocked'},
|
|
103
|
+
{label: 'Release notes v4.0', status: 'neutral', statusLabel: 'Idle'},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const SELECTED_CHAT = 'StyleX migration notes';
|
|
109
|
+
|
|
110
|
+
const MESSAGES = [
|
|
111
|
+
{role: 'assistant', width: '78%', height: 104},
|
|
112
|
+
{role: 'user', width: '48%', height: 48},
|
|
113
|
+
{role: 'assistant', width: '64%', height: 132},
|
|
114
|
+
{role: 'user', width: '38%', height: 40},
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
function ConversationItem({
|
|
118
|
+
label,
|
|
119
|
+
status,
|
|
120
|
+
statusLabel,
|
|
121
|
+
isSelected,
|
|
122
|
+
}: {
|
|
123
|
+
label: string;
|
|
124
|
+
status: StatusDotVariant;
|
|
125
|
+
statusLabel: string;
|
|
126
|
+
isSelected?: boolean;
|
|
127
|
+
}) {
|
|
128
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
129
|
+
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
130
|
+
const showMenu = isHovered || isMenuOpen;
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<Stack
|
|
134
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
135
|
+
onMouseLeave={() => setIsHovered(false)}>
|
|
136
|
+
<SideNavItem
|
|
137
|
+
label={label}
|
|
138
|
+
href="#"
|
|
139
|
+
isSelected={isSelected}
|
|
140
|
+
endContent={
|
|
141
|
+
showMenu ? (
|
|
142
|
+
<MoreMenu
|
|
143
|
+
size="sm"
|
|
144
|
+
label="Conversation options"
|
|
145
|
+
onOpenChange={setIsMenuOpen}
|
|
146
|
+
items={[
|
|
147
|
+
{label: 'Pin', onClick: () => {}},
|
|
148
|
+
{label: 'Rename', onClick: () => {}},
|
|
149
|
+
{label: 'Archive', onClick: () => {}},
|
|
150
|
+
{label: 'Delete', onClick: () => {}},
|
|
151
|
+
]}
|
|
152
|
+
/>
|
|
153
|
+
) : (
|
|
154
|
+
<StatusDot variant={status} label={statusLabel} />
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
/>
|
|
158
|
+
</Stack>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export default function ShellSideNav() {
|
|
163
|
+
return (
|
|
164
|
+
<AppShell
|
|
165
|
+
contentPadding={0}
|
|
166
|
+
sideNav={
|
|
167
|
+
<SideNav
|
|
168
|
+
collapsible
|
|
169
|
+
resizable={{defaultWidth: 300, minWidth: 220, maxWidth: 420}}
|
|
170
|
+
header={
|
|
171
|
+
<SideNavHeading
|
|
172
|
+
heading="AI Assistant"
|
|
173
|
+
icon={<NavIcon icon={<Icon icon={SparklesIcon} size="sm" />} />}
|
|
174
|
+
headingHref="#"
|
|
175
|
+
/>
|
|
176
|
+
}
|
|
177
|
+
footer={
|
|
178
|
+
<SideNavSection title="Account" isHeaderHidden>
|
|
179
|
+
<SideNavItem label="Settings" icon={Cog6ToothIcon} href="#" />
|
|
180
|
+
<SideNavItem label="Sarah Chen" icon={UserCircleIcon} href="#" />
|
|
181
|
+
</SideNavSection>
|
|
182
|
+
}>
|
|
183
|
+
<SideNavSection title="Menu" isHeaderHidden>
|
|
184
|
+
<SideNavItem label="New chat" icon={PlusIcon} href="#" />
|
|
185
|
+
<SideNavItem label="Search" icon={MagnifyingGlassIcon} href="#" />
|
|
186
|
+
<SideNavItem label="Library" icon={BookOpenIcon} href="#" />
|
|
187
|
+
</SideNavSection>
|
|
188
|
+
<Divider />
|
|
189
|
+
<SideNavSection title="Workspaces" isHeaderHidden>
|
|
190
|
+
{WORKSPACES.map(workspace => (
|
|
191
|
+
<SideNavItem
|
|
192
|
+
key={workspace.name}
|
|
193
|
+
label={workspace.name}
|
|
194
|
+
icon={workspace.icon}
|
|
195
|
+
collapsible={{defaultIsCollapsed: false}}>
|
|
196
|
+
<VStack gap={0.5}>
|
|
197
|
+
{workspace.chats.map(chat => (
|
|
198
|
+
<ConversationItem
|
|
199
|
+
key={chat.label}
|
|
200
|
+
label={chat.label}
|
|
201
|
+
status={chat.status}
|
|
202
|
+
statusLabel={chat.statusLabel}
|
|
203
|
+
isSelected={chat.label === SELECTED_CHAT}
|
|
204
|
+
/>
|
|
205
|
+
))}
|
|
206
|
+
</VStack>
|
|
207
|
+
</SideNavItem>
|
|
208
|
+
))}
|
|
209
|
+
</SideNavSection>
|
|
210
|
+
</SideNav>
|
|
211
|
+
}>
|
|
212
|
+
<Layout
|
|
213
|
+
height="fill"
|
|
214
|
+
contentWidth={768}
|
|
215
|
+
content={
|
|
216
|
+
<LayoutContent padding={6}>
|
|
217
|
+
<VStack gap={5}>
|
|
218
|
+
{MESSAGES.map((message, mi) => (
|
|
219
|
+
<HStack
|
|
220
|
+
key={mi}
|
|
221
|
+
hAlign={message.role === 'assistant' ? 'start' : 'end'}>
|
|
222
|
+
<Card
|
|
223
|
+
variant="muted"
|
|
224
|
+
padding={0}
|
|
225
|
+
width={message.width}
|
|
226
|
+
height={message.height}
|
|
227
|
+
/>
|
|
228
|
+
</HStack>
|
|
229
|
+
))}
|
|
230
|
+
</VStack>
|
|
231
|
+
</LayoutContent>
|
|
232
|
+
}
|
|
233
|
+
footer={
|
|
234
|
+
<LayoutFooter>
|
|
235
|
+
<Card variant="muted" padding={0} width="100%" height={56} />
|
|
236
|
+
</LayoutFooter>
|
|
237
|
+
}
|
|
238
|
+
/>
|
|
239
|
+
</AppShell>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
@@ -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: 'Side Nav',
|
|
7
|
+
displayName: 'Side Nav',
|
|
8
|
+
description:
|
|
9
|
+
'A side-nav app shell with a collapsible, resizable SideNav (new chat, search, library, and workspace-grouped conversations with status dots) over static grey-card conversation and composer placeholders.',
|
|
10
|
+
isReady: true,
|
|
11
|
+
category: 'Shell - Left Sidebar',
|
|
12
|
+
};
|