@streamscloud/kit 0.2.39 → 0.2.40

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.
@@ -87,13 +87,28 @@ A three-state checkbox (unchecked, checked, indeterminate) with optional label o
87
87
  .checkbox__icon--checked {
88
88
  --sc-kit--icon--color: var(--_checkbox--color--checked);
89
89
  }
90
- .checkbox__label, .checkbox__body {
90
+ .checkbox__label {
91
91
  font-size: var(--_checkbox--label--font-size);
92
92
  line-height: var(--_checkbox--label--line-height);
93
+ min-width: 0;
94
+ text-overflow: ellipsis;
95
+ max-width: 100%;
96
+ white-space: nowrap;
97
+ overflow: hidden;
93
98
  -webkit-user-drag: none;
94
99
  user-select: none;
95
100
  }
96
- .checkbox__label :global([contenteditable]), .checkbox__body :global([contenteditable]) {
101
+ .checkbox__label :global([contenteditable]) {
102
+ user-select: text;
103
+ }
104
+ .checkbox__body {
105
+ font-size: var(--_checkbox--label--font-size);
106
+ line-height: var(--_checkbox--label--line-height);
107
+ min-width: 0;
108
+ -webkit-user-drag: none;
109
+ user-select: none;
110
+ }
111
+ .checkbox__body :global([contenteditable]) {
97
112
  user-select: text;
98
113
  }
99
114
  .checkbox--disabled {
@@ -0,0 +1,76 @@
1
+ <script lang="ts">import { ThreeStateCheckbox } from '../checkbox';
2
+ import CheckboxNode from './cmp.checkbox-node.svelte';
3
+ const { treeNode, canSelectChildrenWithoutParent, allSuffix = ' (All)', on } = $props();
4
+ let treeNodeInternal = $derived(treeNode);
5
+ const getIsChecked = (node) => {
6
+ if (node.checked) {
7
+ return true;
8
+ }
9
+ if (node.children?.some((c) => getIsChecked(c))) {
10
+ return true;
11
+ }
12
+ return false;
13
+ };
14
+ const setIsChecked = (node, value) => {
15
+ node.checked = value;
16
+ if (node.children?.length) {
17
+ node.children = node.children.map((c) => setIsChecked(c, value));
18
+ }
19
+ return node;
20
+ };
21
+ let checkboxState = $derived.by(() => {
22
+ if (treeNodeInternal.checked) {
23
+ if (!treeNodeInternal.children?.length || treeNodeInternal.children.every((c) => getIsChecked(c))) {
24
+ return 'checked';
25
+ }
26
+ return 'indeterminate';
27
+ }
28
+ return 'unchecked';
29
+ });
30
+ const handleChanged = (value) => {
31
+ treeNodeInternal = setIsChecked(treeNodeInternal, value);
32
+ on?.change(treeNodeInternal);
33
+ };
34
+ const onChildChanged = (child) => {
35
+ if (!treeNodeInternal.children) {
36
+ return;
37
+ }
38
+ const index = treeNodeInternal.children.findIndex((c) => c.id === child.id);
39
+ if (index === -1) {
40
+ return;
41
+ }
42
+ treeNodeInternal.children[index] = child;
43
+ if (canSelectChildrenWithoutParent) {
44
+ on?.change(treeNodeInternal);
45
+ return;
46
+ }
47
+ if (treeNodeInternal.children.some((c) => c.checked)) {
48
+ treeNodeInternal.checked = true;
49
+ }
50
+ on?.change(treeNodeInternal);
51
+ };
52
+ </script>
53
+
54
+ <div class="checkbox-node">
55
+ <ThreeStateCheckbox state={checkboxState} label={treeNodeInternal.name + (treeNodeInternal.children ? allSuffix : '')} on={{ change: handleChanged }} />
56
+ {#if treeNodeInternal.children?.length}
57
+ <div class="checkbox-node__children">
58
+ {#each treeNodeInternal.children as child (child.id)}
59
+ {#if !child.hidden}
60
+ <CheckboxNode treeNode={child} allSuffix={allSuffix} on={{ change: onChildChanged }} />
61
+ {/if}
62
+ {/each}
63
+ </div>
64
+ {/if}
65
+ </div>
66
+
67
+ <style>.checkbox-node {
68
+ --sc-kit--checkbox--label--font-size: 0.875rem;
69
+ overflow: hidden;
70
+ }
71
+ .checkbox-node__children {
72
+ display: flex;
73
+ flex-direction: column;
74
+ gap: 0.25rem;
75
+ margin-inline-start: 1.25rem;
76
+ }</style>
@@ -0,0 +1,14 @@
1
+ import type { MultiselectTreeNode } from './types';
2
+ type Props = {
3
+ treeNode: MultiselectTreeNode;
4
+ /** When true, child selection state propagates without forcing parent on */
5
+ canSelectChildrenWithoutParent?: boolean;
6
+ /** Suffix appended to the parent label when it has children */
7
+ allSuffix?: string;
8
+ on?: {
9
+ change: (treeNode: MultiselectTreeNode) => void;
10
+ };
11
+ };
12
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
13
+ type Cmp = ReturnType<typeof Cmp>;
14
+ export default Cmp;
@@ -0,0 +1,276 @@
1
+ <script lang="ts">import { Button } from '../button';
2
+ import { Dropdown } from '../dropdown';
3
+ import { Icon } from '../icon';
4
+ import { Input } from '../inputs';
5
+ import { Singleselect } from '../selects';
6
+ import CheckboxNode from './cmp.checkbox-node.svelte';
7
+ import { flattenTree, mapToTree } from './mapper';
8
+ import { MultiselectDropdownLocalization } from './multiselect-dropdown-localization';
9
+ import IconCheckmark from '@fluentui/svg-icons/icons/checkmark_20_regular.svg?raw';
10
+ import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_20_regular.svg?raw';
11
+ import IconSearch from '@fluentui/svg-icons/icons/search_20_regular.svg?raw';
12
+ import IconTag from '@fluentui/svg-icons/icons/tag_20_regular.svg?raw';
13
+ import { nanoid } from 'nanoid';
14
+ let { placeholder, values, possibleValues, dropdownIcon, on, disableMultilevel, canSelectChildrenWithoutParent, disabled, label, createNewLabel, createNewPlaceholder } = $props();
15
+ const localization = new MultiselectDropdownLocalization();
16
+ let possibleValuesInternal = $state([]);
17
+ let filteredValues = $state([]);
18
+ $effect(() => {
19
+ possibleValuesInternal = possibleValues;
20
+ filteredValues = possibleValues;
21
+ });
22
+ const possibleValuesAsTree = $derived(mapToTree(possibleValuesInternal, values, filteredValues));
23
+ let search = $state('');
24
+ let selectedParentNode = $state(null);
25
+ const onNodeChanged = (node) => {
26
+ const newValues = flattenTree([...possibleValuesAsTree.filter((v) => v.id !== node.id), node]);
27
+ on?.change?.(newValues);
28
+ };
29
+ const createNewNode = () => {
30
+ if (!search) {
31
+ return;
32
+ }
33
+ const newNode = {
34
+ id: nanoid(),
35
+ name: search,
36
+ parentId: disableMultilevel ? null : selectedParentNode?.id || null
37
+ };
38
+ possibleValuesInternal = [...possibleValuesInternal, newNode];
39
+ filteredValues = possibleValuesInternal;
40
+ search = '';
41
+ selectedParentNode = null;
42
+ on?.create?.(newNode);
43
+ };
44
+ const onSearchInput = (value) => {
45
+ search = value;
46
+ if (!value) {
47
+ filteredValues = possibleValuesInternal;
48
+ return;
49
+ }
50
+ const searchTerm = value.toLowerCase();
51
+ filteredValues = possibleValuesInternal.filter((v) => v.name.toLowerCase().includes(searchTerm));
52
+ let parents = [];
53
+ do {
54
+ parents = possibleValuesInternal.filter((v) => filteredValues.some((fv) => fv.parentId === v.id) && !filteredValues.some((fv) => fv.id === v.id));
55
+ filteredValues = [...filteredValues, ...parents];
56
+ } while (parents.length);
57
+ };
58
+ </script>
59
+
60
+ <div class="multiselect-dropdown">
61
+ {#if label}
62
+ {@render label()}
63
+ {/if}
64
+ <Dropdown
65
+ keepDropdownOpen
66
+ disabled={disabled}
67
+ on={{
68
+ closed: () => {
69
+ onSearchInput('');
70
+ selectedParentNode = null;
71
+ }
72
+ }}>
73
+ {#snippet trigger()}
74
+ <div class="multiselect-dropdown__trigger">
75
+ <Input value={null} inert placeholder={placeholder ?? localization.dropdownPlaceholder} on={{}}>
76
+ {#snippet icon()}
77
+ {#if dropdownIcon}
78
+ <Icon src={dropdownIcon} />
79
+ {/if}
80
+ {/snippet}
81
+ {#snippet clearButton()}
82
+ <Icon src={IconChevronDown} />
83
+ {/snippet}
84
+ </Input>
85
+ </div>
86
+ {/snippet}
87
+ <div class="multiselect-dropdown__content">
88
+ <div class="multiselect-dropdown__search">
89
+ <Input
90
+ value={search}
91
+ placeholder={on?.create ? localization.searchOrTypeToCreatePlaceholder : localization.searchPlaceholder}
92
+ on={{ input: onSearchInput }}>
93
+ {#snippet icon()}
94
+ <Icon src={IconSearch} />
95
+ {/snippet}
96
+ </Input>
97
+ </div>
98
+ {#if (on?.create && !filteredValues.length) || (on?.create && search && !filteredValues.some((v) => v.name.toLowerCase() === search.toLowerCase()))}
99
+ <div class="multiselect-dropdown__create-new">
100
+ <div class="multiselect-dropdown__create-new-title">{createNewLabel ?? localization.createNewItem}</div>
101
+ <div class="multiselect-dropdown__create-new-subtitle">
102
+ <div class="multiselect-dropdown__create-new-description" class:multiselect-dropdown__create-new-description--create-in={selectedParentNode}>
103
+ {#if disableMultilevel}
104
+ {localization.create}<span>"{search}"</span>
105
+ {:else if selectedParentNode}
106
+ {localization.createIn}<span>"{selectedParentNode.name}"</span>
107
+ {:else}
108
+ {localization.createAsParent}<span>"{search}"</span>
109
+ {/if}
110
+ </div>
111
+ <div class="multiselect-dropdown__create-new-action">
112
+ <Button size="small" variant="standard" on={{ click: () => createNewNode() }}>
113
+ <Icon src={IconCheckmark} color="green" />
114
+ </Button>
115
+ </div>
116
+ </div>
117
+ {#if !disableMultilevel}
118
+ <div class="multiselect-dropdown__create-new-select">
119
+ <Singleselect
120
+ placeholder={createNewPlaceholder ?? localization.orSelectParentItem}
121
+ options={possibleValuesInternal.filter((c) => !c.parentId).map((v) => ({ label: v.name, value: v }))}
122
+ on={{ change: (value: MultiselectNode | null) => (selectedParentNode = value) }}>
123
+ {#snippet icon()}
124
+ <Icon src={IconTag} />
125
+ {/snippet}
126
+ </Singleselect>
127
+ </div>
128
+ {/if}
129
+ </div>
130
+ {/if}
131
+ {#key possibleValuesAsTree}
132
+ <div class="multiselect-dropdown__items">
133
+ {#each possibleValuesAsTree as item, index (index)}
134
+ {#if !item.hidden}
135
+ <CheckboxNode
136
+ treeNode={item}
137
+ canSelectChildrenWithoutParent={canSelectChildrenWithoutParent}
138
+ allSuffix={localization.allSuffix}
139
+ on={{ change: onNodeChanged }} />
140
+ {/if}
141
+ {/each}
142
+ </div>
143
+ {/key}
144
+ </div>
145
+ </Dropdown>
146
+ </div>
147
+
148
+ <!--
149
+ @component
150
+ A dropdown with a tree of three-state checkboxes for selecting multiple items, optional creation of new items (with parent picker), and built-in fuzzy search across the tree (parents of matched items are kept visible).
151
+
152
+ ### CSS Custom Properties
153
+ | Property | Description | Default |
154
+ |---|---|---|
155
+ | `--sc-kit--multiselect-dropdown--content--background` | Dropdown panel background | `light-dark(white, gray-900)` |
156
+ | `--sc-kit--multiselect-dropdown--content--min-width` | Dropdown panel min width | `21.875em` |
157
+ | `--sc-kit--multiselect-dropdown--content--max-height` | Dropdown panel max height | `18.75em` |
158
+ | `--sc-kit--multiselect-dropdown--create-new--background` | Create-new section background | `light-dark(neutral-50, neutral-800)` |
159
+ | `--sc-kit--multiselect-dropdown--create-new-subtitle--background` | Subtitle row background | `light-dark(neutral-100, neutral-700)` |
160
+ | `--sc-kit--multiselect-dropdown--create-new-title--color` | Create-new title color | `light-dark(gray-700, neutral-200)` |
161
+ | `--sc-kit--multiselect-dropdown--create-new-description--color` | Default description color | `light-dark(primary-500, primary-400)` |
162
+ | `--sc-kit--multiselect-dropdown--create-new-description--color--create-in` | Description color when a parent is selected | `success-700` |
163
+ | `--sc-kit--multiselect-dropdown--create-new-description--accent-color` | Highlighted token (search/parent name) color | `light-dark(gray-800, white)` |
164
+ -->
165
+
166
+ <style>.multiselect-dropdown {
167
+ --_multiselect-dropdown--content--background: var(
168
+ --sc-kit--multiselect-dropdown--content--background,
169
+ light-dark(#ffffff, #1c1c1c)
170
+ );
171
+ --_multiselect-dropdown--content--min-width: var(--sc-kit--multiselect-dropdown--content--min-width, 21.875rem);
172
+ --_multiselect-dropdown--content--max-height: var(--sc-kit--multiselect-dropdown--content--max-height, 18.75rem);
173
+ --_multiselect-dropdown--create-new--background: var(
174
+ --sc-kit--multiselect-dropdown--create-new--background,
175
+ light-dark(#f9fafb, #1f2937)
176
+ );
177
+ --_multiselect-dropdown--create-new-subtitle--background: var(
178
+ --sc-kit--multiselect-dropdown--create-new-subtitle--background,
179
+ light-dark(#f2f2f3, #374151)
180
+ );
181
+ --_multiselect-dropdown--create-new-title--color: var(
182
+ --sc-kit--multiselect-dropdown--create-new-title--color,
183
+ light-dark(#4d4d4d, #e5e7eb)
184
+ );
185
+ --_multiselect-dropdown--create-new-description--color: var(
186
+ --sc-kit--multiselect-dropdown--create-new-description--color,
187
+ light-dark(#144ab0, #5a8dec)
188
+ );
189
+ --_multiselect-dropdown--create-new-description--color--create-in: var(
190
+ --sc-kit--multiselect-dropdown--create-new-description--color--create-in,
191
+ #0aa454
192
+ );
193
+ --_multiselect-dropdown--create-new-description--accent-color: var(
194
+ --sc-kit--multiselect-dropdown--create-new-description--accent-color,
195
+ light-dark(#2e2e2e, #ffffff)
196
+ );
197
+ }
198
+ .multiselect-dropdown__trigger {
199
+ width: 100%;
200
+ --sc-kit--input--background--disabled: var(--sc-kit--input--background, light-dark(#ffffff, #1c1c1c));
201
+ --sc-kit--input--accent-color: transparent;
202
+ caret-color: transparent;
203
+ }
204
+ .multiselect-dropdown__content {
205
+ background-color: var(--_multiselect-dropdown--content--background);
206
+ min-width: var(--_multiselect-dropdown--content--min-width);
207
+ padding-block: 1rem;
208
+ max-height: var(--_multiselect-dropdown--content--max-height);
209
+ overflow-y: auto;
210
+ --_cross-browser-scrollbar--thumb-color: var(--scrollbar--thumb-color, light-dark(#d1d5db, #4b5563));
211
+ --_cross-browser-scrollbar--track-color: var(--scrollbar--track-color, transparent);
212
+ }
213
+ .multiselect-dropdown__content::-webkit-scrollbar {
214
+ width: 6px;
215
+ height: 6px;
216
+ }
217
+ .multiselect-dropdown__content::-webkit-scrollbar-track {
218
+ background: var(--_cross-browser-scrollbar--track-color);
219
+ border-radius: 100vw;
220
+ }
221
+ .multiselect-dropdown__content::-webkit-scrollbar-thumb {
222
+ background: var(--_cross-browser-scrollbar--thumb-color);
223
+ border-radius: 100vw;
224
+ }
225
+ @supports (scrollbar-color: transparent transparent) {
226
+ .multiselect-dropdown__content {
227
+ scrollbar-color: var(--_cross-browser-scrollbar--thumb-color) var(--_cross-browser-scrollbar--track-color);
228
+ scrollbar-width: thin;
229
+ }
230
+ }
231
+ .multiselect-dropdown__search {
232
+ width: 100%;
233
+ padding-inline: 1.25rem;
234
+ }
235
+ .multiselect-dropdown__items {
236
+ margin-block-start: 0.625rem;
237
+ padding-inline: 1.25rem;
238
+ }
239
+ .multiselect-dropdown__create-new {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: 0.6875rem;
243
+ margin-block-start: 0.625rem;
244
+ padding: 0.625rem 1.25rem;
245
+ background-color: var(--_multiselect-dropdown--create-new--background);
246
+ }
247
+ .multiselect-dropdown__create-new-title {
248
+ font-size: 0.75rem;
249
+ font-weight: 400;
250
+ margin-block-end: 0.25rem;
251
+ color: var(--_multiselect-dropdown--create-new-title--color);
252
+ }
253
+ .multiselect-dropdown__create-new-subtitle {
254
+ display: flex;
255
+ flex-direction: row;
256
+ justify-content: space-between;
257
+ align-items: center;
258
+ gap: 0.625rem;
259
+ background-color: var(--_multiselect-dropdown--create-new-subtitle--background);
260
+ padding: 0.5rem 0.625rem;
261
+ }
262
+ .multiselect-dropdown__create-new-action {
263
+ --sc-kit--button--padding--inline: 0.375rem;
264
+ }
265
+ .multiselect-dropdown__create-new-description {
266
+ font-size: 0.75rem;
267
+ font-weight: 500;
268
+ color: var(--_multiselect-dropdown--create-new-description--color);
269
+ }
270
+ .multiselect-dropdown__create-new-description--create-in {
271
+ color: var(--_multiselect-dropdown--create-new-description--color--create-in);
272
+ }
273
+ .multiselect-dropdown__create-new-description span {
274
+ color: var(--_multiselect-dropdown--create-new-description--accent-color);
275
+ font-weight: 400;
276
+ }</style>
@@ -0,0 +1,45 @@
1
+ import type { MultiselectNode } from './types';
2
+ import type { Snippet } from 'svelte';
3
+ type Props = {
4
+ /** Currently selected nodes */
5
+ values: MultiselectNode[];
6
+ /** Full pool of selectable nodes (flat — parent-child via `parentId`) */
7
+ possibleValues: MultiselectNode[];
8
+ placeholder?: string;
9
+ /** Header label for the create-new section */
10
+ createNewLabel?: string;
11
+ /** Placeholder for the parent-picker shown in the create-new section */
12
+ createNewPlaceholder?: string;
13
+ disabled?: boolean;
14
+ /** Treat the tree as flat — never nest new items under a parent */
15
+ disableMultilevel?: boolean;
16
+ /** Allow children to be checked without forcing the parent on */
17
+ canSelectChildrenWithoutParent?: boolean;
18
+ /** Custom icon shown on the trigger input */
19
+ dropdownIcon?: string;
20
+ on?: {
21
+ change?: (values: MultiselectNode[]) => Promise<void> | void;
22
+ create?: (value: MultiselectNode) => Promise<void> | void;
23
+ };
24
+ /** Optional label rendered above the trigger */
25
+ label?: Snippet;
26
+ };
27
+ /**
28
+ * A dropdown with a tree of three-state checkboxes for selecting multiple items, optional creation of new items (with parent picker), and built-in fuzzy search across the tree (parents of matched items are kept visible).
29
+ *
30
+ * ### CSS Custom Properties
31
+ * | Property | Description | Default |
32
+ * |---|---|---|
33
+ * | `--sc-kit--multiselect-dropdown--content--background` | Dropdown panel background | `light-dark(white, gray-900)` |
34
+ * | `--sc-kit--multiselect-dropdown--content--min-width` | Dropdown panel min width | `21.875em` |
35
+ * | `--sc-kit--multiselect-dropdown--content--max-height` | Dropdown panel max height | `18.75em` |
36
+ * | `--sc-kit--multiselect-dropdown--create-new--background` | Create-new section background | `light-dark(neutral-50, neutral-800)` |
37
+ * | `--sc-kit--multiselect-dropdown--create-new-subtitle--background` | Subtitle row background | `light-dark(neutral-100, neutral-700)` |
38
+ * | `--sc-kit--multiselect-dropdown--create-new-title--color` | Create-new title color | `light-dark(gray-700, neutral-200)` |
39
+ * | `--sc-kit--multiselect-dropdown--create-new-description--color` | Default description color | `light-dark(primary-500, primary-400)` |
40
+ * | `--sc-kit--multiselect-dropdown--create-new-description--color--create-in` | Description color when a parent is selected | `success-700` |
41
+ * | `--sc-kit--multiselect-dropdown--create-new-description--accent-color` | Highlighted token (search/parent name) color | `light-dark(gray-800, white)` |
42
+ */
43
+ declare const Cmp: import("svelte").Component<Props, {}, "">;
44
+ type Cmp = ReturnType<typeof Cmp>;
45
+ export default Cmp;
@@ -0,0 +1,3 @@
1
+ export { default as MultiselectDropdown } from './cmp.multiselect-dropdown.svelte';
2
+ export { MultiselectDropdownLocalization } from './multiselect-dropdown-localization';
3
+ export type { MultiselectNode, MultiselectTreeNode } from './types';
@@ -0,0 +1,2 @@
1
+ export { default as MultiselectDropdown } from './cmp.multiselect-dropdown.svelte';
2
+ export { MultiselectDropdownLocalization } from './multiselect-dropdown-localization';
@@ -0,0 +1,3 @@
1
+ import type { MultiselectNode, MultiselectTreeNode } from './types';
2
+ export declare const mapToTree: <T extends MultiselectNode>(nodes: ReadonlyArray<T>, checkedNodes: ReadonlyArray<T>, visibleNodes: ReadonlyArray<T>) => Array<MultiselectTreeNode>;
3
+ export declare const flattenTree: (nodes: ReadonlyArray<MultiselectTreeNode>) => Array<MultiselectNode>;
@@ -0,0 +1,39 @@
1
+ export const mapToTree = (nodes, checkedNodes, visibleNodes) => {
2
+ const nodeMap = {};
3
+ const tree = [];
4
+ nodes.forEach((node) => {
5
+ nodeMap[node.id] = {
6
+ ...node,
7
+ checked: checkedNodes.some((checkedNode) => checkedNode.id === node.id),
8
+ hidden: !visibleNodes.some((visibleNode) => visibleNode.id === node.id)
9
+ };
10
+ });
11
+ nodes.forEach((node) => {
12
+ if (node.parentId) {
13
+ const parent = nodeMap[node.parentId];
14
+ if (parent) {
15
+ if (!parent.children) {
16
+ parent.children = [];
17
+ }
18
+ parent.children.push(nodeMap[node.id]);
19
+ }
20
+ }
21
+ else {
22
+ tree.push(nodeMap[node.id]);
23
+ }
24
+ });
25
+ return tree;
26
+ };
27
+ export const flattenTree = (nodes) => {
28
+ const flatList = [];
29
+ const traverse = (node) => {
30
+ if (node.checked) {
31
+ flatList.push({ id: node.id, name: node.name, parentId: node.parentId });
32
+ }
33
+ if (node.children) {
34
+ node.children.forEach(traverse);
35
+ }
36
+ };
37
+ nodes.forEach(traverse);
38
+ return flatList;
39
+ };
@@ -0,0 +1,11 @@
1
+ export declare class MultiselectDropdownLocalization {
2
+ get dropdownPlaceholder(): string;
3
+ get searchPlaceholder(): string;
4
+ get searchOrTypeToCreatePlaceholder(): string;
5
+ get createNewItem(): string;
6
+ get orSelectParentItem(): string;
7
+ get create(): string;
8
+ get createIn(): string;
9
+ get createAsParent(): string;
10
+ get allSuffix(): string;
11
+ }
@@ -0,0 +1,41 @@
1
+ import { AppLocale } from '../../core/locale';
2
+ const loc = {
3
+ dropdownPlaceholder: { en: 'Select items', no: 'Velg elementer' },
4
+ searchPlaceholder: { en: 'Search', no: 'Søk' },
5
+ searchOrTypeToCreatePlaceholder: { en: 'Search or type to create', no: 'Søk eller skriv for å opprette' },
6
+ createNewItem: { en: 'Create new item', no: 'Opprett nytt element' },
7
+ orSelectParentItem: { en: 'Or select parent item', no: 'Eller velg overordnet element' },
8
+ create: { en: 'Create ', no: 'Opprett ' },
9
+ createIn: { en: 'Create in ', no: 'Opprett i ' },
10
+ createAsParent: { en: 'Create as parent ', no: 'Opprett som overordnet ' },
11
+ allSuffix: { en: ' (All)', no: ' (Alle)' }
12
+ };
13
+ export class MultiselectDropdownLocalization {
14
+ get dropdownPlaceholder() {
15
+ return loc.dropdownPlaceholder[AppLocale.current];
16
+ }
17
+ get searchPlaceholder() {
18
+ return loc.searchPlaceholder[AppLocale.current];
19
+ }
20
+ get searchOrTypeToCreatePlaceholder() {
21
+ return loc.searchOrTypeToCreatePlaceholder[AppLocale.current];
22
+ }
23
+ get createNewItem() {
24
+ return loc.createNewItem[AppLocale.current];
25
+ }
26
+ get orSelectParentItem() {
27
+ return loc.orSelectParentItem[AppLocale.current];
28
+ }
29
+ get create() {
30
+ return loc.create[AppLocale.current];
31
+ }
32
+ get createIn() {
33
+ return loc.createIn[AppLocale.current];
34
+ }
35
+ get createAsParent() {
36
+ return loc.createAsParent[AppLocale.current];
37
+ }
38
+ get allSuffix() {
39
+ return loc.allSuffix[AppLocale.current];
40
+ }
41
+ }
@@ -0,0 +1,10 @@
1
+ export interface MultiselectNode {
2
+ id: string;
3
+ name: string;
4
+ parentId?: string | null;
5
+ }
6
+ export interface MultiselectTreeNode extends MultiselectNode {
7
+ checked: boolean;
8
+ hidden?: boolean;
9
+ children?: Array<MultiselectTreeNode>;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.2.39",
3
+ "version": "0.2.40",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -189,6 +189,10 @@
189
189
  "types": "./dist/ui/media-viewer-dialog/index.d.ts",
190
190
  "svelte": "./dist/ui/media-viewer-dialog/index.js"
191
191
  },
192
+ "./ui/multiselect-dropdown": {
193
+ "types": "./dist/ui/multiselect-dropdown/index.d.ts",
194
+ "svelte": "./dist/ui/multiselect-dropdown/index.js"
195
+ },
192
196
  "./ui/page-toolbar": {
193
197
  "types": "./dist/ui/page-toolbar/index.d.ts",
194
198
  "svelte": "./dist/ui/page-toolbar/index.js"