sveltacular 1.0.21 → 1.0.24
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 +1 -1
- package/dist/forms/button/button.svelte +17 -15
- package/dist/forms/button/button.svelte.d.ts +1 -2
- package/dist/forms/date-box/date-box.svelte +5 -8
- package/dist/forms/form-actions/form-actions.svelte +128 -0
- package/dist/forms/form-actions/form-actions.svelte.d.ts +23 -0
- package/dist/forms/index.d.ts +2 -0
- package/dist/forms/index.js +1 -0
- package/dist/modals/alert.svelte +4 -4
- package/dist/modals/confirm.svelte +5 -5
- package/dist/modals/prompt.svelte +5 -5
- package/dist/navigation/wizard/wizard.svelte +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ npm i sveltacular
|
|
|
50
50
|
import { Button } from 'sveltacular';
|
|
51
51
|
</script>
|
|
52
52
|
|
|
53
|
-
<Button variant="primary"
|
|
53
|
+
<Button variant="primary">Hello World</Button>
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
**Note**: The stylesheet import is required for components to render with default styling. Import it once at the app level (not in individual components). If you prefer to provide your own theme, you can skip this import and define your own CSS variables (see [Theming](#theming) below).
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
import type { Snippet } from 'svelte';
|
|
7
7
|
import { navigateTo } from '../../helpers/navigate-to.js';
|
|
8
8
|
import type { ButtonVariant, FormFieldSizeOptions } from '../../types/form.js';
|
|
9
|
+
import Spinner from '../../generic/spinner/spinner.svelte';
|
|
9
10
|
|
|
10
11
|
let {
|
|
11
|
-
/** Button label text */
|
|
12
|
-
label,
|
|
13
12
|
/** Optional href for navigation */
|
|
14
13
|
href = undefined,
|
|
15
14
|
/** Button size */
|
|
@@ -26,7 +25,7 @@
|
|
|
26
25
|
disabled = $bindable(false),
|
|
27
26
|
/** Loading state */
|
|
28
27
|
loading = false,
|
|
29
|
-
/** ARIA label
|
|
28
|
+
/** ARIA label for accessibility (required if button content is not text) */
|
|
30
29
|
ariaLabel = undefined,
|
|
31
30
|
/** Remove margins */
|
|
32
31
|
noMargin = false,
|
|
@@ -36,10 +35,9 @@
|
|
|
36
35
|
repeatSubmitDelay = 500,
|
|
37
36
|
/** Click handler */
|
|
38
37
|
onClick = undefined,
|
|
39
|
-
/**
|
|
38
|
+
/** Button content */
|
|
40
39
|
children
|
|
41
40
|
}: {
|
|
42
|
-
label?: string;
|
|
43
41
|
href?: string | undefined;
|
|
44
42
|
size?: FormFieldSizeOptions;
|
|
45
43
|
variant?: ButtonVariant;
|
|
@@ -53,12 +51,12 @@
|
|
|
53
51
|
collapse?: boolean;
|
|
54
52
|
repeatSubmitDelay?: number | 'infinite';
|
|
55
53
|
onClick?: ((e?: Event) => void) | undefined;
|
|
56
|
-
children
|
|
54
|
+
children: Snippet;
|
|
57
55
|
} = $props();
|
|
58
56
|
|
|
59
57
|
let isDisabled = $derived(disabled || loading);
|
|
60
58
|
|
|
61
|
-
const
|
|
59
|
+
const handleClick = (e: Event) => {
|
|
62
60
|
if (isDisabled) {
|
|
63
61
|
e.preventDefault();
|
|
64
62
|
e.stopPropagation();
|
|
@@ -79,25 +77,23 @@
|
|
|
79
77
|
|
|
80
78
|
<button
|
|
81
79
|
{type}
|
|
82
|
-
onclick={
|
|
80
|
+
onclick={handleClick}
|
|
83
81
|
class="{size} {variant} {flex ? 'flex' : ''}"
|
|
84
82
|
class:block
|
|
85
83
|
class:noMargin
|
|
86
84
|
class:collapse
|
|
87
85
|
class:loading
|
|
88
86
|
disabled={isDisabled}
|
|
89
|
-
aria-label={ariaLabel
|
|
87
|
+
aria-label={ariaLabel}
|
|
90
88
|
aria-busy={loading}
|
|
91
89
|
aria-disabled={isDisabled}
|
|
92
90
|
>
|
|
93
91
|
{#if loading}
|
|
94
|
-
<span class="
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{@render children()}
|
|
98
|
-
{:else if label}
|
|
99
|
-
<span class="label">{label}</span>
|
|
92
|
+
<span class="spinner-wrapper" aria-hidden="true">
|
|
93
|
+
<Spinner {size} variant={variant === 'outline' ? 'secondary' : 'primary'} />
|
|
94
|
+
</span>
|
|
100
95
|
{/if}
|
|
96
|
+
{@render children()}
|
|
101
97
|
</button>
|
|
102
98
|
|
|
103
99
|
<style>button {
|
|
@@ -228,4 +224,10 @@ button.link {
|
|
|
228
224
|
}
|
|
229
225
|
button.link:hover {
|
|
230
226
|
color: var(--base-link-hover-fg);
|
|
227
|
+
}
|
|
228
|
+
button .spinner-wrapper {
|
|
229
|
+
display: inline-flex;
|
|
230
|
+
align-items: center;
|
|
231
|
+
margin-right: var(--spacing-xs);
|
|
232
|
+
vertical-align: middle;
|
|
231
233
|
}</style>
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import type { Snippet } from 'svelte';
|
|
6
6
|
import type { ButtonVariant, FormFieldSizeOptions } from '../../types/form.js';
|
|
7
7
|
type $$ComponentProps = {
|
|
8
|
-
label?: string;
|
|
9
8
|
href?: string | undefined;
|
|
10
9
|
size?: FormFieldSizeOptions;
|
|
11
10
|
variant?: ButtonVariant;
|
|
@@ -19,7 +18,7 @@ type $$ComponentProps = {
|
|
|
19
18
|
collapse?: boolean;
|
|
20
19
|
repeatSubmitDelay?: number | 'infinite';
|
|
21
20
|
onClick?: ((e?: Event) => void) | undefined;
|
|
22
|
-
children
|
|
21
|
+
children: Snippet;
|
|
23
22
|
};
|
|
24
23
|
declare const Button: import("svelte").Component<$$ComponentProps, {}, "disabled">;
|
|
25
24
|
type Button = ReturnType<typeof Button>;
|
|
@@ -152,14 +152,11 @@
|
|
|
152
152
|
</FormInputWrapper>
|
|
153
153
|
{#if steps.length > 0}
|
|
154
154
|
<span class="steps">
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
label={step.label}
|
|
161
|
-
/>
|
|
162
|
-
{/each}
|
|
155
|
+
{#each steps as step}
|
|
156
|
+
<Button noMargin={true} collapse={true} onClick={() => incrementValue(step)}>
|
|
157
|
+
{step.label}
|
|
158
|
+
</Button>
|
|
159
|
+
{/each}
|
|
163
160
|
</span>
|
|
164
161
|
{/if}
|
|
165
162
|
</div>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import Button from '../button/button.svelte';
|
|
4
|
+
import type { ButtonVariant } from '../../types';
|
|
5
|
+
|
|
6
|
+
export type AdditionalButton = {
|
|
7
|
+
type?: 'button' | 'submit' | 'reset';
|
|
8
|
+
variant?: ButtonVariant;
|
|
9
|
+
text: string;
|
|
10
|
+
onClick?: ((e?: Event) => void) | undefined;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
children,
|
|
16
|
+
disabled = false,
|
|
17
|
+
onCancel = undefined,
|
|
18
|
+
onSubmit = undefined,
|
|
19
|
+
cancelText = 'Cancel',
|
|
20
|
+
cancelVariant = 'secondary',
|
|
21
|
+
submitText = 'Submit',
|
|
22
|
+
submitVariant = 'primary',
|
|
23
|
+
additionalButtons = []
|
|
24
|
+
}: {
|
|
25
|
+
children?: Snippet;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
onCancel?: (() => void) | undefined;
|
|
28
|
+
cancelText?: string;
|
|
29
|
+
cancelVariant?: ButtonVariant;
|
|
30
|
+
submitText?: string;
|
|
31
|
+
submitVariant?: ButtonVariant;
|
|
32
|
+
onSubmit?: (() => void) | undefined;
|
|
33
|
+
additionalButtons?: AdditionalButton[];
|
|
34
|
+
} = $props();
|
|
35
|
+
|
|
36
|
+
const buttons = $derived(
|
|
37
|
+
[
|
|
38
|
+
onCancel
|
|
39
|
+
? {
|
|
40
|
+
type: 'button' as const,
|
|
41
|
+
variant: cancelVariant,
|
|
42
|
+
text: cancelText,
|
|
43
|
+
onClick: onCancel,
|
|
44
|
+
disabled
|
|
45
|
+
}
|
|
46
|
+
: undefined,
|
|
47
|
+
...additionalButtons.map((btn) => ({ ...btn, disabled: btn.disabled || disabled })),
|
|
48
|
+
{
|
|
49
|
+
type: 'submit' as const,
|
|
50
|
+
variant: submitVariant,
|
|
51
|
+
text: submitText,
|
|
52
|
+
onClick: onSubmit,
|
|
53
|
+
disabled
|
|
54
|
+
}
|
|
55
|
+
].filter(Boolean) as AdditionalButton[]
|
|
56
|
+
);
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<div class="form-actions">
|
|
60
|
+
{#if children}
|
|
61
|
+
<div class="content">
|
|
62
|
+
{@render children()}
|
|
63
|
+
</div>
|
|
64
|
+
{/if}
|
|
65
|
+
<div class="buttons">
|
|
66
|
+
{#each buttons as button}
|
|
67
|
+
<Button
|
|
68
|
+
type={button.type ?? 'button'}
|
|
69
|
+
variant={button.variant ?? 'secondary'}
|
|
70
|
+
onClick={button.onClick}
|
|
71
|
+
disabled={button.disabled}
|
|
72
|
+
>
|
|
73
|
+
{button.text}
|
|
74
|
+
</Button>
|
|
75
|
+
{/each}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<style>/* ============================================
|
|
80
|
+
BREAKPOINTS - Responsive Design
|
|
81
|
+
============================================ */
|
|
82
|
+
.form-actions {
|
|
83
|
+
display: flex;
|
|
84
|
+
flex-direction: row;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: space-between;
|
|
87
|
+
gap: var(--spacing-md);
|
|
88
|
+
/* Vertical spacing - separate form from actions and actions from content below */
|
|
89
|
+
margin-top: var(--spacing-xl);
|
|
90
|
+
margin-bottom: var(--spacing-lg);
|
|
91
|
+
padding-top: var(--spacing-lg);
|
|
92
|
+
/* Optional: Add a subtle top border to visually separate from form content */
|
|
93
|
+
border-top: 1px solid var(--gray-200);
|
|
94
|
+
}
|
|
95
|
+
.form-actions .content {
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: row;
|
|
98
|
+
align-items: center;
|
|
99
|
+
gap: var(--spacing-sm);
|
|
100
|
+
flex: 0 1 auto; /* Don't grow, can shrink, auto basis */
|
|
101
|
+
}
|
|
102
|
+
.form-actions .buttons {
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: row;
|
|
105
|
+
align-items: center;
|
|
106
|
+
gap: var(--spacing-sm);
|
|
107
|
+
flex: 0 0 auto; /* Don't grow, don't shrink, auto basis */
|
|
108
|
+
margin-left: auto; /* Push to the right */
|
|
109
|
+
}
|
|
110
|
+
.form-actions {
|
|
111
|
+
/* Responsive: Stack on mobile */
|
|
112
|
+
}
|
|
113
|
+
@media (max-width: 479.98px) {
|
|
114
|
+
.form-actions {
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
align-items: stretch;
|
|
117
|
+
gap: var(--spacing-md);
|
|
118
|
+
}
|
|
119
|
+
.form-actions .content,
|
|
120
|
+
.form-actions .buttons {
|
|
121
|
+
width: 100%;
|
|
122
|
+
justify-content: flex-start;
|
|
123
|
+
}
|
|
124
|
+
.form-actions .buttons {
|
|
125
|
+
margin-left: 0;
|
|
126
|
+
justify-content: flex-end;
|
|
127
|
+
}
|
|
128
|
+
}</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ButtonVariant } from '../../types';
|
|
3
|
+
export type AdditionalButton = {
|
|
4
|
+
type?: 'button' | 'submit' | 'reset';
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
text: string;
|
|
7
|
+
onClick?: ((e?: Event) => void) | undefined;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type $$ComponentProps = {
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
onCancel?: (() => void) | undefined;
|
|
14
|
+
cancelText?: string;
|
|
15
|
+
cancelVariant?: ButtonVariant;
|
|
16
|
+
submitText?: string;
|
|
17
|
+
submitVariant?: ButtonVariant;
|
|
18
|
+
onSubmit?: (() => void) | undefined;
|
|
19
|
+
additionalButtons?: AdditionalButton[];
|
|
20
|
+
};
|
|
21
|
+
declare const FormActions: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
22
|
+
type FormActions = ReturnType<typeof FormActions>;
|
|
23
|
+
export default FormActions;
|
package/dist/forms/index.d.ts
CHANGED
|
@@ -21,10 +21,12 @@ export * from './list-box/index.js';
|
|
|
21
21
|
export * from './phone-box/index.js';
|
|
22
22
|
export * from './radio-group/index.js';
|
|
23
23
|
export { default as Form } from './form.svelte';
|
|
24
|
+
export { default as FormActions } from './form-actions/form-actions.svelte';
|
|
24
25
|
export { default as FormField } from './form-field/form-field.svelte';
|
|
25
26
|
export { default as FormFooter } from './form-footer.svelte';
|
|
26
27
|
export { default as FormHeader } from './form-header.svelte';
|
|
27
28
|
export { default as FormLabel } from './form-label/form-label.svelte';
|
|
28
29
|
export { default as FormSection } from './form-section/form-section.svelte';
|
|
29
30
|
export { default as FormRow } from './form-row/form-row.svelte';
|
|
31
|
+
export type { AdditionalButton } from './form-actions/form-actions.svelte';
|
|
30
32
|
export * from './validation.js';
|
package/dist/forms/index.js
CHANGED
|
@@ -24,6 +24,7 @@ export * from './phone-box/index.js';
|
|
|
24
24
|
export * from './radio-group/index.js';
|
|
25
25
|
// Form structure components
|
|
26
26
|
export { default as Form } from './form.svelte';
|
|
27
|
+
export { default as FormActions } from './form-actions/form-actions.svelte';
|
|
27
28
|
export { default as FormField } from './form-field/form-field.svelte';
|
|
28
29
|
export { default as FormFooter } from './form-footer.svelte';
|
|
29
30
|
export { default as FormHeader } from './form-header.svelte';
|
package/dist/modals/alert.svelte
CHANGED
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
<DialogBody>
|
|
55
55
|
{@render children?.()}
|
|
56
56
|
</DialogBody>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
<Divider />
|
|
58
|
+
<DialogFooter>
|
|
59
|
+
<Button onClick={close} size="full" variant={buttonVariant}>{buttonText}</Button>
|
|
60
|
+
</DialogFooter>
|
|
61
61
|
</Dialog>
|
|
62
62
|
</Overlay>
|
|
63
63
|
{/if}
|
|
@@ -65,11 +65,11 @@
|
|
|
65
65
|
<DialogBody>
|
|
66
66
|
{@render children?.()}
|
|
67
67
|
</DialogBody>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
<Divider />
|
|
69
|
+
<DialogFooter>
|
|
70
|
+
<Button onClick={no} variant={noVariant} size="full">{noText}</Button>
|
|
71
|
+
<Button onClick={yes} variant={yesVariant} size="full">{yesText}</Button>
|
|
72
|
+
</DialogFooter>
|
|
73
73
|
</Dialog>
|
|
74
74
|
</Overlay>
|
|
75
75
|
{/if}
|
|
@@ -78,11 +78,11 @@
|
|
|
78
78
|
{@render children()}
|
|
79
79
|
{/if}
|
|
80
80
|
</DialogBody>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
<Divider />
|
|
82
|
+
<DialogFooter>
|
|
83
|
+
<Button onClick={no} variant={cancelVariant} size="full">{cancelText}</Button>
|
|
84
|
+
<Button onClick={yes} variant={okVariant} size="full">{okText}</Button>
|
|
85
|
+
</DialogFooter>
|
|
86
86
|
</Dialog>
|
|
87
87
|
</Overlay>
|
|
88
88
|
{/if}
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
<footer>
|
|
127
127
|
<div>
|
|
128
128
|
{#if !isFirstStep}
|
|
129
|
-
<Button type="button" variant="secondary" onClick={previous} {disabled}
|
|
129
|
+
<Button type="button" variant="secondary" onClick={previous} {disabled}>Previous</Button>
|
|
130
130
|
{/if}
|
|
131
131
|
</div>
|
|
132
132
|
<div>
|
|
@@ -134,9 +134,9 @@
|
|
|
134
134
|
</div>
|
|
135
135
|
<div>
|
|
136
136
|
{#if isLastStep}
|
|
137
|
-
<Button type="submit" variant="primary" onClick={done} {disabled}
|
|
137
|
+
<Button type="submit" variant="primary" onClick={done} {disabled}>Done</Button>
|
|
138
138
|
{:else}
|
|
139
|
-
<Button type="button" variant="primary" onClick={next} {disabled}
|
|
139
|
+
<Button type="button" variant="primary" onClick={next} {disabled}>Next</Button>
|
|
140
140
|
{/if}
|
|
141
141
|
</div>
|
|
142
142
|
</footer>
|