hamzus-ui 0.0.12 → 0.0.13

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/index.d.ts CHANGED
@@ -21,6 +21,9 @@ export { default as TextArea } from "./src/components/hamzus-ui/TextArea/TextAre
21
21
  export { default as Checkbox } from "./src/components/hamzus-ui/Checkboxes/Checkbox/Checkbox.svelte"
22
22
  export { default as Switch } from "./src/components/hamzus-ui/Swicth/Swicth.svelte"
23
23
 
24
+ // data
25
+ export { default as ProgressCircle } from "./src/components/hamzus-ui/ProgressCircle/ProgressCircle.svelte"
26
+
24
27
 
25
28
  export * as DropdownMenu from "./src/components/hamzus-ui/DropdownMenu";
26
29
  export * as Popover from "./src/components/hamzus-ui/Popover";
package/index.js CHANGED
@@ -16,7 +16,8 @@ export { default as DatePicker } from "./src/components/hamzus-ui/DatePicker/Dat
16
16
  export { default as TextArea } from "./src/components/hamzus-ui/TextArea/TextArea.svelte"
17
17
  export { default as Checkbox } from "./src/components/hamzus-ui/Checkboxes/Checkbox/Checkbox.svelte"
18
18
  export { default as Switch } from "./src/components/hamzus-ui/Swicth/Swicth.svelte"
19
-
19
+ // data
20
+ export { default as ProgressCircle } from "./src/components/hamzus-ui/ProgressCircle/ProgressCircle.svelte"
20
21
 
21
22
  export * as DropdownMenu from "./src/components/hamzus-ui/DropdownMenu"
22
23
  export * as Popover from "./src/components/hamzus-ui/Popover"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hamzus-ui",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "svelte": "index.js",
@@ -32,7 +32,7 @@
32
32
  </svg>
33
33
  {/if}
34
34
  </IconButton>
35
- <TinyScrollArea>
35
+ <TinyScrollArea style="justify-content:center;">
36
36
  <h4 class="code" style="text-align: left;">{displayedText}</h4>
37
37
  </TinyScrollArea>
38
38
  </div>
