fuma 2.1.1 → 2.1.4

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.
Files changed (82) hide show
  1. package/dist/_doc/DocExample.svelte +122 -0
  2. package/dist/_doc/DocExample.svelte.d.ts +10 -0
  3. package/dist/_doc/DocProps.svelte +61 -0
  4. package/dist/_doc/DocProps.svelte.d.ts +13 -0
  5. package/dist/_doc/DocSection.svelte +22 -0
  6. package/dist/_doc/DocSection.svelte.d.ts +9 -0
  7. package/dist/_doc/highlight.d.ts +2 -0
  8. package/dist/_doc/highlight.js +18 -0
  9. package/dist/_doc/index.d.ts +4 -0
  10. package/dist/_doc/index.js +3 -0
  11. package/dist/_doc/parse-props.d.ts +2 -0
  12. package/dist/_doc/parse-props.js +253 -0
  13. package/dist/command/command.svelte.d.ts +4 -2
  14. package/dist/command/command.svelte.js +29 -2
  15. package/dist/command/index.d.ts +1 -1
  16. package/dist/command/index.js +1 -1
  17. package/dist/index.d.ts +11 -5
  18. package/dist/index.js +11 -5
  19. package/dist/input/InputBoolean.svelte +4 -7
  20. package/dist/input/InputBoolean.svelte.d.ts +1 -1
  21. package/dist/input/InputNumber.svelte +1 -1
  22. package/dist/input/InputNumber.svelte.d.ts +1 -1
  23. package/dist/input/InputRadio.svelte +2 -2
  24. package/dist/input/InputRadio.svelte.d.ts +1 -1
  25. package/dist/input/InputRange.svelte +1 -1
  26. package/dist/input/InputRange.svelte.d.ts +1 -1
  27. package/dist/input/InputRelation.svelte +133 -52
  28. package/dist/input/InputRelation.svelte.d.ts +60 -4
  29. package/dist/input/InputSelect.svelte +2 -2
  30. package/dist/input/InputSelectNative.svelte +3 -3
  31. package/dist/input/InputSelectNative.svelte.d.ts +2 -2
  32. package/dist/input/InputString.svelte +1 -1
  33. package/dist/input/InputString.svelte.d.ts +1 -1
  34. package/dist/input/InputTextarea.svelte +2 -3
  35. package/dist/input/InputTextarea.svelte.d.ts +1 -1
  36. package/dist/input/Issues.svelte +3 -4
  37. package/dist/input/Issues.svelte.d.ts +2 -2
  38. package/dist/input/index.d.ts +1 -1
  39. package/dist/loading/Loading.svelte +43 -0
  40. package/dist/loading/Loading.svelte.d.ts +11 -0
  41. package/dist/loading/index.d.ts +1 -0
  42. package/dist/loading/index.js +1 -0
  43. package/dist/popover/Popover.svelte +1 -1
  44. package/dist/popover/index.d.ts +1 -1
  45. package/dist/popover/index.js +1 -1
  46. package/dist/popover/popover.svelte.d.ts +4 -1
  47. package/dist/popover/popover.svelte.js +14 -9
  48. package/dist/remote/index.d.ts +1 -0
  49. package/dist/remote/index.js +1 -0
  50. package/dist/remote/useForm.d.ts +10 -0
  51. package/dist/remote/useForm.js +23 -3
  52. package/dist/search/Spans.svelte +3 -2
  53. package/dist/search/Spans.svelte.d.ts +1 -1
  54. package/dist/search/index.d.ts +1 -1
  55. package/dist/search/index.js +1 -1
  56. package/dist/search/search.d.ts +38 -0
  57. package/dist/search/search.js +15 -2
  58. package/dist/ui/copy/ButtonCopy.svelte +1 -1
  59. package/dist/ui/copy/ButtonCopy.svelte.d.ts +1 -1
  60. package/dist/ui/copy/index.d.ts +1 -1
  61. package/dist/ui/copy/index.js +1 -1
  62. package/dist/ui/drawer/Drawer.svelte +1 -1
  63. package/dist/ui/drawer/drawerFly.js +1 -1
  64. package/dist/ui/menu/DropDownMenu.svelte +3 -17
  65. package/dist/ui/menu/DropDownMenu.svelte.d.ts +0 -3
  66. package/dist/ui/pagination/Pagination.svelte +1 -1
  67. package/dist/ui/range/RangePicker.svelte +1 -2
  68. package/dist/ui/range/RangePickerButton.svelte +1 -1
  69. package/dist/ui/table/Table.svelte +1 -3
  70. package/dist/ui/table/Table.svelte.d.ts +0 -1
  71. package/dist/ui/table/TableFieldsEdition.svelte +4 -3
  72. package/dist/ui/table/TableViewSelect.svelte +3 -12
  73. package/dist/ui/table/TableViewSelect.svelte.d.ts +0 -5
  74. package/dist/ui/table/head/TableHeadDate.svelte +2 -2
  75. package/dist/ui/table/head/TableHeadNumber.svelte +1 -1
  76. package/dist/ui/table/head/TableHeadSelect.svelte +3 -3
  77. package/dist/utils/options.d.ts +1 -1
  78. package/dist/utils/options.js +1 -1
  79. package/dist/validation/zod.js +2 -1
  80. package/package.json +3 -24
  81. /package/dist/{data.d.ts → _doc/data.d.ts} +0 -0
  82. /package/dist/{data.js → _doc/data.js} +0 -0
