@mrintel/villain-ui 0.3.0 → 0.7.1
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 -21
- package/README.md +3490 -1296
- package/dist/components/buttons/Button.svelte +27 -33
- package/dist/components/buttons/Button.svelte.d.ts +4 -1
- package/dist/components/buttons/ButtonGroup.svelte +17 -30
- package/dist/components/buttons/FloatingActionButton.svelte +20 -44
- package/dist/components/buttons/FloatingActionButton.svelte.d.ts +2 -1
- package/dist/components/buttons/IconButton.svelte +23 -53
- package/dist/components/buttons/IconButton.svelte.d.ts +2 -1
- package/dist/components/buttons/LinkButton.svelte +24 -37
- package/dist/components/buttons/LinkButton.svelte.d.ts +4 -1
- package/dist/components/buttons/buttonClasses.d.ts +5 -0
- package/dist/components/buttons/buttonClasses.js +8 -3
- package/dist/components/cards/Card.svelte +54 -46
- package/dist/components/cards/Card.svelte.d.ts +9 -2
- package/dist/components/cards/Container.svelte +17 -33
- package/dist/components/cards/Divider.svelte +36 -52
- package/dist/components/cards/Divider.svelte.d.ts +2 -0
- package/dist/components/cards/Grid.svelte +55 -44
- package/dist/components/cards/Panel.svelte +18 -32
- package/dist/components/cards/Panel.svelte.d.ts +2 -1
- package/dist/components/cards/SectionHeader.svelte +24 -38
- package/dist/components/cards/SectionHeader.svelte.d.ts +1 -0
- package/dist/components/data/Avatar.svelte +48 -67
- package/dist/components/data/Badge.svelte +45 -32
- package/dist/components/data/Badge.svelte.d.ts +7 -1
- package/dist/components/data/CalendarGrid.svelte +433 -0
- package/dist/components/data/CalendarGrid.svelte.d.ts +25 -0
- package/dist/components/data/CalendarGrid.types.d.ts +7 -0
- package/dist/components/data/CalendarGrid.types.js +1 -0
- package/dist/components/data/CodeBlock.svelte +119 -121
- package/dist/components/data/CodeBlock.svelte.d.ts +8 -0
- package/dist/components/data/List.svelte +87 -64
- package/dist/components/data/List.svelte.d.ts +7 -0
- package/dist/components/data/Pagination.svelte +121 -123
- package/dist/components/data/Pagination.svelte.d.ts +5 -0
- package/dist/components/data/Sparkline.svelte +117 -0
- package/dist/components/data/Sparkline.svelte.d.ts +43 -0
- package/dist/components/data/Stat.svelte +92 -103
- package/dist/components/data/Table.svelte +443 -76
- package/dist/components/data/Table.svelte.d.ts +23 -2
- package/dist/components/data/Table.types.d.ts +14 -0
- package/dist/components/data/Table.types.js +1 -0
- package/dist/components/data/Tag.svelte +51 -53
- package/dist/components/data/Tag.svelte.d.ts +5 -1
- package/dist/components/data/index.d.ts +4 -0
- package/dist/components/data/index.js +2 -0
- package/dist/components/forms/Checkbox.svelte +39 -51
- package/dist/components/forms/Checkbox.svelte.d.ts +3 -1
- package/dist/components/forms/DatePicker.svelte +61 -0
- package/dist/components/forms/DatePicker.svelte.d.ts +15 -0
- package/dist/components/forms/DateTimePicker.svelte +63 -0
- package/dist/components/forms/DateTimePicker.svelte.d.ts +16 -0
- package/dist/components/forms/FileUpload.svelte +136 -164
- package/dist/components/forms/FileUpload.svelte.d.ts +1 -0
- package/dist/components/forms/Input.svelte +284 -57
- package/dist/components/forms/Input.svelte.d.ts +10 -3
- package/dist/components/forms/InputGroup.svelte +7 -7
- package/dist/components/forms/RadioGroup.svelte +77 -87
- package/dist/components/forms/RadioGroup.svelte.d.ts +3 -1
- package/dist/components/forms/RangeSlider.svelte +90 -116
- package/dist/components/forms/Select.svelte +106 -71
- package/dist/components/forms/Select.svelte.d.ts +3 -1
- package/dist/components/forms/Step.svelte +25 -0
- package/dist/components/forms/Step.svelte.d.ts +12 -0
- package/dist/components/forms/StepContext.d.ts +3 -0
- package/dist/components/forms/StepContext.js +5 -0
- package/dist/components/forms/Stepper.types.d.ts +37 -0
- package/dist/components/forms/Stepper.types.js +1 -0
- package/dist/components/forms/StepperForm.svelte +183 -0
- package/dist/components/forms/StepperForm.svelte.d.ts +17 -0
- package/dist/components/forms/Switch.svelte +44 -56
- package/dist/components/forms/Switch.svelte.d.ts +3 -1
- package/dist/components/forms/Textarea.svelte +52 -57
- package/dist/components/forms/Textarea.svelte.d.ts +3 -1
- package/dist/components/forms/TimePicker.svelte +63 -0
- package/dist/components/forms/TimePicker.svelte.d.ts +16 -0
- package/dist/components/forms/formClasses.d.ts +3 -0
- package/dist/components/forms/formClasses.js +3 -0
- package/dist/components/forms/index.d.ts +6 -0
- package/dist/components/forms/index.js +5 -0
- package/dist/components/navigation/Breadcrumbs.svelte +56 -59
- package/dist/components/navigation/Breadcrumbs.svelte.d.ts +1 -0
- package/dist/components/navigation/ContextMenu.svelte +133 -83
- package/dist/components/navigation/ContextMenu.svelte.d.ts +8 -1
- package/dist/components/navigation/DropdownMenu.svelte +139 -80
- package/dist/components/navigation/DropdownMenu.svelte.d.ts +8 -1
- package/dist/components/navigation/Menu.svelte +72 -48
- package/dist/components/navigation/Navbar.svelte +111 -32
- package/dist/components/navigation/Navbar.svelte.d.ts +6 -0
- package/dist/components/navigation/Sidebar.svelte +236 -35
- package/dist/components/navigation/Sidebar.svelte.d.ts +2 -0
- package/dist/components/navigation/Stepper.svelte +204 -0
- package/dist/components/navigation/Stepper.svelte.d.ts +34 -0
- package/dist/components/navigation/Tabs.svelte +86 -54
- package/dist/components/navigation/Tabs.svelte.d.ts +5 -1
- package/dist/components/navigation/index.d.ts +1 -0
- package/dist/components/navigation/index.js +1 -0
- package/dist/components/overlays/Alert.svelte +81 -99
- package/dist/components/overlays/Alert.svelte.d.ts +5 -1
- package/dist/components/overlays/CommandPalette.svelte +182 -217
- package/dist/components/overlays/Drawer.svelte +158 -167
- package/dist/components/overlays/Drawer.svelte.d.ts +3 -1
- package/dist/components/overlays/Dropdown.svelte +62 -30
- package/dist/components/overlays/Dropdown.svelte.d.ts +2 -0
- package/dist/components/overlays/Modal.svelte +125 -130
- package/dist/components/overlays/Modal.svelte.d.ts +3 -1
- package/dist/components/overlays/Popover.svelte +106 -131
- package/dist/components/overlays/ProgressBar.svelte +29 -45
- package/dist/components/overlays/SkeletonLoader.svelte +66 -82
- package/dist/components/overlays/Spinner.svelte +33 -43
- package/dist/components/overlays/Toast.svelte +111 -140
- package/dist/components/overlays/Toast.svelte.d.ts +3 -0
- package/dist/components/overlays/Tooltip.svelte +94 -115
- package/dist/components/overlays/Tooltip.svelte.d.ts +3 -1
- package/dist/components/typography/Code.svelte +10 -14
- package/dist/components/typography/Heading.svelte +15 -22
- package/dist/components/typography/Heading.svelte.d.ts +1 -0
- package/dist/components/typography/Text.svelte +21 -24
- package/dist/components/typography/Text.svelte.d.ts +2 -1
- package/dist/components/utilities/Accordion.svelte +54 -67
- package/dist/components/utilities/Accordion.svelte.d.ts +4 -1
- package/dist/components/utilities/Carousel.svelte +124 -152
- package/dist/components/utilities/Collapse.svelte +46 -60
- package/dist/components/utilities/Hero.svelte +42 -0
- package/dist/components/utilities/Hero.svelte.d.ts +10 -0
- package/dist/components/utilities/Portal.svelte +47 -72
- package/dist/components/utilities/ScrollArea.svelte +33 -41
- package/dist/components/utilities/SystemConsole.svelte +310 -0
- package/dist/components/utilities/SystemConsole.svelte.d.ts +20 -0
- package/dist/components/utilities/SystemInterface.svelte +726 -0
- package/dist/components/utilities/SystemInterface.svelte.d.ts +19 -0
- package/dist/components/utilities/index.d.ts +4 -0
- package/dist/components/utilities/index.js +3 -0
- package/dist/components/utilities/utilities.types.d.ts +46 -0
- package/dist/components/utilities/utilities.types.js +4 -0
- package/dist/index.d.ts +57 -5
- package/dist/index.js +5 -5
- package/dist/theme.css +2889 -218
- package/package.json +83 -76
|
@@ -1,115 +1,94 @@
|
|
|
1
|
-
<script lang="ts">
|
|
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
|
-
visible
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
onmouseenter={handleMouseEnter}
|
|
96
|
-
onmouseleave={handleMouseLeave}
|
|
97
|
-
onfocus={handleFocus}
|
|
98
|
-
onblur={handleBlur}
|
|
99
|
-
role="presentation"
|
|
100
|
-
class="contents"
|
|
101
|
-
>
|
|
102
|
-
{@render trigger?.()}
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
{#if visible}
|
|
106
|
-
<div
|
|
107
|
-
bind:this={tooltipElement}
|
|
108
|
-
id={tooltipId}
|
|
109
|
-
role="tooltip"
|
|
110
|
-
class="absolute {placementClasses[actualPlacement]} z-50 glass-panel rounded-md px-3 py-2 text-sm text-text whitespace-nowrap animate-[fade-in_0.15s_var(--ease-luxe)] pointer-events-none"
|
|
111
|
-
>
|
|
112
|
-
{content}
|
|
113
|
-
</div>
|
|
114
|
-
{/if}
|
|
115
|
-
</div>
|
|
1
|
+
<script lang="ts">import { createId } from '../../lib/internal/id.js';
|
|
2
|
+
let { content, placement = 'top', delay = 200, trigger, children, class: className = '' } = $props();
|
|
3
|
+
// Use children as fallback if trigger not provided
|
|
4
|
+
const renderedTrigger = $derived(trigger ?? children);
|
|
5
|
+
let visible = $state(false);
|
|
6
|
+
let actualPlacement = $state(placement);
|
|
7
|
+
let tooltipElement = $state();
|
|
8
|
+
let timeoutId;
|
|
9
|
+
const tooltipId = createId('tooltip');
|
|
10
|
+
const placementClasses = {
|
|
11
|
+
top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
|
|
12
|
+
bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
|
|
13
|
+
left: 'right-full top-1/2 -translate-y-1/2 mr-2',
|
|
14
|
+
right: 'left-full top-1/2 -translate-y-1/2 ml-2'
|
|
15
|
+
};
|
|
16
|
+
const oppositePlacement = {
|
|
17
|
+
top: 'bottom',
|
|
18
|
+
bottom: 'top',
|
|
19
|
+
left: 'right',
|
|
20
|
+
right: 'left'
|
|
21
|
+
};
|
|
22
|
+
function handleMouseEnter() {
|
|
23
|
+
if (typeof window === 'undefined')
|
|
24
|
+
return;
|
|
25
|
+
timeoutId = window.setTimeout(() => {
|
|
26
|
+
visible = true;
|
|
27
|
+
}, delay);
|
|
28
|
+
}
|
|
29
|
+
function handleMouseLeave() {
|
|
30
|
+
if (timeoutId) {
|
|
31
|
+
clearTimeout(timeoutId);
|
|
32
|
+
}
|
|
33
|
+
visible = false;
|
|
34
|
+
}
|
|
35
|
+
function handleFocus() {
|
|
36
|
+
handleMouseEnter();
|
|
37
|
+
}
|
|
38
|
+
function handleBlur() {
|
|
39
|
+
handleMouseLeave();
|
|
40
|
+
}
|
|
41
|
+
// Reset actualPlacement when visibility changes
|
|
42
|
+
$effect(() => {
|
|
43
|
+
if (!visible) {
|
|
44
|
+
actualPlacement = placement;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Check viewport bounds and flip placement if needed
|
|
48
|
+
$effect(() => {
|
|
49
|
+
if (typeof window === 'undefined')
|
|
50
|
+
return;
|
|
51
|
+
if (visible && tooltipElement) {
|
|
52
|
+
const rect = tooltipElement.getBoundingClientRect();
|
|
53
|
+
const viewportWidth = window.innerWidth;
|
|
54
|
+
const viewportHeight = window.innerHeight;
|
|
55
|
+
// Determine if current placement overflows and flip if needed
|
|
56
|
+
if (actualPlacement === 'top' && rect.top < 0 && actualPlacement !== oppositePlacement[placement]) {
|
|
57
|
+
actualPlacement = 'bottom';
|
|
58
|
+
}
|
|
59
|
+
else if (actualPlacement === 'bottom' && rect.bottom > viewportHeight && actualPlacement !== oppositePlacement[placement]) {
|
|
60
|
+
actualPlacement = 'top';
|
|
61
|
+
}
|
|
62
|
+
else if (actualPlacement === 'left' && rect.left < 0 && actualPlacement !== oppositePlacement[placement]) {
|
|
63
|
+
actualPlacement = 'right';
|
|
64
|
+
}
|
|
65
|
+
else if (actualPlacement === 'right' && rect.right > viewportWidth && actualPlacement !== oppositePlacement[placement]) {
|
|
66
|
+
actualPlacement = 'left';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<div class="relative inline-block">
|
|
73
|
+
<div
|
|
74
|
+
aria-describedby={tooltipId}
|
|
75
|
+
onmouseenter={handleMouseEnter}
|
|
76
|
+
onmouseleave={handleMouseLeave}
|
|
77
|
+
onfocus={handleFocus}
|
|
78
|
+
onblur={handleBlur}
|
|
79
|
+
role="presentation"
|
|
80
|
+
class="contents"
|
|
81
|
+
>
|
|
82
|
+
{@render renderedTrigger?.()}
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div
|
|
86
|
+
bind:this={tooltipElement}
|
|
87
|
+
id={tooltipId}
|
|
88
|
+
role="tooltip"
|
|
89
|
+
aria-hidden={visible ? 'false' : 'true'}
|
|
90
|
+
class="absolute {placementClasses[actualPlacement]} z-[var(--z-50)] panel-floating rounded-[var(--radius-md)] px-4 py-2.5 text-sm text-text whitespace-nowrap pointer-events-none {className} {visible ? 'animate-[fade-in_0.15s_var(--ease-luxe)] opacity-100' : 'opacity-0 invisible'}"
|
|
91
|
+
>
|
|
92
|
+
{content}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
interface Props {
|
|
2
|
+
export interface Props {
|
|
3
3
|
content: string;
|
|
4
4
|
placement?: 'top' | 'bottom' | 'left' | 'right';
|
|
5
5
|
delay?: number;
|
|
6
6
|
trigger?: Snippet;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
class?: string;
|
|
7
9
|
}
|
|
8
10
|
declare const Tooltip: import("svelte").Component<Props, {}, "">;
|
|
9
11
|
type Tooltip = ReturnType<typeof Tooltip>;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
style="background: rgba(127, 61, 255, 0.1); border: 1px solid var(--color-border); padding: 0.125rem 0.375rem; border-radius: var(--radius-sm); font-family: var(--font-mono); color: var(--color-accent-soft); font-size: 0.9em;"
|
|
12
|
-
>
|
|
13
|
-
{@render children?.()}
|
|
14
|
-
</code>
|
|
1
|
+
<script lang="ts">"use strict";
|
|
2
|
+
let { children } = $props();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<code
|
|
6
|
+
class="inline-flex items-center transition-all duration-300 hover:shadow-[0_0_12px_var(--color-accent-overlay-30)]"
|
|
7
|
+
style="background: var(--color-accent-overlay-10); border: 1px solid var(--color-border); padding: 0.125rem 0.375rem; border-radius: var(--radius-sm); font-family: var(--font-mono); color: var(--color-accent-soft); font-size: 0.9em;"
|
|
8
|
+
>
|
|
9
|
+
{@render children?.()}
|
|
10
|
+
</code>
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
`font-size: var(--text-h${level}-size); line-height: var(--text-h${level}-line-height); font-weight: var(--text-h${level}-weight); font-family: var(--font-heading); color: var(--color-text);`
|
|
17
|
-
);
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<svelte:element this={element} class={baseClasses} style={styles}>
|
|
21
|
-
{@render children?.()}
|
|
22
|
-
</svelte:element>
|
|
1
|
+
<script lang="ts">"use strict";
|
|
2
|
+
let { level = 1, glow = false, variant = 'default', as, children } = $props();
|
|
3
|
+
const element = $derived(as ?? `h${level}`);
|
|
4
|
+
const variantClasses = {
|
|
5
|
+
default: '',
|
|
6
|
+
accent: 'text-accent',
|
|
7
|
+
gradient: 'text-gradient'
|
|
8
|
+
};
|
|
9
|
+
const baseClasses = $derived(`transition-all duration-300 ${glow ? 'text-glow' : ''} ${variantClasses[variant]}`);
|
|
10
|
+
const styles = $derived(`font-size: var(--text-h${level}-size); line-height: var(--text-h${level}-line-height); font-weight: var(--text-h${level}-weight); letter-spacing: var(--text-h${level}-letter-spacing); font-family: var(--font-heading); color: var(--color-text);`);
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<svelte:element this={element} class={baseClasses} style={styles}>
|
|
14
|
+
{@render children?.()}
|
|
15
|
+
</svelte:element>
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
<svelte:element this={as} class="transition-colors duration-300" style={styles}>
|
|
23
|
-
{@render children?.()}
|
|
24
|
-
</svelte:element>
|
|
1
|
+
<script lang="ts">"use strict";
|
|
2
|
+
let { variant = 'body', color = 'default', weight = 'normal', as = 'p', children } = $props();
|
|
3
|
+
const colorMap = {
|
|
4
|
+
default: 'var(--color-text)',
|
|
5
|
+
soft: 'var(--color-text-soft)',
|
|
6
|
+
muted: 'var(--color-text-muted)',
|
|
7
|
+
success: 'var(--color-success)',
|
|
8
|
+
warning: 'var(--color-warning)',
|
|
9
|
+
error: 'var(--color-error)',
|
|
10
|
+
};
|
|
11
|
+
const weightMap = {
|
|
12
|
+
normal: '400',
|
|
13
|
+
semibold: '600',
|
|
14
|
+
bold: '700',
|
|
15
|
+
};
|
|
16
|
+
const styles = $derived(`font-size: var(--text-${variant}-size); line-height: var(--text-${variant}-line-height); font-weight: ${weightMap[weight] || '400'}; letter-spacing: var(--text-${variant}-letter-spacing); font-family: var(--font-body); color: ${colorMap[color]};`);
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<svelte:element this={as} class="transition-colors duration-300" style={styles}>
|
|
20
|
+
{@render children?.()}
|
|
21
|
+
</svelte:element>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
interface Props {
|
|
2
2
|
variant?: 'body' | 'caption';
|
|
3
|
-
color?: 'default' | 'soft' | 'muted';
|
|
3
|
+
color?: 'default' | 'soft' | 'muted' | 'success' | 'warning' | 'error';
|
|
4
|
+
weight?: 'normal' | 'bold' | 'semibold';
|
|
4
5
|
as?: 'p' | 'span' | 'div';
|
|
5
6
|
children?: import('svelte').Snippet;
|
|
6
7
|
}
|
|
@@ -1,67 +1,54 @@
|
|
|
1
|
-
<script lang="ts">
|
|
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
|
-
<Collapse
|
|
56
|
-
title={item.title}
|
|
57
|
-
open={isItemOpen(item.id)}
|
|
58
|
-
onToggle={() => toggleItem(item.id)}
|
|
59
|
-
>
|
|
60
|
-
{#if typeof item.content === 'string'}
|
|
61
|
-
{item.content}
|
|
62
|
-
{:else}
|
|
63
|
-
{@render item.content()}
|
|
64
|
-
{/if}
|
|
65
|
-
</Collapse>
|
|
66
|
-
{/each}
|
|
67
|
-
</div>
|
|
1
|
+
<script lang="ts">import Collapse from './Collapse.svelte';
|
|
2
|
+
let { items, openItems = $bindable([]), mode = 'single', onToggle, ontoggle } = $props();
|
|
3
|
+
const onToggleCallback = $derived(onToggle ?? ontoggle);
|
|
4
|
+
// Normalize openItems to array
|
|
5
|
+
let openItemsArray = $derived(mode === 'single'
|
|
6
|
+
? typeof openItems === 'string'
|
|
7
|
+
? [openItems]
|
|
8
|
+
: []
|
|
9
|
+
: Array.isArray(openItems)
|
|
10
|
+
? openItems
|
|
11
|
+
: []);
|
|
12
|
+
function isItemOpen(id) {
|
|
13
|
+
return openItemsArray.includes(id);
|
|
14
|
+
}
|
|
15
|
+
function toggleItem(id) {
|
|
16
|
+
const wasOpen = isItemOpen(id);
|
|
17
|
+
if (mode === 'single') {
|
|
18
|
+
// Single mode: only one item open at a time
|
|
19
|
+
if (wasOpen) {
|
|
20
|
+
openItems = '';
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
openItems = id;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Multiple mode: toggle independently
|
|
28
|
+
if (wasOpen) {
|
|
29
|
+
openItems = openItemsArray.filter(itemId => itemId !== id);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
openItems = [...openItemsArray, id];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Call onToggle callback if provided
|
|
36
|
+
onToggleCallback?.(id, !wasOpen);
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div class="space-y-2">
|
|
41
|
+
{#each items as item (item.id)}
|
|
42
|
+
<Collapse
|
|
43
|
+
title={item.title}
|
|
44
|
+
open={isItemOpen(item.id)}
|
|
45
|
+
onToggle={() => toggleItem(item.id)}
|
|
46
|
+
>
|
|
47
|
+
{#if typeof item.content === 'string'}
|
|
48
|
+
{item.content}
|
|
49
|
+
{:else}
|
|
50
|
+
{@render item.content()}
|
|
51
|
+
{/if}
|
|
52
|
+
</Collapse>
|
|
53
|
+
{/each}
|
|
54
|
+
</div>
|
|
@@ -4,10 +4,13 @@ interface AccordionItem {
|
|
|
4
4
|
title: string;
|
|
5
5
|
content: string | Snippet;
|
|
6
6
|
}
|
|
7
|
-
interface Props {
|
|
7
|
+
export interface Props {
|
|
8
8
|
items: AccordionItem[];
|
|
9
9
|
openItems?: string | string[];
|
|
10
10
|
mode?: 'single' | 'multiple';
|
|
11
|
+
onToggle?: (itemId: string, isOpen: boolean) => void;
|
|
12
|
+
/** @deprecated Use onToggle */
|
|
13
|
+
ontoggle?: (itemId: string, isOpen: boolean) => void;
|
|
11
14
|
}
|
|
12
15
|
declare const Accordion: import("svelte").Component<Props, {}, "openItems">;
|
|
13
16
|
type Accordion = ReturnType<typeof Accordion>;
|