hamzus-ui 0.0.11 → 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
@@ -1,5 +1,4 @@
1
1
  // index.d.ts
2
- import type { SvelteComponentTyped } from "svelte";
3
2
 
4
3
  // button
5
4
  export { default as Button } from "./src/components/hamzus-ui/Button/Button.svelte"
@@ -18,6 +17,12 @@ export { default as Dialog } from "./src/components/hamzus-ui/Dialog/Dialog.svel
18
17
  // form
19
18
  export { default as Input } from "./src/components/hamzus-ui/Input/Input.svelte"
20
19
  export { default as DatePicker } from "./src/components/hamzus-ui/DatePicker/DatePicker.svelte"
20
+ export { default as TextArea } from "./src/components/hamzus-ui/TextArea/TextArea.svelte"
21
+ export { default as Checkbox } from "./src/components/hamzus-ui/Checkboxes/Checkbox/Checkbox.svelte"
22
+ export { default as Switch } from "./src/components/hamzus-ui/Swicth/Swicth.svelte"
23
+
24
+ // data
25
+ export { default as ProgressCircle } from "./src/components/hamzus-ui/ProgressCircle/ProgressCircle.svelte"
21
26
 
22
27
 
23
28
  export * as DropdownMenu from "./src/components/hamzus-ui/DropdownMenu";
package/index.js CHANGED
@@ -13,7 +13,11 @@ export { default as Dialog } from "./src/components/hamzus-ui/Dialog/Dialog.svel
13
13
  // form
14
14
  export { default as Input } from "./src/components/hamzus-ui/Input/Input.svelte"
15
15
  export { default as DatePicker } from "./src/components/hamzus-ui/DatePicker/DatePicker.svelte"
16
-
16
+ export { default as TextArea } from "./src/components/hamzus-ui/TextArea/TextArea.svelte"
17
+ export { default as Checkbox } from "./src/components/hamzus-ui/Checkboxes/Checkbox/Checkbox.svelte"
18
+ export { default as Switch } from "./src/components/hamzus-ui/Swicth/Swicth.svelte"
19
+ // data
20
+ export { default as ProgressCircle } from "./src/components/hamzus-ui/ProgressCircle/ProgressCircle.svelte"
17
21
 
18
22
  export * as DropdownMenu from "./src/components/hamzus-ui/DropdownMenu"
19
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.11",
3
+ "version": "0.0.13",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "svelte": "index.js",
@@ -1,41 +1,116 @@
1
1
  <script>
2
- export let size = "24px"
3
- export let name = '';
4
- export let label = '';
5
- export let disabled = false;
6
- export let fullWidth = false;
7
- export let checked = false;
8
- export let onChange = null;
2
+ export let size = 24;
3
+ export let name = '';
4
+ export let label = '';
5
+ export let disabled = false;
6
+ export let fullWidth = false;
7
+ export let checked = false;
8
+ export let direction = 'ltr';
9
+ export let onChange = null;
9
10
 
10
- import "./index.css"
11
+ function handleCheckboxChange() {
12
+ if (disabled) {
13
+ checked = checked;
14
+ return;
15
+ }
11
16
 
12
- function handleCheckboxChange() {
13
- if (disabled) {
14
- checked = checked
15
- return
16
- }
17
-
18
- checked = !checked
17
+ checked = !checked;
19
18
 
20
- if (onChange) {
21
- onChange(checked)
22
- }
23
- }
19
+ if (onChange) {
20
+ onChange(checked);
21
+ }
22
+ }
24
23
  </script>
