@reshape-biotech/design-system 1.2.5 → 1.2.7
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 +3 -1
- package/dist/app.css +97 -97
- package/dist/components/activity/Activity.stories.svelte +104 -104
- package/dist/components/activity/Activity.svelte +112 -112
- package/dist/components/avatar/Avatar.stories.svelte +23 -23
- package/dist/components/avatar/Avatar.svelte +54 -54
- package/dist/components/banner/Banner.stories.svelte +105 -105
- package/dist/components/banner/Banner.svelte +42 -42
- package/dist/components/button/Button.stories.svelte +61 -61
- package/dist/components/button/Button.svelte +95 -95
- package/dist/components/card/Card.stories.svelte +112 -112
- package/dist/components/card/Card.svelte +18 -18
- package/dist/components/checkbox/Checkbox.stories.svelte +8 -8
- package/dist/components/checkbox/Checkbox.svelte +17 -17
- package/dist/components/collapsible/Collapsible.stories.svelte +26 -26
- package/dist/components/collapsible/components/collapsible-content.svelte +20 -20
- package/dist/components/collapsible/components/collapsible-trigger.svelte +12 -12
- package/dist/components/combobox/Combobox.stories.svelte +412 -412
- package/dist/components/combobox/components/combobox-add.svelte +8 -8
- package/dist/components/combobox/components/combobox-content.svelte +39 -39
- package/dist/components/combobox/components/combobox-indicator.svelte +1 -1
- package/dist/components/datepicker/DatePicker.stories.svelte +196 -196
- package/dist/components/datepicker/DatePicker.svelte +173 -173
- package/dist/components/divider/Divider.stories.svelte +7 -7
- package/dist/components/divider/Divider.svelte +9 -9
- package/dist/components/drawer/Drawer.stories.svelte +51 -51
- package/dist/components/drawer/Drawer.svelte +33 -33
- package/dist/components/drawer/DrawerLabel.svelte +10 -10
- package/dist/components/dropdown/Dropdown.stories.svelte +210 -210
- package/dist/components/dropdown/Dropdown.svelte +57 -57
- package/dist/components/dropdown/components/DropdownContent.svelte +16 -16
- package/dist/components/dropdown/components/DropdownMenu.svelte +10 -10
- package/dist/components/dropdown/components/DropdownTrigger.svelte +37 -37
- package/dist/components/dropdown/components/OutlinedButton.svelte +9 -9
- package/dist/components/empty-content/EmptyContent.stories.svelte +38 -38
- package/dist/components/empty-content/EmptyContent.svelte +12 -12
- package/dist/components/graphs/bar-chart/BarChart.stories.svelte +91 -91
- package/dist/components/graphs/bar-chart/BarChart.svelte +147 -147
- package/dist/components/graphs/bar-chart/StackedBarChart.stories.svelte +57 -57
- package/dist/components/graphs/bar-chart/StackedBarChart.svelte +198 -199
- package/dist/components/graphs/chart/Chart.stories.svelte +96 -96
- package/dist/components/graphs/chart/Chart.svelte +207 -207
- package/dist/components/graphs/line/LineChart.stories.svelte +138 -138
- package/dist/components/graphs/line/LineChart.svelte +140 -142
- package/dist/components/graphs/matrix/Matrix.stories.svelte +117 -117
- package/dist/components/graphs/matrix/Matrix.svelte +141 -141
- package/dist/components/graphs/multiline/MultiLineChart.stories.svelte +168 -168
- package/dist/components/graphs/multiline/MultiLineChart.svelte +236 -236
- package/dist/components/graphs/scatterplot/Scatterplot.stories.svelte +84 -84
- package/dist/components/graphs/scatterplot/Scatterplot.svelte +302 -302
- package/dist/components/graphs/utils/duration.d.ts +1 -0
- package/dist/components/graphs/utils/duration.js +33 -0
- package/dist/components/graphs/utils/tooltipFormatter.js +1 -1
- package/dist/components/icon-button/IconButton.stories.svelte +64 -64
- package/dist/components/icon-button/IconButton.svelte +88 -88
- package/dist/components/icons/AnalysisIcon.stories.svelte +18 -18
- package/dist/components/icons/AnalysisIcon.svelte +96 -96
- package/dist/components/icons/Icon.stories.svelte +111 -111
- package/dist/components/icons/Icon.svelte +17 -17
- package/dist/components/icons/PrincipalIcon.svelte +59 -59
- package/dist/components/icons/custom/Halo.svelte +31 -31
- package/dist/components/icons/custom/Well.svelte +27 -27
- package/dist/components/icons/index.d.ts +3 -2
- package/dist/components/icons/index.js +3 -1
- package/dist/components/image/Image.svelte +42 -42
- package/dist/components/input/Input.stories.svelte +55 -55
- package/dist/components/input/Input.svelte +121 -121
- package/dist/components/label/Label.stories.svelte +18 -18
- package/dist/components/label/Label.svelte +11 -11
- package/dist/components/list/List.stories.svelte +84 -84
- package/dist/components/list/List.svelte +20 -20
- package/dist/components/logo/Logo.stories.svelte +15 -15
- package/dist/components/logo/Logo.svelte +30 -30
- package/dist/components/manual-cfu-counter/ManualCFUCounter.stories.svelte +102 -102
- package/dist/components/manual-cfu-counter/ManualCFUCounter.svelte +557 -565
- package/dist/components/manual-cfu-counter/test/ManualCFUCounterTestWrapper.svelte +11 -11
- package/dist/components/markdown/Markdown.stories.svelte +10 -10
- package/dist/components/markdown/Markdown.svelte +6 -6
- package/dist/components/modal/Modal.stories.svelte +29 -29
- package/dist/components/modal/Modal.svelte +71 -71
- package/dist/components/multi-cfu-counter/MultiCFUCounter.stories.svelte +215 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.stories.svelte.d.ts +3 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.svelte +662 -0
- package/dist/components/multi-cfu-counter/MultiCFUCounter.svelte.d.ts +32 -0
- package/dist/components/multi-cfu-counter/index.d.ts +1 -0
- package/dist/components/multi-cfu-counter/index.js +1 -0
- package/dist/components/multi-cfu-counter/test/MultiCFUCounterTestWrapper.svelte +28 -0
- package/dist/components/multi-cfu-counter/test/MultiCFUCounterTestWrapper.svelte.d.ts +20 -0
- package/dist/components/notification-popup/NotificationPopup.stories.svelte +18 -18
- package/dist/components/notification-popup/NotificationPopup.svelte +26 -26
- package/dist/components/notifications/Notifications.stories.svelte +101 -101
- package/dist/components/notifications/Notifications.svelte +9 -9
- package/dist/components/pill/Pill.stories.svelte +8 -8
- package/dist/components/pill/Pill.svelte +27 -27
- package/dist/components/progress-circle/ProgressCircle.stories.svelte +8 -8
- package/dist/components/progress-circle/ProgressCircle.svelte +54 -54
- package/dist/components/required-status-indicator/RequiredStatusIndicator.stories.svelte +18 -18
- package/dist/components/required-status-indicator/RequiredStatusIndicator.svelte +14 -14
- package/dist/components/segmented-control-buttons/ControlButton.svelte +36 -36
- package/dist/components/segmented-control-buttons/SegmentedControlButtons.stories.svelte +35 -35
- package/dist/components/segmented-control-buttons/SegmentedControlButtons.svelte +13 -13
- package/dist/components/select/Select.stories.svelte +77 -77
- package/dist/components/select/Select.svelte +114 -114
- package/dist/components/select-new/Select.stories.svelte +188 -188
- package/dist/components/select-new/components/Group.svelte +17 -17
- package/dist/components/select-new/components/MultiSelectTrigger.svelte +57 -57
- package/dist/components/select-new/components/SelectContent.svelte +22 -22
- package/dist/components/select-new/components/SelectGroupHeading.svelte +10 -10
- package/dist/components/select-new/components/SelectItem.svelte +25 -25
- package/dist/components/select-new/components/SelectTrigger.svelte +38 -38
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte +76 -76
- package/dist/components/sjsf-wrappers/SjsfNumberInputWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte +53 -53
- package/dist/components/sjsf-wrappers/SjsfTextInputWrapper.svelte.d.ts +1 -1
- package/dist/components/sjsf-wrappers/sjsfCustomTheme.js +1 -1
- package/dist/components/skeleton-loader/SkeletonLoader.stories.svelte +32 -32
- package/dist/components/skeleton-loader/SkeletonLoader.svelte +10 -10
- package/dist/components/skeleton-loader/StatcardSkeleton.svelte +9 -9
- package/dist/components/skeleton-loader/components/Skeleton.svelte +7 -7
- package/dist/components/skeleton-loader/components/SkeletonImage.svelte +12 -12
- package/dist/components/slider/Slider.stories.svelte +23 -23
- package/dist/components/slider/Slider.svelte +107 -107
- package/dist/components/spinner/Spinner.stories.svelte +8 -8
- package/dist/components/spinner/Spinner.svelte +18 -18
- package/dist/components/stat-card/StatCard.stories.svelte +26 -26
- package/dist/components/stat-card/StatCard.svelte +128 -128
- package/dist/components/status-badge/StatusBadge.stories.svelte +365 -365
- package/dist/components/status-badge/StatusBadge.svelte +54 -54
- package/dist/components/stepper/Stepper.stories.svelte +219 -219
- package/dist/components/stepper/components/stepper-root.svelte +12 -12
- package/dist/components/stepper/components/stepper-step.svelte +83 -83
- package/dist/components/table/Table.stories.svelte +87 -87
- package/dist/components/table/Table.svelte +32 -32
- package/dist/components/table/components/TBody.svelte +7 -7
- package/dist/components/table/components/THead.svelte +7 -7
- package/dist/components/table/components/Td.svelte +8 -8
- package/dist/components/table/components/Th.svelte +8 -8
- package/dist/components/table/components/Tr.svelte +11 -11
- package/dist/components/tabs/Tabs.stories.svelte +20 -20
- package/dist/components/tabs/Tabs.svelte +8 -8
- package/dist/components/tabs/components/Content.svelte +8 -8
- package/dist/components/tabs/components/Tab.svelte +14 -14
- package/dist/components/tabs/components/Tabs.svelte +7 -7
- package/dist/components/tag/Tag.stories.svelte +57 -57
- package/dist/components/tag/Tag.svelte +95 -95
- package/dist/components/textarea/Textarea.stories.svelte +70 -70
- package/dist/components/textarea/Textarea.svelte +76 -76
- package/dist/components/toast/Toast.stories.svelte +204 -204
- package/dist/components/toast/Toast.svelte +53 -53
- package/dist/components/toggle/Toggle.stories.svelte +9 -9
- package/dist/components/toggle/Toggle.svelte +53 -53
- package/dist/components/toggle-icon-button/ToggleIconButton.stories.svelte +152 -152
- package/dist/components/toggle-icon-button/ToggleIconButton.svelte +99 -99
- package/dist/components/tooltip/Tooltip.stories.svelte +105 -105
- package/dist/components/tooltip/Tooltip.svelte +26 -26
- package/dist/fonts/index.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -1
- package/dist/notifications.d.ts +1 -4
- package/dist/notifications.js +1 -1
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +4 -0
- package/dist/tailwind-safelist.js +406 -398
- package/dist/tailwind.preset.d.ts +4 -0
- package/dist/tailwind.preset.js +10 -10
- package/dist/tokens/colors.d.ts +246 -0
- package/dist/tokens/colors.js +139 -0
- package/dist/tokens/index.d.ts +3 -0
- package/dist/tokens/index.js +5 -0
- package/dist/tokens/typography.d.ts +48 -0
- package/dist/tokens/typography.js +48 -0
- package/dist/tokens.d.ts +16 -252
- package/dist/tokens.js +33 -164
- package/dist/types/fonts.d.ts +2 -2
- package/package.json +398 -78
|
@@ -1,442 +1,442 @@
|
|
|
1
1
|
<script module 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
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import { userEvent, within } from '@storybook/test';
|
|
4
|
+
import { Root as ComboboxRootForMeta } from './index';
|
|
5
|
+
import * as Combobox from './index';
|
|
6
|
+
import { Icon } from '../icons';
|
|
7
|
+
import IconButton from '../icon-button/IconButton.svelte';
|
|
8
|
+
import Divider from '../divider/Divider.svelte';
|
|
9
|
+
import Tag from '../tag/Tag.svelte';
|
|
10
|
+
import Button from '../button/Button.svelte';
|
|
11
|
+
|
|
12
|
+
const { Story } = defineMeta({
|
|
13
|
+
component: ComboboxRootForMeta,
|
|
14
|
+
title: 'Design System/Combobox',
|
|
15
|
+
tags: ['autodocs'],
|
|
16
|
+
parameters: {
|
|
17
|
+
design: {
|
|
18
|
+
type: 'figma',
|
|
19
|
+
url: 'https://www.figma.com/design/VHTMNdy8PAXAMx43edNZGW/%F0%9F%92%A0--Reshape-Design-System%3A-V1?node-id=9-3294&t=sCuBI8dX6K6NjNR6-0',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const fruits = [
|
|
25
|
+
{ value: 'mango', label: 'Mango' },
|
|
26
|
+
{ value: 'watermelon', label: 'Watermelon' },
|
|
27
|
+
{ value: 'apple', label: 'Apple' },
|
|
28
|
+
{ value: 'pineapple', label: 'Pineapple' },
|
|
29
|
+
{ value: 'orange', label: 'Orange' },
|
|
30
|
+
{ value: 'grape', label: 'Grape' },
|
|
31
|
+
{ value: 'strawberry', label: 'Strawberry' },
|
|
32
|
+
{ value: 'banana', label: 'Banana' },
|
|
33
|
+
{ value: 'kiwi', label: 'Kiwi' },
|
|
34
|
+
{ value: 'peach', label: 'Peach' },
|
|
35
|
+
{ value: 'cherry', label: 'Cherry' },
|
|
36
|
+
{ value: 'blueberry', label: 'Blueberry' },
|
|
37
|
+
{ value: 'raspberry', label: 'Raspberry' },
|
|
38
|
+
{ value: 'blackberry', label: 'Blackberry' },
|
|
39
|
+
{ value: 'plum', label: 'Plum' },
|
|
40
|
+
{ value: 'apricot', label: 'Apricot' },
|
|
41
|
+
{ value: 'pear', label: 'Pear' },
|
|
42
|
+
{ value: 'grapefruit', label: 'Grapefruit' },
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const categories = [
|
|
46
|
+
{ value: 'citrus', label: 'Citrus', items: ['orange', 'grapefruit', 'lemon'] },
|
|
47
|
+
{
|
|
48
|
+
value: 'berries',
|
|
49
|
+
label: 'Berries',
|
|
50
|
+
items: ['strawberry', 'blueberry', 'raspberry', 'blackberry'],
|
|
51
|
+
},
|
|
52
|
+
{ value: 'tropical', label: 'Tropical', items: ['mango', 'pineapple', 'banana', 'kiwi'] },
|
|
53
|
+
{ value: 'stone', label: 'Stone Fruits', items: ['peach', 'cherry', 'plum', 'apricot'] },
|
|
54
|
+
{ value: 'other', label: 'Other', items: ['apple', 'pear', 'watermelon', 'grape'] },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
let searchValue = $state('');
|
|
58
|
+
let searchValueSingle = $state('');
|
|
59
|
+
let searchValueGrouped = $state('');
|
|
60
|
+
let searchValueCustom = $state('');
|
|
61
|
+
|
|
62
|
+
let selected = $state<string[]>([]);
|
|
63
|
+
let selectedSingle = $state<string>('');
|
|
64
|
+
let selectedGrouped = $state<string[]>([]);
|
|
65
|
+
let selectedCustom = $state<string[]>([]);
|
|
66
|
+
|
|
67
|
+
const filteredFruits = $derived(
|
|
68
|
+
searchValue === ''
|
|
69
|
+
? fruits
|
|
70
|
+
: fruits.filter((fruit) => fruit.label.toLowerCase().includes(searchValue.toLowerCase()))
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const filteredFruitsSingle = $derived(
|
|
74
|
+
searchValueSingle === ''
|
|
75
|
+
? fruits
|
|
76
|
+
: fruits.filter((fruit) =>
|
|
77
|
+
fruit.label.toLowerCase().includes(searchValueSingle.toLowerCase())
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const filteredFruitsGrouped = $derived(
|
|
82
|
+
searchValueGrouped === ''
|
|
83
|
+
? fruits
|
|
84
|
+
: fruits.filter((fruit) =>
|
|
85
|
+
fruit.label.toLowerCase().includes(searchValueGrouped.toLowerCase())
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const filteredFruitsCustom = $derived(
|
|
90
|
+
searchValueCustom === ''
|
|
91
|
+
? fruits
|
|
92
|
+
: fruits.filter((fruit) =>
|
|
93
|
+
fruit.label.toLowerCase().includes(searchValueCustom.toLowerCase())
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const exactMatch = $derived(
|
|
98
|
+
filteredFruits.find((fruit) => fruit.value.toLowerCase() === searchValue.toLowerCase())
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const exactMatchCustom = $derived(
|
|
102
|
+
filteredFruitsCustom.find(
|
|
103
|
+
(fruit) => fruit.value.toLowerCase() === searchValueCustom.toLowerCase()
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
let customAnchor = $state<HTMLElement>(null!);
|
|
108
|
+
let customAnchorButton = $state<HTMLElement>(null!);
|
|
109
|
+
let customAnchorSingle = $state<HTMLElement>(null!);
|
|
110
|
+
let customAnchorGrouped = $state<HTMLElement>(null!);
|
|
111
|
+
let customAnchorCustom = $state<HTMLElement>(null!);
|
|
112
112
|
</script>
|
|
113
113
|
|
|
114
114
|
<Story name="Multiple Selection" asChild>
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
115
|
+
<Combobox.Root
|
|
116
|
+
onOpenChange={(o) => {
|
|
117
|
+
if (!o) searchValue = '';
|
|
118
|
+
}}
|
|
119
|
+
type="multiple"
|
|
120
|
+
name="favoriteFruit"
|
|
121
|
+
items={filteredFruits}
|
|
122
|
+
bind:value={selected}
|
|
123
|
+
>
|
|
124
|
+
<div class="flex gap-2">
|
|
125
|
+
{#each selected as fruit}
|
|
126
|
+
<Tag>
|
|
127
|
+
{fruit}
|
|
128
|
+
</Tag>
|
|
129
|
+
{/each}
|
|
130
|
+
</div>
|
|
131
|
+
<Combobox.Trigger>
|
|
132
|
+
<div bind:this={customAnchor}>
|
|
133
|
+
<IconButton rounded={false}>
|
|
134
|
+
<Icon iconName="Plus" />
|
|
135
|
+
</IconButton>
|
|
136
|
+
</div>
|
|
137
|
+
</Combobox.Trigger>
|
|
138
|
+
<Combobox.Content {customAnchor} class="flex flex-col justify-between">
|
|
139
|
+
<div>
|
|
140
|
+
<Combobox.Input
|
|
141
|
+
placeholder="Search a fruit"
|
|
142
|
+
oninput={(e: Event) => (searchValue = (e.target as HTMLInputElement).value)}
|
|
143
|
+
autofocus
|
|
144
|
+
/>
|
|
145
|
+
<Divider />
|
|
146
|
+
</div>
|
|
147
|
+
<div class="flex flex-grow flex-col">
|
|
148
|
+
{#if filteredFruits.length > 0}
|
|
149
|
+
<Combobox.Group>
|
|
150
|
+
<Combobox.GroupHeading>Fruits</Combobox.GroupHeading>
|
|
151
|
+
{#each filteredFruits as fruit (fruit.value)}
|
|
152
|
+
<Combobox.Item value={fruit.value} label={fruit.label}>
|
|
153
|
+
{#snippet children({ selected })}
|
|
154
|
+
{fruit.label}
|
|
155
|
+
{#if selected}
|
|
156
|
+
<Combobox.Indicator />
|
|
157
|
+
{/if}
|
|
158
|
+
{/snippet}
|
|
159
|
+
</Combobox.Item>
|
|
160
|
+
{:else}
|
|
161
|
+
<span class="block px-5 py-2 text-sm text-muted-foreground"> No results found </span>
|
|
162
|
+
{/each}
|
|
163
|
+
</Combobox.Group>
|
|
164
|
+
{/if}
|
|
165
|
+
</div>
|
|
166
|
+
{#if !exactMatch && searchValue !== ''}
|
|
167
|
+
<Divider />
|
|
168
|
+
|
|
169
|
+
<Combobox.Add
|
|
170
|
+
onclick={() => {
|
|
171
|
+
selected.push(searchValue);
|
|
172
|
+
fruits.push({ value: searchValue, label: searchValue });
|
|
173
|
+
searchValue = '';
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
<p>Add new fruit</p>
|
|
177
|
+
</Combobox.Add>
|
|
178
|
+
{/if}
|
|
179
|
+
</Combobox.Content>
|
|
180
|
+
</Combobox.Root>
|
|
181
181
|
</Story>
|
|
182
182
|
|
|
183
183
|
<Story name="Single Selection" asChild>
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
184
|
+
<Combobox.Root
|
|
185
|
+
onOpenChange={(o) => {
|
|
186
|
+
if (!o) searchValueSingle = '';
|
|
187
|
+
}}
|
|
188
|
+
type="single"
|
|
189
|
+
name="singleFruit"
|
|
190
|
+
items={filteredFruitsSingle}
|
|
191
|
+
bind:value={selectedSingle}
|
|
192
|
+
>
|
|
193
|
+
<Combobox.Trigger>
|
|
194
|
+
<div bind:this={customAnchorSingle}>
|
|
195
|
+
<Button variant="secondary" size="sm">
|
|
196
|
+
{selectedSingle ? selectedSingle : 'Select a fruit'}
|
|
197
|
+
</Button>
|
|
198
|
+
</div>
|
|
199
|
+
</Combobox.Trigger>
|
|
200
|
+
<Combobox.Content class="flex flex-col justify-between" customAnchor={customAnchorSingle}>
|
|
201
|
+
<div class="flex flex-grow flex-col">
|
|
202
|
+
{#if filteredFruitsSingle.length > 0}
|
|
203
|
+
<Combobox.Group>
|
|
204
|
+
<Combobox.GroupHeading>Fruits</Combobox.GroupHeading>
|
|
205
|
+
{#each filteredFruitsSingle as fruit (fruit.value)}
|
|
206
|
+
<Combobox.Item value={fruit.value} label={fruit.label}>
|
|
207
|
+
{#snippet children({ selected })}
|
|
208
|
+
{fruit.label}
|
|
209
|
+
{#if selected}
|
|
210
|
+
<Combobox.Indicator />
|
|
211
|
+
{/if}
|
|
212
|
+
{/snippet}
|
|
213
|
+
</Combobox.Item>
|
|
214
|
+
{:else}
|
|
215
|
+
<span class="block px-5 py-2 text-sm text-muted-foreground"> No results found </span>
|
|
216
|
+
{/each}
|
|
217
|
+
</Combobox.Group>
|
|
218
|
+
{/if}
|
|
219
|
+
</div>
|
|
220
|
+
</Combobox.Content>
|
|
221
|
+
</Combobox.Root>
|
|
222
222
|
</Story>
|
|
223
223
|
|
|
224
224
|
<Story name="Grouped Items" asChild>
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
225
|
+
<Combobox.Root
|
|
226
|
+
onOpenChange={(o) => {
|
|
227
|
+
if (!o) searchValueGrouped = '';
|
|
228
|
+
}}
|
|
229
|
+
type="multiple"
|
|
230
|
+
name="groupedFruits"
|
|
231
|
+
items={filteredFruitsGrouped}
|
|
232
|
+
bind:value={selectedGrouped}
|
|
233
|
+
>
|
|
234
|
+
<div class="flex flex-wrap gap-2">
|
|
235
|
+
{#each selectedGrouped as fruit}
|
|
236
|
+
<Tag>
|
|
237
|
+
{fruit}
|
|
238
|
+
</Tag>
|
|
239
|
+
{/each}
|
|
240
|
+
</div>
|
|
241
|
+
<Combobox.Trigger>
|
|
242
|
+
<div bind:this={customAnchorGrouped}>
|
|
243
|
+
<Button variant="primary" size="sm">
|
|
244
|
+
<Icon iconName="List" />
|
|
245
|
+
Select fruits by category
|
|
246
|
+
</Button>
|
|
247
|
+
</div>
|
|
248
|
+
</Combobox.Trigger>
|
|
249
|
+
<Combobox.Content class="flex flex-col justify-between" customAnchor={customAnchorGrouped}>
|
|
250
|
+
<div>
|
|
251
|
+
<Combobox.Input
|
|
252
|
+
placeholder="Search across categories"
|
|
253
|
+
oninput={(e: Event) => (searchValueGrouped = (e.target as HTMLInputElement).value)}
|
|
254
|
+
autofocus
|
|
255
|
+
/>
|
|
256
|
+
<Divider />
|
|
257
|
+
</div>
|
|
258
|
+
<div class="flex max-h-80 flex-grow flex-col overflow-y-auto">
|
|
259
|
+
{#if searchValueGrouped === ''}
|
|
260
|
+
{#each categories as category}
|
|
261
|
+
<Combobox.Group>
|
|
262
|
+
<Combobox.GroupHeading>{category.label}</Combobox.GroupHeading>
|
|
263
|
+
{#each category.items as item}
|
|
264
|
+
{@const fruit = fruits.find((f) => f.value === item)}
|
|
265
|
+
{#if fruit}
|
|
266
|
+
<Combobox.Item value={fruit.value} label={fruit.label}>
|
|
267
|
+
{#snippet children({ selected })}
|
|
268
|
+
{fruit.label}
|
|
269
|
+
{#if selected}
|
|
270
|
+
<Combobox.Indicator />
|
|
271
|
+
{/if}
|
|
272
|
+
{/snippet}
|
|
273
|
+
</Combobox.Item>
|
|
274
|
+
{/if}
|
|
275
|
+
{/each}
|
|
276
|
+
</Combobox.Group>
|
|
277
|
+
{/each}
|
|
278
|
+
{:else if filteredFruitsGrouped.length > 0}
|
|
279
|
+
<Combobox.Group>
|
|
280
|
+
<Combobox.GroupHeading>Search Results</Combobox.GroupHeading>
|
|
281
|
+
{#each filteredFruitsGrouped as fruit (fruit.value)}
|
|
282
|
+
<Combobox.Item value={fruit.value} label={fruit.label}>
|
|
283
|
+
{#snippet children({ selected })}
|
|
284
|
+
{fruit.label}
|
|
285
|
+
{#if selected}
|
|
286
|
+
<Combobox.Indicator />
|
|
287
|
+
{/if}
|
|
288
|
+
{/snippet}
|
|
289
|
+
</Combobox.Item>
|
|
290
|
+
{/each}
|
|
291
|
+
</Combobox.Group>
|
|
292
|
+
{:else}
|
|
293
|
+
<span class="text-muted-foreground block px-5 py-2 text-sm"> No results found </span>
|
|
294
|
+
{/if}
|
|
295
|
+
</div>
|
|
296
|
+
</Combobox.Content>
|
|
297
|
+
</Combobox.Root>
|
|
298
298
|
</Story>
|
|
299
299
|
|
|
300
300
|
<Story
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
301
|
+
name="Interaction Test"
|
|
302
|
+
asChild
|
|
303
|
+
play={async ({ canvasElement }) => {
|
|
304
|
+
// Get the canvas element
|
|
305
|
+
const canvas = within(canvasElement);
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
307
|
+
// Find and click the trigger button to open the combobox
|
|
308
|
+
const triggerButton = canvas.getByTestId('combobox-trigger');
|
|
309
|
+
await userEvent.click(triggerButton);
|
|
310
310
|
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
// Wait for the combobox content to appear in the document
|
|
312
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
313
313
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
314
|
+
// Find the combobox content in the document
|
|
315
|
+
const comboboxContent = document.querySelector(
|
|
316
|
+
'[data-testid="combobox-content"]'
|
|
317
|
+
) as HTMLElement;
|
|
318
|
+
if (!comboboxContent) {
|
|
319
|
+
console.log('Combobox content not found');
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
322
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
// Use within to scope queries to the combobox content
|
|
324
|
+
const contentScope = within(comboboxContent);
|
|
325
|
+
const searchInput = contentScope.getByTestId('combobox-input');
|
|
326
326
|
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
// Type "berry" in the search input
|
|
328
|
+
await userEvent.type(searchInput, 'berry');
|
|
329
329
|
|
|
330
|
-
|
|
331
|
-
|
|
330
|
+
// Wait for the filtering to complete
|
|
331
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
332
332
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
333
|
+
// Find and click on the Strawberry option
|
|
334
|
+
const strawberryOption = contentScope.getByText('Strawberry');
|
|
335
|
+
await userEvent.click(strawberryOption);
|
|
336
336
|
|
|
337
|
-
|
|
337
|
+
// Wait for selection to be processed
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
// Open the combobox again
|
|
340
340
|
|
|
341
|
-
|
|
341
|
+
// Get the search input again
|
|
342
342
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
343
|
+
// Clear the previous search and type "mango"
|
|
344
|
+
await userEvent.clear(searchInput);
|
|
345
|
+
await userEvent.type(searchInput, 'mango');
|
|
346
346
|
|
|
347
|
-
|
|
348
|
-
|
|
347
|
+
// Wait for filtering to complete
|
|
348
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
349
349
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
350
|
+
// Find and click on the Mango option
|
|
351
|
+
const mangoOption = contentScope.getByText('Mango');
|
|
352
|
+
await userEvent.click(mangoOption);
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
await userEvent.keyboard('{Escape}');
|
|
355
355
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
356
|
+
// Test complete
|
|
357
|
+
console.log('Successfully selected Strawberry and Mango');
|
|
358
|
+
}}
|
|
359
359
|
>
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
360
|
+
<div data-testid="combobox-container">
|
|
361
|
+
<Combobox.Root
|
|
362
|
+
onOpenChange={(o) => {
|
|
363
|
+
if (!o) searchValue = '';
|
|
364
|
+
}}
|
|
365
|
+
type="multiple"
|
|
366
|
+
name="favoriteFruit"
|
|
367
|
+
items={filteredFruits}
|
|
368
|
+
bind:value={selected}
|
|
369
|
+
>
|
|
370
|
+
<div class="flex gap-2" data-testid="selected-tags">
|
|
371
|
+
{#each selected as fruit}
|
|
372
|
+
<Tag>
|
|
373
|
+
<div data-value={fruit}>
|
|
374
|
+
{fruit}
|
|
375
|
+
</div>
|
|
376
|
+
</Tag>
|
|
377
|
+
{/each}
|
|
378
|
+
</div>
|
|
379
|
+
<Combobox.Trigger data-testid="combobox-trigger">
|
|
380
|
+
<div bind:this={customAnchor}>
|
|
381
|
+
<IconButton rounded={false}>
|
|
382
|
+
<Icon iconName="Plus" />
|
|
383
|
+
</IconButton>
|
|
384
|
+
</div>
|
|
385
|
+
</Combobox.Trigger>
|
|
386
|
+
<Combobox.Content
|
|
387
|
+
{customAnchor}
|
|
388
|
+
class="flex flex-col justify-between"
|
|
389
|
+
data-testid="combobox-content"
|
|
390
|
+
>
|
|
391
|
+
<div>
|
|
392
|
+
<Combobox.Input
|
|
393
|
+
placeholder="Search a fruit"
|
|
394
|
+
oninput={(e: Event) => (searchValue = (e.target as HTMLInputElement).value)}
|
|
395
|
+
autofocus
|
|
396
|
+
data-testid="combobox-input"
|
|
397
|
+
/>
|
|
398
|
+
<Divider />
|
|
399
|
+
</div>
|
|
400
|
+
<div class="flex flex-grow flex-col">
|
|
401
|
+
{#if filteredFruits.length > 0}
|
|
402
|
+
<Combobox.Group>
|
|
403
|
+
<Combobox.GroupHeading>Fruits</Combobox.GroupHeading>
|
|
404
|
+
{#each filteredFruits as fruit (fruit.value)}
|
|
405
|
+
<Combobox.Item
|
|
406
|
+
value={fruit.value}
|
|
407
|
+
label={fruit.label}
|
|
408
|
+
data-testid={`fruit-option-${fruit.value}`}
|
|
409
|
+
>
|
|
410
|
+
{#snippet children({ selected })}
|
|
411
|
+
{fruit.label}
|
|
412
|
+
{#if selected}
|
|
413
|
+
<Combobox.Indicator />
|
|
414
|
+
{/if}
|
|
415
|
+
{/snippet}
|
|
416
|
+
</Combobox.Item>
|
|
417
|
+
{:else}
|
|
418
|
+
<span class="block px-5 py-2 text-sm text-muted-foreground">
|
|
419
|
+
No results found
|
|
420
|
+
</span>
|
|
421
|
+
{/each}
|
|
422
|
+
</Combobox.Group>
|
|
423
|
+
{/if}
|
|
424
|
+
</div>
|
|
425
|
+
{#if !exactMatch && searchValue !== ''}
|
|
426
|
+
<Divider />
|
|
427
|
+
|
|
428
|
+
<Combobox.Add
|
|
429
|
+
data-testid="add-new-fruit"
|
|
430
|
+
onclick={() => {
|
|
431
|
+
selected.push(searchValue);
|
|
432
|
+
fruits.push({ value: searchValue, label: searchValue });
|
|
433
|
+
searchValue = '';
|
|
434
|
+
}}
|
|
435
|
+
>
|
|
436
|
+
<p>Add new fruit</p>
|
|
437
|
+
</Combobox.Add>
|
|
438
|
+
{/if}
|
|
439
|
+
</Combobox.Content>
|
|
440
|
+
</Combobox.Root>
|
|
441
|
+
</div>
|
|
442
442
|
</Story>
|