svelora 3.0.0 → 3.0.2
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/dist/Accordion/Accordion.svelte +66 -97
- package/dist/Alert/Alert.svelte +39 -64
- package/dist/Alert/Alert.svelte.d.ts +1 -1
- package/dist/Avatar/Avatar.svelte +35 -75
- package/dist/AvatarGroup/AvatarGroup.svelte +38 -55
- package/dist/Badge/Badge.svelte +28 -50
- package/dist/Banner/Banner.svelte +46 -41
- package/dist/Banner/Banner.svelte.d.ts +1 -1
- package/dist/Breadcrumb/Breadcrumb.svelte +32 -26
- package/dist/Button/Button.svelte +70 -138
- package/dist/Calendar/Calendar.svelte +94 -157
- package/dist/Calendar/Calendar.svelte.d.ts +1 -1
- package/dist/Card/Card.svelte +18 -31
- package/dist/Carousel/Carousel.svelte +118 -173
- package/dist/Checkbox/Checkbox.svelte +52 -97
- package/dist/CheckboxGroup/CheckboxGroup.svelte +62 -107
- package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +1 -1
- package/dist/Chip/Chip.svelte +22 -34
- package/dist/CodeBlock/CodeBlock.svelte +42 -59
- package/dist/Collapsible/Collapsible.svelte +22 -38
- package/dist/Collapsible/Collapsible.svelte.d.ts +1 -1
- package/dist/Collapsible/CollapsibleTestWrapper.svelte +2 -5
- package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +1 -1
- package/dist/Command/Command.svelte +40 -77
- package/dist/Command/Command.svelte.d.ts +1 -1
- package/dist/Command/CommandTestWrapper.svelte +2 -10
- package/dist/Command/CommandTestWrapper.svelte.d.ts +1 -1
- package/dist/Container/Container.svelte +11 -14
- package/dist/ContextMenu/ContextMenu.svelte +51 -114
- package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
- package/dist/Drawer/Drawer.svelte +72 -110
- package/dist/Drawer/DrawerTriggerTestWrapper.svelte +1 -2
- package/dist/DropdownMenu/DropdownMenu.svelte +63 -124
- package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte +2 -5
- package/dist/Editor/Editor.svelte +441 -576
- package/dist/Editor/Editor.svelte.d.ts +1 -1
- package/dist/Editor/EditorUrlPrompt.svelte +40 -53
- package/dist/Editor/SlashPopup.svelte +12 -24
- package/dist/Empty/Empty.svelte +32 -63
- package/dist/FieldGroup/FieldGroup.svelte +23 -38
- package/dist/FileUpload/FileUpload.svelte +242 -320
- package/dist/FileUpload/FileUpload.svelte.d.ts +1 -1
- package/dist/Fonts/Fonts.svelte +15 -37
- package/dist/Form/Form.svelte +112 -170
- package/dist/FormField/FormField.svelte +102 -135
- package/dist/Icon/Icon.svelte +7 -32
- package/dist/Input/Input.svelte +71 -141
- package/dist/Input/Input.svelte.d.ts +2 -2
- package/dist/Kbd/Kbd.svelte +18 -34
- package/dist/Link/Link.svelte +129 -196
- package/dist/LocaleButton/LocaleButton.svelte +165 -0
- package/dist/LocaleButton/LocaleButton.svelte.d.ts +5 -0
- package/dist/LocaleButton/index.d.ts +2 -0
- package/dist/LocaleButton/index.js +1 -0
- package/dist/LocaleButton/locale-button.types.d.ts +182 -0
- package/dist/LocaleButton/locale-button.types.js +1 -0
- package/dist/LocaleButton/locale-button.variants.d.ts +61 -0
- package/dist/LocaleButton/locale-button.variants.js +34 -0
- package/dist/Modal/Modal.svelte +52 -106
- package/dist/Modal/ModalTriggerTestWrapper.svelte +1 -2
- package/dist/Pagination/Pagination.svelte +48 -92
- package/dist/Pagination/pagination.variants.d.ts +1 -1
- package/dist/PinInput/PinInput.svelte +57 -111
- package/dist/PinInput/PinInput.svelte.d.ts +1 -1
- package/dist/Popover/Popover.svelte +28 -61
- package/dist/Popover/Popover.svelte.d.ts +1 -1
- package/dist/Progress/Progress.svelte +75 -94
- package/dist/RadioGroup/RadioGroup.svelte +54 -99
- package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
- package/dist/Select/Select.svelte +112 -269
- package/dist/Select/Select.svelte.d.ts +1 -1
- package/dist/SelectMenu/SelectMenu.svelte +211 -409
- package/dist/SelectMenu/SelectMenu.svelte.d.ts +1 -1
- package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte +3 -6
- package/dist/Separator/Separator.svelte +29 -44
- package/dist/Skeleton/Skeleton.svelte +11 -23
- package/dist/Slideover/Slideover.svelte +52 -106
- package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +1 -2
- package/dist/Slider/Slider.svelte +48 -84
- package/dist/Slider/Slider.svelte.d.ts +1 -1
- package/dist/Stepper/Stepper.svelte +139 -132
- package/dist/Stepper/Stepper.svelte.d.ts +1 -1
- package/dist/Switch/Switch.svelte +62 -98
- package/dist/Table/Table.svelte +232 -283
- package/dist/Table/table.variants.d.ts +1 -1
- package/dist/Tabs/Tabs.svelte +96 -129
- package/dist/Tabs/Tabs.svelte.d.ts +1 -1
- package/dist/Textarea/Textarea.svelte +90 -173
- package/dist/Textarea/Textarea.svelte.d.ts +1 -1
- package/dist/ThemeModeButton/ThemeModeButton.svelte +16 -38
- package/dist/Timeline/Timeline.svelte +75 -54
- package/dist/Toast/Toaster.svelte +8 -25
- package/dist/Tooltip/Tooltip.svelte +34 -66
- package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/Tooltip/TooltipTestWrapper.svelte +2 -5
- package/dist/User/User.svelte +33 -49
- package/dist/docs/navigation.d.ts +1 -1
- package/dist/docs/navigation.js +8 -1
- package/dist/hooks/HookContextProbe.svelte +2 -4
- package/dist/hooks/HookContextProvider.svelte +8 -6
- package/dist/hooks/HookEmitProbe.svelte +8 -11
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.js +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/svelora-docs.data.json +4 -2
- package/dist/theme.css +1 -1
- package/package.json +16 -8
package/dist/Input/Input.svelte
CHANGED
|
@@ -1,146 +1,76 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { InputProps, InputValue } from './input.types.js'
|
|
3
|
-
|
|
4
|
-
export type Props<T extends InputValue = InputValue> = InputProps<T>
|
|
1
|
+
<script lang="ts" module>export {};
|
|
5
2
|
</script>
|
|
6
3
|
|
|
7
|
-
<script lang="ts" generics="T extends InputValue = InputValue">
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
| undefined
|
|
78
|
-
>('fieldGroup')
|
|
79
|
-
|
|
80
|
-
const hasError = $derived(
|
|
81
|
-
formFieldContext?.error !== undefined && formFieldContext?.error !== false
|
|
82
|
-
)
|
|
83
|
-
const resolvedSize = $derived(
|
|
84
|
-
size ?? formFieldContext?.size ?? fieldGroupContext?.size ?? config.defaultVariants.size
|
|
85
|
-
)
|
|
86
|
-
const resolvedColor = $derived(hasError ? 'error' : color)
|
|
87
|
-
const resolvedHighlight = $derived(highlight ?? hasError)
|
|
88
|
-
const fieldGroupClass = $derived(
|
|
89
|
-
fieldGroupContext
|
|
90
|
-
? fieldGroupVariantWithRoot.fieldGroup[fieldGroupContext.orientation ?? 'horizontal']
|
|
91
|
-
: undefined
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
const resolvedId = $derived(id ?? formFieldContext?.ariaId)
|
|
95
|
-
const resolvedName = $derived(name ?? formFieldContext?.name)
|
|
96
|
-
|
|
97
|
-
const loadingLeading = $derived(loading && !trailing)
|
|
98
|
-
const loadingTrailing = $derived(loading && trailing)
|
|
99
|
-
|
|
100
|
-
const isLeading = $derived((!!icon && !trailing) || !!leadingIcon || !!avatar || loadingLeading)
|
|
101
|
-
const isTrailing = $derived((!!icon && trailing) || !!trailingIcon || loadingTrailing)
|
|
102
|
-
|
|
103
|
-
const leadingIconName = $derived(leadingIcon || (icon && !trailing ? icon : undefined))
|
|
104
|
-
const trailingIconName = $derived(trailingIcon || (icon && trailing ? icon : undefined))
|
|
105
|
-
|
|
106
|
-
const ariaDescribedBy = $derived(
|
|
107
|
-
!formFieldContext
|
|
108
|
-
? undefined
|
|
109
|
-
: hasError
|
|
110
|
-
? `${formFieldContext.ariaId}-error`
|
|
111
|
-
: `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
const variantSlots = $derived(
|
|
115
|
-
inputVariants({
|
|
116
|
-
variant,
|
|
117
|
-
color: resolvedColor,
|
|
118
|
-
size: resolvedSize,
|
|
119
|
-
leading: isLeading,
|
|
120
|
-
trailing: isTrailing,
|
|
121
|
-
highlight: resolvedHighlight
|
|
122
|
-
})
|
|
123
|
-
)
|
|
124
|
-
const classes = $derived({
|
|
125
|
-
root: variantSlots.root({
|
|
126
|
-
class: [config.slots.root, fieldGroupClass?.root, className, ui?.root]
|
|
127
|
-
}),
|
|
128
|
-
base: variantSlots.base({
|
|
129
|
-
class: [config.slots.base, fieldGroupClass?.base, ui?.base]
|
|
130
|
-
}),
|
|
131
|
-
leading: variantSlots.leading({ class: [config.slots.leading, ui?.leading] }),
|
|
132
|
-
leadingIcon: variantSlots.leadingIcon({
|
|
133
|
-
class: [config.slots.leadingIcon, ui?.leadingIcon]
|
|
134
|
-
}),
|
|
135
|
-
leadingAvatar: variantSlots.leadingAvatar({
|
|
136
|
-
class: [config.slots.leadingAvatar, ui?.leadingAvatar]
|
|
137
|
-
}),
|
|
138
|
-
leadingAvatarSize: variantSlots.leadingAvatarSize() as AvatarSize,
|
|
139
|
-
trailing: variantSlots.trailing({ class: [config.slots.trailing, ui?.trailing] }),
|
|
140
|
-
trailingIcon: variantSlots.trailingIcon({
|
|
141
|
-
class: [config.slots.trailingIcon, ui?.trailingIcon]
|
|
142
|
-
})
|
|
143
|
-
})
|
|
4
|
+
<script lang="ts" generics="T extends InputValue = InputValue">import { getContext } from "svelte";
|
|
5
|
+
import Avatar from "../Avatar/Avatar.svelte";
|
|
6
|
+
import { getComponentConfig, iconsDefaults } from "../config.js";
|
|
7
|
+
import { fieldGroupVariantWithRoot } from "../FieldGroup/field-group.variants.js";
|
|
8
|
+
import { useFormField, useFormFieldEmit } from "../hooks/useFormField.svelte.js";
|
|
9
|
+
import Icon from "../Icon/Icon.svelte";
|
|
10
|
+
import { inputDefaults, inputVariants } from "./input.variants.js";
|
|
11
|
+
const config = getComponentConfig("input", inputDefaults);
|
|
12
|
+
const icons = getComponentConfig("icons", iconsDefaults);
|
|
13
|
+
let { ref = $bindable(null), value = $bindable(), ui, id, name, color = config.defaultVariants.color, variant = config.defaultVariants.variant, size, type = "text", highlight, loading = false, loadingIcon = icons.loading, disabled = false, icon, leadingIcon, trailingIcon, trailing = false, avatar, leadingSlot, trailingSlot, class: className, onblur, oninput, onchange, onfocus, ...restProps } = $props();
|
|
14
|
+
const formFieldContext = useFormField();
|
|
15
|
+
const emit = useFormFieldEmit();
|
|
16
|
+
function handleBlur(event) {
|
|
17
|
+
emit.onBlur();
|
|
18
|
+
onblur?.(event);
|
|
19
|
+
}
|
|
20
|
+
function handleInput(event) {
|
|
21
|
+
emit.onInput();
|
|
22
|
+
oninput?.(event);
|
|
23
|
+
}
|
|
24
|
+
function handleChange(event) {
|
|
25
|
+
emit.onChange();
|
|
26
|
+
onchange?.(event);
|
|
27
|
+
}
|
|
28
|
+
function handleFocus(event) {
|
|
29
|
+
emit.onFocus();
|
|
30
|
+
onfocus?.(event);
|
|
31
|
+
}
|
|
32
|
+
const fieldGroupContext = getContext("fieldGroup");
|
|
33
|
+
const hasError = $derived(formFieldContext?.error !== undefined && formFieldContext?.error !== false);
|
|
34
|
+
const resolvedSize = $derived(size ?? formFieldContext?.size ?? fieldGroupContext?.size ?? config.defaultVariants.size);
|
|
35
|
+
const resolvedColor = $derived(hasError ? "error" : color);
|
|
36
|
+
const resolvedHighlight = $derived(highlight ?? hasError);
|
|
37
|
+
const fieldGroupClass = $derived(fieldGroupContext ? fieldGroupVariantWithRoot.fieldGroup[fieldGroupContext.orientation ?? "horizontal"] : undefined);
|
|
38
|
+
const resolvedId = $derived(id ?? formFieldContext?.ariaId);
|
|
39
|
+
const resolvedName = $derived(name ?? formFieldContext?.name);
|
|
40
|
+
const loadingLeading = $derived(loading && !trailing);
|
|
41
|
+
const loadingTrailing = $derived(loading && trailing);
|
|
42
|
+
const isLeading = $derived(!!icon && !trailing || !!leadingIcon || !!avatar || loadingLeading);
|
|
43
|
+
const isTrailing = $derived(!!icon && trailing || !!trailingIcon || loadingTrailing);
|
|
44
|
+
const leadingIconName = $derived(leadingIcon || (icon && !trailing ? icon : undefined));
|
|
45
|
+
const trailingIconName = $derived(trailingIcon || (icon && trailing ? icon : undefined));
|
|
46
|
+
const ariaDescribedBy = $derived(!formFieldContext ? undefined : hasError ? `${formFieldContext.ariaId}-error` : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`);
|
|
47
|
+
const variantSlots = $derived(inputVariants({
|
|
48
|
+
variant,
|
|
49
|
+
color: resolvedColor,
|
|
50
|
+
size: resolvedSize,
|
|
51
|
+
leading: isLeading,
|
|
52
|
+
trailing: isTrailing,
|
|
53
|
+
highlight: resolvedHighlight
|
|
54
|
+
}));
|
|
55
|
+
const classes = $derived({
|
|
56
|
+
root: variantSlots.root({ class: [
|
|
57
|
+
config.slots.root,
|
|
58
|
+
fieldGroupClass?.root,
|
|
59
|
+
className,
|
|
60
|
+
ui?.root
|
|
61
|
+
] }),
|
|
62
|
+
base: variantSlots.base({ class: [
|
|
63
|
+
config.slots.base,
|
|
64
|
+
fieldGroupClass?.base,
|
|
65
|
+
ui?.base
|
|
66
|
+
] }),
|
|
67
|
+
leading: variantSlots.leading({ class: [config.slots.leading, ui?.leading] }),
|
|
68
|
+
leadingIcon: variantSlots.leadingIcon({ class: [config.slots.leadingIcon, ui?.leadingIcon] }),
|
|
69
|
+
leadingAvatar: variantSlots.leadingAvatar({ class: [config.slots.leadingAvatar, ui?.leadingAvatar] }),
|
|
70
|
+
leadingAvatarSize: variantSlots.leadingAvatarSize(),
|
|
71
|
+
trailing: variantSlots.trailing({ class: [config.slots.trailing, ui?.trailing] }),
|
|
72
|
+
trailingIcon: variantSlots.trailingIcon({ class: [config.slots.trailingIcon, ui?.trailingIcon] })
|
|
73
|
+
});
|
|
144
74
|
</script>
|
|
145
75
|
|
|
146
76
|
<div class={classes.root}>
|
|
@@ -3,7 +3,7 @@ export type Props<T extends InputValue = InputValue> = InputProps<T>;
|
|
|
3
3
|
declare function $$render<T extends InputValue = InputValue>(): {
|
|
4
4
|
props: Props<T>;
|
|
5
5
|
exports: {};
|
|
6
|
-
bindings: "
|
|
6
|
+
bindings: "ref" | "value";
|
|
7
7
|
slots: {};
|
|
8
8
|
events: {};
|
|
9
9
|
};
|
|
@@ -11,7 +11,7 @@ declare class __sveltets_Render<T extends InputValue = InputValue> {
|
|
|
11
11
|
props(): ReturnType<typeof $$render<T>>['props'];
|
|
12
12
|
events(): ReturnType<typeof $$render<T>>['events'];
|
|
13
13
|
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
14
|
-
bindings(): "
|
|
14
|
+
bindings(): "ref" | "value";
|
|
15
15
|
exports(): {};
|
|
16
16
|
}
|
|
17
17
|
interface $$IsomorphicComponent {
|
package/dist/Kbd/Kbd.svelte
CHANGED
|
@@ -1,39 +1,23 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { KbdProps } from './kbd.types.js'
|
|
3
|
-
import { resolveKey } from './useKbd.svelte.js'
|
|
4
|
-
|
|
5
|
-
export type Props = KbdProps
|
|
1
|
+
<script lang="ts" module>import { resolveKey } from "./useKbd.svelte.js";
|
|
6
2
|
</script>
|
|
7
3
|
|
|
8
|
-
<script lang="ts">
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
...restProps
|
|
26
|
-
}: Props = $props()
|
|
27
|
-
|
|
28
|
-
let mounted = $state(false)
|
|
29
|
-
onMount(() => (mounted = true))
|
|
30
|
-
|
|
31
|
-
const displayValue = $derived(resolveKey(value, mounted))
|
|
32
|
-
const kbdClass = $derived(
|
|
33
|
-
kbdVariants({ color, size, variant }).base({
|
|
34
|
-
class: [config.slots.base, className, ui?.base]
|
|
35
|
-
})
|
|
36
|
-
)
|
|
4
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
5
|
+
import { getComponentConfig } from "../config.js";
|
|
6
|
+
import { kbdDefaults, kbdVariants } from "./kbd.variants.js";
|
|
7
|
+
const config = getComponentConfig("kbd", kbdDefaults);
|
|
8
|
+
let { ref = $bindable(null), as = "kbd", value, color = config.defaultVariants.color, size = config.defaultVariants.size, variant = config.defaultVariants.variant, ui, class: className, children, ...restProps } = $props();
|
|
9
|
+
let mounted = $state(false);
|
|
10
|
+
onMount(() => mounted = true);
|
|
11
|
+
const displayValue = $derived(resolveKey(value, mounted));
|
|
12
|
+
const kbdClass = $derived(kbdVariants({
|
|
13
|
+
color,
|
|
14
|
+
size,
|
|
15
|
+
variant
|
|
16
|
+
}).base({ class: [
|
|
17
|
+
config.slots.base,
|
|
18
|
+
className,
|
|
19
|
+
ui?.base
|
|
20
|
+
] }));
|
|
37
21
|
</script>
|
|
38
22
|
|
|
39
23
|
<svelte:element this={as} bind:this={ref} class={kbdClass} {...restProps}>
|
package/dist/Link/Link.svelte
CHANGED
|
@@ -1,201 +1,134 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
isHistoryPatched = true
|
|
82
|
-
patchHistoryMethod('pushState')
|
|
83
|
-
patchHistoryMethod('replaceState')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function subscribeToLocation(callback: () => void) {
|
|
87
|
-
if (typeof window === 'undefined') {
|
|
88
|
-
return () => undefined
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
ensureNavigationEvents()
|
|
92
|
-
|
|
93
|
-
const handleLocationChange = () => callback()
|
|
94
|
-
|
|
95
|
-
handleLocationChange()
|
|
96
|
-
window.addEventListener('popstate', handleLocationChange)
|
|
97
|
-
window.addEventListener('hashchange', handleLocationChange)
|
|
98
|
-
window.addEventListener(navigationEvent, handleLocationChange)
|
|
99
|
-
|
|
100
|
-
return () => {
|
|
101
|
-
window.removeEventListener('popstate', handleLocationChange)
|
|
102
|
-
window.removeEventListener('hashchange', handleLocationChange)
|
|
103
|
-
window.removeEventListener(navigationEvent, handleLocationChange)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
1
|
+
<script lang="ts" module>const navigationEvent = "svelora:navigation";
|
|
2
|
+
let isHistoryPatched = false;
|
|
3
|
+
function parseUrl(url, baseUrl) {
|
|
4
|
+
try {
|
|
5
|
+
const parsed = new URL(url, baseUrl.origin);
|
|
6
|
+
return {
|
|
7
|
+
pathname: parsed.pathname,
|
|
8
|
+
query: parsed.searchParams,
|
|
9
|
+
hash: parsed.hash
|
|
10
|
+
};
|
|
11
|
+
} catch {
|
|
12
|
+
return {
|
|
13
|
+
pathname: url,
|
|
14
|
+
query: new URLSearchParams(),
|
|
15
|
+
hash: ""
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function isQueryMatch(linkQuery, currentQuery, mode) {
|
|
20
|
+
if (mode === false) return true;
|
|
21
|
+
if (mode === "partial") {
|
|
22
|
+
for (const [key, value] of linkQuery) {
|
|
23
|
+
if (!currentQuery.getAll(key).includes(value)) return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
// Exact: check size first (O(1) bail-out), then compare sorted strings
|
|
28
|
+
if (linkQuery.size !== currentQuery.size) return false;
|
|
29
|
+
const sorted = (p) => new URLSearchParams([...p].sort()).toString();
|
|
30
|
+
return sorted(linkQuery) === sorted(currentQuery);
|
|
31
|
+
}
|
|
32
|
+
function isPathnameMatch(linkPath, currentPath, exactMatch) {
|
|
33
|
+
if (exactMatch) return linkPath === currentPath;
|
|
34
|
+
const link = linkPath.replace(/\/$/, "") || "/";
|
|
35
|
+
const current = currentPath.replace(/\/$/, "") || "/";
|
|
36
|
+
return link === "/" ? current === "/" : current === link || current.startsWith(`${link}/`);
|
|
37
|
+
}
|
|
38
|
+
function dispatchNavigationEvent() {
|
|
39
|
+
if (typeof window === "undefined") {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
window.dispatchEvent(new Event(navigationEvent));
|
|
43
|
+
}
|
|
44
|
+
function patchHistoryMethod(method) {
|
|
45
|
+
const historyMethod = window.history[method].bind(window.history);
|
|
46
|
+
Object.defineProperty(window.history, method, {
|
|
47
|
+
configurable: true,
|
|
48
|
+
value: (...args) => {
|
|
49
|
+
historyMethod(...args);
|
|
50
|
+
dispatchNavigationEvent();
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function ensureNavigationEvents() {
|
|
55
|
+
if (typeof window === "undefined" || isHistoryPatched) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
isHistoryPatched = true;
|
|
59
|
+
patchHistoryMethod("pushState");
|
|
60
|
+
patchHistoryMethod("replaceState");
|
|
61
|
+
}
|
|
62
|
+
function subscribeToLocation(callback) {
|
|
63
|
+
if (typeof window === "undefined") {
|
|
64
|
+
return () => undefined;
|
|
65
|
+
}
|
|
66
|
+
ensureNavigationEvents();
|
|
67
|
+
const handleLocationChange = () => callback();
|
|
68
|
+
handleLocationChange();
|
|
69
|
+
window.addEventListener("popstate", handleLocationChange);
|
|
70
|
+
window.addEventListener("hashchange", handleLocationChange);
|
|
71
|
+
window.addEventListener(navigationEvent, handleLocationChange);
|
|
72
|
+
return () => {
|
|
73
|
+
window.removeEventListener("popstate", handleLocationChange);
|
|
74
|
+
window.removeEventListener("hashchange", handleLocationChange);
|
|
75
|
+
window.removeEventListener(navigationEvent, handleLocationChange);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export {};
|
|
106
79
|
</script>
|
|
107
80
|
|
|
108
|
-
<script lang="ts">
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const resolvedRel = $derived(
|
|
160
|
-
isLink
|
|
161
|
-
? (rel ??
|
|
162
|
-
(isExternal || resolvedTarget === '_blank' ? 'noopener noreferrer' : undefined))
|
|
163
|
-
: undefined
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
const isActive = $derived.by(() => {
|
|
167
|
-
if (active !== undefined) return active
|
|
168
|
-
if (!isLink || !currentUrl || isExternal) return false
|
|
169
|
-
|
|
170
|
-
const link = parseUrl(href!, currentUrl)
|
|
171
|
-
|
|
172
|
-
if (exactHash && link.hash !== currentUrl.hash) return false
|
|
173
|
-
if (!isQueryMatch(link.query, currentUrl.searchParams, exactQuery)) return false
|
|
174
|
-
|
|
175
|
-
return isPathnameMatch(link.pathname, currentUrl.pathname, exact)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
const baseClass = $derived.by(() => {
|
|
179
|
-
const stateClass = isActive ? activeClass : inactiveClass
|
|
180
|
-
if (raw) return twMerge(stateClass, className)
|
|
181
|
-
|
|
182
|
-
const slots = linkVariants({ active: isActive, disabled, raw })
|
|
183
|
-
return slots.base({ class: [config.slots.base, stateClass, className, ui?.base] })
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
const ariaCurrent = $derived(isActive && exact ? ('page' as const) : undefined)
|
|
187
|
-
|
|
188
|
-
function handleClick(e: MouseEvent) {
|
|
189
|
-
if (disabled) {
|
|
190
|
-
e.preventDefault()
|
|
191
|
-
e.stopPropagation()
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (typeof onclick === 'function') {
|
|
196
|
-
;(onclick as (e: MouseEvent) => void)(e)
|
|
197
|
-
}
|
|
198
|
-
}
|
|
81
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
82
|
+
import { twMerge } from "tailwind-merge";
|
|
83
|
+
import { getComponentConfig } from "../config.js";
|
|
84
|
+
import { linkDefaults, linkVariants } from "./link.variants.js";
|
|
85
|
+
const config = getComponentConfig("link", linkDefaults);
|
|
86
|
+
let { ref = $bindable(null), href, type, active, exact = false, exactQuery = false, exactHash = false, activeClass, inactiveClass, disabled = false, raw = false, external, children, class: className, ui, target, rel, onclick, ...restProps } = $props();
|
|
87
|
+
const isLink = $derived(!!href);
|
|
88
|
+
let currentUrl = $state(undefined);
|
|
89
|
+
onMount(() => {
|
|
90
|
+
return subscribeToLocation(() => {
|
|
91
|
+
currentUrl = new URL(window.location.href);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
const isExternal = $derived(isLink && (external ?? (href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//"))));
|
|
95
|
+
const resolvedTarget = $derived(isLink ? target ?? (isExternal ? "_blank" : undefined) : undefined);
|
|
96
|
+
const resolvedRel = $derived(isLink ? rel ?? (isExternal || resolvedTarget === "_blank" ? "noopener noreferrer" : undefined) : undefined);
|
|
97
|
+
const isActive = $derived.by(() => {
|
|
98
|
+
if (active !== undefined) return active;
|
|
99
|
+
if (!isLink || !currentUrl || isExternal) return false;
|
|
100
|
+
const link = parseUrl(href, currentUrl);
|
|
101
|
+
if (exactHash && link.hash !== currentUrl.hash) return false;
|
|
102
|
+
if (!isQueryMatch(link.query, currentUrl.searchParams, exactQuery)) return false;
|
|
103
|
+
return isPathnameMatch(link.pathname, currentUrl.pathname, exact);
|
|
104
|
+
});
|
|
105
|
+
const baseClass = $derived.by(() => {
|
|
106
|
+
const stateClass = isActive ? activeClass : inactiveClass;
|
|
107
|
+
if (raw) return twMerge(stateClass, className);
|
|
108
|
+
const slots = linkVariants({
|
|
109
|
+
active: isActive,
|
|
110
|
+
disabled,
|
|
111
|
+
raw
|
|
112
|
+
});
|
|
113
|
+
return slots.base({ class: [
|
|
114
|
+
config.slots.base,
|
|
115
|
+
stateClass,
|
|
116
|
+
className,
|
|
117
|
+
ui?.base
|
|
118
|
+
] });
|
|
119
|
+
});
|
|
120
|
+
const ariaCurrent = $derived(isActive && exact ? "page" : undefined);
|
|
121
|
+
function handleClick(e) {
|
|
122
|
+
if (disabled) {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
e.stopPropagation();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (typeof onclick === "function") {
|
|
128
|
+
;
|
|
129
|
+
onclick(e);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
199
132
|
</script>
|
|
200
133
|
|
|
201
134
|
{#if isLink}
|