cynx-ui 1.3.20 → 1.3.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
- import { useState, useRef, useEffect, useCallback } from 'react';
1
+ import { useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
2
+ import { createPortal } from 'react-dom';
2
3
 
3
4
  export function ActionsMenu({ items, align = 'right' }) {
4
5
  const [open, setOpen] = useState(false);
@@ -12,23 +13,7 @@ export function ActionsMenu({ items, align = 'right' }) {
12
13
  setTimeout(() => { setClosing(false); setOpen(false); }, 140);
13
14
  }, []);
14
15
 
15
- useEffect(() => {
16
- if (!open) return;
17
- function onDocClick(e) {
18
- if (wrapRef.current && !wrapRef.current.contains(e.target)) close();
19
- }
20
- function onScroll() { if (menuRef.current) positionMenu(); }
21
- document.addEventListener('mousedown', onDocClick);
22
- document.addEventListener('scroll', onScroll, true);
23
- window.addEventListener('resize', onScroll);
24
- return () => {
25
- document.removeEventListener('mousedown', onDocClick);
26
- document.removeEventListener('scroll', onScroll, true);
27
- window.removeEventListener('resize', onScroll);
28
- };
29
- }, [open, close]);
30
-
31
- function positionMenu() {
16
+ const positionMenu = useCallback(() => {
32
17
  const btn = btnRef.current;
33
18
  const menu = menuRef.current;
34
19
  if (!btn || !menu) return;
@@ -41,25 +26,48 @@ export function ActionsMenu({ items, align = 'right' }) {
41
26
 
42
27
  let top, left;
43
28
  if (openUp) {
44
- top = br.top + window.scrollY - mh - 6;
29
+ top = br.top - mh - 6;
45
30
  } else {
46
- top = br.bottom + window.scrollY + 6;
31
+ top = br.bottom + 6;
47
32
  }
48
33
  if (align === 'left') {
49
- left = br.left + window.scrollX;
34
+ left = br.left;
50
35
  } else {
51
- left = br.right + window.scrollX - mw;
36
+ left = br.right - mw;
52
37
  }
53
38
  left = Math.max(8, Math.min(left, window.innerWidth - mw - 8));
54
39
 
55
40
  menu.style.top = top + 'px';
56
41
  menu.style.left = left + 'px';
57
42
  menu.classList.toggle('open-up', openUp);
58
- }
43
+ }, [align]);
59
44
 
60
45
  useEffect(() => {
61
- if (open) requestAnimationFrame(positionMenu);
62
- }, [open]);
46
+ if (!open) return;
47
+ function onDocClick(e) {
48
+ if (
49
+ wrapRef.current && !wrapRef.current.contains(e.target) &&
50
+ menuRef.current && !menuRef.current.contains(e.target)
51
+ ) {
52
+ close();
53
+ }
54
+ }
55
+ function onScroll() { positionMenu(); }
56
+ document.addEventListener('mousedown', onDocClick);
57
+ document.addEventListener('scroll', onScroll, true);
58
+ window.addEventListener('resize', onScroll);
59
+ return () => {
60
+ document.removeEventListener('mousedown', onDocClick);
61
+ document.removeEventListener('scroll', onScroll, true);
62
+ window.removeEventListener('resize', onScroll);
63
+ };
64
+ }, [open, close, positionMenu]);
65
+
66
+ useLayoutEffect(() => {
67
+ if (open) {
68
+ positionMenu();
69
+ }
70
+ }, [open, positionMenu]);
63
71
 
64
72
  function toggle() {
65
73
  if (open) close();
@@ -79,7 +87,7 @@ export function ActionsMenu({ items, align = 'right' }) {
79
87
  border: isOpen ? '1px solid var(--accent,#f99e2c)' : '1px solid var(--border-light,#d7d8e0)',
80
88
  background: 'var(--surface,#fff)',
81
89
  cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
82
- color: isOpen ? 'var(--accent)' : 'var(--muted,#797b8d)', transition: 'all .14s',
90
+ color: isOpen ? 'var(--accent, #f99e2c)' : 'var(--muted,#797b8d)', transition: 'all .14s',
83
91
  boxShadow: isOpen ? 'var(--pd, rgba(249,158,44,.12))' : 'var(--shadow, 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06))',
84
92
  }}
85
93
  >
