@gridland/demo 0.2.52 → 0.2.53
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/demo-names.json +1 -1
- package/dist/landing.js +703 -87
- package/dist/run.js +1035 -386
- package/package.json +3 -3
package/dist/run.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/run.tsx
|
|
2
|
-
import { createCliRenderer, createRoot, useKeyboard as
|
|
2
|
+
import { createCliRenderer, createRoot, useKeyboard as useKeyboard22 } from "@gridland/bun";
|
|
3
3
|
|
|
4
4
|
// demos/index.tsx
|
|
5
|
-
import { useKeyboard as
|
|
5
|
+
import { useKeyboard as useKeyboard21 } from "@gridland/utils";
|
|
6
6
|
|
|
7
7
|
// demos/gradient.tsx
|
|
8
8
|
import { useState as useState8 } from "react";
|
|
@@ -160,9 +160,9 @@ import { useState as useState3 } from "react";
|
|
|
160
160
|
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
161
161
|
function SpinnerPicker({ useKeyboard: useKeyboardProp }) {
|
|
162
162
|
const theme = useTheme();
|
|
163
|
-
const
|
|
163
|
+
const useKeyboard23 = useKeyboardContext(useKeyboardProp);
|
|
164
164
|
const [selected, setSelected] = useState3(0);
|
|
165
|
-
|
|
165
|
+
useKeyboard23?.((event) => {
|
|
166
166
|
if (event.name === "left") {
|
|
167
167
|
setSelected((s) => s > 0 ? s - 1 : VARIANT_NAMES.length - 1);
|
|
168
168
|
} else if (event.name === "right") {
|
|
@@ -291,7 +291,7 @@ function SelectInput({
|
|
|
291
291
|
useKeyboard: useKeyboardProp
|
|
292
292
|
}) {
|
|
293
293
|
const theme = useTheme();
|
|
294
|
-
const
|
|
294
|
+
const useKeyboard23 = useKeyboardContext(useKeyboardProp);
|
|
295
295
|
const resolvedHighlight = highlightColor ?? theme.primary;
|
|
296
296
|
const isControlled = controlledValue !== void 0;
|
|
297
297
|
const controlledRef = useRef2(isControlled);
|
|
@@ -334,7 +334,7 @@ function SelectInput({
|
|
|
334
334
|
const scrollOffset = Math.max(0, Math.min(cursorRowIndex - Math.floor(visibleCount / 2), flatRows.length - visibleCount));
|
|
335
335
|
const visibleRows = flatRows.slice(scrollOffset, scrollOffset + visibleCount);
|
|
336
336
|
const diamondColor = invalid ? theme.error : disabled ? theme.muted : theme.accent;
|
|
337
|
-
|
|
337
|
+
useKeyboard23?.((event) => {
|
|
338
338
|
if (state.submitted || disabled) return;
|
|
339
339
|
if (event.name === "up" || event.name === "k") {
|
|
340
340
|
const direction = -1;
|
|
@@ -498,7 +498,7 @@ function MultiSelect({
|
|
|
498
498
|
useKeyboard: useKeyboardProp
|
|
499
499
|
}) {
|
|
500
500
|
const theme = useTheme();
|
|
501
|
-
const
|
|
501
|
+
const useKeyboard23 = useKeyboardContext(useKeyboardProp);
|
|
502
502
|
const resolvedHighlight = highlightColor ?? theme.primary;
|
|
503
503
|
const resolvedCheckbox = checkboxColor ?? theme.accent;
|
|
504
504
|
const isControlled = controlledSelected !== void 0;
|
|
@@ -554,7 +554,7 @@ function MultiSelect({
|
|
|
554
554
|
}
|
|
555
555
|
};
|
|
556
556
|
const diamondColor = invalid ? theme.error : disabled ? theme.muted : theme.accent;
|
|
557
|
-
|
|
557
|
+
useKeyboard23?.((event) => {
|
|
558
558
|
if (state.submitted || disabled) return;
|
|
559
559
|
const move = (direction) => {
|
|
560
560
|
let next = cursorRef.current + direction;
|
|
@@ -1004,9 +1004,9 @@ function Modal({
|
|
|
1004
1004
|
useKeyboard: useKeyboardProp
|
|
1005
1005
|
}) {
|
|
1006
1006
|
const theme = useTheme();
|
|
1007
|
-
const
|
|
1007
|
+
const useKeyboard23 = useKeyboardContext(useKeyboardProp);
|
|
1008
1008
|
const resolvedBorderColor = borderColor ?? theme.muted;
|
|
1009
|
-
|
|
1009
|
+
useKeyboard23?.((event) => {
|
|
1010
1010
|
if (event.name === "escape" && onClose) {
|
|
1011
1011
|
onClose();
|
|
1012
1012
|
}
|
|
@@ -1037,7 +1037,7 @@ import {
|
|
|
1037
1037
|
createContext as createContext5,
|
|
1038
1038
|
useContext as useContext5
|
|
1039
1039
|
} from "react";
|
|
1040
|
-
import {
|
|
1040
|
+
import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1041
1041
|
var PromptInputControllerCtx = createContext5(null);
|
|
1042
1042
|
var useOptionalController = () => useContext5(PromptInputControllerCtx);
|
|
1043
1043
|
var PromptInputContext = createContext5(null);
|
|
@@ -1064,10 +1064,11 @@ function resolveStatusHintText(status, submittedText, streamingText, errorText,
|
|
|
1064
1064
|
if (status === "error") return errorText;
|
|
1065
1065
|
return disabledText;
|
|
1066
1066
|
}
|
|
1067
|
-
var DIVIDER_LINE = "\u2500".repeat(500);
|
|
1068
1067
|
function PromptInputDivider() {
|
|
1069
|
-
const { theme } = usePromptInput();
|
|
1070
|
-
|
|
1068
|
+
const { dividerColor, dividerDashed, theme } = usePromptInput();
|
|
1069
|
+
const color = dividerColor ?? theme.muted;
|
|
1070
|
+
const char = dividerDashed ? "\u254C" : "\u2500";
|
|
1071
|
+
return /* @__PURE__ */ jsx16("text", { wrapMode: "none", marginLeft: -1, marginRight: -1, children: /* @__PURE__ */ jsx16("span", { style: textStyle({ dim: !dividerColor, fg: color }), children: char.repeat(500) }) });
|
|
1071
1072
|
}
|
|
1072
1073
|
function PromptInputSuggestions() {
|
|
1073
1074
|
const { suggestions, sugIdx, maxSuggestions, theme } = usePromptInput();
|
|
@@ -1082,18 +1083,25 @@ function PromptInputSuggestions() {
|
|
|
1082
1083
|
] }, sug.text);
|
|
1083
1084
|
}) });
|
|
1084
1085
|
}
|
|
1085
|
-
var CURSOR_CHAR = "\u258D";
|
|
1086
1086
|
function PromptInputTextarea() {
|
|
1087
|
-
const { value, disabled, statusHintText, placeholder, prompt, promptColor, theme } = usePromptInput();
|
|
1088
|
-
return /* @__PURE__ */ jsxs10("
|
|
1089
|
-
/* @__PURE__ */ jsx16("span", { style: textStyle({ fg: promptColor }), children: prompt }),
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1087
|
+
const { value, isFocused, disabled, statusHintText, placeholder, prompt, promptColor, theme, handleInput, handleInputSubmit, handleInputKeyDown } = usePromptInput();
|
|
1088
|
+
return /* @__PURE__ */ jsxs10("box", { flexDirection: "row", children: [
|
|
1089
|
+
/* @__PURE__ */ jsx16("text", { children: /* @__PURE__ */ jsx16("span", { style: textStyle({ fg: promptColor }), children: prompt }) }),
|
|
1090
|
+
isFocused ? /* @__PURE__ */ jsx16(
|
|
1091
|
+
"input",
|
|
1092
|
+
{
|
|
1093
|
+
value,
|
|
1094
|
+
placeholder,
|
|
1095
|
+
focused: true,
|
|
1096
|
+
onInput: handleInput,
|
|
1097
|
+
onSubmit: handleInputSubmit,
|
|
1098
|
+
onKeyDown: handleInputKeyDown,
|
|
1099
|
+
cursorColor: theme.muted,
|
|
1100
|
+
cursorStyle: { style: "line", blinking: !value },
|
|
1101
|
+
placeholderColor: theme.placeholder,
|
|
1102
|
+
textColor: theme.foreground
|
|
1103
|
+
}
|
|
1104
|
+
) : disabled && value.length === 0 ? /* @__PURE__ */ jsx16("text", { children: /* @__PURE__ */ jsx16("span", { style: textStyle({ dim: true, fg: theme.placeholder }), children: statusHintText }) }) : /* @__PURE__ */ jsx16("text", { children: /* @__PURE__ */ jsx16("span", { style: textStyle({ fg: value ? theme.foreground : theme.placeholder, dim: !value }), children: value || placeholder }) })
|
|
1097
1105
|
] });
|
|
1098
1106
|
}
|
|
1099
1107
|
function PromptInputSubmit(props) {
|
|
@@ -1140,13 +1148,16 @@ function PromptInput({
|
|
|
1140
1148
|
maxSuggestions = 5,
|
|
1141
1149
|
enableHistory = true,
|
|
1142
1150
|
model,
|
|
1151
|
+
focus = true,
|
|
1143
1152
|
showDividers = true,
|
|
1144
1153
|
autoFocus = false,
|
|
1154
|
+
dividerColor,
|
|
1155
|
+
dividerDashed,
|
|
1145
1156
|
useKeyboard: useKeyboardProp,
|
|
1146
1157
|
children
|
|
1147
1158
|
}) {
|
|
1148
1159
|
const theme = useTheme();
|
|
1149
|
-
const
|
|
1160
|
+
const useKeyboard23 = useKeyboardContext(useKeyboardProp);
|
|
1150
1161
|
useEffect2(() => {
|
|
1151
1162
|
if (!autoFocus) return;
|
|
1152
1163
|
if (typeof document === "undefined") return;
|
|
@@ -1157,6 +1168,7 @@ function PromptInput({
|
|
|
1157
1168
|
}, [autoFocus]);
|
|
1158
1169
|
const resolvedPromptColor = promptColor ?? theme.muted;
|
|
1159
1170
|
const disabled = status ? status === "submitted" || status === "streaming" : disabledProp;
|
|
1171
|
+
const isFocused = focus && !disabled;
|
|
1160
1172
|
const statusHintText = resolveStatusHintText(status, submittedText, streamingLabel, errorText, disabledText);
|
|
1161
1173
|
const controller = useOptionalController();
|
|
1162
1174
|
const usingProvider = !!controller;
|
|
@@ -1247,18 +1259,86 @@ function PromptInput({
|
|
|
1247
1259
|
clearInput();
|
|
1248
1260
|
}
|
|
1249
1261
|
}, [onSubmit, clearInput]);
|
|
1250
|
-
|
|
1262
|
+
const handleInputSubmit = (text) => {
|
|
1263
|
+
const trimmed = text.trim();
|
|
1264
|
+
if (!trimmed) return;
|
|
1265
|
+
if (enableHistory) {
|
|
1266
|
+
setHist([trimmed, ...historyRef.current]);
|
|
1267
|
+
}
|
|
1268
|
+
updateValue("");
|
|
1269
|
+
setHistI(-1);
|
|
1270
|
+
handleSubmit(trimmed);
|
|
1271
|
+
};
|
|
1272
|
+
const handleInputKeyDown = (key) => {
|
|
1273
|
+
if (key.name === "return" && suggestionsRef.current.length > 0) {
|
|
1274
|
+
const sel = suggestionsRef.current[sugIdxRef.current];
|
|
1275
|
+
if (sel) {
|
|
1276
|
+
if (valueRef.current.startsWith("/")) {
|
|
1277
|
+
updateValue("");
|
|
1278
|
+
if (enableHistory) {
|
|
1279
|
+
setHist([sel.text, ...historyRef.current]);
|
|
1280
|
+
}
|
|
1281
|
+
setHistI(-1);
|
|
1282
|
+
handleSubmit(sel.text);
|
|
1283
|
+
} else {
|
|
1284
|
+
const base = valueRef.current.slice(0, valueRef.current.lastIndexOf("@"));
|
|
1285
|
+
updateValue(base + sel.text + " ");
|
|
1286
|
+
setSug([]);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
key.preventDefault();
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
if (key.name === "tab" && suggestionsRef.current.length > 0) {
|
|
1293
|
+
setSugI((sugIdxRef.current + 1) % suggestionsRef.current.length);
|
|
1294
|
+
key.preventDefault();
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
if (key.name === "up") {
|
|
1298
|
+
if (suggestionsRef.current.length > 0) {
|
|
1299
|
+
setSugI(Math.max(0, sugIdxRef.current - 1));
|
|
1300
|
+
} else if (enableHistory && historyRef.current.length > 0) {
|
|
1301
|
+
const idx = Math.min(historyRef.current.length - 1, histIdxRef.current + 1);
|
|
1302
|
+
setHistI(idx);
|
|
1303
|
+
updateValue(historyRef.current[idx]);
|
|
1304
|
+
}
|
|
1305
|
+
key.preventDefault();
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
if (key.name === "down") {
|
|
1309
|
+
if (suggestionsRef.current.length > 0) {
|
|
1310
|
+
setSugI(Math.min(suggestionsRef.current.length - 1, sugIdxRef.current + 1));
|
|
1311
|
+
} else if (enableHistory && histIdxRef.current > 0) {
|
|
1312
|
+
const nextIdx = histIdxRef.current - 1;
|
|
1313
|
+
setHistI(nextIdx);
|
|
1314
|
+
updateValue(historyRef.current[nextIdx]);
|
|
1315
|
+
} else if (enableHistory && histIdxRef.current === 0) {
|
|
1316
|
+
setHistI(-1);
|
|
1317
|
+
updateValue("");
|
|
1318
|
+
}
|
|
1319
|
+
key.preventDefault();
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
if (key.name === "escape") {
|
|
1323
|
+
if (suggestionsRef.current.length > 0) {
|
|
1324
|
+
setSug([]);
|
|
1325
|
+
key.preventDefault();
|
|
1326
|
+
}
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
useKeyboard23?.((event) => {
|
|
1251
1331
|
if (event.name === "escape" && (status === "streaming" || status === "submitted") && onStop) {
|
|
1252
1332
|
onStop();
|
|
1253
1333
|
return;
|
|
1254
1334
|
}
|
|
1335
|
+
if (isFocused) return;
|
|
1255
1336
|
if (disabled) return;
|
|
1256
1337
|
if (event.name === "return") {
|
|
1257
1338
|
if (suggestionsRef.current.length > 0) {
|
|
1258
1339
|
const sel = suggestionsRef.current[sugIdxRef.current];
|
|
1259
1340
|
if (sel) {
|
|
1260
1341
|
if (valueRef.current.startsWith("/")) {
|
|
1261
|
-
setSug([]);
|
|
1262
1342
|
updateValue("");
|
|
1263
1343
|
if (enableHistory) {
|
|
1264
1344
|
setHist([sel.text, ...historyRef.current]);
|
|
@@ -1279,7 +1359,6 @@ function PromptInput({
|
|
|
1279
1359
|
}
|
|
1280
1360
|
updateValue("");
|
|
1281
1361
|
setHistI(-1);
|
|
1282
|
-
setSug([]);
|
|
1283
1362
|
handleSubmit(trimmed);
|
|
1284
1363
|
}
|
|
1285
1364
|
return;
|
|
@@ -1333,6 +1412,7 @@ function PromptInput({
|
|
|
1333
1412
|
const visibleSuggestions = suggestions.slice(0, maxSuggestions);
|
|
1334
1413
|
const ctxValue = {
|
|
1335
1414
|
value,
|
|
1415
|
+
isFocused,
|
|
1336
1416
|
disabled,
|
|
1337
1417
|
status,
|
|
1338
1418
|
onStop,
|
|
@@ -1345,7 +1425,12 @@ function PromptInput({
|
|
|
1345
1425
|
maxSuggestions,
|
|
1346
1426
|
errorText,
|
|
1347
1427
|
model,
|
|
1348
|
-
|
|
1428
|
+
dividerColor,
|
|
1429
|
+
dividerDashed,
|
|
1430
|
+
theme,
|
|
1431
|
+
handleInput: updateValue,
|
|
1432
|
+
handleInputSubmit,
|
|
1433
|
+
handleInputKeyDown
|
|
1349
1434
|
};
|
|
1350
1435
|
if (children) {
|
|
1351
1436
|
return /* @__PURE__ */ jsx16(PromptInputContext.Provider, { value: ctxValue, children: /* @__PURE__ */ jsx16("box", { flexDirection: "column", flexShrink: 0, children }) });
|
|
@@ -1438,6 +1523,7 @@ function ChatPanel({
|
|
|
1438
1523
|
userColor,
|
|
1439
1524
|
assistantColor,
|
|
1440
1525
|
loadingText = "Thinking...",
|
|
1526
|
+
focus,
|
|
1441
1527
|
useKeyboard: useKeyboardProp
|
|
1442
1528
|
}) {
|
|
1443
1529
|
const theme = useTheme();
|
|
@@ -1483,6 +1569,7 @@ function ChatPanel({
|
|
|
1483
1569
|
promptColor: resolvedPromptColor,
|
|
1484
1570
|
foregroundColor: theme.foreground,
|
|
1485
1571
|
submittedText: loadingText,
|
|
1572
|
+
focus,
|
|
1486
1573
|
useKeyboard: useKeyboardProp
|
|
1487
1574
|
}
|
|
1488
1575
|
) })
|
|
@@ -1491,7 +1578,7 @@ function ChatPanel({
|
|
|
1491
1578
|
|
|
1492
1579
|
// ../ui/components/chain-of-thought/chain-of-thought.tsx
|
|
1493
1580
|
import { createContext as createContext6, memo, useContext as useContext6, useEffect as useEffect3, useMemo as useMemo4, useState as useState7 } from "react";
|
|
1494
|
-
import { Fragment as
|
|
1581
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1495
1582
|
var DOTS = ["\u25CB", "\u25D4", "\u25D1", "\u25D5", "\u25CF"];
|
|
1496
1583
|
var SPINNER_INTERVAL = 150;
|
|
1497
1584
|
var ChainOfThoughtContext = createContext6(null);
|
|
@@ -1550,7 +1637,7 @@ var ChainOfThoughtHeader = memo(({
|
|
|
1550
1637
|
var ChainOfThoughtContent = memo(({ children }) => {
|
|
1551
1638
|
const { isOpen } = useChainOfThought();
|
|
1552
1639
|
if (!isOpen) return null;
|
|
1553
|
-
return /* @__PURE__ */ jsx18(
|
|
1640
|
+
return /* @__PURE__ */ jsx18(Fragment5, { children });
|
|
1554
1641
|
});
|
|
1555
1642
|
var ChainOfThoughtStep = memo(({
|
|
1556
1643
|
label,
|
|
@@ -1854,18 +1941,15 @@ function TableApp() {
|
|
|
1854
1941
|
|
|
1855
1942
|
// demos/spinner.tsx
|
|
1856
1943
|
import { useKeyboard as useKeyboard3 } from "@gridland/utils";
|
|
1857
|
-
import { jsx as jsx24
|
|
1944
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1858
1945
|
function SpinnerApp() {
|
|
1859
|
-
return /* @__PURE__ */
|
|
1860
|
-
/* @__PURE__ */ jsx24("box", { flexGrow: 1, children: /* @__PURE__ */ jsx24(SpinnerPicker, { useKeyboard: useKeyboard3 }) }),
|
|
1861
|
-
/* @__PURE__ */ jsx24("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx24(StatusBar, { items: [{ key: "\u2190\u2192", label: "change variant" }] }) })
|
|
1862
|
-
] });
|
|
1946
|
+
return /* @__PURE__ */ jsx24("box", { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx24(SpinnerPicker, { useKeyboard: useKeyboard3 }) });
|
|
1863
1947
|
}
|
|
1864
1948
|
|
|
1865
1949
|
// demos/select-input.tsx
|
|
1866
1950
|
import { useState as useState10 } from "react";
|
|
1867
1951
|
import { useKeyboard as useKeyboard4 } from "@gridland/utils";
|
|
1868
|
-
import { jsx as jsx25, jsxs as
|
|
1952
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1869
1953
|
var items = [
|
|
1870
1954
|
{ label: "TypeScript", value: "ts" },
|
|
1871
1955
|
{ label: "JavaScript", value: "js" },
|
|
@@ -1881,7 +1965,7 @@ function SelectInputApp() {
|
|
|
1881
1965
|
setResetKey((k) => k + 1);
|
|
1882
1966
|
}
|
|
1883
1967
|
});
|
|
1884
|
-
return /* @__PURE__ */
|
|
1968
|
+
return /* @__PURE__ */ jsxs17("box", { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
1885
1969
|
/* @__PURE__ */ jsx25("box", { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx25(
|
|
1886
1970
|
SelectInput,
|
|
1887
1971
|
{
|
|
@@ -1902,7 +1986,7 @@ function SelectInputApp() {
|
|
|
1902
1986
|
// demos/multi-select.tsx
|
|
1903
1987
|
import { useState as useState11 } from "react";
|
|
1904
1988
|
import { useKeyboard as useKeyboard5 } from "@gridland/utils";
|
|
1905
|
-
import { jsx as jsx26, jsxs as
|
|
1989
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1906
1990
|
var items2 = [
|
|
1907
1991
|
{ label: "TypeScript", value: "ts" },
|
|
1908
1992
|
{ label: "JavaScript", value: "js" },
|
|
@@ -1918,7 +2002,7 @@ function MultiSelectApp() {
|
|
|
1918
2002
|
setResetKey((k) => k + 1);
|
|
1919
2003
|
}
|
|
1920
2004
|
});
|
|
1921
|
-
return /* @__PURE__ */
|
|
2005
|
+
return /* @__PURE__ */ jsxs18("box", { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
1922
2006
|
/* @__PURE__ */ jsx26("box", { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx26(
|
|
1923
2007
|
MultiSelect,
|
|
1924
2008
|
{
|
|
@@ -1941,7 +2025,7 @@ function MultiSelectApp() {
|
|
|
1941
2025
|
// demos/prompt-input.tsx
|
|
1942
2026
|
import { useState as useState12 } from "react";
|
|
1943
2027
|
import { useKeyboard as useKeyboard6 } from "@gridland/utils";
|
|
1944
|
-
import { jsx as jsx27, jsxs as
|
|
2028
|
+
import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1945
2029
|
var commands = [{ cmd: "/model", desc: "Switch model" }];
|
|
1946
2030
|
var files = ["src/index.ts", "src/routes.ts", "src/auth.ts", "package.json"];
|
|
1947
2031
|
var models = [
|
|
@@ -1977,8 +2061,8 @@ function PromptInputApp() {
|
|
|
1977
2061
|
}
|
|
1978
2062
|
) }) }) });
|
|
1979
2063
|
}
|
|
1980
|
-
return /* @__PURE__ */
|
|
1981
|
-
/* @__PURE__ */ jsx27("box", { flexDirection: "column", flexGrow: 1, children: lastMessage ? /* @__PURE__ */
|
|
2064
|
+
return /* @__PURE__ */ jsxs19("box", { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
2065
|
+
/* @__PURE__ */ jsx27("box", { flexDirection: "column", flexGrow: 1, children: lastMessage ? /* @__PURE__ */ jsxs19("text", { children: [
|
|
1982
2066
|
/* @__PURE__ */ jsx27("span", { style: textStyle({ fg: theme.muted }), children: "Sent: " }),
|
|
1983
2067
|
/* @__PURE__ */ jsx27("span", { style: textStyle({ fg: theme.foreground }), children: lastMessage })
|
|
1984
2068
|
] }) : /* @__PURE__ */ jsx27("text", { children: /* @__PURE__ */ jsx27("span", { children: " " }) }) }),
|
|
@@ -1989,6 +2073,7 @@ function PromptInputApp() {
|
|
|
1989
2073
|
files,
|
|
1990
2074
|
placeholder: "Message Claude...",
|
|
1991
2075
|
showDividers: true,
|
|
2076
|
+
autoFocus: true,
|
|
1992
2077
|
useKeyboard: useKeyboard6,
|
|
1993
2078
|
onSubmit: handleSubmit
|
|
1994
2079
|
},
|
|
@@ -2006,7 +2091,7 @@ function PromptInputApp() {
|
|
|
2006
2091
|
// demos/text-input.tsx
|
|
2007
2092
|
import { useState as useState13 } from "react";
|
|
2008
2093
|
import { useKeyboard as useKeyboard7 } from "@gridland/utils";
|
|
2009
|
-
import { jsx as jsx28, jsxs as
|
|
2094
|
+
import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2010
2095
|
var FIELDS = [
|
|
2011
2096
|
{ label: "Username", placeholder: "enter your name", maxLength: 30, required: true },
|
|
2012
2097
|
{ label: "Email", placeholder: "user@example.com", maxLength: 50, required: true, description: "We'll never share your email" },
|
|
@@ -2020,7 +2105,7 @@ function TextInputApp() {
|
|
|
2020
2105
|
if (event.name === "up") setActiveField((i) => Math.max(0, i - 1));
|
|
2021
2106
|
if (event.name === "down") setActiveField((i) => Math.min(FIELDS.length - 1, i + 1));
|
|
2022
2107
|
});
|
|
2023
|
-
return /* @__PURE__ */
|
|
2108
|
+
return /* @__PURE__ */ jsxs20("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2024
2109
|
/* @__PURE__ */ jsx28("box", { flexDirection: "column", paddingX: 1, paddingTop: 1, flexGrow: 1, children: FIELDS.map((field, i) => /* @__PURE__ */ jsx28("box", { marginBottom: 1, children: /* @__PURE__ */ jsx28(
|
|
2025
2110
|
TextInput,
|
|
2026
2111
|
{
|
|
@@ -2043,7 +2128,7 @@ function TextInputApp() {
|
|
|
2043
2128
|
// demos/link.tsx
|
|
2044
2129
|
import { useState as useState14 } from "react";
|
|
2045
2130
|
import { useKeyboard as useKeyboard8 } from "@gridland/utils";
|
|
2046
|
-
import { jsx as jsx29, jsxs as
|
|
2131
|
+
import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2047
2132
|
var MODES = ["solid", "dashed", "dotted", "none"];
|
|
2048
2133
|
function LinkApp() {
|
|
2049
2134
|
const theme = useTheme();
|
|
@@ -2053,8 +2138,8 @@ function LinkApp() {
|
|
|
2053
2138
|
if (event.name === "right") setModeIndex((i) => (i + 1) % MODES.length);
|
|
2054
2139
|
if (event.name === "left") setModeIndex((i) => (i - 1 + MODES.length) % MODES.length);
|
|
2055
2140
|
});
|
|
2056
|
-
return /* @__PURE__ */
|
|
2057
|
-
/* @__PURE__ */ jsx29("box", { padding: 1, flexGrow: 1, children: /* @__PURE__ */
|
|
2141
|
+
return /* @__PURE__ */ jsxs21("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2142
|
+
/* @__PURE__ */ jsx29("box", { padding: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs21("text", { style: textStyle({ fg: theme.foreground }), children: [
|
|
2058
2143
|
"Made by ",
|
|
2059
2144
|
/* @__PURE__ */ jsx29("a", { href: "https://cjroth.com", style: { attributes: mode === "solid" ? 8 : mode === "dashed" ? 24 : mode === "dotted" ? 72 : 0, fg: theme.accent }, children: "Chris Roth" }),
|
|
2060
2145
|
" and ",
|
|
@@ -2074,7 +2159,7 @@ function LinkApp() {
|
|
|
2074
2159
|
// demos/tabs.tsx
|
|
2075
2160
|
import { useState as useState15 } from "react";
|
|
2076
2161
|
import { useKeyboard as useKeyboard9 } from "@gridland/utils";
|
|
2077
|
-
import { jsx as jsx30, jsxs as
|
|
2162
|
+
import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2078
2163
|
var tabs = ["Files", "Search", "Git", "Debug"];
|
|
2079
2164
|
function TabBarApp() {
|
|
2080
2165
|
const [selectedIndex, setSelectedIndex] = useState15(0);
|
|
@@ -2082,7 +2167,7 @@ function TabBarApp() {
|
|
|
2082
2167
|
if (event.name === "left") setSelectedIndex((i) => i > 0 ? i - 1 : tabs.length - 1);
|
|
2083
2168
|
if (event.name === "right") setSelectedIndex((i) => i < tabs.length - 1 ? i + 1 : 0);
|
|
2084
2169
|
});
|
|
2085
|
-
return /* @__PURE__ */
|
|
2170
|
+
return /* @__PURE__ */ jsxs22("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2086
2171
|
/* @__PURE__ */ jsx30("box", { padding: 1, children: /* @__PURE__ */ jsx30(TabBar, { options: tabs, selectedIndex }) }),
|
|
2087
2172
|
/* @__PURE__ */ jsx30("box", { flexGrow: 1 }),
|
|
2088
2173
|
/* @__PURE__ */ jsx30("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx30(StatusBar, { items: [{ key: "\u2190\u2192", label: "switch tab" }] }) })
|
|
@@ -2092,7 +2177,7 @@ function TabBarApp() {
|
|
|
2092
2177
|
// demos/status-bar.tsx
|
|
2093
2178
|
import { useState as useState16 } from "react";
|
|
2094
2179
|
import { useKeyboard as useKeyboard10 } from "@gridland/utils";
|
|
2095
|
-
import { jsx as jsx31, jsxs as
|
|
2180
|
+
import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2096
2181
|
var shortcuts = [
|
|
2097
2182
|
{ key: "Tab", label: "switch focus" },
|
|
2098
2183
|
{ key: "\u2190\u2192", label: "cycle" },
|
|
@@ -2109,8 +2194,8 @@ function StatusBarApp() {
|
|
|
2109
2194
|
else if (event.name === "b") setLastKey("back (b)");
|
|
2110
2195
|
else if (event.name === "z") setLastKey("reset (z)");
|
|
2111
2196
|
});
|
|
2112
|
-
return /* @__PURE__ */
|
|
2113
|
-
lastKey ? /* @__PURE__ */
|
|
2197
|
+
return /* @__PURE__ */ jsxs23("box", { flexDirection: "column", gap: 1, padding: 1, children: [
|
|
2198
|
+
lastKey ? /* @__PURE__ */ jsxs23("text", { children: [
|
|
2114
2199
|
/* @__PURE__ */ jsx31("span", { children: "Pressed: " }),
|
|
2115
2200
|
/* @__PURE__ */ jsx31("span", { style: textStyle({ bold: true, fg: theme.accent }), children: lastKey })
|
|
2116
2201
|
] }) : /* @__PURE__ */ jsx31("text", { style: textStyle({ dim: true }), children: "Press a key to trigger an action" }),
|
|
@@ -2127,7 +2212,7 @@ function StatusBarApp() {
|
|
|
2127
2212
|
// demos/modal.tsx
|
|
2128
2213
|
import { useState as useState17 } from "react";
|
|
2129
2214
|
import { useKeyboard as useKeyboard11 } from "@gridland/utils";
|
|
2130
|
-
import { jsx as jsx32, jsxs as
|
|
2215
|
+
import { jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2131
2216
|
function ModalApp() {
|
|
2132
2217
|
const theme = useTheme();
|
|
2133
2218
|
const [isOpen, setIsOpen] = useState17(false);
|
|
@@ -2136,8 +2221,8 @@ function ModalApp() {
|
|
|
2136
2221
|
if (isOpen && (event.name === "q" || event.name === "escape")) setIsOpen(false);
|
|
2137
2222
|
});
|
|
2138
2223
|
if (isOpen) {
|
|
2139
|
-
return /* @__PURE__ */
|
|
2140
|
-
/* @__PURE__ */ jsx32(Modal, { title: "Example Modal", useKeyboard: useKeyboard11, onClose: () => setIsOpen(false), children: /* @__PURE__ */
|
|
2224
|
+
return /* @__PURE__ */ jsxs24("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2225
|
+
/* @__PURE__ */ jsx32(Modal, { title: "Example Modal", useKeyboard: useKeyboard11, onClose: () => setIsOpen(false), children: /* @__PURE__ */ jsxs24("box", { paddingX: 1, flexDirection: "column", children: [
|
|
2141
2226
|
/* @__PURE__ */ jsx32("text", { style: textStyle({ fg: theme.foreground }), children: "This is a modal overlay component." }),
|
|
2142
2227
|
/* @__PURE__ */ jsx32("text", { children: " " }),
|
|
2143
2228
|
/* @__PURE__ */ jsx32("text", { style: textStyle({ dim: true, fg: theme.muted }), children: "It stretches to fill the full terminal height." })
|
|
@@ -2145,7 +2230,7 @@ function ModalApp() {
|
|
|
2145
2230
|
/* @__PURE__ */ jsx32("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx32(StatusBar, { items: [{ key: "q", label: "close" }] }) })
|
|
2146
2231
|
] });
|
|
2147
2232
|
}
|
|
2148
|
-
return /* @__PURE__ */ jsx32("box", { flexDirection: "column", flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */
|
|
2233
|
+
return /* @__PURE__ */ jsx32("box", { flexDirection: "column", flexGrow: 1, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ jsxs24("text", { children: [
|
|
2149
2234
|
/* @__PURE__ */ jsx32("span", { style: textStyle({ dim: true, fg: theme.muted }), children: "Press " }),
|
|
2150
2235
|
/* @__PURE__ */ jsx32("span", { style: textStyle({ bold: true, fg: theme.background, bg: theme.muted }), children: " m " }),
|
|
2151
2236
|
/* @__PURE__ */ jsx32("span", { style: textStyle({ dim: true, fg: theme.muted }), children: " to open modal" })
|
|
@@ -2153,9 +2238,9 @@ function ModalApp() {
|
|
|
2153
2238
|
}
|
|
2154
2239
|
|
|
2155
2240
|
// demos/primitives.tsx
|
|
2156
|
-
import { jsx as jsx33, jsxs as
|
|
2241
|
+
import { jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2157
2242
|
function PrimitivesApp() {
|
|
2158
|
-
return /* @__PURE__ */
|
|
2243
|
+
return /* @__PURE__ */ jsxs25("box", { flexDirection: "column", padding: 1, children: [
|
|
2159
2244
|
/* @__PURE__ */ jsx33(
|
|
2160
2245
|
"box",
|
|
2161
2246
|
{
|
|
@@ -2165,7 +2250,7 @@ function PrimitivesApp() {
|
|
|
2165
2250
|
title: "Layout",
|
|
2166
2251
|
titleAlignment: "center",
|
|
2167
2252
|
padding: 1,
|
|
2168
|
-
children: /* @__PURE__ */
|
|
2253
|
+
children: /* @__PURE__ */ jsxs25("box", { flexDirection: "row", gap: 2, children: [
|
|
2169
2254
|
/* @__PURE__ */ jsx33("box", { border: true, borderStyle: "single", borderColor: "#a6e22e", padding: 1, flexGrow: 1, children: /* @__PURE__ */ jsx33("text", { fg: "#a6e22e", bold: true, children: "Box 1" }) }),
|
|
2170
2255
|
/* @__PURE__ */ jsx33("box", { border: true, borderStyle: "single", borderColor: "#f92672", padding: 1, flexGrow: 1, children: /* @__PURE__ */ jsx33("text", { fg: "#f92672", bold: true, children: "Box 2" }) }),
|
|
2171
2256
|
/* @__PURE__ */ jsx33("box", { border: true, borderStyle: "single", borderColor: "#66d9ef", padding: 1, flexGrow: 1, children: /* @__PURE__ */ jsx33("text", { fg: "#66d9ef", bold: true, children: "Box 3" }) })
|
|
@@ -2248,7 +2333,7 @@ function ChatApp() {
|
|
|
2248
2333
|
// demos/chain-of-thought.tsx
|
|
2249
2334
|
import { useState as useState19, useEffect as useEffect4, useRef as useRef6 } from "react";
|
|
2250
2335
|
import { useKeyboard as useKeyboard13 } from "@gridland/utils";
|
|
2251
|
-
import { jsx as jsx35, jsxs as
|
|
2336
|
+
import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2252
2337
|
var ALL_STEPS = [
|
|
2253
2338
|
{ tool: "Read", label: "Reading codebase", description: "src/", status: "done", delay: 1800 },
|
|
2254
2339
|
{ tool: "Think", label: "Planning changes", description: "auth module", status: "done", delay: 2500 },
|
|
@@ -2298,8 +2383,8 @@ function ChainOfThoughtApp() {
|
|
|
2298
2383
|
const elapsedMs = ALL_STEPS.slice(0, stepIndex).reduce((sum, s) => sum + s.delay, 0);
|
|
2299
2384
|
const totalMs = ALL_STEPS.reduce((sum, s) => sum + s.delay, 0);
|
|
2300
2385
|
const durationStr = phase === "done" ? `${(totalMs / 1e3).toFixed(1)}s` : `${(elapsedMs / 1e3).toFixed(1)}s`;
|
|
2301
|
-
return /* @__PURE__ */
|
|
2302
|
-
/* @__PURE__ */ jsx35("box", { flexDirection: "column", padding: 1, flexGrow: 1, children: /* @__PURE__ */
|
|
2386
|
+
return /* @__PURE__ */ jsxs26("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2387
|
+
/* @__PURE__ */ jsx35("box", { flexDirection: "column", padding: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs26(ChainOfThought, { open: expanded, onOpenChange: setExpanded, children: [
|
|
2303
2388
|
/* @__PURE__ */ jsx35(ChainOfThoughtHeader, { duration: durationStr }),
|
|
2304
2389
|
/* @__PURE__ */ jsx35(ChainOfThoughtContent, { children: steps.map((step, i) => /* @__PURE__ */ jsx35(
|
|
2305
2390
|
ChainOfThoughtStep,
|
|
@@ -2323,7 +2408,7 @@ function ChainOfThoughtApp() {
|
|
|
2323
2408
|
// demos/message.tsx
|
|
2324
2409
|
import { useState as useState20, useEffect as useEffect5, useRef as useRef7 } from "react";
|
|
2325
2410
|
import { useKeyboard as useKeyboard14 } from "@gridland/utils";
|
|
2326
|
-
import { jsx as jsx36, jsxs as
|
|
2411
|
+
import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2327
2412
|
var RESPONSE = "I've refactored the auth module. The changes include extracting the token validation into a shared helper, consolidating the middleware chain, and updating the test suite to match.";
|
|
2328
2413
|
function MessageApp() {
|
|
2329
2414
|
const [phase, setPhase] = useState20("idle");
|
|
@@ -2369,8 +2454,8 @@ function MessageApp() {
|
|
|
2369
2454
|
const isStreaming = phase === "streaming";
|
|
2370
2455
|
const isDone = phase === "done";
|
|
2371
2456
|
const showAssistant = phase !== "idle";
|
|
2372
|
-
return /* @__PURE__ */
|
|
2373
|
-
/* @__PURE__ */
|
|
2457
|
+
return /* @__PURE__ */ jsxs27("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2458
|
+
/* @__PURE__ */ jsxs27("box", { flexDirection: "column", padding: 1, gap: 1, flexGrow: 1, children: [
|
|
2374
2459
|
/* @__PURE__ */ jsx36(Message, { role: "user", children: /* @__PURE__ */ jsx36(Message.Content, { children: /* @__PURE__ */ jsx36(Message.Text, { children: "Can you refactor the auth module?" }) }) }),
|
|
2375
2460
|
showAssistant && /* @__PURE__ */ jsx36(Message, { role: "assistant", isStreaming, children: /* @__PURE__ */ jsx36(Message.Content, { children: /* @__PURE__ */ jsx36(Message.Text, { isLast: true, children: isDone ? RESPONSE : streamedText }) }) })
|
|
2376
2461
|
] }),
|
|
@@ -2379,10 +2464,10 @@ function MessageApp() {
|
|
|
2379
2464
|
}
|
|
2380
2465
|
|
|
2381
2466
|
// demos/terminal-window.tsx
|
|
2382
|
-
import { jsx as jsx37, jsxs as
|
|
2467
|
+
import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2383
2468
|
function TerminalWindowApp() {
|
|
2384
2469
|
const theme = useTheme();
|
|
2385
|
-
return /* @__PURE__ */
|
|
2470
|
+
return /* @__PURE__ */ jsxs28("box", { flexDirection: "column", padding: 1, children: [
|
|
2386
2471
|
/* @__PURE__ */ jsx37("text", { style: textStyle({ fg: theme.secondary }), children: '$ echo "Hello from TerminalWindow"' }),
|
|
2387
2472
|
/* @__PURE__ */ jsx37("text", { style: textStyle({ fg: theme.foreground }), children: "Hello from TerminalWindow" }),
|
|
2388
2473
|
/* @__PURE__ */ jsx37("text", { style: textStyle({ fg: theme.secondary }), children: "$ _" })
|
|
@@ -2390,28 +2475,33 @@ function TerminalWindowApp() {
|
|
|
2390
2475
|
}
|
|
2391
2476
|
|
|
2392
2477
|
// demos/focus.tsx
|
|
2393
|
-
import {
|
|
2394
|
-
import { useKeyboard as useKeyboard15 } from "@gridland/utils";
|
|
2395
|
-
import {
|
|
2396
|
-
var
|
|
2478
|
+
import { useRef as useRef8, useCallback as useCallback4 } from "react";
|
|
2479
|
+
import { useKeyboard as useKeyboard15, useFocus, FocusProvider, useShortcuts, useFocusedShortcuts } from "@gridland/utils";
|
|
2480
|
+
import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2481
|
+
var focusMultiSelects = [
|
|
2397
2482
|
{
|
|
2398
|
-
|
|
2483
|
+
id: "language",
|
|
2484
|
+
title: "Language",
|
|
2399
2485
|
items: [
|
|
2400
2486
|
{ label: "TypeScript", value: "ts" },
|
|
2401
2487
|
{ label: "JavaScript", value: "js" },
|
|
2402
|
-
{ label: "Python", value: "py" }
|
|
2488
|
+
{ label: "Python", value: "py" },
|
|
2489
|
+
{ label: "Rust", value: "rs" }
|
|
2403
2490
|
]
|
|
2404
2491
|
},
|
|
2405
2492
|
{
|
|
2406
|
-
|
|
2493
|
+
id: "framework",
|
|
2494
|
+
title: "Framework",
|
|
2407
2495
|
items: [
|
|
2408
2496
|
{ label: "React", value: "react" },
|
|
2409
2497
|
{ label: "Vue", value: "vue" },
|
|
2410
|
-
{ label: "Svelte", value: "svelte" }
|
|
2498
|
+
{ label: "Svelte", value: "svelte" },
|
|
2499
|
+
{ label: "Solid", value: "solid" }
|
|
2411
2500
|
]
|
|
2412
2501
|
},
|
|
2413
2502
|
{
|
|
2414
|
-
|
|
2503
|
+
id: "runtime",
|
|
2504
|
+
title: "Runtime",
|
|
2415
2505
|
items: [
|
|
2416
2506
|
{ label: "Bun", value: "bun" },
|
|
2417
2507
|
{ label: "Node", value: "node" },
|
|
@@ -2419,118 +2509,168 @@ var focusPanels = [
|
|
|
2419
2509
|
]
|
|
2420
2510
|
}
|
|
2421
2511
|
];
|
|
2422
|
-
function
|
|
2423
|
-
const
|
|
2424
|
-
const
|
|
2425
|
-
const
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
const enteredRef = useRef8(false);
|
|
2429
|
-
const cursorsRef = useRef8([0, 0, 0]);
|
|
2430
|
-
panelRef.current = panelIndex;
|
|
2431
|
-
enteredRef.current = entered;
|
|
2432
|
-
cursorsRef.current = cursors;
|
|
2512
|
+
function FocusMultiSelectPanel({ id, title, items: items3, autoFocus }) {
|
|
2513
|
+
const { isFocused, isSelected, isAnySelected, focusId, focusRef } = useFocus({ id, autoFocus });
|
|
2514
|
+
const multiSelectHandlerRef = useRef8(null);
|
|
2515
|
+
const captureKeyboard = useCallback4((handler) => {
|
|
2516
|
+
multiSelectHandlerRef.current = handler;
|
|
2517
|
+
}, []);
|
|
2433
2518
|
useKeyboard15((event) => {
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
return n;
|
|
2454
|
-
});
|
|
2455
|
-
enteredRef.current = false;
|
|
2456
|
-
setEntered(false);
|
|
2457
|
-
} else if (event.name === "escape") {
|
|
2458
|
-
enteredRef.current = false;
|
|
2459
|
-
setEntered(false);
|
|
2460
|
-
}
|
|
2461
|
-
} else {
|
|
2462
|
-
if (event.name === "right" || event.name === "tab") {
|
|
2463
|
-
const next = (pi + 1) % focusPanels.length;
|
|
2464
|
-
panelRef.current = next;
|
|
2465
|
-
setPanelIndex(next);
|
|
2466
|
-
} else if (event.name === "left") {
|
|
2467
|
-
const next = (pi - 1 + focusPanels.length) % focusPanels.length;
|
|
2468
|
-
panelRef.current = next;
|
|
2469
|
-
setPanelIndex(next);
|
|
2470
|
-
} else if (event.name === "return") {
|
|
2471
|
-
enteredRef.current = true;
|
|
2472
|
-
setEntered(true);
|
|
2473
|
-
}
|
|
2519
|
+
multiSelectHandlerRef.current?.(event);
|
|
2520
|
+
}, { focusId, selectedOnly: true });
|
|
2521
|
+
useShortcuts(
|
|
2522
|
+
isSelected ? [{ key: "\u2191\u2193", label: "move" }, { key: "enter", label: "toggle" }, { key: "esc", label: "back" }] : [{ key: "\u2190\u2192", label: "navigate" }, { key: "tab", label: "cycle" }, { key: "enter", label: "select" }],
|
|
2523
|
+
focusId
|
|
2524
|
+
);
|
|
2525
|
+
const borderStyle = isSelected ? "rounded" : isFocused ? "dashed" : "rounded";
|
|
2526
|
+
const borderColor = isSelected ? "#818cf8" : isAnySelected ? "transparent" : isFocused ? "#6366f1" : "#3b3466";
|
|
2527
|
+
return /* @__PURE__ */ jsx38("box", { ref: focusRef, border: true, borderStyle, borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx38("box", { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx38(
|
|
2528
|
+
MultiSelect,
|
|
2529
|
+
{
|
|
2530
|
+
items: items3,
|
|
2531
|
+
title,
|
|
2532
|
+
allowEmpty: true,
|
|
2533
|
+
enableSelectAll: false,
|
|
2534
|
+
enableClear: false,
|
|
2535
|
+
highlightColor: isSelected ? "#a5b4fc" : "#6366f1",
|
|
2536
|
+
checkboxColor: "#818cf8",
|
|
2537
|
+
useKeyboard: captureKeyboard
|
|
2474
2538
|
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
border: true,
|
|
2486
|
-
borderStyle: "rounded",
|
|
2487
|
-
borderColor: active ? "#22c55e" : focused ? "#3b82f6" : "#555",
|
|
2488
|
-
flexGrow: 1,
|
|
2489
|
-
children: /* @__PURE__ */ jsxs30("box", { flexDirection: "column", padding: 1, children: [
|
|
2490
|
-
/* @__PURE__ */ jsxs30("text", { style: {
|
|
2491
|
-
fg: active ? "#22c55e" : focused ? "#3b82f6" : "#888",
|
|
2492
|
-
bold: focused
|
|
2493
|
-
}, children: [
|
|
2494
|
-
focused ? "\u25B8 " : " ",
|
|
2495
|
-
panel.label,
|
|
2496
|
-
selected ? `: ${selected}` : ""
|
|
2497
|
-
] }),
|
|
2498
|
-
(active || !entered && focused) && /* @__PURE__ */ jsxs30(Fragment7, { children: [
|
|
2499
|
-
/* @__PURE__ */ jsx38("box", { height: 1 }),
|
|
2500
|
-
/* @__PURE__ */ jsx38("box", { flexDirection: "column", children: panel.items.map((item, j) => {
|
|
2501
|
-
const highlighted = active && j === cursors[i];
|
|
2502
|
-
return /* @__PURE__ */ jsxs30("text", { style: {
|
|
2503
|
-
fg: highlighted ? "#22c55e" : active ? "#ccc" : "#666",
|
|
2504
|
-
bold: highlighted
|
|
2505
|
-
}, children: [
|
|
2506
|
-
highlighted ? " \u25B8 " : " ",
|
|
2507
|
-
item.label
|
|
2508
|
-
] }, item.value);
|
|
2509
|
-
}) })
|
|
2510
|
-
] })
|
|
2511
|
-
] })
|
|
2512
|
-
},
|
|
2513
|
-
panel.label
|
|
2514
|
-
);
|
|
2515
|
-
}) }),
|
|
2516
|
-
/* @__PURE__ */ jsx38("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx38(
|
|
2517
|
-
StatusBar,
|
|
2539
|
+
) }) });
|
|
2540
|
+
}
|
|
2541
|
+
function FocusNavStatusBar() {
|
|
2542
|
+
const shortcuts2 = useFocusedShortcuts();
|
|
2543
|
+
return /* @__PURE__ */ jsx38("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx38(StatusBar, { items: shortcuts2 }) });
|
|
2544
|
+
}
|
|
2545
|
+
function FocusApp() {
|
|
2546
|
+
return /* @__PURE__ */ jsx38(FocusProvider, { selectable: true, children: /* @__PURE__ */ jsxs29("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2547
|
+
/* @__PURE__ */ jsx38("box", { flexDirection: "row", gap: 1, padding: 1, flexGrow: 1, children: focusMultiSelects.map((panel, i) => /* @__PURE__ */ jsx38(
|
|
2548
|
+
FocusMultiSelectPanel,
|
|
2518
2549
|
{
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2550
|
+
id: panel.id,
|
|
2551
|
+
title: panel.title,
|
|
2552
|
+
items: panel.items,
|
|
2553
|
+
autoFocus: i === 0
|
|
2554
|
+
},
|
|
2555
|
+
panel.id
|
|
2556
|
+
)) }),
|
|
2557
|
+
/* @__PURE__ */ jsx38(FocusNavStatusBar, {})
|
|
2558
|
+
] }) });
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
// demos/focus-grid.tsx
|
|
2562
|
+
import { useFocus as useFocus2, FocusProvider as FocusProvider2, useShortcuts as useShortcuts2, useFocusedShortcuts as useFocusedShortcuts2 } from "@gridland/utils";
|
|
2563
|
+
import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2564
|
+
var gridItems = [
|
|
2565
|
+
{ id: "cell-1" },
|
|
2566
|
+
{ id: "cell-2" },
|
|
2567
|
+
{ id: "cell-3" },
|
|
2568
|
+
{ id: "cell-4" },
|
|
2569
|
+
{ id: "cell-5" },
|
|
2570
|
+
{ id: "cell-6" }
|
|
2571
|
+
];
|
|
2572
|
+
function GridCell({ id, autoFocus }) {
|
|
2573
|
+
const { isFocused, isSelected, isAnySelected, focusId, focusRef } = useFocus2({ id, autoFocus });
|
|
2574
|
+
useShortcuts2(
|
|
2575
|
+
isSelected ? [{ key: "esc", label: "back" }] : [{ key: "\u2191\u2193\u2190\u2192", label: "navigate" }, { key: "enter", label: "select" }, { key: "tab", label: "cycle" }],
|
|
2576
|
+
focusId
|
|
2577
|
+
);
|
|
2578
|
+
const borderStyle = isSelected ? "rounded" : isFocused ? "dashed" : "rounded";
|
|
2579
|
+
const borderColor = isSelected ? "#818cf8" : isAnySelected ? "transparent" : isFocused ? "#6366f1" : "#3b3466";
|
|
2580
|
+
const fg = isSelected ? "#a5b4fc" : isFocused ? "#a5b4fc" : "#888";
|
|
2581
|
+
return /* @__PURE__ */ jsx39("box", { ref: focusRef, border: true, borderStyle, borderColor, width: 16, height: 5, children: /* @__PURE__ */ jsx39("box", { flexDirection: "column", alignItems: "center", justifyContent: "center", flexGrow: 1, children: /* @__PURE__ */ jsx39("text", { style: { fg, bold: isFocused || isSelected }, children: isSelected ? "selected" : "not selected" }) }) });
|
|
2582
|
+
}
|
|
2583
|
+
function FocusGridStatusBar() {
|
|
2584
|
+
const shortcuts2 = useFocusedShortcuts2();
|
|
2585
|
+
return /* @__PURE__ */ jsx39("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx39(StatusBar, { items: shortcuts2 }) });
|
|
2586
|
+
}
|
|
2587
|
+
function FocusGridApp() {
|
|
2588
|
+
return /* @__PURE__ */ jsx39(FocusProvider2, { selectable: true, children: /* @__PURE__ */ jsxs30("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2589
|
+
/* @__PURE__ */ jsxs30("box", { flexDirection: "column", gap: 1, padding: 1, flexGrow: 1, alignItems: "center", children: [
|
|
2590
|
+
/* @__PURE__ */ jsx39("box", { flexDirection: "row", gap: 1, children: gridItems.slice(0, 3).map((item, i) => /* @__PURE__ */ jsx39(GridCell, { ...item, autoFocus: i === 0 }, item.id)) }),
|
|
2591
|
+
/* @__PURE__ */ jsx39("box", { flexDirection: "row", gap: 1, children: gridItems.slice(3, 6).map((item) => /* @__PURE__ */ jsx39(GridCell, { ...item }, item.id)) })
|
|
2592
|
+
] }),
|
|
2593
|
+
/* @__PURE__ */ jsx39(FocusGridStatusBar, {})
|
|
2594
|
+
] }) });
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
// demos/focus-chat.tsx
|
|
2598
|
+
import { useState as useState22, useRef as useRef9, useCallback as useCallback5 } from "react";
|
|
2599
|
+
import { useKeyboard as useKeyboard16, useFocus as useFocus3, FocusProvider as FocusProvider3, useShortcuts as useShortcuts3, useFocusedShortcuts as useFocusedShortcuts3 } from "@gridland/utils";
|
|
2600
|
+
import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2601
|
+
function CotSection() {
|
|
2602
|
+
const { isFocused, isSelected, isAnySelected, focusId, focusRef } = useFocus3({ id: "cot", autoFocus: true });
|
|
2603
|
+
const [cotOpen, setCotOpen] = useState22(false);
|
|
2604
|
+
useKeyboard16((event) => {
|
|
2605
|
+
if (event.name === "return") {
|
|
2606
|
+
setCotOpen((v) => !v);
|
|
2607
|
+
event.preventDefault();
|
|
2608
|
+
}
|
|
2609
|
+
}, { focusId, selectedOnly: true });
|
|
2610
|
+
useShortcuts3(
|
|
2611
|
+
isSelected ? [{ key: "enter", label: "expand/collapse" }, { key: "esc", label: "back" }] : [{ key: "\u2191\u2193", label: "navigate" }, { key: "tab", label: "cycle" }, { key: "enter", label: "select" }],
|
|
2612
|
+
focusId
|
|
2613
|
+
);
|
|
2614
|
+
const borderStyle = isSelected ? "rounded" : isFocused ? "dashed" : "rounded";
|
|
2615
|
+
const borderColor = isSelected ? "#818cf8" : isAnySelected ? "transparent" : isFocused ? "#6366f1" : "#3b3466";
|
|
2616
|
+
return /* @__PURE__ */ jsx40("box", { ref: focusRef, marginTop: 1, border: true, borderStyle, borderColor, children: /* @__PURE__ */ jsxs31(ChainOfThought, { open: cotOpen, onOpenChange: setCotOpen, children: [
|
|
2617
|
+
/* @__PURE__ */ jsx40(ChainOfThoughtHeader, { duration: "1.2s" }),
|
|
2618
|
+
/* @__PURE__ */ jsx40(ChainOfThoughtContent, { children: /* @__PURE__ */ jsx40(ChainOfThoughtStep, { label: "Searched docs", status: "done", isLast: true }) })
|
|
2619
|
+
] }) });
|
|
2620
|
+
}
|
|
2621
|
+
function PromptSection() {
|
|
2622
|
+
const { isFocused, isSelected, isAnySelected, focusId, focusRef } = useFocus3({ id: "prompt" });
|
|
2623
|
+
const promptHandlerRef = useRef9(null);
|
|
2624
|
+
const captureKeyboard = useCallback5((handler) => {
|
|
2625
|
+
promptHandlerRef.current = handler;
|
|
2626
|
+
}, []);
|
|
2627
|
+
useKeyboard16((event) => {
|
|
2628
|
+
promptHandlerRef.current?.(event);
|
|
2629
|
+
}, { focusId, selectedOnly: true });
|
|
2630
|
+
useShortcuts3(
|
|
2631
|
+
isSelected ? [{ key: "\u23CE", label: "send" }, { key: "esc", label: "back" }] : [{ key: "\u2191\u2193", label: "navigate" }, { key: "tab", label: "cycle" }, { key: "enter", label: "select" }],
|
|
2632
|
+
focusId
|
|
2633
|
+
);
|
|
2634
|
+
const dividerColor = isSelected ? "#818cf8" : isAnySelected ? void 0 : isFocused ? "#6366f1" : "#3b3466";
|
|
2635
|
+
const dividerDashed = isFocused && !isSelected && !isAnySelected;
|
|
2636
|
+
return /* @__PURE__ */ jsx40("box", { ref: focusRef, children: /* @__PURE__ */ jsx40(
|
|
2637
|
+
PromptInput,
|
|
2638
|
+
{
|
|
2639
|
+
placeholder: "Type a message...",
|
|
2640
|
+
status: "ready",
|
|
2641
|
+
dividerColor,
|
|
2642
|
+
dividerDashed,
|
|
2643
|
+
useKeyboard: captureKeyboard
|
|
2644
|
+
}
|
|
2645
|
+
) });
|
|
2646
|
+
}
|
|
2647
|
+
function FocusChatStatusBar() {
|
|
2648
|
+
const shortcuts2 = useFocusedShortcuts3();
|
|
2649
|
+
return /* @__PURE__ */ jsx40("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx40(StatusBar, { items: shortcuts2 }) });
|
|
2650
|
+
}
|
|
2651
|
+
function FocusChatApp() {
|
|
2652
|
+
return /* @__PURE__ */ jsx40(FocusProvider3, { selectable: true, children: /* @__PURE__ */ jsxs31("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2653
|
+
/* @__PURE__ */ jsxs31("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
2654
|
+
/* @__PURE__ */ jsxs31("box", { flexDirection: "column", paddingX: 1, paddingTop: 1, flexGrow: 1, children: [
|
|
2655
|
+
/* @__PURE__ */ jsx40(Message, { role: "user", children: /* @__PURE__ */ jsx40(Message.Content, { children: /* @__PURE__ */ jsx40(Message.Text, { children: "How do I set up keyboard navigation?" }) }) }),
|
|
2656
|
+
/* @__PURE__ */ jsx40(CotSection, {}),
|
|
2657
|
+
/* @__PURE__ */ jsx40(Message, { role: "assistant", children: /* @__PURE__ */ jsx40(Message.Content, { children: /* @__PURE__ */ jsx40(Message.Text, { children: "Use the useKeyboard hook to listen for key events. Wrap your app in a FocusProvider to enable tab navigation between focusable components." }) }) })
|
|
2658
|
+
] }),
|
|
2659
|
+
/* @__PURE__ */ jsx40(PromptSection, {})
|
|
2660
|
+
] }),
|
|
2661
|
+
/* @__PURE__ */ jsx40(FocusChatStatusBar, {})
|
|
2662
|
+
] }) });
|
|
2523
2663
|
}
|
|
2524
2664
|
|
|
2525
2665
|
// demos/pointer.tsx
|
|
2526
|
-
import { useState as
|
|
2527
|
-
import { useKeyboard as
|
|
2528
|
-
import { jsx as
|
|
2666
|
+
import { useState as useState23, useRef as useRef10 } from "react";
|
|
2667
|
+
import { useKeyboard as useKeyboard17 } from "@gridland/utils";
|
|
2668
|
+
import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2529
2669
|
var pointerColors = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#3b82f6", "#8b5cf6"];
|
|
2530
2670
|
var pointerColorNames = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple"];
|
|
2531
2671
|
function HoverBox() {
|
|
2532
|
-
const [hovering, setHovering] =
|
|
2533
|
-
return /* @__PURE__ */
|
|
2672
|
+
const [hovering, setHovering] = useState23(false);
|
|
2673
|
+
return /* @__PURE__ */ jsx41(
|
|
2534
2674
|
"box",
|
|
2535
2675
|
{
|
|
2536
2676
|
border: true,
|
|
@@ -2540,19 +2680,19 @@ function HoverBox() {
|
|
|
2540
2680
|
height: 5,
|
|
2541
2681
|
onMouseOver: () => setHovering(true),
|
|
2542
2682
|
onMouseOut: () => setHovering(false),
|
|
2543
|
-
children: /* @__PURE__ */
|
|
2683
|
+
children: /* @__PURE__ */ jsx41("box", { padding: 1, children: /* @__PURE__ */ jsx41("text", { style: { fg: hovering ? "#22c55e" : "#888", bold: hovering }, children: hovering ? "Mouse inside!" : "Hover me" }) })
|
|
2544
2684
|
}
|
|
2545
2685
|
);
|
|
2546
2686
|
}
|
|
2547
2687
|
function PointerApp() {
|
|
2548
|
-
const [selected, setSelected] =
|
|
2549
|
-
const [clickCount, setClickCount] =
|
|
2550
|
-
const [mousePos, setMousePos] =
|
|
2551
|
-
const selectedRef =
|
|
2552
|
-
const clickCountRef =
|
|
2688
|
+
const [selected, setSelected] = useState23(null);
|
|
2689
|
+
const [clickCount, setClickCount] = useState23(0);
|
|
2690
|
+
const [mousePos, setMousePos] = useState23(null);
|
|
2691
|
+
const selectedRef = useRef10(null);
|
|
2692
|
+
const clickCountRef = useRef10(0);
|
|
2553
2693
|
selectedRef.current = selected;
|
|
2554
2694
|
clickCountRef.current = clickCount;
|
|
2555
|
-
|
|
2695
|
+
useKeyboard17((event) => {
|
|
2556
2696
|
const cur = selectedRef.current ?? -1;
|
|
2557
2697
|
if (event.name === "right" || event.name === "tab") {
|
|
2558
2698
|
const next = (cur + 1) % pointerColors.length;
|
|
@@ -2565,8 +2705,8 @@ function PointerApp() {
|
|
|
2565
2705
|
}
|
|
2566
2706
|
event.preventDefault();
|
|
2567
2707
|
});
|
|
2568
|
-
return /* @__PURE__ */
|
|
2569
|
-
/* @__PURE__ */
|
|
2708
|
+
return /* @__PURE__ */ jsxs32("box", { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
2709
|
+
/* @__PURE__ */ jsx41("box", { flexDirection: "row", gap: 1, children: pointerColors.map((color, i) => /* @__PURE__ */ jsx41(
|
|
2570
2710
|
"box",
|
|
2571
2711
|
{
|
|
2572
2712
|
flexGrow: 1,
|
|
@@ -2581,22 +2721,22 @@ function PointerApp() {
|
|
|
2581
2721
|
setSelected(i);
|
|
2582
2722
|
setMousePos({ x: e.x, y: e.y });
|
|
2583
2723
|
},
|
|
2584
|
-
children: /* @__PURE__ */
|
|
2724
|
+
children: /* @__PURE__ */ jsx41("text", { style: { fg: color, bold: i === selected }, children: i === selected ? `\u25B8 ${pointerColorNames[i]}` : ` ${pointerColorNames[i]}` })
|
|
2585
2725
|
},
|
|
2586
2726
|
color
|
|
2587
2727
|
)) }),
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
/* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2591
|
-
/* @__PURE__ */
|
|
2592
|
-
/* @__PURE__ */
|
|
2728
|
+
/* @__PURE__ */ jsx41("box", { height: 1 }),
|
|
2729
|
+
/* @__PURE__ */ jsxs32("box", { flexDirection: "row", gap: 2, children: [
|
|
2730
|
+
/* @__PURE__ */ jsx41(HoverBox, {}),
|
|
2731
|
+
/* @__PURE__ */ jsxs32("box", { flexDirection: "column", flexGrow: 1, paddingTop: 1, children: [
|
|
2732
|
+
/* @__PURE__ */ jsxs32("text", { style: { fg: selected !== null ? pointerColors[selected] : "#888" }, children: [
|
|
2593
2733
|
selected !== null ? `Clicked ${pointerColorNames[selected]}` : "Click a color",
|
|
2594
2734
|
clickCount > 0 ? ` (${clickCount} clicks)` : ""
|
|
2595
2735
|
] }),
|
|
2596
|
-
/* @__PURE__ */
|
|
2736
|
+
/* @__PURE__ */ jsx41("text", { style: { dim: true, fg: "#888" }, children: mousePos ? `mouse: ${mousePos.x}, ${mousePos.y}` : "" })
|
|
2597
2737
|
] })
|
|
2598
2738
|
] }),
|
|
2599
|
-
/* @__PURE__ */
|
|
2739
|
+
/* @__PURE__ */ jsx41("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx41(StatusBar, { items: [
|
|
2600
2740
|
{ key: "click", label: "select" },
|
|
2601
2741
|
{ key: "\u2190\u2192", label: "keyboard nav" }
|
|
2602
2742
|
] }) })
|
|
@@ -2604,11 +2744,11 @@ function PointerApp() {
|
|
|
2604
2744
|
}
|
|
2605
2745
|
|
|
2606
2746
|
// demos/cursor-highlight.tsx
|
|
2607
|
-
import { useState as
|
|
2608
|
-
import { jsx as
|
|
2747
|
+
import { useState as useState24 } from "react";
|
|
2748
|
+
import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2609
2749
|
function CursorHighlightApp() {
|
|
2610
|
-
const [pos, setPos] =
|
|
2611
|
-
return /* @__PURE__ */
|
|
2750
|
+
const [pos, setPos] = useState24(null);
|
|
2751
|
+
return /* @__PURE__ */ jsxs33(
|
|
2612
2752
|
"box",
|
|
2613
2753
|
{
|
|
2614
2754
|
flexDirection: "column",
|
|
@@ -2617,27 +2757,27 @@ function CursorHighlightApp() {
|
|
|
2617
2757
|
setPos({ x: e.x, y: e.y });
|
|
2618
2758
|
},
|
|
2619
2759
|
children: [
|
|
2620
|
-
/* @__PURE__ */
|
|
2621
|
-
/* @__PURE__ */
|
|
2622
|
-
/* @__PURE__ */
|
|
2623
|
-
/* @__PURE__ */
|
|
2624
|
-
/* @__PURE__ */
|
|
2760
|
+
/* @__PURE__ */ jsxs33("box", { flexDirection: "column", flexGrow: 1, padding: 1, children: [
|
|
2761
|
+
/* @__PURE__ */ jsx42("text", { style: { bold: true, fg: "#fff" }, children: "Cursor Highlight" }),
|
|
2762
|
+
/* @__PURE__ */ jsx42("text", { style: { dim: true, fg: "#888" }, children: "Move your mouse over the grid" }),
|
|
2763
|
+
/* @__PURE__ */ jsx42("box", { height: 1 }),
|
|
2764
|
+
/* @__PURE__ */ jsx42("box", { flexDirection: "column", children: Array.from({ length: 6 }, (_, row) => /* @__PURE__ */ jsx42("text", { children: Array.from({ length: 40 }, (_2, col) => {
|
|
2625
2765
|
const isEven = (row + col) % 2 === 0;
|
|
2626
|
-
return /* @__PURE__ */
|
|
2766
|
+
return /* @__PURE__ */ jsx42("span", { style: {
|
|
2627
2767
|
fg: isEven ? "#3b82f6" : "#8b5cf6",
|
|
2628
2768
|
dim: !isEven
|
|
2629
2769
|
}, children: isEven ? "\u2591\u2591" : "\u2593\u2593" }, col);
|
|
2630
2770
|
}) }, row)) })
|
|
2631
2771
|
] }),
|
|
2632
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsx42("box", { paddingX: 1, paddingBottom: 1, children: /* @__PURE__ */ jsx42(
|
|
2633
2773
|
StatusBar,
|
|
2634
2774
|
{
|
|
2635
2775
|
items: [],
|
|
2636
|
-
extra: /* @__PURE__ */
|
|
2637
|
-
/* @__PURE__ */
|
|
2638
|
-
/* @__PURE__ */
|
|
2639
|
-
/* @__PURE__ */
|
|
2640
|
-
/* @__PURE__ */
|
|
2776
|
+
extra: /* @__PURE__ */ jsxs33("span", { children: [
|
|
2777
|
+
/* @__PURE__ */ jsx42("span", { style: textStyle({ bold: true, fg: "#1e1e2e", bg: "#888" }), children: " x " }),
|
|
2778
|
+
/* @__PURE__ */ jsx42("span", { style: textStyle({ dim: true, fg: "#888" }), children: ` ${pos ? String(pos.x).padStart(3) : " -"} ` }),
|
|
2779
|
+
/* @__PURE__ */ jsx42("span", { style: textStyle({ bold: true, fg: "#1e1e2e", bg: "#888" }), children: " y " }),
|
|
2780
|
+
/* @__PURE__ */ jsx42("span", { style: textStyle({ dim: true, fg: "#888" }), children: ` ${pos ? String(pos.y).padStart(3) : " -"}` })
|
|
2641
2781
|
] })
|
|
2642
2782
|
}
|
|
2643
2783
|
) })
|
|
@@ -2647,14 +2787,14 @@ function CursorHighlightApp() {
|
|
|
2647
2787
|
}
|
|
2648
2788
|
|
|
2649
2789
|
// demos/text-style.tsx
|
|
2650
|
-
import { jsx as
|
|
2790
|
+
import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2651
2791
|
function TextStyleApp() {
|
|
2652
2792
|
const theme = useTheme();
|
|
2653
2793
|
const desc = textStyle({ fg: theme.muted });
|
|
2654
|
-
return /* @__PURE__ */
|
|
2655
|
-
/* @__PURE__ */
|
|
2656
|
-
/* @__PURE__ */
|
|
2657
|
-
/* @__PURE__ */
|
|
2794
|
+
return /* @__PURE__ */ jsxs34("box", { flexDirection: "column", padding: 1, gap: 0, children: [
|
|
2795
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2796
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.foreground, bold: true }), children: "bold " }),
|
|
2797
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2658
2798
|
"textStyle(",
|
|
2659
2799
|
"{",
|
|
2660
2800
|
" bold: true ",
|
|
@@ -2662,9 +2802,9 @@ function TextStyleApp() {
|
|
|
2662
2802
|
")"
|
|
2663
2803
|
] })
|
|
2664
2804
|
] }),
|
|
2665
|
-
/* @__PURE__ */
|
|
2666
|
-
/* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2805
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2806
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.foreground, dim: true }), children: "dim " }),
|
|
2807
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2668
2808
|
"textStyle(",
|
|
2669
2809
|
"{",
|
|
2670
2810
|
" dim: true ",
|
|
@@ -2672,9 +2812,9 @@ function TextStyleApp() {
|
|
|
2672
2812
|
")"
|
|
2673
2813
|
] })
|
|
2674
2814
|
] }),
|
|
2675
|
-
/* @__PURE__ */
|
|
2676
|
-
/* @__PURE__ */
|
|
2677
|
-
/* @__PURE__ */
|
|
2815
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2816
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.foreground, italic: true }), children: "italic " }),
|
|
2817
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2678
2818
|
"textStyle(",
|
|
2679
2819
|
"{",
|
|
2680
2820
|
" italic: true ",
|
|
@@ -2682,9 +2822,9 @@ function TextStyleApp() {
|
|
|
2682
2822
|
")"
|
|
2683
2823
|
] })
|
|
2684
2824
|
] }),
|
|
2685
|
-
/* @__PURE__ */
|
|
2686
|
-
/* @__PURE__ */
|
|
2687
|
-
/* @__PURE__ */
|
|
2825
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2826
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.foreground, underline: true }), children: "underline " }),
|
|
2827
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2688
2828
|
"textStyle(",
|
|
2689
2829
|
"{",
|
|
2690
2830
|
" underline: true ",
|
|
@@ -2692,9 +2832,9 @@ function TextStyleApp() {
|
|
|
2692
2832
|
")"
|
|
2693
2833
|
] })
|
|
2694
2834
|
] }),
|
|
2695
|
-
/* @__PURE__ */
|
|
2696
|
-
/* @__PURE__ */
|
|
2697
|
-
/* @__PURE__ */
|
|
2835
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2836
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ inverse: true }), children: "inverse " }),
|
|
2837
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2698
2838
|
"textStyle(",
|
|
2699
2839
|
"{",
|
|
2700
2840
|
" inverse: true ",
|
|
@@ -2702,10 +2842,10 @@ function TextStyleApp() {
|
|
|
2702
2842
|
")"
|
|
2703
2843
|
] })
|
|
2704
2844
|
] }),
|
|
2705
|
-
/* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
2707
|
-
/* @__PURE__ */
|
|
2708
|
-
/* @__PURE__ */
|
|
2845
|
+
/* @__PURE__ */ jsx43("text", { children: " " }),
|
|
2846
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2847
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.primary }), children: "fg color " }),
|
|
2848
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2709
2849
|
"textStyle(",
|
|
2710
2850
|
"{",
|
|
2711
2851
|
" fg: theme.primary ",
|
|
@@ -2713,9 +2853,9 @@ function TextStyleApp() {
|
|
|
2713
2853
|
")"
|
|
2714
2854
|
] })
|
|
2715
2855
|
] }),
|
|
2716
|
-
/* @__PURE__ */
|
|
2717
|
-
/* @__PURE__ */
|
|
2718
|
-
/* @__PURE__ */
|
|
2856
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2857
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.foreground, bg: theme.secondary }), children: "bg color " }),
|
|
2858
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2719
2859
|
"textStyle(",
|
|
2720
2860
|
"{",
|
|
2721
2861
|
" fg: theme.foreground, bg: theme.secondary ",
|
|
@@ -2723,10 +2863,10 @@ function TextStyleApp() {
|
|
|
2723
2863
|
")"
|
|
2724
2864
|
] })
|
|
2725
2865
|
] }),
|
|
2726
|
-
/* @__PURE__ */
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
2866
|
+
/* @__PURE__ */ jsx43("text", { children: " " }),
|
|
2867
|
+
/* @__PURE__ */ jsxs34("text", { children: [
|
|
2868
|
+
/* @__PURE__ */ jsx43("span", { style: textStyle({ fg: theme.accent, bold: true, underline: true }), children: "combined " }),
|
|
2869
|
+
/* @__PURE__ */ jsxs34("span", { style: desc, children: [
|
|
2730
2870
|
"textStyle(",
|
|
2731
2871
|
"{",
|
|
2732
2872
|
" fg: theme.accent, bold: true, underline: true ",
|
|
@@ -2738,19 +2878,19 @@ function TextStyleApp() {
|
|
|
2738
2878
|
}
|
|
2739
2879
|
|
|
2740
2880
|
// demos/headless.tsx
|
|
2741
|
-
import { jsx as
|
|
2881
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
2742
2882
|
var data = [
|
|
2743
2883
|
{ name: "Alice", role: "Engineer", status: "Active" },
|
|
2744
2884
|
{ name: "Bob", role: "Designer", status: "Active" },
|
|
2745
2885
|
{ name: "Charlie", role: "PM", status: "Away" }
|
|
2746
2886
|
];
|
|
2747
2887
|
function HeadlessApp() {
|
|
2748
|
-
return /* @__PURE__ */
|
|
2888
|
+
return /* @__PURE__ */ jsx44("box", { padding: 1, children: /* @__PURE__ */ jsx44(Table, { data }) });
|
|
2749
2889
|
}
|
|
2750
2890
|
|
|
2751
2891
|
// demos/theming.tsx
|
|
2752
|
-
import { useKeyboard as
|
|
2753
|
-
import { jsx as
|
|
2892
|
+
import { useKeyboard as useKeyboard18 } from "@gridland/utils";
|
|
2893
|
+
import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2754
2894
|
var tableData = [
|
|
2755
2895
|
{ name: "Alice", role: "Engineer", status: "Active" },
|
|
2756
2896
|
{ name: "Bob", role: "Designer", status: "Away" }
|
|
@@ -2761,21 +2901,21 @@ var selectItems = [
|
|
|
2761
2901
|
{ label: "Python", value: "py" }
|
|
2762
2902
|
];
|
|
2763
2903
|
function ThemingApp() {
|
|
2764
|
-
return /* @__PURE__ */
|
|
2765
|
-
/* @__PURE__ */
|
|
2766
|
-
/* @__PURE__ */
|
|
2767
|
-
/* @__PURE__ */
|
|
2904
|
+
return /* @__PURE__ */ jsxs35("box", { flexDirection: "column", padding: 1, gap: 1, flexGrow: 1, children: [
|
|
2905
|
+
/* @__PURE__ */ jsx45(Spinner, { text: "Loading data..." }),
|
|
2906
|
+
/* @__PURE__ */ jsx45(Table, { data: tableData }),
|
|
2907
|
+
/* @__PURE__ */ jsx45(MultiSelect, { items: selectItems, useKeyboard: useKeyboard18 })
|
|
2768
2908
|
] });
|
|
2769
2909
|
}
|
|
2770
2910
|
|
|
2771
2911
|
// src/landing/landing-app.tsx
|
|
2772
|
-
import { useMemo as
|
|
2912
|
+
import { useMemo as useMemo8, useRef as useRef15, useState as useState29 } from "react";
|
|
2773
2913
|
|
|
2774
2914
|
// src/landing/install-box.tsx
|
|
2775
|
-
import { jsx as
|
|
2915
|
+
import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2776
2916
|
function InstallBox() {
|
|
2777
2917
|
const theme = useTheme();
|
|
2778
|
-
return /* @__PURE__ */
|
|
2918
|
+
return /* @__PURE__ */ jsx46(
|
|
2779
2919
|
"box",
|
|
2780
2920
|
{
|
|
2781
2921
|
border: true,
|
|
@@ -2784,21 +2924,23 @@ function InstallBox() {
|
|
|
2784
2924
|
paddingX: 1,
|
|
2785
2925
|
flexDirection: "column",
|
|
2786
2926
|
flexShrink: 0,
|
|
2787
|
-
children: /* @__PURE__ */
|
|
2788
|
-
/* @__PURE__ */
|
|
2789
|
-
/* @__PURE__ */
|
|
2790
|
-
/* @__PURE__ */
|
|
2927
|
+
children: /* @__PURE__ */ jsxs36("text", { children: [
|
|
2928
|
+
/* @__PURE__ */ jsx46("span", { style: textStyle({ dim: true }), children: "$ " }),
|
|
2929
|
+
/* @__PURE__ */ jsx46("span", { style: textStyle({ bold: true }), children: "bun create " }),
|
|
2930
|
+
/* @__PURE__ */ jsx46("span", { style: textStyle({ fg: theme.accent }), children: "gridland" })
|
|
2791
2931
|
] })
|
|
2792
2932
|
}
|
|
2793
2933
|
);
|
|
2794
2934
|
}
|
|
2795
2935
|
|
|
2796
2936
|
// src/landing/links-box.tsx
|
|
2797
|
-
import {
|
|
2937
|
+
import { isBrowser } from "@gridland/utils";
|
|
2938
|
+
import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2798
2939
|
var UNDERLINE3 = 1 << 3;
|
|
2799
2940
|
function LinksBox() {
|
|
2800
2941
|
const theme = useTheme();
|
|
2801
|
-
|
|
2942
|
+
const docsHref = isBrowser() ? `${window.location.origin}/docs` : "https://gridland.io/docs";
|
|
2943
|
+
return /* @__PURE__ */ jsx47(
|
|
2802
2944
|
"box",
|
|
2803
2945
|
{
|
|
2804
2946
|
border: true,
|
|
@@ -2807,36 +2949,36 @@ function LinksBox() {
|
|
|
2807
2949
|
paddingX: 1,
|
|
2808
2950
|
flexDirection: "column",
|
|
2809
2951
|
flexShrink: 0,
|
|
2810
|
-
children: /* @__PURE__ */
|
|
2811
|
-
/* @__PURE__ */
|
|
2812
|
-
/* @__PURE__ */
|
|
2813
|
-
/* @__PURE__ */
|
|
2814
|
-
/* @__PURE__ */
|
|
2815
|
-
/* @__PURE__ */
|
|
2952
|
+
children: /* @__PURE__ */ jsxs37("text", { children: [
|
|
2953
|
+
/* @__PURE__ */ jsx47("span", { children: "\u{1F431}" }),
|
|
2954
|
+
/* @__PURE__ */ jsx47("a", { href: "https://github.com/thoughtfulllc/gridland", style: { attributes: UNDERLINE3, fg: theme.accent }, children: " GitHub" }),
|
|
2955
|
+
/* @__PURE__ */ jsx47("span", { children: " " }),
|
|
2956
|
+
/* @__PURE__ */ jsx47("span", { children: "\u{1F4D6}" }),
|
|
2957
|
+
/* @__PURE__ */ jsx47("a", { href: docsHref, style: { attributes: UNDERLINE3, fg: theme.accent }, children: " Docs" })
|
|
2816
2958
|
] })
|
|
2817
2959
|
}
|
|
2818
2960
|
);
|
|
2819
2961
|
}
|
|
2820
2962
|
|
|
2821
2963
|
// src/landing/logo.tsx
|
|
2822
|
-
import { useState as
|
|
2964
|
+
import { useState as useState25, useEffect as useEffect6, useRef as useRef11, useMemo as useMemo5 } from "react";
|
|
2823
2965
|
import figlet3 from "figlet";
|
|
2824
|
-
import
|
|
2825
|
-
import { Fragment as
|
|
2826
|
-
figlet3.parseFont("
|
|
2827
|
-
function makeArt(text) {
|
|
2828
|
-
return figlet3.textSync(text, { font
|
|
2829
|
-
}
|
|
2830
|
-
var fullArt = makeArt("gridland");
|
|
2831
|
-
var gridArt = makeArt("grid");
|
|
2832
|
-
var landArt = makeArt("land");
|
|
2833
|
-
var ART_HEIGHT =
|
|
2966
|
+
import blockFont from "figlet/importable-fonts/Block.js";
|
|
2967
|
+
import { Fragment as Fragment6, jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2968
|
+
figlet3.parseFont("Block", blockFont);
|
|
2969
|
+
function makeArt(text, font = "Block") {
|
|
2970
|
+
return figlet3.textSync(text, { font }).split("\n").filter((l) => l.trimEnd().length > 0).join("\n");
|
|
2971
|
+
}
|
|
2972
|
+
var fullArt = makeArt("gridland", "Block");
|
|
2973
|
+
var gridArt = makeArt("grid", "Block");
|
|
2974
|
+
var landArt = makeArt("land", "Block");
|
|
2975
|
+
var ART_HEIGHT = fullArt.split("\n").length;
|
|
2834
2976
|
function useAnimation(duration = 1e3) {
|
|
2835
|
-
const
|
|
2836
|
-
const [progress, setProgress] =
|
|
2837
|
-
const startTime =
|
|
2977
|
+
const isBrowser2 = typeof document !== "undefined";
|
|
2978
|
+
const [progress, setProgress] = useState25(isBrowser2 ? 0 : 1);
|
|
2979
|
+
const startTime = useRef11(null);
|
|
2838
2980
|
useEffect6(() => {
|
|
2839
|
-
if (!
|
|
2981
|
+
if (!isBrowser2) return;
|
|
2840
2982
|
let raf;
|
|
2841
2983
|
const tick = (time) => {
|
|
2842
2984
|
if (startTime.current === null) startTime.current = time;
|
|
@@ -2851,13 +2993,20 @@ function useAnimation(duration = 1e3) {
|
|
|
2851
2993
|
}, []);
|
|
2852
2994
|
return progress;
|
|
2853
2995
|
}
|
|
2996
|
+
function darkenHex(hex, factor = 0.4) {
|
|
2997
|
+
const r = Math.round(parseInt(hex.slice(1, 3), 16) * factor);
|
|
2998
|
+
const g = Math.round(parseInt(hex.slice(3, 5), 16) * factor);
|
|
2999
|
+
const b = Math.round(parseInt(hex.slice(5, 7), 16) * factor);
|
|
3000
|
+
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
|
3001
|
+
}
|
|
2854
3002
|
function RevealGradient({ children, revealCol }) {
|
|
2855
3003
|
const gradientColors = GRADIENTS.instagram;
|
|
2856
3004
|
const lines2 = children.split("\n");
|
|
2857
3005
|
const maxLength = Math.max(...lines2.map((l) => l.length));
|
|
2858
|
-
if (maxLength === 0) return /* @__PURE__ */
|
|
3006
|
+
if (maxLength === 0) return /* @__PURE__ */ jsx48("text", { children });
|
|
2859
3007
|
const hexColors = useMemo5(() => generateGradient(gradientColors, maxLength), [maxLength]);
|
|
2860
|
-
|
|
3008
|
+
const bgColors = useMemo5(() => hexColors.map((c) => darkenHex(c)), [hexColors]);
|
|
3009
|
+
return /* @__PURE__ */ jsx48("box", { position: "relative", width: maxLength, height: lines2.length, shouldFill: false, children: lines2.map((line, lineIndex) => {
|
|
2861
3010
|
const runs = [];
|
|
2862
3011
|
let current = null;
|
|
2863
3012
|
for (let i = 0; i < line.length; i++) {
|
|
@@ -2877,17 +3026,17 @@ function RevealGradient({ children, revealCol }) {
|
|
|
2877
3026
|
}
|
|
2878
3027
|
}
|
|
2879
3028
|
if (current) runs.push(current);
|
|
2880
|
-
return runs.map((run, runIndex) => /* @__PURE__ */
|
|
3029
|
+
return runs.map((run, runIndex) => /* @__PURE__ */ jsx48(
|
|
2881
3030
|
"box",
|
|
2882
3031
|
{
|
|
2883
3032
|
position: "absolute",
|
|
2884
3033
|
top: lineIndex,
|
|
2885
3034
|
left: run.start,
|
|
2886
3035
|
shouldFill: false,
|
|
2887
|
-
children: /* @__PURE__ */
|
|
3036
|
+
children: /* @__PURE__ */ jsx48("text", { shouldFill: false, children: run.chars.map((char, ci) => /* @__PURE__ */ jsx48(
|
|
2888
3037
|
"span",
|
|
2889
3038
|
{
|
|
2890
|
-
style: { fg: hexColors[run.start + ci] },
|
|
3039
|
+
style: { fg: hexColors[run.start + ci], bg: bgColors[run.start + ci] },
|
|
2891
3040
|
children: char
|
|
2892
3041
|
},
|
|
2893
3042
|
ci
|
|
@@ -2898,28 +3047,28 @@ function RevealGradient({ children, revealCol }) {
|
|
|
2898
3047
|
}) });
|
|
2899
3048
|
}
|
|
2900
3049
|
function Logo({ compact, narrow, mobile }) {
|
|
2901
|
-
const
|
|
3050
|
+
const isBrowser2 = typeof document !== "undefined";
|
|
2902
3051
|
const progress = useAnimation(900);
|
|
2903
|
-
const artHeight = compact ? 1 : narrow ? ART_HEIGHT * 2 : ART_HEIGHT;
|
|
3052
|
+
const artHeight = compact ? 1 : narrow && !mobile ? ART_HEIGHT * 2 : ART_HEIGHT;
|
|
2904
3053
|
const dropOffset = Math.round((1 - progress) * -artHeight);
|
|
2905
3054
|
const revealProgress = Math.max(0, Math.min(1, (progress - 0.1) / 0.7));
|
|
2906
|
-
const maxWidth = compact ? 8 : narrow ?
|
|
3055
|
+
const maxWidth = compact ? 8 : narrow ? 35 : 69;
|
|
2907
3056
|
const revealCol = Math.round(revealProgress * (maxWidth + 4)) - 2;
|
|
2908
3057
|
const taglineOpacity = Math.max(0, Math.min(1, (progress - 0.7) / 0.3));
|
|
2909
|
-
const subtitle = /* @__PURE__ */
|
|
2910
|
-
/* @__PURE__ */
|
|
2911
|
-
/* @__PURE__ */
|
|
3058
|
+
const subtitle = /* @__PURE__ */ jsxs38(Fragment6, { children: [
|
|
3059
|
+
/* @__PURE__ */ jsx48("text", { children: " " }),
|
|
3060
|
+
/* @__PURE__ */ jsx48("box", { flexDirection: "column", alignItems: "center", width: "100%", shouldFill: false, children: /* @__PURE__ */ jsxs38("text", { style: textStyle({ fg: "#d4b0e8" }), opacity: taglineOpacity, wrapMode: "word", textAlign: "center", width: "100%", shouldFill: false, children: [
|
|
2912
3061
|
"A framework for building terminal apps, built on ",
|
|
2913
|
-
/* @__PURE__ */
|
|
3062
|
+
/* @__PURE__ */ jsx48("a", { href: "https://opentui.com", style: { attributes: 72, fg: "#d4b0e8" }, children: "OpenTUI" }),
|
|
2914
3063
|
" + React." + (mobile ? " " : "\n") + "(Gridland apps, like this website, work in the browser and terminal.)"
|
|
2915
3064
|
] }) })
|
|
2916
3065
|
] });
|
|
2917
|
-
if (!
|
|
2918
|
-
const art2 = compact ? "gridland" : narrow ? gridArt + "\n" + landArt : fullArt;
|
|
2919
|
-
return /* @__PURE__ */
|
|
2920
|
-
/* @__PURE__ */
|
|
2921
|
-
/* @__PURE__ */
|
|
2922
|
-
/* @__PURE__ */
|
|
3066
|
+
if (!isBrowser2) {
|
|
3067
|
+
const art2 = compact ? "gridland" : narrow && !mobile ? gridArt + "\n" + landArt : fullArt;
|
|
3068
|
+
return /* @__PURE__ */ jsxs38("box", { flexDirection: "column", flexShrink: 0, width: "100%", alignItems: "center", shouldFill: false, children: [
|
|
3069
|
+
/* @__PURE__ */ jsx48(Gradient, { name: "instagram", children: art2 }),
|
|
3070
|
+
/* @__PURE__ */ jsx48("text", { children: " " }),
|
|
3071
|
+
/* @__PURE__ */ jsx48("box", { flexDirection: "column", alignItems: "center", width: "100%", shouldFill: false, children: /* @__PURE__ */ jsxs38("text", { style: textStyle({ fg: "#d4b0e8" }), shouldFill: false, children: [
|
|
2923
3072
|
"A framework for building terminal apps, built on OpenTUI + React.",
|
|
2924
3073
|
"\n",
|
|
2925
3074
|
"(Gridland apps, like this website, work in the browser and terminal.)"
|
|
@@ -2927,22 +3076,22 @@ function Logo({ compact, narrow, mobile }) {
|
|
|
2927
3076
|
] });
|
|
2928
3077
|
}
|
|
2929
3078
|
if (compact) {
|
|
2930
|
-
return /* @__PURE__ */
|
|
2931
|
-
/* @__PURE__ */
|
|
3079
|
+
return /* @__PURE__ */ jsxs38("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
3080
|
+
/* @__PURE__ */ jsx48("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx48("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: /* @__PURE__ */ jsx48(RevealGradient, { revealCol, children: "gridland" }) }) }),
|
|
2932
3081
|
subtitle
|
|
2933
3082
|
] });
|
|
2934
3083
|
}
|
|
2935
|
-
if (narrow) {
|
|
2936
|
-
return /* @__PURE__ */
|
|
2937
|
-
/* @__PURE__ */
|
|
2938
|
-
/* @__PURE__ */
|
|
2939
|
-
/* @__PURE__ */
|
|
3084
|
+
if (narrow && !mobile) {
|
|
3085
|
+
return /* @__PURE__ */ jsxs38("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
3086
|
+
/* @__PURE__ */ jsx48("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsxs38("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: [
|
|
3087
|
+
/* @__PURE__ */ jsx48(RevealGradient, { revealCol, children: gridArt }),
|
|
3088
|
+
/* @__PURE__ */ jsx48(RevealGradient, { revealCol, children: landArt })
|
|
2940
3089
|
] }) }),
|
|
2941
3090
|
subtitle
|
|
2942
3091
|
] });
|
|
2943
3092
|
}
|
|
2944
|
-
return /* @__PURE__ */
|
|
2945
|
-
/* @__PURE__ */
|
|
3093
|
+
return /* @__PURE__ */ jsxs38("box", { flexDirection: "column", flexShrink: 0, width: "100%", shouldFill: false, children: [
|
|
3094
|
+
/* @__PURE__ */ jsx48("box", { height: artHeight, overflow: "hidden", position: "relative", width: "100%", flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx48("box", { position: "absolute", top: dropOffset, width: "100%", flexDirection: "column", alignItems: "center", shouldFill: false, children: /* @__PURE__ */ jsx48(RevealGradient, { revealCol, children: fullArt }) }) }),
|
|
2946
3095
|
subtitle
|
|
2947
3096
|
] });
|
|
2948
3097
|
}
|
|
@@ -2951,7 +3100,7 @@ function Logo({ compact, narrow, mobile }) {
|
|
|
2951
3100
|
import { useMemo as useMemo6 } from "react";
|
|
2952
3101
|
|
|
2953
3102
|
// src/landing/use-matrix.ts
|
|
2954
|
-
import { useState as
|
|
3103
|
+
import { useState as useState26, useEffect as useEffect7, useLayoutEffect, useRef as useRef12 } from "react";
|
|
2955
3104
|
var CHARS = "abcdefghijklmnopqrstuvwxyz0123456789@#$%^&*(){}[]|;:<>,.?/~`";
|
|
2956
3105
|
function randomChar() {
|
|
2957
3106
|
return CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
@@ -2965,7 +3114,11 @@ function createDrop(height, seeded = false) {
|
|
|
2965
3114
|
chars: Array.from({ length }, randomChar)
|
|
2966
3115
|
};
|
|
2967
3116
|
}
|
|
2968
|
-
|
|
3117
|
+
var PULL_RADIUS = 18;
|
|
3118
|
+
var PULL_STRENGTH = 7;
|
|
3119
|
+
var RIPPLE_DURATION_MS = 3200;
|
|
3120
|
+
var RIPPLE_SPEED = 8e-3;
|
|
3121
|
+
function buildGrid(columns, width, height, mousePos, ripples, now = Date.now()) {
|
|
2969
3122
|
const grid = Array.from({ length: height }, () => Array(width).fill(" "));
|
|
2970
3123
|
const brightness = Array.from({ length: height }, () => Array(width).fill(0));
|
|
2971
3124
|
for (let x = 0; x < width; x++) {
|
|
@@ -2974,30 +3127,67 @@ function buildGrid(columns, width, height) {
|
|
|
2974
3127
|
for (let i = 0; i < drop.length; i++) {
|
|
2975
3128
|
const row = Math.floor(drop.y) - i;
|
|
2976
3129
|
if (row < 0 || row >= height) continue;
|
|
2977
|
-
|
|
2978
|
-
if (
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
3130
|
+
let renderX = x;
|
|
3131
|
+
if (mousePos) {
|
|
3132
|
+
const dx = mousePos.x - x;
|
|
3133
|
+
const dy = mousePos.y - row;
|
|
3134
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
3135
|
+
if (dist < PULL_RADIUS && dist > 0.5) {
|
|
3136
|
+
const t = 1 - dist / PULL_RADIUS;
|
|
3137
|
+
const strength = t * t * PULL_STRENGTH;
|
|
3138
|
+
renderX = Math.round(x + dx / dist * strength);
|
|
3139
|
+
renderX = Math.max(0, Math.min(width - 1, renderX));
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
const b = i === 0 ? 1 : Math.max(0.15, 1 - i / drop.length);
|
|
3143
|
+
if (brightness[row][renderX] < b) {
|
|
3144
|
+
grid[row][renderX] = drop.chars[i];
|
|
3145
|
+
brightness[row][renderX] = b;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
for (const ripple of ripples) {
|
|
3150
|
+
const elapsed = now - ripple.createdAt;
|
|
3151
|
+
if (elapsed > RIPPLE_DURATION_MS || elapsed < 0) continue;
|
|
3152
|
+
const radius = elapsed * RIPPLE_SPEED;
|
|
3153
|
+
const fade = 1 - elapsed / RIPPLE_DURATION_MS;
|
|
3154
|
+
const maxR = Math.ceil(radius) + 2;
|
|
3155
|
+
const rx = Math.round(ripple.x);
|
|
3156
|
+
const ry = Math.round(ripple.y);
|
|
3157
|
+
for (let dy = -maxR; dy <= maxR; dy++) {
|
|
3158
|
+
for (let dx = -maxR; dx <= maxR; dx++) {
|
|
3159
|
+
const cy = ry + dy;
|
|
3160
|
+
const cx = rx + dx;
|
|
3161
|
+
if (cy < 0 || cy >= height || cx < 0 || cx >= width) continue;
|
|
3162
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
3163
|
+
const ringDist = Math.abs(dist - radius);
|
|
3164
|
+
if (ringDist < 2) {
|
|
3165
|
+
const boost = (1 - ringDist / 2) * fade * 0.7;
|
|
3166
|
+
brightness[cy][cx] = Math.min(1, brightness[cy][cx] + boost);
|
|
3167
|
+
if (grid[cy][cx] === " " && boost > 0.2) {
|
|
3168
|
+
grid[cy][cx] = randomChar();
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
2982
3171
|
}
|
|
2983
3172
|
}
|
|
2984
3173
|
}
|
|
2985
3174
|
return { grid, brightness };
|
|
2986
3175
|
}
|
|
2987
|
-
function useMatrix(width, height) {
|
|
2988
|
-
const columnsRef =
|
|
2989
|
-
const [state, setState] =
|
|
3176
|
+
function useMatrix(width, height, mousePosRef, ripplesRef) {
|
|
3177
|
+
const columnsRef = useRef12([]);
|
|
3178
|
+
const [state, setState] = useState26(() => {
|
|
2990
3179
|
const columns = Array.from(
|
|
2991
3180
|
{ length: width },
|
|
2992
3181
|
() => Math.random() < 0.5 ? createDrop(height, true) : null
|
|
2993
3182
|
);
|
|
2994
3183
|
columnsRef.current = columns;
|
|
2995
|
-
return buildGrid(columns, width, height);
|
|
3184
|
+
return buildGrid(columns, width, height, null, []);
|
|
2996
3185
|
});
|
|
2997
3186
|
useEffect7(() => {
|
|
2998
3187
|
if (width < 2 || height < 2) return;
|
|
2999
3188
|
const id = setInterval(() => {
|
|
3000
3189
|
const columns = columnsRef.current;
|
|
3190
|
+
const now = Date.now();
|
|
3001
3191
|
for (let x = 0; x < width; x++) {
|
|
3002
3192
|
if (columns[x] === null || columns[x] === void 0) {
|
|
3003
3193
|
if (Math.random() < 0.03) {
|
|
@@ -3015,22 +3205,29 @@ function useMatrix(width, height) {
|
|
|
3015
3205
|
columns[x] = null;
|
|
3016
3206
|
}
|
|
3017
3207
|
}
|
|
3018
|
-
|
|
3208
|
+
if (ripplesRef?.current) {
|
|
3209
|
+
ripplesRef.current = ripplesRef.current.filter(
|
|
3210
|
+
(r) => now - r.createdAt < RIPPLE_DURATION_MS
|
|
3211
|
+
);
|
|
3212
|
+
}
|
|
3213
|
+
const mousePos = mousePosRef?.current ?? null;
|
|
3214
|
+
const ripples = ripplesRef?.current ?? [];
|
|
3215
|
+
setState(buildGrid(columns, width, height, mousePos, ripples, now));
|
|
3019
3216
|
}, 80);
|
|
3020
3217
|
return () => clearInterval(id);
|
|
3021
3218
|
}, [width, height]);
|
|
3022
|
-
|
|
3219
|
+
useLayoutEffect(() => {
|
|
3023
3220
|
columnsRef.current = Array.from(
|
|
3024
3221
|
{ length: width },
|
|
3025
3222
|
() => Math.random() < 0.5 ? createDrop(height, true) : null
|
|
3026
3223
|
);
|
|
3027
|
-
setState(buildGrid(columnsRef.current, width, height));
|
|
3224
|
+
setState(buildGrid(columnsRef.current, width, height, null, []));
|
|
3028
3225
|
}, [width, height]);
|
|
3029
3226
|
return state;
|
|
3030
3227
|
}
|
|
3031
3228
|
|
|
3032
3229
|
// src/landing/matrix-background.tsx
|
|
3033
|
-
import { jsx as
|
|
3230
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
3034
3231
|
var MUTE_LEVELS = [0.12, 0.18, 0.24, 0.3, 0.38];
|
|
3035
3232
|
var BG = hexToRgb("#1a1a2e");
|
|
3036
3233
|
function buildMutedColors(baseHex) {
|
|
@@ -3046,8 +3243,8 @@ function colorForCell(mutedColors, b) {
|
|
|
3046
3243
|
const idx = Math.min(Math.floor(b * (MUTE_LEVELS.length - 1)), MUTE_LEVELS.length - 2);
|
|
3047
3244
|
return mutedColors[idx];
|
|
3048
3245
|
}
|
|
3049
|
-
function MatrixBackground({ width, height, clearRect, clearRects }) {
|
|
3050
|
-
const { grid, brightness } = useMatrix(width, height);
|
|
3246
|
+
function MatrixBackground({ width, height, clearRect, clearRects, mousePosRef, ripplesRef }) {
|
|
3247
|
+
const { grid, brightness } = useMatrix(width, height, mousePosRef, ripplesRef);
|
|
3051
3248
|
const theme = useTheme();
|
|
3052
3249
|
const columnColors = useMemo6(
|
|
3053
3250
|
() => width > 0 ? generateGradient([theme.accent, theme.secondary, theme.primary], width) : [],
|
|
@@ -3057,15 +3254,15 @@ function MatrixBackground({ width, height, clearRect, clearRects }) {
|
|
|
3057
3254
|
() => columnColors.map(buildMutedColors),
|
|
3058
3255
|
[columnColors]
|
|
3059
3256
|
);
|
|
3060
|
-
return /* @__PURE__ */
|
|
3257
|
+
return /* @__PURE__ */ jsx49("box", { flexDirection: "column", children: grid.map((row, y) => /* @__PURE__ */ jsx49("text", { children: row.map((cell, x) => {
|
|
3061
3258
|
const inClearRect = clearRect && y >= clearRect.top && y < clearRect.top + clearRect.height && x >= clearRect.left && x < clearRect.left + clearRect.width || clearRects && clearRects.some(
|
|
3062
3259
|
(r) => y >= r.top && y < r.top + r.height && x >= r.left && x < r.left + r.width
|
|
3063
3260
|
);
|
|
3064
3261
|
const mutedColors = columnMutedColors[x];
|
|
3065
3262
|
if (cell === " " || inClearRect || !mutedColors) {
|
|
3066
|
-
return /* @__PURE__ */
|
|
3263
|
+
return /* @__PURE__ */ jsx49("span", { children: " " }, x);
|
|
3067
3264
|
}
|
|
3068
|
-
return /* @__PURE__ */
|
|
3265
|
+
return /* @__PURE__ */ jsx49(
|
|
3069
3266
|
"span",
|
|
3070
3267
|
{
|
|
3071
3268
|
style: {
|
|
@@ -3078,88 +3275,540 @@ function MatrixBackground({ width, height, clearRect, clearRects }) {
|
|
|
3078
3275
|
}) }, y)) });
|
|
3079
3276
|
}
|
|
3080
3277
|
|
|
3278
|
+
// demos/ripple.tsx
|
|
3279
|
+
import { useState as useState27, useEffect as useEffect8, useRef as useRef13, useCallback as useCallback6 } from "react";
|
|
3280
|
+
import { useKeyboard as useKeyboard19 } from "@gridland/utils";
|
|
3281
|
+
import { jsx as jsx50, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3282
|
+
var DEFAULT_COLS = 40;
|
|
3283
|
+
var DEFAULT_ROWS = 10;
|
|
3284
|
+
var CHARS2 = ["\xB7", "\u2591", "\u2592", "\u2593", "\u2588"];
|
|
3285
|
+
function hexToRgb2(hex) {
|
|
3286
|
+
const h = hex.replace("#", "");
|
|
3287
|
+
return [
|
|
3288
|
+
parseInt(h.slice(0, 2), 16),
|
|
3289
|
+
parseInt(h.slice(2, 4), 16),
|
|
3290
|
+
parseInt(h.slice(4, 6), 16)
|
|
3291
|
+
];
|
|
3292
|
+
}
|
|
3293
|
+
function rgbToHex2(r, g, b) {
|
|
3294
|
+
const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
|
|
3295
|
+
return "#" + clamp(r).toString(16).padStart(2, "0") + clamp(g).toString(16).padStart(2, "0") + clamp(b).toString(16).padStart(2, "0");
|
|
3296
|
+
}
|
|
3297
|
+
function lerp2(a, b, t) {
|
|
3298
|
+
return a + (b - a) * t;
|
|
3299
|
+
}
|
|
3300
|
+
function RippleApp({ mouseOffset = { x: 0, y: 0 }, containerWidth, containerHeight } = {}) {
|
|
3301
|
+
const theme = useTheme();
|
|
3302
|
+
const [, setTick] = useState27(0);
|
|
3303
|
+
const COLS2 = containerWidth ? containerWidth - 2 : DEFAULT_COLS;
|
|
3304
|
+
const ROWS2 = containerHeight ? Math.max(3, containerHeight - 2 - 2) : DEFAULT_ROWS;
|
|
3305
|
+
const cursorRef = useRef13({ x: Math.floor(COLS2 / 2), y: Math.floor(ROWS2 / 2) });
|
|
3306
|
+
const ripplesRef = useRef13([]);
|
|
3307
|
+
const frameRef = useRef13(0);
|
|
3308
|
+
const mousePosRef = useRef13(null);
|
|
3309
|
+
const accentRgb = hexToRgb2(theme.accent);
|
|
3310
|
+
const dimRgb = [40, 40, 50];
|
|
3311
|
+
const baseRgb = [60, 60, 70];
|
|
3312
|
+
const addRipple = useCallback6((x, y) => {
|
|
3313
|
+
ripplesRef.current = [
|
|
3314
|
+
...ripplesRef.current,
|
|
3315
|
+
{ x, y, time: frameRef.current }
|
|
3316
|
+
];
|
|
3317
|
+
}, []);
|
|
3318
|
+
useEffect8(() => {
|
|
3319
|
+
const interval = setInterval(() => {
|
|
3320
|
+
frameRef.current++;
|
|
3321
|
+
ripplesRef.current = ripplesRef.current.filter(
|
|
3322
|
+
(r) => frameRef.current - r.time < 30
|
|
3323
|
+
);
|
|
3324
|
+
setTick((t) => t + 1);
|
|
3325
|
+
}, 60);
|
|
3326
|
+
return () => clearInterval(interval);
|
|
3327
|
+
}, []);
|
|
3328
|
+
useKeyboard19((event) => {
|
|
3329
|
+
const cursor2 = cursorRef.current;
|
|
3330
|
+
if (event.name === "up") {
|
|
3331
|
+
cursorRef.current = { ...cursor2, y: Math.max(0, cursor2.y - 1) };
|
|
3332
|
+
} else if (event.name === "down") {
|
|
3333
|
+
cursorRef.current = { ...cursor2, y: Math.min(ROWS2 - 1, cursor2.y + 1) };
|
|
3334
|
+
} else if (event.name === "left") {
|
|
3335
|
+
cursorRef.current = { ...cursor2, x: Math.max(0, cursor2.x - 1) };
|
|
3336
|
+
} else if (event.name === "right") {
|
|
3337
|
+
cursorRef.current = { ...cursor2, x: Math.min(COLS2 - 1, cursor2.x + 1) };
|
|
3338
|
+
} else if (event.name === "return") {
|
|
3339
|
+
addRipple(cursorRef.current.x, cursorRef.current.y);
|
|
3340
|
+
}
|
|
3341
|
+
event.preventDefault();
|
|
3342
|
+
});
|
|
3343
|
+
const cursor = cursorRef.current;
|
|
3344
|
+
const frame = frameRef.current;
|
|
3345
|
+
const ripples = ripplesRef.current;
|
|
3346
|
+
const grid = Array.from({ length: ROWS2 }, (_, row) => /* @__PURE__ */ jsx50("text", { children: Array.from({ length: COLS2 }, (_2, col) => {
|
|
3347
|
+
const isCursor = col === cursor.x && row === cursor.y;
|
|
3348
|
+
const baseWave = Math.sin(frame * 0.08 + col * 0.3 + row * 0.5) * 0.5 + 0.5;
|
|
3349
|
+
let intensity = baseWave * 0.15;
|
|
3350
|
+
for (const ripple of ripples) {
|
|
3351
|
+
const dx = col - ripple.x;
|
|
3352
|
+
const dy = row - ripple.y;
|
|
3353
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
3354
|
+
const age = frame - ripple.time;
|
|
3355
|
+
const radius = age * 0.5;
|
|
3356
|
+
const fade = 1 - age / 30;
|
|
3357
|
+
const ringDist = Math.abs(dist - radius);
|
|
3358
|
+
if (ringDist < 1.5) {
|
|
3359
|
+
const ringIntensity = (1 - ringDist / 1.5) * fade;
|
|
3360
|
+
intensity = Math.max(intensity, ringIntensity);
|
|
3361
|
+
} else if (dist < radius) {
|
|
3362
|
+
const innerIntensity = fade * 0.3 * (1 - dist / radius);
|
|
3363
|
+
intensity = Math.max(intensity, innerIntensity);
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
intensity = Math.max(0, Math.min(1, intensity));
|
|
3367
|
+
const charIndex = Math.min(
|
|
3368
|
+
CHARS2.length - 1,
|
|
3369
|
+
Math.floor(intensity * CHARS2.length)
|
|
3370
|
+
);
|
|
3371
|
+
const char = isCursor ? "\u25C6" : CHARS2[charIndex];
|
|
3372
|
+
let fg;
|
|
3373
|
+
if (isCursor) {
|
|
3374
|
+
fg = theme.primary;
|
|
3375
|
+
} else {
|
|
3376
|
+
const r = lerp2(dimRgb[0], accentRgb[0], intensity);
|
|
3377
|
+
const g = lerp2(dimRgb[1], accentRgb[1], intensity);
|
|
3378
|
+
const b = lerp2(dimRgb[2], accentRgb[2], intensity);
|
|
3379
|
+
fg = rgbToHex2(r, g, b);
|
|
3380
|
+
}
|
|
3381
|
+
return /* @__PURE__ */ jsx50("span", { style: { fg, bold: isCursor || intensity > 0.7 }, children: char }, col);
|
|
3382
|
+
}) }, row));
|
|
3383
|
+
return /* @__PURE__ */ jsxs39("box", { flexDirection: "column", flexGrow: 1, children: [
|
|
3384
|
+
/* @__PURE__ */ jsxs39(
|
|
3385
|
+
"box",
|
|
3386
|
+
{
|
|
3387
|
+
flexDirection: "column",
|
|
3388
|
+
flexGrow: 1,
|
|
3389
|
+
paddingX: 1,
|
|
3390
|
+
onMouseMove: (e) => {
|
|
3391
|
+
const gx = e.x - mouseOffset.x - 1;
|
|
3392
|
+
const gy = e.y - mouseOffset.y - 2;
|
|
3393
|
+
if (gx >= 0 && gx < COLS2 && gy >= 0 && gy < ROWS2) {
|
|
3394
|
+
mousePosRef.current = { x: gx, y: gy };
|
|
3395
|
+
cursorRef.current = { x: gx, y: gy };
|
|
3396
|
+
}
|
|
3397
|
+
},
|
|
3398
|
+
onMouseDown: (e) => {
|
|
3399
|
+
const gx = e.x - mouseOffset.x - 1;
|
|
3400
|
+
const gy = e.y - mouseOffset.y - 2;
|
|
3401
|
+
if (gx >= 0 && gx < COLS2 && gy >= 0 && gy < ROWS2) {
|
|
3402
|
+
addRipple(gx, gy);
|
|
3403
|
+
}
|
|
3404
|
+
},
|
|
3405
|
+
children: [
|
|
3406
|
+
/* @__PURE__ */ jsx50("text", { style: { dim: true, fg: theme.muted }, children: "Click or press Enter to create ripples" }),
|
|
3407
|
+
/* @__PURE__ */ jsx50("box", { flexDirection: "column", children: grid })
|
|
3408
|
+
]
|
|
3409
|
+
}
|
|
3410
|
+
),
|
|
3411
|
+
/* @__PURE__ */ jsx50("box", { flexGrow: 1 }),
|
|
3412
|
+
/* @__PURE__ */ jsx50("box", { paddingX: 1, children: /* @__PURE__ */ jsx50(
|
|
3413
|
+
StatusBar,
|
|
3414
|
+
{
|
|
3415
|
+
items: [
|
|
3416
|
+
{ key: "\u2191\u2193\u2190\u2192", label: "move" },
|
|
3417
|
+
{ key: "enter/click", label: "ripple" }
|
|
3418
|
+
]
|
|
3419
|
+
}
|
|
3420
|
+
) })
|
|
3421
|
+
] });
|
|
3422
|
+
}
|
|
3423
|
+
|
|
3424
|
+
// demos/puzzle.tsx
|
|
3425
|
+
import { useState as useState28, useEffect as useEffect9, useRef as useRef14, useMemo as useMemo7 } from "react";
|
|
3426
|
+
import { useKeyboard as useKeyboard20 } from "@gridland/utils";
|
|
3427
|
+
import { jsx as jsx51, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3428
|
+
var COLS = 4;
|
|
3429
|
+
var ROWS = 3;
|
|
3430
|
+
var TILE_COUNT = COLS * ROWS;
|
|
3431
|
+
var DEFAULT_TILE_WIDTH = 8;
|
|
3432
|
+
var DEFAULT_TILE_HEIGHT = 3;
|
|
3433
|
+
var SOLVED = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0];
|
|
3434
|
+
var tileColors = [
|
|
3435
|
+
"#ef4444",
|
|
3436
|
+
"#f97316",
|
|
3437
|
+
"#eab308",
|
|
3438
|
+
"#22c55e",
|
|
3439
|
+
"#3b82f6",
|
|
3440
|
+
"#8b5cf6",
|
|
3441
|
+
"#ec4899",
|
|
3442
|
+
"#14b8a6",
|
|
3443
|
+
"#f43f5e",
|
|
3444
|
+
"#6366f1",
|
|
3445
|
+
"#84cc16"
|
|
3446
|
+
];
|
|
3447
|
+
function isSolved(board) {
|
|
3448
|
+
for (let i = 0; i < TILE_COUNT; i++) {
|
|
3449
|
+
if (board[i] !== SOLVED[i]) return false;
|
|
3450
|
+
}
|
|
3451
|
+
return true;
|
|
3452
|
+
}
|
|
3453
|
+
function getEmptyIndex(board) {
|
|
3454
|
+
return board.indexOf(0);
|
|
3455
|
+
}
|
|
3456
|
+
function getNeighbor(emptyIdx, direction) {
|
|
3457
|
+
const row = Math.floor(emptyIdx / COLS);
|
|
3458
|
+
const col = emptyIdx % COLS;
|
|
3459
|
+
switch (direction) {
|
|
3460
|
+
case "up":
|
|
3461
|
+
return row > 0 ? emptyIdx - COLS : null;
|
|
3462
|
+
case "down":
|
|
3463
|
+
return row < ROWS - 1 ? emptyIdx + COLS : null;
|
|
3464
|
+
case "left":
|
|
3465
|
+
return col > 0 ? emptyIdx - 1 : null;
|
|
3466
|
+
case "right":
|
|
3467
|
+
return col < COLS - 1 ? emptyIdx + 1 : null;
|
|
3468
|
+
default:
|
|
3469
|
+
return null;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
function swap(board, a, b) {
|
|
3473
|
+
const next = [...board];
|
|
3474
|
+
next[a] = board[b];
|
|
3475
|
+
next[b] = board[a];
|
|
3476
|
+
return next;
|
|
3477
|
+
}
|
|
3478
|
+
function shuffle(board, count) {
|
|
3479
|
+
let current = [...board];
|
|
3480
|
+
const directions = ["up", "down", "left", "right"];
|
|
3481
|
+
let lastDir = "";
|
|
3482
|
+
for (let i = 0; i < count; i++) {
|
|
3483
|
+
const emptyIdx = getEmptyIndex(current);
|
|
3484
|
+
const validMoves = directions.filter((d) => {
|
|
3485
|
+
if (d === lastDir) return false;
|
|
3486
|
+
return getNeighbor(emptyIdx, d) !== null;
|
|
3487
|
+
});
|
|
3488
|
+
const dir = validMoves[Math.floor(Math.random() * validMoves.length)];
|
|
3489
|
+
const neighbor = getNeighbor(emptyIdx, dir);
|
|
3490
|
+
current = swap(current, emptyIdx, neighbor);
|
|
3491
|
+
const opposites = { up: "down", down: "up", left: "right", right: "left" };
|
|
3492
|
+
lastDir = opposites[dir];
|
|
3493
|
+
}
|
|
3494
|
+
return current;
|
|
3495
|
+
}
|
|
3496
|
+
function isAdjacentToEmpty(board, tileIdx) {
|
|
3497
|
+
const emptyIdx = getEmptyIndex(board);
|
|
3498
|
+
const eRow = Math.floor(emptyIdx / COLS);
|
|
3499
|
+
const eCol = emptyIdx % COLS;
|
|
3500
|
+
const tRow = Math.floor(tileIdx / COLS);
|
|
3501
|
+
const tCol = tileIdx % COLS;
|
|
3502
|
+
return Math.abs(eRow - tRow) === 1 && eCol === tCol || Math.abs(eCol - tCol) === 1 && eRow === tRow;
|
|
3503
|
+
}
|
|
3504
|
+
function PuzzleApp({ containerWidth, containerHeight } = {}) {
|
|
3505
|
+
const theme = useTheme();
|
|
3506
|
+
const TILE_WIDTH = containerWidth ? Math.floor((containerWidth - 2) / COLS) : DEFAULT_TILE_WIDTH;
|
|
3507
|
+
const TILE_HEIGHT = containerHeight ? Math.max(3, Math.floor((containerHeight - 2 - 4) / ROWS)) : DEFAULT_TILE_HEIGHT;
|
|
3508
|
+
const [board, setBoard] = useState28(SOLVED);
|
|
3509
|
+
const [moves, setMoves] = useState28(0);
|
|
3510
|
+
const [solved, setSolved] = useState28(false);
|
|
3511
|
+
const boardRef = useRef14(board);
|
|
3512
|
+
const movesRef = useRef14(moves);
|
|
3513
|
+
boardRef.current = board;
|
|
3514
|
+
movesRef.current = moves;
|
|
3515
|
+
const doMove = (direction) => {
|
|
3516
|
+
const current = boardRef.current;
|
|
3517
|
+
if (isSolved(current) && movesRef.current > 0) return;
|
|
3518
|
+
const emptyIdx = getEmptyIndex(current);
|
|
3519
|
+
const neighbor = getNeighbor(emptyIdx, direction);
|
|
3520
|
+
if (neighbor === null) return;
|
|
3521
|
+
const next = swap(current, emptyIdx, neighbor);
|
|
3522
|
+
boardRef.current = next;
|
|
3523
|
+
movesRef.current++;
|
|
3524
|
+
setBoard(next);
|
|
3525
|
+
setMoves(movesRef.current);
|
|
3526
|
+
setSolved(isSolved(next));
|
|
3527
|
+
};
|
|
3528
|
+
const doShuffle = () => {
|
|
3529
|
+
const shuffled = shuffle(SOLVED, 30);
|
|
3530
|
+
boardRef.current = shuffled;
|
|
3531
|
+
movesRef.current = 0;
|
|
3532
|
+
setBoard(shuffled);
|
|
3533
|
+
setMoves(0);
|
|
3534
|
+
setSolved(false);
|
|
3535
|
+
};
|
|
3536
|
+
useEffect9(() => {
|
|
3537
|
+
doShuffle();
|
|
3538
|
+
}, []);
|
|
3539
|
+
useKeyboard20((event) => {
|
|
3540
|
+
if (event.name === "up") {
|
|
3541
|
+
doMove("down");
|
|
3542
|
+
event.preventDefault();
|
|
3543
|
+
} else if (event.name === "down") {
|
|
3544
|
+
doMove("up");
|
|
3545
|
+
event.preventDefault();
|
|
3546
|
+
} else if (event.name === "left") {
|
|
3547
|
+
doMove("right");
|
|
3548
|
+
event.preventDefault();
|
|
3549
|
+
} else if (event.name === "right") {
|
|
3550
|
+
doMove("left");
|
|
3551
|
+
event.preventDefault();
|
|
3552
|
+
} else if (event.key === "r") {
|
|
3553
|
+
doShuffle();
|
|
3554
|
+
event.preventDefault();
|
|
3555
|
+
}
|
|
3556
|
+
});
|
|
3557
|
+
const rows = useMemo7(() => {
|
|
3558
|
+
const result = [];
|
|
3559
|
+
for (let r = 0; r < ROWS; r++) {
|
|
3560
|
+
result.push(board.slice(r * COLS, r * COLS + COLS));
|
|
3561
|
+
}
|
|
3562
|
+
return result;
|
|
3563
|
+
}, [board]);
|
|
3564
|
+
return /* @__PURE__ */ jsxs40("box", { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
|
|
3565
|
+
/* @__PURE__ */ jsx51("text", { style: textStyle({ dim: true, fg: theme.muted }), children: "Slide tiles to solve the puzzle" }),
|
|
3566
|
+
/* @__PURE__ */ jsx51("box", { flexDirection: "column", children: rows.map((row, rowIdx) => /* @__PURE__ */ jsx51("box", { flexDirection: "row", children: row.map((tile, colIdx) => {
|
|
3567
|
+
const idx = rowIdx * COLS + colIdx;
|
|
3568
|
+
if (tile === 0) {
|
|
3569
|
+
return /* @__PURE__ */ jsx51("box", { width: TILE_WIDTH, height: TILE_HEIGHT }, idx);
|
|
3570
|
+
}
|
|
3571
|
+
const color = tileColors[tile - 1];
|
|
3572
|
+
return /* @__PURE__ */ jsx51(
|
|
3573
|
+
"box",
|
|
3574
|
+
{
|
|
3575
|
+
width: TILE_WIDTH,
|
|
3576
|
+
height: TILE_HEIGHT,
|
|
3577
|
+
border: true,
|
|
3578
|
+
borderStyle: "rounded",
|
|
3579
|
+
borderColor: solved ? theme.success : color,
|
|
3580
|
+
onMouseDown: () => {
|
|
3581
|
+
if (isAdjacentToEmpty(boardRef.current, idx)) {
|
|
3582
|
+
const emptyIdx = getEmptyIndex(boardRef.current);
|
|
3583
|
+
const next = swap(boardRef.current, emptyIdx, idx);
|
|
3584
|
+
boardRef.current = next;
|
|
3585
|
+
movesRef.current++;
|
|
3586
|
+
setBoard(next);
|
|
3587
|
+
setMoves(movesRef.current);
|
|
3588
|
+
setSolved(isSolved(next));
|
|
3589
|
+
}
|
|
3590
|
+
},
|
|
3591
|
+
children: /* @__PURE__ */ jsx51("text", { style: textStyle({
|
|
3592
|
+
fg: solved ? theme.success : color,
|
|
3593
|
+
bold: true
|
|
3594
|
+
}), children: String(tile).padStart(2) })
|
|
3595
|
+
},
|
|
3596
|
+
idx
|
|
3597
|
+
);
|
|
3598
|
+
}) }, rowIdx)) }),
|
|
3599
|
+
/* @__PURE__ */ jsx51("box", { height: 1 }),
|
|
3600
|
+
/* @__PURE__ */ jsxs40("box", { flexDirection: "row", gap: 2, children: [
|
|
3601
|
+
/* @__PURE__ */ jsxs40("text", { style: textStyle({ dim: true, fg: theme.muted }), children: [
|
|
3602
|
+
"Moves: ",
|
|
3603
|
+
moves
|
|
3604
|
+
] }),
|
|
3605
|
+
solved && moves > 0 && /* @__PURE__ */ jsx51("text", { style: textStyle({ fg: theme.success, bold: true }), children: "Solved!" })
|
|
3606
|
+
] }),
|
|
3607
|
+
/* @__PURE__ */ jsx51("box", { flexGrow: 1 }),
|
|
3608
|
+
/* @__PURE__ */ jsx51("box", { paddingX: 1, children: /* @__PURE__ */ jsx51(StatusBar, { items: [
|
|
3609
|
+
{ key: "\u2191\u2193\u2190\u2192", label: "slide" },
|
|
3610
|
+
{ key: "click", label: "slide tile" },
|
|
3611
|
+
{ key: "r", label: "shuffle" }
|
|
3612
|
+
] }) })
|
|
3613
|
+
] });
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3081
3616
|
// src/landing/landing-app.tsx
|
|
3082
|
-
import { jsx as
|
|
3083
|
-
|
|
3617
|
+
import { Fragment as Fragment7, jsx as jsx52, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
3618
|
+
var DEMOS = ["ripple", "puzzle"];
|
|
3619
|
+
var TAB_HEIGHT = 2;
|
|
3620
|
+
var TAB_WIDTHS = DEMOS.map((n) => n.length + 4);
|
|
3621
|
+
var TAB_POSITIONS = [];
|
|
3622
|
+
var _pos = 0;
|
|
3623
|
+
for (const w of TAB_WIDTHS) {
|
|
3624
|
+
TAB_POSITIONS.push(_pos);
|
|
3625
|
+
_pos += w;
|
|
3626
|
+
}
|
|
3627
|
+
function LandingApp({ useKeyboard: useKeyboard23 }) {
|
|
3084
3628
|
const theme = useTheme();
|
|
3085
3629
|
const { width, height, isNarrow, isTiny, isMobile } = useBreakpoints();
|
|
3086
|
-
const
|
|
3087
|
-
const
|
|
3088
|
-
|
|
3089
|
-
|
|
3630
|
+
const [activeIndex, setActiveIndex] = useState29(0);
|
|
3631
|
+
const mousePosRef = useRef15(null);
|
|
3632
|
+
const matrixRipplesRef = useRef15([]);
|
|
3633
|
+
useKeyboard23((event) => {
|
|
3634
|
+
if (event.name === "tab") {
|
|
3635
|
+
setActiveIndex((prev) => (prev + 1) % DEMOS.length);
|
|
3636
|
+
event.preventDefault();
|
|
3637
|
+
}
|
|
3638
|
+
});
|
|
3639
|
+
const isBrowser2 = typeof document !== "undefined";
|
|
3640
|
+
const { clearRect, installLinksClearRect, boxTop } = useMemo8(() => {
|
|
3641
|
+
const logoHeight = isTiny ? 2 : isMobile ? 7 : isNarrow ? 13 : 7;
|
|
3642
|
+
const logoExtra = isBrowser2 ? 1 : 0;
|
|
3090
3643
|
const gap = isMobile ? 0 : 1;
|
|
3091
|
-
const
|
|
3644
|
+
const paddingTop = isMobile ? 1 : 3;
|
|
3645
|
+
const installLinksTop = paddingTop + logoHeight + logoExtra + gap;
|
|
3092
3646
|
const installLinksHeight = 3;
|
|
3093
|
-
const
|
|
3094
|
-
const bh = height -
|
|
3647
|
+
const boxTop2 = installLinksTop + installLinksHeight + gap + 1;
|
|
3648
|
+
const bh = height - boxTop2 - 1;
|
|
3649
|
+
const bw = Math.min(82, width - 2);
|
|
3650
|
+
const bl = Math.floor((width - bw) / 2);
|
|
3095
3651
|
return {
|
|
3096
|
-
clearRect: { top:
|
|
3097
|
-
installLinksClearRect: { top: installLinksTop, left: 1, width: width - 2, height: installLinksHeight }
|
|
3652
|
+
clearRect: { top: boxTop2, left: bl, width: bw, height: bh },
|
|
3653
|
+
installLinksClearRect: { top: installLinksTop, left: 1, width: width - 2, height: installLinksHeight },
|
|
3654
|
+
boxTop: boxTop2
|
|
3098
3655
|
};
|
|
3099
|
-
}, [width, height, isTiny, isNarrow, isMobile,
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3656
|
+
}, [width, height, isTiny, isNarrow, isMobile, isBrowser2]);
|
|
3657
|
+
const MAX_BOX_WIDTH = 82;
|
|
3658
|
+
const availableWidth = width - 2;
|
|
3659
|
+
const boxWidth = Math.min(MAX_BOX_WIDTH, availableWidth);
|
|
3660
|
+
const boxLeft = Math.floor((width - boxWidth) / 2);
|
|
3661
|
+
const mouseOffset = useMemo8(() => ({
|
|
3662
|
+
x: boxLeft + 1,
|
|
3663
|
+
// box left edge + border(1)
|
|
3664
|
+
y: boxTop + TAB_HEIGHT + 1
|
|
3665
|
+
// boxTop + tab rows + box top border(1)
|
|
3666
|
+
}), [boxTop, boxLeft]);
|
|
3667
|
+
const containerWidth = boxWidth - 2;
|
|
3668
|
+
const maxBoxHeight = 20;
|
|
3669
|
+
const containerHeight = Math.min(height - boxTop - 1 - TAB_HEIGHT, maxBoxHeight - TAB_HEIGHT);
|
|
3670
|
+
const activeStart = TAB_POSITIONS[activeIndex];
|
|
3671
|
+
const activeWidth = TAB_WIDTHS[activeIndex];
|
|
3672
|
+
const activeEnd = activeStart + activeWidth;
|
|
3673
|
+
const connectParts = [];
|
|
3674
|
+
if (activeStart === 0) {
|
|
3675
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2502" }, "cl"));
|
|
3676
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: " ".repeat(activeWidth - 2) }, "gap"));
|
|
3677
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2570" }, "cr"));
|
|
3678
|
+
} else {
|
|
3679
|
+
connectParts.push(
|
|
3680
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u256D" + "\u2500".repeat(activeStart - 1) }, "left")
|
|
3681
|
+
);
|
|
3682
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u256F" }, "cl"));
|
|
3683
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: " ".repeat(activeWidth - 2) }, "gap"));
|
|
3684
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2570" }, "cr"));
|
|
3685
|
+
}
|
|
3686
|
+
const rightFill = boxWidth - activeEnd - 1;
|
|
3687
|
+
if (rightFill > 0) {
|
|
3688
|
+
connectParts.push(
|
|
3689
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2500".repeat(rightFill) }, "right")
|
|
3690
|
+
);
|
|
3691
|
+
}
|
|
3692
|
+
connectParts.push(/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u256E" }, "corner-r"));
|
|
3693
|
+
return /* @__PURE__ */ jsxs41("box", { width: "100%", height: "100%", position: "relative", children: [
|
|
3694
|
+
/* @__PURE__ */ jsx52(MatrixBackground, { width, height, clearRect, clearRects: isBrowser2 ? void 0 : [installLinksClearRect], mousePosRef, ripplesRef: matrixRipplesRef }),
|
|
3695
|
+
/* @__PURE__ */ jsx52(
|
|
3696
|
+
"box",
|
|
3697
|
+
{
|
|
3698
|
+
position: "absolute",
|
|
3699
|
+
top: 0,
|
|
3700
|
+
left: 0,
|
|
3701
|
+
width,
|
|
3702
|
+
height,
|
|
3703
|
+
zIndex: 1,
|
|
3704
|
+
flexDirection: "column",
|
|
3705
|
+
shouldFill: false,
|
|
3706
|
+
onMouseMove: (e) => {
|
|
3707
|
+
mousePosRef.current = { x: e.x, y: e.y };
|
|
3708
|
+
},
|
|
3709
|
+
onMouseDown: (e) => {
|
|
3710
|
+
matrixRipplesRef.current = [
|
|
3711
|
+
...matrixRipplesRef.current,
|
|
3712
|
+
{ x: e.x, y: e.y, createdAt: Date.now() }
|
|
3713
|
+
];
|
|
3714
|
+
},
|
|
3715
|
+
children: /* @__PURE__ */ jsxs41("box", { flexGrow: 1, flexDirection: "column", paddingTop: isMobile ? 1 : 3, paddingLeft: 1, paddingRight: 1, paddingBottom: 1, gap: isMobile ? 0 : 1, shouldFill: false, children: [
|
|
3716
|
+
/* @__PURE__ */ jsx52("box", { flexShrink: 0, shouldFill: false, children: /* @__PURE__ */ jsx52(Logo, { compact: isTiny, narrow: isNarrow, mobile: isMobile }) }),
|
|
3717
|
+
/* @__PURE__ */ jsxs41("box", { flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: isMobile ? 0 : 1, flexShrink: 0, shouldFill: false, children: [
|
|
3718
|
+
!isMobile && /* @__PURE__ */ jsx52("box", { border: true, borderStyle: "rounded", borderColor: theme.border, paddingX: 1, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsxs41("text", { children: [
|
|
3719
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ dim: true }), children: "$ " }),
|
|
3720
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ bold: true }), children: "bunx " }),
|
|
3721
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.accent }), children: "@gridland/demo landing" })
|
|
3722
|
+
] }) }),
|
|
3723
|
+
!isMobile && /* @__PURE__ */ jsx52(InstallBox, {}),
|
|
3724
|
+
/* @__PURE__ */ jsx52(LinksBox, {})
|
|
3725
|
+
] }),
|
|
3726
|
+
/* @__PURE__ */ jsxs41("box", { flexDirection: "column", width: boxWidth, maxWidth: MAX_BOX_WIDTH, maxHeight: 20, alignSelf: "center", flexGrow: 1, children: [
|
|
3727
|
+
/* @__PURE__ */ jsx52("box", { height: 1, flexShrink: 0, flexDirection: "row", shouldFill: false, children: DEMOS.map((name2, i) => {
|
|
3728
|
+
const isActive = i === activeIndex;
|
|
3729
|
+
const w = TAB_WIDTHS[i];
|
|
3730
|
+
return /* @__PURE__ */ jsx52("box", { width: w, onMouseDown: () => setActiveIndex(i), children: /* @__PURE__ */ jsx52("text", { style: textStyle({ fg: theme.border }), children: isActive ? "\u256D" + "\u2500".repeat(w - 2) + "\u256E" : " ".repeat(w) }) }, name2);
|
|
3731
|
+
}) }),
|
|
3732
|
+
/* @__PURE__ */ jsx52("box", { height: 1, flexShrink: 0, flexDirection: "row", shouldFill: false, children: DEMOS.map((name2, i) => {
|
|
3733
|
+
const isActive = i === activeIndex;
|
|
3734
|
+
const w = TAB_WIDTHS[i];
|
|
3735
|
+
return /* @__PURE__ */ jsx52("box", { width: w, onMouseDown: () => setActiveIndex(i), children: /* @__PURE__ */ jsx52("text", { children: isActive ? /* @__PURE__ */ jsxs41(Fragment7, { children: [
|
|
3736
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2502" }),
|
|
3737
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ bold: true, fg: theme.foreground }), children: ` ${name2} ` }),
|
|
3738
|
+
/* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.border }), children: "\u2502" })
|
|
3739
|
+
] }) : /* @__PURE__ */ jsx52("span", { style: textStyle({ fg: theme.muted }), children: ` ${name2} ` }) }) }, name2);
|
|
3740
|
+
}) }),
|
|
3741
|
+
/* @__PURE__ */ jsxs41("box", { position: "relative", flexGrow: 1, children: [
|
|
3742
|
+
/* @__PURE__ */ jsx52("box", { position: "absolute", top: 0, left: 0, width: boxWidth, height: 1, zIndex: 2, children: /* @__PURE__ */ jsx52("text", { children: connectParts }) }),
|
|
3743
|
+
/* @__PURE__ */ jsxs41("box", { border: true, borderStyle: "rounded", borderColor: theme.border, flexGrow: 1, flexDirection: "column", overflow: "hidden", children: [
|
|
3744
|
+
activeIndex === 0 && /* @__PURE__ */ jsx52(RippleApp, { mouseOffset, containerWidth, containerHeight }),
|
|
3745
|
+
activeIndex === 1 && /* @__PURE__ */ jsx52(PuzzleApp, { containerWidth, containerHeight })
|
|
3746
|
+
] })
|
|
3747
|
+
] }),
|
|
3748
|
+
/* @__PURE__ */ jsx52("box", { height: 1 }),
|
|
3749
|
+
/* @__PURE__ */ jsx52("box", { width: "100%", alignItems: "center", flexDirection: "column", shouldFill: false, children: /* @__PURE__ */ jsxs41("text", { style: textStyle({ dim: true, fg: theme.muted }), children: [
|
|
3750
|
+
"Made with \u2764\uFE0F by ",
|
|
3751
|
+
/* @__PURE__ */ jsx52("a", { href: "https://cjroth.com", style: { attributes: 1 << 3, fg: theme.muted }, children: "Chris Roth" }),
|
|
3752
|
+
" + ",
|
|
3753
|
+
/* @__PURE__ */ jsx52("a", { href: "https://jessicacheng.studio", style: { attributes: 1 << 3, fg: theme.muted }, children: "Jessica Cheng" })
|
|
3754
|
+
] }) })
|
|
3755
|
+
] })
|
|
3756
|
+
] })
|
|
3757
|
+
}
|
|
3758
|
+
)
|
|
3115
3759
|
] });
|
|
3116
3760
|
}
|
|
3117
3761
|
|
|
3118
3762
|
// src/landing/matrix-rain.tsx
|
|
3119
|
-
import { jsx as
|
|
3763
|
+
import { jsx as jsx53 } from "react/jsx-runtime";
|
|
3120
3764
|
|
|
3121
3765
|
// src/landing/about-modal.tsx
|
|
3122
|
-
import { jsx as
|
|
3766
|
+
import { jsx as jsx54, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3123
3767
|
|
|
3124
3768
|
// demos/index.tsx
|
|
3125
|
-
import { jsx as
|
|
3769
|
+
import { jsx as jsx55 } from "react/jsx-runtime";
|
|
3126
3770
|
var demos = [
|
|
3127
|
-
{ name: "gradient", app: () => /* @__PURE__ */
|
|
3128
|
-
{ name: "ascii", app: () => /* @__PURE__ */
|
|
3129
|
-
{ name: "table", app: () => /* @__PURE__ */
|
|
3130
|
-
{ name: "spinner", app: () => /* @__PURE__ */
|
|
3131
|
-
{ name: "select-input", app: () => /* @__PURE__ */
|
|
3132
|
-
{ name: "multi-select", app: () => /* @__PURE__ */
|
|
3133
|
-
{ name: "prompt-input", app: () => /* @__PURE__ */
|
|
3134
|
-
{ name: "text-input", app: () => /* @__PURE__ */
|
|
3135
|
-
{ name: "link", app: () => /* @__PURE__ */
|
|
3136
|
-
{ name: "tabs", app: () => /* @__PURE__ */
|
|
3137
|
-
{ name: "status-bar", app: () => /* @__PURE__ */
|
|
3138
|
-
{ name: "modal", app: () => /* @__PURE__ */
|
|
3139
|
-
{ name: "primitives", app: () => /* @__PURE__ */
|
|
3140
|
-
{ name: "chat", app: () => /* @__PURE__ */
|
|
3141
|
-
{ name: "chain-of-thought", app: () => /* @__PURE__ */
|
|
3142
|
-
{ name: "message", app: () => /* @__PURE__ */
|
|
3143
|
-
{ name: "terminal-window", app: () => /* @__PURE__ */
|
|
3144
|
-
{ name: "focus", app: () => /* @__PURE__ */
|
|
3145
|
-
{ name: "
|
|
3146
|
-
{ name: "
|
|
3147
|
-
{ name: "
|
|
3148
|
-
{ name: "
|
|
3149
|
-
{ name: "
|
|
3150
|
-
{ name: "
|
|
3771
|
+
{ name: "gradient", app: () => /* @__PURE__ */ jsx55(GradientApp, {}) },
|
|
3772
|
+
{ name: "ascii", app: () => /* @__PURE__ */ jsx55(AsciiApp, {}) },
|
|
3773
|
+
{ name: "table", app: () => /* @__PURE__ */ jsx55(TableApp, {}) },
|
|
3774
|
+
{ name: "spinner", app: () => /* @__PURE__ */ jsx55(SpinnerApp, {}) },
|
|
3775
|
+
{ name: "select-input", app: () => /* @__PURE__ */ jsx55(SelectInputApp, {}) },
|
|
3776
|
+
{ name: "multi-select", app: () => /* @__PURE__ */ jsx55(MultiSelectApp, {}) },
|
|
3777
|
+
{ name: "prompt-input", app: () => /* @__PURE__ */ jsx55(PromptInputApp, {}) },
|
|
3778
|
+
{ name: "text-input", app: () => /* @__PURE__ */ jsx55(TextInputApp, {}) },
|
|
3779
|
+
{ name: "link", app: () => /* @__PURE__ */ jsx55(LinkApp, {}) },
|
|
3780
|
+
{ name: "tabs", app: () => /* @__PURE__ */ jsx55(TabBarApp, {}) },
|
|
3781
|
+
{ name: "status-bar", app: () => /* @__PURE__ */ jsx55(StatusBarApp, {}) },
|
|
3782
|
+
{ name: "modal", app: () => /* @__PURE__ */ jsx55(ModalApp, {}) },
|
|
3783
|
+
{ name: "primitives", app: () => /* @__PURE__ */ jsx55(PrimitivesApp, {}) },
|
|
3784
|
+
{ name: "chat", app: () => /* @__PURE__ */ jsx55(ChatApp, {}) },
|
|
3785
|
+
{ name: "chain-of-thought", app: () => /* @__PURE__ */ jsx55(ChainOfThoughtApp, {}) },
|
|
3786
|
+
{ name: "message", app: () => /* @__PURE__ */ jsx55(MessageApp, {}) },
|
|
3787
|
+
{ name: "terminal-window", app: () => /* @__PURE__ */ jsx55(TerminalWindowApp, {}) },
|
|
3788
|
+
{ name: "focus-grid", app: () => /* @__PURE__ */ jsx55(FocusGridApp, {}) },
|
|
3789
|
+
{ name: "focus-chat", app: () => /* @__PURE__ */ jsx55(FocusChatApp, {}) },
|
|
3790
|
+
{ name: "focus", app: () => /* @__PURE__ */ jsx55(FocusApp, {}) },
|
|
3791
|
+
{ name: "pointer", app: () => /* @__PURE__ */ jsx55(PointerApp, {}) },
|
|
3792
|
+
{ name: "cursor-highlight", app: () => /* @__PURE__ */ jsx55(CursorHighlightApp, {}) },
|
|
3793
|
+
{ name: "text-style", app: () => /* @__PURE__ */ jsx55(TextStyleApp, {}) },
|
|
3794
|
+
{ name: "headless", app: () => /* @__PURE__ */ jsx55(HeadlessApp, {}) },
|
|
3795
|
+
{ name: "theming", app: () => /* @__PURE__ */ jsx55(ThemingApp, {}) },
|
|
3796
|
+
{ name: "landing", app: () => /* @__PURE__ */ jsx55(LandingApp, { useKeyboard: useKeyboard21 }) },
|
|
3797
|
+
{ name: "ripple", app: () => /* @__PURE__ */ jsx55(RippleApp, {}) },
|
|
3798
|
+
{ name: "puzzle", app: () => /* @__PURE__ */ jsx55(PuzzleApp, {}) }
|
|
3151
3799
|
];
|
|
3152
3800
|
|
|
3153
3801
|
// src/run.tsx
|
|
3154
|
-
import { jsx as
|
|
3802
|
+
import { jsx as jsx56 } from "react/jsx-runtime";
|
|
3155
3803
|
var _renderer;
|
|
3156
3804
|
function DemoShell({ children }) {
|
|
3157
|
-
|
|
3158
|
-
if (event.
|
|
3805
|
+
useKeyboard22((event) => {
|
|
3806
|
+
if (event.defaultPrevented) return;
|
|
3807
|
+
if (event.name === "escape") {
|
|
3159
3808
|
_renderer.destroy();
|
|
3160
3809
|
}
|
|
3161
3810
|
});
|
|
3162
|
-
return /* @__PURE__ */
|
|
3811
|
+
return /* @__PURE__ */ jsx56("box", { flexDirection: "column", flexGrow: 1, children });
|
|
3163
3812
|
}
|
|
3164
3813
|
async function runDemo(name2) {
|
|
3165
3814
|
const demo = demos.find((d) => d.name === name2);
|
|
@@ -3169,7 +3818,7 @@ async function runDemo(name2) {
|
|
|
3169
3818
|
process.exit(1);
|
|
3170
3819
|
}
|
|
3171
3820
|
_renderer = await createCliRenderer({ exitOnCtrlC: true });
|
|
3172
|
-
createRoot(_renderer).render(/* @__PURE__ */
|
|
3821
|
+
createRoot(_renderer).render(/* @__PURE__ */ jsx56(DemoShell, { children: demo.app() }));
|
|
3173
3822
|
}
|
|
3174
3823
|
var name = process.argv[2];
|
|
3175
3824
|
if (name) {
|