doom-design-system 0.4.14 → 0.4.15

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.
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import clsx from "clsx";
4
4
  import { AlertCircle, CheckCircle, Info, XCircle } from "lucide-react";
5
+ import { Text } from "../Text/Text.js";
5
6
  import styles from "./Alert.module.css";
6
7
  const icons = {
7
8
  info: Info,
@@ -11,5 +12,5 @@ const icons = {
11
12
  };
12
13
  export function Alert({ variant = "info", title, description, icon, className, }) {
13
14
  const IconComponent = icons[variant];
14
- return (_jsxs("div", { className: clsx(styles.alert, styles[variant], className), role: "alert", children: [_jsx("div", { className: clsx(styles.iconWrapper, styles[variant]), children: icon || _jsx(IconComponent, { size: 20, strokeWidth: 2.5 }) }), _jsxs("div", { className: styles.content, children: [_jsx("h5", { className: styles.title, children: title }), description && _jsx("p", { className: styles.description, children: description })] })] }));
15
+ return (_jsxs("div", { className: clsx(styles.alert, styles[variant], className), role: "alert", children: [_jsx("div", { className: clsx(styles.iconWrapper, styles[variant]), children: icon || _jsx(IconComponent, { size: 20, strokeWidth: 2.5 }) }), _jsxs("div", { className: styles.content, children: [_jsx(Text, { as: "h1", className: styles.title, variant: "h5", children: title }), description && (_jsx(Text, { as: "p", className: styles.description, variant: "body", children: description }))] })] }));
15
16
  }
@@ -104,20 +104,48 @@
104
104
  padding: 0;
105
105
  }
106
106
  .chartContainer.solid {
107
- --solid-bg: var(--primary);
108
- --solid-fg: var(--primary-foreground);
107
+ /* ROOT CONTEXT (The Field) */
109
108
  background-color: var(--solid-bg);
110
109
  color: var(--solid-fg);
111
- border-color: var(--border-strong);
112
- --text-primary: var(--solid-fg);
113
- --muted-foreground: color-mix(in srgb, var(--solid-fg) 70%, transparent);
114
- --muted: color-mix(in srgb, var(--solid-fg) 20%, transparent);
110
+ /* Root Variables */
115
111
  --background: var(--solid-bg);
116
112
  --foreground: var(--solid-fg);
117
- }
118
- .chartContainer.solid > * {
113
+ --muted-foreground: color-mix(in srgb, var(--solid-fg) 70%, transparent);
114
+ /*
115
+ * Standardized Brand Surface Logic
116
+ * Decouples Modals (Surface) from Buttons (Action)
117
+ */
118
+ --surface-brand: var(--solid-bg);
119
+ --surface-brand-foreground: var(--solid-fg);
120
+ /* SEMANTICS (True Semantic Colors) */
121
+ --success: var(--solid-success);
122
+ --success-foreground: var(--solid-fg);
123
+ --error: var(--solid-error);
124
+ --error-foreground: var(--solid-fg);
125
+ --warning: var(--solid-warning);
126
+ --warning-foreground: var(--solid-fg);
127
+ /* SURFACE COLORS */
128
+ --on-surface: var(--solid-bg);
129
+ --on-surface-muted: var(--solid-bg);
130
+ /* COMPONENT TOKENS */
131
+ --card-bg: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
132
+ --card-border: var(--solid-fg);
133
+ --card-foreground: var(--solid-fg);
134
+ /* POPOVER TOKENS */
135
+ --popover: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
136
+ --popover-foreground: var(--solid-bg);
137
+ /* INPUT TOKENS */
138
+ --input: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
139
+ --border-strong: var(--solid-fg);
140
+ /* BUTTON TOKENS */
119
141
  --primary: var(--solid-fg);
120
- --primary-hover: color-mix(in srgb, var(--solid-fg) 80%, transparent);
142
+ --primary-foreground: var(--solid-bg);
143
+ /* SECONDARY TOKENS */
144
+ --secondary: color-mix(in srgb, var(--solid-bg) 90%, transparent);
145
+ --secondary-foreground: var(--solid-fg);
146
+ /* MUTED TOKENS */
147
+ --muted: color-mix(in srgb, var(--solid-fg) 20%, transparent);
148
+ border-color: var(--border-strong);
121
149
  }
