@mks2508/mks-ui 0.4.0 → 0.5.1

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.
Files changed (129) hide show
  1. package/dist/index.css +129 -0
  2. package/dist/react-ui/blocks/Terminal/TerminalDisplay.d.ts +46 -0
  3. package/dist/react-ui/blocks/Terminal/TerminalDisplay.d.ts.map +1 -0
  4. package/dist/react-ui/blocks/Terminal/TerminalDisplay.js +175 -0
  5. package/dist/react-ui/blocks/Terminal/TerminalDisplay.styles.d.ts +21 -0
  6. package/dist/react-ui/blocks/Terminal/TerminalDisplay.styles.d.ts.map +1 -0
  7. package/dist/react-ui/blocks/Terminal/TerminalDisplay.styles.js +31 -0
  8. package/dist/react-ui/blocks/Terminal/TerminalDisplay.types.d.ts +56 -0
  9. package/dist/react-ui/blocks/Terminal/TerminalDisplay.types.d.ts.map +1 -0
  10. package/dist/react-ui/blocks/Terminal/chrome.d.ts +14 -0
  11. package/dist/react-ui/blocks/Terminal/chrome.d.ts.map +1 -0
  12. package/dist/react-ui/blocks/Terminal/chrome.js +6 -0
  13. package/dist/react-ui/blocks/Terminal/components/LogLineBadges.d.ts +5 -5
  14. package/dist/react-ui/blocks/Terminal/components/LogLineBadges.d.ts.map +1 -1
  15. package/dist/react-ui/blocks/Terminal/display.d.ts +20 -0
  16. package/dist/react-ui/blocks/Terminal/display.d.ts.map +1 -0
  17. package/dist/react-ui/blocks/Terminal/display.js +9 -0
  18. package/dist/react-ui/blocks/Terminal/index.d.ts +4 -0
  19. package/dist/react-ui/blocks/Terminal/index.d.ts.map +1 -1
  20. package/dist/react-ui/blocks/Terminal/index.js +4 -1
  21. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.d.ts +7 -6
  22. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.d.ts.map +1 -1
  23. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.js +51 -30
  24. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.styles.d.ts +35 -0
  25. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.styles.d.ts.map +1 -0
  26. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.styles.js +57 -0
  27. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.types.d.ts +7 -2
  28. package/dist/react-ui/blocks/Terminal/panel/TerminalPanelChrome.types.d.ts.map +1 -1
  29. package/dist/react-ui/primitives/AutoHeight/index.d.ts +1 -1
  30. package/dist/react-ui/primitives/CountingNumber/index.d.ts +1 -1
  31. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts.map +1 -1
  32. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.js +2 -0
  33. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts.map +1 -1
  34. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.js +2 -0
  35. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts.map +1 -1
  36. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.js +2 -0
  37. package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts.map +1 -1
  38. package/dist/react-ui/primitives/waapi/Morph/useMorph.js +2 -0
  39. package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts.map +1 -1
  40. package/dist/react-ui/primitives/waapi/Reorder/useReorder.js +2 -0
  41. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts.map +1 -1
  42. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.js +2 -0
  43. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts +1 -1
  44. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts +1 -1
  45. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts.map +1 -1
  46. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.js +2 -0
  47. package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts.map +1 -1
  48. package/dist/react-ui/primitives/waapi/core/useElementRegistry.js +2 -0
  49. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts.map +1 -1
  50. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.js +2 -0
  51. package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts.map +1 -1
  52. package/dist/react-ui/primitives/waapi/core/usePositionCapture.js +2 -0
  53. package/dist/react-ui/ui/Accordion/Accordion.styles.d.ts +1 -1
  54. package/dist/react-ui/ui/Accordion/Accordion.types.d.ts +1 -1
  55. package/dist/react-ui/ui/AlertDialog/AlertDialog.styles.d.ts +1 -1
  56. package/dist/react-ui/ui/AlertDialog/AlertDialog.types.d.ts +1 -1
  57. package/dist/react-ui/ui/Badge/Badge.styles.d.ts +1 -1
  58. package/dist/react-ui/ui/Badge/Badge.types.d.ts +1 -1
  59. package/dist/react-ui/ui/Button/Button.styles.d.ts +1 -1
  60. package/dist/react-ui/ui/Button/Button.types.d.ts +1 -1
  61. package/dist/react-ui/ui/Card/Card.styles.d.ts +1 -1
  62. package/dist/react-ui/ui/Card/Card.types.d.ts +1 -1
  63. package/dist/react-ui/ui/Checkbox/Checkbox.styles.d.ts +1 -1
  64. package/dist/react-ui/ui/Checkbox/Checkbox.types.d.ts +1 -1
  65. package/dist/react-ui/ui/Combobox/Combobox.styles.d.ts +1 -1
  66. package/dist/react-ui/ui/Combobox/Combobox.types.d.ts +1 -1
  67. package/dist/react-ui/ui/CornerBracket/CornerBracket.styles.d.ts +1 -1
  68. package/dist/react-ui/ui/CornerBracket/CornerBracket.types.d.ts +1 -1
  69. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts +1 -1
  70. package/dist/react-ui/ui/DataCard/DataCard.types.d.ts +1 -1
  71. package/dist/react-ui/ui/DataCard/index.d.ts +1 -1
  72. package/dist/react-ui/ui/Dialog/Dialog.styles.d.ts +1 -1
  73. package/dist/react-ui/ui/Dialog/Dialog.types.d.ts +1 -1
  74. package/dist/react-ui/ui/DropdownMenu/DropdownMenu.styles.d.ts +1 -1
  75. package/dist/react-ui/ui/DropdownMenu/DropdownMenu.types.d.ts +1 -1
  76. package/dist/react-ui/ui/Field/Field.styles.d.ts +1 -1
  77. package/dist/react-ui/ui/Field/Field.types.d.ts +1 -1
  78. package/dist/react-ui/ui/Input/Input.styles.d.ts +1 -1
  79. package/dist/react-ui/ui/Input/Input.types.d.ts +1 -1
  80. package/dist/react-ui/ui/InputGroup/InputGroup.styles.d.ts +1 -1
  81. package/dist/react-ui/ui/InputGroup/InputGroup.types.d.ts +1 -1
  82. package/dist/react-ui/ui/InputGroup/index.d.ts.map +1 -1
  83. package/dist/react-ui/ui/InputGroup/index.js +2 -0
  84. package/dist/react-ui/ui/Label/Label.styles.d.ts +1 -1
  85. package/dist/react-ui/ui/Label/Label.types.d.ts +1 -1
  86. package/dist/react-ui/ui/Menu/Menu.styles.d.ts +1 -1
  87. package/dist/react-ui/ui/Menu/Menu.types.d.ts +2 -2
  88. package/dist/react-ui/ui/Popover/Popover.styles.d.ts +1 -1
  89. package/dist/react-ui/ui/Popover/Popover.types.d.ts +1 -1
  90. package/dist/react-ui/ui/Progress/Progress.styles.d.ts +1 -1
  91. package/dist/react-ui/ui/Progress/Progress.types.d.ts +2 -2
  92. package/dist/react-ui/ui/Select/Select.styles.d.ts +1 -1
  93. package/dist/react-ui/ui/Select/Select.types.d.ts +1 -1
  94. package/dist/react-ui/ui/Separator/Separator.styles.d.ts +1 -1
  95. package/dist/react-ui/ui/Separator/Separator.types.d.ts +1 -1
  96. package/dist/react-ui/ui/Switch/Switch.styles.d.ts +1 -1
  97. package/dist/react-ui/ui/Switch/Switch.types.d.ts +1 -1
  98. package/dist/react-ui/ui/Tabs/Tabs.styles.d.ts +1 -1
  99. package/dist/react-ui/ui/Tabs/Tabs.types.d.ts +3 -3
  100. package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts +1 -1
  101. package/dist/react-ui/ui/Textarea/Textarea.styles.d.ts +1 -1
  102. package/dist/react-ui/ui/Textarea/Textarea.types.d.ts +1 -1
  103. package/dist/react-ui/ui/Tooltip/Tooltip.styles.d.ts +1 -1
  104. package/dist/react-ui/ui/Tooltip/Tooltip.types.d.ts +1 -1
  105. package/package.json +41 -34
  106. package/src/css.d.ts +6 -0
  107. package/src/react-ui/blocks/Terminal/TerminalDisplay.styles.ts +38 -0
  108. package/src/react-ui/blocks/Terminal/TerminalDisplay.tsx +254 -0
  109. package/src/react-ui/blocks/Terminal/TerminalDisplay.types.ts +73 -0
  110. package/src/react-ui/blocks/Terminal/chrome.ts +25 -0
  111. package/src/react-ui/blocks/Terminal/display.ts +46 -0
  112. package/src/react-ui/blocks/Terminal/index.ts +8 -0
  113. package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.styles.ts +75 -0
  114. package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.tsx +69 -40
  115. package/src/react-ui/blocks/Terminal/panel/TerminalPanelChrome.types.ts +8 -2
  116. package/src/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.ts +1 -0
  117. package/src/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.ts +1 -0
  118. package/src/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.ts +1 -0
  119. package/src/react-ui/primitives/waapi/Morph/useMorph.ts +1 -0
  120. package/src/react-ui/primitives/waapi/Reorder/useReorder.ts +1 -0
  121. package/src/react-ui/primitives/waapi/Reorder/useReorderPresence.ts +1 -0
  122. package/src/react-ui/primitives/waapi/core/useAnimationOrchestrator.ts +1 -0
  123. package/src/react-ui/primitives/waapi/core/useElementRegistry.ts +1 -0
  124. package/src/react-ui/primitives/waapi/core/useFLIPAnimation.ts +1 -0
  125. package/src/react-ui/primitives/waapi/core/usePositionCapture.ts +1 -0
  126. package/src/react-ui/ui/Accordion/index.tsx +3 -3
  127. package/src/react-ui/ui/InputGroup/index.tsx +2 -0
  128. /package/dist/react-ui/blocks/Terminal/panel/{terminal-filter-dropdown.module-Bovc57nm.css → terminal-filter-dropdown.module-CNVWCefU.css} +0 -0
  129. /package/dist/react-ui/blocks/Terminal/panel/{terminal-session-tabs.module-QyxHO7cN.css → terminal-session-tabs.module-cmyJ11jP.css} +0 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * TerminalDisplay — Readonly GPU-rendered terminal for ANSI content.