@@ -0,0 +1,167 @@
1
+ <script>
2
+ import { onMount } from 'svelte';
3
+
4
+ export let size = 100;
5
+ export let thickness = 10;
6
+ export let progress = 100; // 0–100
7
+ export let gapPixels = 4; // Écart visuel minimal
8
+ export let color = null;
9
+ export let colorPercentBased = {
10
+ 0: 'var(--red)',
11
+ 40: 'var(--orange)',
12
+ 60: 'var(--green)'
13
+ };
14
+ export let bgColor = 'var(--bg-2)';
15
+ export let showLabel = false;
16
+ export let animated = true;
17
+ export let linecap = 'round';
18
+
19
+ const r = (size - thickness) / 2;
20
+ const cx = size / 2;
21
+ const cy = size / 2;
22
+ const circumference = 2 * Math.PI * r;
23
+
24
+ let dynamicColor = color === null;
25
+ let copyColor = dynamicColor
26
+ ? animated
27
+ ? colorPercentBased[0]
28
+ : getCorrectColor(progress)
29
+ : color;
30
+ let copyProgress = animated ? 0 : progress === 100 ? 99.99 : progress;
31
+
32
+ // Fonction ease-out (courbe cubic)
33
+ function easeOutCubic(t) {
34
+ return 1 - Math.pow(1 - t, 3);
35
+ }
36
+
37
+ onMount(() => {
38
+ if (!animated) return;
39
+
40
+ const duration = 800; // en ms
41
+ const start = performance.now();
42
+
43
+ function animate(now) {
44
+ const elapsed = now - start;
45
+ const t = Math.min(elapsed / duration, 1); // clamp entre 0 et 1
46
+
47
+ const eased = easeOutCubic(t);
48
+
49
+ let newValue = Math.round(progress * eased);
50
+
51
+ copyProgress = newValue === 100 ? 99.99 : newValue;
52
+
53
+ // determiner la couleur si il y a dynamic color
54
+ if (dynamicColor) {
55
+ let finalColor = colorPercentBased[0];
56
+ for (const step in colorPercentBased) {
57
+ const color = colorPercentBased[step];
58
+
59
+ if (copyProgress > step) {
60
+ finalColor = color;
61
+ continue;
62
+ }
63
+
64
+ break;
65
+ }
66
+
67
+ copyColor = finalColor;
68
+ }
69
+
70
+ if (t < 1) {
71
+ requestAnimationFrame(animate);
72
+ }
73
+ }
74
+
75
+ requestAnimationFrame(animate);
76
+ });
77
+
78
+ function getCorrectColor(progress) {
79
+ let finalColor = colorPercentBased[0];
80
+ for (const step in colorPercentBased) {
81
+ const color = colorPercentBased[step];
82
+
83
+ if (progress > step) {
84
+ finalColor = color;
85
+ continue;
86
+ }
87
+
88
+ break;
89
+ }
90
+
91
+ return finalColor;
92
+ }
93
+
94
+ // Progrès en angle
95
+ $: progressAngle = (copyProgress / 100) * 360;
96
+
97
+ // ➕ Compensation du stroke-linecap (ajoute une demi-thickness de chaque côté de l'arc)
98
+ const capVisualOverlap = thickness; // total débordement = thickness (2 * thickness/2)
99
+
100
+ $: totalGapPx = gapPixels + capVisualOverlap;
101
+ $: gapAngle = (totalGapPx / circumference) * 360;
102
+
103
+ $: startAngleProgress = -90;
104
+ $: endAngleProgress = startAngleProgress + progressAngle;
105
+
106
+ $: startAngleBg = endAngleProgress + gapAngle;
107
+ $: endAngleBg = 270 - gapAngle;
108
+
109
+ function polarToCartesian(cx, cy, r, angleDeg) {
110
+ const angleRad = (angleDeg * Math.PI) / 180;
111
+ return {
112
+ x: cx + r * Math.cos(angleRad),
113
+ y: cy + r * Math.sin(angleRad)
114
+ };
115
+ }
116
+
117
+ function describeArc(cx, cy, r, startAngle, endAngle) {
118
+ const start = polarToCartesian(cx, cy, r, endAngle);
119
+ const end = polarToCartesian(cx, cy, r, startAngle);
120
+ const largeArcFlag = endAngle - startAngle > 180 ? 1 : 0;
121
+
122
+ return ['M', start.x, start.y, 'A', r, r, 0, largeArcFlag, 0, end.x, end.y].join(' ');
123
+ }
124
+ </script>
125
+
126
+ <svg class="progress-circle" width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
127
+ <!-- Arc de progression -->
128
+ <path
129
+ d={describeArc(cx, cy, r, startAngleProgress, endAngleProgress)}
130
+ stroke={copyColor}
131
+ stroke-width={thickness}
132
+ fill="none"
133
+ stroke-linecap={linecap}
134
+ />
135
+
136
+ {#if showLabel}
137
+ <text
138
+ x="50%"
139
+ y="50%"
140
+ text-anchor="middle"
141
+ dominant-baseline="central"
142
+ fill={copyColor}
143
+ style="font-size: {size / 3.5}px;"
144
+ class="h4">{Math.round(copyProgress)}%</text
145
+ >
146
+ {/if}
147
+
148
+ <!-- Arc de fond, après le progress + gap -->
149
+ {#if copyProgress < 96}
150
+ <path
151
+ d={describeArc(cx, cy, r, startAngleBg, endAngleBg)}
152
+ stroke={bgColor}
153
+ stroke-width={thickness}
154
+ fill="none"
155
+ stroke-linecap={linecap}
156
+ />
157
+ {/if}
158
+ </svg>
159
+
160
+ <style>
161
+ .progress-circle path {
162
+ transition: stroke 0.3s ease-out;
163
+ }
164
+ .progress-circle text {
165
+ transition: color 0.3s ease-out;
166
+ }
167
+ </style>