hamzus-ui 0.0.50 → 0.0.51

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hamzus-ui",
3
- "version": "0.0.50",
3
+ "version": "0.0.51",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "svelte": "index.js",
@@ -0,0 +1,75 @@
1
+ <script>
2
+ import { blur, slide } from "svelte/transition";
3
+ import Portal from "../Portal/Portal.svelte";
4
+ import IconButton from "../IconButton/IconButton.svelte";
5
+
6
+ export let src = ""
7
+ export let alt = ""
8
+
9
+ let preview = false
10
+
11
+ function handleDisplay() {
12
+ preview = true
13
+ }
14
+
15
+ function handleExit() {
16
+ preview = false
17
+ }
18
+ </script>
19
+
20
+ {#if preview}
21
+ <Portal target="body">
22
+ <div on:click={handleExit} transition:blur class="image-preview">
23
+ <div class="image">
24
+ <div class="close">
25
+ <IconButton variant="secondary">
26
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
27
+ <path d="M16.7735 8.28772L8.28826 16.773C7.99834 17.0629 7.51751 17.0629 7.2276 16.773C6.93768 16.4831 6.93768 16.0023 7.2276 15.7123L15.7129 7.22706C16.0028 6.93715 16.4836 6.93715 16.7735 7.22706C17.0635 7.51698 17.0635 7.99781 16.7735 8.28772Z" fill="#292D32"/>
28
+ <path d="M16.7735 16.7729C16.4836 17.0628 16.0028 17.0628 15.7129 16.7729L7.2276 8.28765C6.93768 7.99774 6.93768 7.51691 7.2276 7.22699C7.51751 6.93708 7.99834 6.93708 8.28826 7.22699L16.7735 15.7123C17.0635 16.0022 17.0635 16.483 16.7735 16.7729Z" fill="#292D32"/>
29
+ </svg>
30
+
31
+ </IconButton>
32
+ </div>
33
+ <img transition:slide {src} {alt} {...$$restProps}>
34
+ </div>
35
+ </div>
36
+ </Portal>
37
+ {/if}
38
+
39
+ <img {src} {alt} {...$$restProps} on:click={handleDisplay}>
40
+
41
+ <style>
42
+ .image-preview {
43
+ position: fixed;
44
+ z-index: 1000;
45
+ top: 0;
46
+ left: 0;
47
+ width: 100%;
48
+ height: 100%;
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ background-color: var(--bg-blur);
53
+ backdrop-filter: blur(20px);
54
+ -webkit-backdrop-filter: blur(20px);
55
+ padding: var(--pad-m);
56
+ }
57
+ .image-preview .close {
58
+ position: absolute;
59
+ top: var(--pad-m);
60
+ right: var(--pad-m);
61
+ }
62
+
63
+ .image-preview > .image {
64
+ width: 100%;
65
+ height: 100%;
66
+ border-radius: var(--radius-m);
67
+ overflow: hidden;
68
+ object-fit: contain;
69
+ }
70
+ .image-preview > .image > img {
71
+ width: 100%;
72
+ height: 100%;
73
+ object-fit: contain;
74
+ }
75
+ </style>
@@ -0,0 +1,256 @@
1
+ <script>
2
+ import Image from '../Image/Image.svelte';
3
+ import AlertCard from '../AlertCard/AlertCard.svelte';
4
+ import Button from '../Button/Button.svelte';
5
+ import IconButton from '../IconButton/IconButton.svelte';
6
+ import { createEventDispatcher } from 'svelte';
7
+
8
+ export let label = 'Fichier';
9
+ export let buttonLabel = 'ajouter un fichier';
10
+ export let multiple = false;
11
+ export let name = 'file';
12
+ export let accept = null;
13
+ export let required = false;
14
+ export let actualFiles = '';
15
+
16
+ const acceptData = {
17
+ image: '.jpg, .jpeg, .png, .gif',
18
+ pdf: 'application/pdf'
19
+ };
20
+ const acceptText = {
21
+ image: '(jpg, jpeg, png, gif)',
22
+ pdf: '(pdf)'
23
+ };
24
+
25
+ let inputRef;
26
+ let files = [];
27
+
28
+ function handleFileChange(event) {
29
+ let newFiles = Array.from(event.target.files);
30
+ // Si on est en mode multiple, on ajoute les nouveaux fichiers
31
+ if (multiple) {
32
+ // verifier les doublons
33
+ newFiles = newFiles.filter(
34
+ (newFile) => !files.some((existingFile) => existingFile.name === newFile.name)
35
+ );
36
+ files = [...files, ...newFiles];
37
+ } else {
38
+ files = newFiles;
39
+ }
40
+
41
+ const dt = new DataTransfer();
42
+ Array.from(files).forEach((file, i) => {
43
+ dt.items.add(file);
44
+ });
45
+ inputRef.files = dt.files;
46
+ console.log(inputRef.files);
47
+ }
48
+
49
+ function handleDelete(fileName) {
50
+ const newFiles = files.filter((file) => file.name !== fileName);
51
+
52
+ files = [...newFiles];
53
+
54
+ const dt = new DataTransfer();
55
+ Array.from(files).forEach((file, i) => {
56
+ dt.items.add(file);
57
+ });
58
+ inputRef.files = dt.files;
59
+ }
60
+
61
+ function triggerInput() {
62
+ inputRef.click();
63
+ }
64
+ </script>
65
+
66
+ <div class="file-input">
67
+ <div class="title">
68
+ <h4>
69
+ {label}
70
+ {#if required}
71
+ <strong style="color:var(--red);">*</strong>
72
+ {/if}
73
+ {#if accept && acceptText[accept]}
74
+ <strong style="color:var(--accent);">{acceptText[accept]}</strong>
75
+ {/if}
76
+ </h4>
77
+
78
+ <Button onClick={triggerInput} label={buttonLabel}></Button>
79
+ </div>
80
+ {#if actualFiles.length > 0 && files.length <= 0}
81
+ {#each actualFiles as actualFile}
82
+ <input type="hidden" name="{name}ActualImage" value={actualFile.value} />
83
+ {/each}
84
+ {/if}
85
+ <input
86
+ class="file-input-hidden"
87
+ bind:this={inputRef}
88
+ type="file"
89
+ {name}
90
+ {multiple}
91
+ required={actualFiles.length > 0 ? false : required}
92
+ on:change={handleFileChange}
93
+ accept={acceptData[accept]}
94
+ />
95
+
96
+ {#if files.length > 0}
97
+ <div class="file-list">
98
+ <h4>Fichier selectionné:</h4>
99
+ {#each files as file}
100
+ <div class="file-item">
101
+ <h4>{file.name}</h4>
102
+ <IconButton
103
+ onClick={() => {
104
+ handleDelete(file.name);
105
+ }}
106
+ variant="ghost"
107
+ >
108
+ <svg
109
+ width="25"
110
+ height="25"
111
+ viewBox="0 0 25 25"
112
+ fill="none"
113
+ xmlns="http://www.w3.org/2000/svg"
114
+ >
115
+ <path
116
+ d="M8.02188 18.1153C7.72277 18.1153 7.42365 18.0051 7.1875 17.7689C6.73096 17.3124 6.73096 16.5567 7.1875 16.1002L16.0981 7.18964C16.5546 6.73309 17.3103 6.73309 17.7668 7.18964C18.2234 7.64619 18.2234 8.40185 17.7668 8.8584L8.85626 17.7689C8.63586 18.0051 8.321 18.1153 8.02188 18.1153Z"
117
+ fill="black"
118
+ />
119
+ <path
120
+ d="M16.9324 18.1153C16.6333 18.1153 16.3342 18.0051 16.0981 17.7689L7.1875 8.8584C6.73096 8.40185 6.73096 7.64619 7.1875 7.18964C7.64405 6.73309 8.39972 6.73309 8.85626 7.18964L17.7668 16.1002C18.2234 16.5567 18.2234 17.3124 17.7668 17.7689C17.5307 18.0051 17.2315 18.1153 16.9324 18.1153Z"
121
+ fill="black"
122
+ />
123
+ </svg>
124
+ </IconButton>
125
+ </div>
126
+ {/each}
127
+ </div>
128
+ {:else if actualFiles.length > 0}
129
+ <AlertCard
130
+ >Ajouter une image et enregistrer aura pour conséquence de remplacer les images suivantes par
131
+ ceux que vous inséré !</AlertCard
132
+ >
133
+ <div class="previews">
134
+ {#each actualFiles as actualFile}
135
+ {#if accept === "image"}
136
+ <Image src={actualFile.src}></Image>
137
+ {:else}
138
+ <div class="pdf">
139
+ <h4>{actualFile.name}</h4>
140
+ </div>
141
+ {/if}
142
+ {/each}
143
+ </div>
144
+ {:else}
145
+ <div class="no-file">
146
+ <svg
147
+ width="24"
148
+ height="24"
149
+ viewBox="0 0 24 24"
150
+ fill="none"
151
+ xmlns="http://www.w3.org/2000/svg"
152
+ >
153
+ <path
154
+ opacity="0.4"
155
+ d="M20.5 10.19H17.61C15.24 10.19 13.31 8.26 13.31 5.89V3C13.31 2.45 12.86 2 12.31 2H8.07C4.99 2 2.5 4 2.5 7.57V16.43C2.5 20 4.99 22 8.07 22H15.93C19.01 22 21.5 20 21.5 16.43V11.19C21.5 10.64 21.05 10.19 20.5 10.19Z"
156
+ fill="#007AFF"
157
+ />
158
+ <path
159
+ d="M15.7997 2.20999C15.3897 1.79999 14.6797 2.07999 14.6797 2.64999V6.13999C14.6797 7.59999 15.9197 8.80999 17.4297 8.80999C18.3797 8.81999 19.6997 8.81999 20.8297 8.81999C21.3997 8.81999 21.6997 8.14999 21.2997 7.74999C19.8597 6.29999 17.2797 3.68999 15.7997 2.20999Z"
160
+ fill="#007AFF"
161
+ />
162
+ <path
163
+ d="M12.2795 14.72C11.9895 14.43 11.5095 14.43 11.2195 14.72L10.4995 15.44V11.25C10.4995 10.84 10.1595 10.5 9.74945 10.5C9.33945 10.5 8.99945 10.84 8.99945 11.25V15.44L8.27945 14.72C7.98945 14.43 7.50945 14.43 7.21945 14.72C6.92945 15.01 6.92945 15.49 7.21945 15.78L9.21945 17.78C9.22945 17.79 9.23945 17.79 9.23945 17.8C9.29945 17.86 9.37945 17.91 9.45945 17.95C9.55945 17.98 9.64945 18 9.74945 18C9.84945 18 9.93945 17.98 10.0295 17.94C10.1195 17.9 10.1995 17.85 10.2795 17.78L12.2795 15.78C12.5695 15.49 12.5695 15.01 12.2795 14.72Z"
164
+ fill="#007AFF"
165
+ />
166
+ </svg>
167
+
168
+ <h3>Aucun fichier ajouté !</h3>
169
+ <p>Cliqué sur "{buttonLabel}" pour ajouter un fichier.</p>
170
+ {#if multiple}
171
+ <p>Vous pouvez selectionner plusieurs fichier !</p>
172
+ {/if}
173
+ </div>
174
+ {/if}
175
+ </div>
176
+
177
+ <style>
178
+ .file-input {
179
+ display: flex;
180
+ flex-direction: column;
181
+ padding: var(--pad-m);
182
+ border-radius: var(--radius-xl);
183
+ border: 1px solid var(--stroke);
184
+ row-gap: var(--pad-m);
185
+ }
186
+ .file-input:has(input:user-invalid) {
187
+ border: 1px solid var(--red);
188
+ }
189
+
190
+ .title {
191
+ display: flex;
192
+ justify-content: space-between;
193
+ }
194
+
195
+ .file-input-hidden {
196
+ display: none;
197
+ }
198
+
199
+ .file-list {
200
+ margin-top: 10px;
201
+ display: flex;
202
+ flex-direction: column;
203
+ row-gap: var(--pad-m);
204
+ }
205
+
206
+ .file-item {
207
+ padding: var(--pad-s) var(--pad-l);
208
+ border-radius: var(--radius-m);
209
+ background-color: var(--bg-2);
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: space-between;
213
+ }
214
+
215
+ .no-file {
216
+ display: flex;
217
+ flex-direction: column;
218
+ align-items: center;
219
+ text-align: center;
220
+ row-gap: var(--pad-m);
221
+ padding: var(--pad-m);
222
+ background-color: var(--bg-2);
223
+ border-radius: var(--radius-m);
224
+ }
225
+ .no-file > svg {
226
+ width: 50px;
227
+ height: 50px;
228
+ flex-shrink: 0;
229
+ }
230
+
231
+ .previews {
232
+ display: flex;
233
+ flex-wrap: wrap;
234
+ gap: var(--pad-m);
235
+ }
236
+
237
+ .previews > :global(img) {
238
+ width: min(100%, 100px);
239
+ height: min(100%, 100px);
240
+ }
241
+
242
+ .pdf {
243
+ display: flex;
244
+ align-items: center;
245
+ justify-content: center;
246
+ text-align: center;
247
+ width: min(100%, 100px);
248
+ height: min(100%, 100px);
249
+ aspect-ratio: 1/1;
250
+ border-radius: var(--radius-m);
251
+ background-color: var(--blue-b);
252
+ }
253
+ .pdf > h4 {
254
+ color: var(--blue);
255
+ }
256
+ </style>
@@ -8,11 +8,21 @@
8
8
  $: currentPath = $page.url.pathname;
9
9
 
10
10
 
11
- $: if (currentPath.includes(href)) {
11
+ $: if (checkUrl(currentPath, href)) {
12
12
  active = true
13
13
  }else{
14
14
  active = false
15
15
  }
16
+
17
+ function checkUrl(currentPath, href) {
18
+ // Normalise les chemins (retire slash final sauf pour la racine)
19
+ const normalize = (path) => path.endsWith('/') && path !== '/' ? path.slice(0, -1) : path;
20
+
21
+ const current = normalize(currentPath);
22
+ const target = normalize(href);
23
+
24
+ return current === target || current.startsWith(target + '/');
25
+ }
16
26
  </script>
17
27
 
18
28
  <a {href} class="sidebar-btn" class:active={active}>