fuma 2.1.5 → 2.2.7

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 (84) hide show
  1. package/dist/_doc/data.d.ts +3 -1
  2. package/dist/_doc/data.js +6 -2
  3. package/dist/command/index.d.ts +1 -1
  4. package/dist/command/index.js +1 -1
  5. package/dist/command/{command.svelte.js → useCommand.svelte.js} +1 -1
  6. package/dist/input/InputBoolean.svelte +25 -7
  7. package/dist/input/InputBoolean.svelte.d.ts +4 -0
  8. package/dist/input/InputCheckboxes.svelte +116 -0
  9. package/dist/input/InputCheckboxes.svelte.d.ts +16 -0
  10. package/dist/input/InputDateTime.svelte +194 -0
  11. package/dist/input/InputDateTime.svelte.d.ts +23 -0
  12. package/dist/input/InputMultiSelect.svelte +286 -0
  13. package/dist/input/{InputRelation.svelte.d.ts → InputMultiSelect.svelte.d.ts} +27 -13
  14. package/dist/input/InputNumber.svelte +36 -6
  15. package/dist/input/InputNumber.svelte.d.ts +5 -0
  16. package/dist/input/InputRadio.svelte +54 -23
  17. package/dist/input/InputRange.svelte +19 -4
  18. package/dist/input/InputRange.svelte.d.ts +6 -0
  19. package/dist/input/InputSelect.svelte +204 -62
  20. package/dist/input/InputSelect.svelte.d.ts +87 -6
  21. package/dist/input/InputSelectNative.svelte +44 -19
  22. package/dist/input/InputSelectNative.svelte.d.ts +5 -0
  23. package/dist/input/InputString.svelte +36 -6
  24. package/dist/input/InputString.svelte.d.ts +5 -0
  25. package/dist/input/InputTextarea.svelte +41 -12
  26. package/dist/input/InputTextarea.svelte.d.ts +5 -0
  27. package/dist/input/index.d.ts +4 -1
  28. package/dist/input/index.js +4 -1
  29. package/dist/input/useItems.svelte.d.ts +38 -0
  30. package/dist/input/useItems.svelte.js +142 -0
  31. package/dist/loading/Loading.svelte +3 -2
  32. package/dist/loading/Loading.svelte.d.ts +3 -2
  33. package/dist/popover/Popover.svelte +1 -2
  34. package/dist/popover/Popover.svelte.d.ts +13 -0
  35. package/dist/popover/index.d.ts +1 -1
  36. package/dist/popover/index.js +1 -1
  37. package/dist/popover/{popover.svelte.d.ts → usePopover.svelte.d.ts} +2 -1
  38. package/dist/popover/usePopover.svelte.js +145 -0
  39. package/dist/remote/useForm.d.ts +4 -5
  40. package/dist/remote/useForm.js +9 -4
  41. package/dist/state/index.d.ts +1 -1
  42. package/dist/state/index.js +1 -1
  43. package/dist/ui/button/ButtonDelete.svelte +4 -2
  44. package/dist/ui/dialog/Dialog.svelte +5 -5
  45. package/dist/ui/drawer/Drawer.svelte +74 -26
  46. package/dist/ui/drawer/Drawer.svelte.d.ts +10 -4
  47. package/dist/ui/drawer/index.d.ts +1 -0
  48. package/dist/ui/drawer/index.js +1 -0
  49. package/dist/ui/drawer/inertBackground.d.ts +13 -0
  50. package/dist/ui/drawer/inertBackground.js +59 -0
  51. package/dist/ui/drawer/useLayer.svelte.d.ts +1 -1
  52. package/dist/ui/drawer/useLayer.svelte.js +11 -7
  53. package/dist/ui/index.d.ts +1 -0
  54. package/dist/ui/index.js +1 -0
  55. package/dist/ui/menu/ContextMenu.svelte +30 -17
  56. package/dist/ui/menu/ContextMenu.svelte.d.ts +2 -3
  57. package/dist/ui/menu/DropDown.svelte +1 -1
  58. package/dist/ui/menu/DropDown.svelte.d.ts +1 -1
  59. package/dist/ui/menu/DropDownMenu.svelte +12 -10
  60. package/dist/ui/menu/DropDownMenu.svelte.d.ts +2 -3
  61. package/dist/ui/menu/index.d.ts +0 -1
  62. package/dist/ui/menu/index.js +0 -2
  63. package/dist/ui/range/RangePicker.svelte +25 -13
  64. package/dist/ui/range/RangePicker.svelte.d.ts +9 -25
  65. package/dist/ui/range/RangePickerButton.svelte +49 -32
  66. package/dist/ui/range/RangePickerButton.svelte.d.ts +1 -1
  67. package/dist/ui/table/Table.svelte +7 -10
  68. package/dist/ui/table/Table.svelte.d.ts +1 -1
  69. package/dist/ui/table/TableFieldsEdition.svelte +24 -22
  70. package/dist/ui/table/TableHead.svelte +5 -1
  71. package/dist/ui/table/TableViewSelect.svelte +52 -47
  72. package/dist/ui/table/cell/TableCellBoolean.svelte +2 -2
  73. package/dist/ui/table/head/TableHeadDate.svelte +62 -55
  74. package/dist/ui/table/head/TableHeadNumber.svelte +55 -19
  75. package/dist/ui/table/head/TableHeadSelect.svelte +30 -27
  76. package/dist/ui/table/head/TableHeadString.svelte +11 -7
  77. package/dist/ui/table/index.d.ts +1 -0
  78. package/dist/ui/table/index.js +1 -0
  79. package/package.json +7 -4
  80. package/dist/input/InputRelation.svelte +0 -200
  81. package/dist/popover/popover.svelte.js +0 -106
  82. /package/dist/command/{command.svelte.d.ts → useCommand.svelte.d.ts} +0 -0
  83. /package/dist/state/{param.svelte.d.ts → param.d.ts} +0 -0
  84. /package/dist/state/{param.svelte.js → param.js} +0 -0