3
+ *
4
+ * Uses restty directly (not xterm) for GPU-accelerated rendering of
5
+ * ANSI-formatted text without PTY connection. Content is written via
6
+ * `restty.sendInput(data, "pty")` which feeds text to the WASM terminal
7
+ * engine for parsing and rendering.
8
+ *
9
+ * Optionally wrapped in TerminalPanelChrome glassmorphism shell.
10
+ *
11
+ * @module components/devenv/terminal/TerminalDisplay
12
+ */
13
+
14
+ 'use client';
15
+
16
+ import {
17
+ useRef,
18
+ useEffect,
19
+ useCallback,
20
+ forwardRef,
21
+ useImperativeHandle,
22
+ useState,
23
+ } from 'react';
24
+ import type { Restty } from 'restty';
25
+ import type { ITerminalDisplayProps, ITerminalDisplayRef } from './TerminalDisplay.types';
26
+ import { terminalDisplayStyles, terminalDisplayVariants } from './TerminalDisplay.styles';
27
+ import { TerminalPanelChrome } from './panel/TerminalPanelChrome';
28
+ import { getSynthwaveGhosttyTheme, xtermThemeToGhostty } from './Terminal.theme.restty';
29
+ import { cn } from '@/react-ui/lib/utils';
30
+
31
+ /**
32
+ * TerminalDisplay — Readonly restty terminal for displaying ANSI content.
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * <TerminalDisplay
37
+ * content={"\x1b[31mError:\x1b[0m Something failed"}
38
+ * title="Error Output"
39
+ * variant="error"
40
+ * fontSize={12}
41
+ * />
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * // Without chrome shell
47
+ * <TerminalDisplay
48
+ * content={ansiOutput}
49
+ * chrome={false}
50
+ * minHeight={100}
51
+ * />
52
+ * ```
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * // With imperative handle
57
+ * const ref = useRef<ITerminalDisplayRef>(null);
58
+ * ref.current?.write("Additional output\r\n");
59
+ * ref.current?.clear();
60
+ * ```
61
+ */
62
+ export const TerminalDisplay = forwardRef<ITerminalDisplayRef, ITerminalDisplayProps>(
63
+ (
64
+ {
65
+ content,
66
+ title = 'Output',
67
+ variant = 'default',
68
+ chrome = true,
69
+ fontSize = 13,
70
+ minHeight = 200,
71
+ theme,
72
+ resttyThemeName,
73
+ gpuRenderer = 'auto',
74
+ slots,
75
+ className,
76
+ emptyText,
77
+ onReady,
78
+ },
79
+ ref,
80
+ ) => {
81
+ const containerRef = useRef<HTMLDivElement>(null);
82
+ const resttyRef = useRef<Restty | null>(null);
83
+ const [isReady, setIsReady] = useState(false);
84
+
85
+ // Store callbacks in refs
86
+ const callbacksRef = useRef({ onReady });
87
+ callbacksRef.current = { onReady };
88
+
89
+ // Store content in ref to avoid re-creating restty on content change
90
+ const contentRef = useRef(content);
91
+ contentRef.current = content;
92
+
93
+ /**
94
+ * Initialize restty on mount.
95
+ * Dynamic import for SSR safety and code-splitting.
96
+ */
97
+ useEffect(() => {
98
+ if (!containerRef.current) return;
99
+ let destroyed = false;
100
+
101
+ const init = async () => {
102
+ const { Restty: ResttyClass, getBuiltinTheme } = await import('restty');
103
+ if (destroyed || !containerRef.current) return;
104
+
105
+ const restty = new ResttyClass({
106
+ root: containerRef.current,
107
+ appOptions: {
108
+ renderer: gpuRenderer,
109
+ fontSize,
110
+ autoResize: true,
111
+ },
112
+ fontSources: [
113
+ {
114
+ type: 'local',
115
+ matchers: [
116
+ 'jetbrains mono',
117
+ 'fira code',
118
+ 'sf mono',
119
+ 'cascadia code',
120
+ 'meslo',
121
+ ],
122
+ },
123
+ ],
124
+ createInitialPane: true,
125
+ shortcuts: false,
126
+ defaultContextMenu: false,
127
+ });
128
+
129
+ resttyRef.current = restty;
130
+
131
+ // Apply theme
132
+ if (resttyThemeName) {
133
+ const builtinTheme = getBuiltinTheme(resttyThemeName);
134
+ if (builtinTheme) restty.applyTheme(builtinTheme);
135
+ } else if (theme) {
136
+ restty.applyTheme(xtermThemeToGhostty(theme));
137
+ } else {
138
+ restty.applyTheme(getSynthwaveGhosttyTheme());
139
+ }
140
+
141
+ // Wait for WASM to be ready before writing content.
142
+ // Restty loads WASM async internally — panes() returns empty until ready.
143
+ const waitForWasm = () => {
144
+ if (destroyed) return;
145
+ const panes = restty.panes();
146
+ if (panes && panes.length > 0) {
147
+ // WASM loaded, pane created — safe to write
148
+ if (contentRef.current) {
149
+ restty.sendInput(contentRef.current, 'pty');
150
+ }
151
+ setIsReady(true);
152
+ callbacksRef.current.onReady?.(restty);
153
+ } else {
154
+ // Not ready yet, retry
155
+ requestAnimationFrame(waitForWasm);
156
+ }
157
+ };
158
+ requestAnimationFrame(waitForWasm);
159
+ };
160
+
161
+ init().catch(() => {
162
+ // Silently fail — container will show empty
163
+ });
164
+
165
+ return () => {
166
+ destroyed = true;
167
+ resttyRef.current?.destroy();
168
+ resttyRef.current = null;
169
+ setIsReady(false);
170
+ };
171
+ }, []); // Mount once
172
+
173
+ /**
174
+ * Re-write content when it changes after initialization.
175
+ */
176
+ useEffect(() => {
177
+ if (!isReady || !resttyRef.current) return;
178
+ resttyRef.current.clearScreen();
179
+ if (content) {
180
+ resttyRef.current.sendInput(content, 'pty');
181
+ }
182
+ }, [content, isReady]);
183
+
184
+ /**
185
+ * Handle fontSize changes after initialization.
186
+ */
187
+ useEffect(() => {
188
+ if (!isReady || !resttyRef.current) return;
189
+ resttyRef.current.setFontSize(fontSize);
190
+ }, [fontSize, isReady]);
191
+
192
+ /**
193
+ * Expose imperative handle.
194
+ */
195
+ useImperativeHandle(ref, () => ({
196
+ getRestty: () => resttyRef.current,
197
+ clear: () => resttyRef.current?.clearScreen(),
198
+ write: (data: string) => resttyRef.current?.sendInput(data, 'pty'),
199
+ }));
200
+
201
+ /** Map variant to chrome variant */
202
+ const chromeVariant = variant === 'error' ? 'error' : 'default';
203
+ const chromeSize = variant === 'compact' ? 'compact' : 'default';
204
+
205
+ /** The terminal content area */
206
+ const terminalElement = (
207
+ <div
208
+ className={cn(
209
+ terminalDisplayVariants({ variant }),
210
+ slots?.root,
211
+ className,
212
+ )}
213
+ style={{ minHeight: `${minHeight}px` }}
214
+ >
215
+ {/* Empty state */}
216
+ {!content && emptyText && (
217
+ <div
218
+ className={cn(terminalDisplayStyles.emptyState, slots?.emptyState)}
219
+ style={{ minHeight: `${minHeight}px` }}
220
+ >
221
+ {emptyText}
222
+ </div>
223
+ )}
224
+
225
+ {/* Restty container */}
226
+ <div
227
+ ref={containerRef}
228
+ className={cn(terminalDisplayStyles.terminal, slots?.terminal)}
229
+ style={{
230
+ minHeight: `${minHeight}px`,
231
+ display: !content && emptyText ? 'none' : undefined,
232
+ }}
233
+ />
234
+ </div>
235
+ );
236
+
237
+ if (!chrome) return terminalElement;
238
+
239
+ return (
240
+ <TerminalPanelChrome
241
+ containerName={title}
242
+ isConnected={isReady}
243
+ variant={chromeVariant}
244
+ size={chromeSize}
245
+ slots={{ root: slots?.chrome }}
246
+ className={className}
247
+ >
248
+ {terminalElement}
249
+ </TerminalPanelChrome>
250
+ );
251
+ },
252
+ );
253
+
254
+ TerminalDisplay.displayName = 'TerminalDisplay';
@@ -0,0 +1,73 @@
1
+ /**
2
+ * TerminalDisplay component types.
3
+ *
4
+ * Readonly GPU-rendered terminal for displaying ANSI-formatted text
5
+ * without PTY connection, using restty.
6
+ *
7
+ * @module components/devenv/terminal/TerminalDisplay.types
8
+ */
9
+
10
+ import type { SlotOverrides } from '@/core/types';
11
+ import type { Restty } from 'restty';
12
+ import type { ITerminalTheme } from './Terminal.types';
13
+
14
+ /** Slot names for TerminalDisplay sub-regions */
15
+ export type TerminalDisplaySlot = 'root' | 'chrome' | 'terminal' | 'emptyState';
16
+
17
+ /**
18
+ * Props for TerminalDisplay component.
19
+ */
20
+ export interface ITerminalDisplayProps {
21
+ /** ANSI-formatted string content to display */
22
+ content: string;
23
+
24
+ /** Title shown in the chrome header */
25
+ title?: string;
26
+
27
+ /** Visual variant — 'error' uses red accent line */
28
+ variant?: 'default' | 'compact' | 'error';
29
+
30
+ /** Whether to show the glassmorphism chrome shell (default: true) */
31
+ chrome?: boolean;
32
+
33
+ /** Font size in CSS pixels (default: 13) */
34
+ fontSize?: number;
35
+
36
+ /** Minimum height in CSS pixels (default: 200) */
37
+ minHeight?: number;
38
+
39
+ /** Terminal theme in xterm.js format (auto-converted to Ghostty) */
40
+ theme?: ITerminalTheme;
41
+
42
+ /** Restty built-in theme name from the 458-theme catalog */
43
+ resttyThemeName?: string;
44
+
45
+ /** GPU renderer preference (default: 'auto') */
46
+ gpuRenderer?: 'auto' | 'webgpu' | 'webgl2';
47
+
48
+ /** Slot class overrides for each visual region */
49
+ slots?: SlotOverrides<TerminalDisplaySlot>;
50
+
51
+ /** Custom class name on root element */
52
+ className?: string;
53
+
54
+ /** Placeholder text when content is empty */
55
+ emptyText?: string;
56
+
57
+ /** Callback when restty instance is ready */
58
+ onReady?: (restty: Restty) => void;
59
+ }
60
+
61
+ /**
62
+ * Imperative handle for TerminalDisplay.
63
+ */
64
+ export interface ITerminalDisplayRef {
65
+ /** Get the underlying Restty instance */
66
+ getRestty: () => Restty | null;
67
+
68
+ /** Clear the terminal display */
69
+ clear: () => void;
70
+
71
+ /** Write additional ANSI content (appends) */
72
+ write: (data: string) => void;
73
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Terminal Chrome — lightweight barrel export.
3
+ *
4
+ * Exports only the glassmorphism shell components (no restty, no xterm).
5
+ * Use `@mks2508/mks-ui/react/blocks/Terminal/chrome` for zero terminal deps.
6
+ *
7
+ * @module @mks2508/mks-ui/react/blocks/Terminal/chrome
8
+ */
9
+
10
+ // Chrome shell
11
+ export { TerminalPanelChrome, NOISE_TEXTURE_SVG, terminalScrollStyles } from './panel/TerminalPanelChrome';
12
+ export { TerminalPanelHeader } from './panel/TerminalPanelHeader';
13
+ export { TerminalPanelFooter } from './panel/TerminalPanelFooter';
14
+
15
+ // Chrome styles + variants
16
+ export {
17
+ terminalChromeStyles,
18
+ terminalChromeVariants,
19
+ ACCENT_GRADIENTS,
20
+ type TerminalChromeSlot,
21
+ type TerminalChromeVariantProps,
22
+ } from './panel/TerminalPanelChrome.styles';
23
+
24
+ // Chrome types
25
+ export type { ITerminalPanelChromeProps } from './panel/TerminalPanelChrome.types';
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Terminal Display — lightweight barrel export.
3
+ *
4
+ * Exports the readonly TerminalDisplay component + restty wrapper + chrome.
5
+ * Depends on restty only (not xterm, not shiki, not xterm addons).
6
+ * Use `@mks2508/mks-ui/react/blocks/Terminal/display` for minimal deps.
7
+ *
8
+ * @module @mks2508/mks-ui/react/blocks/Terminal/display
9
+ */
10
+
11
+ // TerminalDisplay (readonly restty terminal)
12
+ export { TerminalDisplay } from './TerminalDisplay';
13
+ export {
14
+ terminalDisplayStyles,
15
+ terminalDisplayVariants,
16
+ type TerminalDisplayVariantProps,
17
+ } from './TerminalDisplay.styles';
18
+ export type {
19
+ ITerminalDisplayProps,
20
+ ITerminalDisplayRef,
21
+ TerminalDisplaySlot,
22
+ } from './TerminalDisplay.types';
23
+
24
+ // Restty React wrapper (for advanced use)
25
+ export { TerminalRestty } from './TerminalRestty';
26
+ export type { ITerminalResttyProps, ITerminalResttyRef } from './TerminalRestty';
27
+
28
+ // Chrome (re-exported for convenience)
29
+ export { TerminalPanelChrome, NOISE_TEXTURE_SVG, terminalScrollStyles } from './panel/TerminalPanelChrome';
30
+ export type { ITerminalPanelChromeProps } from './panel/TerminalPanelChrome.types';
31
+ export {
32
+ terminalChromeStyles,
33
+ terminalChromeVariants,
34
+ ACCENT_GRADIENTS,
35
+ type TerminalChromeSlot,
36
+ } from './panel/TerminalPanelChrome.styles';
37
+
38
+ // Theme utilities (needed for display customization)
39
+ export { SYNTHWAVE_TERMINAL_THEME, getTerminalTheme } from './Terminal.theme';
40
+ export {
41
+ hexToResttyColor,
42
+ xtermThemeToGhostty,
43
+ getSynthwaveGhosttyTheme,
44
+ type IResttyThemeColor,
45
+ type IResttyGhosttyTheme,
46
+ } from './Terminal.theme.restty';
@@ -101,3 +101,11 @@ export type {
101
101
  } from './panel/TerminalLogsPanel.types';
102
102
  export type { ILogLinesViewerProps } from './panel/LogLinesViewer';
103
103
  export type { TLogLevelFilter } from './parsing/LogParser.types';
104
+
105
+ // TerminalDisplay (lightweight readonly restty terminal)
106
+ export { TerminalDisplay } from './TerminalDisplay';
107
+ export type { ITerminalDisplayProps, ITerminalDisplayRef, TerminalDisplaySlot } from './TerminalDisplay.types';
108
+ export { terminalDisplayStyles, terminalDisplayVariants, type TerminalDisplayVariantProps } from './TerminalDisplay.styles';
109
+
110
+ // Chrome StyleSlots + CVA variants
111
+ export { terminalChromeStyles, terminalChromeVariants, ACCENT_GRADIENTS, type TerminalChromeSlot, type TerminalChromeVariantProps } from './panel/TerminalPanelChrome.styles';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * TerminalPanelChrome style definitions.
3
+ *
4
+ * StyleSlots + CVA variants for the Ghostty-inspired glassmorphism shell.
5
+ * Follows the mks-ui composable pattern: base styles via StyleSlots,
6
+ * visual variants via CVA, consumer overrides via SlotOverrides.
7
+ *
8
+ * @module components/devenv/terminal/panel/chrome/styles
9
+ */
10
+
11
+ import { cva, type VariantProps } from 'class-variance-authority';
12
+ import type { StyleSlots } from '@/core/types';
13
+
14
+ /** Slot names for TerminalPanelChrome sub-regions */
15
+ export type TerminalChromeSlot =
16
+ | 'root'
17
+ | 'accentLine'
18
+ | 'accentGradient'
19
+ | 'accentShimmer'
20
+ | 'header'
21
+ | 'sessionTabs'
22
+ | 'actionBar'
23
+ | 'content'
24
+ | 'footer';
25
+
26
+ /**
27
+ * Default style slots for each chrome sub-region.
28
+ */
29
+ export const terminalChromeStyles: StyleSlots<TerminalChromeSlot> = {
30
+ root: 'glass-heavy glass-noise rounded-2xl overflow-hidden relative',
31
+ accentLine: 'absolute top-0 left-0 right-0 h-px z-10 pointer-events-none overflow-hidden',
32
+ accentGradient: 'h-full w-full',
33
+ accentShimmer: 'absolute inset-0 bg-gradient-to-r from-transparent via-white/40 to-transparent',
34
+ header: '',
35
+ sessionTabs: '',
36
+ actionBar: '',
37
+ content: '',
38
+ footer: '',
39
+ };
40
+
41
+ /**
42
+ * Accent line gradient classes per variant.
43
+ */
44
+ export const ACCENT_GRADIENTS = {
45
+ default: 'bg-gradient-to-r from-transparent via-primary/70 to-transparent shadow-[0_0_12px_hsla(330,85%,43%,0.5)]',
46
+ error: 'bg-gradient-to-r from-transparent via-destructive/70 to-transparent shadow-[0_0_12px_hsla(0,72%,51%,0.5)]',
47
+ minimal: '',
48
+ } as const;
49
+
50
+ /**
51
+ * CVA variants for the chrome root element.
52
+ */
53
+ export const terminalChromeVariants = cva(terminalChromeStyles.root, {
54
+ variants: {
55
+ variant: {
56
+ /** Default: magenta accent line, full glassmorphism */
57
+ default: '',
58
+ /** Minimal: no accent line, no noise texture, simpler rounding */
59
+ minimal: 'rounded-lg',
60
+ /** Error: red/destructive accent line instead of magenta */
61
+ error: '',
62
+ },
63
+ size: {
64
+ default: '',
65
+ compact: 'rounded-xl',
66
+ },
67
+ },
68
+ defaultVariants: {
69
+ variant: 'default',
70
+ size: 'default',
71
+ },
72
+ });
73
+
74
+ /** Extracted variant props type for consumer use */
75
+ export type TerminalChromeVariantProps = VariantProps<typeof terminalChromeVariants>;
@@ -12,6 +12,7 @@
12
12
  * - macOS-style header (TerminalPanelHeader)
13
13
  * - Slots for action bar, children (terminal content), and footer
14
14
  * - Neon magenta scrollbar styles
15
+ * - StyleSlots + CVA variants for customization
15
16
  *
16
17
  * @module components/devenv/terminal/panel/chrome
17
18
  */
@@ -19,6 +20,11 @@
19
20
  'use client';
20
21
 
21
22
  import type { ITerminalPanelChromeProps } from './TerminalPanelChrome.types';
23
+ import {
24
+ terminalChromeStyles,
25
+ terminalChromeVariants,
26
+ ACCENT_GRADIENTS,
27
+ } from './TerminalPanelChrome.styles';
22
28
  import { TerminalPanelHeader } from './TerminalPanelHeader';
23
29
  import { TerminalSessionTabs } from './TerminalSessionTabs';
24
30
  import { cn } from '@/react-ui/lib/utils';
@@ -129,16 +135,16 @@ export const terminalScrollStyles = `
129
135
  * consistent visual chrome. Used by both TerminalLogsPanel (readonly)
130
136
  * and TerminalInteractivePanel (interactive).
131
137
  *
138
+ * Supports StyleSlots for class overrides and CVA variants
139
+ * for visual presets (default, minimal, error).
140
+ *
132
141
  * @example
133
142
  * ```tsx
134
143
  * <TerminalPanelChrome
135
144
  * containerName="devenv-agent-backend"
136
145
  * isConnected={true}
137
- * sessions={sessions}
138
- * activeSessionId="session-1"
139
- * onSessionTabClick={(id) => setActiveSession(id)}
140
- * onSessionClose={(id) => closeSession(id)}
141
- * onNewSession={() => createSession()}
146
+ * variant="error"
147
+ * slots={{ root: 'max-h-[400px]', content: 'p-2' }}
142
148
  * actionBar={<TerminalFilterTabs ... />}
143
149
  * footer={<TerminalPanelFooter ... />}
144
150
  * >
@@ -149,6 +155,8 @@ export const terminalScrollStyles = `
149
155
  export function TerminalPanelChrome({
150
156
  containerName,
151
157
  isConnected,
158
+ variant = 'default',
159
+ size = 'default',
152
160
  viewMode = 'terminal',
153
161
  onViewModeChange,
154
162
  sessions,
@@ -165,6 +173,7 @@ export function TerminalPanelChrome({
165
173
  onMinimize,
166
174
  onMaximize,
167
175
  crtEffect,
176
+ slots,
168
177
  className,
169
178
  }: ITerminalPanelChromeProps) {
170
179
  /** Whether to render session tabs (multi-session mode) */
@@ -172,63 +181,83 @@ export function TerminalPanelChrome({
172
181
  (sessions && sessions.length > 0) ||
173
182
  (availableContainers && availableContainers.length > 0);
174
183
 
184
+ /** Whether to show the accent line (hidden in minimal variant) */
185
+ const showAccentLine = variant !== 'minimal';
186
+
187
+ /** Accent gradient based on variant */
188
+ const accentGradient = ACCENT_GRADIENTS[variant ?? 'default'] ?? ACCENT_GRADIENTS.default;
189
+
175
190
  return (
176
191
  <div
177
192
  className={cn(
178
- 'glass-heavy glass-noise rounded-2xl overflow-hidden',
179
- className
193
+ terminalChromeVariants({ variant, size }),
194
+ slots?.root,
195
+ className,
180
196
  )}
181
197
  >
182
198
  {/* Animated top accent line with shimmer */}
183
- <div className="absolute top-0 left-0 right-0 h-px z-10 pointer-events-none overflow-hidden">
184
- <div
185
- className="h-full w-full bg-gradient-to-r from-transparent via-primary/70 to-transparent shadow-[0_0_12px_hsla(330,85%,43%,0.5)]"
186
- />
187
- <div
188
- className="absolute inset-0 bg-gradient-to-r from-transparent via-white/40 to-transparent"
189
- style={{
190
- backgroundSize: '200% 100%',
191
- animation: 'shimmer-line 4s ease-in-out infinite',
192
- }}
193
- />
194
- </div>
199
+ {showAccentLine && (
200
+ <div className={cn(terminalChromeStyles.accentLine, slots?.accentLine)}>
201
+ <div className={cn(accentGradient, slots?.accentGradient)} />
202
+ <div
203
+ className={cn(terminalChromeStyles.accentShimmer, slots?.accentShimmer)}
204
+ style={{
205
+ backgroundSize: '200% 100%',
206
+ animation: 'shimmer-line 4s ease-in-out infinite',
207
+ }}
208
+ />
209
+ </div>
210
+ )}
195
211
 
196
212
  {/* Session Tabs */}
197
213
  {showSessionTabs && (
198
- <TerminalSessionTabs
199
- sessions={sessions || []}
200
- activeSessionId={activeSessionId || null}
201
- onTabClick={(sessionId) => onSessionTabClick?.(sessionId)}
202
- onClose={(sessionId) => onSessionClose?.(sessionId)}
203
- onNewSession={onNewSession}
204
- availableContainers={availableContainers}
205
- onAddContainer={onAddContainer}
206
- />
214
+ <div className={cn(slots?.sessionTabs)}>
215
+ <TerminalSessionTabs
216
+ sessions={sessions || []}
217
+ activeSessionId={activeSessionId || null}
218
+ onTabClick={(sessionId) => onSessionTabClick?.(sessionId)}
219
+ onClose={(sessionId) => onSessionClose?.(sessionId)}
220
+ onNewSession={onNewSession}
221
+ availableContainers={availableContainers}
222
+ onAddContainer={onAddContainer}
223
+ />
224
+ </div>
207
225
  )}
208
226
 
209
227
  {/* Header */}
210
- <TerminalPanelHeader
211
- containerName={containerName}
212
- isConnected={isConnected}
213
- viewMode={viewMode}
214
- onViewModeChange={onViewModeChange}
215
- onClose={onClose}
216
- onMinimize={onMinimize}
217
- onMaximize={onMaximize}
218
- />
228
+ <div className={cn(slots?.header)}>
229
+ <TerminalPanelHeader
230
+ containerName={containerName}
231
+ isConnected={isConnected}
232
+ viewMode={viewMode}
233
+ onViewModeChange={onViewModeChange}
234
+ onClose={onClose}
235
+ onMinimize={onMinimize}
236
+ onMaximize={onMaximize}
237
+ />
238
+ </div>
219
239
 
220
240
  {/* Action Bar Slot */}
221
- {actionBar}
241
+ {actionBar && (
242
+ <div className={cn(slots?.actionBar)}>
243
+ {actionBar}
244
+ </div>
245
+ )}
222
246
 
223
247
  {/* Terminal Content - with optional CRT effects */}
224
248
  <div className={cn(
225
- crtEffect && 'terminal-crt terminal-bloom'
249
+ crtEffect && 'terminal-crt terminal-bloom',
250
+ slots?.content,
226
251
  )}>
227
252
  {children}
228
253
  </div>
229
254
 
230
255
  {/* Footer Slot */}
231
- {footer}
256
+ {footer && (
257
+ <div className={cn(slots?.footer)}>
258
+ {footer}
259
+ </div>
260
+ )}
232
261
 
233
262
  {/* Terminal scroll styles */}
234
263
  <style>{terminalScrollStyles}</style>