astryx-dracula 0.5.0 → 0.6.2
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/BRAND.md +3 -3
- package/README.md +7 -4
- package/USAGE.md +49 -49
- package/astryx-dracula.d.ts +2 -2
- package/astryx-dracula.js +25 -9
- package/astryx-dracula.variants.d.ts +2 -2
- package/astryx.integration.mjs +1 -1
- package/icons.mjs +21 -17
- package/icons.tsx +69 -62
- package/package.json +125 -120
- package/shared/auth-chrome-config.ts +6 -6
- package/shared/auth-chrome.tsx +143 -144
- package/shared/auth-copy.ts +14 -14
- package/shared/chaptered-doc-config.ts +48 -51
- package/shared/chaptered-doc.tsx +267 -289
- package/shared/chart-hues.ts +25 -10
- package/shared/chart-labels.tsx +31 -30
- package/shared/chart-legend.tsx +55 -56
- package/shared/chart-panel-style.ts +3 -3
- package/shared/data-bar.tsx +97 -102
- package/shared/format-money.ts +1 -1
- package/shared/gallery-image.ts +6 -6
- package/shared/login-demo.ts +1 -1
- package/shared/metric-card.tsx +101 -105
- package/shared/metric-delta.tsx +28 -27
- package/shared/order-desk.tsx +205 -216
- package/shared/revenue-chart.tsx +145 -165
- package/shared/scene-castle.tsx +206 -291
- package/shared/scene-frame.tsx +33 -32
- package/shared/scene-hues.ts +17 -17
- package/shared/scene-tile.tsx +88 -92
- package/shared/settings-data.ts +119 -125
- package/shared/settings-rows.tsx +122 -159
- package/shared/sparkline.tsx +75 -88
- package/shared/sso-icons.tsx +10 -22
- package/shared/stars.tsx +16 -25
- package/templates/ai-chat-landing.template.mjs +5 -4
- package/templates/ai-chat-landing.tsx +473 -460
- package/templates/ai-chat.template.mjs +5 -4
- package/templates/ai-chat.tsx +543 -612
- package/templates/blank.template.mjs +5 -4
- package/templates/blank.tsx +18 -14
- package/templates/centered-hero.template.mjs +5 -4
- package/templates/centered-hero.tsx +55 -68
- package/templates/classic-gallery.template.mjs +5 -4
- package/templates/classic-gallery.tsx +97 -104
- package/templates/contact-form.template.mjs +5 -4
- package/templates/contact-form.tsx +247 -282
- package/templates/dashboard-portfolio.template.mjs +5 -4
- package/templates/dashboard-portfolio.tsx +717 -548
- package/templates/dashboard.template.mjs +5 -4
- package/templates/dashboard.tsx +596 -567
- package/templates/detail-page.template.mjs +5 -4
- package/templates/detail-page.tsx +546 -603
- package/templates/documentation-design.template.mjs +5 -4
- package/templates/documentation-design.tsx +231 -243
- package/templates/documentation-technical.template.mjs +5 -4
- package/templates/documentation-technical.tsx +236 -239
- package/templates/documentation.template.mjs +5 -4
- package/templates/documentation.tsx +267 -279
- package/templates/editor.template.mjs +5 -4
- package/templates/editor.tsx +844 -877
- package/templates/file-explorer.template.mjs +5 -4
- package/templates/file-explorer.tsx +566 -590
- package/templates/form-two-column.template.mjs +5 -4
- package/templates/form-two-column.tsx +195 -210
- package/templates/gallery-hero.template.mjs +5 -4
- package/templates/gallery-hero.tsx +93 -114
- package/templates/ide.template.mjs +5 -4
- package/templates/ide.tsx +407 -453
- package/templates/incident-console.template.mjs +5 -4
- package/templates/incident-console.tsx +593 -575
- package/templates/kanban-board.template.mjs +5 -4
- package/templates/kanban-board.tsx +665 -683
- package/templates/library.template.mjs +5 -4
- package/templates/library.tsx +409 -430
- package/templates/login-card.template.mjs +5 -4
- package/templates/login-card.tsx +63 -72
- package/templates/login-split.template.mjs +5 -4
- package/templates/login-split.tsx +192 -193
- package/templates/login-sso.template.mjs +5 -4
- package/templates/login-sso.tsx +257 -258
- package/templates/login.template.mjs +5 -4
- package/templates/login.tsx +53 -49
- package/templates/messaging-shell.template.mjs +5 -4
- package/templates/messaging-shell.tsx +556 -574
- package/templates/mixed-gallery.template.mjs +5 -4
- package/templates/mixed-gallery.tsx +60 -58
- package/templates/payment-form.template.mjs +5 -4
- package/templates/payment-form.tsx +882 -991
- package/templates/product-detail.template.mjs +5 -4
- package/templates/product-detail.tsx +261 -272
- package/templates/product-gallery.template.mjs +5 -4
- package/templates/product-gallery.tsx +126 -137
- package/templates/product-tour.template.mjs +5 -4
- package/templates/product-tour.tsx +741 -773
- package/templates/settings-dialog.template.mjs +5 -4
- package/templates/settings-dialog.tsx +688 -717
- package/templates/settings-sidebar.template.mjs +5 -4
- package/templates/settings-sidebar.tsx +762 -807
- package/templates/settings.template.mjs +5 -4
- package/templates/settings.tsx +289 -304
- package/templates/shell-nav.template.mjs +5 -4
- package/templates/shell-nav.tsx +212 -219
- package/templates/shell-side-nav.template.mjs +5 -4
- package/templates/shell-side-nav.tsx +135 -157
- package/templates/shell-top-nav.template.mjs +5 -4
- package/templates/shell-top-nav.tsx +182 -203
- package/templates/side-gallery.template.mjs +5 -4
- package/templates/side-gallery.tsx +85 -90
- package/templates/table-grouped.template.mjs +5 -4
- package/templates/table-grouped.tsx +1000 -1053
- package/templates/table-page-chart.template.mjs +5 -4
- package/templates/table-page-chart.tsx +400 -398
- package/templates/table-page-heatmap-status.template.mjs +5 -4
- package/templates/table-page-heatmap-status.tsx +483 -512
- package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
- package/templates/table-page-shoe-store-heatmap.tsx +748 -746
- package/templates/table-page.template.mjs +5 -4
- package/templates/table-page.tsx +396 -405
- package/templates/table.template.mjs +5 -4
- package/templates/table.tsx +92 -93
- package/templates/tech-report.template.mjs +5 -4
- package/templates/tech-report.tsx +1316 -1304
- package/templates/theme-showcase.template.mjs +5 -4
- package/templates/theme-showcase.tsx +871 -951
- package/theme.css +35 -77
- package/theme.css.d.ts +9 -0
- package/tokens.css +373 -380
package/templates/ide.tsx
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
// XLE (canonical structure
|
|
3
|
-
//
|
|
2
|
+
// XLE (canonical structure of the tree below; the CLI had no XLE validator
|
|
3
|
+
// after `astryx layout` was removed in 0.7.0, so this is a reading aid and a
|
|
4
|
+
// human drift check — update it with the file, never alone):
|
|
5
|
+
// L[h=fill] > LC[p=0] > (VH"Code editor" + L[h=fill] > (LP[w=256 p=4] > V[g=2] > TI"Search the night" + TrL) + RH + (LC[p=0] > L[h=fill] > (LC[p=0] > V > (SI[fill] > Cd) + RH + (V[h=300] > (TL[size=sm] > Tab"Terminal"! + Tab"Problems" + Tab"Output" + Tab"Debug") + (SI[fill] > Cd))) + (RH + (LP[w=320 p=4] > V[g=3] > (SG > SGI"Properties"! + SGI"History") + (V[g=3] > (V[g=1] > Hd"NightCounter.tsx"[level=3] + Tx"src/components/NightCounter.tsx"[t=supporting]) + ML + (V[g=2] > B.secondary"Format Document" + B.secondary"Go to Definition" + B.secondary"Find References")) + (V[g=1] > UL > LI*3)))))
|
|
4
6
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
26
|
-
import {TextInput} from '@astryxdesign/core/TextInput';
|
|
27
|
-
import {TreeList} from '@astryxdesign/core/TreeList';
|
|
28
|
-
import type {TreeListItemData} from '@astryxdesign/core/TreeList';
|
|
29
|
-
import {Folder, FileText, Search} from 'lucide-react';
|
|
7
|
+
import { Button } from "@astryxdesign/core/Button";
|
|
8
|
+
import { Center } from "@astryxdesign/core/Center";
|
|
9
|
+
import { CodeBlock } from "@astryxdesign/core/CodeBlock";
|
|
10
|
+
import { EmptyState } from "@astryxdesign/core/EmptyState";
|
|
11
|
+
import { useMediaQuery } from "@astryxdesign/core/hooks";
|
|
12
|
+
import { Icon } from "@astryxdesign/core/Icon";
|
|
13
|
+
import { Layout, LayoutContent, LayoutPanel, Stack, StackItem } from "@astryxdesign/core/Layout";
|
|
14
|
+
import { List, ListItem } from "@astryxdesign/core/List";
|
|
15
|
+
import { MetadataList, MetadataListItem } from "@astryxdesign/core/MetadataList";
|
|
16
|
+
import { ResizeHandle, useResizable } from "@astryxdesign/core/Resizable";
|
|
17
|
+
import { SegmentedControl, SegmentedControlItem } from "@astryxdesign/core/SegmentedControl";
|
|
18
|
+
import { StatusDot } from "@astryxdesign/core/StatusDot";
|
|
19
|
+
import { Tab, TabList } from "@astryxdesign/core/TabList";
|
|
20
|
+
import { Heading, Text } from "@astryxdesign/core/Text";
|
|
21
|
+
import { TextInput } from "@astryxdesign/core/TextInput";
|
|
22
|
+
import type { TreeListItemData } from "@astryxdesign/core/TreeList";
|
|
23
|
+
import { TreeList } from "@astryxdesign/core/TreeList";
|
|
24
|
+
import { VisuallyHidden } from "@astryxdesign/core/VisuallyHidden";
|
|
25
|
+
import { FileText, Folder, Search } from "lucide-react";
|
|
26
|
+
import { type CSSProperties, useMemo, useState } from "react";
|
|
30
27
|
|
|
31
28
|
const styles: Record<string, CSSProperties> = {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
29
|
+
contentFill: {
|
|
30
|
+
height: "100%",
|
|
31
|
+
},
|
|
32
|
+
terminalWrapper: {
|
|
33
|
+
minHeight: 0,
|
|
34
|
+
overflow: "hidden",
|
|
35
|
+
display: "grid",
|
|
36
|
+
},
|
|
37
|
+
tabListPadding: {
|
|
38
|
+
paddingTop: "var(--spacing-2)",
|
|
39
|
+
// The focus ring is a fixed 2px outline (core's defineTheme.ts), and the
|
|
40
|
+
// ring lands INSIDE this box's clip rather than on its edge being cut in
|
|
41
|
+
// half. The 2px of that is a PIXEL relationship, so it is written as
|
|
42
|
+
// pixels: --spacing-1 is rem since core 0.7.0, and at a 20px root it
|
|
43
|
+
// is 5px, which would clip the ring by a pixel. Deliberately NOT
|
|
44
|
+
// applied to `terminalPanel`: that would inset the CodeBlock itself,
|
|
45
|
+
// moving the code rather than giving the ring somewhere to live.
|
|
46
|
+
paddingInline: "calc(var(--spacing-1) + 2px)",
|
|
47
|
+
},
|
|
48
|
+
metadataCompact: {
|
|
49
|
+
gap: "var(--spacing-1) var(--spacing-3)",
|
|
50
|
+
},
|
|
51
|
+
// No `overflow` here, deliberately. The only child is a `CodeBlock` at
|
|
52
|
+
// `height: 100%` whose own root is `overflow: hidden`, so this box could
|
|
53
|
+
// never overflow and the scroller never fired — it only clipped. An
|
|
54
|
+
// `overflow: auto` on a parent whose sole child is a fixed-height
|
|
55
|
+
// `overflow: hidden` box is inert, which is what the deleted line was.
|
|
56
|
+
editorArea: {
|
|
57
|
+
minHeight: 0,
|
|
58
|
+
},
|
|
59
|
+
fileExplorer: {
|
|
60
|
+
minWidth: 0,
|
|
61
|
+
},
|
|
62
|
+
propertiesPanel: {
|
|
63
|
+
height: "100%",
|
|
64
|
+
},
|
|
65
|
+
propertiesContent: {
|
|
66
|
+
flex: 1,
|
|
67
|
+
minHeight: 0,
|
|
68
|
+
},
|
|
69
|
+
propertyActions: {
|
|
70
|
+
marginTop: "auto",
|
|
71
|
+
},
|
|
72
|
+
terminalPanel: {
|
|
73
|
+
flexShrink: 0,
|
|
74
|
+
overflow: "hidden",
|
|
75
|
+
},
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
// Full-bleed CodeBlock inside a panel: the panel owns the chrome, so the
|
|
79
79
|
// block drops its own border and radius rather than drawing a box in a box.
|
|
80
80
|
const codeBlockFlush: CSSProperties = {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
width: "100%",
|
|
82
|
+
height: "100%",
|
|
83
|
+
borderWidth: 0,
|
|
84
|
+
borderRadius: 0,
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
const EDITOR_CODE = `import {useState, useCallback} from 'react';
|
|
@@ -136,398 +136,352 @@ const OUTPUT_LOG = `[@astryxdesign/core] theme tokens resolved in 38ms
|
|
|
136
136
|
[HMR] connected, watching src/components/NightCounter.tsx
|
|
137
137
|
[HMR] updated src/tokens.ts in 122ms`;
|
|
138
138
|
|
|
139
|
-
function buildFileTree(
|
|
140
|
-
|
|
141
|
-
): TreeListItemData
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
],
|
|
182
|
-
},
|
|
183
|
-
file('package.json'),
|
|
184
|
-
file('tsconfig.json'),
|
|
185
|
-
file('next.config.mjs'),
|
|
186
|
-
];
|
|
139
|
+
function buildFileTree(onFileClick: (name: string) => void): TreeListItemData[] {
|
|
140
|
+
const label = (text: string) => <Text maxLines={1}>{text}</Text>;
|
|
141
|
+
const file = (id: string): TreeListItemData => ({
|
|
142
|
+
id,
|
|
143
|
+
label: label(id),
|
|
144
|
+
startContent: <Icon icon={FileText} size="xsm" />,
|
|
145
|
+
onClick: () => onFileClick(id),
|
|
146
|
+
});
|
|
147
|
+
return [
|
|
148
|
+
{
|
|
149
|
+
id: "src",
|
|
150
|
+
label: label("src"),
|
|
151
|
+
startContent: <Icon icon={Folder} size="xsm" />,
|
|
152
|
+
isExpanded: true,
|
|
153
|
+
children: [
|
|
154
|
+
{
|
|
155
|
+
id: "components",
|
|
156
|
+
label: label("components"),
|
|
157
|
+
startContent: <Icon icon={Folder} size="xsm" />,
|
|
158
|
+
isExpanded: true,
|
|
159
|
+
children: [file("NightCounter.tsx"), file("Header.tsx"), file("Layout.tsx")],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: "pages",
|
|
163
|
+
label: label("pages"),
|
|
164
|
+
startContent: <Icon icon={Folder} size="xsm" />,
|
|
165
|
+
isExpanded: true,
|
|
166
|
+
children: [file("index.tsx"), file("about.tsx")],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "styles",
|
|
170
|
+
label: label("styles"),
|
|
171
|
+
startContent: <Icon icon={Folder} size="xsm" />,
|
|
172
|
+
isExpanded: true,
|
|
173
|
+
children: [file("tokens.ts"), file("theme.ts")],
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
file("package.json"),
|
|
178
|
+
file("tsconfig.json"),
|
|
179
|
+
file("next.config.mjs"),
|
|
180
|
+
];
|
|
187
181
|
}
|
|
188
182
|
|
|
189
|
-
function filterFileTree(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
):
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
item.id.toLowerCase().includes(query) ||
|
|
200
|
-
(children && children.length > 0)
|
|
201
|
-
) {
|
|
202
|
-
out.push({...item, ...(children ? {children, isExpanded: true} : null)});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return out;
|
|
183
|
+
function filterFileTree(items: TreeListItemData[], query: string): TreeListItemData[] {
|
|
184
|
+
const out: TreeListItemData[] = [];
|
|
185
|
+
for (const item of items) {
|
|
186
|
+
const children = item.children ? filterFileTree(item.children, query) : undefined;
|
|
187
|
+
if (item.id.toLowerCase().includes(query) || (children && children.length > 0)) {
|
|
188
|
+
out.push({ ...item, ...(children ? { children, isExpanded: true } : null) });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
206
192
|
}
|
|
207
193
|
|
|
208
194
|
const PROPERTIES = [
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
195
|
+
{ label: "Type", value: "React Component" },
|
|
196
|
+
{ label: "Language", value: "TypeScript" },
|
|
197
|
+
{ label: "Lines", value: "42" },
|
|
198
|
+
{ label: "Size", value: "1.2 KB" },
|
|
199
|
+
{ label: "Last modified", value: "2 hours ago" },
|
|
200
|
+
{ label: "Imports", value: "4 modules" },
|
|
201
|
+
{ label: "Exports", value: "1 default" },
|
|
202
|
+
{ label: "Hooks", value: "useState, useCallback" },
|
|
217
203
|
];
|
|
218
204
|
|
|
219
205
|
const HISTORY_ITEMS = [
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
206
|
+
{ label: "Opened NightCounter.tsx", time: "2 min ago" },
|
|
207
|
+
{ label: "Opened Layout.tsx", time: "6 min ago" },
|
|
208
|
+
{ label: "Viewed tokens.ts", time: "11 min ago" },
|
|
223
209
|
];
|
|
224
210
|
|
|
225
211
|
export default function IdeWorkspace() {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
212
|
+
const [activeFile, setActiveFile] = useState("NightCounter.tsx");
|
|
213
|
+
const [activeTermTab, setActiveTermTab] = useState("terminal");
|
|
214
|
+
const [activePropertiesTab, setActivePropertiesTab] = useState("properties");
|
|
215
|
+
const [query, setQuery] = useState("");
|
|
216
|
+
const fileTree = useMemo(() => buildFileTree(setActiveFile), []);
|
|
217
|
+
const visibleTree = useMemo(() => {
|
|
218
|
+
const q = query.trim().toLowerCase();
|
|
219
|
+
return q ? filterFileTree(fileTree, q) : fileTree;
|
|
220
|
+
}, [fileTree, query]);
|
|
235
221
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
222
|
+
const startPanel = useResizable({
|
|
223
|
+
defaultSize: 256,
|
|
224
|
+
minSize: 160,
|
|
225
|
+
maxSize: 400,
|
|
226
|
+
collapsible: true,
|
|
227
|
+
collapsedSize: 50,
|
|
228
|
+
});
|
|
243
229
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
230
|
+
const endPanel = useResizable({
|
|
231
|
+
defaultSize: 320,
|
|
232
|
+
minSize: 180,
|
|
233
|
+
maxSize: 500,
|
|
234
|
+
collapsible: true,
|
|
235
|
+
collapsedSize: 50,
|
|
236
|
+
});
|
|
251
237
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
238
|
+
// Capped so the terminal cannot swallow the canvas: the editor stack above
|
|
239
|
+
// has no minimum of its own, and an unbounded drag leaves nothing to grab.
|
|
240
|
+
const bottomPanel = useResizable({
|
|
241
|
+
defaultSize: 300,
|
|
242
|
+
minSize: 80,
|
|
243
|
+
maxSize: 520,
|
|
244
|
+
collapsible: true,
|
|
245
|
+
collapsedSize: 40,
|
|
246
|
+
});
|
|
261
247
|
|
|
262
|
-
|
|
248
|
+
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
263
249
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
type="supporting"
|
|
502
|
-
color="secondary"
|
|
503
|
-
maxLines={1}
|
|
504
|
-
hasTabularNumbers>
|
|
505
|
-
{item.time}
|
|
506
|
-
</Text>
|
|
507
|
-
}
|
|
508
|
-
startContent={
|
|
509
|
-
<StatusDot
|
|
510
|
-
variant="neutral"
|
|
511
|
-
label="Timeline marker"
|
|
512
|
-
/>
|
|
513
|
-
}
|
|
514
|
-
/>
|
|
515
|
-
))}
|
|
516
|
-
</List>
|
|
517
|
-
</Stack>
|
|
518
|
-
)}
|
|
519
|
-
</Stack>
|
|
520
|
-
</LayoutPanel>
|
|
521
|
-
)}
|
|
522
|
-
</>
|
|
523
|
-
)
|
|
524
|
-
}
|
|
525
|
-
/>
|
|
526
|
-
</LayoutContent>
|
|
527
|
-
}
|
|
528
|
-
/>
|
|
529
|
-
</LayoutContent>
|
|
530
|
-
}
|
|
531
|
-
/>
|
|
532
|
-
);
|
|
250
|
+
return (
|
|
251
|
+
<Layout
|
|
252
|
+
height="fill"
|
|
253
|
+
content={
|
|
254
|
+
<LayoutContent padding={0}>
|
|
255
|
+
<VisuallyHidden as="h1">Code editor</VisuallyHidden>
|
|
256
|
+
<Layout
|
|
257
|
+
height="fill"
|
|
258
|
+
start={
|
|
259
|
+
isMobile ? undefined : (
|
|
260
|
+
<>
|
|
261
|
+
{!startPanel.isCollapsed && (
|
|
262
|
+
<LayoutPanel width={startPanel.size} hasDivider={false} padding={4}>
|
|
263
|
+
<Stack direction="vertical" style={styles.fileExplorer} gap={2}>
|
|
264
|
+
<TextInput
|
|
265
|
+
label="Search files"
|
|
266
|
+
isLabelHidden
|
|
267
|
+
value={query}
|
|
268
|
+
onChange={setQuery}
|
|
269
|
+
placeholder="Search the night"
|
|
270
|
+
size="md"
|
|
271
|
+
startIcon={Search}
|
|
272
|
+
hasClear
|
|
273
|
+
/>
|
|
274
|
+
{visibleTree.length > 0 ? (
|
|
275
|
+
<TreeList items={visibleTree} density="compact" />
|
|
276
|
+
) : (
|
|
277
|
+
<EmptyState
|
|
278
|
+
title="No files match"
|
|
279
|
+
description={`Nothing in the night answers to "${query.trim()}".`}
|
|
280
|
+
isCompact
|
|
281
|
+
/>
|
|
282
|
+
)}
|
|
283
|
+
</Stack>
|
|
284
|
+
</LayoutPanel>
|
|
285
|
+
)}
|
|
286
|
+
<ResizeHandle
|
|
287
|
+
direction="horizontal"
|
|
288
|
+
hasDivider
|
|
289
|
+
isAlwaysVisible={false}
|
|
290
|
+
resizable={startPanel.props}
|
|
291
|
+
label="Resize file explorer"
|
|
292
|
+
/>
|
|
293
|
+
</>
|
|
294
|
+
)
|
|
295
|
+
}
|
|
296
|
+
content={
|
|
297
|
+
<LayoutContent padding={0}>
|
|
298
|
+
<Layout
|
|
299
|
+
height="fill"
|
|
300
|
+
content={
|
|
301
|
+
<LayoutContent padding={0}>
|
|
302
|
+
<Stack direction="vertical" style={styles.contentFill}>
|
|
303
|
+
<StackItem size="fill" style={styles.editorArea}>
|
|
304
|
+
<CodeBlock
|
|
305
|
+
code={EDITOR_CODE}
|
|
306
|
+
language="typescript"
|
|
307
|
+
container="section"
|
|
308
|
+
hasLanguageLabel={false}
|
|
309
|
+
hasLineNumbers
|
|
310
|
+
highlightLines={[21]}
|
|
311
|
+
hasCopyButton={false}
|
|
312
|
+
size="sm"
|
|
313
|
+
style={codeBlockFlush}
|
|
314
|
+
/>
|
|
315
|
+
</StackItem>
|
|
316
|
+
<ResizeHandle
|
|
317
|
+
direction="vertical"
|
|
318
|
+
hasDivider
|
|
319
|
+
isReversed
|
|
320
|
+
isAlwaysVisible={false}
|
|
321
|
+
resizable={bottomPanel.props}
|
|
322
|
+
label="Resize terminal"
|
|
323
|
+
/>
|
|
324
|
+
{!bottomPanel.isCollapsed && (
|
|
325
|
+
<Stack
|
|
326
|
+
direction="vertical"
|
|
327
|
+
height={bottomPanel.size}
|
|
328
|
+
style={styles.terminalPanel}
|
|
329
|
+
>
|
|
330
|
+
<TabList
|
|
331
|
+
value={activeTermTab}
|
|
332
|
+
onChange={(val) => setActiveTermTab(val)}
|
|
333
|
+
size="sm"
|
|
334
|
+
hasDivider={false}
|
|
335
|
+
style={styles.tabListPadding}
|
|
336
|
+
>
|
|
337
|
+
<Tab label="Terminal" value="terminal" />
|
|
338
|
+
<Tab label="Problems" value="problems" />
|
|
339
|
+
<Tab label="Output" value="output" />
|
|
340
|
+
<Tab label="Debug" value="debug" />
|
|
341
|
+
</TabList>
|
|
342
|
+
<StackItem size="fill" style={styles.terminalWrapper}>
|
|
343
|
+
{activeTermTab === "terminal" && (
|
|
344
|
+
<CodeBlock
|
|
345
|
+
code={TERMINAL_OUTPUT}
|
|
346
|
+
language="bash"
|
|
347
|
+
container="section"
|
|
348
|
+
hasLanguageLabel={false}
|
|
349
|
+
hasCopyButton={false}
|
|
350
|
+
size="sm"
|
|
351
|
+
style={codeBlockFlush}
|
|
352
|
+
/>
|
|
353
|
+
)}
|
|
354
|
+
{activeTermTab === "output" && (
|
|
355
|
+
<CodeBlock
|
|
356
|
+
code={OUTPUT_LOG}
|
|
357
|
+
language="bash"
|
|
358
|
+
container="section"
|
|
359
|
+
hasLanguageLabel={false}
|
|
360
|
+
hasCopyButton={false}
|
|
361
|
+
size="sm"
|
|
362
|
+
style={codeBlockFlush}
|
|
363
|
+
/>
|
|
364
|
+
)}
|
|
365
|
+
{activeTermTab === "problems" && (
|
|
366
|
+
<Center style={{ height: "100%" }}>
|
|
367
|
+
<EmptyState
|
|
368
|
+
title="No problems"
|
|
369
|
+
description="The night watch reports no errors or warnings."
|
|
370
|
+
isCompact
|
|
371
|
+
/>
|
|
372
|
+
</Center>
|
|
373
|
+
)}
|
|
374
|
+
{activeTermTab === "debug" && (
|
|
375
|
+
<Center style={{ height: "100%" }}>
|
|
376
|
+
<EmptyState
|
|
377
|
+
title="No debug session"
|
|
378
|
+
description="Start debugging to inspect the night shift."
|
|
379
|
+
isCompact
|
|
380
|
+
/>
|
|
381
|
+
</Center>
|
|
382
|
+
)}
|
|
383
|
+
</StackItem>
|
|
384
|
+
</Stack>
|
|
385
|
+
)}
|
|
386
|
+
</Stack>
|
|
387
|
+
</LayoutContent>
|
|
388
|
+
}
|
|
389
|
+
end={
|
|
390
|
+
isMobile ? undefined : (
|
|
391
|
+
<>
|
|
392
|
+
<ResizeHandle
|
|
393
|
+
direction="horizontal"
|
|
394
|
+
hasDivider
|
|
395
|
+
isReversed
|
|
396
|
+
isAlwaysVisible={false}
|
|
397
|
+
resizable={endPanel.props}
|
|
398
|
+
label="Resize properties panel"
|
|
399
|
+
/>
|
|
400
|
+
{!endPanel.isCollapsed && (
|
|
401
|
+
<LayoutPanel width={endPanel.size} hasDivider={false} padding={4}>
|
|
402
|
+
<Stack direction="vertical" gap={3} style={styles.propertiesPanel}>
|
|
403
|
+
<SegmentedControl
|
|
404
|
+
label="Properties panel sections"
|
|
405
|
+
value={activePropertiesTab}
|
|
406
|
+
onChange={setActivePropertiesTab}
|
|
407
|
+
size="sm"
|
|
408
|
+
layout="fill"
|
|
409
|
+
>
|
|
410
|
+
<SegmentedControlItem label="Properties" value="properties" />
|
|
411
|
+
<SegmentedControlItem label="History" value="history" />
|
|
412
|
+
</SegmentedControl>
|
|
413
|
+
{activePropertiesTab === "properties" ? (
|
|
414
|
+
<Stack
|
|
415
|
+
direction="vertical"
|
|
416
|
+
gap={3}
|
|
417
|
+
style={styles.propertiesContent}
|
|
418
|
+
>
|
|
419
|
+
<Stack direction="vertical" gap={1}>
|
|
420
|
+
<Heading level={3} maxLines={1}>
|
|
421
|
+
{activeFile}
|
|
422
|
+
</Heading>
|
|
423
|
+
<Text color="secondary" type="supporting" maxLines={1}>
|
|
424
|
+
src/components/{activeFile}
|
|
425
|
+
</Text>
|
|
426
|
+
</Stack>
|
|
427
|
+
<MetadataList style={styles.metadataCompact}>
|
|
428
|
+
{PROPERTIES.map((prop) => (
|
|
429
|
+
<MetadataListItem key={prop.label} label={prop.label}>
|
|
430
|
+
{prop.value}
|
|
431
|
+
</MetadataListItem>
|
|
432
|
+
))}
|
|
433
|
+
</MetadataList>
|
|
434
|
+
<Stack
|
|
435
|
+
direction="vertical"
|
|
436
|
+
gap={2}
|
|
437
|
+
style={styles.propertyActions}
|
|
438
|
+
>
|
|
439
|
+
<Button label="Format Document" size="sm" variant="secondary" />
|
|
440
|
+
<Button
|
|
441
|
+
label="Go to Definition"
|
|
442
|
+
size="sm"
|
|
443
|
+
variant="secondary"
|
|
444
|
+
/>
|
|
445
|
+
<Button label="Find References" size="sm" variant="secondary" />
|
|
446
|
+
</Stack>
|
|
447
|
+
</Stack>
|
|
448
|
+
) : (
|
|
449
|
+
<Stack direction="vertical" gap={1}>
|
|
450
|
+
<List>
|
|
451
|
+
{HISTORY_ITEMS.map((item) => (
|
|
452
|
+
<ListItem
|
|
453
|
+
key={item.label}
|
|
454
|
+
label={item.label}
|
|
455
|
+
endContent={
|
|
456
|
+
<Text
|
|
457
|
+
type="supporting"
|
|
458
|
+
color="secondary"
|
|
459
|
+
maxLines={1}
|
|
460
|
+
hasTabularNumbers
|
|
461
|
+
>
|
|
462
|
+
{item.time}
|
|
463
|
+
</Text>
|
|
464
|
+
}
|
|
465
|
+
startContent={
|
|
466
|
+
<StatusDot variant="neutral" label="Timeline marker" />
|
|
467
|
+
}
|
|
468
|
+
/>
|
|
469
|
+
))}
|
|
470
|
+
</List>
|
|
471
|
+
</Stack>
|
|
472
|
+
)}
|
|
473
|
+
</Stack>
|
|
474
|
+
</LayoutPanel>
|
|
475
|
+
)}
|
|
476
|
+
</>
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
/>
|
|
480
|
+
</LayoutContent>
|
|
481
|
+
}
|
|
482
|
+
/>
|
|
483
|
+
</LayoutContent>
|
|
484
|
+
}
|
|
485
|
+
/>
|
|
486
|
+
);
|
|
533
487
|
}
|