@@ -2,36 +2,49 @@
2
2
  import { CalendarRangeIcon } from '@lucide/svelte'
3
3
  import { slide } from 'svelte/transition'
4
4
  import { goto } from '$app/navigation'
5
- import { param, urlParam } from '../../state/param.svelte.js'
6
- import { DropDown } from '../menu/index.js'
5
+ import { InputDateTime } from '../../input/index.js'
6
+ import { usePopover } from '../../popover/index.js'
7
+ import { param, urlParam } from '../../state/param.js'
7
8
  import { formatRangeShort } from './format.js'
8
9
  import { type RangeAsDate, RangePicker } from './index.js'
9
10
  import { jsonParse } from '../../utils/jsonParse.js'
10
11
 
11
- let dropDown: DropDown
12
12
  let rangePicker: RangePicker
13
13
 
14
14
  let {
15
15
  key = 'range',
16
- range = $bindable(
17
- jsonParse<RangeAsDate>(param.get(key), {
18
- start: null,
19
- end: null
20
- })
21
- ),
16
+ range = $bindable(parseRange(param.get(key))),
22
17
  minDate,
23
18
  maxDate,
24
19
  class: klass = '',
25
20
  classLabel = ''
26
21
  }: {
27
22
  key?: string
28
- range: RangeAsDate
23
+ range?: RangeAsDate
29
24
  minDate?: Date | number | string
30
25
  maxDate?: Date | number | string
31
26
  class?: string
32
27
  classLabel?: string
33
28
  } = $props()
34
29
 
30
+ const popover = usePopover()
31
+
32
+ // Le paramètre d'URL porte des chaînes ISO: sans cette reprise, `range` contiendrait des
33
+ // chaînes là où tout le reste — `updateURL`, `InputDateTime` — attend des `Date`.
34
+ function parseRange(value?: string | null): RangeAsDate {
35
+ const { start, end } = jsonParse<{ start?: string; end?: string }>(value, {})
36
+ return { start: start ? new Date(start) : null, end: end ? new Date(end) : null }
37
+ }
38
+
39
+ // Le light-dismiss (clic à l'extérieur) ne passe pas par `hide()`, donc pas par
40
+ // `onHide`: on suit `isOpen` pour que l'URL soit à jour à chaque fermeture.
41
+ let wasOpen = false
42
+ $effect(() => {
43
+ const { isOpen } = popover
44
+ if (wasOpen && !isOpen) updateURL()
45
+ wasOpen = isOpen
46
+ })
47
+
35
48
  let isValidPeriod = $derived(!!range.start && !!range.end)
36
49
 
