svelora 3.0.10 → 3.0.12
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/Icon/Icon.svelte +29 -11
- package/dist/Icon/Icon.svelte.d.ts +0 -1
- package/dist/LocaleButton/LocaleButton.svelte +77 -67
- package/dist/LocaleButton/locale-button.types.d.ts +17 -0
- package/dist/LocaleButton/locale-button.variants.d.ts +72 -3
- package/dist/LocaleButton/locale-button.variants.js +24 -1
- package/dist/NavigationMenu/NavigationMenu.svelte +40 -8
- package/dist/NavigationMenu/navigation-menu.types.d.ts +17 -0
- package/dist/NavigationMenu/navigation-menu.variants.d.ts +15 -0
- package/dist/NavigationMenu/navigation-menu.variants.js +17 -1
- package/dist/Table/TableBulkActionBar.svelte +38 -0
- package/dist/Table/TableBulkActionBar.svelte.d.ts +5 -0
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.js +1 -0
- package/dist/Table/table-bulk-action-bar.types.d.ts +31 -0
- package/dist/Table/table-bulk-action-bar.types.js +1 -0
- package/dist/Table/table-bulk-action-bar.variants.d.ts +52 -0
- package/dist/Table/table-bulk-action-bar.variants.js +10 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/docs/navigation.d.ts +1 -0
- package/dist/docs/navigation.js +13 -5
- package/dist/mcp/svelora-docs.data.json +92 -92
- package/package.json +1 -1
package/dist/Icon/Icon.svelte
CHANGED
|
@@ -1,21 +1,39 @@
|
|
|
1
1
|
<script lang="ts" module>export {};
|
|
2
2
|
</script>
|
|
3
3
|
|
|
4
|
-
<script lang="ts">import
|
|
4
|
+
<script lang="ts">import Iconify from "@iconify/svelte";
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
|
+
import { getComponentConfig, iconsDefaults } from "../config.js";
|
|
7
|
+
const config = getComponentConfig("icons", iconsDefaults);
|
|
6
8
|
let { name, size = 24, color, flipH = false, flipV = false, rotate = 0, class: className, ...restProps } = $props();
|
|
7
9
|
const flip = $derived(flipH && flipV ? "horizontal,vertical" : flipH ? "horizontal" : flipV ? "vertical" : undefined);
|
|
8
10
|
const rotateValue = $derived(rotate ? rotate / 90 : undefined);
|
|
9
11
|
const iconClass = $derived(twMerge("shrink-0", className));
|
|
12
|
+
const provider = $derived(config.provider ?? "iconify");
|
|
13
|
+
// Automatically map "lucide:bell" to "icon-[lucide--bell]" if using tailwind provider
|
|
14
|
+
const tailwindClass = $derived(name.startsWith("icon-") || name.startsWith("i-") ? name : `icon-[${name.replace(":", "--")}]`);
|
|
15
|
+
// Resolve size value for inline styles
|
|
16
|
+
const sizeStyle = $derived(typeof size === "number" ? `${size}px` : size);
|
|
10
17
|
</script>
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
{#if provider === 'tailwind'}
|
|
20
|
+
<span
|
|
21
|
+
class={twMerge(tailwindClass, iconClass)}
|
|
22
|
+
style:width={sizeStyle}
|
|
23
|
+
style:height={sizeStyle}
|
|
24
|
+
style:color={color}
|
|
25
|
+
style:transform={rotateValue ? `rotate(${rotateValue * 90}deg)` : undefined}
|
|
26
|
+
{...(restProps as any)}
|
|
27
|
+
></span>
|
|
28
|
+
{:else}
|
|
29
|
+
<Iconify
|
|
30
|
+
icon={name}
|
|
31
|
+
width={size}
|
|
32
|
+
height={size}
|
|
33
|
+
{color}
|
|
34
|
+
{flip}
|
|
35
|
+
rotate={rotateValue}
|
|
36
|
+
class={iconClass}
|
|
37
|
+
{...restProps}
|
|
38
|
+
/>
|
|
39
|
+
{/if}
|
|
@@ -9,28 +9,30 @@ import Link from "../Link/Link.svelte";
|
|
|
9
9
|
import { localeButtonDefaults, localeButtonVariants } from "./locale-button.variants.js";
|
|
10
10
|
const config = getComponentConfig("localeButton", localeButtonDefaults);
|
|
11
11
|
const icons = getComponentConfig("icons", iconsDefaults);
|
|
12
|
-
let { locales = [], locale, variant = config.defaultVariants.variant ?? "outline", color = config.defaultVariants.color ?? "surface", size = config.defaultVariants.size ?? "md", loading = false, disabled = false, block = false, square = false, placeholder = "Select language", ariaLabel = "Change language", menuLabel = "Language", icon = "lucide:languages", chevronIcon = icons.chevronDown, showIcon = true, showChevron = true, showCode = true, showIndicator = true, disableCurrentLocale = true, closeOnSelect = true, getLocaleHref, onLocaleChange, open = $bindable(false), onOpenChange, side = "bottom", sideOffset = 4, align = "start", alignOffset = 0, avoidCollisions = true, collisionBoundary, collisionPadding = 8, sticky = "partial", hideWhenDetached = false, onEscapeKeydown, onInteractOutside, onCloseAutoFocus, forceMount, loop = true, portal = true, arrow = false, ui, children: triggerContent, class: className, ...restProps } = $props();
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
12
|
+
let { locales = [], locale, variant = config.defaultVariants.variant ?? "outline", color = config.defaultVariants.color ?? "surface", size = config.defaultVariants.size ?? "md", loading = false, disabled = false, block = false, square = false, placeholder = "Select language", ariaLabel = "Change language", menuLabel = "Language", icon = "lucide:languages", chevronIcon = icons.chevronDown, showIcon = true, showChevron = true, showCode = true, showIndicator = true, disableCurrentLocale = true, closeOnSelect = true, getLocaleHref, onLocaleChange, open = $bindable(false), onOpenChange, side = "bottom", sideOffset = 4, align = "start", alignOffset = 0, avoidCollisions = true, collisionBoundary, collisionPadding = 8, sticky = "partial", hideWhenDetached = false, onEscapeKeydown, onInteractOutside, onCloseAutoFocus, forceMount, loop = true, portal = true, arrow = false, ui, children: triggerContent, item: itemSnippet, menu: menuSnippet, class: className, ...restProps } = $props();
|
|
13
|
+
const classes = $derived.by(() => {
|
|
14
|
+
const slots = localeButtonVariants({ size });
|
|
15
|
+
return {
|
|
16
|
+
base: slots.base({ class: [
|
|
17
|
+
config.slots.base,
|
|
18
|
+
className,
|
|
19
|
+
ui?.base
|
|
20
|
+
] }),
|
|
21
|
+
triggerLabel: slots.triggerLabel({ class: [config.slots.triggerLabel, ui?.triggerLabel] }),
|
|
22
|
+
triggerIcon: slots.triggerIcon({ class: [config.slots.triggerIcon, ui?.triggerIcon] }),
|
|
23
|
+
triggerChevron: slots.triggerChevron({ class: [config.slots.triggerChevron, ui?.triggerChevron] }),
|
|
24
|
+
menu: slots.menu({ class: [config.slots.menu, ui?.menu] }),
|
|
25
|
+
menuLabel: slots.menuLabel({ class: [config.slots.menuLabel, ui?.menuLabel] }),
|
|
26
|
+
item: slots.item({ class: [config.slots.item, ui?.item] }),
|
|
27
|
+
itemIdle: slots.itemIdle({ class: [config.slots.itemIdle, ui?.itemIdle] }),
|
|
28
|
+
itemCurrent: slots.itemCurrent({ class: [config.slots.itemCurrent, ui?.itemCurrent] }),
|
|
29
|
+
itemLeading: slots.itemLeading({ class: [config.slots.itemLeading, ui?.itemLeading] }),
|
|
30
|
+
itemText: slots.itemText({ class: [config.slots.itemText, ui?.itemText] }),
|
|
31
|
+
itemLabel: slots.itemLabel({ class: [config.slots.itemLabel, ui?.itemLabel] }),
|
|
32
|
+
itemDescription: slots.itemDescription({ class: [config.slots.itemDescription, ui?.itemDescription] }),
|
|
33
|
+
itemCode: slots.itemCode({ class: [config.slots.itemCode, ui?.itemCode] }),
|
|
34
|
+
itemIndicator: slots.itemIndicator({ class: [config.slots.itemIndicator, ui?.itemIndicator] })
|
|
35
|
+
};
|
|
34
36
|
});
|
|
35
37
|
const currentLocale = $derived(locales.find((item) => item.code === locale) ?? locales[0]);
|
|
36
38
|
const triggerLabel = $derived(currentLocale?.shortLabel ?? currentLocale?.label ?? placeholder);
|
|
@@ -112,54 +114,62 @@ async function handleItemClick(event, item, close) {
|
|
|
112
114
|
{/snippet}
|
|
113
115
|
|
|
114
116
|
{#snippet content({ close })}
|
|
115
|
-
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
{
|
|
117
|
+
{#if menuSnippet}
|
|
118
|
+
{@render menuSnippet({ close })}
|
|
119
|
+
{:else}
|
|
120
|
+
<div class={classes.menu}>
|
|
121
|
+
{#if menuLabel}
|
|
122
|
+
<p class={classes.menuLabel}>{menuLabel}</p>
|
|
123
|
+
{/if}
|
|
119
124
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
{#each locales as item (item.code)}
|
|
126
|
+
{@const current = isCurrentLocale(item)}
|
|
127
|
+
{@const href = getResolvedHref(item)}
|
|
128
|
+
{@const itemDisabled = isItemDisabled(item)}
|
|
124
129
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<span class={classes.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
130
|
+
{#if itemSnippet}
|
|
131
|
+
{@render itemSnippet({ item, current, disabled: itemDisabled, close })}
|
|
132
|
+
{:else}
|
|
133
|
+
<Link
|
|
134
|
+
href={href}
|
|
135
|
+
hreflang={item.hreflang ?? item.code}
|
|
136
|
+
raw
|
|
137
|
+
role="menuitemradio"
|
|
138
|
+
aria-checked={current}
|
|
139
|
+
disabled={itemDisabled}
|
|
140
|
+
class={[
|
|
141
|
+
classes.item,
|
|
142
|
+
current ? classes.itemCurrent : classes.itemIdle,
|
|
143
|
+
item.class
|
|
144
|
+
]}
|
|
145
|
+
onclick={(event) => handleItemClick(event, item, close)}
|
|
146
|
+
>
|
|
147
|
+
<span class={classes.itemLeading}>
|
|
148
|
+
{#if item.icon}
|
|
149
|
+
<Icon name={item.icon} />
|
|
150
|
+
{/if}
|
|
151
|
+
<span class={classes.itemText}>
|
|
152
|
+
<span class={classes.itemLabel}>{item.label}</span>
|
|
153
|
+
{#if item.description}
|
|
154
|
+
<span class={classes.itemDescription}>{item.description}</span>
|
|
155
|
+
{/if}
|
|
156
|
+
</span>
|
|
157
|
+
</span>
|
|
150
158
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
<span class="flex items-center gap-2">
|
|
160
|
+
{#if showCode}
|
|
161
|
+
<span class={classes.itemCode}>{item.shortLabel ?? item.code}</span>
|
|
162
|
+
{/if}
|
|
163
|
+
{#if showIndicator && current}
|
|
164
|
+
<span class={classes.itemIndicator}>
|
|
165
|
+
<Icon name={icons.check} />
|
|
166
|
+
</span>
|
|
167
|
+
{/if}
|
|
158
168
|
</span>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
</Link>
|
|
170
|
+
{/if}
|
|
171
|
+
{/each}
|
|
172
|
+
</div>
|
|
173
|
+
{/if}
|
|
164
174
|
{/snippet}
|
|
165
175
|
</DropdownMenu>
|
|
@@ -160,6 +160,23 @@ export type LocaleButtonProps = Omit<HTMLAttributes<HTMLElement>, 'children' | '
|
|
|
160
160
|
open: boolean;
|
|
161
161
|
currentLocale: LocaleButtonLocale | undefined;
|
|
162
162
|
}]>;
|
|
163
|
+
/**
|
|
164
|
+
* Render custom content for each locale item in the menu.
|
|
165
|
+
*/
|
|
166
|
+
item?: Snippet<[
|
|
167
|
+
{
|
|
168
|
+
item: LocaleButtonLocale;
|
|
169
|
+
current: boolean;
|
|
170
|
+
disabled: boolean;
|
|
171
|
+
close: () => void;
|
|
172
|
+
}
|
|
173
|
+
]>;
|
|
174
|
+
/**
|
|
175
|
+
* Render a custom menu layout entirely.
|
|
176
|
+
*/
|
|
177
|
+
menu?: Snippet<[{
|
|
178
|
+
close: () => void;
|
|
179
|
+
}]>;
|
|
163
180
|
/**
|
|
164
181
|
* Whether to render the menu in a portal.
|
|
165
182
|
* @default true
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import { type VariantProps } from 'tailwind-variants';
|
|
2
2
|
import type { ButtonVariantProps } from '../Button/button.variants.js';
|
|
3
|
-
export declare const localeButtonVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
export declare const localeButtonVariants: import("tailwind-variants").TVReturnType<{
|
|
4
|
+
size: {
|
|
5
|
+
xs: {
|
|
6
|
+
triggerIcon: string;
|
|
7
|
+
triggerChevron: string;
|
|
8
|
+
};
|
|
9
|
+
sm: {
|
|
10
|
+
triggerIcon: string;
|
|
11
|
+
triggerChevron: string;
|
|
12
|
+
};
|
|
13
|
+
md: {
|
|
14
|
+
triggerIcon: string;
|
|
15
|
+
triggerChevron: string;
|
|
16
|
+
};
|
|
17
|
+
lg: {
|
|
18
|
+
triggerIcon: string;
|
|
19
|
+
triggerChevron: string;
|
|
20
|
+
};
|
|
21
|
+
xl: {
|
|
22
|
+
triggerIcon: string;
|
|
23
|
+
triggerChevron: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}, {
|
|
4
27
|
base: string;
|
|
5
28
|
triggerLabel: string;
|
|
6
29
|
triggerIcon: string;
|
|
@@ -16,7 +39,30 @@ export declare const localeButtonVariants: import("tailwind-variants").TVReturnT
|
|
|
16
39
|
itemDescription: string;
|
|
17
40
|
itemCode: string;
|
|
18
41
|
itemIndicator: string;
|
|
19
|
-
}, undefined, {
|
|
42
|
+
}, undefined, {
|
|
43
|
+
size: {
|
|
44
|
+
xs: {
|
|
45
|
+
triggerIcon: string;
|
|
46
|
+
triggerChevron: string;
|
|
47
|
+
};
|
|
48
|
+
sm: {
|
|
49
|
+
triggerIcon: string;
|
|
50
|
+
triggerChevron: string;
|
|
51
|
+
};
|
|
52
|
+
md: {
|
|
53
|
+
triggerIcon: string;
|
|
54
|
+
triggerChevron: string;
|
|
55
|
+
};
|
|
56
|
+
lg: {
|
|
57
|
+
triggerIcon: string;
|
|
58
|
+
triggerChevron: string;
|
|
59
|
+
};
|
|
60
|
+
xl: {
|
|
61
|
+
triggerIcon: string;
|
|
62
|
+
triggerChevron: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
}, {
|
|
20
66
|
base: string;
|
|
21
67
|
triggerLabel: string;
|
|
22
68
|
triggerIcon: string;
|
|
@@ -32,7 +78,30 @@ export declare const localeButtonVariants: import("tailwind-variants").TVReturnT
|
|
|
32
78
|
itemDescription: string;
|
|
33
79
|
itemCode: string;
|
|
34
80
|
itemIndicator: string;
|
|
35
|
-
}, import("tailwind-variants").TVReturnType<{
|
|
81
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
82
|
+
size: {
|
|
83
|
+
xs: {
|
|
84
|
+
triggerIcon: string;
|
|
85
|
+
triggerChevron: string;
|
|
86
|
+
};
|
|
87
|
+
sm: {
|
|
88
|
+
triggerIcon: string;
|
|
89
|
+
triggerChevron: string;
|
|
90
|
+
};
|
|
91
|
+
md: {
|
|
92
|
+
triggerIcon: string;
|
|
93
|
+
triggerChevron: string;
|
|
94
|
+
};
|
|
95
|
+
lg: {
|
|
96
|
+
triggerIcon: string;
|
|
97
|
+
triggerChevron: string;
|
|
98
|
+
};
|
|
99
|
+
xl: {
|
|
100
|
+
triggerIcon: string;
|
|
101
|
+
triggerChevron: string;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}, {
|
|
36
105
|
base: string;
|
|
37
106
|
triggerLabel: string;
|
|
38
107
|
triggerIcon: string;
|
|
@@ -20,7 +20,30 @@ export const localeButtonVariants = tv({
|
|
|
20
20
|
itemCode: 'shrink-0 rounded-md bg-surface-container px-1.5 py-0.5 text-[11px] font-medium text-on-surface-variant uppercase',
|
|
21
21
|
itemIndicator: 'shrink-0 text-primary'
|
|
22
22
|
},
|
|
23
|
-
variants: {
|
|
23
|
+
variants: {
|
|
24
|
+
size: {
|
|
25
|
+
xs: {
|
|
26
|
+
triggerIcon: 'size-3.5',
|
|
27
|
+
triggerChevron: 'size-3.5'
|
|
28
|
+
},
|
|
29
|
+
sm: {
|
|
30
|
+
triggerIcon: 'size-4',
|
|
31
|
+
triggerChevron: 'size-4'
|
|
32
|
+
},
|
|
33
|
+
md: {
|
|
34
|
+
triggerIcon: 'size-5',
|
|
35
|
+
triggerChevron: 'size-5'
|
|
36
|
+
},
|
|
37
|
+
lg: {
|
|
38
|
+
triggerIcon: 'size-5',
|
|
39
|
+
triggerChevron: 'size-5'
|
|
40
|
+
},
|
|
41
|
+
xl: {
|
|
42
|
+
triggerIcon: 'size-6',
|
|
43
|
+
triggerChevron: 'size-6'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
24
47
|
defaultVariants: {}
|
|
25
48
|
});
|
|
26
49
|
export const localeButtonDefaults = {
|
|
@@ -6,7 +6,7 @@ import Kbd from "../Kbd/Kbd.svelte";
|
|
|
6
6
|
import { DropdownMenu } from "../DropdownMenu/index.js";
|
|
7
7
|
import { Tooltip } from "../Tooltip/index.js";
|
|
8
8
|
import { navigationMenuVariants } from "./navigation-menu.variants.js";
|
|
9
|
-
let { items = [], variant = "default", orientation = "horizontal", accordion = false, class: className, ui, children } = $props();
|
|
9
|
+
let { items = [], variant = "default", orientation = "horizontal", accordion = false, tree = false, class: className, ui, children } = $props();
|
|
10
10
|
const sidebarCollapsedFn = getContext("sidebar-collapsed");
|
|
11
11
|
let isCollapsed = $derived(sidebarCollapsedFn ? sidebarCollapsedFn() : false);
|
|
12
12
|
const sidebarPositionFn = getContext("sidebar-position");
|
|
@@ -14,7 +14,8 @@ let sidebarPosition = $derived(sidebarPositionFn ? sidebarPositionFn() : "left")
|
|
|
14
14
|
let styles = $derived(navigationMenuVariants({
|
|
15
15
|
variant,
|
|
16
16
|
orientation,
|
|
17
|
-
collapsed: isCollapsed
|
|
17
|
+
collapsed: isCollapsed,
|
|
18
|
+
tree
|
|
18
19
|
}));
|
|
19
20
|
let normalizedItems = $derived.by(() => {
|
|
20
21
|
if (!items || items.length === 0) return [];
|
|
@@ -52,22 +53,53 @@ function isGroupOpen(item) {
|
|
|
52
53
|
if (!item.label) return false;
|
|
53
54
|
return openGroups.includes(item.label);
|
|
54
55
|
}
|
|
56
|
+
import { LINK_LOCATION_CONTEXT_KEY } from "../Link/location-context.js";
|
|
57
|
+
const linkLocation = getContext(LINK_LOCATION_CONTEXT_KEY);
|
|
55
58
|
// --- Auto Active State ---
|
|
56
|
-
let
|
|
59
|
+
let windowPath = $state("");
|
|
57
60
|
$effect(() => {
|
|
58
|
-
if (typeof window !== "undefined") {
|
|
59
|
-
|
|
61
|
+
if (!linkLocation && typeof window !== "undefined") {
|
|
62
|
+
windowPath = window.location.pathname;
|
|
60
63
|
const onPopState = () => {
|
|
61
|
-
|
|
64
|
+
windowPath = window.location.pathname;
|
|
62
65
|
};
|
|
63
66
|
window.addEventListener("popstate", onPopState);
|
|
64
67
|
return () => window.removeEventListener("popstate", onPopState);
|
|
65
68
|
}
|
|
66
69
|
});
|
|
70
|
+
const currentPath = $derived(linkLocation ? linkLocation.currentUrl().pathname : windowPath);
|
|
71
|
+
const bestMatchHref = $derived.by(() => {
|
|
72
|
+
let best = "";
|
|
73
|
+
const search = (menuItems) => {
|
|
74
|
+
for (const item of menuItems) {
|
|
75
|
+
const target = item.matchPattern || item.href;
|
|
76
|
+
if (target) {
|
|
77
|
+
const isExact = item.exact !== false;
|
|
78
|
+
if (isExact && currentPath === target) {
|
|
79
|
+
return target;
|
|
80
|
+
} else if (!isExact && (currentPath === target || currentPath.startsWith(target + "/"))) {
|
|
81
|
+
if (target.length > best.length) {
|
|
82
|
+
best = target;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const children = item.items || item.children || [];
|
|
87
|
+
if (children.length > 0) {
|
|
88
|
+
const childBest = search(children);
|
|
89
|
+
if (childBest && childBest.length > best.length) best = childBest;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return best;
|
|
93
|
+
};
|
|
94
|
+
return search(normalizedItems.flat());
|
|
95
|
+
});
|
|
67
96
|
function isActive(item) {
|
|
68
97
|
if (item.active) return true;
|
|
69
|
-
|
|
70
|
-
|
|
98
|
+
const target = item.matchPattern || item.href;
|
|
99
|
+
if (target && target === bestMatchHref) return true;
|
|
100
|
+
const children = item.items || item.children || [];
|
|
101
|
+
if (children.some((child) => isActive(child))) {
|
|
102
|
+
return true;
|
|
71
103
|
}
|
|
72
104
|
return false;
|
|
73
105
|
}
|
|
@@ -16,6 +16,18 @@ export type NavigationMenuItemType = {
|
|
|
16
16
|
* Optional icon to display before the label.
|
|
17
17
|
*/
|
|
18
18
|
icon?: string;
|
|
19
|
+
/**
|
|
20
|
+
* If true, the item will only be active if the current path matches the item's href exactly.
|
|
21
|
+
* If false, it will be active if the current path starts with the item's href.
|
|
22
|
+
* Defaults to true.
|
|
23
|
+
*/
|
|
24
|
+
exact?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Optional pattern to use for active state matching instead of the href.
|
|
27
|
+
* Useful when href points to a subpage (e.g. /docs/components/button)
|
|
28
|
+
* but you want it to match any page in the section (e.g. /docs/components).
|
|
29
|
+
*/
|
|
30
|
+
matchPattern?: string;
|
|
19
31
|
/**
|
|
20
32
|
* Optional badge text/number to display after the label.
|
|
21
33
|
*/
|
|
@@ -88,6 +100,11 @@ export type NavigationMenuProps = {
|
|
|
88
100
|
* @default false
|
|
89
101
|
*/
|
|
90
102
|
accordion?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Enable tree line styling for vertical accordion mode.
|
|
105
|
+
* @default false
|
|
106
|
+
*/
|
|
107
|
+
tree?: boolean;
|
|
91
108
|
/**
|
|
92
109
|
* Additional CSS classes.
|
|
93
110
|
*/
|
|
@@ -35,6 +35,11 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
|
|
|
35
35
|
item: string;
|
|
36
36
|
icon: string;
|
|
37
37
|
};
|
|
38
|
+
};
|
|
39
|
+
tree: {
|
|
40
|
+
true: {
|
|
41
|
+
accordionGroupContent: string;
|
|
42
|
+
};
|
|
38
43
|
false: {};
|
|
39
44
|
};
|
|
40
45
|
}, {
|
|
@@ -81,6 +86,11 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
|
|
|
81
86
|
item: string;
|
|
82
87
|
icon: string;
|
|
83
88
|
};
|
|
89
|
+
};
|
|
90
|
+
tree: {
|
|
91
|
+
true: {
|
|
92
|
+
accordionGroupContent: string;
|
|
93
|
+
};
|
|
84
94
|
false: {};
|
|
85
95
|
};
|
|
86
96
|
}, {
|
|
@@ -127,6 +137,11 @@ export declare const navigationMenuVariants: import("tailwind-variants").TVRetur
|
|
|
127
137
|
item: string;
|
|
128
138
|
icon: string;
|
|
129
139
|
};
|
|
140
|
+
};
|
|
141
|
+
tree: {
|
|
142
|
+
true: {
|
|
143
|
+
accordionGroupContent: string;
|
|
144
|
+
};
|
|
130
145
|
false: {};
|
|
131
146
|
};
|
|
132
147
|
}, {
|
|
@@ -59,13 +59,29 @@ export const navigationMenuVariants = tv({
|
|
|
59
59
|
true: {
|
|
60
60
|
item: 'w-10 h-10 justify-center p-0 aspect-square shrink-0',
|
|
61
61
|
icon: 'text-[1.25rem] m-0'
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
tree: {
|
|
65
|
+
true: {
|
|
66
|
+
accordionGroupContent: 'pl-2 ml-6 border-l border-outline-variant/50 relative'
|
|
62
67
|
},
|
|
63
68
|
false: {}
|
|
64
69
|
}
|
|
65
70
|
},
|
|
71
|
+
compoundVariants: [
|
|
72
|
+
{
|
|
73
|
+
active: true,
|
|
74
|
+
tree: true,
|
|
75
|
+
class: {
|
|
76
|
+
item: 'border-primary',
|
|
77
|
+
accordionTrigger: 'border-primary bg-primary/10 text-primary'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
],
|
|
66
81
|
defaultVariants: {
|
|
67
82
|
variant: 'default',
|
|
68
83
|
active: false,
|
|
69
|
-
orientation: 'horizontal'
|
|
84
|
+
orientation: 'horizontal',
|
|
85
|
+
tree: false
|
|
70
86
|
}
|
|
71
87
|
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts" module>export {};
|
|
2
|
+
</script>
|
|
3
|
+
|
|
4
|
+
<script lang="ts">import { fly } from "svelte/transition";
|
|
5
|
+
import { tableBulkActionBarVariants } from "./table-bulk-action-bar.variants.js";
|
|
6
|
+
import Button from "../Button/Button.svelte";
|
|
7
|
+
let { count, onClear, text = "items selected", class: className, ui, children, ...restProps } = $props();
|
|
8
|
+
const slots = $derived(tableBulkActionBarVariants());
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div
|
|
12
|
+
class={slots.root({ class: [ui?.root, className] })}
|
|
13
|
+
transition:fly={{ y: 20, duration: 250 }}
|
|
14
|
+
{...restProps}
|
|
15
|
+
>
|
|
16
|
+
<div class={slots.content({ class: ui?.content })}>
|
|
17
|
+
<span class={slots.countBadge({ class: ui?.countBadge })}>{count}</span>
|
|
18
|
+
<span class="opacity-90">{text}</span>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
{#if children}
|
|
22
|
+
<div class={slots.actions({ class: ui?.actions })}>
|
|
23
|
+
{@render children()}
|
|
24
|
+
</div>
|
|
25
|
+
{/if}
|
|
26
|
+
|
|
27
|
+
<div class={slots.clearButton({ class: ui?.clearButton })}>
|
|
28
|
+
<Button
|
|
29
|
+
variant="ghost"
|
|
30
|
+
color="surface"
|
|
31
|
+
size="sm"
|
|
32
|
+
icon="lucide:x"
|
|
33
|
+
onclick={onClear}
|
|
34
|
+
class="h-8 w-8 !p-0 rounded-full"
|
|
35
|
+
aria-label="Clear selection"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TableBulkActionBarProps } from './table-bulk-action-bar.types.js';
|
|
2
|
+
export type Props = TableBulkActionBarProps;
|
|
3
|
+
declare const TableBulkActionBar: import("svelte").Component<TableBulkActionBarProps, {}, "">;
|
|
4
|
+
type TableBulkActionBar = ReturnType<typeof TableBulkActionBar>;
|
|
5
|
+
export default TableBulkActionBar;
|
package/dist/Table/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as Table } from './Table.svelte';
|
|
2
|
+
export { default as TableBulkActionBar } from './TableBulkActionBar.svelte';
|
|
2
3
|
export type { SortState, TableCellSlotProps, TableColumn, TableFooterSlotProps, TableHeaderSlotProps, TableProps } from './table.types.js';
|
|
4
|
+
export type { TableBulkActionBarProps } from './table-bulk-action-bar.types.js';
|
package/dist/Table/index.js
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
import type { TableBulkActionBarSlots } from './table-bulk-action-bar.variants.js';
|
|
4
|
+
export type TableBulkActionBarProps = {
|
|
5
|
+
/**
|
|
6
|
+
* The number of selected items to display.
|
|
7
|
+
*/
|
|
8
|
+
count: number;
|
|
9
|
+
/**
|
|
10
|
+
* Callback when the clear/close button is clicked.
|
|
11
|
+
* This is usually where you clear the selection state (`selectedRows = []`).
|
|
12
|
+
*/
|
|
13
|
+
onClear?: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Text to display next to the count.
|
|
16
|
+
* @default 'items selected'
|
|
17
|
+
*/
|
|
18
|
+
text?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Additional CSS classes.
|
|
21
|
+
*/
|
|
22
|
+
class?: ClassNameValue;
|
|
23
|
+
/**
|
|
24
|
+
* Override specific slot classes.
|
|
25
|
+
*/
|
|
26
|
+
ui?: Partial<Record<TableBulkActionBarSlots, ClassNameValue>>;
|
|
27
|
+
/**
|
|
28
|
+
* The action buttons to display.
|
|
29
|
+
*/
|
|
30
|
+
children?: Snippet;
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|