fuma 0.1.13 → 0.1.16

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.
@@ -0,0 +1,70 @@
1
+ <script>import { onDestroy } from "svelte";
2
+ import { fade, fly } from "svelte/transition";
3
+ import { mdiClose } from "@mdi/js";
4
+ import { goto } from "$app/navigation";
5
+ import { urlParam } from "../../store/param.js";
6
+ import { Icon } from "../index.js";
7
+ import { subscibeDrawerLayers } from "./layers.js";
8
+ export let title = "";
9
+ export let key;
10
+ export let value = "1";
11
+ let klass = "";
12
+ export { klass as class };
13
+ export let maxWidth = "32rem";
14
+ export function open() {
15
+ goto($urlParam.with({ key: value }), { replaceState: true });
16
+ }
17
+ export function close() {
18
+ console.log("close");
19
+ goto($urlParam.without(key), { replaceState: true });
20
+ }
21
+ const { offset, destroy, isActive } = subscibeDrawerLayers(key, value);
22
+ onDestroy(destroy);
23
+ </script>
24
+
25
+ <svelte:head>
26
+ {#if $isActive}
27
+ <style>
28
+ :root {
29
+ scrollbar-width: none;
30
+ }
31
+ </style>
32
+ {/if}
33
+ </svelte:head>
34
+
35
+ {#if $isActive}
36
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
37
+ <div
38
+ on:click={close}
39
+ on:keyup={close}
40
+ transition:fade={{ duration: 200 }}
41
+ class="
42
+ fixed inset-0 z-10 bg-black/25 backdrop-blur-[1.5px]
43
+ dark:bg-white/25"
44
+ />
45
+
46
+ <aside
47
+ transition:fly|local={{ x: 500, duration: 200 }}
48
+ style="max-width: min(100%, {maxWidth}); transform: translateX({-$offset * 4}rem);"
49
+ class="{klass}
50
+ fixed bottom-0 right-0 top-0 z-10 flex
51
+ flex-col overflow-y-scroll bg-base-100 transition-transform
52
+ "
53
+ >
54
+ <div
55
+ class="
56
+ sticky top-0 z-10 flex items-center
57
+ justify-between gap-32 border-b bg-base-100 p-4 pl-8
58
+ "
59
+ >
60
+ <h2 class="title">{title}</h2>
61
+ <button on:click={close} class="btn btn-square btn-sm">
62
+ <Icon path={mdiClose} title="annuler" />
63
+ </button>
64
+ </div>
65
+
66
+ <div class="grow">
67
+ <slot />
68
+ </div>
69
+ </aside>
70
+ {/if}
@@ -0,0 +1,26 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ title?: string | undefined;
5
+ /** Key used in url query params */ key: string;
6
+ /** Value need to match in url query params*/ value?: string | undefined;
7
+ class?: string | undefined;
8
+ maxWidth?: string | undefined;
9
+ open?: (() => void) | undefined;
10
+ close?: (() => void) | undefined;
11
+ };
12
+ events: {
13
+ [evt: string]: CustomEvent<any>;
14
+ };
15
+ slots: {
16
+ default: {};
17
+ };
18
+ };
19
+ export type DrawerProps = typeof __propDef.props;
20
+ export type DrawerEvents = typeof __propDef.events;
21
+ export type DrawerSlots = typeof __propDef.slots;
22
+ export default class Drawer extends SvelteComponent<DrawerProps, DrawerEvents, DrawerSlots> {
23
+ get open(): () => void;
24
+ get close(): () => void;
25
+ }
26
+ export {};
@@ -0,0 +1 @@
1
+ export { default as Drawer } from './Drawer.svelte';
@@ -0,0 +1 @@
1
+ export { default as Drawer } from './Drawer.svelte';
@@ -0,0 +1,7 @@
1
+ /// <reference types="svelte" />
2
+ import { type Readable } from 'svelte/store';
3
+ export declare function subscibeDrawerLayers(key: string, value: string): {
4
+ isActive: Readable<boolean>;
5
+ offset: Readable<number>;
6
+ destroy(): void;
7
+ };
@@ -0,0 +1,34 @@
1
+ import { derived, writable } from 'svelte/store';
2
+ import { page } from '$app/stores';
3
+ const layers = writable([]);
4
+ const layersOffset = derived(layers, (ids) => {
5
+ const nbDrawer = ids.length;
6
+ return ids.reduce((acc, id, index) => {
7
+ const drawerOffset = nbDrawer - index - 1;
8
+ return { ...acc, [id]: drawerOffset };
9
+ }, {});
10
+ });
11
+ export function subscibeDrawerLayers(key, value) {
12
+ const layerId = Math.random().toString().slice(2, 12);
13
+ const isActive = derived(page, ({ url }) => url.searchParams.get(key) === value);
14
+ const isActiveUnsubscribe = isActive.subscribe((_isActive) => {
15
+ if (_isActive)
16
+ layers.update((ids) => [...ids, layerId]);
17
+ else
18
+ removeLayer();
19
+ });
20
+ function removeLayer() {
21
+ layers.update((ids) => {
22
+ const index = ids.indexOf(layerId);
23
+ return ids.toSpliced(index, 1);
24
+ });
25
+ }
26
+ return {
27
+ isActive,
28
+ offset: derived(layersOffset, (drawers) => drawers[layerId]),
29
+ destroy() {
30
+ removeLayer();
31
+ isActiveUnsubscribe();
32
+ }
33
+ };
34
+ }
@@ -0,0 +1,96 @@
1
+ <script>import {
2
+ initData,
3
+ getFieldType
4
+ } from "./form.js";
5
+ import { createEventDispatcher, onMount } from "svelte";
6
+ import { fade } from "svelte/transition";
7
+ import { page } from "$app/stores";
8
+ import { useForm } from "../../validation/form.js";
9
+ import Input from "./Input.svelte";
10
+ import FormSection from "./FormSection.svelte";
11
+ let klass = "";
12
+ export { klass as class };
13
+ export let classSection = "";
14
+ export let fields = [];
15
+ export let sections = [{}];
16
+ export let data = initData(fields);
17
+ export let action = "";
18
+ export let actionDelete = "";
19
+ export let actionPrefix = "";
20
+ export let successMessage = "Succ\xE8s";
21
+ export function set(key, value) {
22
+ data[key] = value;
23
+ }
24
+ const dispatch = createEventDispatcher();
25
+ const { enhance } = useForm({
26
+ onSuccess(action2, data2) {
27
+ dispatch("success", { action: action2, data: data2 });
28
+ },
29
+ successMessage
30
+ });
31
+ onMount(lookupValueFromParams);
32
+ function lookupValueFromParams() {
33
+ fields.flat().forEach(({ key }) => {
34
+ if (data[key])
35
+ return;
36
+ const value = $page.url.searchParams.get(key);
37
+ if (value)
38
+ data[key] = value;
39
+ });
40
+ }
41
+ const getBoolean = (bool) => (_data) => typeof bool === "boolean" || bool === void 0 ? !!bool : !!bool(_data);
42
+ </script>
43
+
44
+ <form
45
+ method="post"
46
+ action="{actionPrefix}{action}"
47
+ enctype="multipart/form-data"
48
+ class="{klass} flex flex-col gap-4"
49
+ use:enhance
50
+ >
51
+ {#if data.id}
52
+ <input type="hidden" name="id" value={data.id} />
53
+ {/if}
54
+
55
+ {#each fields as groupFields, groupIndex}
56
+ {@const section = sections[groupIndex] || {}}
57
+ {#if !getBoolean(section?.hide)(data)}
58
+ <div class="contents" in:fade|local={{ duration: 200 }}>
59
+ <FormSection {...section} class="{classSection} {section.class || ''} max-w-full">
60
+ <div class="grid grid-cols-4 gap-x-4 gap-y-2">
61
+ {#each groupFields as field (field.key)}
62
+ {#if !getBoolean(field.hide)(data)}
63
+ {@const inputType = getFieldType(field)}
64
+ <div
65
+ style={`grid-column: span ${field.colSpan || 2};`}
66
+ in:fade|local={{ duration: 200 }}
67
+ >
68
+ <Input
69
+ key={field.key}
70
+ type={inputType}
71
+ bind:value={data[field.key]}
72
+ {...field[inputType]}
73
+ />
74
+ </div>
75
+ {/if}
76
+ {/each}
77
+ </div>
78
+ </FormSection>
79
+ </div>
80
+ {/if}
81
+ {/each}
82
+
83
+ <div class="sticky bottom-0 col-span-full mt-2 flex gap-2 border-t px-4 py-4 backdrop-blur-sm">
84
+ {#if actionDelete}
85
+ <button
86
+ class="btn-ghos btn text-error"
87
+ type="button"
88
+ formaction="{actionPrefix}{actionDelete}"
89
+ >
90
+ Supprimer
91
+ </button>
92
+ {/if}
93
+ <div class="grow" />
94
+ <button class="btn btn-primary"> Valider </button>
95
+ </div>
96
+ </form>
@@ -0,0 +1,71 @@
1
+ <script>import { slide } from "svelte/transition";
2
+ import { mdiChevronRight } from "@mdi/js";
3
+ import { Icon } from "../index.js";
4
+ export let title = "";
5
+ export let isActive = false;
6
+ export let isReducible = false;
7
+ let klass = "";
8
+ export { klass as class };
9
+ export let contentClass = "";
10
+ function open() {
11
+ isActive = true;
12
+ }
13
+ function toggle(event) {
14
+ event.stopPropagation();
15
+ isActive = !isActive;
16
+ }
17
+ </script>
18
+
19
+ <div>
20
+ {#if isReducible && isActive}
21
+ <div class="h-4" transition:slide></div>
22
+ {/if}
23
+
24
+ <section class="{klass} flex flex-col bg-base-100">
25
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
26
+ <div
27
+ on:click={open}
28
+ on:keyup={open}
29
+ class="flex items-center gap-2 py-2
30
+ {isReducible && !isActive ? 'cursor-pointer rounded-lg hover:bg-base-200/40' : ''}
31
+ "
32
+ class:rounded-lg={!isActive}
33
+ class:border={isReducible && !isActive}
34
+ >
35
+ <slot name="title">
36
+ {#if isReducible || title}
37
+ <h2
38
+ class="title-md origin-left pl-1 transition-transform"
39
+ class:translate-x-4={isReducible && !isActive}
40
+ class:scale-105={isReducible && isActive}
41
+ >
42
+ {title}
43
+ </h2>
44
+ {/if}
45
+ </slot>
46
+ {#if isReducible}
47
+ <div class="grow" />
48
+ <button
49
+ type="button"
50
+ on:click={toggle}
51
+ class="btn btn-square btn-ghost btn-sm transition-transform"
52
+ class:-translate-x-2={isReducible && !isActive}
53
+ >
54
+ <Icon path={mdiChevronRight} class="transition-transform {isActive ? 'rotate-90' : ''}" />
55
+ </button>
56
+ {/if}
57
+ </div>
58
+
59
+ {#if !isReducible || isActive}
60
+ <div transition:slide|local={{ duration: 200 }} class="{contentClass} grow py-4">
61
+ <slot />
62
+ </div>
63
+ {:else}
64
+ <div class="hidden"><slot /></div>
65
+ {/if}
66
+ </section>
67
+
68
+ {#if isReducible && isActive}
69
+ <div class="h-8" transition:slide></div>
70
+ {/if}
71
+ </div>
@@ -0,0 +1,27 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ isActive?: boolean | undefined;
5
+ class?: string | undefined;
6
+ contentClass?: string | undefined;
7
+ } & ({
8
+ isReducible: true;
9
+ title: string;
10
+ } | {
11
+ isReducible?: false | undefined;
12
+ title?: string | undefined;
13
+ });
14
+ events: {
15
+ [evt: string]: CustomEvent<any>;
16
+ };
17
+ slots: {
18
+ title: {};
19
+ default: {};
20
+ };
21
+ };
22
+ export type FormSectionProps = typeof __propDef.props;
23
+ export type FormSectionEvents = typeof __propDef.events;
24
+ export type FormSectionSlots = typeof __propDef.slots;
25
+ export default class FormSection extends SvelteComponent<FormSectionProps, FormSectionEvents, FormSectionSlots> {
26
+ }
27
+ export {};
@@ -0,0 +1,41 @@
1
+ <script context="module">import {
2
+ InputText,
3
+ InputTextarea,
4
+ InputBoolean,
5
+ InputDate,
6
+ InputDatetime,
7
+ InputNumber,
8
+ InputPassword,
9
+ InputRadio,
10
+ InputSelect,
11
+ InputRelation,
12
+ InputRelations
13
+ } from "../input/index.js";
14
+ export const inputs = {
15
+ text: InputText,
16
+ textarea: InputTextarea,
17
+ boolean: InputBoolean,
18
+ date: InputDate,
19
+ datetime: InputDatetime,
20
+ number: InputNumber,
21
+ password: InputPassword,
22
+ radio: InputRadio,
23
+ select: InputSelect,
24
+ relation: InputRelation,
25
+ relations: InputRelations
26
+ };
27
+ export const inputsType = Object.keys(inputs);
28
+ export function relationProps(props) {
29
+ return props;
30
+ }
31
+ export function relationsProps(props) {
32
+ return props;
33
+ }
34
+ </script>
35
+
36
+ <script>let inputType;
37
+ export { inputType as type };
38
+ export let value;
39
+ </script>
40
+
41
+ <svelte:component this={inputs[inputType]} bind:value {...$$restProps} />
@@ -0,0 +1,24 @@
1
+ import type { z } from 'zod';
2
+ import type { ComponentProps } from 'svelte';
3
+ import { type InputsProps, type InputsType } from './Input.svelte';
4
+ import type FormSection from './FormSection.svelte';
5
+ type Shape = z.ZodRawShape;
6
+ type PickOne<T> = {
7
+ [P in keyof T]: Record<P, T[P]> & Partial<Record<Exclude<keyof T, P>, undefined>>;
8
+ }[keyof T];
9
+ export type BoolOrFunction<M extends Shape> = boolean | ((data: FormData<M>) => unknown);
10
+ export type FormData<M extends Shape> = Partial<z.infer<z.ZodObject<M>>>;
11
+ export type FormField<M extends Shape> = {
12
+ key: string & keyof M;
13
+ /** number col used by field */
14
+ colSpan?: number;
15
+ /** hide field if true */
16
+ hide?: BoolOrFunction<M>;
17
+ } & PickOne<InputsProps>;
18
+ export type FormSectionProps<M extends Shape> = ComponentProps<FormSection> & {
19
+ /** hide group if true */
20
+ hide?: BoolOrFunction<M>;
21
+ };
22
+ export declare function initData<M extends Shape>(fields: FormField<M>[][]): FormData<M>;
23
+ export declare function getFieldType<M extends Shape>(field: FormField<M>): InputsType;
24
+ export {};
@@ -0,0 +1,15 @@
1
+ import { inputsType } from './Input.svelte';
2
+ export function initData(fields) {
3
+ // @ts-ignore
4
+ return fields.flat().reduce((acc, cur) => {
5
+ const inputType = getFieldType(cur);
6
+ // @ts-ignore
7
+ return { ...acc, [cur.key]: cur[inputType]?.value };
8
+ }, {});
9
+ }
10
+ export function getFieldType(field) {
11
+ const inputType = inputsType.find((t) => field[t]);
12
+ if (!inputType)
13
+ return 'text';
14
+ return inputType;
15
+ }
@@ -0,0 +1,2 @@
1
+ export { default as Input, relationProps, relationsProps } from './Input.svelte';
2
+ export { default as Form } from './Form.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as Input, relationProps, relationsProps } from './Input.svelte';
2
+ export { default as Form } from './Form.svelte';
@@ -1,9 +1,11 @@
1
- export * from './menu/index.js';
2
- export * from './tabs/index.js';
3
1
  export * from './card/index.js';
2
+ export * from './drawer/index.js';
3
+ export * from './form/index.js';
4
4
  export * from './input/index.js';
5
- export * from './table/index.js';
5
+ export * from './menu/index.js';
6
6
  export * from './period/index.js';
7
+ export * from './table/index.js';
8
+ export * from './tabs/index.js';
7
9
  export { default as ButtonCopy } from './ButtonCopy.svelte';
8
10
  export { default as ButtonDelete } from './ButtonDelete.svelte';
9
11
  export { default as Dialog } from './Dialog.svelte';
package/dist/ui/index.js CHANGED
@@ -1,9 +1,11 @@
1
- export * from './menu/index.js';
2
- export * from './tabs/index.js';
3
1
  export * from './card/index.js';
2
+ export * from './drawer/index.js';
3
+ export * from './form/index.js';
4
4
  export * from './input/index.js';
5
- export * from './table/index.js';
5
+ export * from './menu/index.js';
6
6
  export * from './period/index.js';
7
+ export * from './table/index.js';
8
+ export * from './tabs/index.js';
7
9
  export { default as ButtonCopy } from './ButtonCopy.svelte';
8
10
  export { default as ButtonDelete } from './ButtonDelete.svelte';
9
11
  export { default as Dialog } from './Dialog.svelte';
@@ -3,6 +3,8 @@ import { parseOptions } from "../../utils/options.js";
3
3
  import { FormControl, DropDown, Icon, SelectorList } from "../index.js";
4
4
  $:
5
5
  ({ input, value: _value, options, tippyProps, ...props } = $$props);
6
+ $:
7
+ ({ class: inputClass, ...inputProps } = input || {});
6
8
  export let value = _value;
7
9
  export let inputElement = void 0;
8
10
  let focusIndex = 0;
@@ -44,8 +46,9 @@ async function select(index = focusIndex) {
44
46
  on:blur={() => (searchValue = '')}
45
47
  on:input={(e) => filterOptions(e.currentTarget.value)}
46
48
  autocomplete="off"
47
- class="input input-bordered grow"
48
- {...input}
49
+ size={1}
50
+ class="input input-bordered grow {inputClass || {}}"
51
+ {...inputProps}
49
52
  />
50
53
  </div>
51
54
  <slot name="append" />
@@ -3,6 +3,8 @@ import dayjs from "dayjs";
3
3
  import { FormControl } from "./index.js";
4
4
  $:
5
5
  ({ input, value: _value, ...props } = $$props);
6
+ $:
7
+ ({ class: inputClass, ...inputProps } = input || {});
6
8
  export let value = _value;
7
9
  const dispatch = createEventDispatcher();
8
10
  const handleInput = ({ currentTarget }) => {
@@ -20,7 +22,8 @@ const handleInput = ({ currentTarget }) => {
20
22
  type="date"
21
23
  name={key}
22
24
  id={key}
23
- class="input input-bordered"
24
- {...input}
25
+ size={1}
26
+ class="input input-bordered {inputClass || {}}"
27
+ {...inputProps}
25
28
  />
26
29
  </FormControl>
@@ -1,6 +1,8 @@
1
1
  <script>import { FormControl } from "./index.js";
2
2
  $:
3
3
  ({ input, value: _value, ...props } = $$props);
4
+ $:
5
+ ({ class: inputClass, ...inputProps } = input || {});
4
6
  export let value = _value;
5
7
  </script>
6
8
 
@@ -15,7 +17,8 @@ export let value = _value;
15
17
  on:blur
16
18
  type="datetime-local"
17
19
  id={key}
18
- class="input input-bordered"
19
- {...input}
20
+ size={1}
21
+ class="input input-bordered {inputClass || {}}"
22
+ {...inputProps}
20
23
  />
21
24
  </FormControl>
@@ -1,6 +1,8 @@
1
1
  <script>import { FormControl } from "./index.js";
2
2
  $:
3
3
  ({ input, value: _value, ...props } = $$props);
4
+ $:
5
+ ({ class: inputClass, ...inputProps } = input || {});
4
6
  export let value = _value;
5
7
  </script>
6
8
 
@@ -15,8 +17,9 @@ export let value = _value;
15
17
  type="number"
16
18
  name={key}
17
19
  id={key}
18
- class="input input-bordered"
20
+ size={1}
19
21
  inputmode="numeric"
20
- {...input}
22
+ class="input input-bordered {inputClass || ''}"
23
+ {...inputProps}
21
24
  />
22
25
  </FormControl>
@@ -77,6 +77,7 @@ async function handleBlur() {
77
77
  autocomplete="off"
78
78
  {placeholder}
79
79
  class="grow"
80
+ size={1}
80
81
  />
81
82
 
82
83
  <RelationAfter {isLoading} {createUrl} {createTitle} />
@@ -116,6 +116,7 @@ async function handleBlur() {
116
116
  autocomplete="off"
117
117
  {placeholder}
118
118
  class="grow"
119
+ size={1}
119
120
  />
120
121
 
121
122
  <RelationAfter {isLoading} {createUrl} {createTitle} />
@@ -3,7 +3,7 @@ import { SelectorList, DropDown, Icon, FormControl } from "../index.js";
3
3
  import { parseOptions } from "../../utils/options.js";
4
4
  import { mdiUnfoldMoreHorizontal } from "@mdi/js";
5
5
  $:
6
- ({ input, value: _value, options, tippyProps, placeholder, ...props } = $$props);
6
+ ({ value: _value, options, tippyProps, placeholder, ...props } = $$props);
7
7
  export let value = _value;
8
8
  $:
9
9
  _options = parseOptions(options);
@@ -3,7 +3,7 @@ import { type InputProps } from '../index.js';
3
3
  import { type Options } from '../../utils/options.js';
4
4
  import type { TippyProps } from '../../index.js';
5
5
  declare const __propDef: {
6
- props: Omit<InputProps, "inputElement"> & {
6
+ props: Omit<InputProps, "input" | "inputElement"> & {
7
7
  options: Options;
8
8
  tippyProps?: TippyProps | undefined;
9
9
  placeholder?: string | undefined;
@@ -1,10 +1,10 @@
1
1
  <script>import { FormControl, bindValueWithParams } from "./index.js";
2
2
  $:
3
3
  ({ input, value: _value, wrapperClass, bindWithParams, ...props } = $$props);
4
- export let value = _value;
5
- export let inputElement = void 0;
6
4
  $:
7
5
  ({ class: inputClass, ...inputProps } = input || {});
6
+ export let value = _value;
7
+ export let inputElement = void 0;
8
8
  </script>
9
9
 
10
10
  <FormControl {...props} enhanceDisabled={props.enhanceDisabled || bindWithParams} let:key>
@@ -24,6 +24,7 @@ $:
24
24
  type="text"
25
25
  name={key}
26
26
  id={key}
27
+ size={1}
27
28
  class="input input-bordered w-full {inputClass || ''}"
28
29
  {...inputProps}
29
30
  />
@@ -1,6 +1,8 @@
1
1
  <script>import { FormControl } from "./index.js";
2
2
  $:
3
3
  ({ textarea, value: _value, ...props } = $$props);
4
+ $:
5
+ ({ class: inputClass, ...inputProps } = textarea || {});
4
6
  export let value = _value;
5
7
  </script>
6
8
 
@@ -13,8 +15,8 @@ export let value = _value;
13
15
  on:blur
14
16
  name={key}
15
17
  id={key}
16
- class="textarea textarea-bordered"
18
+ class="textarea textarea-bordered {inputClass || ''}"
17
19
  rows="4"
18
- {...textarea}
20
+ {...inputProps}
19
21
  />
20
22
  </FormControl>
@@ -1,6 +1,8 @@
1
1
  <script>import { FormControl } from "./index.js";
2
2
  $:
3
3
  ({ input, value: _value, ...props } = $$props);
4
+ $:
5
+ ({ class: inputClass, ...inputProps } = input || {});
4
6
  export let value = _value;
5
7
  </script>
6
8
 
@@ -13,7 +15,8 @@ export let value = _value;
13
15
  type="time"
14
16
  name={key}
15
17
  id={key}
16
- class="input input-bordered"
17
- {...input}
18
+ size={1}
19
+ class="input input-bordered {inputClass || ''}"
20
+ {...inputProps}
18
21
  />
19
22
  </FormControl>
@@ -49,7 +49,7 @@ export declare function syncFieldsWithParams(tablekey: string, fields: TableFiel
49
49
  $visible: boolean;
50
50
  key: string;
51
51
  label: string;
52
- type: "string" | "number" | "boolean" | "textarea" | "date";
52
+ type: "string" | "number" | "boolean" | "date" | "textarea";
53
53
  options?: Options | undefined;
54
54
  hint?: string | undefined;
55
55
  locked?: boolean | undefined;
@@ -30,6 +30,10 @@ export function useForm({ onSubmit, onSuccess, onResetError, onError, onFail, su
30
30
  }
31
31
  setError[key](issue.message);
32
32
  });
33
+ const issuesKeys = issues
34
+ .map(({ path }) => path[0])
35
+ .filter((k, i, self) => self.indexOf(k) === i);
36
+ toast.warning('Invalid form', { description: issuesKeys.join(', ') });
33
37
  }
34
38
  if (message) {
35
39
  toast.warning(message);
@@ -164,7 +164,7 @@ export declare const z: {
164
164
  map: "map";
165
165
  set: "set";
166
166
  };
167
- getParsedType: (data: any) => "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "map" | "set" | "nan" | "integer" | "float" | "date" | "null" | "array" | "unknown" | "promise" | "void" | "never";
167
+ getParsedType: (data: any) => "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "nan" | "integer" | "float" | "date" | "null" | "array" | "unknown" | "promise" | "void" | "never" | "map" | "set";
168
168
  ZodType: typeof zod.ZodType;
169
169
  ZodString: typeof zod.ZodString;
170
170
  ZodNumber: typeof zod.ZodNumber;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuma",
3
- "version": "0.1.13",
3
+ "version": "0.1.16",
4
4
  "description": "My fullstack material build with sveltekit, daisyui, zod and more",
5
5
  "author": {
6
6
  "name": "Jonas Voisard",