37
50
  function getLabel(_range?: Partial<RangeAsDate>) {
@@ -53,29 +66,27 @@
53
66
  }
54
67
  </script>
55
68
 
56
- <DropDown bind:this={dropDown} tippyProps={{ onHidden: updateURL }} class="max-h-full">
57
- {#snippet activator()}
58
- <button class="min-width-0 btn flex-nowrap btn-sm {klass}">
59
- <CalendarRangeIcon class="opacity-60" size={20} />
60
- {#if isValidPeriod}
61
- <span
62
- transition:slide={{ axis: 'x', duration: 200 }}
63
- class="text-xs font-medium whitespace-nowrap opacity-80 {classLabel}"
64
- >
65
- {getLabel(range)}
66
- </span>
67
- {/if}
68
- </button>
69
- {/snippet}
69
+ <button
70
+ class={['min-width-0 btn flex-nowrap btn-sm', !isValidPeriod && 'btn-square', klass]}
71
+ {...popover.trigger}
72
+ >
73
+ <CalendarRangeIcon class="opacity-70" size={20} />
74
+ {#if isValidPeriod}
75
+ <span
76
+ transition:slide={{ axis: 'x', duration: 200 }}
77
+ class="text-xs font-medium whitespace-nowrap opacity-80 {classLabel}"
78
+ >
79
+ {getLabel(range)}
80
+ </span>
81
+ {/if}
82
+ </button>
70
83
 
84
+ <div {...popover.content} class="rounded-box border bg-base-100 p-1 shadow-xl">
71
85
  <RangePicker bind:this={rangePicker} numberOfMonths={1} bind:range {minDate} {maxDate} />
72
86
 
73
87
  <div class="flex gap-2 p-2">
74
- <!--
75
- <InputString label="A partir de" bind:value={range.start} class="grow" />
76
- <InputString label="Jusqu'à" bind:value={range.end} class="grow" />
77
- -->
78
- <span>TODO: same problème with input...</span>
88
+ <InputDateTime label="À partir de" bind:value={range.start} class="grow" />
89
+ <InputDateTime label="Jusqu'à" bind:value={range.end} class="grow" />
79
90
  </div>
80
91
 
81
92
  <div class="m-2 flex justify-end gap-2">
@@ -86,12 +97,18 @@
86
97
  onclick={() => {
87
98
  range = { start: null, end: null }
88
99
  rangePicker.clear()
89
- dropDown.hide()
100
+ popover.hide()
90
101
  }}
91
102
  >
92
103
  Effacer
93
104
  </button>
94
105
  {/if}
95
- <button class="btn" onclick={() => dropDown.hide()}> Valider </button>
106
+ <button class="btn" onclick={() => popover.hide()}> Valider </button>
96
107
  </div>
97
- </DropDown>
108
+ </div>
109
+
110
+ <style>
111
+ div[popover] {
112
+ border-color: color-mix(in oklab, var(--color-base-content) 20%, #0000);
113
+ }
114
+ </style>
@@ -1,7 +1,7 @@
1
1
  import { type RangeAsDate } from './index.js';
2
2
  type $$ComponentProps = {
3
3
  key?: string;
4
- range: RangeAsDate;
4
+ range?: RangeAsDate;
5
5
  minDate?: Date | number | string;
6
6
  maxDate?: Date | number | string;
7
7
  class?: string;
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="Item extends ItemBase">
2
- import type { Snippet } from 'svelte'
2
+ import { type Snippet, untrack } from 'svelte'
3
3
  import { afterNavigate } from '$app/navigation'
4
4
  import {
5
5
  context,
@@ -35,21 +35,18 @@
35
35
  onclick?: (item?: Item) => void
36
36
  } = $props()
37
37
 
38
- $effect(() => {
39
- const { KEY_FIELDS_VISIBLE, KEY_FIELDS_HIDDEN, KEY_FIELDS_ORDER } = createKeys(key)
40
- context.set(key, {
41
- KEY_FIELDS_VISIBLE,
42
- KEY_FIELDS_HIDDEN,
43
- KEY_FIELDS_ORDER
44
- })
45
- })
38
+ // Posé à l'initialisation et non dans un `$effect`: un effet ne tourne pas au rendu
39
+ // serveur, et `TableFieldsEdition` lirait un contexte vide. `key` identifie la table
40
+ // pour toute sa durée de vie.
41
+ const tableKey = untrack(() => key)
42
+ context.set(tableKey, createKeys(tableKey))
46
43
 
47
44
  const initFields = () => (fields = syncFieldsWithParams(key, fields))
48
45
  initFields()
49
46
  afterNavigate(initFields)
50
47
  </script>
51
48
 
52
- <div class="{klass} overflow-x-auto rounded-lg border bg-base-100" class:min-h-[320px]={!hideBody}>
49
+ <div class="{klass} overflow-x-auto rounded-box border bg-base-100" class:min-h-[320px]={!hideBody}>
53
50
  <table class="table relative">
54
51
  <TableHead {fields} {key} {onCreateField} />
55
52
  {#if !hideBody && items.length}
@@ -1,4 +1,4 @@
1
- import type { Snippet } from 'svelte';
1
+ import { type Snippet } from 'svelte';
2
2
  import { type ItemBase, type TableField } from './index.js';
3
3
  declare function $$render<Item extends ItemBase>(): {
4
4
  props: {
@@ -1,18 +1,20 @@
1
1
  <script lang="ts" generics="Item extends ItemBase">
2
2
  import {
3
3
  CheckIcon,
4
- CircleCheckIcon,
5
- CircleIcon,
4
+ DotIcon,
6
5
  EllipsisIcon,
6
+ FunnelIcon,
7
7
  GripIcon,
8
+ LockKeyholeIcon,
9
+ MoveVerticalIcon,
8
10
  PlusIcon
9
11
  } from '@lucide/svelte'
10
12
  import { goto } from '$app/navigation'
11
13
  import { page } from '$app/state'
12
14
  import { listEditable } from '../../action/list/index.js'
13
15
  import { tip } from '../../action/tip.js'
14
- import { param, urlParam } from '../../state/param.svelte.js'
15
- import { DropDown } from '../menu/index.js'
16
+ import { Popover } from '../../popover/index.js'
17
+ import { param, urlParam } from '../../state/param.js'
16
18
  import { context } from './context.js'
17
19
  import type { ItemBase, TableField } from './index.js'
18
20
  import { jsonParse } from '../../utils/jsonParse.js'
@@ -64,22 +66,19 @@
64
66
  </script>
65
67
 
66
68
  <th class="sticky right-0 z-10 p-0 px-1" align="right">
67
- <DropDown
68
- hideOnNav={false}
69
- class="max-h-none px-0"
70
- tippyProps={{ appendTo: () => document.body, placement: 'bottom-end' }}
71
- >
72
- {#snippet activator()}
69
+ <Popover placement="bottom-end" class="px-0 py-1">
70
+ {#snippet trigger(popover)}
73
71
  <button
74
72
  type="button"
75
73
  class="btn btn-square btn-ghost backdrop-blur btn-sm"
76
- use:tip={{ content: 'Dénfinir les champs' }}
74
+ use:tip={{ content: 'Modifier les colonnes' }}
75
+ {...popover.trigger}
77
76
  >
78
77
  <EllipsisIcon />
79
78
  </button>
80
79
  {/snippet}
81
80
 
82
- {#snippet children({ tip })}
81
+ {#snippet children(popover)}
83
82
  {#if onCreateField}
84
83
  <div class="bordered flex items-center gap-2 border-b pr-1 pb-1 pl-2">
85
84
  <span class=" font-semibold opacity-70">Champs</span>
@@ -88,7 +87,7 @@
88
87
  class="btn ml-auto btn-square btn-sm"
89
88
  onclick={() => {
90
89
  if (onCreateField) onCreateField()
91
- tip?.hide()
90
+ popover.hide()
92
91
  }}
93
92
  >
94
93
  <PlusIcon title="Ajouter un champ" />
@@ -108,35 +107,38 @@
108
107
  <a
109
108
  draggable="false"
110
109
  href={getFieldHref(field)}
111
- class="menu-item w-full"
110
+ class="menu-item group w-full pr-1"
112
111
  class:disabled={field.locked}
113
112
  data-sveltekit-keepfocus
114
113
  data-sveltekit-replacestate
115
114
  data-sveltekit-noscroll
116
115
  >
117
116
  {#if field.locked}
118
- <CheckIcon class="fill-base-content/50" size={21} />
117
+ <LockKeyholeIcon class="mx-0.5 text-primary" size={17} />
119
118
  {:else if param.has(field.key)}
120
- <CircleCheckIcon class="fill-primary" size={21} />
119
+ <FunnelIcon class="mx-0.5 text-primary" size={17} />
121
120
  {:else if field._visible}
122
- <CheckIcon class="fill-success" size={21} />
121
+ <CheckIcon class="text-success" size={21} />
123
122
  {:else}
124
- <CircleIcon class="fill-base-content/50" size={21} />
123
+ <DotIcon class="text-base-content/50" size={21} />
125
124
  {/if}
126
125
 
127
- <span>{field.label}</span>
126
+ <span class=" font-normal">{field.label}</span>
128
127
 
129
128
  <span
130
- class="drag-button btn ml-auto btn-square btn-ghost btn-xs"
129
+ class={[
130
+ 'drag-button btn ml-auto btn-square btn-soft btn-xs',
131
+ 'opacity-0 group-hover:opacity-100'
132
+ ]}
131
133
  onclick={(e) => e.preventDefault()}
132
134
  role="none"
133
135
  >
134
- <GripIcon size={18} class="fill-base-content/80" />
136
+ <MoveVerticalIcon size={18} class="text-base-content/70" />
135
137
  </span>
136
138
  </a>
137
139
  {/each}
138
140
  </div>
139
141
  </div>
140
142
  {/snippet}
141
- </DropDown>
143
+ </Popover>
142
144
  </th>
@@ -34,7 +34,11 @@
34
34
  {:else if field.type === 'date'}
35
35
  <TableHeadDate {field} />
36
36
  {:else if field.options}
37
- <TableHeadSelect {field} options={field.options} />
37
+ <TableHeadSelect
38
+ {field}
39
+ options={field.options}
40
+ multiSelect={field.type === 'multiselect'}
41
+ />
38
42
  {/if}
39
43
  {/each}
40
44
  <TableFieldsEdition {fields} {key} {onCreateField} />
@@ -2,8 +2,8 @@
2
2
  import { ChevronDownIcon, PlusIcon, SaveIcon } from '@lucide/svelte'
3
3
  import { page } from '$app/state'
4
4
 
5
+ import { Popover } from '../../popover/index.js'
5
6
  import { Dialog } from '../dialog/index.js'
6
- import { DropDown } from '../menu/index.js'
7
7
  import { SvelteURLSearchParams } from 'svelte/reactivity'
8
8
 
9
9
  // import { InputText } from '../input/index.js';
@@ -41,69 +41,74 @@
41
41
 
42
42
  /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable
43
43
  @typescript-eslint/no-unused-vars */
44
- <DropDown>
45
- {#snippet activator()}
44
+ <Popover class="p-1">
45
+ {#snippet trigger(popover)}
46
46
  <button
47
47
  type="button"
48
48
  class="menu-item bordered gap-1 rounded-lg border font-semibold opacity-90 btn-sm"
49
+ {...popover.trigger}
49
50
  >
50
51
  <span>{isNewView ? 'Nouvelle vue' : selectedView?.name || 'Vue simple'}</span>
51
52
  <ChevronDownIcon size={20} class="translate-x-1 translate-y-px opacity-90" />
52
53
  </button>
53
54
  {/snippet}
54
55
 
55
- <ul class="flex flex-col gap-1">
56
- {#if isNewView}
57
- <li>
58
- <button
59
- type="button"
60
- class="menu-item w-full pr-1.5"
61
- onclick={() => {
62
- selectedView = undefined
63
- dialog?.showModal()
64
- }}
65
- >
66
- <span>Ajouter la nouvelle vue</span>
67
- <PlusIcon class="ml-auto opacity-80" size={21} />
68
- </button>
69
- <hr class="my-1" />
70
- </li>
71
- {/if}
72
-
73
- <li>
74
- <a href={page.url.pathname} class="menu-item" class:active={!query}>
75
- <span class="grow">Vue simple</span>
76
- </a>
77
- </li>
78
-
79
- {#each views as view (view.id)}
80
- <li>
81
- <a
82
- href="{page.url.pathname}?{view.query}"
83
- class="menu-item group pr-1"
84
- class:active={view.id === selectedView?.id}
85
- >
86
- <span class="grow">{view.name}</span>
56
+ {#snippet children(popover)}
57
+ <ul class="flex flex-col gap-1">
58
+ {#if isNewView}
59
+ <li>
87
60
  <button
88
61
  type="button"
89
- class="btn btn-square rounded btn-ghost btn-xs"
90
- onclick={(e) => {
91
- e.preventDefault()
92
- selectedView = view
62
+ class="menu-item w-full pr-1.5"
63
+ onclick={() => {
64
+ selectedView = undefined
93
65
  dialog?.showModal()
66
+ popover.hide()
94
67
  }}
95
68
  >
96
- <SaveIcon
97
- class="opacity-50 group-hover:opacity-80"
98
- size={18}
99
- title="Modifier la vue '{view.name}'"
100
- />
69
+ <span>Ajouter la nouvelle vue</span>
70
+ <PlusIcon class="ml-auto opacity-80" size={21} />
101
71
  </button>
72
+ <hr class="my-1" />
73
+ </li>
74
+ {/if}
75
+
76
+ <li>
77
+ <a href={page.url.pathname} class="menu-item" class:active={!query} onclick={popover.hide}>
78
+ <span class="grow">Vue simple</span>
102
79
  </a>
103
80
  </li>
104
- {/each}
105
- </ul>
106
- </DropDown>
81
+
82
+ {#each views as view (view.id)}
83
+ <li>
84
+ <a
85
+ href="{page.url.pathname}?{view.query}"
86
+ class="menu-item group pr-1"
87
+ class:active={view.id === selectedView?.id}
88
+ onclick={popover.hide}
89
+ >
90
+ <span class="grow">{view.name}</span>
91
+ <button
92
+ type="button"
93
+ class="btn btn-square rounded btn-ghost btn-xs"
94
+ onclick={(e) => {
95
+ e.preventDefault()
96
+ selectedView = view
97
+ dialog?.showModal()
98
+ }}
99
+ >
100
+ <SaveIcon
101
+ class="opacity-50 group-hover:opacity-80"
102
+ size={18}
103
+ title="Modifier la vue '{view.name}'"
104
+ />
105
+ </button>
106
+ </a>
107
+ </li>
108
+ {/each}
109
+ </ul>
110
+ {/snippet}
111
+ </Popover>
107
112
 
108
113
  <Dialog bind:dialog>
109
114
  {#snippet header()}
@@ -6,8 +6,8 @@
6
6
 
7
7
  <td>
8
8
  {#if cell}
9
- <CheckIcon class="fill-success" />
9
+ <CheckIcon class="text-success" />
10
10
  {:else}
11
- <XIcon class="fill-error" />
11
+ <XIcon class="text-error" />
12
12
  {/if}
13
13
  </td>
@@ -2,8 +2,9 @@
2
2
  import { CalendarArrowDownIcon, CalendarArrowUpIcon, CalendarSearchIcon } from '@lucide/svelte'
3
3
  import { goto } from '$app/navigation'
4
4
  import { page } from '$app/state'
5
- import { urlParam } from '../../../state/param.svelte.js'
6
- import { DropDown } from '../../menu/index.js'
5
+ import { InputDateTime } from '../../../input/index.js'
6
+ import { Popover, type PopoverType } from '../../../popover/index.js'
7
+ import { urlParam } from '../../../state/param.js'
7
8
  import { formatRange } from '../../range/format.js'
8
9
  import { type RangeAsDate, RangePicker } from '../../range/index.js'
9
10
  import type { ItemBase, TableField } from '../index.js'
@@ -12,7 +13,6 @@
12
13
 
13
14
  let { field }: { field: Omit<TableField<Item>, 'cell'> } = $props()
14
15
 
15
- let dropDown: DropDown
16
16
  let rangePicker: RangePicker
17
17
 
18
18
  let initialValue = jsonParse<{
@@ -59,11 +59,11 @@
59
59
  )
60
60
  }
61
61
 
62
- function handleReset() {
62
+ function handleReset(popover: PopoverType) {
63
63
  isValidPeriod = false
64
64
  range.start = null
65
65
  range = { start: null, end: null }
66
- dropDown.hide()
66
+ popover.hide()
67
67
  rangePicker.clear()
68
68
  goto(urlParam.without(field.key, 'skip', 'take'), {
69
69
  replaceState: true,
@@ -74,15 +74,10 @@
74
74
  </script>
75
75
 
76
76
  <th class="p-1">
77
- <DropDown
78
- bind:this={dropDown}
79
- tippyProps={{ appendTo: () => document.body }}
80
- hideOnNav={false}
81
- class="max-h-none"
82
- >
83
- {#snippet activator()}
84
- <button class="menu-item min-h-8 w-full flex-wrap gap-y-1">
85
- <div class="flex gap-2">
77
+ <Popover class="p-1">
78
+ {#snippet trigger(popover)}
79
+ <button class="menu-item min-h-8 w-full flex-wrap gap-y-1" {...popover.trigger}>
80
+ <div class="flex items-center gap-2">
86
81
  <span>{field.label}</span>
87
82
  {#if !isValidPeriod}
88
83
  <CalendarSearchIcon size={15} class="opacity-50" />
@@ -102,49 +97,61 @@
102
97
  </button>
103
98
  {/snippet}
104
99
 
105
- {#if field.sortable !== false}
106
- <OrderButtons
107
- bind:order
108
- onChange={() => {
109
- updateUrl()
110
- dropDown.hide()
111
- }}
112
- IconAsc={CalendarArrowDownIcon}
113
- IconDesc={CalendarArrowUpIcon}
114
- />
115
- {/if}
100
+ {#snippet children(popover)}
101
+ {#if field.sortable !== false}
102
+ <OrderButtons
103
+ bind:order
104
+ onChange={() => {
105
+ updateUrl()
106
+ popover.hide()
107
+ }}
108
+ IconAsc={CalendarArrowDownIcon}
109
+ IconDesc={CalendarArrowUpIcon}
110
+ />
111
+ {/if}
116
112
 
117
- <form
118
- onsubmit={(e) => {
119
- e.preventDefault()
120
- dropDown.hide()
121
- }}
122
- data-sveltekit-replacestate
123
- class="flex flex-col font-normal"
124
- class:mt-6={field.sortable !== false}
125
- >
126
- <RangePicker
127
- bind:this={rangePicker}
128
- numberOfMonths={1}
129
- on:change={({ detail: newRange }) => {
130
- range = newRange
131
- updateUrl()
113
+ <form
114
+ onsubmit={(e) => {
115
+ e.preventDefault()
116
+ popover.hide()
132
117
  }}
133
- />
134
-
135
- <input class="hidden" type="text" name="start" value={range.start?.toJSON()} />
136
- <input class="hidden" type="text" name="end" value={range.end?.toJSON()} />
118
+ data-sveltekit-replacestate
119
+ class="flex flex-col font-normal"
120
+ class:mt-6={field.sortable !== false}
121
+ >
122
+ <RangePicker
123
+ bind:this={rangePicker}
124
+ numberOfMonths={1}
125
+ onchange={(newRange) => {
126
+ range = newRange
127
+ updateUrl()
128
+ }}
129
+ />
137
130
 
138
- <div class="m-2 flex gap-2">
139
- <!-- <InputTime label="A partir de" bind:value={range.start} class="grow" on:input={updateUrl} />
140
- <InputTime label="Jusqu'à" bind:value={range.end} class="grow" on:input={updateUrl} /> -->
141
- <span>TODO: same problème with input...</span>
142
- </div>
131
+ <div class="m-2 flex gap-2">
132
+ <InputDateTime
133
+ label="À partir de"
134
+ name="start"
135
+ bind:value={range.start}
136
+ class="grow"
137
+ onchange={updateUrl}
138
+ />
139
+ <InputDateTime
140
+ label="Jusqu'à"
141
+ name="end"
142
+ bind:value={range.end}
143
+ class="grow"
144
+ onchange={updateUrl}
145
+ />
146
+ </div>
143
147
 
144
- <div class="m-2 flex flex-row-reverse gap-2">
145
- <button class="btn">Ok</button>
146
- <button class="btn btn-ghost" type="button" onclick={handleReset}>Effacer</button>
147
- </div>
148
- </form>
149
- </DropDown>
148
+ <div class="m-2 flex flex-row-reverse gap-2">
149
+ <button class="btn">Ok</button>
150
+ <button class="btn btn-ghost" type="button" onclick={() => handleReset(popover)}>
151
+ Effacer
152
+ </button>
153
+ </div>
154
+ </form>
155
+ {/snippet}
156
+ </Popover>
150
157
  </th>