@gridland/demo 0.2.50 → 0.2.52

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