hamzus-ui 0.0.100 → 0.0.102

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
@@ -11,6 +11,7 @@ export { default as InfoCard } from "./src/components/hamzus-ui/InfoCard/InfoCar
11
11
  export { default as AlertCard } from "./src/components/hamzus-ui/AlertCard/AlertCard.svelte"
12
12
  export { default as Link } from "./src/components/hamzus-ui/Link/Link.svelte"
13
13
  export { default as Kbd } from "./src/components/hamzus-ui/Kbd/Kbd.svelte"
14
+ export * as Accordion from "./src/components/hamzus-ui/Accordion"
14
15
 
15
16
  // dialog
16
17
  export { toast as toast } from "./src/components/hamzus-ui/Toast/toast.js"
package/index.js CHANGED
@@ -9,12 +9,14 @@ export { default as InfoCard } from "./src/components/hamzus-ui/InfoCard/InfoCar
9
9
  export { default as AlertCard } from "./src/components/hamzus-ui/AlertCard/AlertCard.svelte"
10
10
  export { default as Link } from "./src/components/hamzus-ui/Link/Link.svelte"
11
11
  export { default as Kbd } from "./src/components/hamzus-ui/KBD/KBD.svelte"
12
+ export * as Accordion from "./src/components/hamzus-ui/Accordion"
12
13
  // dialog
13
14
  export { toast as toast } from "./src/components/hamzus-ui/Toast/toast.js"
14
15
  export { default as Dialog } from "./src/components/hamzus-ui/Dialog/Dialog.svelte"
15
16
  // form
16
17
  export { default as Form } from "./src/components/hamzus-ui/Form/Form.svelte"
17
18
  export { default as Input } from "./src/components/hamzus-ui/Input/Input.svelte"
19
+ export { default as InputSelector } from "./src/components/hamzus-ui/InputSelector/InputSelector.svelte"
18
20
  export { default as DatePicker } from "./src/components/hamzus-ui/DatePicker/DatePicker.svelte"
19
21
  export { default as TextArea } from "./src/components/hamzus-ui/TextArea/TextArea.svelte"
20
22
  export { default as Checkbox } from "./src/components/hamzus-ui/Checkboxes/Checkbox/Checkbox.svelte"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hamzus-ui",
3
- "version": "0.0.100",
3
+ "version": "0.0.102",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "svelte": "index.js",
@@ -0,0 +1,33 @@
1
+
2
+ <script>
3
+ import IconButton from "@hamzus-ui/IconButton/IconButton.svelte";
4
+
5
+ export let isOpen
6
+ </script>
7
+
8
+ <div class="accordion-btn {$isOpen ? "open" : ""}">
9
+ <slot/>
10
+ <IconButton variant="ghost">
11
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
12
+ <path d="M11.9995 16.8001C11.2995 16.8001 10.5995 16.5301 10.0695 16.0001L3.54953 9.48014C3.25953 9.19014 3.25953 8.71014 3.54953 8.42014C3.83953 8.13014 4.31953 8.13014 4.60953 8.42014L11.1295 14.9401C11.6095 15.4201 12.3895 15.4201 12.8695 14.9401L19.3895 8.42014C19.6795 8.13014 20.1595 8.13014 20.4495 8.42014C20.7395 8.71014 20.7395 9.19014 20.4495 9.48014L13.9295 16.0001C13.3995 16.5301 12.6995 16.8001 11.9995 16.8001Z" fill="#292D32"/>
13
+ </svg>
14
+ </IconButton>
15
+ </div>
16
+
17
+ <style>
18
+ .accordion-btn{
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: space-between;
22
+ width: 100%;
23
+ padding: var(--pad-m) 0;
24
+ cursor: pointer;
25
+ }
26
+ .accordion-btn svg {
27
+ transition: transform .1s ease-in-out;
28
+ transform: rotate(90deg);
29
+ }
30
+ .accordion-btn.open svg {
31
+ transform: rotate(0deg);
32
+ }
33
+ </style>
@@ -0,0 +1,23 @@
1
+
2
+ <script>
3
+ import { onMount } from "svelte";
4
+
5
+ export let isOpen
6
+
7
+ let element
8
+ </script>
9
+
10
+ <div bind:this={element} style="--height:{element?.scrollHeight ?? "0"}px;" class="content {$isOpen ? "open" : ""}">
11
+ <slot/>
12
+ </div>
13
+
14
+ <style>
15
+ .content {
16
+ max-height: 0px;
17
+ overflow: hidden;
18
+ transition: max-height .2s ease-in;
19
+ }
20
+ .content.open {
21
+ max-height: var(--height);
22
+ }
23
+ </style>
@@ -0,0 +1,21 @@
1
+ <script>
2
+ import Trigger from "./Trigger.svelte";
3
+ import { writable } from "svelte/store";
4
+
5
+ export let isOpen = false
6
+
7
+ const isOpenStore = writable(isOpen)
8
+ </script>
9
+
10
+ <div class="root">
11
+ <slot isOpen={isOpenStore}></slot>
12
+ </div>
13
+
14
+
15
+ <style>
16
+ .root {
17
+ display: flex;
18
+ flex-direction: column;
19
+ width: 100%;
20
+ }
21
+ </style>
@@ -0,0 +1,19 @@
1
+ <script>
2
+ import { getContext } from "svelte";
3
+
4
+ export let isOpen // store
5
+
6
+ function handleClick() {
7
+ isOpen.update((value)=>!value)
8
+ }
9
+ </script>
10
+
11
+ <div class="trigger" onclick={handleClick}>
12
+ <slot/>
13
+ </div>
14
+
15
+ <style>
16
+ .trigger {
17
+ display: inline-block;
18
+ }
19
+ </style>
@@ -0,0 +1,4 @@
1
+ export { default as Root } from './Root.svelte';
2
+ export { default as Trigger } from './Trigger.svelte';
3
+ export { default as Content } from './Content.svelte';
4
+ export { default as Button } from './Button.svelte';
@@ -2,9 +2,10 @@
2
2
 
