fuma 2.0.2 → 2.0.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 (58) hide show
  1. package/dist/ui/button/ButtonCopy.svelte +5 -2
  2. package/dist/ui/button/ButtonCopy.svelte.d.ts +2 -0
  3. package/dist/ui/form/Form.svelte +2 -2
  4. package/dist/ui/input/FormControl.svelte +3 -3
  5. package/dist/ui/input/InputSearch.svelte +34 -22
  6. package/dist/ui/input/InputSearch.svelte.d.ts +10 -8
  7. package/dist/ui/input/InputText.svelte +22 -9
  8. package/dist/ui/input/InputText.svelte.d.ts +7 -21
  9. package/dist/ui/input/InputTime.svelte +3 -2
  10. package/dist/ui/input/InputTime.svelte.d.ts +25 -2
  11. package/dist/ui/input/textRich/InputTextRich.svelte +5 -0
  12. package/dist/ui/input/textRich/InputTextRich.svelte.d.ts +11 -1
  13. package/dist/ui/input/textRich/ToolsBar.svelte +1 -4
  14. package/dist/ui/input/textRich/ToolsBar.svelte.d.ts +2 -0
  15. package/dist/ui/menu/DropDown.svelte +5 -5
  16. package/dist/ui/menu/DropDown.svelte.d.ts +12 -4
  17. package/dist/ui/range/RangePicker.svelte +2 -2
  18. package/dist/ui/range/RangePicker.svelte.d.ts +2 -2
  19. package/dist/ui/range/RangePickerButton.svelte +7 -4
  20. package/dist/ui/range/RangePickerButton.svelte.d.ts +4 -2
  21. package/dist/ui/table/Table.svelte +29 -15
  22. package/dist/ui/table/Table.svelte.d.ts +20 -28
  23. package/dist/ui/table/TableBody.svelte +21 -21
  24. package/dist/ui/table/TableBody.svelte.d.ts +19 -25
  25. package/dist/ui/table/TableCell.svelte +14 -15
  26. package/dist/ui/table/TableCell.svelte.d.ts +16 -21
  27. package/dist/ui/table/TableFieldsEdition.svelte +2 -2
  28. package/dist/ui/table/TableHead.svelte +32 -20
  29. package/dist/ui/table/TableHead.svelte.d.ts +7 -32
  30. package/dist/ui/table/cell/TableCellArray.svelte +5 -8
  31. package/dist/ui/table/cell/TableCellArray.svelte.d.ts +5 -20
  32. package/dist/ui/table/cell/TableCellBoolean.svelte +3 -2
  33. package/dist/ui/table/cell/TableCellBoolean.svelte.d.ts +5 -19
  34. package/dist/ui/table/cell/TableCellNumber.svelte +2 -2
  35. package/dist/ui/table/cell/TableCellNumber.svelte.d.ts +5 -19
  36. package/dist/ui/table/cell/TableCellString.svelte +5 -5
  37. package/dist/ui/table/cell/TableCellString.svelte.d.ts +25 -19
  38. package/dist/ui/table/field.d.ts +26 -49
  39. package/dist/ui/table/field.js +6 -7
  40. package/dist/ui/table/head/OrderButtons.svelte +40 -0
  41. package/dist/ui/table/head/OrderButtons.svelte.d.ts +24 -0
  42. package/dist/ui/table/head/TableHeadBoolean.svelte +2 -2
  43. package/dist/ui/table/head/TableHeadBoolean.svelte.d.ts +28 -17
  44. package/dist/ui/table/head/TableHeadDate.svelte +91 -25
  45. package/dist/ui/table/head/TableHeadDate.svelte.d.ts +5 -19
  46. package/dist/ui/table/head/TableHeadDefault.svelte +1 -2
  47. package/dist/ui/table/head/TableHeadDefault.svelte.d.ts +4 -18
  48. package/dist/ui/table/head/TableHeadNumber.svelte +33 -12
  49. package/dist/ui/table/head/TableHeadNumber.svelte.d.ts +28 -17
  50. package/dist/ui/table/head/TableHeadSelect.svelte +2 -2
  51. package/dist/ui/table/head/TableHeadSelect.svelte.d.ts +31 -20
  52. package/dist/ui/table/head/TableHeadString.svelte +9 -9
  53. package/dist/ui/table/head/TableHeadString.svelte.d.ts +4 -18
  54. package/dist/ui/table/head/index.d.ts +6 -0
  55. package/dist/ui/table/head/index.js +6 -22
  56. package/dist/validation/zod.d.ts +8 -0
  57. package/dist/validation/zod.js +4 -2
  58. package/package.json +8 -8