@@ -2,7 +2,7 @@
2
2
  import { CheckIcon } from '@lucide/svelte'
3
3
  import type { RemoteFormField } from '@sveltejs/kit'
4
4
  import Issues from './Issues.svelte'
5
- import type { InputProps } from './type.ts'
5
+ import type { InputProps } from './type.js'
6
6
 
7
7
  let {
8
8
  field,
@@ -10,7 +10,6 @@
10
10
  checked = $bindable(),
11
11
  hint,
12
12
  variant = 'checkbox',
13
- class: klass,
14
13
  ...props
15
14
  }: {
16
15
  label: string
@@ -58,7 +57,8 @@
58
57
  </div>
59
58
 
60
59
  {#snippet variantCheckbox()}
61
- <div class={['squircle h-5 w-5 outline', 'bg-base-100']}>
60
+ <!-- https://developer.mozilla.org/en-US/docs/Web/CSS/corner-shape -->
61
+ <div class={['h-5 w-5 rounded-full outline', 'bg-base-100']} style="corner-shape: squircle;">
62
62
  <div
63
63
  class={[
64
64
  'squircle grid h-5 w-5 place-content-center',
@@ -66,6 +66,7 @@
66
66
  'ease scale-0 opacity-0',
67
67
  isChecked && 'scale-[80%] opacity-100'
68
68
  ]}
69
+ style="corner-shape: squircle"
69
70
  >
70
71
  <CheckIcon size={18} class={['stroke-base-100']} strokeWidth={4} />
71
72
  </div>
@@ -92,10 +93,6 @@
92
93
  transition-timing-function: cubic-bezier(0.275, 0.485, 0.515, 1.45);
93
94
  transition-duration: 200ms;
94
95
  }
95
- .squircle {
96
- corner-shape: squircle;
97
- border-radius: 100%;
98
- }
99
96
 
100
97
  label:has(input[aria-invalid='true']) {
101
98
  --input-color: var(--color-error);
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import type { InputProps } from './type.ts';
2
+ import type { InputProps } from './type.js';
3
3
  type $$ComponentProps = {
4
4
  label: string;
5
5
  field?: RemoteFormField<boolean>;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
3
  import Issues from './Issues.svelte'
4
- import type { InputProps } from './type.ts'
4
+ import type { InputProps } from './type.js'
5
5
 
6
6
  let {
7
7
  label,
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import type { InputProps } from './type.ts';
2
+ import type { InputProps } from './type.js';
3
3
  type $$ComponentProps = {
4
4
  label: string;
5
5
  field?: RemoteFormField<number>;
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
- import { type Options, parseOptions } from '../utils/index.ts'
3
+ import { type Options, parseOptions } from '../utils/index.js'
4
4
  import Issues from './Issues.svelte'
5
5
 
6
6
  let {
@@ -21,7 +21,7 @@
21
21
  <div class="flex flex-col gap-1">
22
22
  <span class="label px-3 text-sm">{label}</span>
23
23
  <div class="join join-vertical">
24
- {#each options as option}
24
+ {#each options as option (option.value)}
25
25
  {@const { class: klass, ...props } = option}
26
26
  <label class="input join-item not-disabled:cursor-pointer not-disabled:hover:bg-base-200">
27
27
  {#if option.icon}
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import { type Options } from '../utils/index.ts';
2
+ import { type Options } from '../utils/index.js';
3
3
  type $$ComponentProps = {
4
4
  field?: RemoteFormField<string>;
5
5
  label: string;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
3
  import Issues from './Issues.svelte'
4
- import type { InputProps } from './type.ts'
4
+ import type { InputProps } from './type.js'
5
5
 
6
6
  let {
7
7
  label,
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import type { InputProps } from './type.ts';
2
+ import type { InputProps } from './type.js';
3
3
  type $$ComponentProps = {
4
4
  label: string;
5
5
  field?: RemoteFormField<number>;
@@ -1,81 +1,139 @@
1
1
  <script lang="ts" generics="Item">
2
- import { ChevronsUpDownIcon } from '@lucide/svelte'
2
+ import { ChevronsUpDownIcon, SearchIcon, XIcon } from '@lucide/svelte'
3
3
  import type { RemoteFormField, RemoteQueryFunction } from '@sveltejs/kit'
4
4
  import type { Snippet } from 'svelte'
5
- import { useCommand } from '../command/command.svelte.ts'
6
- import { usePopover } from '../popover/popover.svelte.ts'
5
+ import type { ClassValue } from 'svelte/elements'
6
+ import { tip } from '../action/tip.js'
7
+ import { useCommand } from '../command/command.svelte.js'
8
+ import Loading from '../loading/Loading.svelte'
9
+ import { type PopoverType, usePopover } from '../popover/popover.svelte.js'
7
10
  import Issues from './Issues.svelte'
8
11
 
9
12
  let {
10
13
  label,
11
14
  searchItems,
12
- getValue,
13
- selected,
14
- proposal,
15
+ getValue = defaultGetValue,
16
+ selected = defaultSnippet,
17
+ proposal = defaultSnippet,
15
18
  field,
16
- value = $bindable()
19
+ value = $bindable(),
20
+ placeholder = 'Selectionner une valeur',
21
+ class: klass,
22
+ nullable,
23
+ hint,
24
+ onSelect,
25
+ hotKey
17
26
  }: {
18
- label: string
19
27
  searchItems: RemoteQueryFunction<{ search: string }, Item[]>
20
- getValue: (item: Item) => string
28
+ label?: string
29
+ getValue?: (item: NoInfer<Item>) => string
21
30
  selected?: Snippet<[Item]>
22
31
  proposal?: Snippet<[Item, { isSelected: boolean; isFocus: boolean }]>
23
32
  field?: RemoteFormField<string>
24
33
  value?: string
34
+ placeholder?: string
35
+ class?: ClassValue
36
+ nullable?: boolean
37
+ hint?: Snippet<[Item | undefined]>
38
+ onSelect?: (item: NoInfer<Item> | undefined, popover: PopoverType) => void
39
+ hotKey?: string
25
40
  } = $props()
26
41
 
27
42
  let search = $state('')
28
- const items = $derived.by(() => searchItems({ search }))
43
+ const query = $derived.by(() => searchItems({ search }))
44
+ const items = $derived(query.current || [])
29
45
 
30
46
  let selectedItem = $state<Item | undefined>(undefined)
31
-
32
47
  $effect(() => {
33
- const targetValue = field?.value() ?? value
34
- selectedItem = items.current?.find((item) => getValue(item) === targetValue)
48
+ const targetValue = (field?.value() ?? value)?.toString()
49
+ if (!targetValue) {
50
+ selectedItem = undefined
51
+ command.selectedIndex = -1
52
+ return
53
+ }
54
+ // TODO: Quelle est la meilleur facon de récupérer l'item initial ?
55
+ command.selectedIndex = items.findIndex((item) => getValue(item) === targetValue)
35
56
  })
36
57
 
37
- const popover = usePopover({ listenFocus: false })
38
- const command = useCommand({
58
+ export const popover = usePopover({
59
+ listenFocus: false,
60
+ onShow: () => command.focusTrigger(),
61
+ hotKey: (() => hotKey)()
62
+ })
63
+ export const command = useCommand({
39
64
  isEnable: () => popover.isOpen,
40
65
  onSelect: (index) => {
41
66
  popover.hide()
42
- const item = items.current?.[index]
67
+ const item = items[index]
68
+ onSelect?.(item, popover)
43
69
  if (!item) return
44
70
  selectedItem = item
45
- if (field) {
46
- field.set(getValue(item))
47
- } else {
48
- value = getValue(item)
49
- }
71
+ setValue(item)
50
72
  }
51
73
  })
74
+
75
+ function setValue(item: Item | undefined) {
76
+ const newValue = item && getValue(item)
77
+ if (field) {
78
+ field.set(newValue)
79
+ } else {
80
+ value = newValue
81
+ }
82
+ }
83
+
84
+ function defaultGetValue(item: Item): string {
85
+ if (item && typeof item === 'object') {
86
+ if ('value' in item && typeof item.value === 'string') return item.value
87
+ if ('rowid' in item && typeof item.rowid === 'string') return item.rowid
88
+ }
89
+ return JSON.stringify(item)
90
+ }
91
+
92
+ function getDefaultLabel(item: Item) {
93
+ if (item && typeof item === 'object' && 'label' in item) {
94
+ if (typeof item.label === 'string') return item.label
95
+ }
96
+ return getValue(item)
97
+ }
98
+
99
+ const isButtonSetNullVisible = $derived(nullable && (field?.value() || value))
52
100
  </script>
53
101
 
54
- {#if field?.value() !== undefined}
55
- <input {...field.as('hidden', field.value() as string)} />
102
+ {#snippet defaultSnippet(item: Item)}
103
+ <span>{getDefaultLabel(item)}</span>
104
+ {/snippet}
105
+
106
+ {#snippet triggerButton()}
107
+ <button
108
+ type="button"
109
+ class={['input', field?.issues.length && 'input-error', klass]}
110
+ {...popover.trigger}
111
+ >
112
+ <div class="grow text-left">
113
+ {#if !selectedItem}
114
+ <span class="opacity-60">{placeholder}</span>
115
+ {:else}
116
+ <!-- item.icon not rerender if not wrapped in #key -->
117
+ {#key selectedItem}{@render selected(selectedItem)}{/key}
118
+ {/if}
119
+ </div>
120
+ <ChevronsUpDownIcon size={14} opacity={0.7} />
121
+ </button>
122
+ {/snippet}
123
+
124
+ {#if field}
125
+ <input {...field.as('hidden', field.value() || '')} />
56
126
  {/if}
57
127
 
58
128
  <div>
59
- <label class="floating-label">
60
- <span>{label}</span>
61
- <button
62
- class={['input', field?.issues.length && 'input-error']}
63
- {...popover.trigger}
64
- type="button"
65
- >
66
- <div class="grow text-left">
67
- {#if !selectedItem}
68
- <span class="opacity-60">Select a value</span>
69
- {:else if selected}
70
- <!-- item.icon not rerender if not wrapped in #key -->
71
- {#key selectedItem}{@render selected(selectedItem)}{/key}
72
- {:else}
73
- {getValue(selectedItem)}
74
- {/if}
75
- </div>
76
- <ChevronsUpDownIcon size={14} />
77
- </button>
78
- </label>
129
+ {#if label}
130
+ <label class="floating-label">
131
+ <span>{label}</span>
132
+ {@render triggerButton()}
133
+ </label>
134
+ {:else}
135
+ {@render triggerButton()}
136
+ {/if}
79
137
 
80
138
  <div
81
139
  {...popover.content}
@@ -83,33 +141,56 @@
83
141
  style="min-width: anchor-size(width);"
84
142
  tabindex="-1"
85
143
  >
86
- <div class="sticky top-0 z-10 bg-base-100 p-2">
87
- <input type="search" {...command.trigger} class="input input-sm" bind:value={search} />
144
+ <div class="sticky top-0 z-10 flex gap-2 bg-base-100/10 p-2 backdrop-blur-md">
145
+ <label class="input input-sm grow input-ghost">
146
+ <SearchIcon opacity={0.6} size={20} />
147
+ <input
148
+ type="search"
149
+ placeholder="Recherche"
150
+ autocomplete="off"
151
+ bind:value={search}
152
+ {...command.trigger}
153
+ />
154
+ </label>
155
+ {#if isButtonSetNullVisible}
156
+ <button
157
+ class="btn btn-square btn-soft btn-sm"
158
+ type="button"
159
+ onclick={() => {
160
+ selectedItem = undefined
161
+ setValue(undefined)
162
+ onSelect?.(undefined, popover)
163
+ popover.hide()
164
+ }}
165
+ use:tip={{ content: 'Pas de sélection' }}
166
+ >
167
+ <XIcon />
168
+ </button>
169
+ {/if}
88
170
  </div>
89
171
 
90
172
  <ul class="menu max-h-80 w-full flex-nowrap pt-0">
91
- {#each items.current as item, index (item)}
173
+ {#each items as item, index (item)}
92
174
  {@const isSelected = index === command.selectedIndex}
93
175
  {@const isFocus = index === command.focusIndex}
94
176
  <li>
95
177
  <button
96
178
  {...command.item(index, '')}
97
- class={[isFocus && 'menu-focus', 'scroll-mt-13 scroll-mb-2']}
179
+ class={[isSelected && 'border', isFocus && 'menu-focus', 'scroll-mt-13 scroll-mb-2']}
98
180
  type="button"
99
181
  tabindex="-1"
100
182
  role="option"
101
183
  >
102
- {#if proposal}
103
- {@render proposal(item, { isSelected, isFocus })}
104
- {:else}
105
- {getValue(item)}
106
- {/if}
184
+ {@render proposal(item, { isSelected, isFocus })}
107
185
  </button>
108
186
  </li>
109
187
  {/each}
110
188
  </ul>
189
+
190
+ <Loading {query} />
111
191
  </div>
112
192
  <Issues {field} />
193
+ {@render hint?.(selectedItem)}
113
194
  </div>
114
195
 
115
196
  <style>
@@ -1,12 +1,14 @@
1
1
  import type { RemoteFormField, RemoteQueryFunction } from '@sveltejs/kit';
2
2
  import type { Snippet } from 'svelte';
3
+ import type { ClassValue } from 'svelte/elements';
4
+ import { type PopoverType } from '../popover/popover.svelte.js';
3
5
  declare function $$render<Item>(): {
4
6
  props: {
5
- label: string;
6
7
  searchItems: RemoteQueryFunction<{
7
8
  search: string;
8
9
  }, Item[]>;
9
- getValue: (item: Item) => string;
10
+ label?: string;
11
+ getValue?: (item: NoInfer<Item>) => string;
10
12
  selected?: Snippet<[Item]>;
11
13
  proposal?: Snippet<[Item, {
12
14
  isSelected: boolean;
@@ -14,8 +16,38 @@ declare function $$render<Item>(): {
14
16
  }]>;
15
17
  field?: RemoteFormField<string>;
16
18
  value?: string;
19
+ placeholder?: string;
20
+ class?: ClassValue;
21
+ nullable?: boolean;
22
+ hint?: Snippet<[Item | undefined]>;
23
+ onSelect?: (item: NoInfer<Item> | undefined, popover: PopoverType) => void;
24
+ hotKey?: string;
25
+ };
26
+ exports: {
27
+ popover: {
28
+ show: () => void;
29
+ hide: () => void;
30
+ readonly isOpen: boolean;
31
+ content: {
32
+ [x: symbol]: (node: HTMLElement) => () => void;
33
+ popover: "auto" | "hint" | "manual";
34
+ };
35
+ trigger: {
36
+ [x: symbol]: (node: HTMLElement) => () => void;
37
+ };
38
+ };
39
+ command: {
40
+ readonly focusIndex: number;
41
+ selectedIndex: number;
42
+ trigger: {
43
+ [x: symbol]: (node: HTMLElement) => () => void;
44
+ };
45
+ focusTrigger: () => void;
46
+ item: (index: number, scrollMargin?: string) => {
47
+ [x: symbol]: (node: HTMLElement) => () => void;
48
+ };
49
+ };
17
50
  };
18
- exports: {};
19
51
  bindings: "value";
20
52
  slots: {};
21
53
  events: {};
@@ -25,7 +57,31 @@ declare class __sveltets_Render<Item> {
25
57
  events(): ReturnType<typeof $$render<Item>>['events'];
26
58
  slots(): ReturnType<typeof $$render<Item>>['slots'];
27
59
  bindings(): "value";
28
- exports(): {};
60
+ exports(): {
61
+ popover: {
62
+ show: () => void;
63
+ hide: () => void;
64
+ readonly isOpen: boolean;
65
+ content: {
66
+ [x: symbol]: (node: HTMLElement) => () => void;
67
+ popover: "auto" | "hint" | "manual";
68
+ };
69
+ trigger: {
70
+ [x: symbol]: (node: HTMLElement) => () => void;
71
+ };
72
+ };
73
+ command: {
74
+ readonly focusIndex: number;
75
+ selectedIndex: number;
76
+ trigger: {
77
+ [x: symbol]: (node: HTMLElement) => () => void;
78
+ };
79
+ focusTrigger: () => void;
80
+ item: (index: number, scrollMargin?: string) => {
81
+ [x: symbol]: (node: HTMLElement) => () => void;
82
+ };
83
+ };
84
+ };
29
85
  }
30
86
  interface $$IsomorphicComponent {
31
87
  new <Item>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Item>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Item>['props']>, ReturnType<__sveltets_Render<Item>['events']>, ReturnType<__sveltets_Render<Item>['slots']>> & {
@@ -2,8 +2,8 @@
2
2
  import { ChevronsUpDownIcon } from '@lucide/svelte'
3
3
  import type { RemoteFormField } from '@sveltejs/kit'
4
4
  import type { Snippet } from 'svelte'
5
- import { useCommand } from '../command/command.svelte.ts'
6
- import { usePopover } from '../popover/popover.svelte.ts'
5
+ import { useCommand } from '../command/command.svelte.js'
6
+ import { usePopover } from '../popover/popover.svelte.js'
7
7
  import Issues from './Issues.svelte'
8
8
 
9
9
  let {
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
- import { type Options, parseOptions } from '../index.ts'
3
+ import { type Options, parseOptions } from '../index.js'
4
4
  import Issues from './Issues.svelte'
5
- import type { SelectProps } from './type.ts'
5
+ import type { SelectProps } from './type.js'
6
6
 
7
7
  let {
8
8
  label,
@@ -31,7 +31,7 @@
31
31
  bind:value
32
32
  {...props}
33
33
  >
34
- {#each options as option}
34
+ {#each options as option (option.value)}
35
35
  <option value={option.value} class={['', option.class]} disabled={option.disabled}>
36
36
  {#if option.icon}
37
37
  <option.icon size={18} opacity={0.8} />
@@ -1,6 +1,6 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import { type Options } from '../index.ts';
3
- import type { SelectProps } from './type.ts';
2
+ import { type Options } from '../index.js';
3
+ import type { SelectProps } from './type.js';
4
4
  type $$ComponentProps = {
5
5
  label: string;
6
6
  options: Options;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
3
  import Issues from './Issues.svelte'
4
- import type { InputProps } from './type.ts'
4
+ import type { InputProps } from './type.js'
5
5
 
6
6
  let {
7
7
  label,
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import type { InputProps } from './type.ts';
2
+ import type { InputProps } from './type.js';
3
3
  type $$ComponentProps = {
4
4
  label: string;
5
5
  field?: RemoteFormField<string>;
@@ -2,7 +2,7 @@
2
2
  import type { RemoteFormField } from '@sveltejs/kit'
3
3
  import { TextareaAutosize } from 'runed'
4
4
  import Issues from './Issues.svelte'
5
- import type { TextareaProps } from './type.ts'
5
+ import type { TextareaProps } from './type.js'
6
6
 
7
7
  let {
8
8
  label,
@@ -22,8 +22,7 @@
22
22
  new TextareaAutosize({
23
23
  element: () => textarea,
24
24
  input: () => field?.value() || value || '',
25
- // svelte-ignore state_referenced_locally
26
- maxHeight
25
+ maxHeight: (() => maxHeight)()
27
26
  })
28
27
  </script>
29
28
 
@@ -1,5 +1,5 @@
1
1
  import type { RemoteFormField } from '@sveltejs/kit';
2
- import type { TextareaProps } from './type.ts';
2
+ import type { TextareaProps } from './type.js';
3
3
  type $$ComponentProps = {
4
4
  label: string;
5
5
  field?: RemoteFormField<string>;
@@ -1,18 +1,17 @@
1
1
  <script lang="ts">
2
- import type { RemoteFormField } from '@sveltejs/kit'
2
+ import type { RemoteFormField, RemoteFormFieldValue } from '@sveltejs/kit'
3
3
  import { slide } from 'svelte/transition'
4
4
 
5
5
  let {
6
6
  field
7
7
  }: {
8
- // biome-ignore lint/suspicious/noExplicitAny: Wathever then value type... we use just field.issues()
9
- field: RemoteFormField<any> | undefined
8
+ field: RemoteFormField<RemoteFormFieldValue> | undefined
10
9
  } = $props()
11
10
  </script>
12
11
 
13
12
  {#if field?.issues()?.length}
14
13
  <div class="my-1 flex flex-col text-xs text-error" transition:slide={{ duration: 200 }}>
15
- {#each field.issues() as issue}
14
+ {#each field.issues() as issue (issue.path)}
16
15
  <span>
17
16
  {issue.message}
18
17
  </span>
@@ -1,6 +1,6 @@
1
- import type { RemoteFormField } from '@sveltejs/kit';
1
+ import type { RemoteFormField, RemoteFormFieldValue } from '@sveltejs/kit';
2
2
  type $$ComponentProps = {
3
- field: RemoteFormField<any> | undefined;
3
+ field: RemoteFormField<RemoteFormFieldValue> | undefined;
4
4
  };
5
5
  declare const Issues: import("svelte").Component<$$ComponentProps, {}, "">;
6
6
  type Issues = ReturnType<typeof Issues>;
@@ -8,4 +8,4 @@ export { default as InputSelectNative } from './InputSelectNative.svelte';
8
8
  export { default as InputString } from './InputString.svelte';
9
9
  export { default as InputTextarea } from './InputTextarea.svelte';
10
10
  export { default as Issues } from './Issues.svelte';
11
- export type * from './type.ts';
11
+ export type * from './type.js';
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ import { GhostIcon, LoaderCircleIcon, TriangleAlertIcon } from '@lucide/svelte'
3
+ import type { RemoteQuery } from '@sveltejs/kit'
4
+ import type { ClassValue } from 'svelte/elements'
5
+ import { fade } from 'svelte/transition'
6
+
7
+ let {
8
+ query,
9
+ empty = 'Aucun résultat',
10
+ error = 'Une erreur est survenue',
11
+ class: klass
12
+ }: {
13
+ query: RemoteQuery<unknown>
14
+ empty?: string
15
+ error?: string
16
+ class?: ClassValue
17
+ } = $props()
18
+
19
+ const isEmpty = $derived.by(() => {
20
+ if (!query.ready) return true
21
+ if (!query.current) return true
22
+ if (Array.isArray(query.current) && !query.current.length) return true
23
+ return false
24
+ })
25
+
26
+ const box = 'm-2 flex flex-col items-center gap-1 rounded border border-dashed p-2 text-sm'
27
+ </script>
28
+
29
+ {#if query.loading}
30
+ <div class={['grid h-12 place-content-center', klass]} in:fade={{ duration: 200 }}>
31
+ <LoaderCircleIcon class="animate-spin" opacity={0.7} />
32
+ </div>
33
+ {:else if query.error}
34
+ <div class={[box, 'border-error/50 text-error', klass]} in:fade={{ duration: 200 }}>
35
+ <TriangleAlertIcon size={18} />
36
+ <span>{error}</span>
37
+ </div>
38
+ {:else if isEmpty}
39
+ <div class={[box, 'border-base-content/50 opacity-70', klass]} in:fade={{ duration: 200 }}>
40
+ <GhostIcon size={18} />
41
+ <span>{empty}</span>
42
+ </div>
43
+ {/if}
@@ -0,0 +1,11 @@
1
+ import type { RemoteQuery } from '@sveltejs/kit';
2
+ import type { ClassValue } from 'svelte/elements';
3
+ type $$ComponentProps = {
4
+ query: RemoteQuery<unknown>;
5
+ empty?: string;
6
+ error?: string;
7
+ class?: ClassValue;
8
+ };
9
+ declare const Loading: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type Loading = ReturnType<typeof Loading>;
11
+ export default Loading;
@@ -0,0 +1 @@
1
+ export { default as Loading } from './Loading.svelte';
@@ -0,0 +1 @@
1
+ export { default as Loading } from './Loading.svelte';
@@ -6,7 +6,7 @@
6
6
  type PopoverOptions,
7
7
  type PopoverType,
8
8
  usePopover
9
- } from './popover.svelte.ts'
9
+ } from './popover.svelte.js'
10
10
 
11
11
  let {
12
12
  children,
@@ -1,2 +1,2 @@
1
1
  export { default as Popover } from './Popover.svelte';
2
- export * from './popover.svelte.ts';
2
+ export * from './popover.svelte.js';
@@ -1,2 +1,2 @@
1
1
  export { default as Popover } from './Popover.svelte';
2
- export * from './popover.svelte.ts';
2
+ export * from './popover.svelte.js';