asterui 0.12.80 → 0.12.81

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.
@@ -1,146 +1,150 @@
1
- import { jsx as C } from "react/jsx-runtime";
2
- import { forwardRef as R, useRef as d, useImperativeHandle as T, useEffect as b } from "react";
3
- import p from "@xterm/xterm";
4
- import g from "@xterm/addon-fit";
5
- import { useTheme as D } from "../hooks/useTheme.js";
6
- const S = p.Terminal ?? p.Terminal, M = g.FitAddon ?? g.FitAddon;
7
- let y = !1;
8
- function H() {
9
- if (y || typeof document > "u") return;
10
- y = !0;
11
- const i = document.createElement("style");
12
- i.setAttribute("data-xterm", ""), i.textContent = ".xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}", document.head.appendChild(i);
1
+ import { jsx as D } from "react/jsx-runtime";
2
+ import { forwardRef as S, useRef as x, useImperativeHandle as M, useEffect as v } from "react";
3
+ import * as b from "@xterm/xterm";
4
+ import * as p from "@xterm/addon-fit";
5
+ import { useTheme as H } from "../hooks/useTheme.js";
6
+ const O = b.Terminal ?? b.default?.Terminal ?? b, $ = p.FitAddon ?? p.default?.FitAddon ?? p;
7
+ let B = !1;
8
+ function j() {
9
+ if (B || typeof document > "u") return;
10
+ B = !0;
11
+ const s = document.createElement("style");
12
+ s.setAttribute("data-xterm", ""), s.textContent = ".xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}", document.head.appendChild(s);
13
13
  }
14
- const O = R(({
15
- onData: i,
16
- onReady: v,
17
- readline: a = !1,
14
+ const X = S(({
15
+ onData: s,
16
+ onReady: k,
17
+ readline: g = !1,
18
18
  prompt: c = "$ ",
19
- onLine: w,
20
- options: B = {},
21
- className: k = "",
22
- style: I,
23
- "data-testid": z
24
- }, A) => {
25
- const u = d(null), o = d(null), x = d(null), { isDark: l, colors: t } = D(), f = d({
19
+ onLine: z,
20
+ options: I = {},
21
+ className: A = "",
22
+ style: F,
23
+ "data-testid": C
24
+ }, R) => {
25
+ const a = x(null), o = x(null), m = x(null), { isDark: l, colors: n } = H(), f = x({
26
26
  buffer: "",
27
27
  cursor: 0,
28
28
  history: [],
29
29
  historyIndex: -1,
30
30
  savedBuffer: ""
31
- }), h = () => ({
32
- background: t.background,
33
- foreground: t.foreground,
34
- cursor: t.primary,
35
- cursorAccent: t.background,
36
- selectionBackground: t.primary + "40",
37
- selectionForeground: t.foreground,
31
+ }), y = () => ({
32
+ background: n.background,
33
+ foreground: n.foreground,
34
+ cursor: n.primary,
35
+ cursorAccent: n.background,
36
+ selectionBackground: n.primary + "40",
37
+ selectionForeground: n.foreground,
38
38
  black: l ? "#000000" : "#2e3436",
39
- red: t.error,
40
- green: t.success,
41
- yellow: t.warning,
42
- blue: t.info,
43
- magenta: t.secondary,
44
- cyan: t.accent,
39
+ red: n.error,
40
+ green: n.success,
41
+ yellow: n.warning,
42
+ blue: n.info,
43
+ magenta: n.secondary,
44
+ cyan: n.accent,
45
45
  white: l ? "#d3d7cf" : "#eeeeec",
46
46
  brightBlack: "#555753",
47
- brightRed: t.error,
48
- brightGreen: t.success,
49
- brightYellow: t.warning,
50
- brightBlue: t.info,
51
- brightMagenta: t.secondary,
52
- brightCyan: t.accent,
47
+ brightRed: n.error,
48
+ brightGreen: n.success,
49
+ brightYellow: n.warning,
50
+ brightBlue: n.info,
51
+ brightMagenta: n.secondary,
52
+ brightCyan: n.accent,
53
53
  brightWhite: l ? "#eeeeec" : "#ffffff"
54
54
  });
55
- T(A, () => ({
55
+ M(R, () => ({
56
56
  terminal: o.current,
57
57
  write: (r) => o.current?.write(r),
58
58
  writeln: (r) => o.current?.writeln(r),
59
59
  clear: () => o.current?.clear(),
60
60
  focus: () => o.current?.focus(),
61
- fit: () => x.current?.fit(),
61
+ fit: () => m.current?.fit(),
62
62
  history: f.current.history,
63
63
  clearHistory: () => {
64
64
  f.current.history = [];
65
65
  }
66
66
  }), []);
67
- const s = () => {
67
+ const u = () => {
68
68
  const r = o.current;
69
69
  if (!r) return;
70
- const n = f.current;
71
- r.write("\r\x1B[K" + c + n.buffer);
72
- const e = n.buffer.length - n.cursor;
70
+ const t = f.current;
71
+ r.write("\r\x1B[K" + c + t.buffer);
72
+ const e = t.buffer.length - t.cursor;
73
73
  e > 0 && r.write(`\x1B[${e}D`);
74
- }, F = (r) => {
75
- const n = o.current;
76
- if (!n) return;
74
+ }, T = (r) => {
75
+ const t = o.current;
76
+ if (!t) return;
77
77
  const e = f.current;
78
78
  if (r === "\x1B[A") {
79
- e.history.length > 0 && e.historyIndex < e.history.length - 1 && (e.historyIndex === -1 && (e.savedBuffer = e.buffer), e.historyIndex++, e.buffer = e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, s());
79
+ e.history.length > 0 && e.historyIndex < e.history.length - 1 && (e.historyIndex === -1 && (e.savedBuffer = e.buffer), e.historyIndex++, e.buffer = e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, u());
80
80
  return;
81
81
  }
82
82
  if (r === "\x1B[B") {
83
- e.historyIndex > -1 && (e.historyIndex--, e.buffer = e.historyIndex === -1 ? e.savedBuffer : e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, s());
83
+ e.historyIndex > -1 && (e.historyIndex--, e.buffer = e.historyIndex === -1 ? e.savedBuffer : e.history[e.history.length - 1 - e.historyIndex], e.cursor = e.buffer.length, u());
84
84
  return;
85
85
  }
86
86
  if (r === "\x1B[C") {
87
- e.cursor < e.buffer.length && (e.cursor++, n.write("\x1B[C"));
87
+ e.cursor < e.buffer.length && (e.cursor++, t.write("\x1B[C"));
88
88
  return;
89
89
  }
90
90
  if (r === "\x1B[D") {
91
- e.cursor > 0 && (e.cursor--, n.write("\x1B[D"));
91
+ e.cursor > 0 && (e.cursor--, t.write("\x1B[D"));
92
92
  return;
93
93
  }
94
94
  if (r === "\x1B[H" || r === "\x1BOH" || r === "\x1B[1~") {
95
- e.cursor > 0 && (n.write(`\x1B[${e.cursor}D`), e.cursor = 0);
95
+ e.cursor > 0 && (t.write(`\x1B[${e.cursor}D`), e.cursor = 0);
96
96
  return;
97
97
  }
98
98
  if (r === "\x1B[F" || r === "\x1BOF" || r === "\x1B[4~") {
99
- e.cursor < e.buffer.length && (n.write(`\x1B[${e.buffer.length - e.cursor}C`), e.cursor = e.buffer.length);
99
+ e.cursor < e.buffer.length && (t.write(`\x1B[${e.buffer.length - e.cursor}C`), e.cursor = e.buffer.length);
100
100
  return;
101
101
  }
102
102
  if (r === "\x1B[3~") {
103
- e.cursor < e.buffer.length && (e.buffer = e.buffer.slice(0, e.cursor) + e.buffer.slice(e.cursor + 1), s());
103
+ e.cursor < e.buffer.length && (e.buffer = e.buffer.slice(0, e.cursor) + e.buffer.slice(e.cursor + 1), u());
104
104
  return;
105
105
  }
106
106
  if (!r.startsWith("\x1B"))
107
107
  if (r === "\r") {
108
- n.writeln("");
109
- const m = e.buffer;
110
- m.trim() && e.history.push(m), e.buffer = "", e.cursor = 0, e.historyIndex = -1, e.savedBuffer = "", w?.(m), n.write(c);
111
- } else r === "" || r === "\b" ? e.cursor > 0 && (e.buffer = e.buffer.slice(0, e.cursor - 1) + e.buffer.slice(e.cursor), e.cursor--, s()) : r === "" ? (n.writeln("^C"), e.buffer = "", e.cursor = 0, e.historyIndex = -1, n.write(c)) : (r >= " " || r === " ") && (e.buffer = e.buffer.slice(0, e.cursor) + r + e.buffer.slice(e.cursor), e.cursor += r.length, s());
108
+ t.writeln("");
109
+ const i = e.buffer;
110
+ i.trim() && e.history.push(i), e.buffer = "", e.cursor = 0, e.historyIndex = -1, e.savedBuffer = "", z?.(i), t.write(c);
111
+ } else r === "" || r === "\b" ? e.cursor > 0 && (e.buffer = e.buffer.slice(0, e.cursor - 1) + e.buffer.slice(e.cursor), e.cursor--, u()) : r === "" ? (t.writeln("^C"), e.buffer = "", e.cursor = 0, e.historyIndex = -1, t.write(c)) : (r >= " " || r === " ") && (e.buffer = e.buffer.slice(0, e.cursor) + r + e.buffer.slice(e.cursor), e.cursor += r.length, u());
112
112
  };
113
- return b(() => {
114
- if (!u.current) return;
115
- H();
116
- const r = new S({
117
- theme: h(),
118
- cursorBlink: !0,
119
- fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
120
- fontSize: 14,
121
- ...B
122
- }), n = new M();
123
- r.loadAddon(n), r.open(u.current), n.fit(), o.current = r, x.current = n, a ? r.onData(F) : i && r.onData(i), v?.(r), a && r.write(c);
124
- const e = new ResizeObserver(() => {
125
- n.fit();
126
- });
127
- return e.observe(u.current), () => {
128
- e.disconnect(), r.dispose(), o.current = null, x.current = null;
113
+ return v(() => {
114
+ if (!a.current) return;
115
+ j();
116
+ const r = a.current;
117
+ let t = null, e = null, i = null, h = !1;
118
+ const w = () => {
119
+ if (h || !r) return;
120
+ const d = r.getBoundingClientRect();
121
+ d.width === 0 || d.height === 0 || (h = !0, t = new O({
122
+ theme: y(),
123
+ cursorBlink: !0,
124
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
125
+ fontSize: 14,
126
+ ...I
127
+ }), e = new $(), t.loadAddon(e), t.open(r), e.fit(), o.current = t, m.current = e, g ? t.onData(T) : s && t.onData(s), k?.(t), g && t.write(c));
129
128
  };
130
- }, []), b(() => {
131
- o.current && (o.current.options.theme = h());
132
- }, [l, t]), /* @__PURE__ */ C(
129
+ return i = new ResizeObserver((d) => {
130
+ d[0] && (h ? e && e.fit() : w());
131
+ }), i.observe(r), requestAnimationFrame(w), () => {
132
+ i?.disconnect(), t?.dispose(), o.current = null, m.current = null;
133
+ };
134
+ }, []), v(() => {
135
+ o.current && (o.current.options.theme = y());
136
+ }, [l, n]), /* @__PURE__ */ D(
133
137
  "div",
134
138
  {
135
- ref: u,
136
- className: k,
137
- style: { width: "100%", height: "100%", ...I },
138
- "data-testid": z
139
+ ref: a,
140
+ className: A,
141
+ style: { width: "100%", height: "100%", ...F },
142
+ "data-testid": C
139
143
  }
140
144
  );
141
145
  });
142
- O.displayName = "Terminal";
146
+ X.displayName = "Terminal";
143
147
  export {
144
- O as Terminal
148
+ X as Terminal
145
149
  };
146
150
  //# sourceMappingURL=Terminal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Terminal.js","sources":["../../src/components/Terminal.tsx"],"sourcesContent":["import React, { useEffect, useRef, useImperativeHandle, forwardRef } from 'react'\nimport XTermPkg from '@xterm/xterm'\nimport FitAddonPkg from '@xterm/addon-fit'\nimport type { Terminal as XTermType, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm'\nimport type { FitAddon as FitAddonType } from '@xterm/addon-fit'\nimport { useTheme } from '../hooks/useTheme'\n\nconst XTerm = XTermPkg.Terminal ?? (XTermPkg as unknown as { Terminal: typeof XTermPkg.Terminal }).Terminal\nconst FitAddon = FitAddonPkg.FitAddon ?? (FitAddonPkg as unknown as { FitAddon: typeof FitAddonPkg.FitAddon }).FitAddon\n\n// Inject xterm.css once (inlined for reliability across bundlers)\nlet cssInjected = false\nfunction injectXtermCSS() {\n if (cssInjected || typeof document === 'undefined') return\n cssInjected = true\n\n const style = document.createElement('style')\n style.setAttribute('data-xterm', '')\n style.textContent = `.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}`\n document.head.appendChild(style)\n}\n\nexport interface TerminalRef {\n /** The underlying xterm.js Terminal instance */\n terminal: XTermType | null\n /** Write data to the terminal */\n write: (data: string) => void\n /** Write a line to the terminal (with newline) */\n writeln: (data: string) => void\n /** Clear the terminal */\n clear: () => void\n /** Focus the terminal */\n focus: () => void\n /** Fit the terminal to its container */\n fit: () => void\n /** Command history (only available with readline mode) */\n history: string[]\n /** Clear command history (only available with readline mode) */\n clearHistory: () => void\n}\n\nexport interface TerminalProps {\n /** Callback when user types in the terminal (raw input) */\n onData?: (data: string) => void\n /** Callback when terminal is ready */\n onReady?: (terminal: XTermType) => void\n /** Enable readline mode with line editing and history */\n readline?: boolean\n /** Prompt string for readline mode (supports ANSI colors) */\n prompt?: string\n /** Callback when user submits a line in readline mode */\n onLine?: (line: string) => void\n /** xterm.js options (theme is auto-applied unless you override it) */\n options?: ITerminalOptions & ITerminalInitOnlyOptions\n /** Additional CSS classes for the container */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n 'data-testid'?: string\n}\n\nexport const Terminal = forwardRef<TerminalRef, TerminalProps>(({\n onData,\n onReady,\n readline = false,\n prompt = '$ ',\n onLine,\n options = {},\n className = '',\n style,\n 'data-testid': testId,\n}, ref) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const terminalRef = useRef<XTermType | null>(null)\n const fitAddonRef = useRef<FitAddonType | null>(null)\n const { isDark, colors } = useTheme()\n\n // Readline state\n const readlineState = useRef({\n buffer: '',\n cursor: 0,\n history: [] as string[],\n historyIndex: -1,\n savedBuffer: '',\n })\n\n // Build theme from DaisyUI colors\n const getTheme = () => ({\n background: colors.background,\n foreground: colors.foreground,\n cursor: colors.primary,\n cursorAccent: colors.background,\n selectionBackground: colors.primary + '40',\n selectionForeground: colors.foreground,\n black: isDark ? '#000000' : '#2e3436',\n red: colors.error,\n green: colors.success,\n yellow: colors.warning,\n blue: colors.info,\n magenta: colors.secondary,\n cyan: colors.accent,\n white: isDark ? '#d3d7cf' : '#eeeeec',\n brightBlack: '#555753',\n brightRed: colors.error,\n brightGreen: colors.success,\n brightYellow: colors.warning,\n brightBlue: colors.info,\n brightMagenta: colors.secondary,\n brightCyan: colors.accent,\n brightWhite: isDark ? '#eeeeec' : '#ffffff',\n })\n\n useImperativeHandle(ref, () => ({\n terminal: terminalRef.current,\n write: (data: string) => terminalRef.current?.write(data),\n writeln: (data: string) => terminalRef.current?.writeln(data),\n clear: () => terminalRef.current?.clear(),\n focus: () => terminalRef.current?.focus(),\n fit: () => fitAddonRef.current?.fit(),\n history: readlineState.current.history,\n clearHistory: () => { readlineState.current.history = [] },\n }), [])\n\n // Redraw the current line in readline mode\n const redrawLine = () => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n // Move to start of line, clear line, write prompt + buffer, position cursor\n term.write('\\r\\x1b[K' + prompt + s.buffer)\n // Move cursor to correct position\n const moveBack = s.buffer.length - s.cursor\n if (moveBack > 0) {\n term.write(`\\x1b[${moveBack}D`)\n }\n }\n\n // Handle readline input\n const handleReadlineData = (data: string) => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n\n // Handle escape sequences (arrow keys)\n if (data === '\\x1b[A') {\n // Up arrow - history previous\n if (s.history.length > 0 && s.historyIndex < s.history.length - 1) {\n if (s.historyIndex === -1) s.savedBuffer = s.buffer\n s.historyIndex++\n s.buffer = s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[B') {\n // Down arrow - history next\n if (s.historyIndex > -1) {\n s.historyIndex--\n s.buffer = s.historyIndex === -1 ? s.savedBuffer : s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[C') {\n // Right arrow\n if (s.cursor < s.buffer.length) {\n s.cursor++\n term.write('\\x1b[C')\n }\n return\n }\n if (data === '\\x1b[D') {\n // Left arrow\n if (s.cursor > 0) {\n s.cursor--\n term.write('\\x1b[D')\n }\n return\n }\n if (data === '\\x1b[H' || data === '\\x1bOH' || data === '\\x1b[1~') {\n // Home - move to start of line\n if (s.cursor > 0) {\n term.write(`\\x1b[${s.cursor}D`)\n s.cursor = 0\n }\n return\n }\n if (data === '\\x1b[F' || data === '\\x1bOF' || data === '\\x1b[4~') {\n // End - move to end of line\n if (s.cursor < s.buffer.length) {\n term.write(`\\x1b[${s.buffer.length - s.cursor}C`)\n s.cursor = s.buffer.length\n }\n return\n }\n if (data === '\\x1b[3~') {\n // Delete key - delete character at cursor\n if (s.cursor < s.buffer.length) {\n s.buffer = s.buffer.slice(0, s.cursor) + s.buffer.slice(s.cursor + 1)\n redrawLine()\n }\n return\n }\n\n // Ignore other escape sequences\n if (data.startsWith('\\x1b')) return\n\n if (data === '\\r') {\n // Enter\n term.writeln('')\n const line = s.buffer\n if (line.trim()) {\n s.history.push(line)\n }\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n s.savedBuffer = ''\n onLine?.(line)\n term.write(prompt)\n } else if (data === '\\x7f' || data === '\\b') {\n // Backspace\n if (s.cursor > 0) {\n s.buffer = s.buffer.slice(0, s.cursor - 1) + s.buffer.slice(s.cursor)\n s.cursor--\n redrawLine()\n }\n } else if (data === '\\x03') {\n // Ctrl+C\n term.writeln('^C')\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n term.write(prompt)\n } else if (data >= ' ' || data === '\\t') {\n // Printable characters\n s.buffer = s.buffer.slice(0, s.cursor) + data + s.buffer.slice(s.cursor)\n s.cursor += data.length\n redrawLine()\n }\n }\n\n // Initialize terminal\n useEffect(() => {\n if (!containerRef.current) return\n\n injectXtermCSS()\n\n const terminal = new XTerm({\n theme: getTheme(),\n cursorBlink: true,\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace',\n fontSize: 14,\n ...options,\n })\n const fitAddon = new FitAddon()\n\n terminal.loadAddon(fitAddon)\n terminal.open(containerRef.current)\n fitAddon.fit()\n\n terminalRef.current = terminal\n fitAddonRef.current = fitAddon\n\n if (readline) {\n terminal.onData(handleReadlineData)\n } else if (onData) {\n terminal.onData(onData)\n }\n\n onReady?.(terminal)\n\n // Write initial prompt after onReady so welcome messages appear first\n if (readline) {\n terminal.write(prompt)\n }\n\n const resizeObserver = new ResizeObserver(() => {\n fitAddon.fit()\n })\n resizeObserver.observe(containerRef.current)\n\n return () => {\n resizeObserver.disconnect()\n terminal.dispose()\n terminalRef.current = null\n fitAddonRef.current = null\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Update theme when colors change\n useEffect(() => {\n if (!terminalRef.current) return\n terminalRef.current.options.theme = getTheme()\n }, [isDark, colors]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ width: '100%', height: '100%', ...style }}\n data-testid={testId}\n />\n )\n})\n\nTerminal.displayName = 'Terminal'\n"],"names":["XTerm","XTermPkg","FitAddon","FitAddonPkg","cssInjected","injectXtermCSS","style","Terminal","forwardRef","onData","onReady","readline","prompt","onLine","options","className","testId","ref","containerRef","useRef","terminalRef","fitAddonRef","isDark","colors","useTheme","readlineState","getTheme","useImperativeHandle","data","redrawLine","term","s","moveBack","handleReadlineData","line","useEffect","terminal","fitAddon","resizeObserver","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Terminal.js","sources":["../../src/components/Terminal.tsx"],"sourcesContent":["import React, { useEffect, useRef, useImperativeHandle, forwardRef } from 'react'\nimport * as XTermPkg from '@xterm/xterm'\nimport * as FitAddonPkg from '@xterm/addon-fit'\nimport type { Terminal as XTermType, ITerminalOptions, ITerminalInitOnlyOptions } from '@xterm/xterm'\nimport type { FitAddon as FitAddonType } from '@xterm/addon-fit'\nimport { useTheme } from '../hooks/useTheme'\n\n// Handle both ESM and CJS module formats\nconst XTerm = (XTermPkg as { Terminal?: typeof XTermType }).Terminal\n ?? (XTermPkg as { default?: { Terminal: typeof XTermType } }).default?.Terminal\n ?? (XTermPkg as unknown as typeof XTermType)\nconst FitAddon = (FitAddonPkg as { FitAddon?: typeof FitAddonType }).FitAddon\n ?? (FitAddonPkg as { default?: { FitAddon: typeof FitAddonType } }).default?.FitAddon\n ?? (FitAddonPkg as unknown as typeof FitAddonType)\n\n// Inject xterm.css once (inlined for reliability across bundlers)\nlet cssInjected = false\nfunction injectXtermCSS() {\n if (cssInjected || typeof document === 'undefined') return\n cssInjected = true\n\n const style = document.createElement('style')\n style.setAttribute('data-xterm', '')\n style.textContent = `.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:.5}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}`\n document.head.appendChild(style)\n}\n\nexport interface TerminalRef {\n /** The underlying xterm.js Terminal instance */\n terminal: XTermType | null\n /** Write data to the terminal */\n write: (data: string) => void\n /** Write a line to the terminal (with newline) */\n writeln: (data: string) => void\n /** Clear the terminal */\n clear: () => void\n /** Focus the terminal */\n focus: () => void\n /** Fit the terminal to its container */\n fit: () => void\n /** Command history (only available with readline mode) */\n history: string[]\n /** Clear command history (only available with readline mode) */\n clearHistory: () => void\n}\n\nexport interface TerminalProps {\n /** Callback when user types in the terminal (raw input) */\n onData?: (data: string) => void\n /** Callback when terminal is ready */\n onReady?: (terminal: XTermType) => void\n /** Enable readline mode with line editing and history */\n readline?: boolean\n /** Prompt string for readline mode (supports ANSI colors) */\n prompt?: string\n /** Callback when user submits a line in readline mode */\n onLine?: (line: string) => void\n /** xterm.js options (theme is auto-applied unless you override it) */\n options?: ITerminalOptions & ITerminalInitOnlyOptions\n /** Additional CSS classes for the container */\n className?: string\n /** Container style */\n style?: React.CSSProperties\n 'data-testid'?: string\n}\n\nexport const Terminal = forwardRef<TerminalRef, TerminalProps>(({\n onData,\n onReady,\n readline = false,\n prompt = '$ ',\n onLine,\n options = {},\n className = '',\n style,\n 'data-testid': testId,\n}, ref) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const terminalRef = useRef<XTermType | null>(null)\n const fitAddonRef = useRef<FitAddonType | null>(null)\n const { isDark, colors } = useTheme()\n\n // Readline state\n const readlineState = useRef({\n buffer: '',\n cursor: 0,\n history: [] as string[],\n historyIndex: -1,\n savedBuffer: '',\n })\n\n // Build theme from DaisyUI colors\n const getTheme = () => ({\n background: colors.background,\n foreground: colors.foreground,\n cursor: colors.primary,\n cursorAccent: colors.background,\n selectionBackground: colors.primary + '40',\n selectionForeground: colors.foreground,\n black: isDark ? '#000000' : '#2e3436',\n red: colors.error,\n green: colors.success,\n yellow: colors.warning,\n blue: colors.info,\n magenta: colors.secondary,\n cyan: colors.accent,\n white: isDark ? '#d3d7cf' : '#eeeeec',\n brightBlack: '#555753',\n brightRed: colors.error,\n brightGreen: colors.success,\n brightYellow: colors.warning,\n brightBlue: colors.info,\n brightMagenta: colors.secondary,\n brightCyan: colors.accent,\n brightWhite: isDark ? '#eeeeec' : '#ffffff',\n })\n\n useImperativeHandle(ref, () => ({\n terminal: terminalRef.current,\n write: (data: string) => terminalRef.current?.write(data),\n writeln: (data: string) => terminalRef.current?.writeln(data),\n clear: () => terminalRef.current?.clear(),\n focus: () => terminalRef.current?.focus(),\n fit: () => fitAddonRef.current?.fit(),\n history: readlineState.current.history,\n clearHistory: () => { readlineState.current.history = [] },\n }), [])\n\n // Redraw the current line in readline mode\n const redrawLine = () => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n // Move to start of line, clear line, write prompt + buffer, position cursor\n term.write('\\r\\x1b[K' + prompt + s.buffer)\n // Move cursor to correct position\n const moveBack = s.buffer.length - s.cursor\n if (moveBack > 0) {\n term.write(`\\x1b[${moveBack}D`)\n }\n }\n\n // Handle readline input\n const handleReadlineData = (data: string) => {\n const term = terminalRef.current\n if (!term) return\n const s = readlineState.current\n\n // Handle escape sequences (arrow keys)\n if (data === '\\x1b[A') {\n // Up arrow - history previous\n if (s.history.length > 0 && s.historyIndex < s.history.length - 1) {\n if (s.historyIndex === -1) s.savedBuffer = s.buffer\n s.historyIndex++\n s.buffer = s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[B') {\n // Down arrow - history next\n if (s.historyIndex > -1) {\n s.historyIndex--\n s.buffer = s.historyIndex === -1 ? s.savedBuffer : s.history[s.history.length - 1 - s.historyIndex]\n s.cursor = s.buffer.length\n redrawLine()\n }\n return\n }\n if (data === '\\x1b[C') {\n // Right arrow\n if (s.cursor < s.buffer.length) {\n s.cursor++\n term.write('\\x1b[C')\n }\n return\n }\n if (data === '\\x1b[D') {\n // Left arrow\n if (s.cursor > 0) {\n s.cursor--\n term.write('\\x1b[D')\n }\n return\n }\n if (data === '\\x1b[H' || data === '\\x1bOH' || data === '\\x1b[1~') {\n // Home - move to start of line\n if (s.cursor > 0) {\n term.write(`\\x1b[${s.cursor}D`)\n s.cursor = 0\n }\n return\n }\n if (data === '\\x1b[F' || data === '\\x1bOF' || data === '\\x1b[4~') {\n // End - move to end of line\n if (s.cursor < s.buffer.length) {\n term.write(`\\x1b[${s.buffer.length - s.cursor}C`)\n s.cursor = s.buffer.length\n }\n return\n }\n if (data === '\\x1b[3~') {\n // Delete key - delete character at cursor\n if (s.cursor < s.buffer.length) {\n s.buffer = s.buffer.slice(0, s.cursor) + s.buffer.slice(s.cursor + 1)\n redrawLine()\n }\n return\n }\n\n // Ignore other escape sequences\n if (data.startsWith('\\x1b')) return\n\n if (data === '\\r') {\n // Enter\n term.writeln('')\n const line = s.buffer\n if (line.trim()) {\n s.history.push(line)\n }\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n s.savedBuffer = ''\n onLine?.(line)\n term.write(prompt)\n } else if (data === '\\x7f' || data === '\\b') {\n // Backspace\n if (s.cursor > 0) {\n s.buffer = s.buffer.slice(0, s.cursor - 1) + s.buffer.slice(s.cursor)\n s.cursor--\n redrawLine()\n }\n } else if (data === '\\x03') {\n // Ctrl+C\n term.writeln('^C')\n s.buffer = ''\n s.cursor = 0\n s.historyIndex = -1\n term.write(prompt)\n } else if (data >= ' ' || data === '\\t') {\n // Printable characters\n s.buffer = s.buffer.slice(0, s.cursor) + data + s.buffer.slice(s.cursor)\n s.cursor += data.length\n redrawLine()\n }\n }\n\n // Initialize terminal\n useEffect(() => {\n if (!containerRef.current) return\n\n injectXtermCSS()\n\n const container = containerRef.current\n let terminal: XTermType | null = null\n let fitAddon: FitAddonType | null = null\n let resizeObserver: ResizeObserver | null = null\n let initialized = false\n\n const initTerminal = () => {\n if (initialized || !container) return\n\n // Check container has dimensions before opening\n const rect = container.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return\n\n initialized = true\n\n terminal = new XTerm({\n theme: getTheme(),\n cursorBlink: true,\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace',\n fontSize: 14,\n ...options,\n })\n fitAddon = new FitAddon()\n\n terminal.loadAddon(fitAddon)\n terminal.open(container)\n fitAddon.fit()\n\n terminalRef.current = terminal\n fitAddonRef.current = fitAddon\n\n if (readline) {\n terminal.onData(handleReadlineData)\n } else if (onData) {\n terminal.onData(onData)\n }\n\n onReady?.(terminal)\n\n // Write initial prompt after onReady so welcome messages appear first\n if (readline) {\n terminal.write(prompt)\n }\n }\n\n // Use ResizeObserver to wait for container to have dimensions\n resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n\n if (!initialized) {\n initTerminal()\n } else if (fitAddon) {\n fitAddon.fit()\n }\n })\n resizeObserver.observe(container)\n\n // Also try immediately in case container already has dimensions\n requestAnimationFrame(initTerminal)\n\n return () => {\n resizeObserver?.disconnect()\n terminal?.dispose()\n terminalRef.current = null\n fitAddonRef.current = null\n }\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n // Update theme when colors change\n useEffect(() => {\n if (!terminalRef.current) return\n terminalRef.current.options.theme = getTheme()\n }, [isDark, colors]) // eslint-disable-line react-hooks/exhaustive-deps\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ width: '100%', height: '100%', ...style }}\n data-testid={testId}\n />\n )\n})\n\nTerminal.displayName = 'Terminal'\n"],"names":["XTerm","XTermPkg","FitAddon","FitAddonPkg","cssInjected","injectXtermCSS","style","Terminal","forwardRef","onData","onReady","readline","prompt","onLine","options","className","testId","ref","containerRef","useRef","terminalRef","fitAddonRef","isDark","colors","useTheme","readlineState","getTheme","useImperativeHandle","data","redrawLine","term","s","moveBack","handleReadlineData","line","useEffect","container","terminal","fitAddon","resizeObserver","initialized","initTerminal","rect","entries","jsx"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asterui",
3
- "version": "0.12.80",
3
+ "version": "0.12.81",
4
4
  "description": "React UI component library with DaisyUI",
5
5
  "homepage": "https://asterui.com",
6
6
  "repository": {