122
150
  .chartContainer.solid :global(.tick) text {
123
151
  fill: var(--solid-fg);
@@ -56,29 +56,53 @@
56
56
  transform: translateX(0);
57
57
  }
58
58
  .panel.solid {
59
- /*
60
- SCALABLE CONTEXTUAL REMAPPING
61
- Save original values then swap semantic tokens to auto-invert content.
62
- */
63
- --solid-bg: var(--primary);
64
- --solid-fg: var(--primary-foreground);
59
+ /* ROOT CONTEXT (The Field) */
65
60
  background-color: var(--solid-bg);
66
61
  color: var(--solid-fg);
67
- /* Swap Semantics & Remap Content on CHILDREN only */
68
- }
69
- .panel.solid > * {
62
+ /* Root Variables */
63
+ --background: var(--solid-bg);
64
+ --foreground: var(--solid-fg);
65
+ --muted-foreground: color-mix(in srgb, var(--solid-fg) 70%, transparent);
66
+ /*
67
+ * Standardized Brand Surface Logic
68
+ * Decouples Modals (Surface) from Buttons (Action)
69
+ */
70
+ --surface-brand: var(--solid-bg);
71
+ --surface-brand-foreground: var(--solid-fg);
72
+ /* SEMANTICS (True Semantic Colors) */
73
+ --success: var(--solid-success);
74
+ --success-foreground: var(--solid-fg);
75
+ --error: var(--solid-error);
76
+ --error-foreground: var(--solid-fg);
77
+ --warning: var(--solid-warning);
78
+ --warning-foreground: var(--solid-fg);
79
+ /* SURFACE COLORS */
80
+ --on-surface: var(--solid-bg);
81
+ --on-surface-muted: var(--solid-bg);
82
+ /* COMPONENT TOKENS */
83
+ --card-bg: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
84
+ --card-border: var(--solid-fg);
85
+ --card-foreground: var(--solid-fg);
86
+ /* POPOVER TOKENS */
87
+ --popover: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
88
+ --popover-foreground: var(--solid-bg);
89
+ /* INPUT TOKENS */
90
+ --input: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
91
+ --border-strong: var(--solid-fg);
92
+ /* BUTTON TOKENS */
70
93
  --primary: var(--solid-fg);
71
94
  --primary-foreground: var(--solid-bg);
72
- --foreground: var(--solid-fg);
73
- --muted-foreground: var(--solid-fg);
95
+ /* SECONDARY TOKENS */
96
+ --secondary: color-mix(in srgb, var(--solid-bg) 90%, transparent);
97
+ --secondary-foreground: var(--solid-fg);
98
+ /* MUTED TOKENS */
99
+ --muted: color-mix(in srgb, var(--solid-fg) 20%, transparent);
74
100
  }
75
101
  .panel.solid .header {
76
102
  background-color: transparent !important;
77
103
  color: var(--solid-fg);
78
104
  }
79
- .panel.solid .content {
80
- background-color: transparent !important;
81
- }
105
+ .panel.solid .content,
82
106
  .panel.solid .footer {
83
107
  background-color: transparent !important;
84
108
  }
@@ -10,7 +10,7 @@
10
10
  flex-direction: column;
11
11
  gap: 0.5rem;
12
12
  width: 100%;
13
- align-items: flex-start;
13
+ align-items: stretch;
14
14
  }
15
15
 
16
16
  .message {
@@ -34,10 +34,22 @@ const getIntrinsicSize = (val) => {
34
34
  }
35
35
  return undefined;
36
36
  };
