@steez-ui/ui 0.1.6 → 0.1.7

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 (31) hide show
  1. package/README.md +3 -3
  2. package/dist/components/LoadingOverlayCrystalline.d.ts +10 -0
  3. package/dist/components/LoadingOverlayCrystalline.d.ts.map +1 -0
  4. package/dist/components/LoadingOverlayCrystalline.js +7 -0
  5. package/dist/components/LoadingOverlayCrystalline.js.map +1 -0
  6. package/dist/components/LoadingOverlayCrystalline.module.css +39 -0
  7. package/dist/components/LoadingScreen.d.ts +17 -0
  8. package/dist/components/LoadingScreen.d.ts.map +1 -0
  9. package/dist/components/LoadingScreen.js +246 -0
  10. package/dist/components/LoadingScreen.js.map +1 -0
  11. package/dist/components/LoadingScreen.module.css +108 -0
  12. package/dist/components/OverlayButton.d.ts +7 -0
  13. package/dist/components/OverlayButton.d.ts.map +1 -0
  14. package/dist/components/OverlayButton.js +8 -0
  15. package/dist/components/OverlayButton.js.map +1 -0
  16. package/dist/components/OverlayButton.module.css +32 -0
  17. package/dist/components/PixelTooltip.d.ts +10 -0
  18. package/dist/components/PixelTooltip.d.ts.map +1 -0
  19. package/dist/components/PixelTooltip.js +41 -0
  20. package/dist/components/PixelTooltip.js.map +1 -0
  21. package/dist/components/PixelTooltip.module.css +81 -0
  22. package/dist/components/WidgetCard.d.ts +12 -0
  23. package/dist/components/WidgetCard.d.ts.map +1 -0
  24. package/dist/components/WidgetCard.js +17 -0
  25. package/dist/components/WidgetCard.js.map +1 -0
  26. package/dist/components/WidgetCard.module.css +75 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +5 -0
  30. package/dist/index.js.map +1 -1
  31. package/package.json +3 -3
package/README.md CHANGED
@@ -101,9 +101,9 @@ GitHub Actions mirror the same CI, npm publish, and Cloudflare Pages deploy path
101
101
 
102
102
  ## Current Packages
103
103
 
104
- - `@steez-ui/theme@0.1.6`
105
- - `@steez-ui/icons@0.1.6`
106
- - `@steez-ui/ui@0.1.6`
104
+ - `@steez-ui/theme@0.1.7`
105
+ - `@steez-ui/icons@0.1.7`
106
+ - `@steez-ui/ui@0.1.7`
107
107
 
108
108
  ## External Setup
