@n3rd-ai/ui 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,7 +45,7 @@ function ToastProvider({
45
45
  display: "flex",
46
46
  flexDirection: "column",
47
47
  gap: "var(--n3rd-space-2)",
48
- zIndex: 9998,
48
+ zIndex: "var(--n3rd-z-toast, 9998)",
49
49
  fontFamily: "var(--n3rd-font)",
50
50
  fontSize: "var(--n3rd-text-sm)"
51
51
  };
@@ -1,11 +1,13 @@
1
1
  "use client";
2
- export { useToast } from '../chunk-MZO6ECNX.js';
2
+ export { useToast } from '../chunk-P5L6UDFY.js';
3
3
  import { useState, useRef, useEffect, useCallback } from 'react';
4
4
 
5
5
  function useTypewriter({ text, speed = 50, delay = 0, onComplete }) {
6
6
  const [displayed, setDisplayed] = useState("");
7
7
  const [done, setDone] = useState(false);
8
8
  const hasRun = useRef(false);
9
+ const onCompleteRef = useRef(onComplete);
10
+ onCompleteRef.current = onComplete;
9
11
  useEffect(() => {
10
12
  if (hasRun.current) return;
11
13
  hasRun.current = true;
@@ -19,7 +21,7 @@ function useTypewriter({ text, speed = 50, delay = 0, onComplete }) {
19
21
  } else {
20
22
  clearInterval(interval);
21
23
  setDone(true);
22
- onComplete?.();
24
+ onCompleteRef.current?.();
23
25
  }
24
26
  }, speed);
25
27
  }, delay);
@@ -27,27 +29,26 @@ function useTypewriter({ text, speed = 50, delay = 0, onComplete }) {
27
29
  clearTimeout(timeout);
28
30
  clearInterval(interval);
29
31
  };
30
- }, [text, speed, delay, onComplete]);
32
+ }, [text, speed, delay]);
31
33
  return { displayed, done };
32
34
  }