@@ -1,79 +1,56 @@
1
- import type { ComponentAndProps, Primitive } from '../../utils/component.js';
2
1
  import type { Options } from '../../utils/options.js';
3
- export type TableFieldType = 'string' | 'textarea' | 'number' | 'boolean' | 'select' | 'multiselect' | 'date';
4
- export type TableField<Item = any> = TableFieldCommon & (TableFieldUntyped<Item> | TableFieldPrimitive<Item> | TableFieldSelect<Item> | TableFieldMultiselect<Item>);
5
- type TableFieldCommon = {
2
+ import type { Snippet } from 'svelte';
3
+ import type { Primitive } from '../../utils/component.js';
4
+ export type ItemBase = {
5
+ id: string | number;
6
+ };
7
+ export type TableField<Item = ItemBase> = (TableFieldCommon<Item> & TableFieldPrimitve) | (TableFieldCommon<Item> & TableFieldSelect);
8
+ type TableFieldCommon<Item> = {
6
9
  key: string;
7
10
  label: string;
8
- type?: TableFieldType;
9
11
  options?: Options;
10
12
  hint?: string;
11
13
  locked?: boolean;
12
14
  visible?: boolean;
15
+ sortable?: boolean;
13
16
  /** Internal usage */
14
- $visible?: boolean;
15
- };
16
- type TableFieldUntyped<Item = any> = {
17
- getCell: (item: Item) => ComponentAndProps[] | ComponentAndProps | Primitive[] | Primitive | undefined | null;
18
- head?: ComponentAndProps | ((field: TableField) => ComponentAndProps);
17
+ _visible?: boolean;
18
+ cell: ((item: Item) => Snippet<[item: Item]>) | ((item: Item) => null | undefined | Primitive | Primitive[]);
19
+ head?: Snippet<[item: Item]>;
19
20
  };
20
- type TableFieldPrimitive<Item = any> = {
21
- type: Exclude<TableFieldType, 'select' | 'multiselect'>;
22
- getCell: (item: Item) => ComponentAndProps[] | ComponentAndProps | Primitive | undefined | null;
21
+ type TableFieldPrimitve = {
22
+ type?: 'string' | 'textarea' | 'number' | 'boolean' | 'date';
23
23
  };
24
- type TableFieldSelect<Item = any> = {
25
- type: 'select';
26
- getCell: (item: Item) => Primitive | undefined | null;
27
- options: Options;
28
- };
29
- type TableFieldMultiselect<Item = any> = {
30
- type: 'multiselect';
31
- getCell: (item: Item) => Primitive[] | undefined | null;
24
+ type TableFieldSelect = {
25
+ type: 'select' | 'multiselect';
32
26
  options: Options;
33
27
  };
34
28
  /**
35
29
  * Initialise fields from url query
36
30
  */
37
- export declare function syncFieldsWithParams(tablekey: string, fields: TableField[]): ({
38
- $visible: boolean;
39
- key: string;
40
- label: string;
41
- type?: TableFieldType;
42
- options?: Options;
43
- hint?: string;
44
- locked?: boolean;
45
- visible?: boolean;
46
- getCell: (item: any) => ComponentAndProps[] | ComponentAndProps | Primitive[] | Primitive | undefined | null;
47
- head?: ComponentAndProps | ((field: TableField) => ComponentAndProps);
48
- } | {
49
- $visible: boolean;
31
+ export declare function syncFieldsWithParams<Item extends ItemBase>(tablekey: string, fields: TableField<Item>[]): ({
32
+ _visible: boolean;
50
33
  key: string;
51
34
  label: string;
52
- type: "string" | "number" | "boolean" | "textarea" | "date";
53
35
  options?: Options;
54
36
  hint?: string;
55
37
  locked?: boolean;
56
38
  visible?: boolean;
57
- getCell: (item: any) => ComponentAndProps[] | ComponentAndProps | Primitive | undefined | null;
58
- } | {
59
- $visible: boolean;
60
- key: string;
61
- label: string;
62
- type: "select";
63
- options: (Options | undefined) & Options;
64
- hint?: string;
65
- locked?: boolean;
66
- visible?: boolean;
67
- getCell: (item: any) => Primitive | undefined | null;
39
+ sortable?: boolean;
40
+ cell: ((item: Item) => Snippet<[item: Item]>) | ((item: Item) => null | undefined | Primitive | Primitive[]);
41
+ head?: Snippet<[item: Item]> | undefined;
42
+ type?: "string" | "textarea" | "number" | "boolean" | "date";
68
43
  } | {
69
- $visible: boolean;
44
+ _visible: boolean;
70
45
  key: string;
71
46
  label: string;
72
- type: "multiselect";
73
47
  options: (Options | undefined) & Options;
74
48
  hint?: string;
75
49
  locked?: boolean;
76
50
  visible?: boolean;
77
- getCell: (item: any) => Primitive[] | undefined | null;
51
+ sortable?: boolean;
52
+ cell: ((item: Item) => Snippet<[item: Item]>) | ((item: Item) => null | undefined | Primitive | Primitive[]);
53
+ head?: Snippet<[item: Item]> | undefined;
54
+ type: "select" | "multiselect";
78
55
  })[];
79
56
  export {};
@@ -1,5 +1,4 @@
1
- import { page } from '$app/stores';
2
- import { get } from 'svelte/store';
1
+ import { page } from '$app/state';
3
2
  import { jsonParse } from '../../utils/jsonParse.js';
4
3
  import { createKeys } from './context.js';
5
4
  /**
@@ -7,14 +6,14 @@ import { createKeys } from './context.js';
7
6
  */
8
7
  export function syncFieldsWithParams(tablekey, fields) {
9
8
  const { KEY_FIELDS_VISIBLE, KEY_FIELDS_HIDDEN, KEY_FIELDS_ORDER } = createKeys(tablekey);
10
- const { url: { searchParams } } = get(page);
11
- const fieldsVisible = jsonParse(searchParams.get(KEY_FIELDS_VISIBLE), []);
12
- const fieldsHidden = jsonParse(searchParams.get(KEY_FIELDS_HIDDEN), []);
13
- const fieldsOrder = jsonParse(searchParams.get(KEY_FIELDS_ORDER), []);
9
+ const getParam = (key) => page.url.searchParams.get(key);
10
+ const fieldsVisible = jsonParse(getParam(KEY_FIELDS_VISIBLE), []);
11
+ const fieldsHidden = jsonParse(getParam(KEY_FIELDS_HIDDEN), []);
12
+ const fieldsOrder = jsonParse(getParam(KEY_FIELDS_ORDER), []);
14
13
  // Init correct visible prop
15
14
  const _fields = fields.map((field) => ({
16
15
  ...field,
17
- $visible: field.locked ||
16
+ _visible: field.locked ||
18
17
  (field.visible ? !fieldsHidden.includes(field.key) : fieldsVisible.includes(field.key))
19
18
  }));
20
19
  // Init correct order fields
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ import { Icon } from '../../icon/index.js'
3
+ import { mdiSortAscending, mdiSortDescending } from '@mdi/js'
4
+ import { createEventDispatcher } from 'svelte'
5
+
6
+ type Order = 'asc' | 'desc' | undefined
7
+ export let order: Order
8
+ export let iconAsc = mdiSortAscending
9
+ export let iconDesc = mdiSortDescending
10
+
11
+ const dispatch = createEventDispatcher<{ change: Order }>()
12
+
13
+ const handleOrderClick = (orderBy: 'asc' | 'desc') => () => {
14
+ if (order === orderBy) order = undefined
15
+ else order = orderBy
16
+ dispatch('change', order)
17
+ }
18
+ </script>
19
+
20
+ <div class="p-1 pt-2">
21
+ <span class="text-sm font-semibold opacity-70">Ordre:</span>
22
+ <div class="grid grid-cols-2 gap-2 pt-2">
23
+ <button
24
+ class="btn ring-primary"
25
+ class:ring-2={order === 'asc'}
26
+ on:click={handleOrderClick('asc')}
27
+ >
28
+ <Icon path={iconAsc} />
29
+ <span>Ascendant</span>
30
+ </button>
31
+ <button
32
+ class="btn ring-primary"
33
+ class:ring-2={order === 'desc'}
34
+ on:click={handleOrderClick('desc')}
35
+ >
36
+ <Icon path={iconDesc} />
37
+ <span>Descendant</span>
38
+ </button>
39
+ </div>
40
+ </div>
@@ -0,0 +1,24 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: Props & {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const OrderButtons: $$__sveltets_2_IsomorphicComponent<{
15
+ order: "desc" | "asc" | undefined;
16
+ iconAsc?: string;
17
+ iconDesc?: string;
18
+ }, {
19
+ change: CustomEvent<"desc" | "asc" | undefined>;
20
+ } & {
21
+ [evt: string]: CustomEvent<any>;
22
+ }, {}, {}, string>;
23
+ type OrderButtons = InstanceType<typeof OrderButtons>;
24
+ export default OrderButtons;
@@ -1,9 +1,9 @@
1
- <script lang="ts">
1
+ <script lang="ts" generics="Item extends {id: string}">
2
2
  import { mdiCheck, mdiClose } from '@mdi/js'
3
3
  import type { TableField } from '../index.js'
4
4
  import TableHeadSelect from './TableHeadSelect.svelte'
5
5
 
6
- export let field: TableField
6
+ export let field: TableField<Item>
7
7
  </script>
8
8
 
9
9
  <TableHeadSelect
@@ -1,21 +1,32 @@
1
1
  import type { TableField } from '../index.js';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
2
+ declare class __sveltets_Render<Item extends {
3
+ id: string;
4
+ }> {
5
+ props(): {
6
+ field: TableField<Item>;
12
7
  };
13
- z_$$bindings?: Bindings;
8
+ events(): {} & {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots(): {};
12
+ bindings(): string;
13
+ exports(): {};
14
+ }
15
+ interface $$IsomorphicComponent {
16
+ new <Item extends {
17
+ id: string;
18
+ }>(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']>> & {
19
+ $$bindings?: ReturnType<__sveltets_Render<Item>['bindings']>;
20
+ } & ReturnType<__sveltets_Render<Item>['exports']>;
21
+ <Item extends {
22
+ id: string;
23
+ }>(internal: unknown, props: ReturnType<__sveltets_Render<Item>['props']> & {
24
+ $$events?: ReturnType<__sveltets_Render<Item>['events']>;
25
+ }): ReturnType<__sveltets_Render<Item>['exports']>;
26
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
14
27
  }
15
- declare const TableHeadBoolean: $$__sveltets_2_IsomorphicComponent<{
16
- field: TableField;
17
- }, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type TableHeadBoolean = InstanceType<typeof TableHeadBoolean>;
28
+ declare const TableHeadBoolean: $$IsomorphicComponent;
29
+ type TableHeadBoolean<Item extends {
30
+ id: string;
31
+ }> = InstanceType<typeof TableHeadBoolean<Item>>;
21
32
  export default TableHeadBoolean;
@@ -1,64 +1,88 @@
1
1
  <script lang="ts">
2
2
  import { goto } from '$app/navigation'
3
- import { page } from '$app/stores'
4
- import { mdiCalendarFilterOutline } from '@mdi/js'
3
+ import { page } from '$app/state'
4
+ import {
5
+ mdiCalendarFilterOutline,
6
+ mdiSortClockAscendingOutline,
7
+ mdiSortClockDescendingOutline
8
+ } from '@mdi/js'
5
9
 
6
10
  import { DropDown } from '../../menu/index.js'
7
11
  import { InputTime } from '../../input/index.js'
8
12
  import type { TableField } from '../index.js'
9
13
  import { formatRange } from '../../range/format.js'
10
- import { RangePicker } from '../../range/index.js'
14
+ import { RangePicker, type RangeAsDate } from '../../range/index.js'
11
15
  import { urlParam } from '../../../store/param.js'
12
16
  import { jsonParse } from '../../../utils/jsonParse.js'
13
17
  import { Icon } from '../../icon/index.js'
18
+ import OrderButtons from './OrderButtons.svelte'
14
19
 
15
- export let field: Omit<TableField, 'getCell' | 'type'>
20
+ let { field }: { field: TableField } = $props()
16
21
 
17
22
  let dropDown: DropDown
18
23
  let rangePicker: RangePicker
19
- const initialValue = jsonParse<{ start?: string; end?: string }>(
20
- $page.url.searchParams.get(field.key),
24
+ let initialValue = jsonParse<{ start?: string; end?: string; order?: 'asc' | 'desc' }>(
25
+ page.url.searchParams.get(field.key),
21
26
  {}
22
27
  )
23
28
 
24
- let range = {
29
+ let range: RangeAsDate = $state({
25
30
  start: initialValue.start ? new Date(initialValue.start) : null,
26
31
  end: initialValue.end ? new Date(initialValue.end) : null
27
- }
32
+ })
33
+ let order = $state(initialValue.order)
28
34
 
29
- $: isValidPeriod = !!range.start && !!range.end
35
+ let isValidPeriod = $derived(!!range.start && !!range.end)
30
36
 
31
- function handleSubmit() {
32
- dropDown.hide()
33
- if (!isValidPeriod) return
37
+ function updateUrl() {
38
+ isValidPeriod = !!range.start && !!range.end
39
+ if (!isValidPeriod && !order) {
40
+ goto($urlParam.without(field.key, 'skip', 'take'), {
41
+ replaceState: true,
42
+ noScroll: true,
43
+ keepFocus: true
44
+ })
45
+ return
46
+ }
34
47
  goto(
35
48
  $urlParam.with(
36
49
  {
37
50
  [field.key]: JSON.stringify({
38
- start: range.start?.toJSON(),
39
- end: range.end?.toJSON()
51
+ ...(isValidPeriod
52
+ ? {
53
+ start: range.start?.toJSON(),
54
+ end: range.end?.toJSON()
55
+ }
56
+ : {}),
57
+ ...(order ? { order } : {})
40
58
  })
41
59
  },
42
60
  'skip',
43
61
  'take'
44
62
  ),
45
- { replaceState: true, noScroll: true }
63
+ { replaceState: true, noScroll: true, keepFocus: true }
46
64
  )
47
65
  }
48
66
 
49
67
  function handleReset() {
50
- dropDown.hide()
68
+ isValidPeriod = false
69
+ range.start = null
51
70
  range = { start: null, end: null }
71
+ dropDown.hide()
52
72
  rangePicker.clear()
53
- goto($urlParam.without(field.key, 'skip', 'take'), { replaceState: true, noScroll: true })
73
+ goto($urlParam.without(field.key, 'skip', 'take'), {
74
+ replaceState: true,
75
+ noScroll: true,
76
+ keepFocus: true
77
+ })
54
78
  }
55
79
  </script>
56
80
 
57
81
  <th class="p-1">
58
82
  <DropDown
59
83
  bind:this={dropDown}
60
- on:mouseLeave={handleSubmit}
61
84
  tippyProps={{ appendTo: () => document.body }}
85
+ hideOnNav={false}
62
86
  class="max-h-none"
63
87
  >
64
88
  <button slot="activator" class="menu-item min-h-8 w-full flex-wrap gap-y-1">
@@ -74,26 +98,68 @@
74
98
  {formatRange(range)}
75
99
  </span>
76
100
  {/if}
101
+ {#if order}
102
+ <Icon
103
+ path={order === 'asc' ? mdiSortClockAscendingOutline : mdiSortClockDescendingOutline}
104
+ size={18}
105
+ class="fill-primary"
106
+ />
107
+ {/if}
77
108
  </button>
78
109
 
110
+ {#if field.sortable !== false}
111
+ <OrderButtons
112
+ bind:order
113
+ on:change={() => {
114
+ updateUrl()
115
+ dropDown.hide()
116
+ }}
117
+ iconAsc={mdiSortClockAscendingOutline}
118
+ iconDesc={mdiSortClockDescendingOutline}
119
+ />
120
+ {/if}
121
+
79
122
  <form
80
- class="flex flex-col font-normal"
81
- on:submit|preventDefault={handleSubmit}
123
+ onsubmit={(e) => {
124
+ e.preventDefault()
125
+ dropDown.hide()
126
+ }}
82
127
  data-sveltekit-replacestate
128
+ class="flex flex-col font-normal"
129
+ class:mt-6={field.sortable !== false}
83
130
  >
84
- <RangePicker bind:this={rangePicker} numberOfMonths={1} bind:range />
131
+ <RangePicker
132
+ bind:this={rangePicker}
133
+ numberOfMonths={1}
134
+ on:change={({ detail: newRange }) => {
135
+ range = newRange
136
+ updateUrl()
137
+ }}
138
+ />
85
139
 
86
140
  <input class="hidden" type="text" name="start" value={range.start?.toJSON()} />
87
141
  <input class="hidden" type="text" name="end" value={range.end?.toJSON()} />
88
142
 
89
143
  <div class="m-2 flex gap-2">
90
- <InputTime label="A partir de" bind:value={range.start} enhanceDisabled class="grow" />
91
- <InputTime label="Jusqu'à" bind:value={range.end} enhanceDisabled class="grow" />
144
+ <InputTime
145
+ label="A partir de"
146
+ bind:value={range.start}
147
+ enhanceDisabled
148
+ class="grow"
149
+ on:input={updateUrl}
150
+ />
151
+ <InputTime
152
+ label="Jusqu'à"
153
+ bind:value={range.end}
154
+ enhanceDisabled
155
+ class="grow"
156
+ on:input={updateUrl}
157
+ />
92
158
  </div>
93
159
 
94
160
  <div class="m-2 flex flex-row-reverse gap-2">
95
- <button class="btn"> Valider </button>
96
- <button class="btn btn-ghost" type="button" on:click={handleReset}>Effacer</button>
161
+ <button class="btn">Ok</button>
162
+ <button class="btn btn-ghost" type="button" onclick={handleReset}>Effacer</button>
97
163
  </div>
98
164
  </form>
99
165
  </DropDown>
@@ -1,21 +1,7 @@
1
1
  import type { TableField } from '../index.js';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const TableHeadDate: $$__sveltets_2_IsomorphicComponent<{
16
- field: Omit<TableField, "getCell" | "type">;
17
- }, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type TableHeadDate = InstanceType<typeof TableHeadDate>;
2
+ type $$ComponentProps = {
3
+ field: TableField;
4
+ };
5
+ declare const TableHeadDate: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type TableHeadDate = ReturnType<typeof TableHeadDate>;
21
7
  export default TableHeadDate;
@@ -1,8 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { TableField } from '../index.js'
3
3
  import { tip } from '../../../action/tip.js'
4
-
5
- export let field: TableField
4
+ let { field }: { field: TableField } = $props()
6
5
  </script>
7
6
 
8
7
  <th use:tip={{ disable: !field.hint, content: field.hint }}>
@@ -1,21 +1,7 @@
1
1
  import type { TableField } from '../index.js';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const TableHeadDefault: $$__sveltets_2_IsomorphicComponent<{
2
+ type $$ComponentProps = {
16
3
  field: TableField;
17
- }, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type TableHeadDefault = InstanceType<typeof TableHeadDefault>;
4
+ };
5
+ declare const TableHeadDefault: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type TableHeadDefault = ReturnType<typeof TableHeadDefault>;
21
7
  export default TableHeadDefault;
@@ -1,4 +1,4 @@
1
- <script lang="ts">
1
+ <script lang="ts" generics="Item extends {id: string}">
2
2
  import { onMount } from 'svelte'
3
3
  import type { TippyInstance } from '../../../utils/tippy.js'
4
4
  import debounce from 'debounce'
@@ -10,32 +10,35 @@
10
10
  import { urlParam } from '../../../store/param.js'
11
11
  import { jsonParse } from '../../../utils/jsonParse.js'
12
12
  import type { TableField } from '../field.js'
13
- import { mdiFilterMultipleOutline } from '@mdi/js'
13
+ import { mdiFilterMultipleOutline, mdiSortAscending, mdiSortDescending } from '@mdi/js'
14
14
  import { Icon } from '../../icon/index.js'
15
+ import OrderButtons from './OrderButtons.svelte'
15
16
 
16
- export let field: TableField
17
+ export let field: TableField<Item>
17
18
 
18
19
  let tip: TippyInstance
19
20
  type Range = { min: number | undefined; max: number | undefined }
20
21
 
21
- let { min, max } = initRange($page.url)
22
- onMount(() => page.subscribe(({ url }) => ({ min, max } = initRange(url))))
22
+ let { min, max, order } = initRange($page.url)
23
+ onMount(() => page.subscribe(({ url }) => ({ min, max, order } = initRange(url))))
23
24
 
24
25
  function initRange({ searchParams }: URL) {
25
- return jsonParse<Range>(searchParams.get(field.key), {
26
+ return jsonParse<Range & { order?: 'asc' | 'desc' }>(searchParams.get(field.key), {
26
27
  min: undefined,
27
- max: undefined
28
+ max: undefined,
29
+ order: undefined
28
30
  })
29
31
  }
30
32
 
31
- const udpateUrl = debounce(() => {
32
- if (isDefined(min) || isDefined(max)) {
33
+ const updateUrl = debounce(() => {
34
+ if (isDefined(min) || isDefined(max) || order) {
33
35
  goto(
34
36
  $urlParam.with(
35
37
  {
36
38
  [field.key]: JSON.stringify({
37
39
  ...(isDefined(min) ? { min } : {}),
38
- ...(isDefined(max) ? { max } : {})
40
+ ...(isDefined(max) ? { max } : {}),
41
+ ...(order ? { order } : {})
39
42
  })
40
43
  },
41
44
  'skip',
@@ -92,13 +95,31 @@
92
95
  {/if}
93
96
  </span>
94
97
  {/if}
98
+ {#if order}
99
+ <Icon
100
+ path={order === 'asc' ? mdiSortAscending : mdiSortDescending}
101
+ size={18}
102
+ class="fill-primary"
103
+ />
104
+ {/if}
95
105
  </button>
96
106
 
107
+ {#if field.sortable !== false}
108
+ <OrderButtons
109
+ bind:order
110
+ on:change={() => {
111
+ updateUrl()
112
+ tip.hide()
113
+ }}
114
+ />
115
+ <div class="divider"></div>
116
+ <span class="p-1 py-1 text-sm font-semibold opacity-70">Filtre:</span>
117
+ {/if}
97
118
  <form class="grid grid-cols-2 gap-2 p-1" on:submit|preventDefault={() => tip.hide()}>
98
- <InputNumber bind:value={min} on:input={udpateUrl} input={{ placeholder: 'Min' }} />
119
+ <InputNumber bind:value={min} on:input={updateUrl} input={{ placeholder: 'Min' }} />
99
120
  <InputNumber
100
121
  bind:value={max}
101
- on:input={udpateUrl}
122
+ on:input={updateUrl}
102
123
  hint={isNegatifRange ? 'Doit être plus grand' : ''}
103
124
  input={{ placeholder: 'Max' }}
104
125
  />
@@ -1,21 +1,32 @@
1
1
  import type { TableField } from '../field.js';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
2
+ declare class __sveltets_Render<Item extends {
3
+ id: string;
4
+ }> {
5
+ props(): {
6
+ field: TableField<Item>;
12
7
  };
13
- z_$$bindings?: Bindings;
8
+ events(): {} & {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots(): {};
12
+ bindings(): string;
13
+ exports(): {};
14
+ }
15
+ interface $$IsomorphicComponent {
16
+ new <Item extends {
17
+ id: string;
18
+ }>(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']>> & {
19
+ $$bindings?: ReturnType<__sveltets_Render<Item>['bindings']>;
20
+ } & ReturnType<__sveltets_Render<Item>['exports']>;
21
+ <Item extends {
22
+ id: string;
23
+ }>(internal: unknown, props: ReturnType<__sveltets_Render<Item>['props']> & {
24
+ $$events?: ReturnType<__sveltets_Render<Item>['events']>;
25
+ }): ReturnType<__sveltets_Render<Item>['exports']>;
26
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
14
27
  }
15
- declare const TableHeadNumber: $$__sveltets_2_IsomorphicComponent<{
16
- field: TableField;
17
- }, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type TableHeadNumber = InstanceType<typeof TableHeadNumber>;
28
+ declare const TableHeadNumber: $$IsomorphicComponent;
29
+ type TableHeadNumber<Item extends {
30
+ id: string;
31
+ }> = InstanceType<typeof TableHeadNumber<Item>>;
21
32
  export default TableHeadNumber;
@@ -1,4 +1,4 @@
1
- <script lang="ts">
1
+ <script lang="ts" generics="Item extends {id: string}">
2
2
  import { derived } from 'svelte/store'
3
3
  import { page } from '$app/stores'
4
4
 
@@ -10,7 +10,7 @@
10
10
  import { urlParam } from '../../../store/param.js'
11
11
  import { mdiOrderBoolAscendingVariant } from '@mdi/js'
12
12
 
13
- export let field: TableField
13
+ export let field: TableField<Item>
14
14
  export let options: Options
15
15
  export let multiSelect = false
16
16
  export let placeholder = 'No option'