3
3
  export let width = "max-content"
4
4
  export let style;
5
+ export let onScroll = ()=>{};
5
6
  </script>
6
7
 
7
- <div class="content" style="--width:{width};{style}" {...$$restProps}>
8
+ <div class="content" style="--width:{width};{style}" onscroll={onScroll} {...$$restProps}>
8
9
  <slot/>
9
10
  </div>
10
11
 
@@ -19,7 +20,7 @@
19
20
  border: 1px solid var(--bg-3);
20
21
  width: min(100vw, var(--width));
21
22
  max-width: var(--hamzus-max-content-width);
23
+ max-height: var(--hamzus-max-content-height);
22
24
  overflow-x: auto;
23
- max-height: 100vh;
24
25
  }
25
26
  </style>
@@ -54,7 +54,7 @@
54
54
  display: flex;
55
55
  align-items: center;
56
56
  justify-content: center;
57
- padding:var(--pad-s);
57
+ /* padding:2.122%; */
58
58
  border-radius: var(--radius-m);
59
59
  background-color: var(--button-default-bg);
60
60
  color: var(--button-default-color);
@@ -76,8 +76,8 @@
76
76
  color: var(--button-default-color);
77
77
  }
78
78
  .button :global(svg){
79
- height: 100%;
80
- width: 100%;
79
+ height: 66.666%;
80
+ width: 66.666%;
81
81
  flex-shrink: 0;
82
82
  }