25
- <label class="checkbox-label {disabled ? "disabled" : ""} {fullWidth ? "full-width" : ""}" >
26
- {#if label}
27
- <h4>{label}</h4>
28
- {/if}
29
- <div class="checkbox-box" style="width:{size};height:{size};">
30
- <input
31
- {disabled}
32
- type="checkbox"
33
- {name}
34
- {checked}
35
- on:change={handleCheckboxChange}
36
- style="display:none;" />
37
- <svg width="20px" height="20px" viewBox="0 0 20 20">
38
- <polyline points="4 11 8 15 16 6"></polyline>
39
- </svg>
40
- </div>
41
- </label>
24
+
25
+ <label class="checkbox-label {disabled ? 'disabled' : ''} {fullWidth ? 'full-width' : ''}">
26
+ {#if label && direction === 'ltr'}
27
+ <h4>{label}</h4>
28
+ {/if}
29
+ <div class="checkbox-box" style="width:{size}px;height:{size}px;--width:{size}px;">
30
+ <input
31
+ {disabled}
32
+ type="checkbox"
33
+ {name}
34
+ {checked}
35
+ on:change={handleCheckboxChange}
36
+ style="display:none;"
37
+ />
38
+ <svg width="20px" height="20px" viewBox="0 0 20 20">
39
+ <polyline points="4 11 8 15 16 6"></polyline>
40
+ </svg>
41
+ </div>
42
+ {#if label && direction === 'rtl'}
43
+ <h4>{label}</h4>
44
+ {/if}
45
+ </label>
46
+
47
+ <style>
48
+ .checkbox-label {
49
+ display: flex;
50
+ align-items: center;
51
+ column-gap: 7px;
52
+ cursor: pointer;
53
+ user-select: none;
54
+ }
55
+ .checkbox-label.full-width {
56
+ width: 100%;
57
+ justify-content: space-between;
58
+ }
59
+ .checkbox-box {
60
+ width: 22px;
61
+ height: 22px;
62
+ display: flex;
63
+ flex-shrink: 0;
64
+ border-radius: calc(var(--width) / 3.5);
65
+ border: 2px solid var(--stroke);
66
+ position: relative;
67
+ cursor: pointer;
68
+ transition: background-color 0.2s ease-out;
69
+ }
70
+ .checkbox-box:hover {
71
+ background-color: var(--bg-2);
72
+ }
73
+ .checkbox-box svg {
74
+ position: absolute;
75
+ width: 70%;
76
+ height: auto;
77
+ left: 50%;
78
+ top: 50%;
79
+ transform: translate(-50%, -50%) scale(0.6);
80
+ user-select: none;
81
+ pointer-events: none;
82
+ transition-property: transform;
83
+ transition-duration: 0.2s;
84
+ transition-timing-function: ease-out;
85
+ }
86
+ .checkbox-box svg polyline {
87
+ fill: none;
88
+ stroke: #fff;
89
+ stroke-width: 2;
90
+ stroke-linecap: round;
91
+ stroke-linejoin: round;
92
+ stroke-dasharray: 50px;
93
+ stroke-dashoffset: 50px;
94
+ transition: stroke-dashoffset 0.2s ease-out;
95
+ }
96
+
97
+ .checkbox-box:has(input:checked) {
98
+ background-color: var(--accent);
99
+ border: 2px solid var(--accent);
100
+ }
101
+ .checkbox-box:has(input:checked) svg {
102
+ user-select: initial;
103
+ pointer-events: initial;
104
+ transform: translate(-50%, -50%) scale(1);
105
+ }
106
+ .checkbox-box:has(input:checked) svg polyline {
107
+ stroke-dashoffset: 0;
108
+ }
109
+ .checkbox-label.disabled {
110
+ opacity: 0.9;
111
+ cursor: not-allowed;
112
+ }
113
+ .checkbox-label.disabled .checkbox-box {
114
+ cursor: not-allowed;
115
+ }
116
+ </style>
@@ -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>
@@ -1,28 +1,26 @@
1
1
  <script>
2
2
  export let style;
3
- export let size = 24;
3
+ export let size = 20;
4
4
  export let checked = false;
5
5
  export let disabled = false;
6
6
  export let disabledIcon = false;
7
- export let onChange = undefined;
7
+ export let onChange = undefined;
8
+ export let fullWidth = false;
8
9
  export let label;
9
10
 
10
- import './index.css';
11
-
12
11
  function handleChange() {
13
-
14
12
  if (disabled) {
15
13
  return;
16
14
  }
17
15
 
18
- checked = !checked;
19
- if (onChange && typeof onChange === 'function') {
20
- onChange(checked)
21
- }
16
+ checked = !checked;
17
+ if (onChange && typeof onChange === 'function') {
18
+ onChange(checked);
19
+ }
22
20
  }
23
21
  </script>
24
22
 
25
- <label class="label-switch">
23
+ <label class="label-switch {fullWidth ? 'full-width' : ''}">
26
24
  {#if label}
27
25
  <h4>{label}</h4>
28
26
  {/if}
@@ -30,55 +28,204 @@
30
28
  style="width:{size * 2 + 4}px;height:{size + 4}px;--size:{size + 4}px; {style ? style : ''}"
31
29
  class="switch {checked ? 'active' : ''} {disabled ? 'disabled' : ''}"
32
30
  >
33
- <input type="checkbox" {checked} style="display:none;" on:change={handleChange}/>
31
+ <input type="checkbox" {checked} style="display:none;" on:change={handleChange} />
34
32
  <div
35
33
  style="width:{size}px;height:{size}px;transform:{checked
36
34
  ? `translateX(${size + 2}px) translateY(2px)`
37
35
  : 'translateX(2px) translateY(2px)'};"
38
36
  class="head"
39
37
  >
40
- {#if disabledIcon}
41
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
42
- <path d="M18 10.75C17.59 10.75 17.25 10.41 17.25 10V8C17.25 4.85 16.36 2.75 12 2.75C7.64 2.75 6.75 4.85 6.75 8V10C6.75 10.41 6.41 10.75 6 10.75C5.59 10.75 5.25 10.41 5.25 10V8C5.25 5.1 5.95 1.25 12 1.25C18.05 1.25 18.75 5.1 18.75 8V10C18.75 10.41 18.41 10.75 18 10.75Z" fill="#292D32"/>
43
- <path d="M12 19.25C10.21 19.25 8.75 17.79 8.75 16C8.75 14.21 10.21 12.75 12 12.75C13.79 12.75 15.25 14.21 15.25 16C15.25 17.79 13.79 19.25 12 19.25ZM12 14.25C11.04 14.25 10.25 15.04 10.25 16C10.25 16.96 11.04 17.75 12 17.75C12.96 17.75 13.75 16.96 13.75 16C13.75 15.04 12.96 14.25 12 14.25Z" fill="#292D32"/>
44
- <path d="M17 22.75H7C2.59 22.75 1.25 21.41 1.25 17V15C1.25 10.59 2.59 9.25 7 9.25H17C21.41 9.25 22.75 10.59 22.75 15V17C22.75 21.41 21.41 22.75 17 22.75ZM7 10.75C3.42 10.75 2.75 11.43 2.75 15V17C2.75 20.57 3.42 21.25 7 21.25H17C20.58 21.25 21.25 20.57 21.25 17V15C21.25 11.43 20.58 10.75 17 10.75H7Z" fill="#292D32"/>
45
- </svg>
46
- {/if}
47
-
48
- </div>
49
- <div class="state">
50
- <div class="active">
38
+ {#if disabledIcon}
51
39
  <svg
52
- width="31"
53
- height="31"
54
- viewBox="0 0 31 31"
40
+ width="24"
41
+ height="24"
42
+ viewBox="0 0 24 24"
55
43
  fill="none"
56
44
  xmlns="http://www.w3.org/2000/svg"
57
45
  >
58
46
  <path
59
- fill-rule="evenodd"
60
- clip-rule="evenodd"
61
- d="M15.5 5.97668C16.0523 5.97668 16.5 6.4244 16.5 6.97668L16.5 24.0233C16.5 24.5756 16.0523 25.0233 15.5 25.0233C14.9477 25.0233 14.5 24.5756 14.5 24.0233L14.5 6.97668C14.5 6.4244 14.9477 5.97668 15.5 5.97668Z"
62
- fill="black"
47
+ d="M18 10.75C17.59 10.75 17.25 10.41 17.25 10V8C17.25 4.85 16.36 2.75 12 2.75C7.64 2.75 6.75 4.85 6.75 8V10C6.75 10.41 6.41 10.75 6 10.75C5.59 10.75 5.25 10.41 5.25 10V8C5.25 5.1 5.95 1.25 12 1.25C18.05 1.25 18.75 5.1 18.75 8V10C18.75 10.41 18.41 10.75 18 10.75Z"
48
+ fill="#292D32"
63
49
  />
64
- </svg>
65
- </div>
66
- <div class="not-active">
67
- <svg
68
- width="31"
69
- height="31"
70
- viewBox="0 0 31 31"
71
- fill="none"
72
- xmlns="http://www.w3.org/2000/svg"
73
- >
74
50
  <path
75
- fill-rule="evenodd"
76
- clip-rule="evenodd"
77
- d="M15.5 5.58868C10.0261 5.58868 5.58868 10.0261 5.58868 15.5C5.58868 20.9739 10.0261 25.4113 15.5 25.4113C20.9739 25.4113 25.4113 20.9739 25.4113 15.5C25.4113 10.0261 20.9739 5.58868 15.5 5.58868ZM3.58868 15.5C3.58868 8.92156 8.92156 3.58868 15.5 3.58868C22.0784 3.58868 27.4113 8.92156 27.4113 15.5C27.4113 22.0784 22.0784 27.4113 15.5 27.4113C8.92156 27.4113 3.58868 22.0784 3.58868 15.5Z"
78
- fill="black"
51
+ d="M12 19.25C10.21 19.25 8.75 17.79 8.75 16C8.75 14.21 10.21 12.75 12 12.75C13.79 12.75 15.25 14.21 15.25 16C15.25 17.79 13.79 19.25 12 19.25ZM12 14.25C11.04 14.25 10.25 15.04 10.25 16C10.25 16.96 11.04 17.75 12 17.75C12.96 17.75 13.75 16.96 13.75 16C13.75 15.04 12.96 14.25 12 14.25Z"
52
+ fill="#292D32"
53
+ />
54
+ <path
55
+ d="M17 22.75H7C2.59 22.75 1.25 21.41 1.25 17V15C1.25 10.59 2.59 9.25 7 9.25H17C21.41 9.25 22.75 10.59 22.75 15V17C22.75 21.41 21.41 22.75 17 22.75ZM7 10.75C3.42 10.75 2.75 11.43 2.75 15V17C2.75 20.57 3.42 21.25 7 21.25H17C20.58 21.25 21.25 20.57 21.25 17V15C21.25 11.43 20.58 10.75 17 10.75H7Z"
56
+ fill="#292D32"
79
57
  />
80
58
  </svg>
59
+ {/if}
60
+ </div>
61
+ <div class="state">
62
+ <div class="active">
63
+ {#if $$slots.activeIcon}
64
+ <slot name="activeIcon" />
65
+ {:else}
66
+ <svg
67
+ width="31"
68
+ height="31"
69
+ viewBox="0 0 31 31"
70
+ fill="none"
71
+ xmlns="http://www.w3.org/2000/svg"
72
+ >
73
+ <path
74
+ fill-rule="evenodd"
75
+ clip-rule="evenodd"
76
+ d="M15.5 5.97668C16.0523 5.97668 16.5 6.4244 16.5 6.97668L16.5 24.0233C16.5 24.5756 16.0523 25.0233 15.5 25.0233C14.9477 25.0233 14.5 24.5756 14.5 24.0233L14.5 6.97668C14.5 6.4244 14.9477 5.97668 15.5 5.97668Z"
77
+ fill="black"
78
+ />
79
+ </svg>
80
+ {/if}
81
+ </div>
82
+ <div class="not-active">
83
+ {#if $$slots.disabledIcon}
84
+ <slot name="disabledIcon" />
85
+ {:else}
86
+ <svg
87
+ width="31"
88
+ height="31"
89
+ viewBox="0 0 31 31"
90
+ fill="none"
91
+ xmlns="http://www.w3.org/2000/svg"
92
+ >
93
+ <path
94
+ fill-rule="evenodd"
95
+ clip-rule="evenodd"
96
+ d="M15.5 5.58868C10.0261 5.58868 5.58868 10.0261 5.58868 15.5C5.58868 20.9739 10.0261 25.4113 15.5 25.4113C20.9739 25.4113 25.4113 20.9739 25.4113 15.5C25.4113 10.0261 20.9739 5.58868 15.5 5.58868ZM3.58868 15.5C3.58868 8.92156 8.92156 3.58868 15.5 3.58868C22.0784 3.58868 27.4113 8.92156 27.4113 15.5C27.4113 22.0784 22.0784 27.4113 15.5 27.4113C8.92156 27.4113 3.58868 22.0784 3.58868 15.5Z"
97
+ fill="black"
98
+ />
99
+ </svg>
100
+ {/if}
81
101
  </div>
82
102
  </div>
83
103
  </div>
84
104
  </label>
105
+
106
+ <style>
107
+ .label-switch {
108
+ display: flex;
109
+ align-items: center;
110
+ column-gap: 7px;
111
+ cursor: pointer;
112
+ }
113
+
114
+ .label-switch.full-width {
115
+ justify-content: space-between;
116
+ width: 100%;
117
+ }
118
+ .switch {
119
+ position: relative;
120
+ border-radius: 1000px;
121
+ background-color: var(--bg-2);
122
+ transition: background-color 0.2s ease-out;
123
+ cursor: pointer;
124
+ transition-property: transform, opacity, background-color;
125
+ transition-duration: 0.2s;
126
+ transition-timing-function: ease-out;
127
+ }
128
+
129
+ .switch:active {
130
+ transform: scale(0.95);
131
+ opacity: 0.8;
132
+ }
133
+
134
+ .switch:hover:not(.disabled) {
135
+ background-color: var(--bg-3);
136
+ }
137
+ .switch .head {
138
+ border-radius: 1000px;
139
+ background-color: var(--white);
140
+ transform: translateX(2px) translateY(2px);
141
+ transition: transform 0.2s ease-out;
142
+ z-index: 2;
143
+ position: relative;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ padding: 5px;
148
+ }
149
+ .switch .head svg {
150
+ width: 100%;
151
+ height: 100%;
152
+ flex-shrink: 0;
153
+ }
154
+ .switch .head svg path {
155
+ fill: var(--red);
156
+ }
157
+ .switch.active {
158
+ background-color: var(--accent) !important;
159
+ }
160
+ .switch .state {
161
+ position: absolute;
162
+ top: 0;
163
+ left: 0;
164
+ width: 100%;
165
+ height: 100%;
166
+ display: flex;
167
+ justify-content: space-between;
168
+ user-select: none;
169
+ pointer-events: none;
170
+ z-index: 1;
171
+ }
172
+ .switch .state .active {
173
+ width: var(--size);
174
+ height: var(--size);
175
+ padding: 4px;
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ color: var(--font-3);
180
+ transform: scale(0.6) translateX(5px);
181
+ opacity: 0;
182
+ transition-property: transform, opacity;
183
+ transition-duration: 0.2s;
184
+ transition-timing-function: ease-out;
185
+ }
186
+ .switch .state .active svg {
187
+ width: 100%;
188
+ height: 100%;
189
+ flex-shrink: 0;
190
+ }
191
+ .switch.active .state .active {
192
+ transform: scale(1);
193
+ opacity: 1;
194
+ }
195
+ .switch.active .state .active * {
196
+ color: var(--white);
197
+ fill: var(--white);
198
+ }
199
+ .switch .state .not-active {
200
+ width: var(--size);
201
+ height: var(--size);
202
+ padding: 4px;
203
+ display: flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ color: var(--font-3);
207
+ transform: scale(0.6) translateX(-5px);
208
+ opacity: 0;
209
+ transition-property: transform, opacity;
210
+ transition-duration: 0.2s;
211
+ transition-timing-function: ease-out;
212
+ }
213
+ .switch .state .not-active svg {
214
+ width: 100%;
215
+ height: 100%;
216
+ flex-shrink: 0;
217
+ }
218
+ .switch:not(.active) .state .not-active {
219
+ transform: scale(1);
220
+ opacity: 1;
221
+ }
222
+ .switch:not(.active) .state .not-active * {
223
+ color: var(--font-1);
224
+ fill: var(--font-1);
225
+ }
226
+ .label-switch:has(.switch.disabled),
227
+ .switch.disabled {
228
+ opacity: 0.9;
229
+ cursor: not-allowed;
230
+ }
231
+ </style>
@@ -0,0 +1,34 @@
1
+ <script>
2
+ import Button from '@hamzus-ui/Button/Button.svelte';
3
+ import { onMount } from 'svelte';
4
+ export let activeButton = null;
5
+ export let link = null;
6
+ export let variant = 'ghost';
7
+ export let style = "flex-shrink:0;{link.active ? activeStyle : ''}";
8
+ export let label = 'exemple';
9
+ export let onClick = (link) => {};
10
+
11
+ let el;
12
+
13
+ onMount(() => {
14
+ if (link.active) {
15
+ activeButton = el;
16
+ }
17
+ });
18
+
19
+ function handleClick() {
20
+ activeButton = el;
21
+ onClick(link);
22
+ }
23
+ </script>
24
+
25
+ <div bind:this={el} class="active">
26
+ <Button {variant} {style} {label} onClick={handleClick} />
27
+ </div>
28
+
29
+ <style>
30
+ .active {
31
+ all: unset;
32
+ min-width: max-content;
33
+ }
34
+ </style>
@@ -7,6 +7,7 @@
7
7
  import Button from '@hamzus-ui/Button/Button.svelte';
8
8
 
9
9
  import { page } from '$app/stores';
10
+ import TabButton from './TabButton.svelte';
10
11
 
11
12
  let activeButton = null;
12
13
 
@@ -30,7 +31,7 @@
30
31
  <div class="tabs" style="--left:{left}px;--width:{width}px;">
31
32
  {#each links as link}
32
33
  {#if link.label}
33
- {#if link.active}
34
+ <!-- {#if link.active}
34
35
  <div bind:this={activeButton} class="active">
35
36
  <Button
36
37
  variant="ghost"
@@ -50,7 +51,17 @@
50
51
  handleClick(link);
51
52
  }}
52
53
  ></Button>
53
- {/if}
54
+ {/if} -->
55
+ <TabButton
56
+ bind:activeButton
57
+ link={link}
58
+ variant="ghost"
59
+ style="flex-shrink:0;{link.active ? activeStyle : ''}"
60
+ label={link.label}
61
+ onClick={() => {
62
+ handleClick(link);
63
+ }}
64
+ ></TabButton>
54
65
  <span class="active-line"></span>
55
66
  {/if}
56
67
  {/each}
@@ -0,0 +1,105 @@
1
+ <script>
2
+ export let name = '';
3
+ export let label = '';
4
+ export let variant = 'default';
5
+ export let value = '';
6
+ export let onChange = undefined;
7
+ export let minHeight = '200px';
8
+ export let style = '';
9
+ export let maxChar = null;
10
+
11
+ $: {
12
+ if (maxChar && value.length > maxChar) {
13
+ value = value.slice(0, maxChar);
14
+ }
15
+ }
16
+
17
+ function handleChange(event) {
18
+ value = event.target.value;
19
+
20
+ if (onChange !== undefined) {
21
+ onChange(value);
22
+ }
23
+ }
24
+ </script>
25
+
26
+ <label class="parent-text-area {variant}">
27
+ <h5 class="label">{label}</h5>
28
+ <textarea
29
+ on:input={handleChange}
30
+ {...$$restProps}
31
+ style="--min-height:{minHeight};{style}"
32
+ class="text-area p"
33
+ {name}
34
+ bind:value
35
+ ></textarea>
36
+ {#if maxChar !== null}
37
+ <h5 class="max-char">{value.length}/{maxChar}</h5>
38
+ {/if}
39
+ </label>
40
+
41
+ <style>
42
+ .parent-text-area {
43
+ display: flex;
44
+ width: 100%;
45
+ flex-direction: column;
46
+ row-gap: var(--pad-s);
47
+ position: relative;
48
+ }
49
+
50
+ .text-area {
51
+ padding: var(--pad-m);
52
+ resize: vertical;
53
+ white-space: pre-wrap;
54
+ min-height: var(--min-height);
55
+ }
56
+
57
+ .max-char {
58
+ position: absolute;
59
+ top: 0;
60
+ right: var(--pad-m);
61
+ color: var(--accent);
62
+ }
63
+
64
+ .parent-text-area.collapse .max-char {
65
+ top: var(--pad-m);
66
+ }
67
+
68
+ .parent-text-area.collapse {
69
+ border: 2px solid var(--bg-2);
70
+ border-radius: var(--radius-m);
71
+ background-color: var(--bg-2);
72
+ padding: calc(var(--pad-m) * 2 + 15px) 0 0 0;
73
+ white-space: pre-wrap;
74
+ position: relative;
75
+ }
76
+ .parent-text-area.collapse > .label {
77
+ position: absolute;
78
+ top: var(--pad-m);
79
+ left: var(--pad-m);
80
+ }
81
+ .parent-text-area.collapse:hover {
82
+ background-color: var(--bg-3);
83
+ }
84
+ .parent-text-area.collapse:has(.text-area:focus) {
85
+ background-color: var(--bg-1);
86
+ }
87
+ .parent-text-area.collapse:has(.text-area:user-invalid) {
88
+ border: 2px solid var(--red);
89
+ }
90
+
91
+ .parent-text-area:not(.collapse) .text-area {
92
+ border: 2px solid var(--bg-2);
93
+ border-radius: var(--radius-m);
94
+ background-color: var(--bg-2);
95
+ }
96
+ .parent-text-area:not(.collapse) .text-area:hover {
97
+ background-color: var(--bg-3);
98
+ }
99
+ .parent-text-area:not(.collapse) .text-area:focus {
100
+ background-color: var(--bg-1);
101
+ }
102
+ .parent-text-area:not(.collapse) .text-area:user-invalid {
103
+ border: 2px solid var(--red);
104
+ }
105
+ </style>
@@ -1,3 +1,92 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap');
2
+
3
+ /* variable */
4
+
5
+ :root {
6
+ /* palet */
7
+ --green: #2fcc5c;
8
+ --green-b: #80f8a233;
9
+ --red: #cc3737;
10
+ --red-b: #e1737328;
11
+ --blue: #1459C1;
12
+ --blue-b: #1459c136;
13
+ --orange: #e0a21d;
14
+ --orange-b: #e0a21d3d;
15
+ --mauve: #7342FF;
16
+ --mauve-b: #7442ff31;
17
+ --yellow: #d8b816;
18
+ --yellow-b: #FFD60033;
19
+ --violet: #FA8DE2;
20
+ --violet-b: #fa8de22d;
21
+ --white: #F6F6F6;
22
+ --white-b: #ffffff4d;
23
+ --white-2: #d6dedf;
24
+ /* font color */
25
+ --font-1: #121212;
26
+ --font-2: #666666;
27
+ --font-3: #93939B;
28
+ /* background */
29
+ --bg-1: #F6F6F6;
30
+ --bg-2: #dddddd;
31
+ --bg-3: #bebebe;
32
+ --bg-blur: #b3b3b334;
33
+ /* stroke color */
34
+ --stroke: #C3CDD2;
35
+ /* default accent */
36
+ --accent: var(--blue);
37
+ --accent-b: var(--blue-b);
38
+ /* box-shadow */
39
+ --box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
40
+ /* Valeur par défaut du curseur */
41
+ --default-cursor: initial;
42
+ /* radius */
43
+ --radius-xs: 3px;
44
+ --radius-s: 5px;
45
+ --radius-m: 8px;
46
+ --radius-l: 10px;
47
+ --radius-xl: 12px;
48
+ --radius-xxl: 16px;
49
+ /* padding */
50
+ --pad-xs: 3px;
51
+ --pad-s: 5px;
52
+ --pad-m: 7px;
53
+ --pad-l: 9px;
54
+ --pad-xl: 12px;
55
+ --pad-xxl: 16px;
56
+ /* gradient */
57
+ --ripple-gradient:radial-gradient(#ffffff31, #ffffff9a);
58
+
59
+ }
60
+
61
+ @media (prefers-color-scheme: dark) {
62
+ :root {
63
+ /* font color */
64
+ --font-1: #ECEBFF;
65
+ --font-2: #899098;
66
+ --font-3: #454545;
67
+ /* background */
68
+ --bg-1: #161616;
69
+ --bg-2: #1F1F1F;
70
+ --bg-3: #292929;
71
+ --bg-blur: #03030334;
72
+ /* stroke color */
73
+ --stroke: #2A2C32;
74
+ /* box-shadow */
75
+ --box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px;
76
+ /* gradient */
77
+ --ripple-gradient:radial-gradient(#ffffff31, #ffffff9a);
78
+ }
79
+ }
80
+
81
+ @media (prefers-color-scheme: dark) {
82
+ html {
83
+ color-scheme: dark;
84
+ background-color: var(--bg-1);
85
+ }
86
+ }
87
+
88
+ /* desable global style */
89
+
1
90
  * {
2
91
  box-sizing: border-box;
3
92
  padding: 0;
@@ -35,3 +124,74 @@ input, textarea {
35
124
  .force-cursor * {
36
125
  cursor: var(--default-cursor) !important;
37
126
  }
127
+
128
+ /* font */
129
+
130
+ :root {
131
+ /* text size */
132
+ --text-1: 70px;
133
+ --text-2: 24px;
134
+ --text-3: 20px;
135
+ --text-4: 16px;
136
+ --text-5: 14px;
137
+ --text-6: 12px;
138
+ --text-p: 16px;
139
+ }
140
+
141
+ .h1, h1 {
142
+ font-size: var(--text-1);
143
+ font-family: 'Geist', 'Inter', sans-serif;
144
+ font-weight: bold;
145
+ color: var(--font-1);
146
+ }
147
+
148
+ .h2, h2 {
149
+ font-size: var(--text-2);
150
+ line-height: 2rem;
151
+ font-family: 'Geist', 'Inter', sans-serif;
152
+ font-weight: bold;
153
+ color: var(--font-1);
154
+ }
155
+
156
+ .h3, h3 {
157
+ font-size: var(--text-3);
158
+ line-height: 1.75rem;
159
+ font-family: 'Geist', 'Inter', sans-serif;
160
+ font-weight: bold;
161
+ color: var(--font-1);
162
+ }
163
+
164
+ .h4, h4 {
165
+ font-size: var(--text-4);
166
+ line-height: 1.5rem;
167
+ font-family: 'Geist', 'Inter', sans-serif;
168
+ font-weight: 500;
169
+ color: var(--font-2);
170
+ }
171
+
172
+ .h5, h5 {
173
+ font-size: var(--text-5);
174
+ line-height: 1.25rem;
175
+ font-family: 'Geist', 'Inter', sans-serif;
176
+ font-weight: 400;
177
+ color: var(--font-2);
178
+ }
179
+
180
+ .h6, h6 {
181
+ font-size: var(--text-6);
182
+ line-height: 1rem;
183
+ font-family: 'Geist', 'Inter', sans-serif;
184
+ font-weight: 300;
185
+ color: var(--font-1);
186
+ }
187
+
188
+ .p, p {
189
+ font-size: var(--text-p);
190
+ font-family: 'Geist', 'Inter', sans-serif;
191
+ font-weight: 300;
192
+ color: var(--font-2);
193
+ }
194
+
195
+ .mono {
196
+ font-family:"Geist Mono", 'Inter', sans-serif;
197
+ }
@@ -1,68 +0,0 @@
1
- .checkbox-label{
2
- display: flex;
3
- align-items: center;
4
- column-gap: 7px;
5
- cursor: pointer;
6
- user-select: none;
7
- }
8
- .checkbox-label.full-width{
9
- width: 100%;
10
- flex-direction: row-reverse;
11
- justify-content: start;
12
- }
13
- .checkbox-box{
14
- width: 22px;
15
- height: 22px;
16
- display: flex;
17
- flex-shrink: 0;
18
- border-radius: var(--radius-m);
19
- border: 2px solid var(--stroke);
20
- position: relative;
21
- cursor: pointer;
22
- transition: background-color .2s ease-out;
23
- }
24
- .checkbox-box:hover{
25
- background-color: var(--bg-2);
26
- }
27
- .checkbox-box svg {
28
- position: absolute;
29
- width: 70%;
30
- height: auto;
31
- left: 50%;
32
- top: 50%;
33
- transform: translate(-50%, -50%) scale(.6);
34
- user-select: none;
35
- pointer-events: none;
36
- transition-property: transform;
37
- transition-duration: .2s;
38
- transition-timing-function: ease-out;
39
- }
40
- .checkbox-box svg polyline{fill: none;
41
- stroke: #FFF;
42
- stroke-width: 2;
43
- stroke-linecap: round;
44
- stroke-linejoin: round;
45
- stroke-dasharray: 50px;
46
- stroke-dashoffset: 50px;
47
- transition: stroke-dashoffset .2s ease-out;
48
- }
49
-
50
- .checkbox-box:has(input:checked){
51
- background-color: var(--accent);
52
- border: 2px solid var(--accent);
53
- }
54
- .checkbox-box:has(input:checked) svg{
55
- user-select: initial;
56
- pointer-events: initial;
57
- transform: translate(-50%, -50%) scale(1);
58
- }
59
- .checkbox-box:has(input:checked) svg polyline{
60
- stroke-dashoffset: 0;
61
- }
62
- .checkbox-label.disabled {
63
- opacity: .9;
64
- cursor: not-allowed;
65
- }
66
- .checkbox-label.disabled .checkbox-box {
67
- cursor: not-allowed;
68
- }
@@ -1,120 +0,0 @@
1
- .label-switch{
2
- display: flex;
3
- align-items: center;
4
- column-gap: 7px;
5
- cursor: pointer;
6
- }
7
- .switch{
8
- position: relative;
9
- border-radius: var(--radius-xxl);
10
- background-color: var(--bg-2);
11
- transition: background-color .2s ease-out;
12
- cursor: pointer;
13
- transition-property:transform, opacity, background-color ;
14
- transition-duration: .2s;
15
- transition-timing-function: ease-out;
16
- }
17
-
18
- .switch:active{
19
- transform: scale(.95);
20
- opacity: .8;
21
- }
22
-
23
- .switch:hover:not(.disabled){
24
- background-color: var(--bg-3);
25
- }
26
- .switch .head{
27
- border-radius: var(--radius-xl);
28
- background-color: var(--white);
29
- transform: translateX(2px) translateY(2px);
30
- transition: transform .2s ease-out;
31
- z-index: 2;
32
- position: relative;
33
- display: flex;
34
- align-items: center;
35
- justify-content: center;
36
- padding: 5px;
37
-
38
- }
39
- .switch .head svg{
40
- width: 100%;
41
- height: 100%;
42
- flex-shrink: 0;
43
- }
44
- .switch .head svg path{
45
- fill: var(--red);
46
- }
47
- .switch.active{
48
- background-color: var(--accent) !important;
49
- }
50
- .switch .state{
51
- position: absolute;
52
- top: 0;
53
- left: 0;
54
- width: 100%;
55
- height: 100%;
56
- display: flex;
57
- justify-content: space-between;
58
- user-select: none;
59
- pointer-events: none;
60
- z-index: 1;
61
- }
62
- .switch .state .active{
63
- width: var(--size);
64
- height: var(--size);
65
- padding: 4px;
66
- display:flex;
67
- align-items:center;
68
- justify-content:center;
69
- color: var(--font-3);
70
- transform: scale(.6) translateX(5px);
71
- opacity: 0;
72
- transition-property:transform, opacity ;
73
- transition-duration: .2s;
74
- transition-timing-function: ease-out;
75
- }
76
- .switch .state .active svg {
77
- width: 100%;
78
- height: 100%;
79
- flex-shrink: 0;
80
- }
81
- .switch.active .state .active{
82
- transform: scale(1);
83
- opacity: 1;
84
- }
85
- .switch.active .state .active *{
86
- color: var(--white);
87
- fill: var(--white);
88
- }
89
- .switch .state .not-active{
90
- width: var(--size);
91
- height: var(--size);
92
- padding: 4px;
93
- display:flex;
94
- align-items:center;
95
- justify-content:center;
96
- color: var(--font-3);
97
- transform: scale(.6) translateX(-5px);
98
- opacity: 0;
99
- transition-property:transform, opacity ;
100
- transition-duration: .2s;
101
- transition-timing-function: ease-out;
102
-
103
- }
104
- .switch .state .not-active svg {
105
- width: 100%;
106
- height: 100%;
107
- flex-shrink: 0;
108
- }
109
- .switch:not(.active) .state .not-active{
110
- transform: scale(1);
111
- opacity: 1;
112
- }
113
- .switch:not(.active) .state .not-active *{
114
- color: var(--font-1);
115
- fill: var(--font-1);
116
- }
117
- .label-switch:has(.switch.disabled), .switch.disabled{
118
- opacity: .9;
119
- cursor: not-allowed;
120
- }
@@ -1,71 +0,0 @@
1
- /* font */
2
- @import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&display=swap');
3
- /* font */
4
- :root {
5
- /* text size */
6
- --text-1: 70px;
7
- --text-2: 24px;
8
- --text-3: 20px;
9
- --text-4: 16px;
10
- --text-5: 14px;
11
- --text-6: 12px;
12
- --text-p: 16px;
13
- }
14
-
15
- .h1, h1 {
16
- font-size: var(--text-1);
17
- font-family: 'Geist', 'Inter', sans-serif;
18
- font-weight: bold;
19
- color: var(--font-1);
20
- }
21
-
22
- .h2, h2 {
23
- font-size: var(--text-2);
24
- line-height: 2rem;
25
- font-family: 'Geist', 'Inter', sans-serif;
26
- font-weight: bold;
27
- color: var(--font-1);
28
- }
29
-
30
- .h3, h3 {
31
- font-size: var(--text-3);
32
- line-height: 1.75rem;
33
- font-family: 'Geist', 'Inter', sans-serif;
34
- font-weight: bold;
35
- color: var(--font-1);
36
- }
37
-
38
- .h4, h4 {
39
- font-size: var(--text-4);
40
- line-height: 1.5rem;
41
- font-family: 'Geist', 'Inter', sans-serif;
42
- font-weight: 500;
43
- color: var(--font-2);
44
- }
45
-
46
- .h5, h5 {
47
- font-size: var(--text-5);
48
- line-height: 1.25rem;
49
- font-family: 'Geist', 'Inter', sans-serif;
50
- font-weight: 400;
51
- color: var(--font-2);
52
- }
53
-
54
- .h6, h6 {
55
- font-size: var(--text-6);
56
- line-height: 1rem;
57
- font-family: 'Geist', 'Inter', sans-serif;
58
- font-weight: 300;
59
- color: var(--font-1);
60
- }
61
-
62
- .p, p {
63
- font-size: var(--text-p);
64
- font-family: 'Geist', 'Inter', sans-serif;
65
- font-weight: 300;
66
- color: var(--font-2);
67
- }
68
-
69
- .mono {
70
- font-family:"Geist Mono", 'Inter', sans-serif;
71
- }
@@ -1,82 +0,0 @@
1
- :root {
2
- /* palet */
3
- --green: #2fcc5c;
4
- --green-b: #80f8a233;
5
- --red: #cc3737;
6
- --red-b: #e1737328;
7
- --blue: #1459C1;
8
- --blue-b: #1459c136;
9
- --orange: #e0a21d;
10
- --orange-b: #e0a21d3d;
11
- --mauve: #7342FF;
12
- --mauve-b: #7442ff31;
13
- --yellow: #d8b816;
14
- --yellow-b: #FFD60033;
15
- --violet: #FA8DE2;
16
- --violet-b: #fa8de22d;
17
- --white: #F6F6F6;
18
- --white-b: #ffffff4d;
19
- --white-2: #d6dedf;
20
- /* font color */
21
- --font-1: #121212;
22
- --font-2: #666666;
23
- --font-3: #93939B;
24
- /* background */
25
- --bg-1: #F6F6F6;
26
- --bg-2: #dddddd;
27
- --bg-3: #bebebe;
28
- --bg-blur: #b3b3b334;
29
- /* stroke color */
30
- --stroke: #C3CDD2;
31
- /* default accent */
32
- --accent: var(--blue);
33
- --accent-b: var(--blue-b);
34
- /* box-shadow */
35
- --box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
36
- /* Valeur par défaut du curseur */
37
- --default-cursor: initial;
38
- /* radius */
39
- --radius-xs: 3px;
40
- --radius-s: 5px;
41
- --radius-m: 8px;
42
- --radius-l: 10px;
43
- --radius-xl: 12px;
44
- --radius-xxl: 16px;
45
- /* padding */
46
- --pad-xs: 3px;
47
- --pad-s: 5px;
48
- --pad-m: 7px;
49
- --pad-l: 9px;
50
- --pad-xl: 12px;
51
- --pad-xxl: 16px;
52
- /* gradient */
53
- --ripple-gradient:radial-gradient(#ffffff31, #ffffff9a);
54
-
55
- }
56
-
57
- @media (prefers-color-scheme: dark) {
58
- :root {
59
- /* font color */
60
- --font-1: #ECEBFF;
61
- --font-2: #899098;
62
- --font-3: #454545;
63
- /* background */
64
- --bg-1: #161616;
65
- --bg-2: #1F1F1F;
66
- --bg-3: #292929;
67
- --bg-blur: #03030334;
68
- /* stroke color */
69
- --stroke: #2A2C32;
70
- /* box-shadow */
71
- --box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px;
72
- /* gradient */
73
- --ripple-gradient:radial-gradient(#ffffff31, #ffffff9a);
74
- }
75
- }
76
-
77
- @media (prefers-color-scheme: dark) {
78
- html {
79
- color-scheme: dark;
80
- background-color: var(--bg-1);
81
- }
82
- }