cynx-ui 1.3.19 → 1.3.21
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.
- package/components/ActionsMenu.jsx +39 -30
- package/components/ActivityCard.jsx +16 -16
- package/components/AuthOverlay.jsx +3 -3
- package/components/BrandingCard.jsx +19 -19
- package/components/Button.jsx +4 -4
- package/components/Checkbox.jsx +2 -2
- package/components/ChipSelect.jsx +4 -4
- package/components/CircularProgress.jsx +3 -3
- package/components/Confirm.jsx +6 -6
- package/components/DatePicker.jsx +45 -45
- package/components/Dropzone.jsx +17 -17
- package/components/FilePicker.jsx +17 -17
- package/components/HoverCard.jsx +4 -4
- package/components/ImageUpload.jsx +19 -19
- package/components/Input.jsx +3 -3
- package/components/LineProgress.jsx +1 -1
- package/components/Modal.jsx +15 -15
- package/components/Pagination.jsx +5 -5
- package/components/Select.jsx +24 -24
- package/components/Spinner.jsx +4 -4
- package/components/StatBarCard.jsx +1 -1
- package/components/StatsBar.jsx +4 -4
- package/components/StatsCard.jsx +2 -2
- package/components/TabBar.jsx +6 -6
- package/components/TimePicker.jsx +69 -70
- package/components/Toast.jsx +2 -2
- package/components/UptimeBar.jsx +17 -17
- package/index.js +95 -101
- package/package.json +1 -1
- package/components/Dropdown.jsx +0 -124
- package/components/MultiSelect.jsx +0 -173
- package/components/SearchableDropdown.jsx +0 -132
|
@@ -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
|
-
|
|
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
|
|
29
|
+
top = br.top - mh - 6;
|
|
45
30
|
} else {
|
|
46
|
-
top = br.bottom +
|
|
31
|
+
top = br.bottom + 6;
|
|
47
32
|
}
|
|
48
33
|
if (align === 'left') {
|
|
49
|
-
left = br.left
|
|
34
|
+
left = br.left;
|
|
50
35
|
} else {
|
|
51
|
-
left = br.right
|
|
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)
|
|
62
|
-
|
|
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:
|
|
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); }}
|
package/components/Button.jsx
CHANGED
|
@@ -80,10 +80,10 @@ const VARIANTS = {
|
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
const SIZES = {
|
|
83
|
-
xs: { padding: '
|
|
84
|
-
sm: { padding: '
|
|
85
|
-
md: { padding: '
|
|
86
|
-
lg: { padding: '
|
|
83
|
+
xs: { padding: '0 6px', fontSize: 11, height: 24 },
|
|
84
|
+
sm: { padding: '0 8px', fontSize: 11.5, height: 28 },
|
|
85
|
+
md: { padding: '0 14px', fontSize: 13, height: 32 },
|
|
86
|
+
lg: { padding: '0 18px', fontSize: 14, height: 36 },
|
|
87
87
|
};
|
|
88
88
|
|
|
89
89
|
export default function Button({
|
package/components/Checkbox.jsx
CHANGED
|
@@ -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
|
);
|
package/components/Confirm.jsx
CHANGED
|
@@ -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>
|