cynx-ui 1.0.0
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/ActionsMenu.jsx +149 -0
- package/ActivityCard.jsx +184 -0
- package/AuthOverlay.jsx +94 -0
- package/Badge.jsx +105 -0
- package/BrandingCard.jsx +145 -0
- package/Button.jsx +76 -0
- package/Card.jsx +62 -0
- package/Checkbox.jsx +59 -0
- package/ChipSelect.jsx +54 -0
- package/CircularProgress.jsx +163 -0
- package/Confirm.jsx +79 -0
- package/DatePicker.jsx +262 -0
- package/DeleteConfirmModal.jsx +119 -0
- package/Dropdown.jsx +108 -0
- package/Dropzone.jsx +29 -0
- package/HoverCard.jsx +81 -0
- package/ImageUpload.jsx +147 -0
- package/Input.jsx +121 -0
- package/Layout.jsx +128 -0
- package/LineProgress.jsx +109 -0
- package/Modal.jsx +98 -0
- package/MultiSelect.jsx +160 -0
- package/Notifications.jsx +118 -0
- package/Pagination.jsx +41 -0
- package/PulseDot.jsx +58 -0
- package/SearchableDropdown.jsx +109 -0
- package/Select.jsx +218 -0
- package/Skeleton.jsx +126 -0
- package/Spinner.jsx +36 -0
- package/StatBarCard.jsx +25 -0
- package/StatsBar.jsx +88 -0
- package/StatsCard.jsx +97 -0
- package/TabBar.jsx +92 -0
- package/Tabs.jsx +16 -0
- package/Toast.jsx +57 -0
- package/Toggle.jsx +58 -0
- package/UptimeBar.jsx +200 -0
- package/XTable.jsx +22 -0
- package/index.js +45 -0
- package/package.json +19 -0
package/Tabs.jsx
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function Tabs({ tabs, value, onChange, style }) {
|
|
2
|
+
return (
|
|
3
|
+
<div className="xtabs" style={style}>
|
|
4
|
+
{tabs.map(t => {
|
|
5
|
+
const label = typeof t === 'string' ? t : t.label;
|
|
6
|
+
const key = typeof t === 'string' ? t : t.value;
|
|
7
|
+
const active = key === value;
|
|
8
|
+
return (
|
|
9
|
+
<button key={key} className={`xtab${active ? ' active' : ''}`} onClick={() => onChange(key)}>
|
|
10
|
+
{label}
|
|
11
|
+
</button>
|
|
12
|
+
);
|
|
13
|
+
})}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
package/Toast.jsx
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
|
|
4
|
+
// ── Module-level state ────────────────────────────────────────────────────────
|
|
5
|
+
let _toasts = [];
|
|
6
|
+
let _listeners = new Set();
|
|
7
|
+
|
|
8
|
+
function notify() {
|
|
9
|
+
const snapshot = [..._toasts];
|
|
10
|
+
_listeners.forEach(fn => fn(snapshot));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Global toast — call from anywhere, no hook needed
|
|
14
|
+
export function toast(msg, type = 'ok') {
|
|
15
|
+
const id = Date.now() + Math.random();
|
|
16
|
+
_toasts = [..._toasts, { id, msg, type }];
|
|
17
|
+
notify();
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
_toasts = _toasts.filter(t => t.id !== id);
|
|
20
|
+
notify();
|
|
21
|
+
}, 3500);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ── Hook — for components that want reactive state ────────────────────────────
|
|
25
|
+
export function useToast() {
|
|
26
|
+
const [toasts, setToasts] = useState(_toasts);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
_listeners.add(setToasts);
|
|
30
|
+
return () => _listeners.delete(setToasts);
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
const remove = useCallback(id => {
|
|
34
|
+
_toasts = _toasts.filter(t => t.id !== id);
|
|
35
|
+
notify();
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
return { toasts, toast, remove };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Render component ──────────────────────────────────────────────────────────
|
|
42
|
+
export function Toast({ toasts, remove }) {
|
|
43
|
+
return createPortal(
|
|
44
|
+
<div id="toast-root">
|
|
45
|
+
{toasts.map(t => (
|
|
46
|
+
<div key={t.id} className={`toast ${t.type}`} onClick={() => remove(t.id)}>
|
|
47
|
+
{t.type === 'ok'
|
|
48
|
+
? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--success)" strokeWidth="2.5" strokeLinecap="round"><polyline points="20 6 9 17 4 12"/></svg>
|
|
49
|
+
: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="var(--danger)" strokeWidth="2.5" strokeLinecap="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
|
|
50
|
+
}
|
|
51
|
+
{t.msg}
|
|
52
|
+
</div>
|
|
53
|
+
))}
|
|
54
|
+
</div>,
|
|
55
|
+
document.body
|
|
56
|
+
);
|
|
57
|
+
}
|
package/Toggle.jsx
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const STYLES = `
|
|
2
|
+
.tgl{display:inline-flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
|
|
3
|
+
.tgl input{position:absolute;opacity:0;width:0;height:0}
|
|
4
|
+
.tgl-tr{position:relative;border-radius:var(--rfull,99px);transition:background .2s ease;flex-shrink:0;box-shadow:var(--shadow,0 1px 3px rgba(20,22,41,.1))}
|
|
5
|
+
.tgl-th{position:absolute;top:50%;transform:translateY(-50%);background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.25);transition:left .25s cubic-bezier(.34,1.56,.64,1)}
|
|
6
|
+
.tgl-sm .tgl-tr{width:28px;height:16px}
|
|
7
|
+
.tgl-sm .tgl-th{width:12px;height:12px;left:2px}
|
|
8
|
+
.tgl-sm input:checked~.tgl-tr .tgl-th{left:14px}
|
|
9
|
+
.tgl-md .tgl-tr{width:34px;height:18px}
|
|
10
|
+
.tgl-md .tgl-th{width:14px;height:14px;left:2px}
|
|
11
|
+
.tgl-md input:checked~.tgl-tr .tgl-th{left:18px}
|
|
12
|
+
.tgl-lg .tgl-tr{width:44px;height:24px}
|
|
13
|
+
.tgl-lg .tgl-th{width:18px;height:18px;left:3px}
|
|
14
|
+
.tgl-lg input:checked~.tgl-tr .tgl-th{left:23px}
|
|
15
|
+
.tgl:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const COLORS = {
|
|
19
|
+
primary: 'var(--accent)',
|
|
20
|
+
success: 'var(--success)',
|
|
21
|
+
warning: '#f59e0b',
|
|
22
|
+
danger: 'var(--danger)',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
let styleInjected = false;
|
|
26
|
+
|
|
27
|
+
export default function Toggle({
|
|
28
|
+
checked = false,
|
|
29
|
+
onChange,
|
|
30
|
+
disabled = false,
|
|
31
|
+
size = 'md',
|
|
32
|
+
color = 'primary',
|
|
33
|
+
label = null,
|
|
34
|
+
labelStyle = {},
|
|
35
|
+
onClick = null,
|
|
36
|
+
className = '',
|
|
37
|
+
style = {},
|
|
38
|
+
}) {
|
|
39
|
+
if (!styleInjected && typeof document !== 'undefined') {
|
|
40
|
+
const tag = document.createElement('style');
|
|
41
|
+
tag.textContent = STYLES;
|
|
42
|
+
document.head.appendChild(tag);
|
|
43
|
+
styleInjected = true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const sizeClass = size !== 'md' ? ` tgl-${size}` : '';
|
|
47
|
+
const classes = `tgl${sizeClass}${className ? ' ' + className : ''}`;
|
|
48
|
+
const trackColor = checked ? (COLORS[color] || COLORS.primary) : 'var(--bd2,#d7d8e0)';
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<label className={classes} style={style} onClick={onClick}>
|
|
52
|
+
<input type="checkbox" checked={checked} disabled={disabled}
|
|
53
|
+
onChange={e => onChange?.(e.target.checked)} />
|
|
54
|
+
<span className="tgl-tr" style={{ background: trackColor }}><span className="tgl-th" /></span>
|
|
55
|
+
{label && <span style={labelStyle}>{label}</span>}
|
|
56
|
+
</label>
|
|
57
|
+
);
|
|
58
|
+
}
|
package/UptimeBar.jsx
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { useMemo, useState, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
const card = {
|
|
4
|
+
background: '#fff',
|
|
5
|
+
border: '1px solid var(--border)',
|
|
6
|
+
borderRadius: 'var(--rad)',
|
|
7
|
+
boxShadow: '0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04)',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
|
11
|
+
|
|
12
|
+
function formatDate(date) {
|
|
13
|
+
return `${MONTHS[date.getMonth()]} ${date.getDate()}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default function UptimeBar({
|
|
17
|
+
title = 'Uptime',
|
|
18
|
+
subtitle,
|
|
19
|
+
successValues = [],
|
|
20
|
+
failedValues = [],
|
|
21
|
+
totalSlots = 90,
|
|
22
|
+
greenColor = 'var(--success)',
|
|
23
|
+
redColor = 'var(--danger)',
|
|
24
|
+
emptyColor = 'var(--grey-1)',
|
|
25
|
+
barHeight = 28,
|
|
26
|
+
barRadius = 3,
|
|
27
|
+
leftLabel,
|
|
28
|
+
rightLabel,
|
|
29
|
+
showDot = true,
|
|
30
|
+
dotColor,
|
|
31
|
+
style,
|
|
32
|
+
}) {
|
|
33
|
+
const [hovered, setHovered] = useState(null);
|
|
34
|
+
const [tooltipPos, setTooltipPos] = useState({ x: 0, y: 0 });
|
|
35
|
+
const containerRef = useRef(null);
|
|
36
|
+
|
|
37
|
+
const bars = useMemo(() => {
|
|
38
|
+
const len = Math.max(successValues.length, failedValues.length, totalSlots);
|
|
39
|
+
const result = [];
|
|
40
|
+
const stepS = successValues.length / len;
|
|
41
|
+
const stepF = failedValues.length / len;
|
|
42
|
+
for (let i = 0; i < len; i++) {
|
|
43
|
+
const si = Math.min(Math.floor(i * stepS), successValues.length - 1);
|
|
44
|
+
const fi = Math.min(Math.floor(i * stepF), failedValues.length - 1);
|
|
45
|
+
const s = successValues[si] || 0;
|
|
46
|
+
const f = failedValues[fi] || 0;
|
|
47
|
+
result.push({ success: s, failed: f });
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}, [successValues, failedValues, totalSlots]);
|
|
51
|
+
|
|
52
|
+
const dates = useMemo(() => {
|
|
53
|
+
const result = [];
|
|
54
|
+
const now = new Date();
|
|
55
|
+
for (let i = 0; i < bars.length; i++) {
|
|
56
|
+
const d = new Date(now);
|
|
57
|
+
d.setDate(d.getDate() - (bars.length - 1 - i));
|
|
58
|
+
result.push(d);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}, [bars.length]);
|
|
62
|
+
|
|
63
|
+
const totalSuccess = bars.reduce((a, b) => a + b.success, 0);
|
|
64
|
+
const totalFailed = bars.reduce((a, b) => a + b.failed, 0);
|
|
65
|
+
const totalAll = totalSuccess + totalFailed;
|
|
66
|
+
const uptimePercent = totalAll > 0 ? Math.round((totalSuccess / totalAll) * 100) : 100;
|
|
67
|
+
|
|
68
|
+
function handleMouseEnter(e, idx) {
|
|
69
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
70
|
+
const containerRect = containerRef.current.getBoundingClientRect();
|
|
71
|
+
setTooltipPos({
|
|
72
|
+
x: rect.left - containerRect.left + rect.width / 2,
|
|
73
|
+
y: rect.top - containerRect.top - 8,
|
|
74
|
+
});
|
|
75
|
+
setHovered(idx);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div ref={containerRef} style={{ ...card, padding: '14px 18px 14px', position: 'relative', ...style }}>
|
|
80
|
+
{/* Header */}
|
|
81
|
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
|
|
82
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
83
|
+
{showDot && (
|
|
84
|
+
<span style={{
|
|
85
|
+
width: 8, height: 8, borderRadius: '50%',
|
|
86
|
+
background: dotColor || greenColor, flexShrink: 0,
|
|
87
|
+
}} />
|
|
88
|
+
)}
|
|
89
|
+
<span style={{ fontSize: '.78rem', fontWeight: 700, color: 'var(--primary-text)', letterSpacing: '-.01em' }}>{title}</span>
|
|
90
|
+
{subtitle && <span style={{ fontSize: '.65rem', color: 'var(--muted)', fontWeight: 500 }}>{subtitle}</span>}
|
|
91
|
+
</div>
|
|
92
|
+
{/* Legend */}
|
|
93
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
|
94
|
+
<LegendDot color={greenColor} label="Success" />
|
|
95
|
+
<LegendDot color={redColor} label="Failed" />
|
|
96
|
+
<LegendDot color={emptyColor} label="None" />
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{/* Bars */}
|
|
101
|
+
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 2, height: barHeight, marginBottom: 6 }}>
|
|
102
|
+
{bars.map((b, i) => {
|
|
103
|
+
const total = b.success + b.failed;
|
|
104
|
+
const hasData = total > 0;
|
|
105
|
+
const successPct = hasData ? (b.success / total) * 100 : 0;
|
|
106
|
+
const failedPct = hasData ? (b.failed / total) * 100 : 0;
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div
|
|
110
|
+
key={i}
|
|
111
|
+
onMouseEnter={(e) => handleMouseEnter(e, i)}
|
|
112
|
+
onMouseLeave={() => setHovered(null)}
|
|
113
|
+
style={{
|
|
114
|
+
flex: 1,
|
|
115
|
+
height: '100%',
|
|
116
|
+
borderRadius: barRadius,
|
|
117
|
+
overflow: 'hidden',
|
|
118
|
+
display: 'flex',
|
|
119
|
+
flexDirection: 'column',
|
|
120
|
+
background: hasData ? 'transparent' : emptyColor,
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
{hasData && (
|
|
124
|
+
<>
|
|
125
|
+
{/* Failed on bottom */}
|
|
126
|
+
{b.failed > 0 && (
|
|
127
|
+
<div style={{ height: `${failedPct}%`, background: redColor, marginTop: 'auto' }} />
|
|
128
|
+
)}
|
|
129
|
+
{/* Success on top */}
|
|
130
|
+
{b.success > 0 && (
|
|
131
|
+
<div style={{ height: `${successPct}%`, background: greenColor }} />
|
|
132
|
+
)}
|
|
133
|
+
</>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
})}
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
{/* Tooltip */}
|
|
141
|
+
{hovered !== null && (
|
|
142
|
+
<div style={{
|
|
143
|
+
position: 'absolute',
|
|
144
|
+
left: tooltipPos.x,
|
|
145
|
+
top: tooltipPos.y,
|
|
146
|
+
transform: 'translate(-50%, -100%)',
|
|
147
|
+
background: '#fff',
|
|
148
|
+
border: '1px solid var(--border)',
|
|
149
|
+
borderRadius: 'var(--rads)',
|
|
150
|
+
boxShadow: '0 4px 12px rgba(0,0,0,.12)',
|
|
151
|
+
padding: '8px 12px',
|
|
152
|
+
pointerEvents: 'none',
|
|
153
|
+
zIndex: 100,
|
|
154
|
+
whiteSpace: 'nowrap',
|
|
155
|
+
}}>
|
|
156
|
+
<div style={{ fontSize: '.65rem', color: 'var(--muted)', fontWeight: 500, marginBottom: 4 }}>
|
|
157
|
+
{formatDate(dates[hovered])}
|
|
158
|
+
</div>
|
|
159
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
160
|
+
{bars[hovered].success > 0 && (
|
|
161
|
+
<div style={{ fontSize: '.7rem', fontWeight: 700, color: greenColor }}>
|
|
162
|
+
{bars[hovered].success} success login{bars[hovered].success !== 1 ? 's' : ''}
|
|
163
|
+
{bars[hovered].failed > 0 && <span style={{ fontWeight: 500, color: 'var(--muted)' }}> ({Math.round((bars[hovered].success / (bars[hovered].success + bars[hovered].failed)) * 100)}%)</span>}
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
{bars[hovered].failed > 0 && (
|
|
167
|
+
<div style={{ fontSize: '.7rem', fontWeight: 700, color: redColor }}>
|
|
168
|
+
{bars[hovered].failed} failed login{bars[hovered].failed !== 1 ? 's' : ''}
|
|
169
|
+
{bars[hovered].success > 0 && <span style={{ fontWeight: 500, color: 'var(--muted)' }}> ({Math.round((bars[hovered].failed / (bars[hovered].success + bars[hovered].failed)) * 100)}%)</span>}
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
{bars[hovered].success === 0 && bars[hovered].failed === 0 && (
|
|
173
|
+
<div style={{ fontSize: '.7rem', fontWeight: 500, color: 'var(--muted)' }}>
|
|
174
|
+
No logins
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
{/* Footer */}
|
|
182
|
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
183
|
+
<span style={{ fontSize: '.58rem', color: 'var(--muted)', fontWeight: 500 }}>{leftLabel || '90 days ago'}</span>
|
|
184
|
+
<span style={{ fontSize: '.78rem', fontWeight: 700, color: greenColor, fontFamily: 'var(--mono)' }}>
|
|
185
|
+
{uptimePercent}%
|
|
186
|
+
</span>
|
|
187
|
+
<span style={{ fontSize: '.58rem', color: 'var(--muted)', fontWeight: 500 }}>{rightLabel || 'Today'}</span>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function LegendDot({ color, label }) {
|
|
194
|
+
return (
|
|
195
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
|
196
|
+
<span style={{ width: 7, height: 7, borderRadius: 2, background: color, flexShrink: 0 }} />
|
|
197
|
+
<span style={{ fontSize: '.55rem', color: 'var(--muted)', fontWeight: 500 }}>{label}</span>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
}
|
package/XTable.jsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function XTable({ children, style }) { return <table className="x-table" style={style}>{children}</table>; }
|
|
2
|
+
export function XThead({ children }) { return <thead>{children}</thead>; }
|
|
3
|
+
export function XTbody({ children }) { return <tbody>{children}</tbody>; }
|
|
4
|
+
export function XTr({ children, onClick }) { return <tr className="x-tr" onClick={onClick}>{children}</tr>; }
|
|
5
|
+
export function XTh({ children, style }) { return <th className="x-th" style={style}>{children}</th>; }
|
|
6
|
+
export function XTd({ children, style, className = '', colSpan }) {
|
|
7
|
+
return <td className={`x-td ${className}`} style={style} colSpan={colSpan}>{children}</td>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function SkeletonTable({ rows = 6, cols = 5 }) {
|
|
11
|
+
return (
|
|
12
|
+
<div>
|
|
13
|
+
{Array.from({ length: rows }).map((_, i) => (
|
|
14
|
+
<div key={i} className="skeleton-row">
|
|
15
|
+
{Array.from({ length: cols }).map((_, j) => (
|
|
16
|
+
<div key={j} className={`skeleton skeleton-text ${j === 0 ? 'short' : j === cols - 1 ? 'short' : 'mid'}`} style={{ flex: 1 }} />
|
|
17
|
+
))}
|
|
18
|
+
</div>
|
|
19
|
+
))}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// cynx-ui — shared component library
|
|
2
|
+
// Re-exports every component so consumers can do:
|
|
3
|
+
// import { Button, Modal, Toast } from 'cynx-ui'
|
|
4
|
+
|
|
5
|
+
export { default as Button } from './Button.jsx';
|
|
6
|
+
export { default as Input } from './Input.jsx';
|
|
7
|
+
export { default as Layout } from './Layout.jsx';
|
|
8
|
+
export { default as Toggle } from './Toggle.jsx';
|
|
9
|
+
export { default as Spinner } from './Spinner.jsx';
|
|
10
|
+
export { default as TabBar } from './TabBar.jsx';
|
|
11
|
+
export { default as Dropdown } from './Dropdown.jsx';
|
|
12
|
+
export { default as Notifications } from './Notifications.jsx';
|
|
13
|
+
export { default as MultiSelect } from './MultiSelect.jsx';
|
|
14
|
+
export { default as ImageUpload } from './ImageUpload.jsx';
|
|
15
|
+
export { default as DeleteConfirmModal } from './DeleteConfirmModal.jsx';
|
|
16
|
+
export { default as ChipSelect } from './ChipSelect.jsx';
|
|
17
|
+
export { default as Checkbox } from './Checkbox.jsx';
|
|
18
|
+
export { default as AuthOverlay } from './AuthOverlay.jsx';
|
|
19
|
+
export { default as UptimeBar } from './UptimeBar.jsx';
|
|
20
|
+
export { default as LineProgress } from './LineProgress.jsx';
|
|
21
|
+
export { default as StatBarCard } from './StatBarCard.jsx';
|
|
22
|
+
export { default as StatsCard } from './StatsCard.jsx';
|
|
23
|
+
export { default as ActivityCard } from './ActivityCard.jsx';
|
|
24
|
+
export { default as HoverCard } from './HoverCard.jsx';
|
|
25
|
+
export { default as StatsBar } from './StatsBar.jsx';
|
|
26
|
+
export { default as Select } from './Select.jsx';
|
|
27
|
+
export { default as Card } from './Card.jsx';
|
|
28
|
+
export { default as Badge } from './Badge.jsx';
|
|
29
|
+
export { default as PulseDot } from './PulseDot.jsx';
|
|
30
|
+
export { default as CircularProgress } from './CircularProgress.jsx';
|
|
31
|
+
export { default as Skeleton } from './Skeleton.jsx';
|
|
32
|
+
|
|
33
|
+
export { Modal, Confirm } from './Modal.jsx';
|
|
34
|
+
export { toast, useToast, Toast } from './Toast.jsx';
|
|
35
|
+
export { ConfirmRoot, confirm } from './Confirm.jsx';
|
|
36
|
+
export { SearchableDropdown } from './SearchableDropdown.jsx';
|
|
37
|
+
export { Pagination } from './Pagination.jsx';
|
|
38
|
+
export { DatePicker } from './DatePicker.jsx';
|
|
39
|
+
export { ActionsMenu } from './ActionsMenu.jsx';
|
|
40
|
+
export { BrandingCard } from './BrandingCard.jsx';
|
|
41
|
+
export { Dropzone } from './Dropzone.jsx';
|
|
42
|
+
export { Tabs } from './Tabs.jsx';
|
|
43
|
+
export { SkeletonText, SkeletonCard, SkeletonRows, SkeletonStats } from './Skeleton.jsx';
|
|
44
|
+
export { XTable, XThead, XTbody, XTr, XTh, XTd, SkeletonTable } from './XTable.jsx';
|
|
45
|
+
export { PageShell, TableCard, TableCardFilters, TableCardBody, TableCardFooter, CardHdr, StatCard, StatCardSkeleton } from './Card.jsx';
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cynx-ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.js",
|
|
7
|
+
"./*": "./*.jsx"
|
|
8
|
+
},
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"react": ">=18",
|
|
11
|
+
"react-dom": ">=18",
|
|
12
|
+
"react-router-dom": ">=6",
|
|
13
|
+
"lucide-react": ">=0.400"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"*.jsx",
|
|
17
|
+
"index.js"
|
|
18
|
+
]
|
|
19
|
+
}
|