@makolabs/ripple 1.7.11 → 1.9.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/README.md +16 -0
- package/dist/adapters/ai/OpenAIAdapter.d.ts +8 -1
- package/dist/adapters/ai/OpenAIAdapter.js +2 -2
- package/dist/adapters/storage/BaseAdapter.js +2 -2
- package/dist/adapters/storage/S3Adapter.js +1 -6
- package/dist/adapters/storage/types.d.ts +3 -3
- package/dist/ai/AIChatInterface.svelte +0 -1
- package/dist/ai/ai-chat-interface.d.ts +21 -22
- package/dist/ai/ai-types.d.ts +44 -0
- package/dist/ai/ai-types.js +1 -0
- package/dist/ai/content-detector.js +0 -1
- package/dist/button/Button.svelte +9 -2
- package/dist/button/button-types.d.ts +25 -0
- package/dist/button/button-types.js +1 -0
- package/dist/button/button.d.ts +39 -40
- package/dist/charts/Chart.svelte +11 -23
- package/dist/charts/chart-types.d.ts +137 -0
- package/dist/charts/chart-types.js +1 -0
- package/dist/drawer/Drawer.svelte +57 -23
- package/dist/drawer/drawer-types.d.ts +33 -0
- package/dist/drawer/drawer-types.js +1 -0
- package/dist/drawer/drawer.d.ts +18 -19
- package/dist/elements/accordion/Accordion.svelte +39 -18
- package/dist/elements/accordion/accordion-types.d.ts +29 -0
- package/dist/elements/accordion/accordion-types.js +1 -0
- package/dist/elements/accordion/accordion.d.ts +21 -22
- package/dist/elements/alert/Alert.svelte +20 -8
- package/dist/elements/badge/Badge.svelte +5 -2
- package/dist/elements/badge/badge-types.d.ts +11 -0
- package/dist/elements/badge/badge-types.js +1 -0
- package/dist/elements/badge/badge.d.ts +39 -40
- package/dist/elements/dropdown/Dropdown.svelte +18 -2
- package/dist/elements/dropdown/Select.svelte +17 -5
- package/dist/elements/dropdown/dropdown-types.d.ts +68 -0
- package/dist/elements/dropdown/dropdown-types.js +1 -0
- package/dist/elements/dropdown/dropdown.d.ts +18 -19
- package/dist/elements/dropdown/select.d.ts +18 -19
- package/dist/elements/file-upload/file-upload-types.d.ts +68 -0
- package/dist/elements/file-upload/file-upload-types.js +1 -0
- package/dist/elements/pagination/Pagination.svelte +15 -2
- package/dist/elements/pagination/Pagination.svelte.d.ts +1 -0
- package/dist/elements/progress/progress-types.d.ts +22 -0
- package/dist/elements/progress/progress-types.js +1 -0
- package/dist/elements/timeline/timeline-types.d.ts +11 -0
- package/dist/elements/timeline/timeline-types.js +1 -0
- package/dist/filters/filter-types.d.ts +24 -0
- package/dist/filters/filter-types.js +1 -0
- package/dist/forms/Checkbox.svelte +16 -4
- package/dist/forms/Form.svelte +0 -2
- package/dist/forms/Input.svelte +19 -5
- package/dist/forms/NumberInput.svelte +8 -1
- package/dist/forms/RadioInputs.svelte +14 -5
- package/dist/forms/Slider.svelte +6 -4
- package/dist/forms/Toggle.svelte +67 -29
- package/dist/forms/form-types.d.ts +168 -0
- package/dist/forms/form-types.js +1 -0
- package/dist/forms/slider.d.ts +72 -10
- package/dist/forms/slider.js +21 -0
- package/dist/header/Breadcrumbs.svelte +47 -24
- package/dist/header/PageHeader.svelte +12 -2
- package/dist/header/breadcrumbs.d.ts +47 -39
- package/dist/header/header-types.d.ts +43 -0
- package/dist/header/header-types.js +1 -0
- package/dist/helper/deprecation.d.ts +14 -0
- package/dist/helper/deprecation.js +24 -0
- package/dist/helper/testid.d.ts +10 -0
- package/dist/helper/testid.js +17 -0
- package/dist/index.d.ts +37 -1007
- package/dist/index.js +38 -14
- package/dist/layout/activity-list/activity-list-types.d.ts +30 -0
- package/dist/layout/activity-list/activity-list-types.js +1 -0
- package/dist/layout/activity-list/activity-list.d.ts +21 -22
- package/dist/layout/card/Card.svelte +19 -5
- package/dist/layout/card/card-types.d.ts +43 -0
- package/dist/layout/card/card-types.js +1 -0
- package/dist/layout/card/card.d.ts +21 -22
- package/dist/layout/card/metric-card.d.ts +3 -3
- package/dist/layout/card/ranked-card.d.ts +2 -1
- package/dist/layout/navbar/Navbar.svelte +14 -16
- package/dist/layout/navbar/navbar-types.d.ts +19 -0
- package/dist/layout/navbar/navbar-types.js +1 -0
- package/dist/layout/navbar/navbar.d.ts +19 -19
- package/dist/layout/sidebar/Sidebar.svelte +6 -3
- package/dist/layout/sidebar/sidebar-types.d.ts +59 -0
- package/dist/layout/sidebar/sidebar-types.js +1 -0
- package/dist/layout/table/Table.svelte +237 -303
- package/dist/layout/table/table-types.d.ts +82 -0
- package/dist/layout/table/table-types.js +1 -0
- package/dist/layout/table/table.d.ts +24 -25
- package/dist/layout/tabs/Tab.svelte +3 -1
- package/dist/layout/tabs/TabGroup.svelte +7 -4
- package/dist/layout/tabs/tabs-types.d.ts +43 -0
- package/dist/layout/tabs/tabs-types.js +1 -0
- package/dist/layout/tabs/tabs.d.ts +39 -40
- package/dist/modal/Modal.svelte +124 -21
- package/dist/modal/modal-types.d.ts +34 -0
- package/dist/modal/modal-types.js +1 -0
- package/dist/modal/modal.d.ts +18 -19
- package/dist/modal/modal.js +2 -2
- package/dist/types/echarts.d.ts +27 -0
- package/dist/user-management/UserModal.svelte +1 -1
- package/dist/user-management/UserTable.svelte +3 -3
- package/dist/user-management/UserViewModal.svelte +2 -2
- package/dist/user-management/user-management-types.d.ts +156 -0
- package/dist/user-management/user-management-types.js +1 -0
- package/dist/variants.d.ts +13 -13
- package/package.json +9 -7
- package/dist/ai/AIChatInterfaceTestWrapper.svelte +0 -26
- package/dist/ai/AIChatInterfaceTestWrapper.svelte.d.ts +0 -17
- package/dist/button/ButtonTestWrapper.svelte +0 -10
- package/dist/button/ButtonTestWrapper.svelte.d.ts +0 -7
- package/dist/drawer/DrawerTestWrapper.svelte +0 -19
- package/dist/drawer/DrawerTestWrapper.svelte.d.ts +0 -9
- package/dist/elements/accordion/AccordionTestWrapper.svelte +0 -21
- package/dist/elements/accordion/AccordionTestWrapper.svelte.d.ts +0 -10
- package/dist/elements/badge/BadgeTestWrapper.svelte +0 -14
- package/dist/elements/badge/BadgeTestWrapper.svelte.d.ts +0 -9
- package/dist/forms/CheckboxTestWrapper.svelte +0 -8
- package/dist/forms/CheckboxTestWrapper.svelte.d.ts +0 -4
- package/dist/forms/InputTestWrapper.svelte +0 -8
- package/dist/forms/InputTestWrapper.svelte.d.ts +0 -4
- package/dist/forms/ToggleTestWrapper.svelte +0 -8
- package/dist/forms/ToggleTestWrapper.svelte.d.ts +0 -7
- package/dist/layout/card/CardTestWrapper.svelte +0 -15
- package/dist/layout/card/CardTestWrapper.svelte.d.ts +0 -7
- package/dist/modal/ModalTestWrapper.svelte +0 -20
- package/dist/modal/ModalTestWrapper.svelte.d.ts +0 -8
- package/dist/user-management/UserManagementTestWrapper.svelte +0 -32
- package/dist/user-management/UserManagementTestWrapper.svelte.d.ts +0 -12
- package/dist/user-management/UserModalTestWrapper.svelte +0 -22
- package/dist/user-management/UserModalTestWrapper.svelte.d.ts +0 -7
- package/dist/user-management/UserTableTestWrapper.svelte +0 -41
- package/dist/user-management/UserTableTestWrapper.svelte.d.ts +0 -7
- package/dist/user-management/UserViewModalTestWrapper.svelte +0 -22
- package/dist/user-management/UserViewModalTestWrapper.svelte.d.ts +0 -7
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { buildTestId } from '../../helper/testid.js';
|
|
3
4
|
import { Color } from '../../variants.js';
|
|
4
|
-
import type { AlertProps } from '../../index.js';
|
|
5
|
+
import type { AlertProps, VariantColors } from '../../index.js';
|
|
5
6
|
|
|
6
7
|
let {
|
|
7
8
|
title,
|
|
@@ -9,30 +10,40 @@
|
|
|
9
10
|
color = Color.DEFAULT,
|
|
10
11
|
onclose,
|
|
11
12
|
footer,
|
|
12
|
-
|
|
13
|
+
icon: Icon,
|
|
14
|
+
class: className = '',
|
|
15
|
+
testId
|
|
13
16
|
}: AlertProps = $props();
|
|
14
17
|
|
|
15
18
|
function handleClose() {
|
|
16
19
|
onclose?.();
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
const colorClasses = {
|
|
22
|
+
const colorClasses: Record<VariantColors, string> = {
|
|
20
23
|
[Color.DEFAULT]: 'bg-default-50 border-default-200 text-default-800',
|
|
21
24
|
[Color.PRIMARY]: 'bg-primary-50 border-primary-200 text-primary-800',
|
|
25
|
+
[Color.SECONDARY]: 'bg-secondary-50 border-secondary-200 text-secondary-800',
|
|
26
|
+
[Color.INFO]: 'bg-info-50 border-info-200 text-info-800',
|
|
22
27
|
[Color.SUCCESS]: 'bg-success-50 border-success-200 text-success-800',
|
|
23
28
|
[Color.WARNING]: 'bg-warning-50 border-warning-200 text-warning-800',
|
|
24
|
-
[Color.DANGER]: 'bg-danger-50 border-danger-200 text-danger-800'
|
|
25
|
-
[Color.INFO]: 'bg-info-50 border-info-200 text-info-800'
|
|
29
|
+
[Color.DANGER]: 'bg-danger-50 border-danger-200 text-danger-800'
|
|
26
30
|
};
|
|
27
31
|
</script>
|
|
28
32
|
|
|
29
|
-
<div
|
|
33
|
+
<div
|
|
34
|
+
role="alert"
|
|
35
|
+
class={cn('relative rounded-lg border p-4', colorClasses[color], className)}
|
|
36
|
+
data-testid={buildTestId('alert', undefined, testId)}
|
|
37
|
+
>
|
|
30
38
|
<div class="flex items-start justify-between gap-4">
|
|
39
|
+
{#if Icon}
|
|
40
|
+
<Icon class="mt-0.5 h-5 w-5 shrink-0" />
|
|
41
|
+
{/if}
|
|
31
42
|
<div class="flex-1">
|
|
32
43
|
{#if title}
|
|
33
|
-
<h4 class="font-semibold">{title}</h4>
|
|
44
|
+
<h4 class="font-semibold" data-testid={buildTestId('alert', 'title', testId)}>{title}</h4>
|
|
34
45
|
{/if}
|
|
35
|
-
<p class="text-sm">{message}</p>
|
|
46
|
+
<p class="text-sm" data-testid={buildTestId('alert', 'message', testId)}>{message}</p>
|
|
36
47
|
</div>
|
|
37
48
|
{#if onclose}
|
|
38
49
|
<button
|
|
@@ -40,6 +51,7 @@
|
|
|
40
51
|
class="hover:bg-default-200/20 flex-shrink-0 cursor-pointer rounded-md p-1"
|
|
41
52
|
onclick={handleClose}
|
|
42
53
|
aria-label="Close alert"
|
|
54
|
+
data-testid={buildTestId('alert', 'close', testId)}
|
|
43
55
|
>
|
|
44
56
|
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
45
57
|
<path
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { cn } from '../../helper/cls.js';
|
|
3
|
+
import { buildTestId } from '../../helper/testid.js';
|
|
3
4
|
import { badge } from './badge.js';
|
|
4
5
|
import { Size, Color } from '../../variants.js';
|
|
5
6
|
import type { BadgeProps } from '../../index.js';
|
|
@@ -9,7 +10,8 @@
|
|
|
9
10
|
color = Color.DEFAULT,
|
|
10
11
|
class: className = '',
|
|
11
12
|
children,
|
|
12
|
-
onclose: onClose
|
|
13
|
+
onclose: onClose,
|
|
14
|
+
testId
|
|
13
15
|
}: BadgeProps = $props();
|
|
14
16
|
|
|
15
17
|
const { base } = $derived(
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
}
|
|
28
30
|
</script>
|
|
29
31
|
|
|
30
|
-
<span class={baseClass}>
|
|
32
|
+
<span class={baseClass} data-testid={buildTestId('badge', undefined, testId)}>
|
|
31
33
|
{@render children()}
|
|
32
34
|
{#if onClose}
|
|
33
35
|
<button
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
title="Close"
|
|
38
40
|
tabindex="0"
|
|
39
41
|
type="button"
|
|
42
|
+
data-testid={buildTestId('badge', 'close', testId)}
|
|
40
43
|
>
|
|
41
44
|
<svg
|
|
42
45
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { VariantColors, VariantSizes } from '../../index.js';
|
|
4
|
+
export type BadgeProps = {
|
|
5
|
+
size?: VariantSizes;
|
|
6
|
+
color?: VariantColors;
|
|
7
|
+
class?: ClassValue;
|
|
8
|
+
children: Snippet;
|
|
9
|
+
onclose?: (event: MouseEvent) => void;
|
|
10
|
+
testId?: string;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,57 +1,56 @@
|
|
|
1
|
-
import { Size, Color } from '../../variants.js';
|
|
2
1
|
export declare const badge: import("tailwind-variants").TVReturnType<{
|
|
3
2
|
size: {
|
|
4
|
-
|
|
3
|
+
xs: {
|
|
5
4
|
base: string;
|
|
6
5
|
icon: string;
|
|
7
6
|
};
|
|
8
|
-
|
|
7
|
+
sm: {
|
|
9
8
|
base: string;
|
|
10
9
|
icon: string;
|
|
11
10
|
};
|
|
12
|
-
|
|
11
|
+
base: {
|
|
13
12
|
base: string;
|
|
14
13
|
icon: string;
|
|
15
14
|
};
|
|
16
|
-
|
|
15
|
+
lg: {
|
|
17
16
|
base: string;
|
|
18
17
|
icon: string;
|
|
19
18
|
};
|
|
20
|
-
|
|
19
|
+
xl: {
|
|
21
20
|
base: string;
|
|
22
21
|
icon: string;
|
|
23
22
|
};
|
|
24
|
-
|
|
23
|
+
"2xl": {
|
|
25
24
|
base: string;
|
|
26
25
|
icon: string;
|
|
27
26
|
};
|
|
28
27
|
};
|
|
29
28
|
color: {
|
|
30
|
-
|
|
29
|
+
default: {
|
|
31
30
|
base: string;
|
|
32
31
|
icon: string;
|
|
33
32
|
};
|
|
34
|
-
|
|
33
|
+
primary: {
|
|
35
34
|
base: string;
|
|
36
35
|
icon: string;
|
|
37
36
|
};
|
|
38
|
-
|
|
37
|
+
secondary: {
|
|
39
38
|
base: string;
|
|
40
39
|
icon: string;
|
|
41
40
|
};
|
|
42
|
-
|
|
41
|
+
success: {
|
|
43
42
|
base: string;
|
|
44
43
|
icon: string;
|
|
45
44
|
};
|
|
46
|
-
|
|
45
|
+
warning: {
|
|
47
46
|
base: string;
|
|
48
47
|
icon: string;
|
|
49
48
|
};
|
|
50
|
-
|
|
49
|
+
danger: {
|
|
51
50
|
base: string;
|
|
52
51
|
icon: string;
|
|
53
52
|
};
|
|
54
|
-
|
|
53
|
+
info: {
|
|
55
54
|
base: string;
|
|
56
55
|
icon: string;
|
|
57
56
|
};
|
|
@@ -61,57 +60,57 @@ export declare const badge: import("tailwind-variants").TVReturnType<{
|
|
|
61
60
|
icon: string;
|
|
62
61
|
}, undefined, {
|
|
63
62
|
size: {
|
|
64
|
-
|
|
63
|
+
xs: {
|
|
65
64
|
base: string;
|
|
66
65
|
icon: string;
|
|
67
66
|
};
|
|
68
|
-
|
|
67
|
+
sm: {
|
|
69
68
|
base: string;
|
|
70
69
|
icon: string;
|
|
71
70
|
};
|
|
72
|
-
|
|
71
|
+
base: {
|
|
73
72
|
base: string;
|
|
74
73
|
icon: string;
|
|
75
74
|
};
|
|
76
|
-
|
|
75
|
+
lg: {
|
|
77
76
|
base: string;
|
|
78
77
|
icon: string;
|
|
79
78
|
};
|
|
80
|
-
|
|
79
|
+
xl: {
|
|
81
80
|
base: string;
|
|
82
81
|
icon: string;
|
|
83
82
|
};
|
|
84
|
-
|
|
83
|
+
"2xl": {
|
|
85
84
|
base: string;
|
|
86
85
|
icon: string;
|
|
87
86
|
};
|
|
88
87
|
};
|
|
89
88
|
color: {
|
|
90
|
-
|
|
89
|
+
default: {
|
|
91
90
|
base: string;
|
|
92
91
|
icon: string;
|
|
93
92
|
};
|
|
94
|
-
|
|
93
|
+
primary: {
|
|
95
94
|
base: string;
|
|
96
95
|
icon: string;
|
|
97
96
|
};
|
|
98
|
-
|
|
97
|
+
secondary: {
|
|
99
98
|
base: string;
|
|
100
99
|
icon: string;
|
|
101
100
|
};
|
|
102
|
-
|
|
101
|
+
success: {
|
|
103
102
|
base: string;
|
|
104
103
|
icon: string;
|
|
105
104
|
};
|
|
106
|
-
|
|
105
|
+
warning: {
|
|
107
106
|
base: string;
|
|
108
107
|
icon: string;
|
|
109
108
|
};
|
|
110
|
-
|
|
109
|
+
danger: {
|
|
111
110
|
base: string;
|
|
112
111
|
icon: string;
|
|
113
112
|
};
|
|
114
|
-
|
|
113
|
+
info: {
|
|
115
114
|
base: string;
|
|
116
115
|
icon: string;
|
|
117
116
|
};
|
|
@@ -121,57 +120,57 @@ export declare const badge: import("tailwind-variants").TVReturnType<{
|
|
|
121
120
|
icon: string;
|
|
122
121
|
}, import("tailwind-variants").TVReturnType<{
|
|
123
122
|
size: {
|
|
124
|
-
|
|
123
|
+
xs: {
|
|
125
124
|
base: string;
|
|
126
125
|
icon: string;
|
|
127
126
|
};
|
|
128
|
-
|
|
127
|
+
sm: {
|
|
129
128
|
base: string;
|
|
130
129
|
icon: string;
|
|
131
130
|
};
|
|
132
|
-
|
|
131
|
+
base: {
|
|
133
132
|
base: string;
|
|
134
133
|
icon: string;
|
|
135
134
|
};
|
|
136
|
-
|
|
135
|
+
lg: {
|
|
137
136
|
base: string;
|
|
138
137
|
icon: string;
|
|
139
138
|
};
|
|
140
|
-
|
|
139
|
+
xl: {
|
|
141
140
|
base: string;
|
|
142
141
|
icon: string;
|
|
143
142
|
};
|
|
144
|
-
|
|
143
|
+
"2xl": {
|
|
145
144
|
base: string;
|
|
146
145
|
icon: string;
|
|
147
146
|
};
|
|
148
147
|
};
|
|
149
148
|
color: {
|
|
150
|
-
|
|
149
|
+
default: {
|
|
151
150
|
base: string;
|
|
152
151
|
icon: string;
|
|
153
152
|
};
|
|
154
|
-
|
|
153
|
+
primary: {
|
|
155
154
|
base: string;
|
|
156
155
|
icon: string;
|
|
157
156
|
};
|
|
158
|
-
|
|
157
|
+
secondary: {
|
|
159
158
|
base: string;
|
|
160
159
|
icon: string;
|
|
161
160
|
};
|
|
162
|
-
|
|
161
|
+
success: {
|
|
163
162
|
base: string;
|
|
164
163
|
icon: string;
|
|
165
164
|
};
|
|
166
|
-
|
|
165
|
+
warning: {
|
|
167
166
|
base: string;
|
|
168
167
|
icon: string;
|
|
169
168
|
};
|
|
170
|
-
|
|
169
|
+
danger: {
|
|
171
170
|
base: string;
|
|
172
171
|
icon: string;
|
|
173
172
|
};
|
|
174
|
-
|
|
173
|
+
info: {
|
|
175
174
|
base: string;
|
|
176
175
|
icon: string;
|
|
177
176
|
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { Size } from '../../variants.js';
|
|
7
7
|
import Portal from '../../utils/Portal.svelte';
|
|
8
8
|
import { resolve } from '$app/paths';
|
|
9
|
+
import { buildTestId } from '../../helper/testid.js';
|
|
9
10
|
|
|
10
11
|
let {
|
|
11
12
|
sections = [],
|
|
@@ -19,7 +20,8 @@
|
|
|
19
20
|
disabled = false,
|
|
20
21
|
position = 'bottom-left',
|
|
21
22
|
width = 'w-56',
|
|
22
|
-
header
|
|
23
|
+
header,
|
|
24
|
+
testId
|
|
23
25
|
}: DropdownMenuProps = $props();
|
|
24
26
|
|
|
25
27
|
// Determine if we're in icon-only mode
|
|
@@ -134,6 +136,16 @@
|
|
|
134
136
|
if (item.onclick) item.onclick();
|
|
135
137
|
isOpen = false;
|
|
136
138
|
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Compute cumulative item counts per section so we can derive flat indices.
|
|
142
|
+
*/
|
|
143
|
+
const sectionOffsets = $derived(
|
|
144
|
+
sections.reduce<number[]>((acc, sec, i) => {
|
|
145
|
+
acc.push(i === 0 ? 0 : acc[i - 1] + sections[i - 1].items.length);
|
|
146
|
+
return acc;
|
|
147
|
+
}, [])
|
|
148
|
+
);
|
|
137
149
|
</script>
|
|
138
150
|
|
|
139
151
|
<svelte:window onclick={handleClickOutside} />
|
|
@@ -148,6 +160,7 @@
|
|
|
148
160
|
class={triggerClass_}
|
|
149
161
|
onclick={handleToggle}
|
|
150
162
|
{disabled}
|
|
163
|
+
data-testid={buildTestId('dropdown', 'trigger', testId)}
|
|
151
164
|
>
|
|
152
165
|
{#if label}
|
|
153
166
|
{label}
|
|
@@ -183,6 +196,7 @@
|
|
|
183
196
|
aria-labelledby="menu-button"
|
|
184
197
|
style={dropdownStyles}
|
|
185
198
|
transition:fly={{ duration: 150, y: 5, opacity: 0 }}
|
|
199
|
+
data-testid={buildTestId('dropdown', 'menu', testId)}
|
|
186
200
|
>
|
|
187
201
|
{#if header}
|
|
188
202
|
<button class={headerClass_} onclick={header.onclick} aria-label="Header Actions">
|
|
@@ -202,12 +216,14 @@
|
|
|
202
216
|
{#each sections as section_, sectionIndex (sectionIndex)}
|
|
203
217
|
<div class={sectionClass}>
|
|
204
218
|
{#each section_.items as menuItem, itemIndex (itemIndex)}
|
|
219
|
+
{@const flatIndex = sectionOffsets[sectionIndex] + itemIndex}
|
|
205
220
|
{@const itemProps = {
|
|
206
221
|
class: itemClass_,
|
|
207
222
|
role: 'menuitem',
|
|
208
223
|
tabindex: -1,
|
|
209
224
|
id: `menu-item-${sectionIndex}-${itemIndex}`,
|
|
210
|
-
'data-active': menuItem.active
|
|
225
|
+
'data-active': menuItem.active,
|
|
226
|
+
'data-testid': buildTestId('dropdown', 'item', testId, flatIndex)
|
|
211
227
|
}}
|
|
212
228
|
{#if menuItem.href}
|
|
213
229
|
<a href={resolve(menuItem.href as `/`)} {...itemProps}>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { tick } from 'svelte';
|
|
3
3
|
import { cn } from '../../helper/cls.js';
|
|
4
|
+
import { buildTestId } from '../../helper/testid.js';
|
|
4
5
|
import { selectTV } from './select.js';
|
|
5
6
|
import type { SelectItem, SelectProps } from '../../index.js';
|
|
6
7
|
import Badge from '../badge/Badge.svelte';
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
triggerClass = '', // recently, just now
|
|
26
27
|
onselect = () => {},
|
|
27
28
|
onopen = () => {},
|
|
28
|
-
onclose = () => {}
|
|
29
|
+
onclose = () => {},
|
|
30
|
+
testId
|
|
29
31
|
}: SelectProps = $props();
|
|
30
32
|
|
|
31
33
|
let open = $state(false);
|
|
@@ -34,6 +36,8 @@
|
|
|
34
36
|
let searchInputRef = $state<HTMLInputElement | null>(null);
|
|
35
37
|
let highlightedIndex = $state(-1);
|
|
36
38
|
|
|
39
|
+
const selectId = crypto.randomUUID().slice(0, 8);
|
|
40
|
+
|
|
37
41
|
// Convert value to array for internal processing if multiple is true
|
|
38
42
|
const valueArray = $derived.by(() => {
|
|
39
43
|
if (multiple) {
|
|
@@ -199,8 +203,9 @@
|
|
|
199
203
|
class={triggerClass_}
|
|
200
204
|
aria-disabled={disabled}
|
|
201
205
|
aria-haspopup="listbox"
|
|
202
|
-
aria-labelledby="
|
|
206
|
+
aria-labelledby="{selectId}-label"
|
|
203
207
|
data-state={open ? 'open' : 'closed'}
|
|
208
|
+
data-testid={buildTestId('select', 'trigger', testId)}
|
|
204
209
|
>
|
|
205
210
|
<button
|
|
206
211
|
type="button"
|
|
@@ -219,11 +224,11 @@
|
|
|
219
224
|
</Badge>
|
|
220
225
|
{/each}
|
|
221
226
|
{:else if !multiple && selectedItem}
|
|
222
|
-
<span id="
|
|
227
|
+
<span id="{selectId}-label" class="flex-1 truncate text-left">
|
|
223
228
|
{selectedItem.label}
|
|
224
229
|
</span>
|
|
225
230
|
{:else}
|
|
226
|
-
<span id="
|
|
231
|
+
<span id="{selectId}-label" class="text-default-500 px-1">
|
|
227
232
|
{placeholder}
|
|
228
233
|
</span>
|
|
229
234
|
{/if}
|
|
@@ -251,7 +256,12 @@
|
|
|
251
256
|
|
|
252
257
|
{#if open}
|
|
253
258
|
<Portal target={labelRef}>
|
|
254
|
-
<div
|
|
259
|
+
<div
|
|
260
|
+
class={containerClass_}
|
|
261
|
+
role="listbox"
|
|
262
|
+
aria-labelledby="{selectId}-label"
|
|
263
|
+
data-testid={buildTestId('select', 'list', testId)}
|
|
264
|
+
>
|
|
255
265
|
{#if searchable}
|
|
256
266
|
<div class={searchInputClass_}>
|
|
257
267
|
<svg
|
|
@@ -273,6 +283,7 @@
|
|
|
273
283
|
class="ring-0 outline-0"
|
|
274
284
|
placeholder="Search..."
|
|
275
285
|
aria-label="Search select options"
|
|
286
|
+
data-testid={buildTestId('select', 'search', testId)}
|
|
276
287
|
/>
|
|
277
288
|
</div>
|
|
278
289
|
{/if}
|
|
@@ -296,6 +307,7 @@
|
|
|
296
307
|
data-selected={valueArray.includes(item.value)}
|
|
297
308
|
data-highlighted={index === highlightedIndex}
|
|
298
309
|
data-index={index}
|
|
310
|
+
data-testid={buildTestId('select', 'option', testId, index)}
|
|
299
311
|
>
|
|
300
312
|
<span class="flex w-full items-center justify-between">
|
|
301
313
|
<span class="flex items-center gap-2 overflow-hidden">
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { Component } from 'svelte';
|
|
4
|
+
import type { VariantSizes } from '../../index.js';
|
|
5
|
+
export type DropdownItem = {
|
|
6
|
+
label: string;
|
|
7
|
+
href?: `/${string}`;
|
|
8
|
+
icon?: Component;
|
|
9
|
+
onclick?: () => void;
|
|
10
|
+
active?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type DropSection = {
|
|
13
|
+
items: DropdownItem[];
|
|
14
|
+
};
|
|
15
|
+
export type DropHeaderConfig = {
|
|
16
|
+
title?: string;
|
|
17
|
+
subtitle?: string;
|
|
18
|
+
content?: Snippet<[]>;
|
|
19
|
+
class?: ClassValue;
|
|
20
|
+
titleClass?: ClassValue;
|
|
21
|
+
subtitleClass?: ClassValue;
|
|
22
|
+
onclick?: () => void;
|
|
23
|
+
};
|
|
24
|
+
export type DropdownMenuProps = {
|
|
25
|
+
open?: boolean;
|
|
26
|
+
sections: DropSection[];
|
|
27
|
+
label?: string;
|
|
28
|
+
icon?: Component;
|
|
29
|
+
containerClass?: ClassValue;
|
|
30
|
+
itemClass?: ClassValue;
|
|
31
|
+
class?: ClassValue;
|
|
32
|
+
size?: VariantSizes;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
35
|
+
width?: string;
|
|
36
|
+
header?: DropHeaderConfig;
|
|
37
|
+
testId?: string;
|
|
38
|
+
};
|
|
39
|
+
export type SelectItem = {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
icon?: Component;
|
|
44
|
+
};
|
|
45
|
+
export type SelectProps = {
|
|
46
|
+
items: SelectItem[];
|
|
47
|
+
value?: string | string[];
|
|
48
|
+
multiple?: boolean;
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
searchable?: boolean;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
size?: VariantSizes;
|
|
53
|
+
class?: ClassValue;
|
|
54
|
+
containerClass?: ClassValue;
|
|
55
|
+
listClass?: ClassValue;
|
|
56
|
+
itemClass?: ClassValue;
|
|
57
|
+
triggerClass?: ClassValue;
|
|
58
|
+
searchInputClass?: ClassValue;
|
|
59
|
+
clearable?: boolean;
|
|
60
|
+
icon?: Component;
|
|
61
|
+
iconClass?: ClassValue;
|
|
62
|
+
onselect?: ({ value }: {
|
|
63
|
+
value: string | string[];
|
|
64
|
+
}) => void;
|
|
65
|
+
onopen?: () => void;
|
|
66
|
+
onclose?: () => void;
|
|
67
|
+
testId?: string;
|
|
68
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|