@sveltier/ui 0.0.0-stage → 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +82 -2
- package/dist/components/Alert/Alert.svelte +88 -0
- package/dist/components/Alert/Alert.svelte.d.ts +4 -0
- package/dist/components/Alert/alert.css +78 -0
- package/dist/components/Alert/index.d.ts +2 -0
- package/dist/components/Alert/index.js +1 -0
- package/dist/components/Alert/types.d.ts +67 -0
- package/dist/components/Alert/types.js +1 -0
- package/dist/components/Avatar/Avatar.svelte +47 -0
- package/dist/components/Avatar/Avatar.svelte.d.ts +4 -0
- package/dist/components/Avatar/avatar.css +34 -0
- package/dist/components/Avatar/index.d.ts +2 -0
- package/dist/components/Avatar/index.js +1 -0
- package/dist/components/Avatar/types.d.ts +47 -0
- package/dist/components/Avatar/types.js +1 -0
- package/dist/components/Badge/Badge.svelte +53 -0
- package/dist/components/Badge/Badge.svelte.d.ts +4 -0
- package/dist/components/Badge/badge.css +57 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Badge/index.js +1 -0
- package/dist/components/Badge/types.d.ts +43 -0
- package/dist/components/Badge/types.js +1 -0
- package/dist/components/Button/Button.svelte +85 -0
- package/dist/components/Button/Button.svelte.d.ts +4 -0
- package/dist/components/Button/button.css +132 -0
- package/dist/components/Button/index.d.ts +2 -0
- package/dist/components/Button/index.js +1 -0
- package/dist/components/Button/types.d.ts +76 -0
- package/dist/components/Button/types.js +1 -0
- package/dist/components/ButtonGroup/ButtonGroup.svelte +61 -0
- package/dist/components/ButtonGroup/ButtonGroup.svelte.d.ts +4 -0
- package/dist/components/ButtonGroup/button-group.css +39 -0
- package/dist/components/ButtonGroup/index.d.ts +2 -0
- package/dist/components/ButtonGroup/index.js +1 -0
- package/dist/components/ButtonGroup/types.d.ts +48 -0
- package/dist/components/ButtonGroup/types.js +1 -0
- package/dist/components/Card/Card.svelte +53 -0
- package/dist/components/Card/Card.svelte.d.ts +4 -0
- package/dist/components/Card/card.css +62 -0
- package/dist/components/Card/index.d.ts +2 -0
- package/dist/components/Card/index.js +1 -0
- package/dist/components/Card/types.d.ts +56 -0
- package/dist/components/Card/types.js +1 -0
- package/dist/components/Checkbox/Checkbox.svelte +105 -0
- package/dist/components/Checkbox/Checkbox.svelte.d.ts +4 -0
- package/dist/components/Checkbox/checkbox.css +138 -0
- package/dist/components/Checkbox/index.d.ts +2 -0
- package/dist/components/Checkbox/index.js +1 -0
- package/dist/components/Checkbox/types.d.ts +76 -0
- package/dist/components/Checkbox/types.js +1 -0
- package/dist/components/Chip/Chip.svelte +109 -0
- package/dist/components/Chip/Chip.svelte.d.ts +4 -0
- package/dist/components/Chip/chip.css +101 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Chip/index.js +1 -0
- package/dist/components/Chip/types.d.ts +69 -0
- package/dist/components/Chip/types.js +1 -0
- package/dist/components/Choice/Choice.svelte +60 -0
- package/dist/components/Choice/Choice.svelte.d.ts +4 -0
- package/dist/components/Choice/choice.css +75 -0
- package/dist/components/Choice/types.d.ts +43 -0
- package/dist/components/Choice/types.js +1 -0
- package/dist/components/Divider/Divider.svelte +19 -0
- package/dist/components/Divider/Divider.svelte.d.ts +4 -0
- package/dist/components/Divider/divider.css +23 -0
- package/dist/components/Divider/index.d.ts +2 -0
- package/dist/components/Divider/index.js +1 -0
- package/dist/components/Divider/types.d.ts +10 -0
- package/dist/components/Divider/types.js +1 -0
- package/dist/components/Field/Field.svelte +95 -0
- package/dist/components/Field/Field.svelte.d.ts +4 -0
- package/dist/components/Field/field.css +210 -0
- package/dist/components/Field/index.d.ts +3 -0
- package/dist/components/Field/index.js +2 -0
- package/dist/components/Field/types.d.ts +109 -0
- package/dist/components/Field/types.js +2 -0
- package/dist/components/Form/Form.svelte +93 -0
- package/dist/components/Form/Form.svelte.d.ts +8 -0
- package/dist/components/Form/form.css +16 -0
- package/dist/components/Form/index.d.ts +2 -0
- package/dist/components/Form/index.js +1 -0
- package/dist/components/Form/types.d.ts +38 -0
- package/dist/components/Form/types.js +1 -0
- package/dist/components/Icon/Icon.svelte +38 -0
- package/dist/components/Icon/Icon.svelte.d.ts +4 -0
- package/dist/components/Icon/icon.css +33 -0
- package/dist/components/Icon/index.d.ts +2 -0
- package/dist/components/Icon/index.js +1 -0
- package/dist/components/Icon/types.d.ts +34 -0
- package/dist/components/Icon/types.js +1 -0
- package/dist/components/List/List.svelte +39 -0
- package/dist/components/List/List.svelte.d.ts +4 -0
- package/dist/components/List/ListItem.svelte +57 -0
- package/dist/components/List/ListItem.svelte.d.ts +4 -0
- package/dist/components/List/index.d.ts +3 -0
- package/dist/components/List/index.js +2 -0
- package/dist/components/List/list.css +127 -0
- package/dist/components/List/types.d.ts +67 -0
- package/dist/components/List/types.js +1 -0
- package/dist/components/NativeSelect/NativeSelect.svelte +110 -0
- package/dist/components/NativeSelect/NativeSelect.svelte.d.ts +25 -0
- package/dist/components/NativeSelect/index.d.ts +2 -0
- package/dist/components/NativeSelect/index.js +1 -0
- package/dist/components/NativeSelect/native-select.css +45 -0
- package/dist/components/NativeSelect/types.d.ts +58 -0
- package/dist/components/NativeSelect/types.js +1 -0
- package/dist/components/NumberField/NumberField.svelte +246 -0
- package/dist/components/NumberField/NumberField.svelte.d.ts +4 -0
- package/dist/components/NumberField/index.d.ts +2 -0
- package/dist/components/NumberField/index.js +1 -0
- package/dist/components/NumberField/number-field.css +74 -0
- package/dist/components/NumberField/types.d.ts +73 -0
- package/dist/components/NumberField/types.js +1 -0
- package/dist/components/Progress/ProgressCircular.svelte +61 -0
- package/dist/components/Progress/ProgressCircular.svelte.d.ts +4 -0
- package/dist/components/Progress/ProgressLinear.svelte +44 -0
- package/dist/components/Progress/ProgressLinear.svelte.d.ts +4 -0
- package/dist/components/Progress/index.d.ts +3 -0
- package/dist/components/Progress/index.js +2 -0
- package/dist/components/Progress/progress-circular.css +61 -0
- package/dist/components/Progress/progress-linear.css +67 -0
- package/dist/components/Progress/types.d.ts +53 -0
- package/dist/components/Progress/types.js +1 -0
- package/dist/components/RadioGroup/RadioGroup.svelte +149 -0
- package/dist/components/RadioGroup/RadioGroup.svelte.d.ts +25 -0
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/RadioGroup/index.js +1 -0
- package/dist/components/RadioGroup/radio-group.css +139 -0
- package/dist/components/RadioGroup/types.d.ts +93 -0
- package/dist/components/RadioGroup/types.js +1 -0
- package/dist/components/SegmentedControl/SegmentedControl.svelte +70 -0
- package/dist/components/SegmentedControl/SegmentedControl.svelte.d.ts +25 -0
- package/dist/components/SegmentedControl/index.d.ts +2 -0
- package/dist/components/SegmentedControl/index.js +1 -0
- package/dist/components/SegmentedControl/segmented-control.css +68 -0
- package/dist/components/SegmentedControl/types.d.ts +60 -0
- package/dist/components/SegmentedControl/types.js +1 -0
- package/dist/components/Skeleton/Skeleton.svelte +33 -0
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +4 -0
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Skeleton/index.js +1 -0
- package/dist/components/Skeleton/skeleton.css +70 -0
- package/dist/components/Skeleton/types.d.ts +25 -0
- package/dist/components/Skeleton/types.js +1 -0
- package/dist/components/Slider/Slider.svelte +153 -0
- package/dist/components/Slider/Slider.svelte.d.ts +4 -0
- package/dist/components/Slider/index.d.ts +2 -0
- package/dist/components/Slider/index.js +1 -0
- package/dist/components/Slider/slider.css +206 -0
- package/dist/components/Slider/types.d.ts +102 -0
- package/dist/components/Slider/types.js +1 -0
- package/dist/components/Switch/Switch.svelte +94 -0
- package/dist/components/Switch/Switch.svelte.d.ts +4 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Switch/index.js +1 -0
- package/dist/components/Switch/switch.css +118 -0
- package/dist/components/Switch/types.d.ts +67 -0
- package/dist/components/Switch/types.js +1 -0
- package/dist/components/Tabs/Tabs.svelte +93 -0
- package/dist/components/Tabs/Tabs.svelte.d.ts +25 -0
- package/dist/components/Tabs/index.d.ts +2 -0
- package/dist/components/Tabs/index.js +1 -0
- package/dist/components/Tabs/tabs.css +73 -0
- package/dist/components/Tabs/types.d.ts +59 -0
- package/dist/components/Tabs/types.js +1 -0
- package/dist/components/TextField/TextField.svelte +115 -0
- package/dist/components/TextField/TextField.svelte.d.ts +4 -0
- package/dist/components/TextField/index.d.ts +2 -0
- package/dist/components/TextField/index.js +1 -0
- package/dist/components/TextField/types.d.ts +57 -0
- package/dist/components/TextField/types.js +1 -0
- package/dist/components/Textarea/Textarea.svelte +116 -0
- package/dist/components/Textarea/Textarea.svelte.d.ts +4 -0
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/Textarea/index.js +1 -0
- package/dist/components/Textarea/textarea.css +35 -0
- package/dist/components/Textarea/types.d.ts +60 -0
- package/dist/components/Textarea/types.js +1 -0
- package/dist/core/defaults/DefaultsProvider.svelte +30 -0
- package/dist/core/defaults/DefaultsProvider.svelte.d.ts +13 -0
- package/dist/core/defaults/context.d.ts +45 -0
- package/dist/core/defaults/context.js +38 -0
- package/dist/core/display/display.d.ts +39 -0
- package/dist/core/display/display.js +53 -0
- package/dist/core/errors/codes.d.ts +112 -0
- package/dist/core/errors/codes.js +96 -0
- package/dist/core/errors/errors.d.ts +8 -0
- package/dist/core/errors/errors.js +7 -0
- package/dist/core/form/constraints.d.ts +15 -0
- package/dist/core/form/constraints.js +42 -0
- package/dist/core/form/context.d.ts +19 -0
- package/dist/core/form/context.js +4 -0
- package/dist/core/form/field.svelte.d.ts +34 -0
- package/dist/core/form/field.svelte.js +66 -0
- package/dist/core/form/number.d.ts +24 -0
- package/dist/core/form/number.js +71 -0
- package/dist/core/form/types.d.ts +22 -0
- package/dist/core/form/types.js +1 -0
- package/dist/core/locale/locale.d.ts +55 -0
- package/dist/core/locale/locale.js +80 -0
- package/dist/core/props/classes.d.ts +21 -0
- package/dist/core/props/classes.js +44 -0
- package/dist/core/props/element.d.ts +18 -0
- package/dist/core/props/element.js +1 -0
- package/dist/core/props/types.d.ts +47 -0
- package/dist/core/props/types.js +16 -0
- package/dist/core/provider/UIProvider.svelte +60 -0
- package/dist/core/provider/UIProvider.svelte.d.ts +29 -0
- package/dist/core/theme/ThemeProvider.svelte +178 -0
- package/dist/core/theme/ThemeProvider.svelte.d.ts +25 -0
- package/dist/core/theme/color.d.ts +23 -0
- package/dist/core/theme/color.js +54 -0
- package/dist/core/theme/context.d.ts +25 -0
- package/dist/core/theme/context.js +14 -0
- package/dist/core/theme/css.d.ts +25 -0
- package/dist/core/theme/css.js +69 -0
- package/dist/core/theme/define.d.ts +11 -0
- package/dist/core/theme/define.js +21 -0
- package/dist/core/theme/resolve.d.ts +6 -0
- package/dist/core/theme/resolve.js +18 -0
- package/dist/core/theme/theme-provider.css +13 -0
- package/dist/core/theme/types.d.ts +35 -0
- package/dist/core/theme/types.js +61 -0
- package/dist/dev/off.d.ts +4 -0
- package/dist/dev/off.js +3 -0
- package/dist/dev/on.d.ts +8 -0
- package/dist/dev/on.js +33 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +72 -0
- package/dist/primitives/anchored/anchored.d.ts +39 -0
- package/dist/primitives/anchored/anchored.js +104 -0
- package/dist/primitives/anchored/fallback.d.ts +31 -0
- package/dist/primitives/anchored/fallback.js +73 -0
- package/dist/primitives/focus/focus-trap.d.ts +25 -0
- package/dist/primitives/focus/focus-trap.js +86 -0
- package/dist/primitives/focus/roving-focus.d.ts +22 -0
- package/dist/primitives/focus/roving-focus.js +86 -0
- package/dist/primitives/focus/tabbable.d.ts +9 -0
- package/dist/primitives/focus/tabbable.js +75 -0
- package/dist/primitives/inert/inert-others.d.ts +12 -0
- package/dist/primitives/inert/inert-others.js +44 -0
- package/dist/primitives/keyboard/keymap.d.ts +17 -0
- package/dist/primitives/keyboard/keymap.js +39 -0
- package/dist/primitives/keyboard/typeahead.d.ts +18 -0
- package/dist/primitives/keyboard/typeahead.js +50 -0
- package/dist/primitives/layer/dismissable.d.ts +26 -0
- package/dist/primitives/layer/dismissable.js +84 -0
- package/dist/primitives/motion/easing.d.ts +9 -0
- package/dist/primitives/motion/easing.js +46 -0
- package/dist/primitives/motion/motion.d.ts +59 -0
- package/dist/primitives/motion/motion.js +80 -0
- package/dist/primitives/portal/Portal.svelte +37 -0
- package/dist/primitives/portal/Portal.svelte.d.ts +9 -0
- package/dist/primitives/portal/PortalContent.svelte +15 -0
- package/dist/primitives/portal/PortalContent.svelte.d.ts +9 -0
- package/dist/primitives/portal/portal.css +8 -0
- package/dist/primitives/scroll-lock/scroll-lock.d.ts +10 -0
- package/dist/primitives/scroll-lock/scroll-lock.js +33 -0
- package/dist/primitives/virtual/virtual-list.svelte.d.ts +65 -0
- package/dist/primitives/virtual/virtual-list.svelte.js +291 -0
- package/dist/styles/base.css +44 -0
- package/dist/styles/props.css +137 -0
- package/dist/styles/tokens.css +84 -0
- package/dist/styles/visually-hidden.css +16 -0
- package/dist/themes/aurora.d.ts +13 -0
- package/dist/themes/aurora.js +103 -0
- package/dist/themes/heritage.d.ts +13 -0
- package/dist/themes/heritage.js +102 -0
- package/dist/themes/maison.d.ts +13 -0
- package/dist/themes/maison.js +99 -0
- package/dist/themes/milano.d.ts +13 -0
- package/dist/themes/milano.js +101 -0
- package/dist/themes/monolith.d.ts +13 -0
- package/dist/themes/monolith.js +101 -0
- package/package.json +87 -5
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TabsProps } from './types.js';
|
|
2
|
+
declare function $$render<T extends string | number>(): {
|
|
3
|
+
props: TabsProps<T>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "ref" | "value";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<T extends string | number> {
|
|
10
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
13
|
+
bindings(): "ref" | "value";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <T extends string | number>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
20
|
+
<T extends string | number>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
declare const Tabs: $$IsomorphicComponent;
|
|
24
|
+
type Tabs<T extends string | number> = InstanceType<typeof Tabs<T>>;
|
|
25
|
+
export default Tabs;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Tabs } from './Tabs.svelte';
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
@layer sv.tokens, sv.base, sv.components, sv.utilities;
|
|
2
|
+
|
|
3
|
+
@layer sv.components {
|
|
4
|
+
.sv-tabs {
|
|
5
|
+
display: grid;
|
|
6
|
+
gap: var(--sv-space-13);
|
|
7
|
+
min-inline-size: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* A row that scrolls when the tabs do not fit, over a hairline. */
|
|
11
|
+
.sv-tabs__list {
|
|
12
|
+
display: flex;
|
|
13
|
+
overflow-x: auto;
|
|
14
|
+
box-shadow: inset 0 calc(var(--sv-hairline) * -1) 0 var(--sv-color-border);
|
|
15
|
+
scrollbar-width: thin;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.sv-tabs__tab {
|
|
19
|
+
position: relative;
|
|
20
|
+
flex: none;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
block-size: calc(var(--sv-size-height) * var(--sv-density));
|
|
23
|
+
margin: 0;
|
|
24
|
+
padding: 0 calc(var(--sv-size-height) * var(--sv-density) * 0.382);
|
|
25
|
+
border: 0;
|
|
26
|
+
background: transparent;
|
|
27
|
+
color: var(--sv-color-text-muted);
|
|
28
|
+
font: var(--sv-weight-medium) var(--sv-size-text) / 1 var(--sv-font-ui);
|
|
29
|
+
white-space: nowrap;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
-webkit-tap-highlight-color: transparent;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.sv-tabs--grow .sv-tabs__tab {
|
|
35
|
+
flex: 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@media (hover: hover) {
|
|
39
|
+
.sv-tabs__tab:not(:disabled):hover {
|
|
40
|
+
color: var(--sv-color-text);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.sv-tabs__tab[aria-selected='true'] {
|
|
45
|
+
color: var(--sv-color);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.sv-tabs__tab:disabled {
|
|
49
|
+
opacity: 0.382;
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* The selected tab's underline scales in: transform only. */
|
|
54
|
+
.sv-tabs__tab::after {
|
|
55
|
+
content: '';
|
|
56
|
+
position: absolute;
|
|
57
|
+
inset-inline: 0;
|
|
58
|
+
inset-block-end: 0;
|
|
59
|
+
block-size: 2px;
|
|
60
|
+
border-radius: 2px 2px 0 0;
|
|
61
|
+
background-color: var(--sv-color);
|
|
62
|
+
transform: scaleX(0);
|
|
63
|
+
transition: transform var(--sv-duration-normal) var(--sv-ease);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.sv-tabs__tab[aria-selected='true']::after {
|
|
67
|
+
transform: scaleX(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.sv-tabs__panel {
|
|
71
|
+
min-inline-size: 0;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ElementProps } from '../../core/props/element.js';
|
|
4
|
+
import type { Color, Density, Size } from '../../core/props/types.js';
|
|
5
|
+
/** The Tabs props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
|
|
6
|
+
export interface TabsDefaults {
|
|
7
|
+
/**
|
|
8
|
+
* The colour of the selected tab and its underline.
|
|
9
|
+
* @default 'primary'
|
|
10
|
+
*/
|
|
11
|
+
color: Color;
|
|
12
|
+
/**
|
|
13
|
+
* Height and text size of the tabs.
|
|
14
|
+
* @default 'md'
|
|
15
|
+
*/
|
|
16
|
+
size: Size;
|
|
17
|
+
/**
|
|
18
|
+
* Multiplies the height and padding of the tabs, never the text.
|
|
19
|
+
* @default 'default'
|
|
20
|
+
*/
|
|
21
|
+
density: Density;
|
|
22
|
+
/**
|
|
23
|
+
* Tabs share the full width equally.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
grow: boolean;
|
|
27
|
+
}
|
|
28
|
+
declare module '../../core/defaults/context.js' {
|
|
29
|
+
interface ComponentDefaults {
|
|
30
|
+
Tabs: TabsDefaults;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** One tab. */
|
|
34
|
+
export interface TabsItem<T extends string | number = string> {
|
|
35
|
+
value: T;
|
|
36
|
+
/** What the tab says. */
|
|
37
|
+
label: string;
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Tabs and the panel of the selected one. Name the tab list with `aria-label` or
|
|
42
|
+
* `aria-labelledby`, which go to it.
|
|
43
|
+
*/
|
|
44
|
+
export type TabsProps<T extends string | number = string> = ElementProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>, Partial<TabsDefaults> & {
|
|
45
|
+
/** The tabs, in order. */
|
|
46
|
+
items: readonly TabsItem<T>[];
|
|
47
|
+
/** The selected tab. Bindable; the first enabled tab when not set. */
|
|
48
|
+
value?: T;
|
|
49
|
+
/** Called with the value of the tab the user selects. */
|
|
50
|
+
onchange?: (value: T) => void;
|
|
51
|
+
/**
|
|
52
|
+
* `automatic` selects a tab as soon as the arrow keys reach it; `manual` waits for Enter or
|
|
53
|
+
* Space, for panels that are slow to show.
|
|
54
|
+
* @default 'automatic'
|
|
55
|
+
*/
|
|
56
|
+
activation?: 'automatic' | 'manual';
|
|
57
|
+
/** The content of the selected tab's panel. */
|
|
58
|
+
panel?: Snippet<[TabsItem<T>]>;
|
|
59
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// A single line of text in a Field, with validation. See TextFieldProps for the props.
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { checkValue, DEV, warnUnnamed } from '#dev';
|
|
5
|
+
import { useDefaults } from '../../core/defaults/context.js';
|
|
6
|
+
import { textConstraintMessage } from '../../core/form/constraints.js';
|
|
7
|
+
import { createField } from '../../core/form/field.svelte.js';
|
|
8
|
+
import { useLocale } from '../../core/locale/locale.js';
|
|
9
|
+
import Field from '../Field/Field.svelte';
|
|
10
|
+
import { TEXT_FIELD_TYPES, type TextFieldDefaults, type TextFieldProps } from './types.js';
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
variant,
|
|
14
|
+
color,
|
|
15
|
+
size,
|
|
16
|
+
density,
|
|
17
|
+
rounded,
|
|
18
|
+
disabled,
|
|
19
|
+
value = $bindable(''),
|
|
20
|
+
type = 'text',
|
|
21
|
+
label,
|
|
22
|
+
hint,
|
|
23
|
+
error,
|
|
24
|
+
rules,
|
|
25
|
+
validateOn,
|
|
26
|
+
required = false,
|
|
27
|
+
readonly = false,
|
|
28
|
+
prepend,
|
|
29
|
+
append,
|
|
30
|
+
id,
|
|
31
|
+
'aria-describedby': describedBy,
|
|
32
|
+
class: className,
|
|
33
|
+
style,
|
|
34
|
+
ref = $bindable(null),
|
|
35
|
+
...rest
|
|
36
|
+
}: TextFieldProps = $props();
|
|
37
|
+
|
|
38
|
+
const resolve = useDefaults<TextFieldDefaults>('TextField', {
|
|
39
|
+
variant: 'outlined',
|
|
40
|
+
color: 'primary',
|
|
41
|
+
size: 'md',
|
|
42
|
+
density: 'default',
|
|
43
|
+
rounded: true,
|
|
44
|
+
disabled: false
|
|
45
|
+
});
|
|
46
|
+
const p = $derived(resolve({ variant, color, size, density, rounded, disabled }));
|
|
47
|
+
const locale = useLocale();
|
|
48
|
+
// A form reset goes back to the text the field started with, as it does for a form rendered on
|
|
49
|
+
// the server. A defaultValue of the app's own wins.
|
|
50
|
+
const initial = untrack(() => value ?? '');
|
|
51
|
+
|
|
52
|
+
const field = createField<string>({
|
|
53
|
+
value: () => value ?? '',
|
|
54
|
+
empty: (text) => text === '',
|
|
55
|
+
check: (text) =>
|
|
56
|
+
textConstraintMessage(
|
|
57
|
+
text,
|
|
58
|
+
{
|
|
59
|
+
required,
|
|
60
|
+
type,
|
|
61
|
+
minlength: rest.minlength,
|
|
62
|
+
maxlength: rest.maxlength,
|
|
63
|
+
pattern: rest.pattern
|
|
64
|
+
},
|
|
65
|
+
locale.t
|
|
66
|
+
),
|
|
67
|
+
rules: () => rules,
|
|
68
|
+
error: () => error,
|
|
69
|
+
validateOn: () => validateOn,
|
|
70
|
+
control: () => ref
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// The Field checks the variant; the input's own props are checked here, once it exists.
|
|
74
|
+
if (DEV) {
|
|
75
|
+
$effect(() => {
|
|
76
|
+
checkValue('TextField', 'type', type, TEXT_FIELD_TYPES);
|
|
77
|
+
warnUnnamed('TextField', ref);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Leaving means focus went outside the field, not to a button in it.
|
|
82
|
+
function leave(event: FocusEvent) {
|
|
83
|
+
const root = event.currentTarget as HTMLElement;
|
|
84
|
+
if (!root.contains(event.relatedTarget as Node | null)) field.left();
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<Field
|
|
89
|
+
{...p}
|
|
90
|
+
{id}
|
|
91
|
+
{label}
|
|
92
|
+
{hint}
|
|
93
|
+
error={field.error}
|
|
94
|
+
{required}
|
|
95
|
+
{readonly}
|
|
96
|
+
{prepend}
|
|
97
|
+
{append}
|
|
98
|
+
class={className}
|
|
99
|
+
{style}
|
|
100
|
+
oninput={field.changed}
|
|
101
|
+
onfocusout={leave}
|
|
102
|
+
>
|
|
103
|
+
{#snippet children(attributes)}
|
|
104
|
+
<input
|
|
105
|
+
bind:this={ref}
|
|
106
|
+
defaultValue={initial}
|
|
107
|
+
{...rest}
|
|
108
|
+
{...attributes}
|
|
109
|
+
aria-describedby={[describedBy, attributes['aria-describedby']].filter(Boolean).join(' ') ||
|
|
110
|
+
undefined}
|
|
111
|
+
{type}
|
|
112
|
+
bind:value
|
|
113
|
+
/>
|
|
114
|
+
{/snippet}
|
|
115
|
+
</Field>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as TextField } from './TextField.svelte';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
import type { Rule, ValidateOn } from '../../core/form/types.js';
|
|
3
|
+
import type { ElementProps } from '../../core/props/element.js';
|
|
4
|
+
import type { FieldContentProps, FieldDefaults } from '../Field/types.js';
|
|
5
|
+
/** The TextField props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
|
|
6
|
+
export type TextFieldDefaults = FieldDefaults;
|
|
7
|
+
declare module '../../core/defaults/context.js' {
|
|
8
|
+
interface ComponentDefaults {
|
|
9
|
+
TextField: TextFieldDefaults;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export declare const TEXT_FIELD_TYPES: readonly ["text", "email", "password", "search", "tel", "url"];
|
|
13
|
+
/** The kinds of single-line text. Numbers and dates have their own fields. */
|
|
14
|
+
export type TextFieldType = (typeof TEXT_FIELD_TYPES)[number];
|
|
15
|
+
type TextFieldOwnProps = Partial<TextFieldDefaults> & FieldContentProps & {
|
|
16
|
+
/** The text. Bindable. */
|
|
17
|
+
value?: string;
|
|
18
|
+
/**
|
|
19
|
+
* The kind of text: it picks the keyboard and autofill, and `email` and `url` are checked.
|
|
20
|
+
* @default 'text'
|
|
21
|
+
*/
|
|
22
|
+
type?: TextFieldType;
|
|
23
|
+
/** Checks run in order after the HTML constraints. The first message is shown. */
|
|
24
|
+
rules?: readonly Rule<string>[];
|
|
25
|
+
/** When the message shows. Defaults to the form's setting, else `'blur'`. */
|
|
26
|
+
validateOn?: ValidateOn;
|
|
27
|
+
/**
|
|
28
|
+
* The field must not be empty. Adds an asterisk to the label.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
required?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* The text can be read, selected and copied but not changed.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
readonly?: boolean;
|
|
37
|
+
/** Inline style of the field's root element. */
|
|
38
|
+
style?: string | null;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* A single line of text with a label, a hint and validation. `class` and `style` apply to the
|
|
42
|
+
* field; `id`, `ref` and every other attribute (`name`, `placeholder`, `autocomplete`,
|
|
43
|
+
* `minlength`, `pattern`, events) go to the `<input>`.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* <TextField
|
|
47
|
+
* label="Username"
|
|
48
|
+
* name="username"
|
|
49
|
+
* required
|
|
50
|
+
* minlength={3}
|
|
51
|
+
* rules={[(value) => /^[a-z0-9_]+$/.test(value) || 'Use lowercase letters, digits and _']}
|
|
52
|
+
* error={form?.errors?.username}
|
|
53
|
+
* bind:value={username}
|
|
54
|
+
* />
|
|
55
|
+
*/
|
|
56
|
+
export type TextFieldProps = ElementProps<HTMLInputElement, HTMLInputAttributes, TextFieldOwnProps>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const TEXT_FIELD_TYPES = ['text', 'email', 'password', 'search', 'tel', 'url'];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Several lines of text in a Field, with validation. See TextareaProps for the props.
|
|
3
|
+
import { untrack } from 'svelte';
|
|
4
|
+
import { DEV, warnUnnamed } from '#dev';
|
|
5
|
+
import { useDefaults } from '../../core/defaults/context.js';
|
|
6
|
+
import { textConstraintMessage } from '../../core/form/constraints.js';
|
|
7
|
+
import { createField } from '../../core/form/field.svelte.js';
|
|
8
|
+
import { useLocale } from '../../core/locale/locale.js';
|
|
9
|
+
import Field from '../Field/Field.svelte';
|
|
10
|
+
import './textarea.css';
|
|
11
|
+
import type { TextareaDefaults, TextareaProps } from './types.js';
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
variant,
|
|
15
|
+
color,
|
|
16
|
+
size,
|
|
17
|
+
density,
|
|
18
|
+
rounded,
|
|
19
|
+
disabled,
|
|
20
|
+
value = $bindable(''),
|
|
21
|
+
rows = 3,
|
|
22
|
+
autoGrow = false,
|
|
23
|
+
maxRows,
|
|
24
|
+
label,
|
|
25
|
+
hint,
|
|
26
|
+
error,
|
|
27
|
+
rules,
|
|
28
|
+
validateOn,
|
|
29
|
+
required = false,
|
|
30
|
+
readonly = false,
|
|
31
|
+
prepend,
|
|
32
|
+
append,
|
|
33
|
+
id,
|
|
34
|
+
'aria-describedby': describedBy,
|
|
35
|
+
class: className,
|
|
36
|
+
style,
|
|
37
|
+
ref = $bindable(null),
|
|
38
|
+
...rest
|
|
39
|
+
}: TextareaProps = $props();
|
|
40
|
+
|
|
41
|
+
const resolve = useDefaults<TextareaDefaults>('Textarea', {
|
|
42
|
+
variant: 'outlined',
|
|
43
|
+
color: 'primary',
|
|
44
|
+
size: 'md',
|
|
45
|
+
density: 'default',
|
|
46
|
+
rounded: true,
|
|
47
|
+
disabled: false
|
|
48
|
+
});
|
|
49
|
+
const p = $derived(resolve({ variant, color, size, density, rounded, disabled }));
|
|
50
|
+
const locale = useLocale();
|
|
51
|
+
// A form reset goes back to the text the field started with; a defaultValue of the app's own wins.
|
|
52
|
+
const initial = untrack(() => value ?? '');
|
|
53
|
+
|
|
54
|
+
const field = createField<string>({
|
|
55
|
+
value: () => value ?? '',
|
|
56
|
+
empty: (text) => text === '',
|
|
57
|
+
check: (text) =>
|
|
58
|
+
textConstraintMessage(
|
|
59
|
+
text,
|
|
60
|
+
{ required, minlength: rest.minlength, maxlength: rest.maxlength },
|
|
61
|
+
locale.t
|
|
62
|
+
),
|
|
63
|
+
rules: () => rules,
|
|
64
|
+
error: () => error,
|
|
65
|
+
validateOn: () => validateOn,
|
|
66
|
+
control: () => ref
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (DEV) $effect(() => warnUnnamed('Textarea', ref));
|
|
70
|
+
|
|
71
|
+
// Browsers without `field-sizing: content` grow the box by measuring the text; CSS caps it
|
|
72
|
+
// at maxRows, past which it scrolls.
|
|
73
|
+
$effect(() => {
|
|
74
|
+
const element = ref;
|
|
75
|
+
void value;
|
|
76
|
+
if (!autoGrow || !element || CSS.supports('field-sizing', 'content')) return;
|
|
77
|
+
element.style.blockSize = 'auto';
|
|
78
|
+
element.style.blockSize = `${element.scrollHeight}px`;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Leaving means focus went outside the field, not to a button in it.
|
|
82
|
+
function leave(event: FocusEvent) {
|
|
83
|
+
const root = event.currentTarget as HTMLElement;
|
|
84
|
+
if (!root.contains(event.relatedTarget as Node | null)) field.left();
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<Field
|
|
89
|
+
{...p}
|
|
90
|
+
{id}
|
|
91
|
+
{label}
|
|
92
|
+
{hint}
|
|
93
|
+
error={field.error}
|
|
94
|
+
{required}
|
|
95
|
+
{readonly}
|
|
96
|
+
{prepend}
|
|
97
|
+
{append}
|
|
98
|
+
class={['sv-textarea', autoGrow && 'sv-textarea--grow', className]}
|
|
99
|
+
{style}
|
|
100
|
+
oninput={field.changed}
|
|
101
|
+
onfocusout={leave}
|
|
102
|
+
>
|
|
103
|
+
{#snippet children(attributes)}
|
|
104
|
+
<textarea
|
|
105
|
+
bind:this={ref}
|
|
106
|
+
defaultValue={initial}
|
|
107
|
+
{...rest}
|
|
108
|
+
{...attributes}
|
|
109
|
+
aria-describedby={[describedBy, attributes['aria-describedby']].filter(Boolean).join(' ') ||
|
|
110
|
+
undefined}
|
|
111
|
+
{rows}
|
|
112
|
+
style:--sv-textarea-rows={rows}
|
|
113
|
+
style:--sv-textarea-max={maxRows}
|
|
114
|
+
bind:value></textarea>
|
|
115
|
+
{/snippet}
|
|
116
|
+
</Field>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Textarea } from './Textarea.svelte';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@layer sv.tokens, sv.base, sv.components, sv.utilities;
|
|
2
|
+
|
|
3
|
+
@layer sv.components {
|
|
4
|
+
/*
|
|
5
|
+
* Several lines start at the top of the box, at the height a one-line field gives its text, so
|
|
6
|
+
* a Textarea lines up with a TextField beside it. Lines are spaced for reading.
|
|
7
|
+
*/
|
|
8
|
+
.sv-textarea > .sv-field__box {
|
|
9
|
+
/* Half of what the box's height leaves around one line, inside its two borders. */
|
|
10
|
+
--sv-textarea-pad: calc(
|
|
11
|
+
(var(--sv-size-height) * var(--sv-density) - 2 * var(--sv-hairline) - 1lh) / 2
|
|
12
|
+
);
|
|
13
|
+
/* The control radius, never rounder than a card, even where controls are pills. */
|
|
14
|
+
--sv-field-radius: min(var(--sv-radius-md), var(--sv-radius-lg));
|
|
15
|
+
align-items: flex-start;
|
|
16
|
+
line-height: var(--sv-leading-normal);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.sv-textarea .sv-field__control {
|
|
20
|
+
padding-block: var(--sv-textarea-pad);
|
|
21
|
+
resize: vertical;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sv-textarea :where(.sv-field__prepend, .sv-field__append) {
|
|
25
|
+
padding-block: var(--sv-textarea-pad);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Growing: at least `rows` lines, at most `maxRows`, then it scrolls. */
|
|
29
|
+
.sv-textarea--grow .sv-field__control {
|
|
30
|
+
field-sizing: content;
|
|
31
|
+
min-block-size: calc(var(--sv-textarea-rows) * 1lh + 2 * var(--sv-textarea-pad));
|
|
32
|
+
max-block-size: calc(var(--sv-textarea-max) * 1lh + 2 * var(--sv-textarea-pad));
|
|
33
|
+
resize: none;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { HTMLTextareaAttributes } from 'svelte/elements';
|
|
2
|
+
import type { Rule, ValidateOn } from '../../core/form/types.js';
|
|
3
|
+
import type { ElementProps } from '../../core/props/element.js';
|
|
4
|
+
import type { FieldContentProps, FieldDefaults } from '../Field/types.js';
|
|
5
|
+
/** The Textarea props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
|
|
6
|
+
export type TextareaDefaults = FieldDefaults;
|
|
7
|
+
declare module '../../core/defaults/context.js' {
|
|
8
|
+
interface ComponentDefaults {
|
|
9
|
+
Textarea: TextareaDefaults;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
type TextareaOwnProps = Partial<TextareaDefaults> & FieldContentProps & {
|
|
13
|
+
/** The text. Bindable. */
|
|
14
|
+
value?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Visible lines, and the fewest it shows when it grows.
|
|
17
|
+
* @default 3
|
|
18
|
+
*/
|
|
19
|
+
rows?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Grows with its text instead of scrolling, up to `maxRows`.
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
autoGrow?: boolean;
|
|
25
|
+
/** With `autoGrow`, the most lines it grows to before it scrolls. Unlimited when not set. */
|
|
26
|
+
maxRows?: number;
|
|
27
|
+
/** Checks run in order after the HTML constraints. The first message is shown. */
|
|
28
|
+
rules?: readonly Rule<string>[];
|
|
29
|
+
/** When the message shows. Defaults to the form's setting, else `'blur'`. */
|
|
30
|
+
validateOn?: ValidateOn;
|
|
31
|
+
/**
|
|
32
|
+
* The field must not be empty. Adds an asterisk to the label.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
required?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The text can be read, selected and copied but not changed.
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
readonly?: boolean;
|
|
41
|
+
/** Inline style of the field's root element. */
|
|
42
|
+
style?: string | null;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Several lines of text with a label, a hint and validation. `class` and `style` apply to the
|
|
46
|
+
* field; `id`, `ref` and every other attribute (`name`, `placeholder`, `minlength`,
|
|
47
|
+
* `maxlength`, events) go to the `<textarea>`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* <Textarea
|
|
51
|
+
* label="Note to the payee"
|
|
52
|
+
* name="note"
|
|
53
|
+
* maxlength={280}
|
|
54
|
+
* autoGrow
|
|
55
|
+
* maxRows={8}
|
|
56
|
+
* bind:value={note}
|
|
57
|
+
* />
|
|
58
|
+
*/
|
|
59
|
+
export type TextareaProps = ElementProps<HTMLTextAreaElement, HTMLTextareaAttributes, TextareaOwnProps>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { DefaultsConfig } from './context.js';
|
|
4
|
+
|
|
5
|
+
export interface DefaultsProviderProps {
|
|
6
|
+
/**
|
|
7
|
+
* Defaults for this subtree: `global` reaches every component with the prop, and a key
|
|
8
|
+
* per component name targets one component. Merged over any outer provider, key by key.
|
|
9
|
+
*/
|
|
10
|
+
defaults: DefaultsConfig;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<script lang="ts">
|
|
16
|
+
import { getDefaultsContext, mergeDefaults, setDefaultsContext } from './context.js';
|
|
17
|
+
|
|
18
|
+
let { defaults, children }: DefaultsProviderProps = $props();
|
|
19
|
+
|
|
20
|
+
const parent = getDefaultsContext();
|
|
21
|
+
const merged = $derived(mergeDefaults(parent?.config, defaults));
|
|
22
|
+
|
|
23
|
+
setDefaultsContext({
|
|
24
|
+
get config() {
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
{@render children?.()}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { DefaultsConfig } from './context.js';
|
|
3
|
+
export interface DefaultsProviderProps {
|
|
4
|
+
/**
|
|
5
|
+
* Defaults for this subtree: `global` reaches every component with the prop, and a key
|
|
6
|
+
* per component name targets one component. Merged over any outer provider, key by key.
|
|
7
|
+
*/
|
|
8
|
+
defaults: DefaultsConfig;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
}
|
|
11
|
+
declare const DefaultsProvider: import("svelte").Component<DefaultsProviderProps, {}, "">;
|
|
12
|
+
type DefaultsProvider = ReturnType<typeof DefaultsProvider>;
|
|
13
|
+
export default DefaultsProvider;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SharedProps } from '../props/types.js';
|
|
2
|
+
/** Defaults that reach every component which declares the prop. */
|
|
3
|
+
export type GlobalDefaults = Pick<SharedProps, 'variant' | 'density' | 'size' | 'color' | 'rounded' | 'disabled'>;
|
|
4
|
+
/**
|
|
5
|
+
* Per-component defaults, keyed by component name. Sveltier's components register here,
|
|
6
|
+
* and so can yours, by declaration merging:
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* declare module '@sveltier/ui' {
|
|
10
|
+
* interface ComponentDefaults {
|
|
11
|
+
* MyCard: { elevated?: boolean };
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export interface ComponentDefaults {
|
|
16
|
+
}
|
|
17
|
+
export type DefaultsConfig = {
|
|
18
|
+
global?: GlobalDefaults;
|
|
19
|
+
} & {
|
|
20
|
+
[Name in keyof ComponentDefaults]?: Partial<ComponentDefaults[Name]>;
|
|
21
|
+
};
|
|
22
|
+
type Bag = Record<string, unknown>;
|
|
23
|
+
type Merged = Record<string, Bag | undefined>;
|
|
24
|
+
interface DefaultsContext {
|
|
25
|
+
/** The merged configuration of this provider and all its ancestors. */
|
|
26
|
+
readonly config: Merged;
|
|
27
|
+
}
|
|
28
|
+
export declare const getDefaultsContext: () => DefaultsContext | undefined;
|
|
29
|
+
export declare const setDefaultsContext: (context: DefaultsContext) => DefaultsContext;
|
|
30
|
+
/** Merges a provider's own config over its parent's, per component and per key. */
|
|
31
|
+
export declare function mergeDefaults(parent: Merged | undefined, own: DefaultsConfig): Merged;
|
|
32
|
+
/**
|
|
33
|
+
* Returns a resolver for a component's defaultable props. Call it during component
|
|
34
|
+
* initialisation, then resolve inside `$derived` so prop and provider changes are tracked:
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* let { size, variant, ...rest }: ButtonProps = $props();
|
|
38
|
+
* const resolve = useDefaults('Button', { size: 'md', variant: 'flat' });
|
|
39
|
+
* const p = $derived(resolve({ size, variant }));
|
|
40
|
+
*
|
|
41
|
+
* Order: the prop passed in, then the nearest provider's defaults for `name`, then its
|
|
42
|
+
* global defaults, then `builtins`. `undefined` and `null` mean "not set".
|
|
43
|
+
*/
|
|
44
|
+
export declare function useDefaults<T extends object>(name: string, builtins: T): (local: Partial<T>) => T;
|
|
45
|
+
export {};
|