109
109
 
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ export interface LoadingOverlayCrystallineProps {
3
+ message: string;
4
+ subtext?: string;
5
+ icon?: React.ReactNode;
6
+ showEffect?: boolean;
7
+ }
8
+ export declare function LoadingOverlayCrystalline({ message, subtext, icon, showEffect, }: LoadingOverlayCrystallineProps): import("react/jsx-runtime").JSX.Element;
9
+ export default LoadingOverlayCrystalline;
10
+ //# sourceMappingURL=LoadingOverlayCrystalline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingOverlayCrystalline.d.ts","sourceRoot":"","sources":["../../src/components/LoadingOverlayCrystalline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,OAAO,EACP,IAAI,EACJ,UAAkB,GACnB,EAAE,8BAA8B,2CAYhC;AAED,eAAe,yBAAyB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styles from "./LoadingOverlayCrystalline.module.css";
3
+ export function LoadingOverlayCrystalline({ message, subtext, icon, showEffect = false, }) {
4
+ return (_jsx("div", { className: `${styles.root} ${showEffect ? "" : styles.noEffect}`.trim(), children: _jsxs("div", { className: styles.card, children: [icon ? _jsx("span", { className: styles.icon, children: icon }) : null, _jsxs("div", { children: [_jsx("div", { children: message }), subtext ? _jsx("div", { className: styles.subtext, children: subtext }) : null] })] }) }));
5
+ }
6
+ export default LoadingOverlayCrystalline;
7
+ //# sourceMappingURL=LoadingOverlayCrystalline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingOverlayCrystalline.js","sourceRoot":"","sources":["../../src/components/LoadingOverlayCrystalline.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,wCAAwC,CAAC;AAS5D,MAAM,UAAU,yBAAyB,CAAC,EACxC,OAAO,EACP,OAAO,EACP,IAAI,EACJ,UAAU,GAAG,KAAK,GACa;IAC/B,OAAO,CACL,cAAK,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,YAC1E,eAAK,SAAS,EAAE,MAAM,CAAC,IAAI,aACxB,IAAI,CAAC,CAAC,CAAC,eAAM,SAAS,EAAE,MAAM,CAAC,IAAI,YAAG,IAAI,GAAQ,CAAC,CAAC,CAAC,IAAI,EAC1D,0BACE,wBAAM,OAAO,GAAO,EACnB,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAAG,OAAO,GAAO,CAAC,CAAC,CAAC,IAAI,IAC7D,IACF,GACF,CACP,CAAC;AACJ,CAAC;AAED,eAAe,yBAAyB,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./LoadingOverlayCrystalline.module.css\";\n\nexport interface LoadingOverlayCrystallineProps {\n message: string;\n subtext?: string;\n icon?: React.ReactNode;\n showEffect?: boolean;\n}\n\nexport function LoadingOverlayCrystalline({\n message,\n subtext,\n icon,\n showEffect = false,\n}: LoadingOverlayCrystallineProps) {\n return (\n <div className={`${styles.root} ${showEffect ? \"\" : styles.noEffect}`.trim()}>\n <div className={styles.card}>\n {icon ? <span className={styles.icon}>{icon}</span> : null}\n <div>\n <div>{message}</div>\n {subtext ? <div className={styles.subtext}>{subtext}</div> : null}\n </div>\n </div>\n </div>\n );\n}\n\nexport default LoadingOverlayCrystalline;\n"]}
@@ -0,0 +1,39 @@
1
+ .root {
2
+ position: absolute;
3
+ inset: 0;
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ z-index: var(--z-viewer-quick-tools);
8
+ background: transparent;
9
+ }
10
+
11
+ .noEffect {
12
+ background: transparent;
13
+ }
14
+
15
+ .card {
16
+ position: relative;
17
+ z-index: 20;
18
+ display: inline-flex;
19
+ align-items: center;
20
+ gap: 10px;
21
+ padding: 14px 16px;
22
+ background: color-mix(in srgb, var(--bg-primary) 85%, transparent);
23
+ border: 1px solid color-mix(in srgb, var(--text-primary) 14%, transparent);
24
+ border-radius: 10px;
25
+ color: var(--text-primary);
26
+ font-size: 14px;
27
+ font-weight: 600;
28
+ }
29
+
30
+ .icon {
31
+ opacity: 0.9;
32
+ }
33
+
34
+ .subtext {
35
+ margin-top: 2px;
36
+ color: color-mix(in srgb, var(--text-secondary) 92%, transparent);
37
+ font-size: 12px;
38
+ font-weight: 500;
39
+ }
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ export interface LoadingScreenProps {
3
+ progress: number;
4
+ message?: string;
5
+ logo?: React.ReactNode;
6
+ title?: React.ReactNode;
7
+ audioFeedback?: boolean;
8
+ fullscreen?: boolean;
9
+ themeMode?: "auto" | "light" | "dark";
10
+ }
11
+ export declare function LoadingScreen({ progress, message, logo, title, audioFeedback, fullscreen, themeMode, }: LoadingScreenProps): import("react/jsx-runtime").JSX.Element;
12
+ export type LoadingStage = "init" | "auth" | "agent" | "config" | "ready";
13
+ export declare function useLoadingProgress(isLoading: boolean, _phase?: string, stage?: LoadingStage): {
14
+ progress: number;
15
+ message: string;
16
+ };
17
+ //# sourceMappingURL=LoadingScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingScreen.d.ts","sourceRoot":"","sources":["../../src/components/LoadingScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CACvC;AAmCD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,KAAiB,EACjB,aAAqB,EACrB,UAAiB,EACjB,SAAkB,GACnB,EAAE,kBAAkB,2CAmPpB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAkB1E,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,OAAO,EAClB,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,GAAE,YAAqB;;;EAgD7B"}
@@ -0,0 +1,246 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { LightCrossIcon } from "@steez-ui/icons";
4
+ import { LoadingProgressBar, LOADING_PROGRESS_SEGMENT_COUNT, } from "./LoadingProgressBar.js";
5
+ import styles from "./LoadingScreen.module.css";
6
+ function randomFloat() {
7
+ return Math.random();
8
+ }
9
+ function resolveIsLightMode(themeMode) {
10
+ if (themeMode === "light") {
11
+ return true;
12
+ }
13
+ if (themeMode === "dark") {
14
+ return false;
15
+ }
16
+ if (typeof window === "undefined") {
17
+ return false;
18
+ }
19
+ return (document.documentElement.getAttribute("data-theme") === "light" ||
20
+ window.localStorage.getItem("theme") === "light");
21
+ }
22
+ export function LoadingScreen({ progress, message, logo, title = "LOADING", audioFeedback = false, fullscreen = true, themeMode = "auto", }) {
23
+ const [displayProgress, setDisplayProgress] = React.useState(0);
24
+ const [ellipsisCount, setEllipsisCount] = React.useState(0);
25
+ const [crosses, setCrosses] = React.useState([]);
26
+ const [bounds, setBounds] = React.useState({ width: 0, height: 0 });
27
+ const prevFilledBars = React.useRef(0);
28
+ const crossIdRef = React.useRef(0);
29
+ const isLoadingRef = React.useRef(true);
30
+ const audioCtxRef = React.useRef(null);
31
+ const audioEnabledRef = React.useRef(false);
32
+ const containerRef = React.useRef(null);
33
+ const updateBounds = React.useCallback(() => {
34
+ const nextWidth = containerRef.current?.clientWidth || window.innerWidth || 0;
35
+ const nextHeight = containerRef.current?.clientHeight || window.innerHeight || 0;
36
+ setBounds((current) => {
37
+ if (current.width === nextWidth && current.height === nextHeight) {
38
+ return current;
39
+ }
40
+ return {
41
+ width: nextWidth,
42
+ height: nextHeight,
43
+ };
44
+ });
45
+ }, []);
46
+ const spawnCross = React.useCallback(() => {
47
+ if (!isLoadingRef.current || typeof window === "undefined") {
48
+ return;
49
+ }
50
+ const tilt = (randomFloat() - 0.5) * 6;
51
+ const availableWidth = Math.max(bounds.width || window.innerWidth, 160);
52
+ const nextCross = {
53
+ id: crossIdRef.current += 1,
54
+ x: randomFloat() * Math.max(availableWidth - 120, 24),
55
+ rotation: tilt,
56
+ scale: 0.4 + randomFloat() * 0.4,
57
+ groundOffset: randomFloat() * 30,
58
+ delay: 0,
59
+ opacity: 0.4 + randomFloat() * 0.3,
60
+ };
61
+ setCrosses((current) => [...current.slice(-17), nextCross]);
62
+ }, [bounds.width]);
63
+ React.useEffect(() => {
64
+ if (typeof window === "undefined") {
65
+ return undefined;
66
+ }
67
+ updateBounds();
68
+ window.addEventListener("resize", updateBounds);
69
+ const observer = typeof ResizeObserver === "undefined" || !containerRef.current
70
+ ? null
71
+ : new ResizeObserver(() => {
72
+ updateBounds();
73
+ });
74
+ if (observer && containerRef.current) {
75
+ observer.observe(containerRef.current);
76
+ }
77
+ return () => {
78
+ window.removeEventListener("resize", updateBounds);
79
+ observer?.disconnect();
80
+ };
81
+ }, [updateBounds]);
82
+ React.useEffect(() => {
83
+ isLoadingRef.current = true;
84
+ const scheduleNextCross = () => {
85
+ const delay = 400 + randomFloat() * 300;
86
+ return setTimeout(() => {
87
+ spawnCross();
88
+ if (isLoadingRef.current) {
89
+ scheduleNextCross();
90
+ }
91
+ }, delay);
92
+ };
93
+ const timeoutId = scheduleNextCross();
94
+ return () => {
95
+ clearTimeout(timeoutId);
96
+ isLoadingRef.current = false;
97
+ };
98
+ }, [spawnCross]);
99
+ React.useEffect(() => {
100
+ if (!audioFeedback) {
101
+ return undefined;
102
+ }
103
+ const enableAudio = async () => {
104
+ const AudioContextClass = window.AudioContext || window.webkitAudioContext;
105
+ if (!AudioContextClass) {
106
+ return;
107
+ }
108
+ try {
109
+ const ctx = audioCtxRef.current ?? new AudioContextClass();
110
+ audioCtxRef.current = ctx;
111
+ if (ctx.state === "suspended") {
112
+ await ctx.resume();
113
+ }
114
+ audioEnabledRef.current = ctx.state === "running";
115
+ }
116
+ catch {
117
+ audioEnabledRef.current = false;
118
+ }
119
+ };
120
+ window.addEventListener("pointerdown", enableAudio, {
121
+ once: true,
122
+ passive: true,
123
+ });
124
+ window.addEventListener("keydown", enableAudio, { once: true });
125
+ return () => {
126
+ window.removeEventListener("pointerdown", enableAudio);
127
+ window.removeEventListener("keydown", enableAudio);
128
+ if (audioCtxRef.current) {
129
+ void audioCtxRef.current.close().catch(() => undefined);
130
+ audioCtxRef.current = null;
131
+ }
132
+ audioEnabledRef.current = false;
133
+ };
134
+ }, [audioFeedback]);
135
+ React.useEffect(() => {
136
+ if (!audioFeedback) {
137
+ return undefined;
138
+ }
139
+ const playBeep = () => {
140
+ const audioCtx = audioCtxRef.current;
141
+ if (!audioCtx || !audioEnabledRef.current) {
142
+ return;
143
+ }
144
+ const osc = audioCtx.createOscillator();
145
+ const gain = audioCtx.createGain();
146
+ osc.type = "triangle";
147
+ osc.frequency.value = 523.25;
148
+ gain.gain.setValueAtTime(0.15, audioCtx.currentTime);
149
+ gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.08);
150
+ osc.connect(gain);
151
+ gain.connect(audioCtx.destination);
152
+ osc.start();
153
+ osc.stop(audioCtx.currentTime + 0.08);
154
+ };
155
+ const filledBars = Math.round((displayProgress / 100) * LOADING_PROGRESS_SEGMENT_COUNT);
156
+ if (filledBars > prevFilledBars.current) {
157
+ playBeep();
158
+ prevFilledBars.current = filledBars;
159
+ }
160
+ return undefined;
161
+ }, [audioFeedback, displayProgress]);
162
+ React.useEffect(() => {
163
+ const ellipsisInterval = setInterval(() => {
164
+ setEllipsisCount((count) => (count + 1) % 4);
165
+ }, 400);
166
+ return () => clearInterval(ellipsisInterval);
167
+ }, []);
168
+ React.useEffect(() => {
169
+ const timeout = setTimeout(() => {
170
+ setDisplayProgress(progress);
171
+ }, 50);
172
+ return () => clearTimeout(timeout);
173
+ }, [progress]);
174
+ const ellipsis = ".".repeat(ellipsisCount);
175
+ const cleanMessage = message ? message.replace(/\.+$/, "") : "";
176
+ const isLightMode = resolveIsLightMode(themeMode);
177
+ const screenWidth = bounds.width || (typeof window === "undefined" ? 0 : window.innerWidth);
178
+ const screenHeight = bounds.height || (typeof window === "undefined" ? 0 : window.innerHeight);
179
+ return (_jsxs("div", { ref: containerRef, className: `${styles.screen} ${fullscreen ? styles.fullscreen : styles.contained} ${isLightMode ? styles.lightTheme : styles.darkTheme}`.trim(), style: {
180
+ "--screen-height": `${screenHeight}px`,
181
+ "--screen-width": `${screenWidth}px`,
182
+ }, children: [crosses.map((cross) => (_jsx("div", { className: styles.crossContainer, style: {
183
+ "--cross-left": `${cross.x}px`,
184
+ "--cross-delay": `${cross.delay}ms`,
185
+ "--rotation": `${cross.rotation}deg`,
186
+ "--ground": `${cross.groundOffset}%`,
187
+ "--cross-scale": String(cross.scale),
188
+ "--cross-opacity": String(cross.opacity),
189
+ }, onAnimationEnd: (event) => {
190
+ if (event.animationName === "crossFall") {
191
+ event.currentTarget.classList.add(styles.crossLanded);
192
+ }
193
+ }, children: _jsx("div", { className: styles.crossSvg, children: _jsx(LightCrossIcon, { className: styles.crossShape }) }) }, cross.id))), _jsxs("div", { className: styles.centerStack, children: [logo ? _jsx("div", { className: styles.logoWrap, children: logo }) : null, _jsx("div", { className: styles.title, children: title })] }), _jsx(LoadingProgressBar, { progress: displayProgress, className: styles.progressRow }), _jsxs("div", { className: styles.footerMessage, children: [cleanMessage, ellipsis] })] }));
194
+ }
195
+ const STAGE_PROGRESS = {
196
+ init: 0,
197
+ auth: 25,
198
+ agent: 50,
199
+ config: 75,
200
+ ready: 100,
201
+ };
202
+ const STAGE_MESSAGES = {
203
+ init: "Initializing...",
204
+ auth: "Authenticating...",
205
+ agent: "Loading agent...",
206
+ config: "Loading configuration...",
207
+ ready: "Preparing interface...",
208
+ };
209
+ export function useLoadingProgress(isLoading, _phase, stage = "init") {
210
+ const [progress, setProgress] = React.useState(0);
211
+ const [currentMessage, setCurrentMessage] = React.useState("Initializing...");
212
+ const progressRef = React.useRef(0);
213
+ React.useEffect(() => {
214
+ progressRef.current = progress;
215
+ }, [progress]);
216
+ React.useEffect(() => {
217
+ if (!isLoading) {
218
+ setProgress(100);
219
+ progressRef.current = 100;
220
+ setCurrentMessage("Complete!");
221
+ return undefined;
222
+ }
223
+ const targetProgress = STAGE_PROGRESS[stage];
224
+ const targetMessage = STAGE_MESSAGES[stage];
225
+ setCurrentMessage(targetMessage);
226
+ const currentProgressSnapshot = progressRef.current;
227
+ const diff = targetProgress - currentProgressSnapshot;
228
+ const steps = 20;
229
+ const stepDuration = 100;
230
+ let step = 0;
231
+ const interval = setInterval(() => {
232
+ step += 1;
233
+ const easedStep = step / steps;
234
+ const easedProgress = diff * easedStep;
235
+ const nextProgress = Math.min(currentProgressSnapshot + easedProgress, targetProgress);
236
+ progressRef.current = nextProgress;
237
+ setProgress(nextProgress);
238
+ if (step >= steps) {
239
+ clearInterval(interval);
240
+ }
241
+ }, stepDuration);
242
+ return () => clearInterval(interval);
243
+ }, [isLoading, stage]);
244
+ return { progress, message: currentMessage };
245
+ }
246
+ //# sourceMappingURL=LoadingScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingScreen.js","sourceRoot":"","sources":["../../src/components/LoadingScreen.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\n\nimport { LightCrossIcon } from \"@steez-ui/icons\";\n\nimport {\n LoadingProgressBar,\n LOADING_PROGRESS_SEGMENT_COUNT,\n} from \"./LoadingProgressBar.js\";\nimport styles from \"./LoadingScreen.module.css\";\n\nexport interface LoadingScreenProps {\n progress: number;\n message?: string;\n logo?: React.ReactNode;\n title?: React.ReactNode;\n audioFeedback?: boolean;\n fullscreen?: boolean;\n themeMode?: \"auto\" | \"light\" | \"dark\";\n}\n\ninterface Cross {\n id: number;\n x: number;\n rotation: number;\n scale: number;\n groundOffset: number;\n delay: number;\n opacity: number;\n}\n\nfunction randomFloat() {\n return Math.random();\n}\n\nfunction resolveIsLightMode(themeMode: LoadingScreenProps[\"themeMode\"]) {\n if (themeMode === \"light\") {\n return true;\n }\n\n if (themeMode === \"dark\") {\n return false;\n }\n\n if (typeof window === \"undefined\") {\n return false;\n }\n\n return (\n document.documentElement.getAttribute(\"data-theme\") === \"light\" ||\n window.localStorage.getItem(\"theme\") === \"light\"\n );\n}\n\nexport function LoadingScreen({\n progress,\n message,\n logo,\n title = \"LOADING\",\n audioFeedback = false,\n fullscreen = true,\n themeMode = \"auto\",\n}: LoadingScreenProps) {\n const [displayProgress, setDisplayProgress] = React.useState(0);\n const [ellipsisCount, setEllipsisCount] = React.useState(0);\n const [crosses, setCrosses] = React.useState<Cross[]>([]);\n const [bounds, setBounds] = React.useState({ width: 0, height: 0 });\n const prevFilledBars = React.useRef(0);\n const crossIdRef = React.useRef(0);\n const isLoadingRef = React.useRef(true);\n const audioCtxRef = React.useRef<AudioContext | null>(null);\n const audioEnabledRef = React.useRef(false);\n const containerRef = React.useRef<HTMLDivElement>(null);\n\n const updateBounds = React.useCallback(() => {\n const nextWidth =\n containerRef.current?.clientWidth || window.innerWidth || 0;\n const nextHeight =\n containerRef.current?.clientHeight || window.innerHeight || 0;\n\n setBounds((current) => {\n if (current.width === nextWidth && current.height === nextHeight) {\n return current;\n }\n\n return {\n width: nextWidth,\n height: nextHeight,\n };\n });\n }, []);\n\n const spawnCross = React.useCallback(() => {\n if (!isLoadingRef.current || typeof window === \"undefined\") {\n return;\n }\n\n const tilt = (randomFloat() - 0.5) * 6;\n const availableWidth = Math.max(bounds.width || window.innerWidth, 160);\n const nextCross: Cross = {\n id: crossIdRef.current += 1,\n x: randomFloat() * Math.max(availableWidth - 120, 24),\n rotation: tilt,\n scale: 0.4 + randomFloat() * 0.4,\n groundOffset: randomFloat() * 30,\n delay: 0,\n opacity: 0.4 + randomFloat() * 0.3,\n };\n setCrosses((current) => [...current.slice(-17), nextCross]);\n }, [bounds.width]);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n updateBounds();\n window.addEventListener(\"resize\", updateBounds);\n\n const observer =\n typeof ResizeObserver === \"undefined\" || !containerRef.current\n ? null\n : new ResizeObserver(() => {\n updateBounds();\n });\n\n if (observer && containerRef.current) {\n observer.observe(containerRef.current);\n }\n\n return () => {\n window.removeEventListener(\"resize\", updateBounds);\n observer?.disconnect();\n };\n }, [updateBounds]);\n\n React.useEffect(() => {\n isLoadingRef.current = true;\n\n const scheduleNextCross = () => {\n const delay = 400 + randomFloat() * 300;\n return setTimeout(() => {\n spawnCross();\n if (isLoadingRef.current) {\n scheduleNextCross();\n }\n }, delay);\n };\n\n const timeoutId = scheduleNextCross();\n return () => {\n clearTimeout(timeoutId);\n isLoadingRef.current = false;\n };\n }, [spawnCross]);\n\n React.useEffect(() => {\n if (!audioFeedback) {\n return undefined;\n }\n\n const enableAudio = async () => {\n const AudioContextClass =\n window.AudioContext || (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!AudioContextClass) {\n return;\n }\n\n try {\n const ctx = audioCtxRef.current ?? new AudioContextClass();\n audioCtxRef.current = ctx;\n if (ctx.state === \"suspended\") {\n await ctx.resume();\n }\n audioEnabledRef.current = ctx.state === \"running\";\n } catch {\n audioEnabledRef.current = false;\n }\n };\n\n window.addEventListener(\"pointerdown\", enableAudio, {\n once: true,\n passive: true,\n });\n window.addEventListener(\"keydown\", enableAudio, { once: true });\n\n return () => {\n window.removeEventListener(\"pointerdown\", enableAudio);\n window.removeEventListener(\"keydown\", enableAudio);\n if (audioCtxRef.current) {\n void audioCtxRef.current.close().catch(() => undefined);\n audioCtxRef.current = null;\n }\n audioEnabledRef.current = false;\n };\n }, [audioFeedback]);\n\n React.useEffect(() => {\n if (!audioFeedback) {\n return undefined;\n }\n\n const playBeep = () => {\n const audioCtx = audioCtxRef.current;\n if (!audioCtx || !audioEnabledRef.current) {\n return;\n }\n\n const osc = audioCtx.createOscillator();\n const gain = audioCtx.createGain();\n osc.type = \"triangle\";\n osc.frequency.value = 523.25;\n gain.gain.setValueAtTime(0.15, audioCtx.currentTime);\n gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.08);\n osc.connect(gain);\n gain.connect(audioCtx.destination);\n osc.start();\n osc.stop(audioCtx.currentTime + 0.08);\n };\n\n const filledBars = Math.round(\n (displayProgress / 100) * LOADING_PROGRESS_SEGMENT_COUNT,\n );\n if (filledBars > prevFilledBars.current) {\n playBeep();\n prevFilledBars.current = filledBars;\n }\n\n return undefined;\n }, [audioFeedback, displayProgress]);\n\n React.useEffect(() => {\n const ellipsisInterval = setInterval(() => {\n setEllipsisCount((count) => (count + 1) % 4);\n }, 400);\n return () => clearInterval(ellipsisInterval);\n }, []);\n\n React.useEffect(() => {\n const timeout = setTimeout(() => {\n setDisplayProgress(progress);\n }, 50);\n return () => clearTimeout(timeout);\n }, [progress]);\n\n const ellipsis = \".\".repeat(ellipsisCount);\n const cleanMessage = message ? message.replace(/\\.+$/, \"\") : \"\";\n const isLightMode = resolveIsLightMode(themeMode);\n const screenWidth =\n bounds.width || (typeof window === \"undefined\" ? 0 : window.innerWidth);\n const screenHeight =\n bounds.height || (typeof window === \"undefined\" ? 0 : window.innerHeight);\n\n return (\n <div\n ref={containerRef}\n className={`${styles.screen} ${fullscreen ? styles.fullscreen : styles.contained} ${\n isLightMode ? styles.lightTheme : styles.darkTheme\n }`.trim()}\n style={\n {\n \"--screen-height\": `${screenHeight}px`,\n \"--screen-width\": `${screenWidth}px`,\n } as React.CSSProperties\n }\n >\n {crosses.map((cross) => (\n <div\n key={cross.id}\n className={styles.crossContainer}\n style={\n {\n \"--cross-left\": `${cross.x}px`,\n \"--cross-delay\": `${cross.delay}ms`,\n \"--rotation\": `${cross.rotation}deg`,\n \"--ground\": `${cross.groundOffset}%`,\n \"--cross-scale\": String(cross.scale),\n \"--cross-opacity\": String(cross.opacity),\n } as React.CSSProperties\n }\n onAnimationEnd={(event) => {\n if (event.animationName === \"crossFall\") {\n event.currentTarget.classList.add(styles.crossLanded);\n }\n }}\n >\n <div className={styles.crossSvg}>\n <LightCrossIcon className={styles.crossShape} />\n </div>\n </div>\n ))}\n\n <div className={styles.centerStack}>\n {logo ? <div className={styles.logoWrap}>{logo}</div> : null}\n <div className={styles.title}>{title}</div>\n </div>\n\n <LoadingProgressBar progress={displayProgress} className={styles.progressRow} />\n\n <div className={styles.footerMessage}>\n {cleanMessage}\n {ellipsis}\n </div>\n </div>\n );\n}\n\nexport type LoadingStage = \"init\" | \"auth\" | \"agent\" | \"config\" | \"ready\";\n\nconst STAGE_PROGRESS: Record<LoadingStage, number> = {\n init: 0,\n auth: 25,\n agent: 50,\n config: 75,\n ready: 100,\n};\n\nconst STAGE_MESSAGES: Record<LoadingStage, string> = {\n init: \"Initializing...\",\n auth: \"Authenticating...\",\n agent: \"Loading agent...\",\n config: \"Loading configuration...\",\n ready: \"Preparing interface...\",\n};\n\nexport function useLoadingProgress(\n isLoading: boolean,\n _phase?: string,\n stage: LoadingStage = \"init\",\n) {\n const [progress, setProgress] = React.useState(0);\n const [currentMessage, setCurrentMessage] = React.useState(\"Initializing...\");\n const progressRef = React.useRef(0);\n\n React.useEffect(() => {\n progressRef.current = progress;\n }, [progress]);\n\n React.useEffect(() => {\n if (!isLoading) {\n setProgress(100);\n progressRef.current = 100;\n setCurrentMessage(\"Complete!\");\n return undefined;\n }\n\n const targetProgress = STAGE_PROGRESS[stage];\n const targetMessage = STAGE_MESSAGES[stage];\n setCurrentMessage(targetMessage);\n\n const currentProgressSnapshot = progressRef.current;\n const diff = targetProgress - currentProgressSnapshot;\n const steps = 20;\n const stepDuration = 100;\n let step = 0;\n\n const interval = setInterval(() => {\n step += 1;\n const easedStep = step / steps;\n const easedProgress = diff * easedStep;\n const nextProgress = Math.min(\n currentProgressSnapshot + easedProgress,\n targetProgress,\n );\n progressRef.current = nextProgress;\n setProgress(nextProgress);\n\n if (step >= steps) {\n clearInterval(interval);\n }\n }, stepDuration);\n\n return () => clearInterval(interval);\n }, [isLoading, stage]);\n\n return { progress, message: currentMessage };\n}\n"]}
@@ -0,0 +1,108 @@
1
+ .screen {
2
+ position: fixed;
3
+ inset: 0;
4
+ z-index: 9999;
5
+ display: flex;
6
+ flex-direction: column;
7
+ align-items: center;
8
+ justify-content: center;
9
+ padding: 20px;
10
+ overflow: hidden;
11
+ font-family: var(--font-primary);
12
+ }
13
+
14
+ .fullscreen {
15
+ position: fixed;
16
+ }
17
+
18
+ .contained {
19
+ position: absolute;
20
+ border: 1px solid var(--border-color);
21
+ }
22
+
23
+ .lightTheme {
24
+ background: #fafbfc;
25
+ color: #1a1a1a;
26
+ }
27
+
28
+ .darkTheme {
29
+ background: #0a0a0a;
30
+ color: #cbcbcc;
31
+ }
32
+
33
+ @keyframes crossFall {
34
+ 0% {
35
+ transform: translateY(-450px) rotate(var(--rotation));
36
+ opacity: 0;
37
+ }
38
+
39
+ 10% {
40
+ opacity: 1;
41
+ }
42
+
43
+ 100% {
44
+ transform: translateY(calc(var(--screen-height, 100vh) - var(--ground) - 50px))
45
+ rotate(var(--rotation));
46
+ opacity: 1;
47
+ }
48
+ }
49
+
50
+ .crossContainer {
51
+ position: absolute;
52
+ top: 0;
53
+ left: var(--cross-left, 0px);
54
+ z-index: 1;
55
+ will-change: transform;
56
+ animation: crossFall 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
57
+ animation-delay: var(--cross-delay, 0ms);
58
+ }
59
+
60
+ .crossSvg {
61
+ transform: scale(var(--cross-scale, 1));
62
+ transform-origin: center top;
63
+ opacity: var(--cross-opacity, 0.6);
64
+ }
65
+
66
+ .crossLanded .crossSvg {
67
+ opacity: 1 !important;
68
+ }
69
+
70
+ .crossShape {
71
+ color: currentColor;
72
+ }
73
+
74
+ .centerStack {
75
+ position: relative;
76
+ z-index: 10;
77
+ display: flex;
78
+ flex-direction: column;
79
+ align-items: center;
80
+ gap: 24px;
81
+ }
82
+
83
+ .logoWrap {
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ }
88
+
89
+ .title {
90
+ font-size: clamp(24px, 8vw, 48px);
91
+ font-weight: 700;
92
+ letter-spacing: 8px;
93
+ }
94
+
95
+ .progressRow {
96
+ position: relative;
97
+ z-index: 10;
98
+ }
99
+
100
+ .footerMessage {
101
+ position: absolute;
102
+ right: 40px;
103
+ bottom: 40px;
104
+ z-index: 10;
105
+ opacity: 0.5;
106
+ font-family: var(--font-mono);
107
+ font-size: 14px;
108
+ }
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ export interface OverlayButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
3
+ active?: boolean;
4
+ }
5
+ export declare function OverlayButton({ active, className, ...props }: OverlayButtonProps): import("react/jsx-runtime").JSX.Element;
6
+ export default OverlayButton;
7
+ //# sourceMappingURL=OverlayButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OverlayButton.d.ts","sourceRoot":"","sources":["../../src/components/OverlayButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,kBACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,SAAc,EACd,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAKpB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import styles from "./OverlayButton.module.css";
3
+ export function OverlayButton({ active, className = "", ...props }) {
4
+ const classes = `${styles.overlayBtn} ${active ? styles.overlayBtnActive : ""} ${className}`.trim();
5
+ return _jsx("button", { type: "button", className: classes, ...props });
6
+ }
7
+ export default OverlayButton;
8
+ //# sourceMappingURL=OverlayButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OverlayButton.js","sourceRoot":"","sources":["../../src/components/OverlayButton.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,4BAA4B,CAAC;AAOhD,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,EACN,SAAS,GAAG,EAAE,EACd,GAAG,KAAK,EACW;IACnB,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,UAAU,IAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EACrC,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC;IACvB,OAAO,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAE,OAAO,KAAM,KAAK,GAAI,CAAC;AACjE,CAAC;AAED,eAAe,aAAa,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./OverlayButton.module.css\";\n\nexport interface OverlayButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n active?: boolean;\n}\n\nexport function OverlayButton({\n active,\n className = \"\",\n ...props\n}: OverlayButtonProps) {\n const classes = `${styles.overlayBtn} ${\n active ? styles.overlayBtnActive : \"\"\n } ${className}`.trim();\n return <button type=\"button\" className={classes} {...props} />;\n}\n\nexport default OverlayButton;\n"]}
@@ -0,0 +1,32 @@
1
+ .overlayBtn {
2
+ width: var(--overlay-btn-size, 2rem);
3
+ height: var(--overlay-btn-size, 2rem);
4
+ display: inline-flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ border: 1px solid var(--border-color);
8
+ border-radius: var(--overlay-btn-radius, 0.5rem);
9
+ background: color-mix(in srgb, var(--bg-primary) 72%, transparent);
10
+ backdrop-filter: blur(2px);
11
+ color: var(--text-secondary);
12
+ cursor: pointer;
13
+ opacity: 0.8;
14
+ transition:
15
+ opacity 150ms ease,
16
+ background-color 150ms ease,
17
+ color 150ms ease,
18
+ border-color 150ms ease;
19
+ }
20
+
21
+ .overlayBtn:hover {
22
+ background: color-mix(in srgb, var(--bg-primary) 92%, transparent);
23
+ color: var(--text-primary);
24
+ opacity: 1;
25
+ }
26
+
27
+ .overlayBtnActive,
28
+ .overlayBtnActive:hover {
29
+ background: var(--text-primary);
30
+ border-color: var(--text-primary);
31
+ color: var(--bg-primary);
32
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ export interface PixelTooltipProps {
3
+ content: string;
4
+ children: React.ReactNode;
5
+ position?: "top" | "bottom" | "left" | "right";
6
+ delay?: number;
7
+ }
8
+ export declare function PixelTooltip({ content, children, position, delay, }: PixelTooltipProps): import("react/jsx-runtime").JSX.Element;
9
+ export default PixelTooltip;
10
+ //# sourceMappingURL=PixelTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixelTooltip.d.ts","sourceRoot":"","sources":["../../src/components/PixelTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,QAAgB,EAChB,KAAW,GACZ,EAAE,iBAAiB,2CAgEnB;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import styles from "./PixelTooltip.module.css";
4
+ export function PixelTooltip({ content, children, position = "top", delay = 200, }) {
5
+ const [isVisible, setIsVisible] = React.useState(false);
6
+ const [coords, setCoords] = React.useState({ x: 0, y: 0, width: 0 });
7
+ const timeoutRef = React.useRef(null);
8
+ const triggerRef = React.useRef(null);
9
+ const handleMouseEnter = React.useCallback(() => {
10
+ timeoutRef.current = setTimeout(() => {
11
+ if (triggerRef.current) {
12
+ const rect = triggerRef.current.getBoundingClientRect();
13
+ setCoords({
14
+ x: rect.left,
15
+ y: rect.bottom,
16
+ width: rect.width,
17
+ });
18
+ }
19
+ setIsVisible(true);
20
+ }, delay);
21
+ }, [delay]);
22
+ const handleMouseLeave = React.useCallback(() => {
23
+ if (timeoutRef.current) {
24
+ clearTimeout(timeoutRef.current);
25
+ timeoutRef.current = null;
26
+ }
27
+ setIsVisible(false);
28
+ }, []);
29
+ React.useEffect(() => () => {
30
+ if (timeoutRef.current) {
31
+ clearTimeout(timeoutRef.current);
32
+ }
33
+ }, []);
34
+ return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, className: styles.trigger, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: children }), isVisible ? (_jsx("div", { className: `${styles.tooltip} ${styles[position]} ${styles.show}`.trim(), style: {
35
+ left: `${coords.x + 5}px`,
36
+ top: `${coords.y + 8}px`,
37
+ width: `${Math.max(coords.width - 20, 60)}px`,
38
+ }, children: _jsx("div", { className: styles.pixelContainer, children: _jsx("div", { className: styles.content, children: content }) }) })) : null] }));
39
+ }
40
+ export default PixelTooltip;
41
+ //# sourceMappingURL=PixelTooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PixelTooltip.js","sourceRoot":"","sources":["../../src/components/PixelTooltip.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAS/C,MAAM,UAAU,YAAY,CAAC,EAC3B,OAAO,EACP,QAAQ,EACR,QAAQ,GAAG,KAAK,EAChB,KAAK,GAAG,GAAG,GACO;IAClB,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAuC,IAAI,CAAC,CAAC;IAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEtD,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC9C,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;gBACxD,SAAS,CAAC;oBACR,CAAC,EAAE,IAAI,CAAC,IAAI;oBACZ,CAAC,EAAE,IAAI,CAAC,MAAM;oBACd,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;YACD,YAAY,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC9C,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACjC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,KAAK,CAAC,SAAS,CACb,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO,CACL,8BACE,cACE,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,MAAM,CAAC,OAAO,EACzB,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,gBAAgB,YAE7B,QAAQ,GACL,EAEL,SAAS,CAAC,CAAC,CAAC,CACX,cACE,SAAS,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EACxE,KAAK,EAAE;oBACL,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI;oBACzB,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI;oBACxB,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI;iBAC9C,YAED,cAAK,SAAS,EAAE,MAAM,CAAC,cAAc,YACnC,cAAK,SAAS,EAAE,MAAM,CAAC,OAAO,YAAG,OAAO,GAAO,GAC3C,GACF,CACP,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./PixelTooltip.module.css\";\n\nexport interface PixelTooltipProps {\n content: string;\n children: React.ReactNode;\n position?: \"top\" | \"bottom\" | \"left\" | \"right\";\n delay?: number;\n}\n\nexport function PixelTooltip({\n content,\n children,\n position = \"top\",\n delay = 200,\n}: PixelTooltipProps) {\n const [isVisible, setIsVisible] = React.useState(false);\n const [coords, setCoords] = React.useState({ x: 0, y: 0, width: 0 });\n const timeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const triggerRef = React.useRef<HTMLDivElement>(null);\n\n const handleMouseEnter = React.useCallback(() => {\n timeoutRef.current = setTimeout(() => {\n if (triggerRef.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n setCoords({\n x: rect.left,\n y: rect.bottom,\n width: rect.width,\n });\n }\n setIsVisible(true);\n }, delay);\n }, [delay]);\n\n const handleMouseLeave = React.useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n setIsVisible(false);\n }, []);\n\n React.useEffect(\n () => () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n },\n [],\n );\n\n return (\n <>\n <div\n ref={triggerRef}\n className={styles.trigger}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {children}\n </div>\n\n {isVisible ? (\n <div\n className={`${styles.tooltip} ${styles[position]} ${styles.show}`.trim()}\n style={{\n left: `${coords.x + 5}px`,\n top: `${coords.y + 8}px`,\n width: `${Math.max(coords.width - 20, 60)}px`,\n }}\n >\n <div className={styles.pixelContainer}>\n <div className={styles.content}>{content}</div>\n </div>\n </div>\n ) : null}\n </>\n );\n}\n\nexport default PixelTooltip;\n"]}
@@ -0,0 +1,81 @@
1
+ .trigger {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ cursor: help;
5
+ }
6
+
7
+ .tooltip {
8
+ position: fixed;
9
+ z-index: var(--z-tooltip);
10
+ pointer-events: none;
11
+ opacity: 0;
12
+ transition:
13
+ opacity 250ms ease-in-out,
14
+ transform 250ms ease-in-out;
15
+ }
16
+
17
+ .tooltip.show {
18
+ opacity: 1;
19
+ animation: tooltipFadeIn 250ms ease-out forwards;
20
+ }
21
+
22
+ .pixelContainer {
23
+ position: relative;
24
+ width: fit-content;
25
+ max-width: 150px;
26
+ padding: 6px 10px;
27
+ background: var(--accent-primary);
28
+ border: 1px solid var(--accent-primary);
29
+ white-space: normal;
30
+ image-rendering: pixelated;
31
+ image-rendering: -moz-crisp-edges;
32
+ image-rendering: crisp-edges;
33
+ }
34
+
35
+ .content {
36
+ position: relative;
37
+ z-index: 1;
38
+ color: #fff;
39
+ font-family: var(--font-mono);
40
+ font-size: 11px;
41
+ line-height: 1.3;
42
+ text-align: left;
43
+ }
44
+
45
+ .tooltip.top {
46
+ margin-top: -8px;
47
+ transform: translateY(-100%);
48
+ }
49
+
50
+ .tooltip.bottom {
51
+ margin-top: 0;
52
+ transform: translateY(0);
53
+ }
54
+
55
+ .tooltip.left {
56
+ margin-left: -8px;
57
+ transform: translateX(-100%) translateY(-50%);
58
+ }
59
+
60
+ .tooltip.right {
61
+ margin-left: 8px;
62
+ transform: translateY(-50%);
63
+ }
64
+
65
+ @keyframes tooltipFadeIn {
66
+ 0% {
67
+ opacity: 0;
68
+ transform: translateY(-4px) scale(0.95);
69
+ }
70
+
71
+ 100% {
72
+ opacity: 1;
73
+ transform: translateY(0) scale(1);
74
+ }
75
+ }
76
+
77
+ @media (max-width: 768px) {
78
+ .tooltip {
79
+ display: none;
80
+ }
81
+ }
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ export type WidgetSize = "xs-a" | "xs-b" | "sm-a" | "sm-b";
3
+ export interface WidgetCardProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ title?: string;
5
+ icon?: React.ReactNode;
6
+ children: React.ReactNode;
7
+ size?: WidgetSize | "sm" | "md" | "lg";
8
+ overlay?: React.ReactNode;
9
+ }
10
+ export declare function WidgetCard({ title, icon, children, size, className, overlay, style, ...props }: WidgetCardProps): import("react/jsx-runtime").JSX.Element;
11
+ export default WidgetCard;
12
+ //# sourceMappingURL=WidgetCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetCard.d.ts","sourceRoot":"","sources":["../../src/components/WidgetCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAa,EACb,SAAc,EACd,OAAO,EACP,KAAK,EACL,GAAG,KAAK,EACT,EAAE,eAAe,2CA+BjB;AAED,eAAe,UAAU,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styles from "./WidgetCard.module.css";
3
+ export function WidgetCard({ title, icon, children, size = "sm-b", className = "", overlay, style, ...props }) {
4
+ const sizeClassMap = {
5
+ "xs-a": styles.widgetXsA,
6
+ "xs-b": styles.widgetXsB,
7
+ "sm-a": styles.widgetSmA,
8
+ "sm-b": styles.widgetSmB,
9
+ sm: styles.widgetSmA,
10
+ md: styles.widgetSmB,
11
+ lg: styles.widgetSmB,
12
+ };
13
+ const sizeClass = sizeClassMap[size] || styles.widgetSmB;
14
+ return (_jsxs("div", { className: `${sizeClass} ${className}`.trim(), style: { position: "relative", ...style }, ...props, children: [title ? (_jsx("div", { className: styles.header, children: _jsxs("div", { className: styles.titleRow, children: [icon ? _jsx("div", { className: styles.icon, children: icon }) : null, _jsx("h3", { className: styles.title, children: title })] }) })) : null, _jsx("div", { className: styles.body, children: children }), overlay] }));
15
+ }
16
+ export default WidgetCard;
17
+ //# sourceMappingURL=WidgetCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetCard.js","sourceRoot":"","sources":["../../src/components/WidgetCard.tsx"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAY7C,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,GAAG,MAAM,EACb,SAAS,GAAG,EAAE,EACd,OAAO,EACP,KAAK,EACL,GAAG,KAAK,EACQ;IAChB,MAAM,YAAY,GAChB;QACE,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,MAAM,EAAE,MAAM,CAAC,SAAS;QACxB,EAAE,EAAE,MAAM,CAAC,SAAS;QACpB,EAAE,EAAE,MAAM,CAAC,SAAS;QACpB,EAAE,EAAE,MAAM,CAAC,SAAS;KACrB,CAAC;IACJ,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC;IAEzD,OAAO,CACL,eACE,SAAS,EAAE,GAAG,SAAS,IAAI,SAAS,EAAE,CAAC,IAAI,EAAE,EAC7C,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,KACrC,KAAK,aAER,KAAK,CAAC,CAAC,CAAC,CACP,cAAK,SAAS,EAAE,MAAM,CAAC,MAAM,YAC3B,eAAK,SAAS,EAAE,MAAM,CAAC,QAAQ,aAC5B,IAAI,CAAC,CAAC,CAAC,cAAK,SAAS,EAAE,MAAM,CAAC,IAAI,YAAG,IAAI,GAAO,CAAC,CAAC,CAAC,IAAI,EACxD,aAAI,SAAS,EAAE,MAAM,CAAC,KAAK,YAAG,KAAK,GAAM,IACrC,GACF,CACP,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,SAAS,EAAE,MAAM,CAAC,IAAI,YAAG,QAAQ,GAAO,EAC5C,OAAO,IACJ,CACP,CAAC;AACJ,CAAC;AAED,eAAe,UAAU,CAAC","sourcesContent":["import React from \"react\";\n\nimport styles from \"./WidgetCard.module.css\";\n\nexport type WidgetSize = \"xs-a\" | \"xs-b\" | \"sm-a\" | \"sm-b\";\n\nexport interface WidgetCardProps extends React.HTMLAttributes<HTMLDivElement> {\n title?: string;\n icon?: React.ReactNode;\n children: React.ReactNode;\n size?: WidgetSize | \"sm\" | \"md\" | \"lg\";\n overlay?: React.ReactNode;\n}\n\nexport function WidgetCard({\n title,\n icon,\n children,\n size = \"sm-b\",\n className = \"\",\n overlay,\n style,\n ...props\n}: WidgetCardProps) {\n const sizeClassMap: Record<Exclude<WidgetCardProps[\"size\"], undefined>, string> =\n {\n \"xs-a\": styles.widgetXsA,\n \"xs-b\": styles.widgetXsB,\n \"sm-a\": styles.widgetSmA,\n \"sm-b\": styles.widgetSmB,\n sm: styles.widgetSmA,\n md: styles.widgetSmB,\n lg: styles.widgetSmB,\n };\n const sizeClass = sizeClassMap[size] || styles.widgetSmB;\n\n return (\n <div\n className={`${sizeClass} ${className}`.trim()}\n style={{ position: \"relative\", ...style }}\n {...props}\n >\n {title ? (\n <div className={styles.header}>\n <div className={styles.titleRow}>\n {icon ? <div className={styles.icon}>{icon}</div> : null}\n <h3 className={styles.title}>{title}</h3>\n </div>\n </div>\n ) : null}\n <div className={styles.body}>{children}</div>\n {overlay}\n </div>\n );\n}\n\nexport default WidgetCard;\n"]}
@@ -0,0 +1,75 @@
1
+ .widgetXsA,
2
+ .widgetXsB,
3
+ .widgetSmA,
4
+ .widgetSmB {
5
+ background: var(--border-color);
6
+ border: none;
7
+ border-radius: 2px;
8
+ overflow: hidden;
9
+ transition: background 200ms ease;
10
+ }
11
+
12
+ .widgetXsA:hover,
13
+ .widgetXsB:hover,
14
+ .widgetSmA:hover,
15
+ .widgetSmB:hover {
16
+ background: var(--text-primary);
17
+ }
18
+
19
+ .widgetXsA {
20
+ grid-column: span 1;
21
+ grid-row: span 1;
22
+ min-height: 180px;
23
+ }
24
+
25
+ .widgetXsB {
26
+ grid-column: span 1;
27
+ grid-row: span 2;
28
+ min-height: 360px;
29
+ }
30
+
31
+ .widgetSmA {
32
+ grid-column: span 2;
33
+ grid-row: span 1;
34
+ min-height: 180px;
35
+ }
36
+
37
+ .widgetSmB {
38
+ grid-column: span 2;
39
+ grid-row: span 2;
40
+ min-height: 360px;
41
+ }
42
+
43
+ .header {
44
+ display: flex;
45
+ align-items: center;
46
+ justify-content: space-between;
47
+ padding: 12px 16px;
48
+ border-bottom: 1px solid var(--border-color);
49
+ }
50
+
51
+ .titleRow {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ }
56
+
57
+ .icon {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ }
62
+
63
+ .title {
64
+ margin: 0;
65
+ color: var(--text-primary);
66
+ font-family: var(--font-mono);
67
+ font-size: 14px;
68
+ font-weight: 600;
69
+ letter-spacing: 0.05em;
70
+ text-transform: uppercase;
71
+ }
72
+
73
+ .body {
74
+ padding: 12px 16px;
75
+ }
package/dist/index.d.ts CHANGED
@@ -13,10 +13,14 @@ export { CornerBracketCard, type CornerBracketCardProps } from "./components/Cor
13
13
  export { ErrorMessage, type ErrorMessageProps } from "./components/ErrorMessage.js";