33
35
  function useKeyboard(shortcuts) {
34
- const handleKeyDown = useCallback(
35
- (e) => {
36
- for (const shortcut of shortcuts) {
37
- const keyMatch = e.key.toLowerCase() === shortcut.key.toLowerCase();
38
- const ctrlMatch = (shortcut.ctrl ?? false) === e.ctrlKey;
39
- const metaMatch = (shortcut.meta ?? false) === e.metaKey;
40
- const shiftMatch = (shortcut.shift ?? false) === e.shiftKey;
41
- const altMatch = (shortcut.alt ?? false) === e.altKey;
42
- if (keyMatch && ctrlMatch && metaMatch && shiftMatch && altMatch) {
43
- e.preventDefault();
44
- shortcut.handler(e);
45
- return;
46
- }
36
+ const shortcutsRef = useRef(shortcuts);
37
+ shortcutsRef.current = shortcuts;
38
+ const handleKeyDown = useCallback((e) => {
39
+ for (const shortcut of shortcutsRef.current) {
40
+ const keyMatch = e.key.toLowerCase() === shortcut.key.toLowerCase();
41
+ const ctrlMatch = (shortcut.ctrl ?? false) === e.ctrlKey;
42
+ const metaMatch = (shortcut.meta ?? false) === e.metaKey;
43
+ const shiftMatch = (shortcut.shift ?? false) === e.shiftKey;
44
+ const altMatch = (shortcut.alt ?? false) === e.altKey;
45
+ if (keyMatch && ctrlMatch && metaMatch && shiftMatch && altMatch) {
46
+ e.preventDefault();
47
+ shortcut.handler(e);
48
+ return;
47
49
  }
48
- },
49
- [shortcuts]
50
- );
50
+ }
51
+ }, []);
51
52
  useEffect(() => {
52
53
  document.addEventListener("keydown", handleKeyDown);
53
54
  return () => document.removeEventListener("keydown", handleKeyDown);
package/dist/index.css CHANGED
@@ -17,6 +17,15 @@
17
17
  transform: translateY(0);
18
18
  }
19
19
  }
20
+ @media (max-width: 640px) {
21
+ .n3rd-nav {
22
+ padding: var(--n3rd-space-2) var(--n3rd-space-3);
23
+ font-size: var(--n3rd-text-xs);
24
+ }
25
+ .n3rd-footer-starfield {
26
+ display: none;
27
+ }
28
+ }
20
29
 
21
30
  /* src/components/layout/Box.css */
22
31
  .n3rd-box {
@@ -62,6 +71,13 @@
62
71
  line-height: var(--n3rd-line-height);
63
72
  }
64
73
 
74
+ /* src/components/layout/Grid.css */
75
+ @media (max-width: 640px) {
76
+ .n3rd-grid {
77
+ grid-template-columns: 1fr !important;
78
+ }
79
+ }
80
+
65
81
  /* src/components/display/Footer.css */
66
82
  .n3rd-footer {
67
83
  font-family: var(--n3rd-font);
@@ -90,6 +106,9 @@
90
106
  flex-direction: column;
91
107
  align-items: center;
92
108
  margin-bottom: 0;
109
+ max-width: 480px;
110
+ margin-left: auto;
111
+ margin-right: auto;
93
112
  }
94
113
  .n3rd-footer-sun-line {
95
114
  height: 6px;
@@ -104,6 +123,9 @@
104
123
  flex-direction: column;
105
124
  align-items: center;
106
125
  margin-bottom: var(--n3rd-space-6);
126
+ max-width: 480px;
127
+ margin-left: auto;
128
+ margin-right: auto;
107
129
  }
108
130
  .n3rd-footer-horizon-bright {
109
131
  width: 100%;
package/dist/index.d.ts CHANGED
@@ -276,8 +276,9 @@ interface ScanlineProps {
276
276
  declare function Scanline({ opacity }: ScanlineProps): react_jsx_runtime.JSX.Element;
277
277
 
278
278
  /**
279
- * 5-line block-letter font for ASCII art logos.
280
- * Each glyph is an array of 5 strings, all padded to the same width.
279
+ * 6-line block-letter font for ASCII art logos.
280
+ * Uses box-drawing characters (╗ ╣) for a 3D shadow effect.
281
+ * Each glyph is an array of 6 strings, all padded to the same width.
281
282
  */
282
283
  /**
283
284
  * Render a string as multi-line ASCII block art.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import "./index.css";
3
- import { ToastProvider } from './chunk-MZO6ECNX.js';
4
- export { ToastProvider, useToast } from './chunk-MZO6ECNX.js';
3
+ import { ToastProvider } from './chunk-P5L6UDFY.js';
4
+ export { ToastProvider, useToast } from './chunk-P5L6UDFY.js';
5
5
  import { getBorderChars } from './chunk-CBVIEAN7.js';
6
6
  export { BORDER_CHARS, getBorderChars } from './chunk-CBVIEAN7.js';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -119,7 +119,7 @@ function Grid({ children, columns = 3, gap = "md", className, style }) {
119
119
  gap: GAP_MAP3[gap],
120
120
  ...style
121
121
  };
122
- return /* @__PURE__ */ jsx("div", { className, style: gridStyle, children });
122
+ return /* @__PURE__ */ jsx("div", { className: `n3rd-grid ${className ?? ""}`, style: gridStyle, children });
123
123
  }
124
124
  var CHARS = {
125
125
  single: "\u2500",
@@ -168,6 +168,7 @@ function Page({ children, maxWidth = "1200px", className, style }) {
168
168
  margin: "0 auto",
169
169
  padding: "var(--n3rd-space-6) var(--n3rd-space-4)",
170
170
  minHeight: "100vh",
171
+ overflowX: "hidden",
171
172
  ...style
172
173
  };
173
174
  return /* @__PURE__ */ jsx("main", { className, style: pageStyle, children });
@@ -356,6 +357,7 @@ function Table({ columns, rows, border = "single", className, style }) {
356
357
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx(
357
358
  "th",
358
359
  {
360
+ scope: "col",
359
361
  style: {
360
362
  textAlign: "left",
361
363
  padding: "var(--n3rd-space-2)",
@@ -473,57 +475,57 @@ function List({ items, bullet = ">", className, style }) {
473
475
 
474
476
  // src/primitives/ascii-font.ts
475
477
  var GLYPHS = {
476
- A: [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588"],
477
- B: ["\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 "],
478
- C: [" \u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588"],
479
- D: ["\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588 ", "\u2588\u2588\u2588\u2588 "],
480
- E: ["\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
481
- F: ["\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 "],
482
- G: [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
483
- H: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588"],
484
- I: ["\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", "\u2588\u2588\u2588\u2588"],
485
- J: [" \u2588\u2588\u2588\u2588", " \u2588\u2588", " \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
486
- K: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588 ", "\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588 ", "\u2588\u2588 \u2588\u2588"],
487
- L: ["\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
488
- M: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588"],
489
- N: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588"],
490
- O: [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
491
- P: ["\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588 "],
492
- Q: [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588 ", " \u2588\u2588 \u2588\u2588"],
493
- R: ["\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588 ", "\u2588\u2588 \u2588\u2588"],
494
- S: [" \u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 "],
495
- T: ["\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "],
496
- U: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
497
- V: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588 "],
498
- W: ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588 \u2588\u2588", "\u2588\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588"],
499
- X: ["\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588"],
500
- Y: ["\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "],
501
- Z: ["\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
478
+ A: [" \u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u255D"],
479
+ B: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
480
+ C: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2551 ", "\u2588\u2588\u2551 ", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D"],
481
+ D: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
482
+ E: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u255D ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
483
+ F: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u255D ", "\u2588\u2588\u2551 ", "\u255A\u2550\u255D "],
484
+ G: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ", "\u2588\u2588\u2551 \u2588\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
485
+ H: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u255D"],
486
+ I: ["\u2588\u2588\u2557", "\u2588\u2588\u2551", "\u2588\u2588\u2551", "\u2588\u2588\u2551", "\u2588\u2588\u2551", "\u255A\u2550\u255D"],
487
+ J: [" \u2588\u2588\u2557", " \u2588\u2588\u2551", " \u2588\u2588\u2551", "\u2588\u2588 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u255D "],
488
+ K: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2554\u255D", "\u2588\u2588\u2588\u2588\u2588\u2554\u255D ", "\u2588\u2588\u2554\u2550\u2588\u2588\u2557 ", "\u2588\u2588\u2551 \u2588\u2588\u2557", "\u255A\u2550\u255D \u255A\u2550\u255D"],
489
+ L: ["\u2588\u2588\u2557 ", "\u2588\u2588\u2551 ", "\u2588\u2588\u2551 ", "\u2588\u2588\u2551 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
490
+ M: ["\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551", "\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551", "\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551", "\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u255D"],
491
+ N: ["\u2588\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551", "\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551", "\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551", "\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D"],
492
+ O: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
493
+ P: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2550\u255D ", "\u2588\u2588\u2551 ", "\u255A\u2550\u255D "],
494
+ Q: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551\u2584\u2584 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2580\u2580\u2550\u255D "],
495
+ R: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u255D"],
496
+ S: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
497
+ T: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D", " \u2588\u2588\u2551 ", " \u2588\u2588\u2551 ", " \u2588\u2588\u2551 ", " \u255A\u2550\u255D "],
498
+ U: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
499
+ V: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D", " \u255A\u2588\u2588\u2588\u2588\u2554\u255D ", " \u255A\u2550\u2550\u2550\u255D "],
500
+ W: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2557 \u2588\u2588\u2551", "\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D "],
501
+ X: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D", " \u255A\u2588\u2588\u2588\u2554\u255D ", " \u2588\u2588\u2554\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u255D \u2588\u2588\u2557", "\u255A\u2550\u255D \u255A\u2550\u255D"],
502
+ Y: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D", " \u255A\u2588\u2588\u2588\u2588\u2554\u255D ", " \u255A\u2588\u2588\u2554\u255D ", " \u2588\u2588\u2551 ", " \u255A\u2550\u255D "],
503
+ Z: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2588\u2588\u2588\u2554\u255D", " \u2588\u2588\u2588\u2554\u255D ", " \u2588\u2588\u2588\u2554\u255D ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
502
504
  // Numbers
503
- "0": [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
504
- "1": [" \u2588\u2588 ", "\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", "\u2588\u2588\u2588\u2588"],
505
- "2": [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
506
- "3": ["\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 "],
507
- "4": ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588", " \u2588\u2588"],
508
- "5": ["\u2588\u2588\u2588\u2588\u2588\u2588", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588", "\u2588\u2588\u2588\u2588\u2588 "],
509
- "6": [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
510
- "7": ["\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "],
511
- "8": [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
512
- "9": [" \u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588", " \u2588\u2588", " \u2588\u2588\u2588\u2588 "],
505
+ "0": [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
506
+ "1": [" \u2588\u2588\u2557", "\u2588\u2588\u2588\u2551", "\u255A\u2588\u2588\u2551", " \u2588\u2588\u2551", " \u2588\u2588\u2551", " \u255A\u2550\u255D"],
507
+ "2": ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2557", " \u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2550\u255D ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
508
+ "3": ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2557", " \u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
509
+ "4": ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551", " \u2588\u2588\u2551", " \u255A\u2550\u255D"],
510
+ "5": ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
511
+ "6": [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u255D "],
512
+ "7": ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551", " \u2588\u2588\u2554\u255D", " \u2588\u2588\u2554\u255D ", " \u2588\u2588\u2551 ", " \u255A\u2550\u255D "],
513
+ "8": [" \u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u255D "],
514
+ "9": [" \u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2551", " \u255A\u2550\u2550\u2550\u2588\u2588\u2551", " \u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u255D "],
513
515
  // Symbols
514
- ".": [" ", " ", " ", " ", "\u2588\u2588"],
515
- ",": [" ", " ", " ", "\u2588\u2588", "\u2588 "],
516
- "!": ["\u2588\u2588", "\u2588\u2588", "\u2588\u2588", " ", "\u2588\u2588"],
517
- "?": ["\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588", " \u2588\u2588 ", " ", " \u2588\u2588 "],
518
- "-": [" ", " ", "\u2588\u2588\u2588\u2588\u2588\u2588", " ", " "],
519
- _: [" ", " ", " ", " ", "\u2588\u2588\u2588\u2588\u2588\u2588"],
520
- ":": [" ", "\u2588\u2588", " ", "\u2588\u2588", " "],
521
- "/": [" \u2588\u2588", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", "\u2588\u2588 "],
522
- "@": [" \u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588\u2588", "\u2588\u2588 \u2588\u2588\u2588\u2588", "\u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588 "],
523
- "#": [" \u2588\u2588 \u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 \u2588\u2588 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588", " \u2588\u2588 \u2588\u2588 "],
524
- " ": [" ", " ", " ", " ", " "]
516
+ ".": [" ", " ", " ", " ", "\u2588\u2588\u2557", "\u255A\u2550\u255D"],
517
+ ",": [" ", " ", " ", "\u2584\u2588\u2557", "\u255A\u2588\u2551", " \u255A\u255D"],
518
+ "!": ["\u2588\u2588\u2557", "\u2588\u2588\u2551", "\u2588\u2588\u2551", "\u255A\u2550\u255D", "\u2588\u2588\u2557", "\u255A\u2550\u255D"],
519
+ "?": ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2557", " \u2584\u2588\u2588\u2554\u2550\u255D", " \u255A\u2550\u255D ", " \u2588\u2588\u2557 ", " \u255A\u2550\u255D "],
520
+ "-": [" ", " ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D", " ", " "],
521
+ _: [" ", " ", " ", " ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
522
+ ":": [" ", "\u2588\u2588\u2557", "\u255A\u2550\u255D", "\u2588\u2588\u2557", "\u255A\u2550\u255D", " "],
523
+ "/": [" \u2588\u2588\u2557", " \u2588\u2588\u2554\u255D", " \u2588\u2588\u2554\u255D ", " \u2588\u2588\u2554\u255D ", "\u2588\u2588\u2554\u255D ", "\u255A\u2550\u255D "],
524
+ "@": [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551\u2588\u2588\u2557\u2588\u2588\u2551", "\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
525
+ "#": [" \u2588\u2588\u2557 \u2588\u2588\u2557 ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2588\u2588\u2554\u2550\u2588\u2588\u2554\u255D", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2588\u2588\u2554\u2550\u2588\u2588\u2554\u255D", " \u255A\u2550\u255D \u255A\u2550\u255D "],
526
+ " ": [" ", " ", " ", " ", " ", " "]
525
527
  };
526
- var LINE_COUNT = 5;
528
+ var LINE_COUNT = 6;
527
529
  function renderAsciiText(input) {
528
530
  const chars = input.toUpperCase().split("");
529
531
  const glyphs = chars.map((ch) => GLYPHS[ch] ?? GLYPHS[" "]);
@@ -547,7 +549,7 @@ function Logo({ text, gradient = false, accent, className, style }) {
547
549
  const gradientValue = typeof gradient === "string" ? gradient : "var(--n3rd-gradient)";
548
550
  const containerStyle = {
549
551
  fontFamily: "var(--n3rd-font)",
550
- fontSize: "var(--n3rd-text-sm)",
552
+ fontSize: "var(--n3rd-text-base)",
551
553
  fontWeight: 700,
552
554
  whiteSpace: "pre",
553
555
  lineHeight: 1,
@@ -845,6 +847,7 @@ function Progress({
845
847
  style: progressStyle,
846
848
  role: "progressbar",
847
849
  "aria-valuenow": value,
850
+ "aria-valuemin": 0,
848
851
  "aria-valuemax": max,
849
852
  children: [
850
853
  /* @__PURE__ */ jsxs("span", { children: [
@@ -899,6 +902,8 @@ function Typewriter({
899
902
  const [displayed, setDisplayed] = useState("");
900
903
  const [done, setDone] = useState(false);
901
904
  const hasRun = useRef(false);
905
+ const onCompleteRef = useRef(onComplete);
906
+ onCompleteRef.current = onComplete;
902
907
  useEffect(() => {
903
908
  if (hasRun.current) return;
904
909
  hasRun.current = true;
@@ -912,7 +917,7 @@ function Typewriter({
912
917
  } else {
913
918
  clearInterval(interval);
914
919
  setDone(true);
915
- onComplete?.();
920
+ onCompleteRef.current?.();
916
921
  }
917
922
  }, speed);
918
923
  }, delay);
@@ -920,7 +925,7 @@ function Typewriter({
920
925
  clearTimeout(timeout);
921
926
  clearInterval(interval);
922
927
  };
923
- }, [text, speed, delay, onComplete]);
928
+ }, [text, speed, delay]);
924
929
  return /* @__PURE__ */ jsxs("span", { className, children: [
925
930
  displayed,
926
931
  !done && cursor !== false && /* @__PURE__ */ jsx(Cursor, { style: cursor })
@@ -934,7 +939,7 @@ function Scanline({ opacity = 0.03 }) {
934
939
  width: "100%",
935
940
  height: "100%",
936
941
  pointerEvents: "none",
937
- zIndex: 9999,
942
+ zIndex: "var(--n3rd-z-scanline, 9999)",
938
943
  background: `repeating-linear-gradient(
939
944
  0deg,
940
945
  transparent,
@@ -65,6 +65,17 @@ pre {
65
65
  font-family: var(--n3rd-font);
66
66
  }
67
67
 
68
+ table {
69
+ border-collapse: collapse;
70
+ border-spacing: 0;
71
+ }
72
+
73
+ th,
74
+ td {
75
+ padding: 0;
76
+ text-align: left;
77
+ }
78
+
68
79
  ::selection {
69
80
  background: var(--n3rd-accent-purple);
70
81
  color: var(--n3rd-bg-primary);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n3rd-ai/ui",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Terminal-first UI framework for Next.js. ASCII everything. Zero images. Pure text.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",