@swr-data-lab/components 1.6.0 → 1.8.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/.storybook/main.ts +13 -16
- package/.storybook/preview.ts +3 -0
- package/.storybook/vitest.setup.ts +9 -0
- package/package.json +8 -5
- package/src/Autocomplete/Autocomplete.stories.svelte +61 -0
- package/src/Autocomplete/Autocomplete.svelte +9 -7
- package/src/Button/Button.svelte +14 -10
- package/src/Card/Card.stories.svelte +5 -20
- package/src/Card/Card.svelte +17 -4
- package/src/ChartFooter/ChartFooter.mdx +17 -0
- package/src/ChartFooter/ChartFooter.stories.svelte +12 -20
- package/src/ChartFooter/ChartFooter.svelte +30 -22
- package/src/ChartHeader/ChartHeader.mdx +15 -0
- package/src/ChartHeader/ChartHeader.stories.svelte +14 -11
- package/src/ChartHeader/ChartHeader.svelte +19 -13
- package/src/DesignTokens/DesignTokens.mdx +15 -9
- package/src/DesignTokens/DesignTokens.svelte +2 -1
- package/src/DesignTokens/index.js +8 -1
- package/src/HighlightCard/HighlightCard.stories.svelte +5 -20
- package/src/HighlightCard/HighlightCard.svelte +15 -11
- package/src/Input/Input.svelte +1 -1
- package/src/Intro.mdx +2 -2
- package/src/Logotype/Logotype.stories.svelte +16 -0
- package/src/Logotype/Logotype.svelte +1 -0
- package/src/Middot/Middot.stories.svelte +16 -0
- package/src/Select/Select.mdx +25 -0
- package/src/Select/Select.stories.svelte +87 -147
- package/src/Select/Select.svelte +65 -73
- package/src/Select/Select.types.ts +8 -0
- package/src/Select/SelectStoriesTemplate.svelte +35 -0
- package/src/Switcher/Switcher.mdx +13 -0
- package/src/Switcher/Switcher.stories.svelte +29 -41
- package/src/Switcher/Switcher.svelte +58 -51
- package/src/index.js +1 -0
- package/src/styles/base.scss +52 -5
- package/vitest.workspace.ts +32 -0
- package/src/Autocomplete/Autocomplete.stories.js +0 -61
- package/src/Container/Container.svelte +0 -12
- package/src/Container/index.js +0 -2
- package/src/styles/_typography.scss +0 -49
- package/src/styles/_vars.scss +0 -30
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
'display: contents',
|
|
17
17
|
'--fast: 150ms',
|
|
18
18
|
'--slow: 300ms',
|
|
19
|
+
'--app-max-width: 40rem',
|
|
19
20
|
'--br-large: 8px',
|
|
20
21
|
'--br-small: 4px',
|
|
21
|
-
'--ratio: 1.15',
|
|
22
22
|
'--input-height: 2.5rem',
|
|
23
23
|
'--swr-sans: "SWR-VAR-Sans", sans-serif',
|
|
24
24
|
'--swr-text: "SWR-VAR-Text", sans-serif',
|
|
25
|
+
'--ratio: 1.15',
|
|
25
26
|
'--fs-small-3: calc(var(--fs-small-2) / var(--ratio))',
|
|
26
27
|
'--fs-small-2: calc(var(--fs-small-1) / var(--ratio))',
|
|
27
28
|
'--fs-small-1: calc(var(--fs-base) / var(--ratio))',
|
|
@@ -1,26 +1,12 @@
|
|
|
1
|
-
<script context="module">
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
2
3
|
import HighlightCard from './HighlightCard.svelte';
|
|
3
4
|
import DesignTokens from '../DesignTokens/DesignTokens.svelte';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
title: '
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: 'Display/Card/HighlightCard',
|
|
7
8
|
component: HighlightCard
|
|
8
|
-
};
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script>
|
|
12
|
-
import { Story, Template } from '@storybook/addon-svelte-csf';
|
|
13
|
-
import {
|
|
14
|
-
userEvent,
|
|
15
|
-
within,
|
|
16
|
-
expect,
|
|
17
|
-
getByTestId,
|
|
18
|
-
getAllByLabelText,
|
|
19
|
-
getByText
|
|
20
|
-
} from '@storybook/test';
|
|
21
|
-
import { hasContext } from 'svelte';
|
|
22
|
-
|
|
23
|
-
let component;
|
|
9
|
+
});
|
|
24
10
|
</script>
|
|
25
11
|
|
|
26
12
|
<Story name="Basic HighlightCard">
|
|
@@ -63,7 +49,6 @@
|
|
|
63
49
|
|
|
64
50
|
:global(.highlight-cards > *) {
|
|
65
51
|
margin: 1rem 0;
|
|
66
|
-
|
|
67
52
|
@media (min-width: 900px) {
|
|
68
53
|
margin: 2rem 1rem;
|
|
69
54
|
flex: 1;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import Card from '../Card/Card.svelte';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
interface HighlightCardProps {
|
|
5
|
+
topline?: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
unit?: string;
|
|
8
|
+
subline?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { topline, value, unit, subline }: HighlightCardProps = $props();
|
|
8
12
|
</script>
|
|
9
13
|
|
|
10
14
|
<Card>
|
|
@@ -20,15 +24,15 @@
|
|
|
20
24
|
</span>
|
|
21
25
|
{unit}
|
|
22
26
|
</div>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
{#if subline}
|
|
28
|
+
<div class="bottom">
|
|
29
|
+
{@html subline}
|
|
30
|
+
</div>
|
|
31
|
+
{/if}
|
|
26
32
|
</div>
|
|
27
33
|
</Card>
|
|
28
34
|
|
|
29
35
|
<style lang="scss">
|
|
30
|
-
@import '../styles/base.scss';
|
|
31
|
-
|
|
32
36
|
.card-wrapper {
|
|
33
37
|
display: flex;
|
|
34
38
|
flex-direction: column;
|
|
@@ -43,7 +47,7 @@
|
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
.middle {
|
|
46
|
-
font-family:
|
|
50
|
+
font-family: var(--swr-sans);
|
|
47
51
|
font-size: 54px;
|
|
48
52
|
font-weight: 700;
|
|
49
53
|
padding-bottom: 0.2em;
|
package/src/Input/Input.svelte
CHANGED
package/src/Intro.mdx
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Logotype from './Logotype.svelte';
|
|
4
|
+
import DesignTokens from '../DesignTokens/DesignTokens.svelte';
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: 'Chart/Logotype',
|
|
8
|
+
component: Logotype
|
|
9
|
+
});
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<Story name="Basic">
|
|
13
|
+
<DesignTokens>
|
|
14
|
+
<Logotype></Logotype>
|
|
15
|
+
</DesignTokens>
|
|
16
|
+
</Story>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Middot from './Middot.svelte';
|
|
4
|
+
import DesignTokens from '../DesignTokens/DesignTokens.svelte';
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: 'Chart/Middot',
|
|
8
|
+
component: Middot
|
|
9
|
+
});
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<Story name="Basic">
|
|
13
|
+
<DesignTokens>
|
|
14
|
+
<Middot></Middot>
|
|
15
|
+
</DesignTokens>
|
|
16
|
+
</Story>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Story, Meta, Primary, Controls, Stories} from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
import * as SelectStories from './Select.stories.svelte';
|
|
4
|
+
|
|
5
|
+
<Meta of={SelectStories}/>
|
|
6
|
+
|
|
7
|
+
# Select
|
|
8
|
+
|
|
9
|
+
This component is a select input with a search feature and various options such as grouped items, multi-select etc. based on [svelte-select](https://github.com/rob-balfre/svelte-select).
|
|
10
|
+
|
|
11
|
+
Select items passed to the `items` prop must be of type `SelectItem`:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
interface SelectItem {
|
|
15
|
+
value: string;
|
|
16
|
+
label: string;
|
|
17
|
+
group?: string;
|
|
18
|
+
details?: any;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
<Controls/>
|
|
23
|
+
|
|
24
|
+
<Stories/>
|
|
25
|
+
|
|
@@ -1,91 +1,23 @@
|
|
|
1
|
-
<script context="module">
|
|
1
|
+
<script context="module" lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
2
3
|
import Select from './Select.svelte';
|
|
4
|
+
import StoryTemplate from './SelectStoriesTemplate.svelte';
|
|
3
5
|
import jobsData from './mock_data/jobs.json';
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
title: '
|
|
7
|
-
component: Select
|
|
8
|
-
|
|
9
|
-
// FIXME: remove this manual documentation when autodocs are fixed
|
|
10
|
-
parameters: {
|
|
11
|
-
docs: {
|
|
12
|
-
description: {
|
|
13
|
-
component:
|
|
14
|
-
'This component is a select input with a search feature and various options such as grouped items, multi-select etc. based on https://github.com/rob-balfre/svelte-select'
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
argTypes: {
|
|
19
|
-
inputId: {
|
|
20
|
-
description: "The input field's ID",
|
|
21
|
-
control: 'text',
|
|
22
|
-
type: { name: 'string', required: false },
|
|
23
|
-
defaultValue: 'select'
|
|
24
|
-
},
|
|
25
|
-
placeholder: {
|
|
26
|
-
description: "The input field's placeholder text",
|
|
27
|
-
control: 'text',
|
|
28
|
-
type: { name: 'string', required: false },
|
|
29
|
-
defaultValue: 'Bitte auswählen'
|
|
30
|
-
},
|
|
31
|
-
groupHeaderSelectable: {
|
|
32
|
-
description: 'Whether the group names should be selectable as well',
|
|
33
|
-
type: { name: 'boolean', required: false },
|
|
34
|
-
defaultValue: 'false'
|
|
35
|
-
},
|
|
36
|
-
clearable: {
|
|
37
|
-
description: 'Show a button to clear the input',
|
|
38
|
-
type: { name: 'boolean', required: false },
|
|
39
|
-
defaultValue: 'false'
|
|
40
|
-
},
|
|
41
|
-
value: {
|
|
42
|
-
description: 'The currently selected option',
|
|
43
|
-
type: { name: 'any', required: false }
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
};
|
|
7
|
+
const { Story } = defineMeta({
|
|
8
|
+
title: 'Form/Select',
|
|
9
|
+
component: Select
|
|
10
|
+
});
|
|
47
11
|
</script>
|
|
48
12
|
|
|
49
|
-
<script>
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
within,
|
|
54
|
-
expect,
|
|
55
|
-
getByTestId,
|
|
56
|
-
getAllByLabelText,
|
|
57
|
-
getByText
|
|
58
|
-
} from '@storybook/test';
|
|
59
|
-
import { hasContext } from 'svelte';
|
|
60
|
-
import Input from '../Input/Input.svelte';
|
|
61
|
-
|
|
62
|
-
let selectedItem;
|
|
63
|
-
let component;
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import { userEvent, within, expect } from '@storybook/test';
|
|
15
|
+
import { type SelectItem } from './Select.types';
|
|
16
|
+
let selectedItem: SelectItem | undefined = undefined;
|
|
64
17
|
</script>
|
|
65
18
|
|
|
66
|
-
<Template let:args>
|
|
67
|
-
<label for={args.inputId}>Select</label>
|
|
68
|
-
|
|
69
|
-
<Select {...args} bind:this={component} bind:value={selectedItem} />
|
|
70
|
-
|
|
71
|
-
{#if selectedItem}
|
|
72
|
-
<code class="output">
|
|
73
|
-
{JSON.stringify(selectedItem)}
|
|
74
|
-
</code>
|
|
75
|
-
{/if}
|
|
76
|
-
</Template>
|
|
77
|
-
|
|
78
19
|
<Story
|
|
79
20
|
name="Simple"
|
|
80
|
-
args={{
|
|
81
|
-
inputId: 'select',
|
|
82
|
-
clearable: true,
|
|
83
|
-
items: [
|
|
84
|
-
{ value: 'chocolate', label: 'Chocolate' },
|
|
85
|
-
{ value: 'cake', label: 'Cake' },
|
|
86
|
-
{ value: 'ice-cream', label: 'Ice Cream' }
|
|
87
|
-
]
|
|
88
|
-
}}
|
|
89
21
|
play={async ({ canvasElement, step }) => {
|
|
90
22
|
const canvas = within(canvasElement);
|
|
91
23
|
const select = canvas.getByLabelText('Select');
|
|
@@ -112,35 +44,38 @@
|
|
|
112
44
|
expect(selectedItem).toEqual(undefined);
|
|
113
45
|
});
|
|
114
46
|
}}
|
|
115
|
-
|
|
47
|
+
>
|
|
48
|
+
<StoryTemplate
|
|
49
|
+
bind:selectedItem
|
|
50
|
+
args={{
|
|
51
|
+
inputId: 'select',
|
|
52
|
+
clearable: true,
|
|
53
|
+
items: [
|
|
54
|
+
{ value: 'chocolate', label: 'Chocolate' },
|
|
55
|
+
{ value: 'cake', label: 'Cake' },
|
|
56
|
+
{ value: 'ice-cream', label: 'Ice Cream' }
|
|
57
|
+
]
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
</Story>
|
|
116
61
|
|
|
117
|
-
<Story
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
62
|
+
<Story name="Grouped">
|
|
63
|
+
<StoryTemplate
|
|
64
|
+
bind:selectedItem
|
|
65
|
+
args={{
|
|
66
|
+
items: [
|
|
67
|
+
{ value: 'chocolate', label: 'Chocolate', group: 'Sweet' },
|
|
68
|
+
{ value: 'pizza', label: 'Pizza', group: 'Savory' },
|
|
69
|
+
{ value: 'cake', label: 'Cake', group: 'Sweet' },
|
|
70
|
+
{ value: 'chips', label: 'Chips', group: 'Savory' },
|
|
71
|
+
{ value: 'ice-cream', label: 'Ice Cream', group: 'Sweet' }
|
|
72
|
+
]
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
</Story>
|
|
129
76
|
|
|
130
77
|
<Story
|
|
131
78
|
name="Grouped (group header selectable)"
|
|
132
|
-
args={{
|
|
133
|
-
inputId: 'job-select',
|
|
134
|
-
placeholder: 'Ihr Beruf',
|
|
135
|
-
groupHeaderSelectable: true,
|
|
136
|
-
items: [
|
|
137
|
-
{ value: 'chocolate', label: 'Chocolate', group: 'Sweet' },
|
|
138
|
-
{ value: 'pizza', label: 'Pizza', group: 'Savory' },
|
|
139
|
-
{ value: 'cake', label: 'Cake', group: 'Sweet' },
|
|
140
|
-
{ value: 'chips', label: 'Chips', group: 'Savory' },
|
|
141
|
-
{ value: 'ice-cream', label: 'Ice Cream', group: 'Sweet' }
|
|
142
|
-
]
|
|
143
|
-
}}
|
|
144
79
|
play={async ({ canvasElement, step }) => {
|
|
145
80
|
const canvas = within(canvasElement);
|
|
146
81
|
const select = canvas.getByLabelText('Select');
|
|
@@ -168,7 +103,23 @@
|
|
|
168
103
|
});
|
|
169
104
|
});
|
|
170
105
|
}}
|
|
171
|
-
|
|
106
|
+
>
|
|
107
|
+
<StoryTemplate
|
|
108
|
+
bind:selectedItem
|
|
109
|
+
args={{
|
|
110
|
+
inputId: 'job-select',
|
|
111
|
+
placeholder: 'Ihr Beruf',
|
|
112
|
+
groupHeaderSelectable: true,
|
|
113
|
+
items: [
|
|
114
|
+
{ value: 'chocolate', label: 'Chocolate', group: 'Sweet' },
|
|
115
|
+
{ value: 'pizza', label: 'Pizza', group: 'Savory' },
|
|
116
|
+
{ value: 'cake', label: 'Cake', group: 'Sweet' },
|
|
117
|
+
{ value: 'chips', label: 'Chips', group: 'Savory' },
|
|
118
|
+
{ value: 'ice-cream', label: 'Ice Cream', group: 'Sweet' }
|
|
119
|
+
]
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
</Story>
|
|
172
123
|
|
|
173
124
|
<Story
|
|
174
125
|
name="Custom items"
|
|
@@ -195,52 +146,41 @@
|
|
|
195
146
|
});
|
|
196
147
|
}}
|
|
197
148
|
>
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
{JSON.stringify(selectedItem)}
|
|
230
|
-
</code>
|
|
231
|
-
{/if}
|
|
149
|
+
<StoryTemplate>
|
|
150
|
+
{#snippet demoComponent()}
|
|
151
|
+
<label for="job-select">Berufe</label>
|
|
152
|
+
<Select
|
|
153
|
+
bind:value={selectedItem}
|
|
154
|
+
inputId="job-select"
|
|
155
|
+
placeholder="z.B. Taxifahrer/in"
|
|
156
|
+
items={jobsData
|
|
157
|
+
.sort((a, b) => a.label.localeCompare(b.label))
|
|
158
|
+
.map((item) => ({
|
|
159
|
+
value: item.value,
|
|
160
|
+
label: `${item.label}: ${item.add_on}`, // used for filtering
|
|
161
|
+
details: {
|
|
162
|
+
title: item.label, // used for display
|
|
163
|
+
addon: item.add_on // used for display
|
|
164
|
+
}
|
|
165
|
+
}))}
|
|
166
|
+
groupHeaderSelectable={false}
|
|
167
|
+
>
|
|
168
|
+
<div slot="item" let:item class="custom-item">
|
|
169
|
+
<h4 class="custom-item-title" data-testid="custom-item-title">
|
|
170
|
+
{item.details.title}
|
|
171
|
+
</h4>
|
|
172
|
+
<p class="custom-item-addon" data-testid="custom-item-addon">{item.details.addon}</p>
|
|
173
|
+
</div>
|
|
174
|
+
<div slot="selection" let:selection class="selection">
|
|
175
|
+
{selection.details.title}
|
|
176
|
+
</div>
|
|
177
|
+
</Select>
|
|
178
|
+
{/snippet}
|
|
179
|
+
</StoryTemplate>
|
|
232
180
|
</Story>
|
|
233
181
|
|
|
234
182
|
<style>
|
|
235
|
-
.output {
|
|
236
|
-
display: block;
|
|
237
|
-
margin-top: 1rem;
|
|
238
|
-
padding: 1rem;
|
|
239
|
-
background: #dadada;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
183
|
.custom-item {
|
|
243
|
-
font-family: sans-serif;
|
|
244
184
|
font-size: 0.9rem;
|
|
245
185
|
margin-top: 0.2rem;
|
|
246
186
|
}
|
package/src/Select/Select.svelte
CHANGED
|
@@ -1,84 +1,76 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Select from 'svelte-select';
|
|
3
|
+
import { type SelectItem } from './Select.types';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
5
|
+
interface SelectProps {
|
|
6
|
+
/**
|
|
7
|
+
* The input field's ID. Should be unique across the page.
|
|
8
|
+
*/
|
|
9
|
+
inputId: string;
|
|
10
|
+
/**
|
|
11
|
+
* The input field's placeholder text
|
|
12
|
+
*/
|
|
13
|
+
placeholder: string;
|
|
14
|
+
/**
|
|
15
|
+
* The list of select options
|
|
16
|
+
*/
|
|
17
|
+
items: SelectItem[];
|
|
18
|
+
/**
|
|
19
|
+
* Define custom item groupings. By default items are grouped by their `group` key
|
|
20
|
+
*/
|
|
21
|
+
groupBy?: ((item: SelectItem) => string) | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Whether group names should be selectable
|
|
24
|
+
*/
|
|
25
|
+
groupHeaderSelectable?: boolean;
|
|
26
|
+
clearable?: boolean;
|
|
27
|
+
value: SelectItem | undefined;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The list of select options
|
|
32
|
-
*/
|
|
33
|
-
export let items: Option[] = [];
|
|
34
|
-
|
|
35
|
-
let groupBy: ((item: Option) => string) | undefined;
|
|
36
|
-
$: groupBy =
|
|
37
|
-
items.length > 0 && items.every((item) => item.group)
|
|
38
|
-
? (item: Option) => item.group as string
|
|
39
|
-
: undefined;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Whether the group names should be selectable as well
|
|
43
|
-
*/
|
|
44
|
-
export let groupHeaderSelectable: boolean = false;
|
|
30
|
+
let {
|
|
31
|
+
inputId = 'select',
|
|
32
|
+
placeholder = 'Bitte auswählen',
|
|
33
|
+
items = [],
|
|
34
|
+
groupBy,
|
|
35
|
+
groupHeaderSelectable = false,
|
|
36
|
+
clearable = true,
|
|
37
|
+
value = $bindable(undefined)
|
|
38
|
+
}: SelectProps = $props();
|
|
45
39
|
|
|
46
|
-
|
|
47
|
-
* Enable clearing the input
|
|
48
|
-
*/
|
|
49
|
-
export let clearable: boolean = true;
|
|
50
|
-
|
|
51
|
-
export let value: Option | undefined;
|
|
40
|
+
const groupByFn = groupBy || ((item: SelectItem) => item.group as string);
|
|
52
41
|
</script>
|
|
53
42
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
43
|
+
<div class="container">
|
|
44
|
+
<Select
|
|
45
|
+
{items}
|
|
46
|
+
groupBy={items.length > 0 && items.every((item) => item.group) ? groupByFn : undefined}
|
|
47
|
+
id={inputId}
|
|
48
|
+
{placeholder}
|
|
49
|
+
{groupHeaderSelectable}
|
|
50
|
+
{clearable}
|
|
51
|
+
class="container"
|
|
52
|
+
bind:value
|
|
53
|
+
>
|
|
54
|
+
<div class="item" slot="item" let:item>
|
|
55
|
+
<slot name="item" {item}>
|
|
56
|
+
{item.label}
|
|
57
|
+
</slot>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="selection" slot="selection" let:selection>
|
|
60
|
+
<slot name="selection" {selection}>
|
|
61
|
+
{selection.label}
|
|
62
|
+
</slot>
|
|
63
|
+
</div>
|
|
64
|
+
</Select>
|
|
65
|
+
</div>
|
|
73
66
|
|
|
74
67
|
<style lang="scss">
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// --placeholder-color: blue;
|
|
68
|
+
.item {
|
|
69
|
+
font-family: var(--swr-sans);
|
|
70
|
+
color: var(--violet-dark-5);
|
|
71
|
+
}
|
|
72
|
+
.selection {
|
|
73
|
+
font-family: var(--swr-sans);
|
|
74
|
+
color: var(--violet-dark-5);
|
|
75
|
+
}
|
|
84
76
|
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Select from './Select.svelte';
|
|
3
|
+
import DesignTokens from '../DesignTokens/DesignTokens.svelte';
|
|
4
|
+
|
|
5
|
+
let { args = null, selectedItem = $bindable(), demoComponent = null } = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<DesignTokens>
|
|
9
|
+
{#if demoComponent}
|
|
10
|
+
{@render demoComponent()}
|
|
11
|
+
{:else}
|
|
12
|
+
<label for={args.inputId}>Select</label>
|
|
13
|
+
<Select {...args} bind:value={selectedItem} />
|
|
14
|
+
{/if}
|
|
15
|
+
</DesignTokens>
|
|
16
|
+
|
|
17
|
+
{#if selectedItem}
|
|
18
|
+
<pre class="output">
|
|
19
|
+
value = {JSON.stringify(selectedItem, null, ' ')}</pre>
|
|
20
|
+
{/if}
|
|
21
|
+
|
|
22
|
+
<style>
|
|
23
|
+
label {
|
|
24
|
+
display: block;
|
|
25
|
+
font-family: var(--swr-sans);
|
|
26
|
+
margin-bottom: 0.25em;
|
|
27
|
+
}
|
|
28
|
+
.output {
|
|
29
|
+
display: block;
|
|
30
|
+
margin-top: 1rem;
|
|
31
|
+
padding: 1rem;
|
|
32
|
+
background: #fcfaff;
|
|
33
|
+
color: rgb(18, 69, 139);
|
|
34
|
+
}
|
|
35
|
+
</style>
|