14
14
  export { HeartbeatIndicator, HeartbeatPulse, type HeartbeatIndicatorProps, type HeartbeatPulseProps, } from "./components/HeartbeatPulse.js";
15
15
  export { HexagonGrid, type HexagonGridProps } from "./components/HexagonGrid.js";
16
+ export { LoadingOverlayCrystalline, type LoadingOverlayCrystallineProps, } from "./components/LoadingOverlayCrystalline.js";
16
17
  export { LOADING_PROGRESS_SEGMENT_COUNT, LoadingProgressBar, type LoadingProgressBarProps, } from "./components/LoadingProgressBar.js";
18
+ export { LoadingScreen, type LoadingScreenProps, type LoadingStage, useLoadingProgress, } from "./components/LoadingScreen.js";
17
19
  export { MarqueeStrip, type MarqueeStripProps } from "./components/MarqueeStrip.js";
20
+ export { OverlayButton, type OverlayButtonProps, } from "./components/OverlayButton.js";
18
21
  export { PageHeader, type PageHeaderProps } from "./components/PageHeader.js";
19
22
  export { PageTemplate, type PageTemplateProps } from "./components/PageTemplate.js";
23
+ export { PixelTooltip, type PixelTooltipProps, } from "./components/PixelTooltip.js";
20
24
  export { QuickInfoCard, type QuickInfoCardProps, type QuickInfoItem, type StorageProgress, } from "./components/QuickInfoCard.js";
