@gridland/demo 0.2.49 → 0.2.51
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/dist/chunk-4VNS5WPM.js +42 -0
- package/dist/chunk-DTDQ3HF4.js +494 -0
- package/dist/demo-names.json +1 -1
- package/dist/landing.js +245 -344
- package/dist/run.js +1376 -1235
- package/dist/token-M3ULGZTY.js +62 -0
- package/dist/token-util-FKUIR5UM.js +5 -0
- package/package.json +4 -4
package/dist/landing.js
CHANGED
|
@@ -52,33 +52,6 @@ function textStyle(opts) {
|
|
|
52
52
|
|
|
53
53
|
// ../ui/components/status-bar/status-bar.tsx
|
|
54
54
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
55
|
-
function StatusBar({ items, extra }) {
|
|
56
|
-
const theme = useTheme();
|
|
57
|
-
const parts = [];
|
|
58
|
-
if (extra !== void 0) {
|
|
59
|
-
parts.push(
|
|
60
|
-
/* @__PURE__ */ jsx3("span", { children: extra }, "extra")
|
|
61
|
-
);
|
|
62
|
-
parts.push(
|
|
63
|
-
/* @__PURE__ */ jsx3("span", { style: textStyle({ dim: true, fg: theme.placeholder }), children: " \u2502 " }, "pipe")
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
items.forEach((item, i) => {
|
|
67
|
-
if (i > 0) {
|
|
68
|
-
parts.push(/* @__PURE__ */ jsx3("span", { children: " " }, `gap-${i}`));
|
|
69
|
-
}
|
|
70
|
-
parts.push(
|
|
71
|
-
/* @__PURE__ */ jsx3("span", { style: textStyle({ bold: true, fg: theme.background, bg: theme.muted }), children: ` ${item.key} ` }, `key-${i}`)
|
|
72
|
-
);
|
|
73
|
-
parts.push(
|
|
74
|
-
/* @__PURE__ */ jsx3("span", { style: textStyle({ dim: true, fg: theme.placeholder }), children: ` ${item.label}` }, `label-${i}`)
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
if (parts.length === 0) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
return /* @__PURE__ */ jsx3("text", { children: parts });
|
|
81
|
-
}
|
|
82
55
|
|
|
83
56
|
// ../ui/components/provider/provider.tsx
|
|
84
57
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
@@ -99,7 +72,7 @@ import { jsx as jsx6 } from "react/jsx-runtime";
|
|
|
99
72
|
import { useEffect, useState as useState2 } from "react";
|
|
100
73
|
import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
101
74
|
var VARIANTS = {
|
|
102
|
-
dots: { frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"], interval:
|
|
75
|
+
dots: { frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"], interval: 80 },
|
|
103
76
|
pulse: { frames: ["\xB7", "\u2219", "\u25CF", "\u2219", "\xB7", "\xB7", "\xB7"], interval: 180 },
|
|
104
77
|
meter: { frames: ["\u25B1\u25B1\u25B1", "\u25B0\u25B1\u25B1", "\u25B0\u25B0\u25B1", "\u25B0\u25B0\u25B0", "\u25B0\u25B0\u25B1", "\u25B0\u25B1\u25B1", "\u25B1\u25B1\u25B1"], interval: 143 },
|
|
105
78
|
bloom: { frames: ["\xB7", "\u2726", "\u2727", "\u2739", "\u273A", "\u274B", "\u2738", "\u2735", "\u2738", "\u274B", "\u273A", "\u2739", "\u2727", "\u2726", "\xB7", "\xB7"], interval: 100 },
|
|
@@ -124,8 +97,9 @@ import { useReducer as useReducer2, useMemo as useMemo2, useRef as useRef3 } fro
|
|
|
124
97
|
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
125
98
|
|
|
126
99
|
// ../ui/components/table/table.tsx
|
|
127
|
-
import { Fragment } from "react";
|
|
100
|
+
import { createContext as createContext3, useContext as useContext3, Children, isValidElement, Fragment } from "react";
|
|
128
101
|
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
102
|
+
var TableContext = createContext3(null);
|
|
129
103
|
|
|
130
104
|
// ../ui/components/gradient/gradient.tsx
|
|
131
105
|
import { Fragment as Fragment2, jsx as jsx13 } from "react/jsx-runtime";
|
|
@@ -194,59 +168,29 @@ function Gradient({ children, name, colors }) {
|
|
|
194
168
|
}
|
|
195
169
|
|
|
196
170
|
// ../ui/components/tab-bar/tab-bar.tsx
|
|
197
|
-
import { createContext as
|
|
171
|
+
import { createContext as createContext4, useContext as useContext4, useState as useState5, Children as Children2, isValidElement as isValidElement2 } from "react";
|
|
198
172
|
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
199
|
-
var TabsContext =
|
|
173
|
+
var TabsContext = createContext4(null);
|
|
200
174
|
|
|
201
175
|
// ../ui/components/modal/modal.tsx
|
|
202
176
|
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
203
|
-
function Modal({
|
|
204
|
-
children,
|
|
205
|
-
title,
|
|
206
|
-
borderColor,
|
|
207
|
-
borderStyle = "rounded",
|
|
208
|
-
onClose,
|
|
209
|
-
useKeyboard: useKeyboardProp
|
|
210
|
-
}) {
|
|
211
|
-
const theme = useTheme();
|
|
212
|
-
const useKeyboard = useKeyboardContext(useKeyboardProp);
|
|
213
|
-
const resolvedBorderColor = borderColor ?? theme.muted;
|
|
214
|
-
useKeyboard?.((event) => {
|
|
215
|
-
if (event.name === "escape" && onClose) {
|
|
216
|
-
onClose();
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
return /* @__PURE__ */ jsx15("box", { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx15(
|
|
220
|
-
"box",
|
|
221
|
-
{
|
|
222
|
-
flexDirection: "column",
|
|
223
|
-
flexGrow: 1,
|
|
224
|
-
border: true,
|
|
225
|
-
borderStyle,
|
|
226
|
-
borderColor: resolvedBorderColor,
|
|
227
|
-
children: title ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
228
|
-
/* @__PURE__ */ jsx15("box", { paddingX: 1, marginBottom: 1, children: /* @__PURE__ */ jsx15("text", { style: textStyle({ bold: true, fg: theme.primary }), children: title }) }),
|
|
229
|
-
children
|
|
230
|
-
] }) : children
|
|
231
|
-
}
|
|
232
|
-
) });
|
|
233
|
-
}
|
|
234
177
|
|
|
235
178
|
// ../ui/components/prompt-input/prompt-input.tsx
|
|
236
179
|
import {
|
|
237
180
|
useState as useState6,
|
|
238
181
|
useRef as useRef4,
|
|
239
182
|
useCallback as useCallback2,
|
|
183
|
+
useEffect as useEffect2,
|
|
240
184
|
useMemo as useMemo3,
|
|
241
|
-
createContext as
|
|
242
|
-
useContext as
|
|
185
|
+
createContext as createContext5,
|
|
186
|
+
useContext as useContext5
|
|
243
187
|
} from "react";
|
|
244
188
|
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
245
|
-
var PromptInputControllerCtx =
|
|
246
|
-
var useOptionalController = () =>
|
|
247
|
-
var PromptInputContext =
|
|
189
|
+
var PromptInputControllerCtx = createContext5(null);
|
|
190
|
+
var useOptionalController = () => useContext5(PromptInputControllerCtx);
|
|
191
|
+
var PromptInputContext = createContext5(null);
|
|
248
192
|
function usePromptInput() {
|
|
249
|
-
const ctx =
|
|
193
|
+
const ctx = useContext5(PromptInputContext);
|
|
250
194
|
if (!ctx) {
|
|
251
195
|
throw new Error("usePromptInput must be used within a <PromptInput> component");
|
|
252
196
|
}
|
|
@@ -268,9 +212,10 @@ function resolveStatusHintText(status, submittedText, streamingText, errorText,
|
|
|
268
212
|
if (status === "error") return errorText;
|
|
269
213
|
return disabledText;
|
|
270
214
|
}
|
|
215
|
+
var DIVIDER_LINE = "\u2500".repeat(500);
|
|
271
216
|
function PromptInputDivider() {
|
|
272
217
|
const { theme } = usePromptInput();
|
|
273
|
-
return /* @__PURE__ */ jsx16("text", { wrapMode: "none", children: /* @__PURE__ */ jsx16("span", { style: textStyle({ dim: true, fg: theme.muted }), children:
|
|
218
|
+
return /* @__PURE__ */ jsx16("text", { wrapMode: "none", marginLeft: -1, marginRight: -1, children: /* @__PURE__ */ jsx16("span", { style: textStyle({ dim: true, fg: theme.muted }), children: DIVIDER_LINE }) });
|
|
274
219
|
}
|
|
275
220
|
function PromptInputSuggestions() {
|
|
276
221
|
const { suggestions, sugIdx, maxSuggestions, theme } = usePromptInput();
|
|
@@ -344,11 +289,20 @@ function PromptInput({
|
|
|
344
289
|
enableHistory = true,
|
|
345
290
|
model,
|
|
346
291
|
showDividers = true,
|
|
292
|
+
autoFocus = false,
|
|
347
293
|
useKeyboard: useKeyboardProp,
|
|
348
294
|
children
|
|
349
295
|
}) {
|
|
350
296
|
const theme = useTheme();
|
|
351
297
|
const useKeyboard = useKeyboardContext(useKeyboardProp);
|
|
298
|
+
useEffect2(() => {
|
|
299
|
+
if (!autoFocus) return;
|
|
300
|
+
if (typeof document === "undefined") return;
|
|
301
|
+
const canvas = document.querySelector("canvas");
|
|
302
|
+
if (canvas && document.activeElement !== canvas) {
|
|
303
|
+
canvas.focus();
|
|
304
|
+
}
|
|
305
|
+
}, [autoFocus]);
|
|
352
306
|
const resolvedPromptColor = promptColor ?? theme.muted;
|
|
353
307
|
const disabled = status ? status === "submitted" || status === "streaming" : disabledProp;
|
|
354
308
|
const statusHintText = resolveStatusHintText(status, submittedText, streamingLabel, errorText, disabledText);
|
|
@@ -542,14 +496,16 @@ function PromptInput({
|
|
|
542
496
|
theme
|
|
543
497
|
};
|
|
544
498
|
if (children) {
|
|
545
|
-
return /* @__PURE__ */ jsx16(PromptInputContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx16("box", { flexDirection: "column", children }) });
|
|
499
|
+
return /* @__PURE__ */ jsx16(PromptInputContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx16("box", { flexDirection: "column", flexShrink: 0, children }) });
|
|
546
500
|
}
|
|
547
|
-
return /* @__PURE__ */ jsx16(PromptInputContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsxs10("box", { flexDirection: "column", children: [
|
|
501
|
+
return /* @__PURE__ */ jsx16(PromptInputContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsxs10("box", { flexDirection: "column", flexShrink: 0, children: [
|
|
548
502
|
showDividers && /* @__PURE__ */ jsx16(PromptInputDivider, {}),
|
|
549
|
-
/* @__PURE__ */
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
503
|
+
/* @__PURE__ */ jsxs10("box", { flexDirection: "column", paddingX: 1, children: [
|
|
504
|
+
/* @__PURE__ */ jsx16(PromptInputSuggestions, {}),
|
|
505
|
+
/* @__PURE__ */ jsx16(PromptInputTextarea, {}),
|
|
506
|
+
/* @__PURE__ */ jsx16(PromptInputStatusText, {}),
|
|
507
|
+
/* @__PURE__ */ jsx16(PromptInputModel, {})
|
|
508
|
+
] }),
|
|
553
509
|
showDividers && /* @__PURE__ */ jsx16(PromptInputDivider, {})
|
|
554
510
|
] }) });
|
|
555
511
|
}
|
|
@@ -563,13 +519,19 @@ PromptInput.Model = PromptInputModel;
|
|
|
563
519
|
// ../ui/components/chat/chat.tsx
|
|
564
520
|
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
565
521
|
|
|
566
|
-
// ../ui/components/
|
|
567
|
-
import {
|
|
568
|
-
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
522
|
+
// ../ui/components/chain-of-thought/chain-of-thought.tsx
|
|
523
|
+
import { createContext as createContext6, memo, useContext as useContext6, useEffect as useEffect3, useMemo as useMemo4, useState as useState7 } from "react";
|
|
524
|
+
import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
569
525
|
var DOTS = ["\u25CB", "\u25D4", "\u25D1", "\u25D5", "\u25CF"];
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
526
|
+
var SPINNER_INTERVAL = 150;
|
|
527
|
+
var ChainOfThoughtContext = createContext6(null);
|
|
528
|
+
var useChainOfThought = () => {
|
|
529
|
+
const context = useContext6(ChainOfThoughtContext);
|
|
530
|
+
if (!context) {
|
|
531
|
+
throw new Error("ChainOfThought components must be used within <ChainOfThought>");
|
|
532
|
+
}
|
|
533
|
+
return context;
|
|
534
|
+
};
|
|
573
535
|
function getStepColor(status, theme) {
|
|
574
536
|
switch (status) {
|
|
575
537
|
case "done":
|
|
@@ -584,78 +546,89 @@ function getStepColor(status, theme) {
|
|
|
584
546
|
return theme.muted;
|
|
585
547
|
}
|
|
586
548
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
549
|
+
var ChainOfThought = memo(({
|
|
550
|
+
open,
|
|
551
|
+
defaultOpen = false,
|
|
552
|
+
onOpenChange,
|
|
553
|
+
children
|
|
554
|
+
}) => {
|
|
555
|
+
const [internalOpen, setInternalOpen] = useState7(defaultOpen);
|
|
556
|
+
const isOpen = open ?? internalOpen;
|
|
557
|
+
const setIsOpen = onOpenChange ?? setInternalOpen;
|
|
558
|
+
const context = useMemo4(
|
|
559
|
+
() => ({ isOpen, setIsOpen }),
|
|
560
|
+
[isOpen, setIsOpen]
|
|
561
|
+
);
|
|
562
|
+
return /* @__PURE__ */ jsx18(ChainOfThoughtContext.Provider, { value: context, children: /* @__PURE__ */ jsx18("box", { flexDirection: "column", children }) });
|
|
563
|
+
});
|
|
564
|
+
var ChainOfThoughtHeader = memo(({
|
|
565
|
+
duration,
|
|
566
|
+
children = "Thought for"
|
|
567
|
+
}) => {
|
|
568
|
+
const theme = useTheme();
|
|
569
|
+
const { isOpen } = useChainOfThought();
|
|
570
|
+
const arrow = isOpen ? "\u25BC" : "\u25B6";
|
|
571
|
+
return /* @__PURE__ */ jsxs12("text", { children: [
|
|
572
|
+
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: theme.muted }), children: arrow }),
|
|
573
|
+
/* @__PURE__ */ jsxs12("span", { style: textStyle({ dim: true, fg: theme.muted }), children: [
|
|
574
|
+
" ",
|
|
575
|
+
children,
|
|
576
|
+
duration ? " " + duration : ""
|
|
577
|
+
] })
|
|
578
|
+
] });
|
|
579
|
+
});
|
|
580
|
+
var ChainOfThoughtContent = memo(({ children }) => {
|
|
581
|
+
const { isOpen } = useChainOfThought();
|
|
582
|
+
if (!isOpen) return null;
|
|
583
|
+
return /* @__PURE__ */ jsx18(Fragment6, { children });
|
|
584
|
+
});
|
|
585
|
+
var ChainOfThoughtStep = memo(({
|
|
586
|
+
label,
|
|
587
|
+
description,
|
|
588
|
+
status = "done",
|
|
589
|
+
isLast = false,
|
|
590
|
+
children
|
|
591
|
+
}) => {
|
|
592
|
+
const theme = useTheme();
|
|
593
|
+
const isActive = status === "running";
|
|
594
|
+
const isPending = status === "pending";
|
|
595
|
+
const color = getStepColor(status, theme);
|
|
591
596
|
const pipe = "\u2502";
|
|
592
|
-
const
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
597
|
+
const [frame, setFrame] = useState7(0);
|
|
598
|
+
useEffect3(() => {
|
|
599
|
+
if (!isActive) {
|
|
600
|
+
setFrame(0);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const id = setInterval(() => setFrame((f) => f + 1), SPINNER_INTERVAL);
|
|
604
|
+
return () => clearInterval(id);
|
|
605
|
+
}, [isActive]);
|
|
606
|
+
const dot = isActive ? DOTS[frame % DOTS.length] : isPending ? "\u25CB" : "\u25CF";
|
|
596
607
|
return /* @__PURE__ */ jsxs12("box", { flexDirection: "column", marginLeft: 1, children: [
|
|
597
608
|
/* @__PURE__ */ jsxs12("text", { children: [
|
|
598
609
|
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: color }), children: dot }),
|
|
599
610
|
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: theme.foreground }), children: " " }),
|
|
600
|
-
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: isPending ? theme.muted : color, dim: isPending, bold: isActive }), children:
|
|
601
|
-
|
|
611
|
+
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: isPending ? theme.muted : color, dim: isPending, bold: isActive }), children: label }),
|
|
612
|
+
description && /* @__PURE__ */ jsx18("span", { style: textStyle({ dim: true, fg: theme.muted }), children: " \u2014 " + description })
|
|
602
613
|
] }),
|
|
603
|
-
|
|
614
|
+
children && /* @__PURE__ */ jsxs12("text", { children: [
|
|
604
615
|
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: color, dim: true }), children: pipe + " " }),
|
|
605
|
-
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg:
|
|
616
|
+
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: status === "error" ? theme.error : theme.accent }), children })
|
|
606
617
|
] }),
|
|
607
618
|
!isLast && /* @__PURE__ */ jsx18("text", { children: /* @__PURE__ */ jsx18("span", { style: textStyle({ fg: color, dim: true }), children: pipe }) })
|
|
608
619
|
] });
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
headerLabel = "Thought for"
|
|
615
|
-
}) {
|
|
616
|
-
const theme = useTheme();
|
|
617
|
-
const arrow = collapsed ? "\u25B6" : "\u25BC";
|
|
618
|
-
const durationStr = duration ?? "0ms";
|
|
619
|
-
const hasRunning = steps?.some((s) => s.status === "running") ?? false;
|
|
620
|
-
const [frame, setFrame] = useState7(0);
|
|
621
|
-
const alive = useRef5(true);
|
|
622
|
-
useEffect2(() => {
|
|
623
|
-
alive.current = true;
|
|
624
|
-
return () => {
|
|
625
|
-
alive.current = false;
|
|
626
|
-
};
|
|
627
|
-
}, []);
|
|
628
|
-
useEffect2(() => {
|
|
629
|
-
if (!hasRunning) return;
|
|
630
|
-
const id = setInterval(() => {
|
|
631
|
-
if (alive.current) setFrame((f) => f + 1);
|
|
632
|
-
}, 150);
|
|
633
|
-
return () => clearInterval(id);
|
|
634
|
-
}, [hasRunning]);
|
|
635
|
-
return /* @__PURE__ */ jsxs12("box", { flexDirection: "column", children: [
|
|
636
|
-
/* @__PURE__ */ jsxs12("text", { children: [
|
|
637
|
-
/* @__PURE__ */ jsx18("span", { style: textStyle({ fg: theme.muted }), children: arrow }),
|
|
638
|
-
/* @__PURE__ */ jsx18("span", { style: textStyle({ dim: true, fg: theme.muted }), children: " " + headerLabel + " " + durationStr })
|
|
639
|
-
] }),
|
|
640
|
-
!collapsed && steps && steps.map((step, i) => /* @__PURE__ */ jsx18(
|
|
641
|
-
StepRow,
|
|
642
|
-
{
|
|
643
|
-
step,
|
|
644
|
-
isLast: i === steps.length - 1,
|
|
645
|
-
theme,
|
|
646
|
-
frame
|
|
647
|
-
},
|
|
648
|
-
`step-${i}`
|
|
649
|
-
))
|
|
650
|
-
] });
|
|
651
|
-
}
|
|
620
|
+
});
|
|
621
|
+
ChainOfThought.displayName = "ChainOfThought";
|
|
622
|
+
ChainOfThoughtHeader.displayName = "ChainOfThoughtHeader";
|
|
623
|
+
ChainOfThoughtContent.displayName = "ChainOfThoughtContent";
|
|
624
|
+
ChainOfThoughtStep.displayName = "ChainOfThoughtStep";
|
|
652
625
|
|
|
653
626
|
// ../ui/components/message/message.tsx
|
|
654
|
-
import { createContext as
|
|
627
|
+
import { createContext as createContext7, useContext as useContext7 } from "react";
|
|
655
628
|
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
656
|
-
var MessageContext =
|
|
629
|
+
var MessageContext = createContext7(null);
|
|
657
630
|
function useMessage() {
|
|
658
|
-
const ctx =
|
|
631
|
+
const ctx = useContext7(MessageContext);
|
|
659
632
|
if (!ctx) throw new Error("useMessage must be used within <Message>");
|
|
660
633
|
return ctx;
|
|
661
634
|
}
|
|
@@ -664,23 +637,25 @@ function getBubbleColors(theme) {
|
|
|
664
637
|
return isDark ? { assistantBg: "#2a2a4a", userBg: "#2a3a3a" } : { assistantBg: "#F1F5F9", userBg: "#E2E8F0" };
|
|
665
638
|
}
|
|
666
639
|
var TOOL_STATE_ICONS = {
|
|
667
|
-
|
|
640
|
+
pending: "\u2022",
|
|
668
641
|
// •
|
|
669
|
-
|
|
642
|
+
running: "\u280B",
|
|
670
643
|
// ⠋
|
|
671
|
-
|
|
644
|
+
completed: "\u2713",
|
|
672
645
|
// ✓
|
|
646
|
+
error: "\u2715"
|
|
647
|
+
// ✕
|
|
673
648
|
};
|
|
674
649
|
function getToolStateColor(state, theme) {
|
|
675
650
|
switch (state) {
|
|
676
|
-
case "
|
|
651
|
+
case "pending":
|
|
677
652
|
return theme.muted;
|
|
678
|
-
case "
|
|
653
|
+
case "running":
|
|
679
654
|
return theme.warning;
|
|
680
|
-
case "
|
|
655
|
+
case "completed":
|
|
681
656
|
return theme.success;
|
|
682
|
-
|
|
683
|
-
return theme.
|
|
657
|
+
case "error":
|
|
658
|
+
return theme.error;
|
|
684
659
|
}
|
|
685
660
|
}
|
|
686
661
|
function MessageContent({ children }) {
|
|
@@ -705,45 +680,57 @@ function MessageText({ children, isLast = false }) {
|
|
|
705
680
|
isLast && isStreaming && /* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: streamingCursor })
|
|
706
681
|
] });
|
|
707
682
|
}
|
|
708
|
-
function MessageReasoning({
|
|
709
|
-
return /* @__PURE__ */
|
|
710
|
-
|
|
711
|
-
{
|
|
712
|
-
steps
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
683
|
+
function MessageReasoning({ duration, steps, collapsed = true, children }) {
|
|
684
|
+
return /* @__PURE__ */ jsxs13(ChainOfThought, { defaultOpen: !collapsed, children: [
|
|
685
|
+
/* @__PURE__ */ jsx19(ChainOfThoughtHeader, { duration }),
|
|
686
|
+
/* @__PURE__ */ jsxs13(ChainOfThoughtContent, { children: [
|
|
687
|
+
steps?.map((step, i) => /* @__PURE__ */ jsx19(
|
|
688
|
+
ChainOfThoughtStep,
|
|
689
|
+
{
|
|
690
|
+
label: step.label,
|
|
691
|
+
description: step.description,
|
|
692
|
+
status: step.status,
|
|
693
|
+
isLast: i === (steps?.length ?? 0) - 1,
|
|
694
|
+
children: step.output
|
|
695
|
+
},
|
|
696
|
+
i
|
|
697
|
+
)),
|
|
698
|
+
children
|
|
699
|
+
] })
|
|
700
|
+
] });
|
|
717
701
|
}
|
|
718
|
-
function
|
|
702
|
+
function MessageToolCall({ name, state = "pending", result, color }) {
|
|
719
703
|
const theme = useTheme();
|
|
720
704
|
const { backgroundColor, textColor } = useMessage();
|
|
721
|
-
const
|
|
722
|
-
const
|
|
723
|
-
const
|
|
724
|
-
const isActive = state === "partial-call" || state === "call";
|
|
705
|
+
const icon = TOOL_STATE_ICONS[state];
|
|
706
|
+
const stateColor = color ?? getToolStateColor(state, theme);
|
|
707
|
+
const isActive = state === "pending" || state === "running";
|
|
725
708
|
return /* @__PURE__ */ jsxs13("box", { flexDirection: "column", children: [
|
|
726
709
|
/* @__PURE__ */ jsxs13("text", { children: [
|
|
727
710
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: stateColor, bg: backgroundColor }), children: icon }),
|
|
728
711
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, bg: backgroundColor }), children: " " }),
|
|
729
|
-
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: stateColor, bold: isActive, bg: backgroundColor }), children:
|
|
712
|
+
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: stateColor, bold: isActive, bg: backgroundColor }), children: name }),
|
|
730
713
|
isActive && /* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: " ..." })
|
|
731
714
|
] }),
|
|
732
|
-
state === "
|
|
715
|
+
state === "completed" && result !== void 0 && /* @__PURE__ */ jsxs13("text", { children: [
|
|
733
716
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: " \u2514\u2500 " }),
|
|
734
717
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: String(result).slice(0, 120) })
|
|
718
|
+
] }),
|
|
719
|
+
state === "error" && result !== void 0 && /* @__PURE__ */ jsxs13("text", { children: [
|
|
720
|
+
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: theme.error, dim: true, bg: backgroundColor }), children: " \u2514\u2500 " }),
|
|
721
|
+
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: theme.error, dim: true, bg: backgroundColor }), children: String(result).slice(0, 120) })
|
|
735
722
|
] })
|
|
736
723
|
] });
|
|
737
724
|
}
|
|
738
|
-
function MessageSource({
|
|
725
|
+
function MessageSource({ title, url, index }) {
|
|
739
726
|
const theme = useTheme();
|
|
740
727
|
const { backgroundColor, textColor } = useMessage();
|
|
741
|
-
const
|
|
728
|
+
const displayTitle = title || url || "source";
|
|
742
729
|
return /* @__PURE__ */ jsxs13("text", { children: [
|
|
743
730
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: "[" }),
|
|
744
731
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: theme.accent, bg: backgroundColor }), children: String(index + 1) }),
|
|
745
732
|
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: textColor, dim: true, bg: backgroundColor }), children: "] " }),
|
|
746
|
-
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: theme.accent, bg: backgroundColor }), children:
|
|
733
|
+
/* @__PURE__ */ jsx19("span", { style: textStyle({ fg: theme.accent, bg: backgroundColor }), children: displayTitle })
|
|
747
734
|
] });
|
|
748
735
|
}
|
|
749
736
|
function MessageFooter({ model, timestamp }) {
|
|
@@ -779,7 +766,7 @@ function Message({
|
|
|
779
766
|
Message.Content = MessageContent;
|
|
780
767
|
Message.Text = MessageText;
|
|
781
768
|
Message.Reasoning = MessageReasoning;
|
|
782
|
-
Message.
|
|
769
|
+
Message.ToolCall = MessageToolCall;
|
|
783
770
|
Message.Source = MessageSource;
|
|
784
771
|
Message.Footer = MessageFooter;
|
|
785
772
|
|
|
@@ -805,64 +792,14 @@ function useBreakpoints() {
|
|
|
805
792
|
};
|
|
806
793
|
}
|
|
807
794
|
|
|
808
|
-
//
|
|
809
|
-
import {
|
|
795
|
+
// src/landing/landing-app.tsx
|
|
796
|
+
import { useMemo as useMemo7 } from "react";
|
|
810
797
|
|
|
811
|
-
//
|
|
798
|
+
// src/landing/install-box.tsx
|
|
812
799
|
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
813
|
-
function AboutModal({ onClose, useKeyboard }) {
|
|
814
|
-
const theme = useTheme();
|
|
815
|
-
return /* @__PURE__ */ jsx21(Modal, { title: "About Gridland", useKeyboard, onClose, children: /* @__PURE__ */ jsxs15("box", { paddingX: 1, flexDirection: "column", gap: 1, children: [
|
|
816
|
-
/* @__PURE__ */ jsx21("text", { style: textStyle({ bold: true, fg: theme.accent }), children: "What is Gridland?" }),
|
|
817
|
-
/* @__PURE__ */ jsx21("text", { children: "Gridland renders terminal UIs to HTML5 Canvas with React." }),
|
|
818
|
-
/* @__PURE__ */ jsx21("text", { children: "No xterm.js. No terminal emulator. Just pixels." }),
|
|
819
|
-
/* @__PURE__ */ jsx21("text", { style: textStyle({ bold: true, fg: theme.accent }), children: "Features" }),
|
|
820
|
-
/* @__PURE__ */ jsxs15("text", { children: [
|
|
821
|
-
/* @__PURE__ */ jsxs15("span", { style: textStyle({ dim: true }), children: [
|
|
822
|
-
"\u2022",
|
|
823
|
-
" "
|
|
824
|
-
] }),
|
|
825
|
-
"Canvas-rendered TUI components"
|
|
826
|
-
] }),
|
|
827
|
-
/* @__PURE__ */ jsxs15("text", { children: [
|
|
828
|
-
/* @__PURE__ */ jsxs15("span", { style: textStyle({ dim: true }), children: [
|
|
829
|
-
"\u2022",
|
|
830
|
-
" "
|
|
831
|
-
] }),
|
|
832
|
-
"React reconciler with JSX"
|
|
833
|
-
] }),
|
|
834
|
-
/* @__PURE__ */ jsxs15("text", { children: [
|
|
835
|
-
/* @__PURE__ */ jsxs15("span", { style: textStyle({ dim: true }), children: [
|
|
836
|
-
"\u2022",
|
|
837
|
-
" "
|
|
838
|
-
] }),
|
|
839
|
-
"Yoga flexbox layout engine"
|
|
840
|
-
] }),
|
|
841
|
-
/* @__PURE__ */ jsxs15("text", { children: [
|
|
842
|
-
/* @__PURE__ */ jsxs15("span", { style: textStyle({ dim: true }), children: [
|
|
843
|
-
"\u2022",
|
|
844
|
-
" "
|
|
845
|
-
] }),
|
|
846
|
-
"Keyboard, mouse, and clipboard support"
|
|
847
|
-
] }),
|
|
848
|
-
/* @__PURE__ */ jsxs15("text", { children: [
|
|
849
|
-
/* @__PURE__ */ jsxs15("span", { style: textStyle({ dim: true }), children: [
|
|
850
|
-
"\u2022",
|
|
851
|
-
" "
|
|
852
|
-
] }),
|
|
853
|
-
"Next.js and Vite plugins"
|
|
854
|
-
] }),
|
|
855
|
-
/* @__PURE__ */ jsx21("text", { style: textStyle({ bold: true, fg: theme.accent }), children: "Tech Stack" }),
|
|
856
|
-
/* @__PURE__ */ jsx21("text", { children: "React + opentui engine + yoga-layout + HTML5 Canvas" }),
|
|
857
|
-
/* @__PURE__ */ jsx21("text", { style: textStyle({ dim: true }), children: "Press q to close" })
|
|
858
|
-
] }) });
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
// ../docs/components/landing/install-box.tsx
|
|
862
|
-
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
863
800
|
function InstallBox() {
|
|
864
801
|
const theme = useTheme();
|
|
865
|
-
return /* @__PURE__ */
|
|
802
|
+
return /* @__PURE__ */ jsx21(
|
|
866
803
|
"box",
|
|
867
804
|
{
|
|
868
805
|
border: true,
|
|
@@ -871,21 +808,21 @@ function InstallBox() {
|
|
|
871
808
|
paddingX: 1,
|
|
872
809
|
flexDirection: "column",
|
|
873
810
|
flexShrink: 0,
|
|
874
|
-
children: /* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
/* @__PURE__ */
|
|
811
|
+
children: /* @__PURE__ */ jsxs15("text", { children: [
|
|
812
|
+
/* @__PURE__ */ jsx21("span", { style: textStyle({ dim: true }), children: "$ " }),
|
|
813
|
+
/* @__PURE__ */ jsx21("span", { style: textStyle({ bold: true }), children: "bun create " }),
|
|
814
|
+
/* @__PURE__ */ jsx21("span", { style: textStyle({ fg: theme.accent }), children: "gridland" })
|
|
878
815
|
] })
|
|
879
816
|
}
|
|
880
817
|
);
|
|
881
818
|
}
|
|
882
819
|
|
|
883
|
-
//
|
|
884
|
-
import { jsx as
|
|
820
|
+
// src/landing/links-box.tsx
|
|
821
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
885
822
|
var UNDERLINE3 = 1 << 3;
|
|
886
823
|
function LinksBox() {
|
|
887
824
|
const theme = useTheme();
|
|
888
|
-
return /* @__PURE__ */
|
|
825
|
+
return /* @__PURE__ */ jsx22(
|
|
889
826
|
"box",
|
|
890
827
|
{
|
|
891
828
|
border: true,
|
|
@@ -894,22 +831,22 @@ function LinksBox() {
|
|
|
894
831
|
paddingX: 1,
|
|
895
832
|
flexDirection: "column",
|
|
896
833
|
flexShrink: 0,
|
|
897
|
-
children: /* @__PURE__ */
|
|
898
|
-
/* @__PURE__ */
|
|
899
|
-
/* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
901
|
-
/* @__PURE__ */
|
|
902
|
-
/* @__PURE__ */
|
|
834
|
+
children: /* @__PURE__ */ jsxs16("text", { children: [
|
|
835
|
+
/* @__PURE__ */ jsx22("span", { children: "\u{1F431}" }),
|
|
836
|
+
/* @__PURE__ */ jsx22("a", { href: "https://github.com/thoughtfulllc/gridland", style: { attributes: UNDERLINE3, fg: theme.accent }, children: " GitHub" }),
|
|
837
|
+
/* @__PURE__ */ jsx22("span", { children: " " }),
|
|
838
|
+
/* @__PURE__ */ jsx22("span", { children: "\u{1F4D6}" }),
|
|
839
|
+
/* @__PURE__ */ jsx22("a", { href: "https://gridland.io/docs", style: { attributes: UNDERLINE3, fg: theme.accent }, children: " Docs" })
|
|
903
840
|
] })
|
|
904
841
|
}
|
|
905
842
|
);
|
|
906
843
|
}
|
|
907
844
|
|
|
908
|
-
//
|
|
909
|
-
import { useState as useState8, useEffect as
|
|
845
|
+
// src/landing/logo.tsx
|
|
846
|
+
import { useState as useState8, useEffect as useEffect4, useRef as useRef5, useMemo as useMemo5 } from "react";
|
|
910
847
|
import figlet from "figlet";
|
|
911
848
|
import ansiShadow from "figlet/importable-fonts/ANSI Shadow.js";
|
|
912
|
-
import { Fragment as
|
|
849
|
+
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
913
850
|
figlet.parseFont("ANSI Shadow", ansiShadow);
|
|
914
851
|
function makeArt(text) {
|
|
915
852
|
return figlet.textSync(text, { font: "ANSI Shadow" }).split("\n").filter((l) => l.trimEnd().length > 0).join("\n");
|
|
@@ -921,8 +858,8 @@ var ART_HEIGHT = 6;
|
|
|
921
858
|
function useAnimation(duration = 1e3) {
|
|
922
859
|
const isBrowser = typeof document !== "undefined";
|
|
923
860
|
const [progress, setProgress] = useState8(isBrowser ? 0 : 1);
|
|
924
|
-
const startTime =
|
|
925
|
-
|
|
861
|
+
const startTime = useRef5(null);
|
|
862
|
+
useEffect4(() => {
|
|
926
863
|
if (!isBrowser) return;
|
|
927
864
|
let raf;
|
|
928
865
|
const tick = (time) => {
|
|
@@ -942,9 +879,9 @@ function RevealGradient({ children, revealCol }) {
|
|
|
942
879
|
const gradientColors = GRADIENTS.instagram;
|
|
943
880
|
const lines = children.split("\n");
|
|
944
881
|
const maxLength = Math.max(...lines.map((l) => l.length));
|
|
945
|
-
if (maxLength === 0) return /* @__PURE__ */
|
|
946
|
-
const hexColors =
|
|
947
|
-
return /* @__PURE__ */
|
|
882
|
+
if (maxLength === 0) return /* @__PURE__ */ jsx23("text", { children });
|
|
883
|
+
const hexColors = useMemo5(() => generateGradient(gradientColors, maxLength), [maxLength]);
|
|
884
|
+
return /* @__PURE__ */ jsx23("box", { position: "relative", width: maxLength, height: lines.length, shouldFill: false, children: lines.map((line, lineIndex) => {
|
|
948
885
|
const runs = [];
|
|
949
886
|
let current = null;
|
|
950
887
|
for (let i = 0; i < line.length; i++) {
|
|
@@ -964,14 +901,14 @@ function RevealGradient({ children, revealCol }) {
|
|
|
964
901
|
}
|
|
965
902
|
}
|
|
966
903
|
if (current) runs.push(current);
|
|
967
|
-
return runs.map((run, runIndex) => /* @__PURE__ */
|
|
904
|
+
return runs.map((run, runIndex) => /* @__PURE__ */ jsx23(
|
|
968
905
|
"box",
|
|
969
906
|
{
|
|
970
907
|
position: "absolute",
|
|
971
908
|
top: lineIndex,
|
|
972
909
|
left: run.start,
|
|
973
910
|
shouldFill: false,
|
|
974
|
-
children: /* @__PURE__ */
|
|
911
|
+
children: /* @__PURE__ */ jsx23("text", { shouldFill: false, children: run.chars.map((char, ci) => /* @__PURE__ */ jsx23(
|
|
975
912
|
"span",
|
|
976
913
|
{
|
|
977
914
|
style: { fg: hexColors[run.start + ci] },
|
|
@@ -993,20 +930,20 @@ function Logo({ compact, narrow, mobile }) {
|
|
|
993
930
|
const maxWidth = compact ? 8 : narrow ? 40 : 62;
|
|
994
931
|
const revealCol = Math.round(revealProgress * (maxWidth + 4)) - 2;
|
|
995
932
|
const taglineOpacity = Math.max(0, Math.min(1, (progress - 0.7) / 0.3));
|
|
996
|
-
const subtitle = /* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
933
|
+
const subtitle = /* @__PURE__ */ jsxs17(Fragment7, { children: [
|
|
934
|
+
/* @__PURE__ */ jsx23("text", { children: " " }),
|
|
935
|
+
/* @__PURE__ */ jsx23("box", { flexDirection: "column", alignItems: "center", width: "100%", shouldFill: false, children: /* @__PURE__ */ jsxs17("text", { style: textStyle({ fg: "#d4b0e8" }), opacity: taglineOpacity, wrapMode: "word", textAlign: "center", width: "100%", shouldFill: false, children: [
|
|
999
936
|
"A framework for building terminal apps, built on ",
|
|
1000
|
-
/* @__PURE__ */
|
|
937
|
+
/* @__PURE__ */ jsx23("a", { href: "https://opentui.com", style: { attributes: 72, fg: "#d4b0e8" }, children: "OpenTUI" }),
|
|
1001
938
|
" + React." + (mobile ? " " : "\n") + "(Gridland apps, like this website, work in the browser and terminal.)"
|
|
1002
939
|
] }) })
|
|
1003
940
|
] });
|
|
1004
941
|
if (!isBrowser) {
|
|
1005
942
|
const art = compact ? "gridland" : narrow ? gridArt + "\n" + landArt : fullArt;
|
|
1006
|
-
return /* @__PURE__ */
|
|
1007
|
-
/* @__PURE__ */
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */
|
|
943
|
+
return /* @__PURE__ */ jsxs17("box", { flexDirection: "column", flexShrink: 0, width: "100%", alignItems: "center", shouldFill: false, children: [
|
|
944
|
+
/* @__PURE__ */ jsx23(Gradient, { name: "instagram", children: art }),
|
|
945
|
+
/* @__PURE__ */ jsx23("text", { children: " " }),
|
|
946
|
+
/* @__PURE__ */ jsx23("box", { flexDirection: "column", alignItems: "center", width: "100%", shouldFill: false, children: /* @__PURE__ */ jsxs17("text", { style: textStyle({ fg: "#d4b0e8" }), shouldFill: false, children: [
|
|
1010
947
|
"A framework for building terminal apps, built on OpenTUI + React.",
|
|
1011
948
|
"\n",
|
|
1012
949
|
"(Gridland apps, like this website, work in the browser and terminal.)"
|
|
@@ -1014,31 +951,31 @@ function Logo({ compact, narrow, mobile }) {
|
|
|
1014
951
|
] });
|
|
1015
952
|
}
|
|
1016
953
|
if (compact) {
|
|
1017
|
-
return /* @__PURE__ */
|
|
1018
|
-
/* @__PURE__ */
|
|
954
|
+
return /* @__PURE__ */ jsxs17("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
955
|
+
/* @__PURE__ */ jsx23("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx23("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: /* @__PURE__ */ jsx23(RevealGradient, { revealCol, children: "gridland" }) }) }),
|
|
1019
956
|
subtitle
|
|
1020
957
|
] });
|
|
1021
958
|
}
|
|
1022
959
|
if (narrow) {
|
|
1023
|
-
return /* @__PURE__ */
|
|
1024
|
-
/* @__PURE__ */
|
|
1025
|
-
/* @__PURE__ */
|
|
1026
|
-
/* @__PURE__ */
|
|
960
|
+
return /* @__PURE__ */ jsxs17("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
961
|
+
/* @__PURE__ */ jsx23("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsxs17("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: [
|
|
962
|
+
/* @__PURE__ */ jsx23(RevealGradient, { revealCol, children: gridArt }),
|
|
963
|
+
/* @__PURE__ */ jsx23(RevealGradient, { revealCol, children: landArt })
|
|
1027
964
|
] }) }),
|
|
1028
965
|
subtitle
|
|
1029
966
|
] });
|
|
1030
967
|
}
|
|
1031
|
-
return /* @__PURE__ */
|
|
1032
|
-
/* @__PURE__ */
|
|
968
|
+
return /* @__PURE__ */ jsxs17("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
969
|
+
/* @__PURE__ */ jsx23("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx23("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: /* @__PURE__ */ jsx23(RevealGradient, { revealCol, children: fullArt }) }) }),
|
|
1033
970
|
subtitle
|
|
1034
971
|
] });
|
|
1035
972
|
}
|
|
1036
973
|
|
|
1037
|
-
//
|
|
1038
|
-
import { useMemo as
|
|
974
|
+
// src/landing/matrix-background.tsx
|
|
975
|
+
import { useMemo as useMemo6 } from "react";
|
|
1039
976
|
|
|
1040
|
-
//
|
|
1041
|
-
import { useState as useState9, useEffect as
|
|
977
|
+
// src/landing/use-matrix.ts
|
|
978
|
+
import { useState as useState9, useEffect as useEffect5, useRef as useRef6 } from "react";
|
|
1042
979
|
var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789@#$%^&*(){}[]|;:<>,.?/~`";
|
|
1043
980
|
function randomChar() {
|
|
1044
981
|
return CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
@@ -1072,7 +1009,7 @@ function buildGrid(columns, width, height) {
|
|
|
1072
1009
|
return { grid, brightness };
|
|
1073
1010
|
}
|
|
1074
1011
|
function useMatrix(width, height) {
|
|
1075
|
-
const columnsRef =
|
|
1012
|
+
const columnsRef = useRef6([]);
|
|
1076
1013
|
const [state, setState] = useState9(() => {
|
|
1077
1014
|
const columns = Array.from(
|
|
1078
1015
|
{ length: width },
|
|
@@ -1081,7 +1018,7 @@ function useMatrix(width, height) {
|
|
|
1081
1018
|
columnsRef.current = columns;
|
|
1082
1019
|
return buildGrid(columns, width, height);
|
|
1083
1020
|
});
|
|
1084
|
-
|
|
1021
|
+
useEffect5(() => {
|
|
1085
1022
|
if (width < 2 || height < 2) return;
|
|
1086
1023
|
const id = setInterval(() => {
|
|
1087
1024
|
const columns = columnsRef.current;
|
|
@@ -1106,7 +1043,7 @@ function useMatrix(width, height) {
|
|
|
1106
1043
|
}, 80);
|
|
1107
1044
|
return () => clearInterval(id);
|
|
1108
1045
|
}, [width, height]);
|
|
1109
|
-
|
|
1046
|
+
useEffect5(() => {
|
|
1110
1047
|
columnsRef.current = Array.from(
|
|
1111
1048
|
{ length: width },
|
|
1112
1049
|
() => Math.random() < 0.5 ? createDrop(height, true) : null
|
|
@@ -1116,8 +1053,8 @@ function useMatrix(width, height) {
|
|
|
1116
1053
|
return state;
|
|
1117
1054
|
}
|
|
1118
1055
|
|
|
1119
|
-
//
|
|
1120
|
-
import { jsx as
|
|
1056
|
+
// src/landing/matrix-background.tsx
|
|
1057
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1121
1058
|
var MUTE_LEVELS = [0.12, 0.18, 0.24, 0.3, 0.38];
|
|
1122
1059
|
var BG = hexToRgb("#1a1a2e");
|
|
1123
1060
|
function buildMutedColors(baseHex) {
|
|
@@ -1136,23 +1073,23 @@ function colorForCell(mutedColors, b) {
|
|
|
1136
1073
|
function MatrixBackground({ width, height, clearRect, clearRects }) {
|
|
1137
1074
|
const { grid, brightness } = useMatrix(width, height);
|
|
1138
1075
|
const theme = useTheme();
|
|
1139
|
-
const columnColors =
|
|
1076
|
+
const columnColors = useMemo6(
|
|
1140
1077
|
() => width > 0 ? generateGradient([theme.accent, theme.secondary, theme.primary], width) : [],
|
|
1141
1078
|
[width, theme.accent, theme.secondary, theme.primary]
|
|
1142
1079
|
);
|
|
1143
|
-
const columnMutedColors =
|
|
1080
|
+
const columnMutedColors = useMemo6(
|
|
1144
1081
|
() => columnColors.map(buildMutedColors),
|
|
1145
1082
|
[columnColors]
|
|
1146
1083
|
);
|
|
1147
|
-
return /* @__PURE__ */
|
|
1084
|
+
return /* @__PURE__ */ jsx24("box", { flexDirection: "column", children: grid.map((row, y) => /* @__PURE__ */ jsx24("text", { children: row.map((cell, x) => {
|
|
1148
1085
|
const inClearRect = clearRect && y >= clearRect.top && y < clearRect.top + clearRect.height && x >= clearRect.left && x < clearRect.left + clearRect.width || clearRects && clearRects.some(
|
|
1149
1086
|
(r) => y >= r.top && y < r.top + r.height && x >= r.left && x < r.left + r.width
|
|
1150
1087
|
);
|
|
1151
1088
|
const mutedColors = columnMutedColors[x];
|
|
1152
1089
|
if (cell === " " || inClearRect || !mutedColors) {
|
|
1153
|
-
return /* @__PURE__ */
|
|
1090
|
+
return /* @__PURE__ */ jsx24("span", { children: " " }, x);
|
|
1154
1091
|
}
|
|
1155
|
-
return /* @__PURE__ */
|
|
1092
|
+
return /* @__PURE__ */ jsx24(
|
|
1156
1093
|
"span",
|
|
1157
1094
|
{
|
|
1158
1095
|
style: {
|
|
@@ -1165,84 +1102,48 @@ function MatrixBackground({ width, height, clearRect, clearRects }) {
|
|
|
1165
1102
|
}) }, y)) });
|
|
1166
1103
|
}
|
|
1167
1104
|
|
|
1168
|
-
//
|
|
1169
|
-
import { jsx as
|
|
1170
|
-
var DEMO_RESPONSES = [
|
|
1171
|
-
"Gridland is a framework for building terminal apps with React. It works in both the browser and terminal!",
|
|
1172
|
-
"You can get started with `bun create gridland` to scaffold a new project.",
|
|
1173
|
-
"OpenTUI provides the layout primitives \u2014 flexbox, borders, text styling \u2014 while React handles the component model.",
|
|
1174
|
-
"Yes! Gridland apps are universal \u2014 the same code renders in a terminal emulator and in the browser.",
|
|
1175
|
-
"Check out the docs for examples of interactive components like inputs, selects, and tables."
|
|
1176
|
-
];
|
|
1105
|
+
// src/landing/landing-app.tsx
|
|
1106
|
+
import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1177
1107
|
function LandingApp({ useKeyboard }) {
|
|
1178
1108
|
const theme = useTheme();
|
|
1179
1109
|
const { width, height, isNarrow, isTiny, isMobile } = useBreakpoints();
|
|
1180
|
-
const [showAbout, setShowAbout] = useState10(false);
|
|
1181
|
-
const [messages, setMessages] = useState10([]);
|
|
1182
|
-
const [chatStatus, setChatStatus] = useState10("ready");
|
|
1183
|
-
const responseIdx = useRef8(0);
|
|
1184
|
-
const handleChatSubmit = useCallback3(({ text }) => {
|
|
1185
|
-
const userMsg = { id: `u-${Date.now()}`, role: "user", content: text };
|
|
1186
|
-
setMessages((prev) => [...prev, userMsg]);
|
|
1187
|
-
setChatStatus("streaming");
|
|
1188
|
-
setTimeout(() => {
|
|
1189
|
-
const response = DEMO_RESPONSES[responseIdx.current % DEMO_RESPONSES.length];
|
|
1190
|
-
responseIdx.current += 1;
|
|
1191
|
-
const assistantMsg = { id: `a-${Date.now()}`, role: "assistant", content: response };
|
|
1192
|
-
setMessages((prev) => [...prev, assistantMsg]);
|
|
1193
|
-
setChatStatus("ready");
|
|
1194
|
-
}, 1200);
|
|
1195
|
-
}, []);
|
|
1196
|
-
useKeyboard((event) => {
|
|
1197
|
-
if (event.name === "a" && !showAbout) {
|
|
1198
|
-
setShowAbout(true);
|
|
1199
|
-
}
|
|
1200
|
-
if (event.name === "q" && showAbout) {
|
|
1201
|
-
setShowAbout(false);
|
|
1202
|
-
}
|
|
1203
|
-
});
|
|
1204
|
-
if (showAbout) {
|
|
1205
|
-
return /* @__PURE__ */ jsxs19("box", { flexDirection: "column", width: "100%", height: "100%", children: [
|
|
1206
|
-
/* @__PURE__ */ jsx26("box", { flexGrow: 1, children: /* @__PURE__ */ jsx26(AboutModal, { onClose: () => setShowAbout(false), useKeyboard }) }),
|
|
1207
|
-
/* @__PURE__ */ jsx26(StatusBar, { items: [{ key: "q", label: "close" }] })
|
|
1208
|
-
] });
|
|
1209
|
-
}
|
|
1210
1110
|
const isBrowser = typeof document !== "undefined";
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
] }),
|
|
1234
|
-
/* @__PURE__ */
|
|
1235
|
-
|
|
1236
|
-
/* @__PURE__ */ jsx26("box", { flexShrink: 0, paddingX: 1, paddingBottom: 0, children: /* @__PURE__ */ jsx26(PromptInput, { splaceholder: "Ask about Gridland...", status: chatStatus, onSubmit: handleChatSubmit, useKeyboard }) })
|
|
1237
|
-
] })
|
|
1111
|
+
const { clearRect, installLinksClearRect } = useMemo7(() => {
|
|
1112
|
+
const logoHeight = isTiny ? 2 : isNarrow ? 13 : 7;
|
|
1113
|
+
const logoExtra = isBrowser ? 1 : 0;
|
|
1114
|
+
const gap = isMobile ? 0 : 1;
|
|
1115
|
+
const installLinksTop = 3 + logoHeight + logoExtra + gap;
|
|
1116
|
+
const installLinksHeight = 3;
|
|
1117
|
+
const boxTop = installLinksTop + installLinksHeight + gap + 1;
|
|
1118
|
+
const bh = height - boxTop - 1;
|
|
1119
|
+
return {
|
|
1120
|
+
clearRect: { top: boxTop, left: 1, width: width - 2, height: bh },
|
|
1121
|
+
installLinksClearRect: { top: installLinksTop, left: 1, width: width - 2, height: installLinksHeight }
|
|
1122
|
+
};
|
|
1123
|
+
}, [width, height, isTiny, isNarrow, isMobile, isBrowser]);
|
|
1124
|
+
return /* @__PURE__ */ jsxs18("box", { width: "100%", height: "100%", position: "relative", children: [
|
|
1125
|
+
/* @__PURE__ */ jsx25(MatrixBackground, { width, height, clearRect, clearRects: isBrowser ? void 0 : [installLinksClearRect] }),
|
|
1126
|
+
/* @__PURE__ */ jsx25("box", { position: "absolute", top: 0, left: 0, width, height, zIndex: 1, flexDirection: "column", shouldFill: false, children: /* @__PURE__ */ jsxs18("box", { flexGrow: 1, flexDirection: "column", paddingTop: 3, paddingLeft: 1, paddingRight: 1, paddingBottom: 1, gap: isMobile ? 0 : 1, shouldFill: false, children: [
|
|
1127
|
+
/* @__PURE__ */ jsx25("box", { flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx25(Logo, { compact: isTiny, narrow: isNarrow, mobile: isMobile }) }),
|
|
1128
|
+
/* @__PURE__ */ jsxs18("box", { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: isMobile ? 0 : 1, flexShrink: 0, shouldFill: false, children: [
|
|
1129
|
+
/* @__PURE__ */ jsx25("box", { border: true, borderStyle: "rounded", borderColor: theme.border, paddingX: 1, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsxs18("text", { children: [
|
|
1130
|
+
/* @__PURE__ */ jsx25("span", { style: textStyle({ dim: true }), children: "$ " }),
|
|
1131
|
+
/* @__PURE__ */ jsx25("span", { style: textStyle({ bold: true }), children: "bunx " }),
|
|
1132
|
+
/* @__PURE__ */ jsx25("span", { style: textStyle({ fg: theme.accent }), children: "@gridland/demo landing" })
|
|
1133
|
+
] }) }),
|
|
1134
|
+
/* @__PURE__ */ jsx25(InstallBox, {}),
|
|
1135
|
+
/* @__PURE__ */ jsx25(LinksBox, {})
|
|
1238
1136
|
] }),
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
] })
|
|
1137
|
+
/* @__PURE__ */ jsx25("box", { flexGrow: 1, border: true, borderStyle: "rounded", borderColor: theme.border, flexDirection: "column", overflow: "hidden" })
|
|
1138
|
+
] }) })
|
|
1241
1139
|
] });
|
|
1242
1140
|
}
|
|
1243
1141
|
|
|
1244
|
-
//
|
|
1245
|
-
import { jsx as
|
|
1142
|
+
// src/landing/matrix-rain.tsx
|
|
1143
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
1144
|
+
|
|
1145
|
+
// src/landing/about-modal.tsx
|
|
1146
|
+
import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1246
1147
|
export {
|
|
1247
1148
|
LandingApp
|
|
1248
1149
|
};
|