cynx-ui 1.3.5 → 1.3.6

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,6 +1,6 @@
1
1
  import { useState, useRef } from 'react';
2
2
  import { UploadCloud, Paperclip, FileCheck, X, Eye, Trash2 } from 'lucide-react';
3
- import LineProgress from './LineProgress.jsx';
3
+ import LinearProgress from './LinearProgress.jsx';
4
4
  import Badge from './Badge.jsx';
5
5
  import Button from './Button.jsx';
6
6
 
@@ -138,7 +138,7 @@ export function FilePicker({
138
138
  </div>
139
139
 
140
140
  {item.status === 'uploading' && (
141
- <LineProgress
141
+ <LinearProgress
142
142
  value={item.progress}
143
143
  color="var(--accent, #3b82f6)"
144
144
  height={4}
@@ -1,133 +1,133 @@
1
- import { useEffect, useRef } from 'react';
2
-
3
- const SIZES = {
4
- xs: { height: 4, fontSize: '.68rem' },
5
- sm: { height: 5, fontSize: '.75rem' },
6
- md: { height: 6, fontSize: '.82rem' },
7
- lg: { height: 8, fontSize: '.9rem' },
8
- xl: { height: 10, fontSize: '1rem' },
9
- };
10
-
11
- export default function LineProgress({
12
- value = 0,
13
- segments,
14
- size = 'md',
15
- customSize,
16
- color = 'var(--blue)',
17
- trackColor = 'var(--bd2, #e0e0e4)',
18
- label = '',
19
- showPercent = true,
20
- animated = true,
21
- rounded = true,
22
- indeterminate = false,
23
- speed = 1,
24
- height,
25
- gap = 5,
26
- labelGap = 2,
27
- className = '',
28
- style = {},
29
- }) {
30
- const base = SIZES[size] || SIZES.md;
31
- const barHeight = height ?? (customSize || base.height);
32
- const fontSize = customSize ? `${Math.max(11, customSize * 1.6)}px` : base.fontSize;
33
- const pct = Math.min(100, Math.max(0, value));
34
- const radius = rounded ? barHeight / 2 : 0;
35
-
36
- const barRef = useRef(null);
37
-
38
- // Indeterminate animation
39
- useEffect(() => {
40
- if (!indeterminate || !barRef.current) return;
41
- let pos = -40, direction = 1, raf;
42
- let lastTime = performance.now();
43
-
44
- function tick(now) {
45
- const dt = (now - lastTime) / 16.67;
46
- lastTime = now;
47
- pos += direction * 1.2 * speed * dt;
48
- if (pos > 100) { pos = 100; direction = -1; }
49
- if (pos < -40) { pos = -40; direction = 1; }
50
- if (barRef.current) {
51
- barRef.current.style.left = pos + '%';
52
- barRef.current.style.width = '40%';
53
- }
54
- raf = requestAnimationFrame(tick);
55
- }
56
- raf = requestAnimationFrame(tick);
57
- return () => cancelAnimationFrame(raf);
58
- }, [indeterminate, speed]);
59
-
60
- const transitionStyle = animated ? 'flex .5s cubic-bezier(0.4,0,0.2,1)' : 'none';
61
- const hasSegments = Array.isArray(segments) && segments.length > 0;
62
- const rawSum = hasSegments ? segments.reduce((sum, s) => sum + (Number(s.value) || 0), 0) : 0;
63
-
64
- return (
65
- <div className={className} style={{ display: 'inline-flex', flexDirection: 'column', gap: labelGap, width: '100%', ...style }}>
66
- {(label || showPercent) && (
67
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
68
- {label && <span style={{ fontSize, fontWeight: 600, color: 'var(--primary-text, #1a1a2e)' }}>{label}</span>}
69
- {showPercent && !indeterminate && !hasSegments && (
70
- <span style={{ fontSize, fontWeight: 600, color: 'var(--muted, #9ca3af)', fontVariantNumeric: 'tabular-nums', marginLeft: label ? 0 : 'auto' }}>
71
- {Math.round(pct)}%
72
- </span>
73
- )}
74
- </div>
75
- )}
76
- <div style={{
77
- height: barHeight, borderRadius: radius,
78
- background: 'transparent', position: 'relative',
79
- display: 'flex', gap: gap, overflow: 'hidden',
80
- }}>
81
- {indeterminate ? (
82
- <>
83
- <div style={{ flex: 1, borderRadius: radius, background: trackColor }} />
84
- <div
85
- ref={barRef}
86
- style={{
87
- position: 'absolute', top: 0, height: '100%',
88
- width: '40%', borderRadius: radius,
89
- background: color, opacity: 0.85,
90
- }}
91
- />
92
- </>
93
- ) : hasSegments && rawSum > 0 ? (
94
- <>
95
- {segments.map((seg, idx) => {
96
- const segVal = Number(seg.value) || 0;
97
- if (segVal <= 0) return null;
98
- const ratioPct = (segVal / rawSum) * 100;
99
- return (
100
- <div
101
- key={idx}
102
- title={seg.label ? `${seg.label}: ${segVal}` : undefined}
103
- style={{
104
- flex: ratioPct,
105
- height: '100%',
106
- borderRadius: radius,
107
- background: seg.color || color,
108
- transition: transitionStyle,
109
- }}
110
- />
111
- );
112
- })}
113
- </>
114
- ) : (
115
- <>
116
- <div ref={barRef} style={{
117
- flex: pct > 0 ? pct : 0, minWidth: pct > 0 ? barHeight : 0,
118
- borderRadius: radius, background: color,
119
- transition: transitionStyle,
120
- }} />
121
- {pct < 100 && (
122
- <div style={{
123
- flex: 100 - pct,
124
- borderRadius: radius, background: trackColor,
125
- transition: transitionStyle,
126
- }} />
127
- )}
128
- </>
129
- )}
130
- </div>
131
- </div>
132
- );
133
- }
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ const SIZES = {
4
+ xs: { height: 4, fontSize: '.68rem' },
5
+ sm: { height: 5, fontSize: '.75rem' },
6
+ md: { height: 6, fontSize: '.82rem' },
7
+ lg: { height: 8, fontSize: '.9rem' },
8
+ xl: { height: 10, fontSize: '1rem' },
9
+ };
10
+
11
+ export default function LineProgress({
12
+ value = 0,
13
+ segments,
14
+ size = 'md',
15
+ customSize,
16
+ color = 'var(--blue)',
17
+ trackColor = 'var(--bd2, #e0e0e4)',
18
+ label = '',
19
+ showPercent = true,
20
+ animated = true,
21
+ rounded = true,
22
+ indeterminate = false,
23
+ speed = 1,
24
+ height,
25
+ gap = 5,
26
+ labelGap = 2,
27
+ className = '',
28
+ style = {},
29
+ }) {
30
+ const base = SIZES[size] || SIZES.md;
31
+ const barHeight = height ?? (customSize || base.height);
32
+ const fontSize = customSize ? `${Math.max(11, customSize * 1.6)}px` : base.fontSize;
33
+ const pct = Math.min(100, Math.max(0, value));
34
+ const radius = rounded ? barHeight / 2 : 0;
35
+
36
+ const barRef = useRef(null);
37
+
38
+ // Indeterminate animation
39
+ useEffect(() => {
40
+ if (!indeterminate || !barRef.current) return;
41
+ let pos = -40, direction = 1, raf;
42
+ let lastTime = performance.now();
43
+
44
+ function tick(now) {
45
+ const dt = (now - lastTime) / 16.67;
46
+ lastTime = now;
47
+ pos += direction * 1.2 * speed * dt;
48
+ if (pos > 100) { pos = 100; direction = -1; }
49
+ if (pos < -40) { pos = -40; direction = 1; }
50
+ if (barRef.current) {
51
+ barRef.current.style.left = pos + '%';
52
+ barRef.current.style.width = '40%';
53
+ }
54
+ raf = requestAnimationFrame(tick);
55
+ }
56
+ raf = requestAnimationFrame(tick);
57
+ return () => cancelAnimationFrame(raf);
58
+ }, [indeterminate, speed]);
59
+
60
+ const transitionStyle = animated ? 'flex .5s cubic-bezier(0.4,0,0.2,1)' : 'none';
61
+ const hasSegments = Array.isArray(segments) && segments.length > 0;
62
+ const rawSum = hasSegments ? segments.reduce((sum, s) => sum + (Number(s.value) || 0), 0) : 0;
63
+
64
+ return (
65
+ <div className={className} style={{ display: 'inline-flex', flexDirection: 'column', gap: labelGap, width: '100%', ...style }}>
66
+ {(label || showPercent) && (
67
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
68
+ {label && <span style={{ fontSize, fontWeight: 600, color: 'var(--primary-text, #1a1a2e)' }}>{label}</span>}
69
+ {showPercent && !indeterminate && !hasSegments && (
70
+ <span style={{ fontSize, fontWeight: 600, color: 'var(--muted, #9ca3af)', fontVariantNumeric: 'tabular-nums', marginLeft: label ? 0 : 'auto' }}>
71
+ {Math.round(pct)}%
72
+ </span>
73
+ )}
74
+ </div>
75
+ )}
76
+ <div style={{
77
+ height: barHeight, borderRadius: radius,
78
+ background: 'transparent', position: 'relative',
79
+ display: 'flex', gap: gap, overflow: 'hidden',
80
+ }}>
81
+ {indeterminate ? (
82
+ <>
83
+ <div style={{ flex: 1, borderRadius: radius, background: trackColor }} />
84
+ <div
85
+ ref={barRef}
86
+ style={{
87
+ position: 'absolute', top: 0, height: '100%',
88
+ width: '40%', borderRadius: radius,
89
+ background: color, opacity: 0.85,
90
+ }}
91
+ />
92
+ </>
93
+ ) : hasSegments && rawSum > 0 ? (
94
+ <>
95
+ {segments.map((seg, idx) => {
96
+ const segVal = Number(seg.value) || 0;
97
+ if (segVal <= 0) return null;
98
+ const ratioPct = (segVal / rawSum) * 100;
99
+ return (
100
+ <div
101
+ key={idx}
102
+ title={seg.label ? `${seg.label}: ${segVal}` : undefined}
103
+ style={{
104
+ flex: ratioPct,
105
+ height: '100%',
106
+ borderRadius: radius,
107
+ background: seg.color || color,
108
+ transition: transitionStyle,
109
+ }}
110
+ />
111
+ );
112
+ })}
113
+ </>
114
+ ) : (
115
+ <>
116
+ <div ref={barRef} style={{
117
+ flex: pct > 0 ? pct : 0, minWidth: pct > 0 ? barHeight : 0,
118
+ borderRadius: radius, background: color,
119
+ transition: transitionStyle,
120
+ }} />
121
+ {pct < 100 && (
122
+ <div style={{
123
+ flex: 100 - pct,
124
+ borderRadius: radius, background: trackColor,
125
+ transition: transitionStyle,
126
+ }} />
127
+ )}
128
+ </>
129
+ )}
130
+ </div>
131
+ </div>
132
+ );
133
+ }
@@ -0,0 +1,132 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ const SIZES = {
4
+ xs: { height: 4, fontSize: '.68rem' },
5
+ sm: { height: 5, fontSize: '.75rem' },
6
+ md: { height: 6, fontSize: '.82rem' },
7
+ lg: { height: 8, fontSize: '.9rem' },
8
+ xl: { height: 10, fontSize: '1rem' },
9
+ };
10
+
11
+ export default function LinearProgress({
12
+ value = 0,
13
+ segments,
14
+ size = 'md',
15
+ customSize,
16
+ color = 'var(--blue, #3b82f6)',
17
+ trackColor = 'var(--bd2, #e0e0e4)',
18
+ label = '',
19
+ showPercent = true,
20
+ animated = true,
21
+ rounded = true,
22
+ indeterminate = false,
23
+ speed = 1,
24
+ height,
25
+ gap = 5,
26
+ labelGap = 2,
27
+ className = '',
28
+ style = {},
29
+ }) {
30
+ const base = SIZES[size] || SIZES.md;
31
+ const barHeight = height ?? (customSize || base.height);
32
+ const fontSize = customSize ? `${Math.max(11, customSize * 1.6)}px` : base.fontSize;
33
+ const pct = Math.min(100, Math.max(0, value));
34
+ const radius = rounded ? barHeight / 2 : 0;
35
+
36
+ const barRef = useRef(null);
37
+
38
+ useEffect(() => {
39
+ if (!indeterminate || !barRef.current) return;
40
+ let pos = -40, direction = 1, raf;
41
+ let lastTime = performance.now();
42
+
43
+ function tick(now) {
44
+ const dt = (now - lastTime) / 16.67;
45
+ lastTime = now;
46
+ pos += direction * 1.2 * speed * dt;
47
+ if (pos > 100) { pos = 100; direction = -1; }
48
+ if (pos < -40) { pos = -40; direction = 1; }
49
+ if (barRef.current) {
50
+ barRef.current.style.left = pos + '%';
51
+ barRef.current.style.width = '40%';
52
+ }
53
+ raf = requestAnimationFrame(tick);
54
+ }
55
+ raf = requestAnimationFrame(tick);
56
+ return () => cancelAnimationFrame(raf);
57
+ }, [indeterminate, speed]);
58
+
59
+ const transitionStyle = animated ? 'flex .5s cubic-bezier(0.4,0,0.2,1)' : 'none';
60
+ const hasSegments = Array.isArray(segments) && segments.length > 0;
61
+ const rawSum = hasSegments ? segments.reduce((sum, s) => sum + (Number(s.value) || 0), 0) : 0;
62
+
63
+ return (
64
+ <div className={className} style={{ display: 'inline-flex', flexDirection: 'column', gap: labelGap, width: '100%', ...style }}>
65
+ {(label || showPercent) && (
66
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
67
+ {label && <span style={{ fontSize, fontWeight: 600, color: 'var(--primary-text, #1a1a2e)' }}>{label}</span>}
68
+ {showPercent && !indeterminate && !hasSegments && (
69
+ <span style={{ fontSize, fontWeight: 600, color: 'var(--muted, #9ca3af)', fontVariantNumeric: 'tabular-nums', marginLeft: label ? 0 : 'auto' }}>
70
+ {Math.round(pct)}%
71
+ </span>
72
+ )}
73
+ </div>
74
+ )}
75
+ <div style={{
76
+ height: barHeight, borderRadius: radius,
77
+ background: 'transparent', position: 'relative',
78
+ display: 'flex', gap: gap, overflow: 'hidden',
79
+ }}>
80
+ {indeterminate ? (
81
+ <>
82
+ <div style={{ flex: 1, borderRadius: radius, background: trackColor }} />
83
+ <div
84
+ ref={barRef}
85
+ style={{
86
+ position: 'absolute', top: 0, height: '100%',
87
+ width: '40%', borderRadius: radius,
88
+ background: color, opacity: 0.85,
89
+ }}
90
+ />
91
+ </>
92
+ ) : hasSegments && rawSum > 0 ? (
93
+ <>
94
+ {segments.map((seg, idx) => {
95
+ const segVal = Number(seg.value) || 0;
96
+ if (segVal <= 0) return null;
97
+ const ratioPct = (segVal / rawSum) * 100;
98
+ return (
99
+ <div
100
+ key={idx}
101
+ title={seg.label ? `${seg.label}: ${segVal}` : undefined}
102
+ style={{
103
+ flex: ratioPct,
104
+ height: '100%',
105
+ borderRadius: radius,
106
+ background: seg.color || color,
107
+ transition: transitionStyle,
108
+ }}
109
+ />
110
+ );
111
+ })}
112
+ </>
113
+ ) : (
114
+ <>
115
+ <div ref={barRef} style={{
116
+ flex: pct > 0 ? pct : 0, minWidth: pct > 0 ? barHeight : 0,
117
+ borderRadius: radius, background: color,
118
+ transition: transitionStyle,
119
+ }} />
120
+ {pct < 100 && (
121
+ <div style={{
122
+ flex: 100 - pct,
123
+ borderRadius: radius, background: trackColor,
124
+ transition: transitionStyle,
125
+ }} />
126
+ )}
127
+ </>
128
+ )}
129
+ </div>
130
+ </div>
131
+ );
132
+ }
package/index.js CHANGED
@@ -11,7 +11,7 @@ import { default as _ChipSelect } from './components/ChipSelect.jsx';
11
11
  import { default as _Checkbox } from './components/Checkbox.jsx';
12
12
  import { default as _AuthOverlay } from './components/AuthOverlay.jsx';
13
13
  import { default as _UptimeBar } from './components/UptimeBar.jsx';
14
- import { default as _LineProgress } from './components/LineProgress.jsx';
14
+ import { default as _LinearProgress } from './components/LinearProgress.jsx';
15
15
  import { default as _StatBarCard } from './components/StatBarCard.jsx';
16
16
  import { default as _StatsCard } from './components/StatsCard.jsx';
17
17
  import { default as _ActivityCard } from './components/ActivityCard.jsx';
@@ -52,7 +52,7 @@ export const ChipSelect = _ChipSelect;
52
52
  export const Checkbox = _Checkbox;
53
53
  export const AuthOverlay = _AuthOverlay;
54
54
  export const UptimeBar = _UptimeBar;
55
- export const LineProgress = _LineProgress;
55
+ export const LinearProgress = _LinearProgress;
56
56
  export const StatBarCard = _StatBarCard;
57
57
  export const StatsCard = _StatsCard;
58
58
  export const ActivityCard = _ActivityCard;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cynx-ui",
3
- "version": "1.3.5",
3
+ "version": "1.3.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js"