21
25
  export { RuntimeOrbitDiagram, type RuntimeOrbitDiagramProps, type RuntimeOrbitNode, } from "./components/RuntimeOrbitDiagram.js";
22
26
  export { Section, type SectionProps } from "./components/Section.js";
@@ -28,4 +32,5 @@ export { StrokedText, type StrokedTextProps } from "./components/StrokedText.js"
28
32
  export { TabbedPanel, type TabbedPanelProps, type TabbedPanelTab } from "./components/TabbedPanel.js";
29
33
  export { ThemedCard, type ThemedCardProps } from "./components/ThemedCard.js";
30
34
  export { ThemeToggle, type ThemeToggleProps } from "./components/ThemeToggle.js";
35
+ export { WidgetCard, type WidgetCardProps, type WidgetSize } from "./components/WidgetCard.js";
31
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EACL,yBAAyB,EACzB,KAAK,8BAA8B,GACpC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,GACxB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/index.js CHANGED
@@ -13,10 +13,14 @@ export { CornerBracketCard } from "./components/CornerBracketCard.js";
13
13
  export { ErrorMessage } from "./components/ErrorMessage.js";
14
14
  export { HeartbeatIndicator, HeartbeatPulse, } from "./components/HeartbeatPulse.js";
15
15
  export { HexagonGrid } from "./components/HexagonGrid.js";
