lutra 0.0.33 → 0.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.
- package/README.md +4 -24
- package/dist/components/AspectRatio.svelte +26 -0
- package/dist/components/AspectRatio.svelte.d.ts +8 -0
- package/dist/components/Avatar.svelte +105 -0
- package/dist/components/Avatar.svelte.d.ts +14 -0
- package/dist/{display → components}/Close.svelte +25 -7
- package/dist/components/Close.svelte.d.ts +7 -0
- package/dist/components/ContextTip.svelte +41 -0
- package/dist/components/ContextTip.svelte.d.ts +7 -0
- package/dist/components/Dialog.svelte +78 -0
- package/dist/components/Dialog.svelte.d.ts +14 -0
- package/dist/components/Icon.svelte +62 -0
- package/dist/components/Icon.svelte.d.ts +8 -0
- package/dist/{display → components}/IconButton.svelte +43 -14
- package/dist/components/IconButton.svelte.d.ts +16 -0
- package/dist/components/Image.svelte +172 -0
- package/dist/components/Image.svelte.d.ts +56 -0
- package/dist/{display → components}/Indicator.svelte +44 -9
- package/dist/components/Indicator.svelte.d.ts +12 -0
- package/dist/{display → components}/Inset.svelte +8 -3
- package/dist/components/Inset.svelte.d.ts +7 -0
- package/dist/components/Layout.svelte +33 -0
- package/dist/components/Layout.svelte.d.ts +11 -0
- package/dist/components/MenuDropdown.svelte +195 -0
- package/dist/components/MenuDropdown.svelte.d.ts +16 -0
- package/dist/{nav → components}/MenuItem.svelte +46 -38
- package/dist/components/MenuItem.svelte.d.ts +11 -0
- package/dist/components/MenuItemContent.svelte +25 -0
- package/dist/components/MenuItemContent.svelte.d.ts +10 -0
- package/dist/{nav → components}/MenuTypes.d.ts +19 -5
- package/dist/components/Modal.svelte +149 -0
- package/dist/components/Modal.svelte.d.ts +16 -0
- package/dist/{display → components}/Notification.svelte +33 -22
- package/dist/components/Notification.svelte.d.ts +12 -0
- package/dist/components/Overlay.svelte +31 -0
- package/dist/components/Overlay.svelte.d.ts +14 -0
- package/dist/{layout → components}/OverlayContainer.svelte +6 -3
- package/dist/{layout → components}/OverlayContainer.svelte.d.ts +4 -1
- package/dist/components/OverlayLayer.svelte +168 -0
- package/dist/components/OverlayLayer.svelte.d.ts +8 -0
- package/dist/components/PageContent.svelte +108 -0
- package/dist/components/PageContent.svelte.d.ts +38 -0
- package/dist/components/TabbedContent.svelte +74 -0
- package/dist/components/TabbedContent.svelte.d.ts +11 -0
- package/dist/components/TabbedContentItem.svelte +33 -0
- package/dist/components/TabbedContentItem.svelte.d.ts +10 -0
- package/dist/components/Table.svelte +41 -0
- package/dist/components/Table.svelte.d.ts +13 -0
- package/dist/{nav → components}/Tabs.svelte +99 -41
- package/dist/components/Tabs.svelte.d.ts +20 -0
- package/dist/components/Tag.svelte +120 -0
- package/dist/components/Tag.svelte.d.ts +21 -0
- package/dist/components/Theme.svelte +105 -0
- package/dist/components/Theme.svelte.d.ts +17 -0
- package/dist/{display → components}/Tooltip.svelte +41 -16
- package/dist/components/Tooltip.svelte.d.ts +12 -0
- package/dist/components/UIContent.svelte +19 -0
- package/dist/components/UIContent.svelte.d.ts +7 -0
- package/dist/components/index.d.ts +28 -0
- package/dist/components/index.js +29 -0
- package/dist/{display → components}/notifications.svelte.d.ts +1 -1
- package/dist/{display → components}/notifications.svelte.js +3 -4
- package/dist/{layout → components}/overlays.svelte.d.ts +4 -2
- package/dist/config.d.ts +30 -0
- package/dist/config.js +18 -0
- package/dist/css/1-props.css +440 -0
- package/dist/css/2-base.css +343 -0
- package/dist/css/3-typo.css +106 -0
- package/dist/css/4-layout.css +368 -0
- package/dist/css/5-media.css +116 -0
- package/dist/css/lutra.css +7 -0
- package/dist/css/themes/DefaultTheme.css +209 -0
- package/dist/form/Button.svelte +35 -16
- package/dist/form/Button.svelte.d.ts +8 -19
- package/dist/form/Datepicker.svelte +311 -0
- package/dist/form/Datepicker.svelte.d.ts +9 -0
- package/dist/form/FieldContent.svelte +69 -44
- package/dist/form/FieldContent.svelte.d.ts +7 -17
- package/dist/form/FieldError.svelte +16 -6
- package/dist/form/FieldError.svelte.d.ts +4 -15
- package/dist/form/Fieldset.svelte +48 -13
- package/dist/form/Fieldset.svelte.d.ts +5 -16
- package/dist/form/Form.svelte +158 -74
- package/dist/form/Form.svelte.d.ts +17 -17
- package/dist/form/{FieldActions.svelte → FormActions.svelte} +29 -17
- package/dist/form/FormActions.svelte.d.ts +9 -0
- package/dist/form/FormSection.svelte +96 -0
- package/dist/form/FormSection.svelte.d.ts +9 -0
- package/dist/form/ImageUpload.svelte +134 -94
- package/dist/form/ImageUpload.svelte.d.ts +5 -16
- package/dist/form/Input.svelte +254 -136
- package/dist/form/Input.svelte.d.ts +12 -21
- package/dist/form/InputLength.svelte +15 -5
- package/dist/form/InputLength.svelte.d.ts +4 -15
- package/dist/form/Label.svelte +55 -11
- package/dist/form/Label.svelte.d.ts +6 -15
- package/dist/form/LogoUpload.svelte +36 -21
- package/dist/form/LogoUpload.svelte.d.ts +4 -15
- package/dist/form/Select.svelte +100 -50
- package/dist/form/Select.svelte.d.ts +5 -16
- package/dist/form/Textarea.svelte +200 -98
- package/dist/form/Textarea.svelte.d.ts +11 -24
- package/dist/form/Toggle.svelte +3 -1
- package/dist/form/Toggle.svelte.d.ts +4 -1
- package/dist/form/client.svelte.d.ts +1 -0
- package/dist/form/client.svelte.js +6 -2
- package/dist/form/form.d.ts +10 -9
- package/dist/form/form.js +37 -32
- package/dist/form/index.d.ts +3 -4
- package/dist/form/index.js +3 -4
- package/dist/form/types.d.ts +9 -16
- package/dist/icons/IconAlert.svelte.d.ts +4 -1
- package/dist/icons/IconCopy.svelte.d.ts +4 -1
- package/dist/icons/IconDone.svelte.d.ts +4 -1
- package/dist/icons/IconError.svelte.d.ts +4 -1
- package/dist/icons/IconHelp.svelte.d.ts +4 -1
- package/dist/icons/IconHide.svelte.d.ts +4 -1
- package/dist/icons/IconInfo.svelte.d.ts +4 -1
- package/dist/icons/IconLink.svelte.d.ts +4 -1
- package/dist/icons/IconMenuBurger.svelte.d.ts +4 -1
- package/dist/icons/IconMenuDots.svelte.d.ts +4 -1
- package/dist/icons/IconSearch.svelte.d.ts +4 -1
- package/dist/icons/IconShow.svelte.d.ts +4 -1
- package/dist/icons/IconSuccess.svelte.d.ts +4 -1
- package/dist/icons/IconWarning.svelte.d.ts +4 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -2
- package/dist/types.d.ts +39 -0
- package/dist/types.js +25 -0
- package/dist/util/StringOrComponent.svelte +20 -0
- package/dist/util/StringOrComponent.svelte.d.ts +8 -0
- package/dist/util/StringOrSnippet.svelte +16 -0
- package/dist/util/StringOrSnippet.svelte.d.ts +8 -0
- package/dist/{utils → util}/dom.js +1 -2
- package/dist/util/locale.d.ts +1 -0
- package/dist/util/locale.js +47 -0
- package/dist/util/settings.d.ts +4 -0
- package/package.json +35 -79
- package/dist/color.css +0 -0
- package/dist/display/Avatar.svelte +0 -61
- package/dist/display/Avatar.svelte.d.ts +0 -19
- package/dist/display/Badge.svelte +0 -91
- package/dist/display/Badge.svelte.d.ts +0 -30
- package/dist/display/Callout.svelte +0 -109
- package/dist/display/Callout.svelte.d.ts +0 -28
- package/dist/display/Close.svelte.d.ts +0 -18
- package/dist/display/Code.svelte +0 -190
- package/dist/display/Code.svelte.d.ts +0 -32
- package/dist/display/ContextTip.svelte +0 -23
- package/dist/display/ContextTip.svelte.d.ts +0 -18
- package/dist/display/DataList.svelte +0 -16
- package/dist/display/DataList.svelte.d.ts +0 -21
- package/dist/display/Details.svelte +0 -49
- package/dist/display/Details.svelte.d.ts +0 -27
- package/dist/display/Hero.svelte +0 -50
- package/dist/display/Hero.svelte.d.ts +0 -26
- package/dist/display/Icon.svelte +0 -39
- package/dist/display/Icon.svelte.d.ts +0 -19
- package/dist/display/IconButton.svelte.d.ts +0 -27
- package/dist/display/Image.svelte +0 -91
- package/dist/display/Image.svelte.d.ts +0 -26
- package/dist/display/Indicator.svelte.d.ts +0 -23
- package/dist/display/Inset.svelte.d.ts +0 -18
- package/dist/display/LineChart.svelte +0 -385
- package/dist/display/LineChart.svelte.d.ts +0 -24
- package/dist/display/LoadingIndicator.svelte +0 -33
- package/dist/display/LoadingIndicator.svelte.d.ts +0 -15
- package/dist/display/Modal.svelte +0 -116
- package/dist/display/Modal.svelte.d.ts +0 -27
- package/dist/display/Notification.svelte.d.ts +0 -23
- package/dist/display/Panel.svelte +0 -23
- package/dist/display/Panel.svelte.d.ts +0 -19
- package/dist/display/Popup.svelte +0 -111
- package/dist/display/Popup.svelte.d.ts +0 -25
- package/dist/display/Stat.svelte +0 -81
- package/dist/display/Stat.svelte.d.ts +0 -30
- package/dist/display/Table.svelte +0 -28
- package/dist/display/Table.svelte.d.ts +0 -24
- package/dist/display/TablePaginator.svelte +0 -51
- package/dist/display/TablePaginator.svelte.d.ts +0 -21
- package/dist/display/Tag.svelte +0 -90
- package/dist/display/Tag.svelte.d.ts +0 -32
- package/dist/display/Tooltip.svelte.d.ts +0 -23
- package/dist/display/chart.d.ts +0 -78
- package/dist/display/chart.js +0 -212
- package/dist/display/index.d.ts +0 -24
- package/dist/display/index.js +0 -24
- package/dist/form/FieldActions.svelte.d.ts +0 -20
- package/dist/form/FieldContainer.svelte +0 -37
- package/dist/form/FieldContainer.svelte.d.ts +0 -19
- package/dist/form/FieldSection.svelte +0 -86
- package/dist/form/FieldSection.svelte.d.ts +0 -20
- package/dist/layout/Layout.svelte +0 -47
- package/dist/layout/Layout.svelte.d.ts +0 -22
- package/dist/layout/LayoutFooter.svelte +0 -21
- package/dist/layout/LayoutFooter.svelte.d.ts +0 -18
- package/dist/layout/LayoutGrid.svelte +0 -51
- package/dist/layout/LayoutGrid.svelte.d.ts +0 -27
- package/dist/layout/LayoutHeader.svelte +0 -97
- package/dist/layout/LayoutHeader.svelte.d.ts +0 -34
- package/dist/layout/LayoutSideMenu.svelte +0 -55
- package/dist/layout/LayoutSideMenu.svelte.d.ts +0 -21
- package/dist/layout/LayoutTypes.d.ts +0 -15
- package/dist/layout/LayoutTypes.js +0 -9
- package/dist/layout/Overlay.svelte +0 -20
- package/dist/layout/Overlay.svelte.d.ts +0 -25
- package/dist/layout/OverlayLayer.svelte +0 -140
- package/dist/layout/OverlayLayer.svelte.d.ts +0 -19
- package/dist/layout/PageContent.svelte +0 -82
- package/dist/layout/PageContent.svelte.d.ts +0 -25
- package/dist/layout/Theme.svelte +0 -243
- package/dist/layout/Theme.svelte.d.ts +0 -19
- package/dist/layout/UIContent.svelte +0 -15
- package/dist/layout/UIContent.svelte.d.ts +0 -18
- package/dist/layout/index.d.ts +0 -11
- package/dist/layout/index.js +0 -11
- package/dist/nav/Breadcrumb.svelte +0 -82
- package/dist/nav/Breadcrumb.svelte.d.ts +0 -28
- package/dist/nav/Menu.svelte +0 -170
- package/dist/nav/Menu.svelte.d.ts +0 -27
- package/dist/nav/MenuItem.svelte.d.ts +0 -22
- package/dist/nav/NavMenu.svelte +0 -181
- package/dist/nav/NavMenu.svelte.d.ts +0 -19
- package/dist/nav/TabbedContent.svelte +0 -43
- package/dist/nav/TabbedContent.svelte.d.ts +0 -23
- package/dist/nav/Tabs.svelte.d.ts +0 -25
- package/dist/nav/index.d.ts +0 -7
- package/dist/nav/index.js +0 -6
- package/dist/style.css +0 -950
- package/dist/typo/Clamp.svelte +0 -25
- package/dist/typo/Clamp.svelte.d.ts +0 -24
- package/dist/typo/H.svelte +0 -52
- package/dist/typo/H.svelte.d.ts +0 -28
- package/dist/typo/H1.svelte +0 -14
- package/dist/typo/H1.svelte.d.ts +0 -26
- package/dist/typo/H2.svelte +0 -14
- package/dist/typo/H2.svelte.d.ts +0 -26
- package/dist/typo/H3.svelte +0 -14
- package/dist/typo/H3.svelte.d.ts +0 -26
- package/dist/typo/H4.svelte +0 -14
- package/dist/typo/H4.svelte.d.ts +0 -26
- package/dist/typo/H5.svelte +0 -14
- package/dist/typo/H5.svelte.d.ts +0 -26
- package/dist/typo/H6.svelte +0 -14
- package/dist/typo/H6.svelte.d.ts +0 -26
- package/dist/typo/P.svelte +0 -34
- package/dist/typo/P.svelte.d.ts +0 -26
- package/dist/typo/index.d.ts +0 -9
- package/dist/typo/index.js +0 -9
- package/dist/utils/StringOrComponent.svelte +0 -14
- package/dist/utils/StringOrComponent.svelte.d.ts +0 -19
- package/dist/utils/StringOrSnippet.svelte +0 -11
- package/dist/utils/StringOrSnippet.svelte.d.ts +0 -19
- package/dist/utils/defaults.d.ts +0 -4
- package/dist/utils/hooks.server.d.ts +0 -2
- package/dist/utils/hooks.server.js +0 -16
- package/dist/utils/id.d.ts +0 -1
- package/dist/utils/id.js +0 -3
- package/dist/utils/index.d.ts +0 -9
- package/dist/utils/index.js +0 -6
- package/dist/utils/isSnippet.d.ts +0 -3
- package/dist/utils/isSnippet.js +0 -11
- /package/dist/{nav → components}/MenuTypes.js +0 -0
- /package/dist/{layout → components}/overlays.svelte.js +0 -0
- /package/dist/{utils → util}/attr.d.ts +0 -0
- /package/dist/{utils → util}/attr.js +0 -0
- /package/dist/{utils → util}/color.d.ts +0 -0
- /package/dist/{utils → util}/color.js +0 -0
- /package/dist/{utils → util}/dom.d.ts +0 -0
- /package/dist/{utils → util}/keyboard.svelte.d.ts +0 -0
- /package/dist/{utils → util}/keyboard.svelte.js +0 -0
- /package/dist/{utils/defaults.js → util/settings.js} +0 -0
- /package/dist/{utils → util}/transitions.d.ts +0 -0
- /package/dist/{utils → util}/transitions.js +0 -0
@@ -1,18 +1,7 @@
|
|
1
|
-
|
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
|
-
z_$$bindings?: Bindings;
|
10
|
-
}
|
11
|
-
declare const FieldError: $$__sveltets_2_IsomorphicComponent<{
|
1
|
+
type $$ComponentProps = {
|
12
2
|
code: string;
|
13
3
|
message?: string;
|
14
|
-
}
|
15
|
-
|
16
|
-
|
17
|
-
type FieldError = InstanceType<typeof FieldError>;
|
4
|
+
};
|
5
|
+
declare const FieldError: import("svelte").Component<$$ComponentProps, {}, "">;
|
6
|
+
type FieldError = ReturnType<typeof FieldError>;
|
18
7
|
export default FieldError;
|
@@ -1,16 +1,51 @@
|
|
1
|
-
<script lang="ts">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<script lang="ts">
|
2
|
+
import { getContext, type Snippet } from "svelte";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @description
|
6
|
+
* A fieldset is a group of related form elements that can be disabled or enabled.
|
7
|
+
* @example
|
8
|
+
* <script>
|
9
|
+
* import Input from "lutra/Input.svelte";
|
10
|
+
* <\/script>
|
11
|
+
* <Fieldset legend="Personal Information">
|
12
|
+
* <Input label="First Name" />
|
13
|
+
* <Input label="Last Name" />
|
14
|
+
* </Fieldset>
|
15
|
+
*/
|
16
|
+
|
17
|
+
let {
|
18
|
+
fullWidth,
|
19
|
+
description,
|
20
|
+
contained,
|
21
|
+
rounded,
|
22
|
+
legend,
|
23
|
+
columns = 1,
|
24
|
+
children,
|
25
|
+
}: {
|
26
|
+
/** Whether the fieldset should be full width. */
|
27
|
+
fullWidth?: boolean;
|
28
|
+
/** The description of the fieldset. */
|
29
|
+
description?: string | Snippet;
|
30
|
+
/** Whether the fieldset should be contained. */
|
31
|
+
contained?: boolean;
|
32
|
+
/** Whether the fieldset should be rounded. */
|
33
|
+
rounded?: boolean;
|
34
|
+
/** The legend of the fieldset. */
|
35
|
+
legend?: string | Snippet;
|
36
|
+
/** The number of columns to display the fieldset in. You can pass a single number or an array of numbers. The array will be used to set the number of columns at different breakpoints (lg, md, sm). */
|
37
|
+
columns?: number | [number] | [number, number] | [number, number, number];
|
38
|
+
/** Content to be rendered inside the fieldset. */
|
39
|
+
children: Snippet;
|
40
|
+
} = $props();
|
41
|
+
|
42
|
+
if(contained === undefined) { contained = getContext('lutra.form.contained') ?? getContext('lutra.contained') ?? false; }
|
43
|
+
|
44
|
+
let columnsArray = Array.isArray(columns) ? columns : [columns, columns, columns];
|
45
|
+
let lgColumns = columnsArray[0];
|
46
|
+
let mdColumns = columnsArray[1] || lgColumns;
|
47
|
+
let smColumns = columnsArray[2] || mdColumns;
|
48
|
+
|
14
49
|
</script>
|
15
50
|
|
16
51
|
<div class="FieldsetContainer">
|
@@ -1,15 +1,5 @@
|
|
1
|
-
import type
|
2
|
-
|
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
|
-
z_$$bindings?: Bindings;
|
11
|
-
}
|
12
|
-
declare const Fieldset: $$__sveltets_2_IsomorphicComponent<{
|
1
|
+
import { type Snippet } from "svelte";
|
2
|
+
type $$ComponentProps = {
|
13
3
|
/** Whether the fieldset should be full width. */
|
14
4
|
fullWidth?: boolean;
|
15
5
|
/** The description of the fieldset. */
|
@@ -24,8 +14,7 @@ declare const Fieldset: $$__sveltets_2_IsomorphicComponent<{
|
|
24
14
|
columns?: number | [number] | [number, number] | [number, number, number];
|
25
15
|
/** Content to be rendered inside the fieldset. */
|
26
16
|
children: Snippet;
|
27
|
-
}
|
28
|
-
|
29
|
-
|
30
|
-
type Fieldset = InstanceType<typeof Fieldset>;
|
17
|
+
};
|
18
|
+
declare const Fieldset: import("svelte").Component<$$ComponentProps, {}, "">;
|
19
|
+
type Fieldset = ReturnType<typeof Fieldset>;
|
31
20
|
export default Fieldset;
|
package/dist/form/Form.svelte
CHANGED
@@ -1,65 +1,148 @@
|
|
1
|
-
<script lang="ts">
|
2
|
-
import
|
3
|
-
import {
|
4
|
-
import
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
import {
|
8
|
-
import {
|
9
|
-
import {
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
1
|
+
<script lang="ts">
|
2
|
+
import { enhance } from "$app/forms";
|
3
|
+
import { goto } from '$app/navigation';
|
4
|
+
import UiContent from "../components/UIContent.svelte";
|
5
|
+
import { Bodyguard, type BodyguardValidator } from "@auth70/bodyguard";
|
6
|
+
import type { ActionResult } from "@sveltejs/kit";
|
7
|
+
import { onMount, setContext } from "svelte";
|
8
|
+
import type { Snippet } from "svelte";
|
9
|
+
import { dezerialize } from "zodex";
|
10
|
+
import type { AddBeforeSubmitFn, BeforeSubmitFn, LutraForm } from "./types.js";
|
11
|
+
import { type ZodObject } from "zod";
|
12
|
+
import { getIndividualValidators, parseFormIssues } from "./form.js";
|
13
|
+
import { useForm } from "./client.svelte.js";
|
14
|
+
|
15
|
+
let {
|
16
|
+
name = 'form',
|
17
|
+
form: _form,
|
18
|
+
formEl = $bindable(null),
|
19
|
+
action,
|
20
|
+
enctype = "multipart/form-data",
|
21
|
+
method = "POST",
|
22
|
+
beforesubmit,
|
23
|
+
fullWidth = false,
|
24
|
+
onresult,
|
25
|
+
resetOnUpdate,
|
26
|
+
children,
|
27
|
+
contained,
|
28
|
+
spacing,
|
29
|
+
actionGap,
|
30
|
+
fieldGap,
|
31
|
+
labelGap,
|
32
|
+
titleGap,
|
33
|
+
sectionGap,
|
34
|
+
padding,
|
35
|
+
paddingBlock,
|
36
|
+
paddingInline,
|
37
|
+
}: {
|
38
|
+
name?: string;
|
39
|
+
form?: LutraForm<any>;
|
40
|
+
formEl?: HTMLFormElement | null;
|
41
|
+
action?: string;
|
42
|
+
enctype?: "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain";
|
43
|
+
method?: "GET" | "POST";
|
44
|
+
beforesubmit?: BeforeSubmitFn;
|
45
|
+
fullWidth?: boolean;
|
46
|
+
resetOnUpdate?: boolean;
|
47
|
+
onresult?: (args: {
|
48
|
+
formData: FormData;
|
49
|
+
formElement: HTMLFormElement;
|
50
|
+
action: URL;
|
51
|
+
result: ActionResult<Record<string, unknown> | undefined, Record<string, unknown> | undefined>;
|
52
|
+
update: (options?: {
|
53
|
+
reset?: boolean | undefined;
|
54
|
+
invalidateAll?: boolean | undefined;
|
55
|
+
} | undefined) => void;
|
56
|
+
}) => void;
|
57
|
+
children: Snippet;
|
58
|
+
contained?: boolean;
|
59
|
+
spacing?: string;
|
60
|
+
actionGap?: string;
|
61
|
+
fieldGap?: string;
|
62
|
+
labelGap?: string;
|
63
|
+
titleGap?: string;
|
64
|
+
sectionGap?: string;
|
65
|
+
padding?: string;
|
66
|
+
paddingBlock?: string;
|
67
|
+
paddingInline?: string;
|
68
|
+
} = $props();
|
69
|
+
|
70
|
+
let form = $state(_form ? useForm(_form) : null);
|
71
|
+
|
72
|
+
setContext('form', form);
|
73
|
+
setContext('form.validators', form ? getIndividualValidators(form) : null);
|
74
|
+
|
75
|
+
const beforesubmitFunctions: { id: string, fn: BeforeSubmitFn }[] = [];
|
76
|
+
const addBeforeSubmit: AddBeforeSubmitFn = (id, fn) => {
|
77
|
+
if(beforesubmitFunctions.find((f) => f.id === id)) {
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
beforesubmitFunctions.push({ id, fn });
|
57
81
|
}
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
82
|
+
setContext('form.beforesubmit', addBeforeSubmit);
|
83
|
+
|
84
|
+
const schema = form?.schema ? dezerialize(form?.schema) as ZodObject<any> : null;
|
85
|
+
const bodyguard = new Bodyguard();
|
86
|
+
|
87
|
+
function setFormIssuesAndFields(issues: any, fields: any) {
|
88
|
+
console.log('setFormIssuesAndFields', issues, fields)
|
89
|
+
if(form) {
|
90
|
+
form.issues = issues;
|
91
|
+
form.fields = fields;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
async function validate() {
|
96
|
+
if(form && schema) {
|
97
|
+
form.tainted = true;
|
98
|
+
const req = new Request('localhost', {
|
99
|
+
method: 'POST',
|
100
|
+
body: new FormData(formEl!),
|
101
|
+
});
|
102
|
+
const result = await bodyguard.softForm(req, schema.parse as BodyguardValidator);
|
103
|
+
if(result.success === true) {
|
104
|
+
form.valid = true;
|
105
|
+
form.issues = [];
|
106
|
+
} else {
|
107
|
+
form.valid = false;
|
108
|
+
form.issues = parseFormIssues((result.error as any).issues);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
onMount(() => {
|
114
|
+
validate();
|
115
|
+
});
|
116
|
+
|
117
|
+
const styleParams = {
|
118
|
+
actionGap,
|
119
|
+
fieldGap,
|
120
|
+
labelGap,
|
121
|
+
titleGap,
|
122
|
+
sectionGap,
|
123
|
+
padding,
|
124
|
+
paddingBlock,
|
125
|
+
paddingInline,
|
126
|
+
};
|
127
|
+
|
128
|
+
const style = `
|
129
|
+
${actionGap ? `--form-action-gap: ${actionGap};` : ''}
|
130
|
+
${fieldGap ? `--form-field-gap: ${fieldGap};` : ''}
|
131
|
+
${labelGap ? `--form-label-gap: ${labelGap};` : ''}
|
132
|
+
${titleGap ? `--form-title-gap: ${titleGap};` : ''}
|
133
|
+
${sectionGap ? `--form-section-gap: ${sectionGap};` : ''}
|
134
|
+
${
|
135
|
+
paddingBlock || paddingInline
|
136
|
+
? `
|
137
|
+
${paddingBlock ? `--form-padding-block: ${paddingBlock};` : ''}
|
138
|
+
${paddingInline ? `--form-padding-inline: ${paddingInline};` : ''}
|
139
|
+
`
|
140
|
+
: padding
|
141
|
+
? `--form-padding-block: ${padding}; --form-padding-inline: ${padding};`
|
142
|
+
: ''
|
143
|
+
}
|
144
|
+
`;
|
145
|
+
|
63
146
|
</script>
|
64
147
|
|
65
148
|
<UiContent>
|
@@ -67,6 +150,7 @@ onMount(() => {
|
|
67
150
|
{method}
|
68
151
|
{action}
|
69
152
|
{enctype}
|
153
|
+
style={style}
|
70
154
|
bind:this={formEl}
|
71
155
|
onchange={validate}
|
72
156
|
use:enhance={async ({ formElement, formData, action, cancel, submitter }) => {
|
@@ -76,12 +160,12 @@ onMount(() => {
|
|
76
160
|
// calling `cancel()` will prevent the submission
|
77
161
|
// `submitter` is the `HTMLElement` that caused the form to be submitted
|
78
162
|
if(form) form.state = 'loading';
|
79
|
-
//await Promise.resolve(
|
80
|
-
if(
|
163
|
+
//await Promise.resolve(beforesubmit(form));
|
164
|
+
if(beforesubmit) await Promise.resolve(beforesubmit({ form: formElement, data: formData, cancel: () => {
|
81
165
|
if(form) form.state = 'error';
|
82
166
|
cancel();
|
83
167
|
}}));
|
84
|
-
for(const { id, fn } of
|
168
|
+
for(const { id, fn } of beforesubmitFunctions) {
|
85
169
|
await Promise.resolve(fn({ form: formElement, data: formData, cancel: () => {
|
86
170
|
if(form) form.state = 'error';
|
87
171
|
cancel();
|
@@ -93,21 +177,21 @@ onMount(() => {
|
|
93
177
|
// `result` is an `ActionResult` object
|
94
178
|
// `update` is a function which triggers the default logic that would be triggered if this callback wasn't set
|
95
179
|
console.log('form result', opts);
|
96
|
-
if(
|
97
|
-
console.log('calling
|
98
|
-
|
180
|
+
if(onresult) {
|
181
|
+
console.log('calling onresult', opts);
|
182
|
+
onresult(opts);
|
99
183
|
}
|
100
184
|
const resultForm = result.type !== "redirect" && result.type !== "error" ? result?.data![name] : null;
|
101
|
-
console.log('resultForm', resultForm, form)
|
185
|
+
console.log('resultForm', resultForm, form);
|
102
186
|
if(result.type === "success") {
|
103
187
|
if(resultForm && form) {
|
104
188
|
form.valid = Object.assign({ valid: false }, resultForm).valid ?? false;
|
105
189
|
}
|
106
190
|
if(form) form.state = 'success';
|
107
|
-
console.log('form state', form?.state);
|
191
|
+
console.log('form state', form?.state, resetOnUpdate, opts);
|
108
192
|
update({ reset: !!resetOnUpdate });
|
109
193
|
} else if(result.type === "failure") {
|
110
|
-
console.log('FAILURE')
|
194
|
+
console.log('FAILURE', opts);
|
111
195
|
if(resultForm && form) {
|
112
196
|
console.log('setting form issues and fields')
|
113
197
|
setFormIssuesAndFields(
|
@@ -117,11 +201,13 @@ onMount(() => {
|
|
117
201
|
}
|
118
202
|
if(form) form.state = 'error';
|
119
203
|
} else if(result.type === "error") {
|
120
|
-
console.error('[lutra] Error from form enhance call', result.error);
|
204
|
+
console.error('[lutra] Error from form enhance call', result.error, opts);
|
121
205
|
if(form) form.state = 'error';
|
122
206
|
} else if(result.type === "redirect") {
|
123
|
-
|
207
|
+
console.log('redirect', opts);
|
208
|
+
//window.location.href = result.location;
|
124
209
|
if(form) form.state = 'success';
|
210
|
+
await goto(result.location);
|
125
211
|
}
|
126
212
|
};
|
127
213
|
}}
|
@@ -131,6 +217,4 @@ onMount(() => {
|
|
131
217
|
</UiContent>
|
132
218
|
|
133
219
|
<style>
|
134
|
-
form {
|
135
|
-
}
|
136
220
|
</style>
|
@@ -1,26 +1,17 @@
|
|
1
1
|
import type { ActionResult } from "@sveltejs/kit";
|
2
2
|
import type { Snippet } from "svelte";
|
3
3
|
import type { BeforeSubmitFn, LutraForm } from "./types.js";
|
4
|
-
|
5
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
6
|
-
$$bindings?: Bindings;
|
7
|
-
} & Exports;
|
8
|
-
(internal: unknown, props: Props & {
|
9
|
-
$$events?: Events;
|
10
|
-
$$slots?: Slots;
|
11
|
-
}): Exports;
|
12
|
-
z_$$bindings?: Bindings;
|
13
|
-
}
|
14
|
-
declare const Form: $$__sveltets_2_IsomorphicComponent<{
|
4
|
+
type $$ComponentProps = {
|
15
5
|
name?: string;
|
16
6
|
form?: LutraForm<any>;
|
7
|
+
formEl?: HTMLFormElement | null;
|
17
8
|
action?: string;
|
18
9
|
enctype?: "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain";
|
19
10
|
method?: "GET" | "POST";
|
20
|
-
|
11
|
+
beforesubmit?: BeforeSubmitFn;
|
21
12
|
fullWidth?: boolean;
|
22
13
|
resetOnUpdate?: boolean;
|
23
|
-
|
14
|
+
onresult?: (args: {
|
24
15
|
formData: FormData;
|
25
16
|
formElement: HTMLFormElement;
|
26
17
|
action: URL;
|
@@ -31,8 +22,17 @@ declare const Form: $$__sveltets_2_IsomorphicComponent<{
|
|
31
22
|
} | undefined) => void;
|
32
23
|
}) => void;
|
33
24
|
children: Snippet;
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
contained?: boolean;
|
26
|
+
spacing?: string;
|
27
|
+
actionGap?: string;
|
28
|
+
fieldGap?: string;
|
29
|
+
labelGap?: string;
|
30
|
+
titleGap?: string;
|
31
|
+
sectionGap?: string;
|
32
|
+
padding?: string;
|
33
|
+
paddingBlock?: string;
|
34
|
+
paddingInline?: string;
|
35
|
+
};
|
36
|
+
declare const Form: import("svelte").Component<$$ComponentProps, {}, "formEl">;
|
37
|
+
type Form = ReturnType<typeof Form>;
|
38
38
|
export default Form;
|
@@ -1,12 +1,21 @@
|
|
1
|
-
<script lang="ts">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
<script lang="ts">
|
2
|
+
import StringOrSnippet from "../util/StringOrSnippet.svelte";
|
3
|
+
import { setContext, type Snippet } from "svelte";
|
4
|
+
|
5
|
+
let {
|
6
|
+
align = 'end',
|
7
|
+
children,
|
8
|
+
info,
|
9
|
+
}: {
|
10
|
+
align?: 'justified' | 'start' | 'center' | 'end' | 'full';
|
11
|
+
children: Snippet;
|
12
|
+
info?: string | Snippet;
|
13
|
+
} = $props();
|
14
|
+
|
15
|
+
setContext('form.actions.align', align);
|
7
16
|
</script>
|
8
17
|
|
9
|
-
<div class="
|
18
|
+
<div class="FormActions {align}" class:hasInfo={!!info}>
|
10
19
|
{#if info}
|
11
20
|
<div class="Info">
|
12
21
|
<StringOrSnippet content={info} />
|
@@ -18,10 +27,10 @@ let {
|
|
18
27
|
</div>
|
19
28
|
|
20
29
|
<style>
|
21
|
-
.
|
30
|
+
.FormActions {
|
22
31
|
display: grid;
|
23
|
-
background: color-mix(in srgb, var(--
|
24
|
-
padding: calc(
|
32
|
+
background: color-mix(in srgb, var(--form-background-actions) calc(var(--fcc) * 100%), transparent);
|
33
|
+
padding: calc(var(--space-md) * var(--fcc)) calc(var(--space-lg) * var(--fcc));
|
25
34
|
grid-column: 1 / -1;
|
26
35
|
grid-template-columns: subgrid;
|
27
36
|
border-bottom-left-radius: inherit;
|
@@ -33,28 +42,31 @@ let {
|
|
33
42
|
flex-direction: row;
|
34
43
|
align-items: center;
|
35
44
|
justify-content: space-between;
|
36
|
-
gap:
|
45
|
+
gap: var(--space-md);
|
37
46
|
grid-column: 2 / -1;
|
38
47
|
}
|
39
|
-
.
|
48
|
+
.FormActions.start .Actions {
|
40
49
|
justify-content: start;
|
41
50
|
grid-column: 1 / -1;
|
42
51
|
}
|
43
|
-
.
|
52
|
+
.FormActions.center .Actions {
|
44
53
|
justify-content: center;
|
45
54
|
grid-column: 1 / -1;
|
46
55
|
}
|
47
|
-
.
|
56
|
+
.FormActions.end .Actions {
|
48
57
|
justify-content: end;
|
49
58
|
grid-column: 1 / -1;
|
50
59
|
}
|
51
|
-
.
|
60
|
+
.FormActions.hasInfo .Actions {
|
52
61
|
grid-column: 2 / -1;
|
53
62
|
}
|
63
|
+
.FormActions.full .Actions {
|
64
|
+
grid-column: 1 / -1;
|
65
|
+
}
|
54
66
|
@container (max-width: 480px) {
|
55
|
-
.
|
67
|
+
.FormActions {
|
56
68
|
justify-content: center;
|
57
|
-
gap:
|
69
|
+
gap: var(--space-sm);
|
58
70
|
}
|
59
71
|
.Info {
|
60
72
|
order: 1;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { type Snippet } from "svelte";
|
2
|
+
type $$ComponentProps = {
|
3
|
+
align?: 'justified' | 'start' | 'center' | 'end' | 'full';
|
4
|
+
children: Snippet;
|
5
|
+
info?: string | Snippet;
|
6
|
+
};
|
7
|
+
declare const FormActions: import("svelte").Component<$$ComponentProps, {}, "">;
|
8
|
+
type FormActions = ReturnType<typeof FormActions>;
|
9
|
+
export default FormActions;
|
@@ -0,0 +1,96 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import type { Snippet } from "svelte";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* @description
|
6
|
+
* A field section is a group of related form elements.
|
7
|
+
*/
|
8
|
+
let {
|
9
|
+
title,
|
10
|
+
description,
|
11
|
+
children,
|
12
|
+
}: {
|
13
|
+
title?: string | Snippet;
|
14
|
+
description?: string | Snippet;
|
15
|
+
children: Snippet;
|
16
|
+
} = $props();
|
17
|
+
</script>
|
18
|
+
|
19
|
+
<div class="FormSection" class:noTitle={!title && !description}>
|
20
|
+
{#if title || description}
|
21
|
+
<div class="FormSectionTitle">
|
22
|
+
{#if title}
|
23
|
+
{#if typeof title === "string"}
|
24
|
+
<h5>{title}</h5>
|
25
|
+
{:else}
|
26
|
+
{@render title()}
|
27
|
+
{/if}
|
28
|
+
{/if}
|
29
|
+
{#if description}
|
30
|
+
{#if typeof description === "string"}
|
31
|
+
<small>{description}</small>
|
32
|
+
{:else}
|
33
|
+
{@render description()}
|
34
|
+
{/if}
|
35
|
+
{/if}
|
36
|
+
</div>
|
37
|
+
{/if}
|
38
|
+
<div class="FormSectionContent">
|
39
|
+
{@render children()}
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<style>
|
44
|
+
.FormSection {
|
45
|
+
padding: 0;
|
46
|
+
display: grid;
|
47
|
+
grid-template-columns: subgrid;
|
48
|
+
grid-column: 1 / -1;
|
49
|
+
padding-block: calc(var(--fcc) * var(--form-padding-block));
|
50
|
+
padding-inline: calc(var(--fcc) * var(--form-padding-inline));
|
51
|
+
gap: var(--form-section-gap, var(--space-lg));
|
52
|
+
}
|
53
|
+
.FormSectionTitle {
|
54
|
+
display: flex;
|
55
|
+
flex-direction: column;
|
56
|
+
background-color: var(--base);
|
57
|
+
gap: var(--form-title-gap, var(--space-md));
|
58
|
+
text-wrap: balance;
|
59
|
+
}
|
60
|
+
.FormSection:not(:first-child) {
|
61
|
+
border-top: calc(var(--fcc) * var(--border-size)) var(--border-style) var(--border-color);
|
62
|
+
}
|
63
|
+
.FormSectionContent {
|
64
|
+
display: grid;
|
65
|
+
gap: var(--form-field-gap, var(--space-lg));
|
66
|
+
}
|
67
|
+
.FormSection.noTitle .FormSectionContent {
|
68
|
+
grid-column: 1 / -1;
|
69
|
+
}
|
70
|
+
@media(max-width: 1280px) {
|
71
|
+
.FormSection {
|
72
|
+
padding: var(--space-lg);
|
73
|
+
gap: var(--space-md);
|
74
|
+
}
|
75
|
+
.FormSectionTitle {
|
76
|
+
gap: var(--space-sm);
|
77
|
+
padding-block-end: var(--space-md);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
@media(max-width: 640px) {
|
81
|
+
.FormSection {
|
82
|
+
padding: var(--space-md);
|
83
|
+
gap: var(--space-md);
|
84
|
+
}
|
85
|
+
.FormSectionTitle {
|
86
|
+
gap: var(--space-sm);
|
87
|
+
padding-block-end: var(--space-md);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
@container (max-width: 800px) {
|
91
|
+
.FormSectionTitle,
|
92
|
+
.FormSectionContent {
|
93
|
+
grid-column: 1 / -1;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
</style>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import type { Snippet } from "svelte";
|
2
|
+
type $$ComponentProps = {
|
3
|
+
title?: string | Snippet;
|
4
|
+
description?: string | Snippet;
|
5
|
+
children: Snippet;
|
6
|
+
};
|
7
|
+
declare const FormSection: import("svelte").Component<$$ComponentProps, {}, "">;
|
8
|
+
type FormSection = ReturnType<typeof FormSection>;
|
9
|
+
export default FormSection;
|