83
83
  .button :global(svg > path) {
@@ -0,0 +1,428 @@
1
+ <script>
2
+ // import
3
+
4
+ import IconButton from '../IconButton/IconButton.svelte';
5
+ import Loader from '../LoaderCircle/Loader.svelte';
6
+ import * as DropdownMenu from '@hamzus-ui/DropdownMenu';
7
+ import Button from '@hamzus-ui/Button/Button.svelte';
8
+ // props
9
+ export let getMultipleElement = (search, offset) => {};
10
+ export let getElement = (data) => {};
11
+ export let component = null;
12
+ export let selectionComponent = null;
13
+
14
+ export let limit = 20;
15
+ export let offset = 0;
16
+ export let totalOfRows = 0;
17
+ export let variant = 'default';
18
+ export let className = '';
19
+ export let iconSize = '24px';
20
+ export let label = '';
21
+ export let labelType = 'h5';
22
+ export let name = '';
23
+ export let selection = null;
24
+ export let value = null;
25
+ export let multiple = false;
26
+ export let search = '';
27
+ export let results = [];
28
+ export let onChange = () => {};
29
+ export let disabled = false;
30
+ export let required = false;
31
+ export let style = '';
32
+ export let placeholder = '';
33
+ export let errorMessage = '';
34
+ export let isLoading = false;
35
+ export let isVisible = false;
36
+ export let padding = '3px 10px';
37
+ export let borderRadius = 'var(--radius-m)';
38
+ export let defaultBg = '--bg-2';
39
+ import { onMount } from 'svelte';
40
+
41
+ // local var
42
+ let input;
43
+ let isMounted = false;
44
+
45
+ let openDropdownMenu = false;
46
+ let closeDropdownMenu = false;
47
+
48
+ $: handleChange(search);
49
+
50
+ // fnctions
51
+ function formatInput(inputValue) {
52
+ // verifier que c est un nombre
53
+
54
+ return inputValue;
55
+ }
56
+ async function handleChange(val) {
57
+ if (!isMounted) {
58
+ return;
59
+ }
60
+ console.log(val);
61
+
62
+ // suprimmer les result
63
+ results = [];
64
+ // set l offset a 0
65
+ offset = 0;
66
+
67
+ // faire une nouvelle requete avec la recherche
68
+ const request = await getMultipleElement(val, offset);
69
+ results = request.rows;
70
+ totalOfRows = request.totalOfRows;
71
+ offset += limit;
72
+ }
73
+
74
+ onMount(async () => {
75
+ isMounted = false;
76
+
77
+ // recuperer les resultat
78
+ const request = await getMultipleElement(search, offset);
79
+ results = request.rows;
80
+ totalOfRows = request.totalOfRows;
81
+ offset += limit;
82
+
83
+ // si la valeur est pas set on fais rien
84
+ if (value === null) {
85
+ isMounted = true;
86
+ return;
87
+ }
88
+
89
+ // si l'input est pas multiple on recupere
90
+ if (!multiple) {
91
+ // recuperer les données et set
92
+ const element = await getElement({ id: value });
93
+
94
+ if (!element) {
95
+ isMounted = true;
96
+ return;
97
+ }
98
+ selection = element;
99
+ isMounted = true;
100
+ return;
101
+ }
102
+
103
+ for (const id of value) {
104
+ const element = await getElement({ id: id });
105
+
106
+ selection = [...(selection ?? []), element];
107
+ }
108
+
109
+ isMounted = true;
110
+ });
111
+
112
+ function handleDisplay() {
113
+ isVisible = !isVisible;
114
+ }
115
+
116
+ async function handleSelect(data) {
117
+ // recuperer les details
118
+ const element = await getElement(data);
119
+
120
+ search = '';
121
+ input.focus();
122
+
123
+ if (multiple) {
124
+ // verifier si il existe deja
125
+ let exist = false;
126
+ if (selection !== null) {
127
+ for (const element of selection) {
128
+ if (element.id == data.id) {
129
+ exist = true;
130
+ break;
131
+ }
132
+ }
133
+ }
134
+
135
+ if (exist) {
136
+ return;
137
+ }
138
+
139
+ selection = [...(selection ?? []), element];
140
+ return;
141
+ }
142
+
143
+ selection = element;
144
+ }
145
+ function handleDelete(data) {
146
+ if (!multiple) {
147
+ selection = null;
148
+ return;
149
+ }
150
+
151
+ let newSelection = [];
152
+
153
+ for (const element of selection) {
154
+ if (element.id === data.id) {
155
+ continue;
156
+ }
157
+
158
+ newSelection.push(element);
159
+ }
160
+
161
+ if (newSelection.length === 0) {
162
+ selection = null;
163
+ return;
164
+ }
165
+
166
+ selection = [...newSelection];
167
+ }
168
+
169
+ async function handleLoadMore() {
170
+ const request = await getMultipleElement(search, offset);
171
+ results = [...results, ...request.rows];
172
+ totalOfRows = request.totalOfRows;
173
+ offset += limit;
174
+ }
175
+ </script>
176
+
177
+ <DropdownMenu.Root
178
+ direction="bottom"
179
+ avoidOpening
180
+ bind:forceOpen={openDropdownMenu}
181
+ bind:forceClose={closeDropdownMenu}
182
+ >
183
+ <DropdownMenu.Trigger slot="trigger">
184
+ <div
185
+ class="input-container {variant == 'default' ? variant : ''} {className}"
186
+ {style}
187
+ {...$$restProps}
188
+ >
189
+ <div
190
+ class="input {errorMessage ? ' error' : ''}"
191
+ style="{variant == 'collapse'
192
+ ? `padding:${padding};`
193
+ : ''}--radius:{borderRadius};--default-bg:var({defaultBg});"
194
+ >
195
+ <div class="top-line">
196
+ {#if label}
197
+ <h5 class={labelType}>
198
+ {label}
199
+ {#if required}
200
+ <span class="required">*</span>
201
+ {/if}
202
+ </h5>
203
+ {/if}
204
+ {#if isLoading}
205
+ <Loader isLoading className="input-loader" color="--accent" size="16px" />
206
+ {/if}
207
+ </div>
208
+ <div
209
+ class="input-line"
210
+ style="{variant == 'default' ? `padding:${padding};` : ''}--icon-size:{iconSize};"
211
+ >
212
+ <slot name="startContent" />
213
+ <div class="list">
214
+ {#if selection}
215
+ {#if multiple}
216
+ {#each selection as selectionElement}
217
+ <input type="hidden" name="{name}[]" value={selectionElement.id} />
218
+ <svelte:component
219
+ this={selectionComponent}
220
+ {...selectionElement}
221
+ onClick={handleDelete}
222
+ ></svelte:component>
223
+ {/each}
224
+ {:else}
225
+ <input type="hidden" {name} value={selection.id} />
226
+ <svelte:component this={selectionComponent} {...selection} onClick={handleDelete}
227
+ ></svelte:component>
228
+ {/if}
229
+ {/if}
230
+ <input
231
+ onfocus={() => {
232
+ openDropdownMenu = true;
233
+ }}
234
+ label=""
235
+ onblur={(e) => {
236
+ try {
237
+ if (e.relatedTarget.closest('.content-popover-hamzus')) {
238
+ return;
239
+ }
240
+ closeDropdownMenu = true;
241
+ } catch (error) {}
242
+ }}
243
+ class="h4 search"
244
+ {placeholder}
245
+ bind:value={search}
246
+ bind:this={input}
247
+ {required}
248
+ disabled={isLoading ? true : disabled}
249
+ />
250
+ </div>
251
+ <slot name="endContent" />
252
+ </div>
253
+ </div>
254
+ {#if errorMessage}
255
+ <h5 class="error-message">{errorMessage}</h5>
256
+ {/if}
257
+ </div>
258
+ </DropdownMenu.Trigger>
259
+ <DropdownMenu.Content slot="content" width="var(--hamzus-tigger-width)">
260
+ {#each results as result}
261
+ {@const isSelected = () => {
262
+ if (selection === null) {
263
+ return false;
264
+ }
265
+
266
+ if (!multiple) {
267
+ return selection.id == result.id;
268
+ }
269
+
270
+ // parcourir pour verifier si il correspond a un rersultat
271
+ for (const element of selection) {
272
+ if (element.id == result.id) {
273
+ return true;
274
+ }
275
+ }
276
+
277
+ return false;
278
+ }}
279
+ <svelte:component this={component} selected={isSelected()} {...result} onClick={handleSelect}
280
+ ></svelte:component>
281
+ {/each}
282
+ {#if results.length < totalOfRows}
283
+ <Button
284
+ label="charger plus"
285
+ style="width:100%;text-align:center"
286
+ variant="secondary"
287
+ onClick={handleLoadMore}
288
+ ></Button>
289
+ {/if}
290
+ </DropdownMenu.Content>
291
+ </DropdownMenu.Root>
292
+
293
+ <style>
294
+ .input-container {
295
+ display: flex;
296
+ flex-direction: column;
297
+ transition-property: transform opacity;
298
+ transition-duration: 0.2s;
299
+ transition-timing-function: ease-out;
300
+ user-select: none;
301
+ cursor: text;
302
+ }
303
+ .input-container :global(svg) {
304
+ padding: 2px;
305
+ }
306
+ .input-container :global(svg path) {
307
+ fill: var(--font-2);
308
+ }
309
+ .input-container input {
310
+ text-align: left;
311
+ }
312
+ .input-container.default .input {
313
+ display: flex;
314
+ flex-direction: column;
315
+ row-gap: 0px;
316
+ }
317
+ .input-container:not(.default) .input {
318
+ display: flex;
319
+ flex-direction: column;
320
+ border-radius: var(--radius);
321
+ background-color: var(--default-bg);
322
+ border: 2px solid var(--default-bg);
323
+ transition-property: background, border;
324
+ transition-duration: 0.2s;
325
+ transition-timing-function: ease-out;
326
+ }
327
+
328
+ .input-container:not(.default):has(input:user-invalid) .input {
329
+ border: 2px solid var(--red);
330
+ }
331
+ .input-container:not(.default) .input:hover {
332
+ background-color: var(--bg-3);
333
+ }
334
+ .input-container:not(.default) .input:has(input:focus) {
335
+ background-color: var(--bg-1);
336
+ /* border: 2px solid var(--accent); */
337
+ }
338
+ .input svg path {
339
+ fill: var(--font-2);
340
+ }
341
+
342
+ .input h6 {
343
+ color: var(--font-2);
344
+ }
345
+ .input .required {
346
+ color: var(--red);
347
+ }
348
+ .input .top-line {
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: space-between;
352
+ column-gap: var(--pad-m);
353
+ }
354
+ .input .top-line .input-loader {
355
+ position: static;
356
+ }
357
+ .input-container.default .input .input-line {
358
+ border-radius: var(--radius);
359
+ background-color: var(--default-bg);
360
+ border: 2px solid var(--default-bg);
361
+ transition-property: background, border;
362
+ transition-duration: 0.2s;
363
+ transition-timing-function: ease-out;
364
+ }
365
+ .input-container.default .input:hover .input-line {
366
+ background-color: var(--bg-3);
367
+ }
368
+ .input-container.default .input:has(input:focus) .input-line {
369
+ background-color: var(--bg-1);
370
+ /* border: 2px solid var(--accent); */
371
+ }
372
+ .input-container.default:has(input:user-invalid) .input-line {
373
+ border: 2px solid var(--red);
374
+ }
375
+ .input .input-line {
376
+ display: flex;
377
+ align-items: center;
378
+ column-gap: var(--pad-s);
379
+ }
380
+ .input-container.default:has(.selection) .input-line {
381
+ border-bottom-left-radius: 0px;
382
+ border-bottom-right-radius: 0px;
383
+ }
384
+ /* .selection {
385
+ display: flex;
386
+ gap: var(--pad-s);
387
+ flex-direction: column;
388
+ background-color: var(--bg-2);
389
+ border-bottom-left-radius: var(--radius-m);
390
+ border-bottom-right-radius: var(--radius-m);
391
+ padding: var(--pad-m);
392
+ border-top: 1px solid var(--stroke);
393
+ } */
394
+ .list {
395
+ display: flex;
396
+ width: 100%;
397
+ gap: var(--pad-s);
398
+ flex-wrap: wrap;
399
+ }
400
+ .input input {
401
+ color: var(--font-1);
402
+ width: 100%;
403
+ min-width: 150px;
404
+ flex: 1;
405
+ font-weight: 300;
406
+ }
407
+ .input input::placeholder {
408
+ color: var(--font-3);
409
+ }
410
+ .input .input-line svg {
411
+ height: var(--icon-size);
412
+ width: auto;
413
+ }
414
+
415
+ .input.error {
416
+ border: 2px solid var(--red) !important;
417
+ border-radius: var(--radius);
418
+ }
419
+ .input-container .error-message {
420
+ color: var(--red);
421
+ margin-left: 4px;
422
+ }
423
+
424
+ .input-container:has(input:disabled) .input {
425
+ opacity: 0.6;
426
+ cursor: not-allowed;
427
+ }
428
+ </style>
@@ -31,6 +31,7 @@
31
31
  <span class="line"></span>
32
32
  </icon>
33
33
  <h5>{label}</h5>
34
+ <slot/>
34
35
  </a>
35
36
 
36
37
  <style>