16
+ export { LoadingOverlayCrystalline, } from "./components/LoadingOverlayCrystalline.js";
16
17
  export { LOADING_PROGRESS_SEGMENT_COUNT, LoadingProgressBar, } from "./components/LoadingProgressBar.js";
18
+ export { LoadingScreen, useLoadingProgress, } from "./components/LoadingScreen.js";
17
19
  export { MarqueeStrip } from "./components/MarqueeStrip.js";
20
+ export { OverlayButton, } from "./components/OverlayButton.js";
18
21
  export { PageHeader } from "./components/PageHeader.js";
19
22
  export { PageTemplate } from "./components/PageTemplate.js";
23
+ export { PixelTooltip, } from "./components/PixelTooltip.js";
20
24
  export { QuickInfoCard, } from "./components/QuickInfoCard.js";
21
25
  export { RuntimeOrbitDiagram, } from "./components/RuntimeOrbitDiagram.js";
22
26
  export { Section } from "./components/Section.js";
@@ -28,4 +32,5 @@ export { StrokedText } from "./components/StrokedText.js";
28
32
  export { TabbedPanel } from "./components/TabbedPanel.js";
29
33
  export { ThemedCard } from "./components/ThemedCard.js";
30
34
  export { ThemeToggle } from "./components/ThemeToggle.js";