37
+ const ImageStatus = {
38
+ Loading: "loading",
39
+ Loaded: "loaded",
40
+ Error: "error",
41
+ };
37
42
  export function Image(_a) {
38
43
  var { src, alt, className, fit, style, onLoad, onError, fallbackSrc, aspectRatio, rounded = true, width, height } = _a, props = __rest(_a, ["src", "alt", "className", "fit", "style", "onLoad", "onError", "fallbackSrc", "aspectRatio", "rounded", "width", "height"]);
39
- const [status, setStatus] = useState("loading");
44
+ const [status, setStatus] = useState(ImageStatus.Loading);
40
45
  const [showSkeleton, setShowSkeleton] = useState(true);
46
+ const [storedSrc, setStoredSrc] = useState(src);
47
+ // Render-time state update to avoid flash of broken image
48
+ if (src !== storedSrc) {
49
+ setStoredSrc(src);
50
+ setStatus(ImageStatus.Loading);
51
+ setShowSkeleton(true);
52
+ }
41
53
  const computedAspectRatio = useMemo(() => {
42
54
  if (aspectRatio) {
43
55
  return aspectRatio;
@@ -46,25 +58,16 @@ export function Image(_a) {
46
58
  const h = getIntrinsicSize(height);
47
59
  return w && h ? `${w} / ${h}` : undefined;
48
60
  }, [aspectRatio, width, height]);
49
- const prevSrcRef = useRef(src);
50
61
  const imgRef = useRef(null);
51
62
  useEffect(() => {
52
63
  var _a;
53
64
  if ((_a = imgRef.current) === null || _a === void 0 ? void 0 : _a.complete) {
54
- setStatus("loaded");
65
+ setStatus(ImageStatus.Loaded);
55
66
  }
56
67
  }, []);
57
- // Reset state when source changes
58
- useEffect(() => {
59
- if (prevSrcRef.current !== src) {
60
- setStatus("loading");
61
- setShowSkeleton(true);
62
- prevSrcRef.current = src;
63
- }
64
- }, [src]);
65
68
  // When loaded, keep skeleton for a moment to allow cross-fade
66
69
  useEffect(() => {
67
- if (status === "loaded") {
70
+ if (status === ImageStatus.Loaded) {
68
71
  const timer = setTimeout(() => {
69
72
  setShowSkeleton(false);
70
73
  }, 500); // 500ms delay to allow image to fade in completely
@@ -79,27 +82,27 @@ export function Image(_a) {
79
82
  await img.decode();
80
83
  }
81
84
  }
82
- catch (error) {
85
+ catch (_error) {
83
86
  // ignore decode errors (e.g. invalid image data)
84
87
  }
85
88
  finally {
86
- setStatus("loaded");
89
+ setStatus(ImageStatus.Loaded);
87
90
  }
88
91
  }, [onLoad]);
89
92
  const handleError = useCallback((e) => {
90
- if (fallbackSrc && status !== "error") {
93
+ if (fallbackSrc && status !== ImageStatus.Error) {
91
94
  // Prevents infinite loop if fallback also fails
92
95
  if (e.currentTarget.src !== fallbackSrc) {
93
96
  e.currentTarget.src = fallbackSrc;
94
97
  return;
95
98
  }
96
99
  }
97
- setStatus("error");
100
+ setStatus(ImageStatus.Error);
98
101
  setShowSkeleton(false); // Remove skeleton immediately on error
99
102
  onError === null || onError === void 0 ? void 0 : onError(e);
100
103
  }, [fallbackSrc, status, onError]);
101
- return (_jsxs("div", { className: clsx(styles.wrapper, rounded && styles.rounded, className), style: Object.assign({ aspectRatio: computedAspectRatio, width: toCssValue(width), height: toCssValue(height) }, style), children: [_jsx("div", { "aria-hidden": "true", className: clsx(styles.skeletonLayer, status === "loaded" && styles.fadeOut), children: showSkeleton && (_jsx(Skeleton, { style: {
104
+ return (_jsxs("div", { className: clsx(styles.wrapper, rounded && styles.rounded, className), style: Object.assign({ aspectRatio: computedAspectRatio, width: toCssValue(width), height: toCssValue(height) }, style), children: [_jsx("div", { "aria-hidden": "true", className: clsx(styles.skeletonLayer, status === ImageStatus.Loaded && styles.fadeOut), children: showSkeleton && (_jsx(Skeleton, { style: {
102
105
  width: "100%",
103
106
  height: "100%",
104
- } })) }), _jsx("img", Object.assign({ ref: imgRef, alt: alt, className: clsx(styles.image, fit && styles[`fit-${fit}`], status === "loaded" ? styles.visible : styles.hidden), height: height, src: src, width: width, onError: handleError, onLoad: handleLoad }, props))] }));
107
+ } })) }), src && (_jsx("img", Object.assign({ ref: imgRef, alt: alt, className: clsx(styles.image, fit && styles[`fit-${fit}`], status === ImageStatus.Loaded ? styles.visible : styles.hidden), height: height, src: src, width: width, onError: handleError, onLoad: handleLoad }, props)))] }));
105
108
  }
@@ -30,38 +30,56 @@
30
30
  }
31
31
 
32
32
  .modalCard {
33
- background-color: var(--primary);
33
+ background-color: var(--surface-brand);
34
34
  }
35
35
  .modalCard.solid {
36
- /*
37
- SCALABLE CONTEXTUAL REMAPPING
38
- Save original values then swap semantic tokens to auto-invert content.
39
- */
40
- --solid-bg: var(--primary);
41
- --solid-fg: var(--primary-foreground);
42
- --original-border: var(--card-border);
36
+ /* ROOT CONTEXT (The Field) */
43
37
  background-color: var(--solid-bg);
44
38
  color: var(--solid-fg);
45
- /*
46
- Swap Semantics & Remap Content on CHILDREN only.
47
- This avoids circular dependency on the container's background-color.
39
+ /* Root Variables */
40
+ --background: var(--solid-bg);
41
+ --foreground: var(--solid-fg);
42
+ --muted-foreground: color-mix(in srgb, var(--solid-fg) 70%, transparent);
43
+ /*
44
+ * Standardized Brand Surface Logic
45
+ * Decouples Modals (Surface) from Buttons (Action)
48
46
  */
49
- }
50
- .modalCard.solid > * {
47
+ --surface-brand: var(--solid-bg);
48
+ --surface-brand-foreground: var(--solid-fg);
49
+ /* SEMANTICS (True Semantic Colors) */
50
+ --success: var(--solid-success);
51
+ --success-foreground: var(--solid-fg);
52
+ --error: var(--solid-error);
53
+ --error-foreground: var(--solid-fg);
54
+ --warning: var(--solid-warning);
55
+ --warning-foreground: var(--solid-fg);
56
+ /* SURFACE COLORS */
57
+ --on-surface: var(--solid-bg);
58
+ --on-surface-muted: var(--solid-bg);
59
+ /* COMPONENT TOKENS */
60
+ --card-bg: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
61
+ --card-border: var(--solid-fg);
62
+ --card-foreground: var(--solid-fg);
63
+ /* POPOVER TOKENS */
64
+ --popover: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
65
+ --popover-foreground: var(--solid-bg);
66
+ /* INPUT TOKENS */
67
+ --input: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
68
+ --border-strong: var(--solid-fg);
69
+ /* BUTTON TOKENS */
51
70
  --primary: var(--solid-fg);
52
71
  --primary-foreground: var(--solid-bg);
53
- --foreground: var(--solid-fg);
54
- --muted-foreground: var(--solid-fg);
72
+ /* SECONDARY TOKENS */
73
+ --secondary: color-mix(in srgb, var(--solid-bg) 90%, transparent);
74
+ --secondary-foreground: var(--solid-fg);
75
+ /* MUTED TOKENS */
76
+ --muted: color-mix(in srgb, var(--solid-fg) 20%, transparent);
55
77
  }
56
78
  .modalCard.solid .header,
57
79
  .modalCard.solid .body,
58
80
  .modalCard.solid .footer,
59
81
  .modalCard.solid .modalContent {
60
82
  background-color: transparent !important;
61
- color: var(--solid-fg);
62
- }
63
- .modalCard.solid {
64
- /* In solid mode, we need to override the close button to ensure contrast */
65
83
  }
66
84
  .modalCard.solid .closeButton:hover {
67
85
  transform: translate(-2px, -2px);
@@ -76,12 +94,12 @@
76
94
 
77
95
  .header {
78
96
  padding: var(--spacing-lg);
79
- background-color: var(--primary);
80
- color: var(--primary-foreground);
97
+ background-color: var(--surface-brand);
98
+ color: var(--surface-brand-foreground);
81
99
  border-bottom: var(--border-width) solid var(--border-strong);
82
100
  /* Remap foreground variables so children (like Text) use the correct contrast color */
83
- --foreground: var(--primary-foreground);
84
- --muted-foreground: var(--primary-foreground);
101
+ --foreground: var(--surface-brand-foreground);
102
+ --muted-foreground: var(--surface-brand-foreground);
85
103
  }
86
104
 
87
105
  .headerContent {
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import clsx from "clsx";
4
4
  import { X } from "lucide-react";
5
- import React, { useEffect, useState } from "react";
5
+ import React, { useEffect, useRef, useState } from "react";
6
6
  import { createPortal } from "react-dom";
7
7
  import { Button } from "../Button/Button.js";
8
8
  import { Flex } from "../Layout/Layout.js";
@@ -11,6 +11,16 @@ export function Sheet({ isOpen, onClose, title, children, footer, variant = "def
11
11
  const reactId = React.useId();
12
12
  const titleId = `sheet-title-${reactId}`;
13
13
  const [mounted, setMounted] = useState(false);
14
+ const panelRef = useRef(null);
15
+ const isDragging = useRef(false);
16
+ const startY = useRef(0);
17
+ const cleanupRef = useRef(null);
18
+ useEffect(() => {
19
+ if (!isOpen && panelRef.current) {
20
+ panelRef.current.style.transform = "";
21
+ panelRef.current.style.transition = "";
22
+ }
23
+ }, [isOpen]);
14
24
  useEffect(() => {
15
25
  setMounted(true);
16
26
  if (isOpen) {
@@ -23,6 +33,59 @@ export function Sheet({ isOpen, onClose, title, children, footer, variant = "def
23
33
  document.body.style.overflow = "";
24
34
  };
25
35
  }, [isOpen]);
36
+ // Ensure strict cleanup on unmount
37
+ useEffect(() => {
38
+ return () => {
39
+ if (cleanupRef.current) {
40
+ cleanupRef.current();
41
+ cleanupRef.current = null;
42
+ }
43
+ };
44
+ }, []);
45
+ const handlePointerDown = (e) => {
46
+ if (!panelRef.current) {
47
+ return;
48
+ }
49
+ isDragging.current = true;
50
+ startY.current = e.clientY;
51
+ const onMove = (moveEvent) => {
52
+ if (!isDragging.current || !panelRef.current) {
53
+ return;
54
+ }
55
+ const delta = moveEvent.clientY - startY.current;
56
+ if (delta < 0) {
57
+ return;
58
+ }
59
+ panelRef.current.style.transition = "none";
60
+ panelRef.current.style.transform = `translateY(${delta}px)`;
61
+ };
62
+ const onUp = (upEvent) => {
63
+ isDragging.current = false;
64
+ document.removeEventListener("pointermove", onMove);
65
+ document.removeEventListener("pointerup", onUp);
66
+ document.removeEventListener("pointercancel", onUp);
67
+ cleanupRef.current = null;
68
+ if (!panelRef.current) {
69
+ return;
70
+ }
71
+ const delta = upEvent.clientY - startY.current;
72
+ if (delta > 150) {
73
+ onClose();
74
+ }
75
+ else {
76
+ panelRef.current.style.transition = "";
77
+ panelRef.current.style.transform = "";
78
+ }
79
+ };
80
+ document.addEventListener("pointermove", onMove);
81
+ document.addEventListener("pointerup", onUp);
82
+ document.addEventListener("pointercancel", onUp);
83
+ cleanupRef.current = () => {
84
+ document.removeEventListener("pointermove", onMove);
85
+ document.removeEventListener("pointerup", onUp);
86
+ document.removeEventListener("pointercancel", onUp);
87
+ };
88
+ };
26
89
  useEffect(() => {
27
90
  const handleEsc = (e) => {
28
91
  if (e.key === "Escape") {
@@ -37,5 +100,5 @@ export function Sheet({ isOpen, onClose, title, children, footer, variant = "def
37
100
  if (!mounted) {
38
101
  return null;
39
102
  }
40
- return createPortal(_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", className: clsx(styles.overlay, isOpen && styles.isOpen), onClick: onClose }), _jsxs("div", { "aria-label": !title ? "Sheet" : undefined, "aria-labelledby": title ? titleId : undefined, "aria-modal": "true", className: clsx(styles.panel, styles[variant], isOpen && styles.isOpen, className), role: "dialog", children: [_jsxs("div", { className: styles.header, children: [_jsx("div", { className: styles.handleBar }), _jsxs(Flex, { align: "center", className: styles.headerBody, justify: "space-between", children: [title && (_jsx("h2", { className: styles.title, id: titleId, children: title })), _jsx(Button, { "aria-label": "Close sheet", size: "sm", variant: "danger", onClick: onClose, children: _jsx(X, { size: 24 }) })] })] }), _jsx("div", { className: styles.content, children: children }), footer && _jsx("div", { className: styles.footer, children: footer })] })] }), document.body);
103
+ return createPortal(_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", className: clsx(styles.overlay, isOpen && styles.isOpen), onClick: onClose }), _jsxs("div", { ref: panelRef, "aria-label": !title ? "Sheet" : undefined, "aria-labelledby": title ? titleId : undefined, "aria-modal": "true", className: clsx(styles.panel, styles[variant], isOpen && styles.isOpen, className), role: "dialog", children: [_jsxs("div", { className: styles.header, onPointerDown: handlePointerDown, children: [_jsx("div", { className: styles.handleBar }), _jsxs(Flex, { align: "center", className: styles.headerBody, justify: "space-between", children: [title && (_jsx("h2", { className: styles.title, id: titleId, children: title })), _jsx(Button, { "aria-label": "Close sheet", size: "sm", variant: "danger", onClick: onClose, children: _jsx(X, { size: 24 }) })] })] }), _jsx("div", { className: styles.content, children: children }), footer && _jsx("div", { className: styles.footer, children: footer })] })] }), document.body);
41
104
  }
@@ -42,44 +42,69 @@
42
42
  transform: translateY(0);
43
43
  }
44
44
  .panel.solid {
45
- /*
46
- SCALABLE CONTEXTUAL REMAPPING
47
- Save original values then swap semantic tokens to auto-invert content.
48
- */
49
- --solid-bg: var(--primary);
50
- --solid-fg: var(--primary-foreground);
45
+ /* ROOT CONTEXT (The Field) */
51
46
  background-color: var(--solid-bg);
52
47
  color: var(--solid-fg);
53
- /* Swap Semantics & Remap Content on CHILDREN only */
54
- }
55
- .panel.solid > * {
48
+ /* Root Variables */
49
+ --background: var(--solid-bg);
50
+ --foreground: var(--solid-fg);
51
+ --muted-foreground: color-mix(in srgb, var(--solid-fg) 70%, transparent);
52
+ /*
53
+ * Standardized Brand Surface Logic
54
+ * Decouples Modals (Surface) from Buttons (Action)
55
+ */
56
+ --surface-brand: var(--solid-bg);
57
+ --surface-brand-foreground: var(--solid-fg);
58
+ /* SEMANTICS (True Semantic Colors) */
59
+ --success: var(--solid-success);
60
+ --success-foreground: var(--solid-fg);
61
+ --error: var(--solid-error);
62
+ --error-foreground: var(--solid-fg);
63
+ --warning: var(--solid-warning);
64
+ --warning-foreground: var(--solid-fg);
65
+ /* SURFACE COLORS */
66
+ --on-surface: var(--solid-bg);
67
+ --on-surface-muted: var(--solid-bg);
68
+ /* COMPONENT TOKENS */
69
+ --card-bg: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
70
+ --card-border: var(--solid-fg);
71
+ --card-foreground: var(--solid-fg);
72
+ /* POPOVER TOKENS */
73
+ --popover: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
74
+ --popover-foreground: var(--solid-bg);
75
+ /* INPUT TOKENS */
76
+ --input: color-mix(in srgb, var(--solid-fg) 95%, var(--solid-bg) 5%);
77
+ --border-strong: var(--solid-fg);
78
+ /* BUTTON TOKENS */
56
79
  --primary: var(--solid-fg);
57
80
  --primary-foreground: var(--solid-bg);
58
- --foreground: var(--solid-fg);
59
- --muted-foreground: var(--solid-fg);
60
- }
61
- .panel.solid .header {
62
- background-color: transparent !important;
63
- color: var(--solid-fg);
81
+ /* SECONDARY TOKENS */
82
+ --secondary: color-mix(in srgb, var(--solid-bg) 90%, transparent);
83
+ --secondary-foreground: var(--solid-fg);
84
+ /* MUTED TOKENS */
85
+ --muted: color-mix(in srgb, var(--solid-fg) 20%, transparent);
64
86
  }
65
87
  .panel.solid .handleBar {
66
88
  background-color: var(--solid-fg);
67
89
  opacity: 0.8;
68
90
  }
69
- .panel.solid .content {
70
- background-color: transparent !important;
71
- }
91
+ .panel.solid .content,
72
92
  .panel.solid .footer {
73
93
  background-color: transparent !important;
74
94
  }
75
95
 
76
96
  .header {
77
- background-color: var(--primary);
78
- color: var(--primary-foreground);
97
+ background-color: var(--surface-brand);
98
+ color: var(--surface-brand-foreground);
79
99
  border-bottom: var(--border-width) solid var(--border-strong);
80
100
  display: flex;
81
101
  flex-direction: column;
82
102
  flex-shrink: 0;
103
+ touch-action: none;
104
+ cursor: grab;
105
+ }
106
+ .header:active {
107
+ cursor: grabbing;
83
108
  }
84
109
 
85
110
  .handleBar {
@@ -7,7 +7,7 @@
7
7
  }
8
8
  }
9
9
  .skeleton {
10
- background: linear-gradient(90deg, rgba(0, 0, 0, 0.06) 25%, rgba(0, 0, 0, 0.12) 37%, rgba(0, 0, 0, 0.06) 63%);
10
+ background: linear-gradient(90deg, color-mix(in srgb, var(--foreground), transparent 90%) 25%, color-mix(in srgb, var(--foreground), transparent 80%) 37%, color-mix(in srgb, var(--foreground), transparent 90%) 63%);
11
11
  background-size: 200% 100%;
12
12
  animation: shimmer 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
13
13
  width: var(--width, 100%);
@@ -4,7 +4,6 @@ import { createContext, useContext, useEffect, useState } from "react";
4
4
  import { themes } from "./definitions.js";
5
5
  const ThemeContext = createContext(undefined);
6
6
  export function ThemeProvider({ children, initialTheme, onThemeChange, }) {
7
- var _a;
8
7
  const [currentTheme, setCurrentTheme] = useState(initialTheme);
9
8
  useEffect(() => {
10
9
  setCurrentTheme(initialTheme);
@@ -14,9 +13,12 @@ export function ThemeProvider({ children, initialTheme, onThemeChange, }) {
14
13
  onThemeChange === null || onThemeChange === void 0 ? void 0 : onThemeChange(newTheme);
15
14
  };
16
15
  // Get the variables for the current theme
17
- const themeVars = ((_a = themes[currentTheme]) === null || _a === void 0 ? void 0 : _a.variables) || themes.default.variables;
18
- // Generate CSS variables string
19
- const cssVariables = Object.entries(themeVars)
16
+ const themeConfig = themes[currentTheme] || themes.default;
17
+ const themeVars = themeConfig.variables;
18
+ const solidVars = themeConfig.solid || {};
19
+ // Generate CSS variables string (includes both theme and solid tokens)
20
+ const allVars = Object.assign(Object.assign({}, themeVars), solidVars);
21
+ const cssVariables = Object.entries(allVars)
20
22
  .map(([key, value]) => `${key}: ${value};`)
21
23
  .join("\n");
22
24
  return (_jsxs(ThemeContext.Provider, { value: {
@@ -16,6 +16,8 @@ export declare const themes: {
16
16
  readonly "--on-surface-muted": "#374151";
17
17
  readonly "--primary": "#a855f7";
18
18
  readonly "--primary-foreground": "#000000";
19
+ readonly "--surface-brand": "#a855f7";
20
+ readonly "--surface-brand-foreground": "#000000";
19
21
  readonly "--primary-hover": "#9333ea";
20
22
  readonly "--secondary": "#fbbf24";
21
23
  readonly "--secondary-foreground": "#000000";
@@ -90,6 +92,13 @@ export declare const themes: {
90
92
  readonly "--shadow-sm-checked-hover": string;
91
93
  readonly "--shadow-lg": string;
92
94
  };
95
+ readonly solid: {
96
+ "--solid-bg": string;
97
+ "--solid-fg": string;
98
+ "--solid-success": string;
99
+ "--solid-error": string;
100
+ "--solid-warning": string;
101
+ };
93
102
  };
94
103
  readonly doom: {
95
104
  readonly name: "DOOMSDAY";
@@ -108,6 +117,8 @@ export declare const themes: {
108
117
  readonly "--on-surface-muted": "#94a3b8";
109
118
  readonly "--primary": "#10b981";
110
119
  readonly "--primary-foreground": "#020617";
120
+ readonly "--surface-brand": "#10b981";
121
+ readonly "--surface-brand-foreground": "#020617";
111
122
  readonly "--primary-hover": "#059669";
112
123
  readonly "--secondary": "#475569";
113
124
  readonly "--secondary-foreground": "#F8FAFC";
@@ -182,6 +193,13 @@ export declare const themes: {
182
193
  readonly "--shadow-sm-checked-hover": string;
183
194
  readonly "--shadow-lg": string;
184
195
  };
196
+ readonly solid: {
197
+ "--solid-bg": string;
198
+ "--solid-fg": string;
199
+ "--solid-success": string;
200
+ "--solid-error": string;
201
+ "--solid-warning": string;
202
+ };
185
203
  };
186
204
  readonly captain: {
187
205
  readonly name: "THE CAPTAIN";
@@ -198,16 +216,18 @@ export declare const themes: {
198
216
  readonly "--muted-foreground": "#475569";
199
217
  readonly "--on-surface": "#0f172a";
200
218
  readonly "--on-surface-muted": "#475569";
201
- readonly "--primary": "#2563eb";
202
- readonly "--primary-foreground": "#ffffff";
203
- readonly "--primary-hover": "#1d4ed8";
219
+ readonly "--primary": "#3B82F6";
220
+ readonly "--primary-foreground": "#000000";
221
+ readonly "--surface-brand": "#3B82F6";
222
+ readonly "--surface-brand-foreground": "#000000";
223
+ readonly "--primary-hover": "#2563eb";
204
224
  readonly "--secondary": "#64748b";
205
225
  readonly "--secondary-foreground": "#ffffff";
206
226
  readonly "--shadow-base": "#000000";
207
227
  readonly "--shadow-error": "#7f1d1d";
208
- readonly "--shadow-primary": "#1e3a8a";
228
+ readonly "--shadow-primary": "#1e40af";
209
229
  readonly "--success": "#10b981";
210
- readonly "--success-foreground": "#ffffff";
230
+ readonly "--success-foreground": "#000000";
211
231
  readonly "--surface-accent": "#f1f5f9";
212
232
  readonly "--warning": "#F7B731";
213
233
  readonly "--warning-foreground": "#0F1419";
@@ -274,6 +294,13 @@ export declare const themes: {
274
294
  readonly "--shadow-sm-checked-hover": string;
275
295
  readonly "--shadow-lg": string;
276
296
  };
297
+ readonly solid: {
298
+ "--solid-bg": string;
299
+ "--solid-fg": string;
300
+ "--solid-success": string;
301
+ "--solid-error": string;
302
+ "--solid-warning": string;
303
+ };
277
304
  };
278
305
  readonly vigilante: {
279
306
  readonly name: "DARK KNIGHT";
@@ -292,6 +319,8 @@ export declare const themes: {
292
319
  readonly "--on-surface-muted": "#9ca3af";
293
320
  readonly "--primary": "#F7B731";
294
321
  readonly "--primary-foreground": "#0F1419";
322
+ readonly "--surface-brand": "#F7B731";
323
+ readonly "--surface-brand-foreground": "#0F1419";
295
324
  readonly "--primary-hover": "#F5A623";
296
325
  readonly "--secondary": "#4b5563";
297
326
  readonly "--secondary-foreground": "#E8E9ED";
@@ -366,6 +395,13 @@ export declare const themes: {
366
395
  readonly "--shadow-sm-checked-hover": string;
367
396
  readonly "--shadow-lg": string;
368
397
  };
398
+ readonly solid: {
399
+ "--solid-bg": string;
400
+ "--solid-fg": string;
401
+ "--solid-success": string;
402
+ "--solid-error": string;
403
+ "--solid-warning": string;
404
+ };
369
405
  };
370
406
  };
371
407
  export type ThemeKey = keyof typeof themes;