@@ -88,11 +96,11 @@ export function ActionsMenu({ items, align = 'right' }) {
88
96
  </svg>
89
97
  </button>
90
98
 
91
- {open && (
99
+ {open && typeof document !== 'undefined' && createPortal(
92
100
  <div
93
101
  ref={menuRef}
94
102
  style={{
95
- position: 'fixed', zIndex: 8100, minWidth: 180, padding: 5,
103
+ position: 'fixed', zIndex: 99999, minWidth: 180, padding: 5,
96
104
  background: 'var(--surface,#fff)', border: '1.5px solid var(--border-light,#e2e8f0)',
97
105
  borderRadius: 'var(--rads,8px)',
98
106
  boxShadow: 'var(--shadow-lg, 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.06))',
@@ -112,7 +120,7 @@ export function ActionsMenu({ items, align = 'right' }) {
112
120
  display: 'flex', alignItems: 'center', gap: 8,
113
121
  padding: '6px 10px', borderRadius: 'var(--rads,8px)',
114
122
  fontSize: 12, cursor: 'pointer', transition: 'all .14s',
115
- color: item.variant === 'danger' ? 'var(--danger)' : item.variant === 'success' ? 'var(--success)' : item.variant === 'warning' ? 'var(--accent)' : 'var(--text,#1a1a2e)',
123
+ color: item.variant === 'danger' ? 'var(--danger, #f64747)' : item.variant === 'success' ? 'var(--success, #27ae60)' : item.variant === 'warning' ? 'var(--accent, #f99e2c)' : 'var(--text,#1a1a2e)',
116
124
  fontWeight: 500,
117
125
  }}
118
126
  onMouseEnter={e => {
@@ -131,7 +139,8 @@ export function ActionsMenu({ items, align = 'right' }) {
131
139
  </div>
132
140
  )
133
141
  ))}
134
- </div>
142
+ </div>,
143
+ document.body
135
144
  )}
136
145
 
137
146
  <style>{`
@@ -6,7 +6,7 @@ function LegendDot({ color, label }) {
6
6
  return (
7
7
  <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
8
8
  <span style={{ width: 7, height: 7, borderRadius: 2, background: color, flexShrink: 0 }} />
9
- <span style={{ fontSize: '.55rem', color: 'var(--muted)', fontWeight: 500 }}>{label}</span>
9
+ <span style={{ fontSize: '.55rem', color: 'var(--muted, #797b8d)', fontWeight: 500 }}>{label}</span>
10
10
  </div>
11
11
  );
12
12
  }
@@ -20,9 +20,9 @@ export default function ActivityCard({
20
20
  primary = [],
21
21
  additional = [],
22
22
  totalSlots = 90,
23
- greenColor = 'var(--success)',
24
- redColor = 'var(--danger)',
25
- emptyColor = 'var(--grey-1)',
23
+ greenColor = 'var(--success, #27ae60)',
24
+ redColor = 'var(--danger, #f64747)',
25
+ emptyColor = 'var(--grey-1, #f5f5f8)',
26
26
  barHeight = 28,
27
27
  barRadius = 3,
28
28
  leftLabel,
@@ -79,7 +79,7 @@ export default function ActivityCard({
79
79
 
80
80
  return (
81
81
  <div ref={containerRef} style={{
82
- background: 'var(--surface,#fff)', border: '1px solid var(--border)', borderRadius: 'var(--rad)',
82
+ background: 'var(--surface,#fff)', border: '1px solid var(--border, #e2e8f0)', borderRadius: 'var(--rad, 10px)',
83
83
  boxShadow: 'var(--shadow, 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04))',
84
84
  padding: '14px 18px', position: 'relative', ...style,
85
85
  }}>
@@ -89,8 +89,8 @@ export default function ActivityCard({
89
89
  {showDot && (
90
90
  <span style={{ width: 8, height: 8, borderRadius: '50%', background: dotColor || greenColor, flexShrink: 0 }} />
91
91
  )}
92
- <span style={{ fontSize: '.78rem', fontWeight: 700, color: 'var(--primary-text)', letterSpacing: '-.01em' }}>{title}</span>
93
- {subtitle && <span style={{ fontSize: '.65rem', color: 'var(--muted)', fontWeight: 500 }}>{subtitle}</span>}
92
+ <span style={{ fontSize: '.78rem', fontWeight: 700, color: 'var(--primary-text, #0f172a)', letterSpacing: '-.01em' }}>{title}</span>
93
+ {subtitle && <span style={{ fontSize: '.65rem', color: 'var(--muted, #797b8d)', fontWeight: 500 }}>{subtitle}</span>}
94
94
  </div>
95
95
  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
96
96
  <LegendDot color={greenColor} label="Success" />
@@ -135,43 +135,43 @@ export default function ActivityCard({
135
135
  <div style={{
136
136
  position: 'absolute', left: tooltipPos.x, top: tooltipPos.y,
137
137
  transform: 'translate(-50%, -100%)', background: 'var(--surface,#fff)',
138
- border: '1px solid var(--border)', borderRadius: 'var(--rads, 8px)',
138
+ border: '1px solid var(--border, #e2e8f0)', borderRadius: 'var(--rads, 8px)',
139
139
  boxShadow: 'var(--smd, 0 4px 12px rgba(0,0,0,.12))', padding: '10px 14px',
140
140
  pointerEvents: 'none', zIndex: 100, whiteSpace: 'nowrap',
141
141
  animation: 'hoverCardIn .15s ease',
142
142
  }}>
143
- <div style={{ fontSize: '.65rem', color: 'var(--muted)', fontWeight: 500, marginBottom: 4 }}>
143
+ <div style={{ fontSize: '.65rem', color: 'var(--muted, #797b8d)', fontWeight: 500, marginBottom: 4 }}>
144
144
  {dates[hovered]?.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
145
145
  </div>
146
146
  {h.success > 0 && (
147
147
  <div style={{ fontSize: '.7rem', fontWeight: 700, color: greenColor }}>
148
148
  {h.success} success{h.success !== 1 ? 'es' : ''}
149
- {h.failed > 0 && <span style={{ fontWeight: 500, color: 'var(--muted)' }}> ({Math.round((h.success / hTotal) * 100)}%)</span>}
149
+ {h.failed > 0 && <span style={{ fontWeight: 500, color: 'var(--muted, #797b8d)' }}> ({Math.round((h.success / hTotal) * 100)}%)</span>}
150
150
  </div>
151
151
  )}
152
152
  {h.failed > 0 && (
153
153
  <div style={{ fontSize: '.7rem', fontWeight: 700, color: redColor }}>
154
154
  {h.failed} failed{h.failed !== 1 ? 's' : ''}
155
- {h.success > 0 && <span style={{ fontWeight: 500, color: 'var(--muted)' }}> ({Math.round((h.failed / hTotal) * 100)}%)</span>}
155
+ {h.success > 0 && <span style={{ fontWeight: 500, color: 'var(--muted, #797b8d)' }}> ({Math.round((h.failed / hTotal) * 100)}%)</span>}
156
156
  </div>
157
157
  )}
158
158
  {!h.success && !h.failed && (
159
- <div style={{ fontSize: '.7rem', fontWeight: 500, color: 'var(--muted)' }}>No activity</div>
159
+ <div style={{ fontSize: '.7rem', fontWeight: 500, color: 'var(--muted, #797b8d)' }}>No activity</div>
160
160
  )}
161
161
  <div style={{
162
162
  position: 'absolute', left: '50%', bottom: -5,
163
163
  transform: 'translateX(-50%) rotate(45deg)',
164
164
  width: 8, height: 8, background: 'var(--surface,#fff)',
165
- borderRight: '1px solid var(--border)', borderBottom: '1px solid var(--border)',
165
+ borderRight: '1px solid var(--border, #e2e8f0)', borderBottom: '1px solid var(--border, #e2e8f0)',
166
166
  }} />
167
167
  </div>
168
168
  )}
169
169
 
170
170
  {/* Footer */}
171
171
  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
172
- <span style={{ fontSize: '.58rem', color: 'var(--muted)', fontWeight: 500 }}>{leftLabel || ''}</span>
173
- <span style={{ fontSize: '.78rem', fontWeight: 700, color: greenColor, fontFamily: 'var(--mono)' }}>{uptimePercent}%</span>
174
- <span style={{ fontSize: '.58rem', color: 'var(--muted)', fontWeight: 500 }}>{rightLabel || ''}</span>
172
+ <span style={{ fontSize: '.58rem', color: 'var(--muted, #797b8d)', fontWeight: 500 }}>{leftLabel || ''}</span>
173
+ <span style={{ fontSize: '.78rem', fontWeight: 700, color: greenColor, fontFamily: 'var(--mono, ui-monospace, monospace)' }}>{uptimePercent}%</span>
174
+ <span style={{ fontSize: '.58rem', color: 'var(--muted, #797b8d)', fontWeight: 500 }}>{rightLabel || ''}</span>
175
175
  </div>
176
176
  <style>{`
177
177
  @keyframes hoverCardIn {
@@ -59,7 +59,7 @@ export default function AuthOverlay({ status, onDone }) {
59
59
  flexDirection: 'column',
60
60
  alignItems: 'center',
61
61
  justifyContent: 'center',
62
- background: 'var(--surface)',
62
+ background: 'var(--surface, #ffffff)',
63
63
  borderRadius: 'inherit',
64
64
  opacity: closing ? 0 : 1,
65
65
  transition: `opacity ${FADE}ms ease`,
@@ -79,8 +79,8 @@ export default function AuthOverlay({ status, onDone }) {
79
79
  <svg width={38} height={38} viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" style={{ animation: 'spin .7s linear infinite' }}>
80
80
  <g fill="none" fillRule="evenodd">
81
81
  <g transform="translate(1 1)" strokeWidth="2.5">
82
- <circle strokeOpacity=".2" cx="18" cy="18" r="18" stroke="var(--accent)" />
83
- <path d="M36 18c0-9.94-8.06-18-18-18" stroke="var(--accent)" strokeLinecap="round" />
82
+ <circle strokeOpacity=".2" cx="18" cy="18" r="18" stroke="var(--accent, #f99e2c)" />
83
+ <path d="M36 18c0-9.94-8.06-18-18-18" stroke="var(--accent, #f99e2c)" strokeLinecap="round" />
84
84
  </g>
85
85
  </g>
86
86
  </svg>
@@ -56,8 +56,8 @@ export function BrandingCard({ label, hint, value, onUpload, onRemove, saving, o
56
56
  <div style={{
57
57
  display: 'flex', alignItems: 'center', justifyContent: 'space-between',
58
58
  gap: 10,
59
- padding: '10px 12px', borderRadius: 'var(--rads)',
60
- border: '1px solid var(--border-light)', background: 'var(--surface)',
59
+ padding: '10px 12px', borderRadius: 'var(--rads, 8px)',
60
+ border: '1px solid var(--border-light, #ebebf0)', background: 'var(--surface, #ffffff)',
61
61
  boxShadow: 'var(--shadow, 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06))',
62
62
  ...cardStyle,
63
63
  }}>
@@ -65,26 +65,26 @@ export function BrandingCard({ label, hint, value, onUpload, onRemove, saving, o
65
65
  <img src={previewUrl} alt={label} onClick={() => fullview && setPreviewOpen(true)}
66
66
  style={{ height: fullview ? 24 : 32, width: fullview ? 'auto' : 32, objectFit: 'contain', borderRadius: 4, flexShrink: 0, cursor: fullview ? 'pointer' : 'default' }} />
67
67
  ) : (
68
- <div style={{ width: fullview ? 24 : 32, height: fullview ? 24 : 32, borderRadius: 4, background: 'var(--grey-2)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
69
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--muted)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
68
+ <div style={{ width: fullview ? 24 : 32, height: fullview ? 24 : 32, borderRadius: 4, background: 'var(--grey-2, #ebebee)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
69
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--muted, #797b8d)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
70
70
  <rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/>
71
71
  </svg>
72
72
  </div>
73
73
  )}
74
74
  {!fullview && (
75
- <div style={{ flex: 1, minWidth: 0, fontSize: '.78rem', color: filename ? 'var(--primary-text)' : 'var(--muted)', fontFamily: filename ? 'var(--mono)' : 'inherit', wordBreak: 'break-all', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
75
+ <div style={{ flex: 1, minWidth: 0, fontSize: '.78rem', color: filename ? 'var(--primary-text, #0f172a)' : 'var(--muted, #797b8d)', fontFamily: filename ? 'var(--mono, ui-monospace, monospace)' : 'inherit', wordBreak: 'break-all', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
76
76
  {filename || 'Not set'}
77
77
  </div>
78
78
  )}
79
79
  <div style={{ display: 'flex', gap: 4, flexShrink: 0 }}>
80
80
  <Button variant="ghost" size="xs" type="button" icon={<Pencil size={11} />} onClick={() => setEditOpen(true)} style={cardStyle ? { background: 'var(--surface,#fff)', color: 'var(--t, #333)' } : undefined}>Edit</Button>
81
81
  {hasExisting && (
82
- <Button variant="ghost" size="xs" type="button" icon={<Trash2 size={11} />} style={cardStyle ? { background: 'var(--surface,#fff)', color: 'var(--danger)' } : { color: 'var(--danger)' }}
82
+ <Button variant="ghost" size="xs" type="button" icon={<Trash2 size={11} />} style={cardStyle ? { background: 'var(--surface,#fff)', color: 'var(--danger, #f64747)' } : { color: 'var(--danger, #f64747)' }}
83
83
  onClick={handleRemove} disabled={saving}>Remove</Button>
84
84
  )}
85
85
  </div>
86
86
  </div>
87
- <div style={{ fontSize: '.68rem', color: 'var(--muted)', marginTop: 4 }}>{hint}</div>
87
+ <div style={{ fontSize: '.68rem', color: 'var(--muted, #797b8d)', marginTop: 4 }}>{hint}</div>
88
88
 
89
89
  {previewOpen && (
90
90
  <Modal title={label} open={previewOpen} onClose={() => setPreviewOpen(false)}
@@ -106,35 +106,35 @@ export function BrandingCard({ label, hint, value, onUpload, onRemove, saving, o
106
106
  </>
107
107
  }>
108
108
  <label
109
- onDragOver={e => { e.preventDefault(); e.currentTarget.style.borderColor = 'var(--accent)'; }}
110
- onDragLeave={e => { e.currentTarget.style.borderColor = pendingFile ? 'var(--accent)' : 'var(--border)'; }}
109
+ onDragOver={e => { e.preventDefault(); e.currentTarget.style.borderColor = 'var(--accent, #f99e2c)'; }}
110
+ onDragLeave={e => { e.currentTarget.style.borderColor = pendingFile ? 'var(--accent, #f99e2c)' : 'var(--border, #e2e8f0)'; }}
111
111
  onDrop={e => { e.preventDefault(); const f = e.dataTransfer.files[0]; if (f) handleFileDrop(f); }}
112
112
  style={{
113
113
  display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
114
- gap: 8, padding: '24px 16px', borderRadius: 'var(--rads)',
115
- border: `1.5px dashed ${pendingFile ? 'var(--accent)' : 'var(--border)'}`,
116
- background: 'var(--grey-1)', cursor: 'pointer', transition: 'all .15s', textAlign: 'center',
114
+ gap: 8, padding: '24px 16px', borderRadius: 'var(--rads, 8px)',
115
+ border: `1.5px dashed ${pendingFile ? 'var(--accent, #f99e2c)' : 'var(--border, #e2e8f0)'}`,
116
+ background: 'var(--grey-1, #f5f5f8)', cursor: 'pointer', transition: 'all .15s', textAlign: 'center',
117
117
  }}>
118
118
  <input type="file" accept="image/*,.ico" style={{ display: 'none' }}
119
119
  onChange={e => { const f = e.target.files[0]; if (f) handleFileDrop(f); }} />
120
120
  {pendingFile ? (
121
121
  <>
122
122
  <img src={URL.createObjectURL(pendingFile)} alt="preview" style={{ height: 48, maxWidth: 160, objectFit: 'contain', borderRadius: 4 }} />
123
- <div style={{ fontSize: '.76rem', fontWeight: 600, color: 'var(--accent)' }}>{pendingFile.name}</div>
124
- <div style={{ fontSize: '.68rem', color: 'var(--muted)' }}>{(pendingFile.size / 1024).toFixed(1)} KB — click to change</div>
123
+ <div style={{ fontSize: '.76rem', fontWeight: 600, color: 'var(--accent, #f99e2c)' }}>{pendingFile.name}</div>
124
+ <div style={{ fontSize: '.68rem', color: 'var(--muted, #797b8d)' }}>{(pendingFile.size / 1024).toFixed(1)} KB — click to change</div>
125
125
  </>
126
126
  ) : (
127
127
  <>
128
- <Upload size={20} style={{ color: 'var(--muted)' }} />
128
+ <Upload size={20} style={{ color: 'var(--muted, #797b8d)' }} />
129
129
  <div style={{ fontSize: '.82rem', fontWeight: 600 }}>Click or drag to upload</div>
130
- <div style={{ fontSize: '.72rem', color: 'var(--muted)' }}>PNG, JPG, SVG, ICO up to 2MB</div>
130
+ <div style={{ fontSize: '.72rem', color: 'var(--muted, #797b8d)' }}>PNG, JPG, SVG, ICO up to 2MB</div>
131
131
  </>
132
132
  )}
133
133
  </label>
134
134
  <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '12px 0 4px' }}>
135
- <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
136
- <span style={{ fontSize: '.72rem', color: 'var(--muted)' }}>or enter URL directly</span>
137
- <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
135
+ <div style={{ flex: 1, height: 1, background: 'var(--border, #e2e8f0)' }} />
136
+ <span style={{ fontSize: '.72rem', color: 'var(--muted, #797b8d)' }}>or enter URL directly</span>
137
+ <div style={{ flex: 1, height: 1, background: 'var(--border, #e2e8f0)' }} />
138
138
  </div>
139
139
  <Input type="url" placeholder="https://example.com/logo.png" value={pendingUrl}
140
140
  onChange={e => { setPendingUrl(e.target.value); setPendingFile(null); }}
@@ -27,9 +27,9 @@ export default function Checkbox({ checked, indeterminate, onChange, disabled =
27
27
  }}>
28
28
  <span style={{
29
29
  position: 'relative', width: dims.w, height: dims.h, flexShrink: 0,
30
- border: `1.5px solid ${checked || indeterminate ? 'var(--accent)' : 'var(--border)'}`,
30
+ border: `1.5px solid ${checked || indeterminate ? 'var(--accent, #f99e2c)' : 'var(--border, #e2e8f0)'}`,
31
31
  borderRadius: size === 'sm' ? 3 : 4,
32
- background: checked || indeterminate ? 'var(--accent)' : 'var(--input-bg)',
32
+ background: checked || indeterminate ? 'var(--accent, #f99e2c)' : 'var(--input-bg, #ffffff)',
33
33
  transition: 'all .14s',
34
34
  cursor: disabled ? 'not-allowed' : 'pointer',
35
35
  }}>
@@ -27,15 +27,15 @@ export default function ChipSelect({ options, value = [], onChange, size = 'md'
27
27
  display:'flex', alignItems:'center', gap: dims.gap,
28
28
  padding:`${dims.py}px ${dims.px}px`, cursor:'pointer',
29
29
  borderRadius: 8,
30
- background: 'var(--grey-1)',
30
+ background: 'var(--grey-1, #f5f5f8)',
31
31
  transition: 'all .14s',
32
32
  userSelect: 'none',
33
33
  }}>
34
34
  <span style={{
35
35
  position:'relative', width: dims.h, height: dims.h, flexShrink:0,
36
36
  borderRadius: 4,
37
- background: active ? 'var(--accent)' : 'var(--input-bg)',
38
- border: `1.5px solid ${active ? 'var(--accent)' : 'var(--border)'}`,
37
+ background: active ? 'var(--accent, #f99e2c)' : 'var(--input-bg, #ffffff)',
38
+ border: `1.5px solid ${active ? 'var(--accent, #f99e2c)' : 'var(--border, #e2e8f0)'}`,
39
39
  transition: 'all .14s',
40
40
  display:'flex', alignItems:'center', justifyContent:'center',
41
41
  }}>
@@ -45,7 +45,7 @@ export default function ChipSelect({ options, value = [], onChange, size = 'md'
45
45
  </svg>
46
46
  )}
47
47
  </span>
48
- <span style={{ fontSize: dims.font, fontWeight:600, textTransform:'uppercase', letterSpacing:'.04em', color: 'var(--muted)' }}>{opt.label}</span>
48
+ <span style={{ fontSize: dims.font, fontWeight:600, textTransform:'uppercase', letterSpacing:'.04em', color: 'var(--muted, #797b8d)' }}>{opt.label}</span>
49
49
  </div>
50
50
  );
51
51
  })}
@@ -13,7 +13,7 @@ export default function CircularProgress({
13
13
  segments,
14
14
  size = 'md',
15
15
  customSize,
16
- color = 'var(--blue)',
16
+ color = 'var(--blue, #2782e4)',
17
17
  trackColor = 'var(--bd2, #e0e0e4)',
18
18
  label = '',
19
19
  centerText,
@@ -201,7 +201,7 @@ export default function CircularProgress({
201
201
  <div style={{
202
202
  position: 'absolute', inset: 0,
203
203
  display: 'flex', alignItems: 'center', justifyContent: 'center',
204
- fontSize, fontWeight: 600, color: 'var(--primary-text)',
204
+ fontSize, fontWeight: 600, color: 'var(--primary-text, #0f172a)',
205
205
  fontVariantNumeric: 'tabular-nums',
206
206
  }}>
207
207
  {centerText !== undefined ? centerText : hasSegments ? rawSum : `${Math.round(pct)}%`}
@@ -209,7 +209,7 @@ export default function CircularProgress({
209
209
  )}
210
210
  </div>
211
211
  {label && (
212
- <span style={{ fontSize: '.6rem', color: 'var(--muted)', fontWeight: 500 }}>{label}</span>
212
+ <span style={{ fontSize: '.6rem', color: 'var(--muted, #797b8d)', fontWeight: 500 }}>{label}</span>
213
213
  )}
214
214
  </div>
215
215
  );
@@ -35,7 +35,7 @@ export function ConfirmRoot() {
35
35
  onClick={e => e.target === e.currentTarget && answer(false)}
36
36
  >
37
37
  <div style={{
38
- background: 'var(--surface)', border: '1px solid var(--border)',
38
+ background: 'var(--surface, #ffffff)', border: '1px solid var(--border, #e2e8f0)',
39
39
  borderRadius: 14, width: '100%', maxWidth: 400,
40
40
  boxShadow: 'var(--slg, 0 20px 60px rgba(0,0,0,.4))',
41
41
  animation: `${closing ? 'modalClose' : 'modalPop'} .25s cubic-bezier(.4,0,.2,1) forwards`,
@@ -46,13 +46,13 @@ export function ConfirmRoot() {
46
46
  background: state.danger ? 'var(--dd, rgba(246,71,71,.1))' : 'var(--pd, rgba(249,158,44,.1))',
47
47
  display: 'flex', alignItems: 'center', justifyContent: 'center',
48
48
  }}>
49
- <AlertTriangle size={17} color={state.danger ? 'var(--danger)' : 'var(--warning)'} />
49
+ <AlertTriangle size={17} color={state.danger ? 'var(--danger, #f64747)' : 'var(--warning, #f59e0b)'} />
50
50
  </div>
51
51
  <div>
52
52
  <div style={{ fontWeight: 700, fontSize: '.9rem', marginBottom: 6 }}>
53
53
  {state.title || 'Are you sure?'}
54
54
  </div>
55
- <div style={{ fontSize: '.8rem', color: 'var(--muted)', lineHeight: 1.6 }}>
55
+ <div style={{ fontSize: '.8rem', color: 'var(--muted, #797b8d)', lineHeight: 1.6 }}>
56
56
  {state.message}
57
57
  </div>
58
58
  </div>
@@ -60,11 +60,11 @@ export function ConfirmRoot() {
60
60
  <div style={{
61
61
  display: 'flex', justifyContent: 'flex-end', gap: 8,
62
62
  padding: '16px 20px', marginTop: 18,
63
- borderTop: '1px solid var(--border-light)',
64
- background: 'var(--grey-1)', borderRadius: '0 0 14px 14px',
63
+ borderTop: '1px solid var(--border-light, #ebebf0)',
64
+ background: 'var(--grey-1, #f5f5f8)', borderRadius: '0 0 14px 14px',
65
65
  }}>
66
66
  <Button variant="ghost" size="sm" onClick={() => answer(false)}>Cancel</Button>
67
- <Button variant={state.danger ? 'ghost' : 'primary'} size="sm" style={state.danger ? { background: 'var(--danger)', color: 'var(--def-btn-text,#fff)', border: 'none' } : {}} onClick={() => answer(true)}>
67
+ <Button variant={state.danger ? 'ghost' : 'primary'} size="sm" style={state.danger ? { background: 'var(--danger, #f64747)', color: 'var(--def-btn-text,#fff)', border: 'none' } : {}} onClick={() => answer(true)}>
68
68
  {state.confirmLabel || 'Confirm'}
69
69
  </Button>
70
70
  </div>