35
+ export { WidgetCard } from "./components/WidgetCard.js";
31
36
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EACL,cAAc,GAEf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,cAAc,EACd,mBAAmB,GAGpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,eAAe,GAGhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,eAAe,GAEhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,iBAAiB,GAElB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,GAGf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,GAEnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,aAAa,GAId,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,mBAAmB,GAGpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,aAAa,GAEd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gBAAgB,GAGjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAA8C,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC","sourcesContent":["export { AvatarStage, type AvatarStageProps } from \"./components/AvatarStage.js\";\nexport { BlinkText, type BlinkTextProps } from \"./components/BlinkText.js\";\nexport { Button, type ButtonProps } from \"./components/Button.js\";\nexport { CopyButton, type CopyButtonProps } from \"./components/CopyButton.js\";\nexport { CyberpunkCheckbox, type CyberpunkCheckboxProps } from \"./components/CyberpunkCheckbox.js\";\nexport {\n CyberpunkInput,\n type CyberpunkInputProps,\n} from \"./components/CyberpunkInput.js\";\nexport {\n CyberpunkRadio,\n CyberpunkRadioGroup,\n type CyberpunkRadioGroupProps,\n type CyberpunkRadioProps,\n} from \"./components/CyberpunkRadio.js\";\nexport {\n CyberpunkSelect,\n type CyberpunkSelectOption,\n type CyberpunkSelectProps,\n} from \"./components/CyberpunkSelect.js\";\nexport {\n CyberpunkSlider,\n type CyberpunkSliderProps,\n} from \"./components/CyberpunkSlider.js\";\nexport {\n CyberpunkTextarea,\n type CyberpunkTextareaProps,\n} from \"./components/CyberpunkTextarea.js\";\nexport { CyberpunkTile, type CyberpunkTileProps } from \"./components/CyberpunkTile.js\";\nexport { CornerBracketCard, type CornerBracketCardProps } from \"./components/CornerBracketCard.js\";\nexport { ErrorMessage, type ErrorMessageProps } from \"./components/ErrorMessage.js\";\nexport {\n HeartbeatIndicator,\n HeartbeatPulse,\n type HeartbeatIndicatorProps,\n type HeartbeatPulseProps,\n} from \"./components/HeartbeatPulse.js\";\nexport { HexagonGrid, type HexagonGridProps } from \"./components/HexagonGrid.js\";\nexport {\n LOADING_PROGRESS_SEGMENT_COUNT,\n LoadingProgressBar,\n type LoadingProgressBarProps,\n} from \"./components/LoadingProgressBar.js\";\nexport { MarqueeStrip, type MarqueeStripProps } from \"./components/MarqueeStrip.js\";\nexport { PageHeader, type PageHeaderProps } from \"./components/PageHeader.js\";\nexport { PageTemplate, type PageTemplateProps } from \"./components/PageTemplate.js\";\nexport {\n QuickInfoCard,\n type QuickInfoCardProps,\n type QuickInfoItem,\n type StorageProgress,\n} from \"./components/QuickInfoCard.js\";\nexport {\n RuntimeOrbitDiagram,\n type RuntimeOrbitDiagramProps,\n type RuntimeOrbitNode,\n} from \"./components/RuntimeOrbitDiagram.js\";\nexport { Section, type SectionProps } from \"./components/Section.js\";\nexport {\n SectionHeader,\n type SectionHeaderProps,\n} from \"./components/SectionHeader.js\";\nexport {\n SegmentedControl,\n type SegmentedControlOption,\n type SegmentedControlProps,\n} from \"./components/SegmentedControl.js\";\nexport { StatCard, type StatCardProps } from \"./components/StatCard.js\";\nexport { StatusMessage, type StatusMessageProps } from \"./components/StatusMessage.js\";\nexport { StrokedText, type StrokedTextProps } from \"./components/StrokedText.js\";\nexport { TabbedPanel, type TabbedPanelProps, type TabbedPanelTab } from \"./components/TabbedPanel.js\";\nexport { ThemedCard, type ThemedCardProps } from \"./components/ThemedCard.js\";\nexport { ThemeToggle, type ThemeToggleProps } from \"./components/ThemeToggle.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,SAAS,EAAuB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAoB,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EACL,cAAc,GAEf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,cAAc,EACd,mBAAmB,GAGpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,eAAe,GAGhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,eAAe,GAEhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,iBAAiB,GAElB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,cAAc,GAGf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EACL,yBAAyB,GAE1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,GAEnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,aAAa,EAGb,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,aAAa,GAEd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EACL,YAAY,GAEb,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,aAAa,GAId,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,mBAAmB,GAGpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AACrE,OAAO,EACL,aAAa,GAEd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,gBAAgB,GAGjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,WAAW,EAA8C,MAAM,6BAA6B,CAAC;AACtG,OAAO,EAAE,UAAU,EAAwB,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,UAAU,EAAyC,MAAM,4BAA4B,CAAC","sourcesContent":["export { AvatarStage, type AvatarStageProps } from \"./components/AvatarStage.js\";\nexport { BlinkText, type BlinkTextProps } from \"./components/BlinkText.js\";\nexport { Button, type ButtonProps } from \"./components/Button.js\";\nexport { CopyButton, type CopyButtonProps } from \"./components/CopyButton.js\";\nexport { CyberpunkCheckbox, type CyberpunkCheckboxProps } from \"./components/CyberpunkCheckbox.js\";\nexport {\n CyberpunkInput,\n type CyberpunkInputProps,\n} from \"./components/CyberpunkInput.js\";\nexport {\n CyberpunkRadio,\n CyberpunkRadioGroup,\n type CyberpunkRadioGroupProps,\n type CyberpunkRadioProps,\n} from \"./components/CyberpunkRadio.js\";\nexport {\n CyberpunkSelect,\n type CyberpunkSelectOption,\n type CyberpunkSelectProps,\n} from \"./components/CyberpunkSelect.js\";\nexport {\n CyberpunkSlider,\n type CyberpunkSliderProps,\n} from \"./components/CyberpunkSlider.js\";\nexport {\n CyberpunkTextarea,\n type CyberpunkTextareaProps,\n} from \"./components/CyberpunkTextarea.js\";\nexport { CyberpunkTile, type CyberpunkTileProps } from \"./components/CyberpunkTile.js\";\nexport { CornerBracketCard, type CornerBracketCardProps } from \"./components/CornerBracketCard.js\";\nexport { ErrorMessage, type ErrorMessageProps } from \"./components/ErrorMessage.js\";\nexport {\n HeartbeatIndicator,\n HeartbeatPulse,\n type HeartbeatIndicatorProps,\n type HeartbeatPulseProps,\n} from \"./components/HeartbeatPulse.js\";\nexport { HexagonGrid, type HexagonGridProps } from \"./components/HexagonGrid.js\";\nexport {\n LoadingOverlayCrystalline,\n type LoadingOverlayCrystallineProps,\n} from \"./components/LoadingOverlayCrystalline.js\";\nexport {\n LOADING_PROGRESS_SEGMENT_COUNT,\n LoadingProgressBar,\n type LoadingProgressBarProps,\n} from \"./components/LoadingProgressBar.js\";\nexport {\n LoadingScreen,\n type LoadingScreenProps,\n type LoadingStage,\n useLoadingProgress,\n} from \"./components/LoadingScreen.js\";\nexport { MarqueeStrip, type MarqueeStripProps } from \"./components/MarqueeStrip.js\";\nexport {\n OverlayButton,\n type OverlayButtonProps,\n} from \"./components/OverlayButton.js\";\nexport { PageHeader, type PageHeaderProps } from \"./components/PageHeader.js\";\nexport { PageTemplate, type PageTemplateProps } from \"./components/PageTemplate.js\";\nexport {\n PixelTooltip,\n type PixelTooltipProps,\n} from \"./components/PixelTooltip.js\";\nexport {\n QuickInfoCard,\n type QuickInfoCardProps,\n type QuickInfoItem,\n type StorageProgress,\n} from \"./components/QuickInfoCard.js\";\nexport {\n RuntimeOrbitDiagram,\n type RuntimeOrbitDiagramProps,\n type RuntimeOrbitNode,\n} from \"./components/RuntimeOrbitDiagram.js\";\nexport { Section, type SectionProps } from \"./components/Section.js\";\nexport {\n SectionHeader,\n type SectionHeaderProps,\n} from \"./components/SectionHeader.js\";\nexport {\n SegmentedControl,\n type SegmentedControlOption,\n type SegmentedControlProps,\n} from \"./components/SegmentedControl.js\";\nexport { StatCard, type StatCardProps } from \"./components/StatCard.js\";\nexport { StatusMessage, type StatusMessageProps } from \"./components/StatusMessage.js\";\nexport { StrokedText, type StrokedTextProps } from \"./components/StrokedText.js\";\nexport { TabbedPanel, type TabbedPanelProps, type TabbedPanelTab } from \"./components/TabbedPanel.js\";\nexport { ThemedCard, type ThemedCardProps } from \"./components/ThemedCard.js\";\nexport { ThemeToggle, type ThemeToggleProps } from \"./components/ThemeToggle.js\";\nexport { WidgetCard, type WidgetCardProps, type WidgetSize } from \"./components/WidgetCard.js\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steez-ui/ui",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "React primitives authored with CSS modules for Steez UI.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,8 +12,8 @@
12
12
  "react-dom": ">=18"
13
13
  },
14
14
  "dependencies": {
15
- "@steez-ui/icons": "^0.1.6",
16
- "@steez-ui/theme": "^0.1.6"
15
+ "@steez-ui/icons": "^0.1.7",
16
+ "@steez-ui/theme": "^0.1.7"
17
17
  },
18
18
  "exports": {
19
19
  ".": {