fuma 2.5.3 → 2.6.0
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/dist/command/useCommand.svelte.d.ts +5 -1
- package/dist/command/useCommand.svelte.js +5 -2
- package/dist/input/InputMultiSelect.svelte +16 -8
- package/dist/input/InputMultiSelect.svelte.d.ts +3 -3
- package/dist/input/InputSelect.svelte +21 -8
- package/dist/input/InputSelect.svelte.d.ts +3 -3
- package/package.json +1 -1
|
@@ -11,7 +11,11 @@ export declare function useCommand({ onSelect, onFocus, isEnable, hotKey }?: Com
|
|
|
11
11
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
12
12
|
};
|
|
13
13
|
focusTrigger: () => void;
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Le dégagement du défilement appartient à l'appelant: `scroll-mt-*` / `scroll-mb-*`
|
|
16
|
+
* sur l'item, puisque lui seul connaît la hauteur de son en-tête collant.
|
|
17
|
+
*/
|
|
18
|
+
item: (index: number) => {
|
|
15
19
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
16
20
|
};
|
|
17
21
|
};
|
|
@@ -74,9 +74,12 @@ export function useCommand({ onSelect, onFocus, isEnable = () => true, hotKey }
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
focusTrigger,
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Le dégagement du défilement appartient à l'appelant: `scroll-mt-*` / `scroll-mb-*`
|
|
79
|
+
* sur l'item, puisque lui seul connaît la hauteur de son en-tête collant.
|
|
80
|
+
*/
|
|
81
|
+
item: (index) => ({
|
|
78
82
|
[createAttachmentKey()]: (node) => {
|
|
79
|
-
node.style.scrollMargin = scrollMargin;
|
|
80
83
|
if (!items.includes(node))
|
|
81
84
|
items.splice(index, 0, node);
|
|
82
85
|
const cleanup = on(node, 'click', () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" generics="Item">
|
|
2
2
|
import { CheckIcon, ChevronsUpDownIcon, SearchIcon, XIcon } from '@lucide/svelte'
|
|
3
3
|
import type { RemoteFormField } from '@sveltejs/kit'
|
|
4
|
-
import type
|
|
4
|
+
import { untrack, type Snippet } from 'svelte'
|
|
5
5
|
import type { ClassValue } from 'svelte/elements'
|
|
6
6
|
import { slide } from 'svelte/transition'
|
|
7
7
|
import { tip } from '../action/tip.js'
|
|
@@ -122,16 +122,25 @@
|
|
|
122
122
|
value = selectedValues.includes(itemValue)
|
|
123
123
|
? value.filter((selectedItem) => getValue(selectedItem) !== itemValue)
|
|
124
124
|
: [...value, item]
|
|
125
|
-
|
|
125
|
+
onSelect?.(value, popover)
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
function remove(item: Item) {
|
|
129
129
|
const itemValue = getValue(item)
|
|
130
130
|
value = value.filter((selectedItem) => getValue(selectedItem) !== itemValue)
|
|
131
|
-
|
|
131
|
+
onSelect?.(value, popover)
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
// L'annonce suit la valeur et non le geste: le parent peut l'écrire lui-même par `bind:`
|
|
135
|
+
// — un item créé dans un tiroir — et `toggle` n'est alors jamais appelé.
|
|
136
|
+
//
|
|
137
|
+
// La ligne de base est prise au montage: annoncer la sélection initiale l'écrirait dans
|
|
138
|
+
// l'état du champ, qui cesserait dès lors de consulter la valeur passée à `as()`.
|
|
139
|
+
let announced = untrack(() => selectedValues.join('\n'))
|
|
140
|
+
$effect(() => {
|
|
141
|
+
const signature = selectedValues.join('\n')
|
|
142
|
+
if (signature === announced) return
|
|
143
|
+
announced = signature
|
|
135
144
|
// Les cases cachées suffisent à soumettre; `set` garde la validation à jour.
|
|
136
145
|
field?.set(selectedValues)
|
|
137
146
|
// Un choix n'émet aucun évènement de formulaire: les cases sont écrites par le code,
|
|
@@ -139,8 +148,7 @@
|
|
|
139
148
|
// au select simple. Sans cette annonce, ce qui surveille le formulaire (une barre de
|
|
140
149
|
// sauvegarde) ne voit la sélection qu'au choix suivant.
|
|
141
150
|
trigger?.dispatchEvent(new Event('change', { bubbles: true }))
|
|
142
|
-
|
|
143
|
-
}
|
|
151
|
+
})
|
|
144
152
|
</script>
|
|
145
153
|
|
|
146
154
|
{#snippet defaultSnippet(item: Item)}
|
|
@@ -262,7 +270,7 @@
|
|
|
262
270
|
type="button"
|
|
263
271
|
onclick={() => {
|
|
264
272
|
value = []
|
|
265
|
-
|
|
273
|
+
onSelect?.(value, popover)
|
|
266
274
|
popover.hide()
|
|
267
275
|
}}
|
|
268
276
|
use:tip={{ content: 'Tout désélectionner' }}
|
|
@@ -285,7 +293,7 @@
|
|
|
285
293
|
{@const isFocus = index === command.focusIndex}
|
|
286
294
|
<li>
|
|
287
295
|
<button
|
|
288
|
-
{...command.item(index
|
|
296
|
+
{...command.item(index)}
|
|
289
297
|
class={[isSelected && 'border', isFocus && 'menu-focus', 'scroll-mt-13 scroll-mb-2']}
|
|
290
298
|
type="button"
|
|
291
299
|
tabindex="-1"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RemoteFormField } from '@sveltejs/kit';
|
|
2
|
-
import type
|
|
2
|
+
import { type Snippet } from 'svelte';
|
|
3
3
|
import type { ClassValue } from 'svelte/elements';
|
|
4
4
|
import { type PopoverType } from '../popover/usePopover.svelte.js';
|
|
5
5
|
import { type ItemsSource } from './useItems.svelte.js';
|
|
@@ -62,7 +62,7 @@ declare function $$render<Item>(): {
|
|
|
62
62
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
63
63
|
};
|
|
64
64
|
focusTrigger: () => void;
|
|
65
|
-
item: (index: number
|
|
65
|
+
item: (index: number) => {
|
|
66
66
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
67
67
|
};
|
|
68
68
|
};
|
|
@@ -96,7 +96,7 @@ declare class __sveltets_Render<Item> {
|
|
|
96
96
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
97
97
|
};
|
|
98
98
|
focusTrigger: () => void;
|
|
99
|
-
item: (index: number
|
|
99
|
+
item: (index: number) => {
|
|
100
100
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
101
101
|
};
|
|
102
102
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" generics="Item">
|
|
2
2
|
import { ChevronsUpDownIcon, SearchIcon, XIcon } from '@lucide/svelte'
|
|
3
3
|
import type { RemoteFormField } from '@sveltejs/kit'
|
|
4
|
-
import type
|
|
4
|
+
import { untrack, type Snippet } from 'svelte'
|
|
5
5
|
import type { ClassValue, HTMLLiAttributes } from 'svelte/elements'
|
|
6
6
|
import { tip } from '../action/tip.js'
|
|
7
7
|
import { useCommand } from '../command/useCommand.svelte.js'
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
} = $props()
|
|
83
83
|
|
|
84
84
|
const inputId = $props.id()
|
|
85
|
+
let trigger = $state<HTMLButtonElement>()
|
|
85
86
|
|
|
86
87
|
let search = $state('')
|
|
87
88
|
// Une énumération courte n'a que faire d'un champ de recherche; une fonction, elle, ne
|
|
@@ -116,15 +117,26 @@
|
|
|
116
117
|
const item = options[index]
|
|
117
118
|
onSelect?.(item, popover)
|
|
118
119
|
if (!item) return
|
|
119
|
-
|
|
120
|
+
value = item
|
|
120
121
|
}
|
|
121
122
|
})
|
|
122
123
|
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
// L'annonce suit la valeur et non le geste: le parent peut l'écrire lui-même par `bind:`
|
|
125
|
+
// — un item créé dans un tiroir — sans passer par la liste.
|
|
126
|
+
//
|
|
127
|
+
// La ligne de base est prise au montage: annoncer la valeur initiale l'écrirait dans
|
|
128
|
+
// l'état du champ, qui cesserait dès lors de consulter la valeur passée à `as()`.
|
|
129
|
+
let announced = untrack(() => submittedValue)
|
|
130
|
+
$effect(() => {
|
|
131
|
+
if (submittedValue === announced) return
|
|
132
|
+
announced = submittedValue
|
|
125
133
|
// L'input caché suffit à soumettre; `set` garde la validation du formulaire à jour.
|
|
126
|
-
field?.set(
|
|
127
|
-
|
|
134
|
+
field?.set(submittedValue)
|
|
135
|
+
// Un choix n'émet aucun évènement de formulaire: l'input caché est écrit par le code.
|
|
136
|
+
// Sans cette annonce, ce qui surveille le formulaire (une barre de sauvegarde) ne voit
|
|
137
|
+
// pas une valeur que le parent a posée lui-même.
|
|
138
|
+
trigger?.dispatchEvent(new Event('change', { bubbles: true }))
|
|
139
|
+
})
|
|
128
140
|
|
|
129
141
|
const isButtonSetNullVisible = $derived(nullable && value)
|
|
130
142
|
</script>
|
|
@@ -135,6 +147,7 @@
|
|
|
135
147
|
|
|
136
148
|
{#snippet triggerButton()}
|
|
137
149
|
<button
|
|
150
|
+
bind:this={trigger}
|
|
138
151
|
id={inputId}
|
|
139
152
|
type="button"
|
|
140
153
|
{disabled}
|
|
@@ -214,7 +227,7 @@
|
|
|
214
227
|
class="btn btn-square btn-soft btn-sm"
|
|
215
228
|
type="button"
|
|
216
229
|
onclick={() => {
|
|
217
|
-
|
|
230
|
+
value = undefined
|
|
218
231
|
onSelect?.(undefined, popover)
|
|
219
232
|
popover.hide()
|
|
220
233
|
}}
|
|
@@ -239,7 +252,7 @@
|
|
|
239
252
|
{@const isFocus = index === command.focusIndex}
|
|
240
253
|
<li {...propsLi}>
|
|
241
254
|
<button
|
|
242
|
-
{...command.item(index
|
|
255
|
+
{...command.item(index)}
|
|
243
256
|
class={[
|
|
244
257
|
isSelected && 'border-hard border',
|
|
245
258
|
isFocus && 'menu-focus',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RemoteFormField } from '@sveltejs/kit';
|
|
2
|
-
import type
|
|
2
|
+
import { type Snippet } from 'svelte';
|
|
3
3
|
import type { ClassValue, HTMLLiAttributes } from 'svelte/elements';
|
|
4
4
|
import { type PopoverType } from '../popover/usePopover.svelte.js';
|
|
5
5
|
import { type ItemsSource } from './useItems.svelte.js';
|
|
@@ -70,7 +70,7 @@ declare function $$render<Item>(): {
|
|
|
70
70
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
71
71
|
};
|
|
72
72
|
focusTrigger: () => void;
|
|
73
|
-
item: (index: number
|
|
73
|
+
item: (index: number) => {
|
|
74
74
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
75
75
|
};
|
|
76
76
|
};
|
|
@@ -104,7 +104,7 @@ declare class __sveltets_Render<Item> {
|
|
|
104
104
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
105
105
|
};
|
|
106
106
|
focusTrigger: () => void;
|
|
107
|
-
item: (index: number
|
|
107
|
+
item: (index: number) => {
|
|
108
108
|
[x: symbol]: (node: HTMLElement) => () => void;
|
|
109
109
|
};
|
|
110
110
|
};
|