@flightlesslabs/dodo-ui 0.6.6 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/index.d.ts +28 -7
  2. package/dist/index.js +12 -2
  3. package/dist/stories/Home.mdx +1 -1
  4. package/dist/stories/components/Form/Button/Button.svelte +2 -2
  5. package/dist/stories/components/Form/Button/Button.svelte.d.ts +8 -5
  6. package/dist/stories/components/Form/FormControl/FormControl.svelte +3 -0
  7. package/dist/stories/components/Form/FormControl/FormControl.svelte.d.ts +1 -1
  8. package/dist/stories/components/Form/Label/Label.svelte +5 -2
  9. package/dist/stories/components/Form/Label/Label.svelte.d.ts +1 -1
  10. package/dist/stories/components/Form/Message/Message.svelte +5 -2
  11. package/dist/stories/components/Form/Message/Message.svelte.d.ts +1 -1
  12. package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte +25 -32
  13. package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte.d.ts +5 -5
  14. package/dist/stories/components/Form/Select/Customize/Customize.stories.svelte +120 -0
  15. package/dist/stories/components/Form/Select/Customize/Customize.stories.svelte.d.ts +18 -0
  16. package/dist/stories/components/Form/Select/Events/Events.stories.svelte +138 -0
  17. package/dist/stories/components/Form/Select/Options/OptionFormat.mdx +40 -0
  18. package/dist/stories/components/Form/Select/Roundness/Roundness.stories.svelte +28 -0
  19. package/dist/stories/components/Form/Select/Roundness/Roundness.stories.svelte.d.ts +18 -0
  20. package/dist/stories/components/Form/Select/Select.stories.svelte +114 -0
  21. package/dist/stories/components/Form/Select/Select.stories.svelte.d.ts +22 -0
  22. package/dist/stories/components/Form/Select/Select.svelte +285 -0
  23. package/dist/stories/components/Form/Select/Select.svelte.d.ts +87 -0
  24. package/dist/stories/components/Form/Select/Size/Size.stories.svelte +24 -0
  25. package/dist/stories/components/Form/Select/Size/Size.stories.svelte.d.ts +18 -0
  26. package/dist/stories/components/Form/Select/WithIcon/WithIcon.stories.svelte +39 -0
  27. package/dist/stories/components/Form/Select/WithIcon/WithIcon.stories.svelte.d.ts +18 -0
  28. package/dist/stories/components/Form/TextInput/TextInput.svelte +9 -28
  29. package/dist/stories/components/Form/TextInput/TextInput.svelte.d.ts +8 -5
  30. package/dist/stories/components/Layout/Menu/Menu.stories.svelte +65 -0
  31. package/dist/stories/components/Layout/Menu/Menu.stories.svelte.d.ts +21 -0
  32. package/dist/stories/components/Layout/Menu/Menu.svelte +30 -0
  33. package/dist/stories/components/Layout/Menu/Menu.svelte.d.ts +23 -0
  34. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.stories.svelte +30 -0
  35. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.stories.svelte.d.ts +21 -0
  36. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.svelte +164 -0
  37. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.svelte.d.ts +49 -0
  38. package/dist/stories/components/Layout/Menu/MenuItem/Size/Size.stories.svelte +16 -0
  39. package/dist/stories/components/Layout/Menu/MenuItem/Type/Type.stories.svelte +21 -0
  40. package/dist/stories/components/{Form/SimpleSelect/WithIcon/WithIcon.stories.svelte.d.ts → Layout/Menu/MenuItem/Type/Type.stories.svelte.d.ts} +3 -3
  41. package/dist/stories/components/Layout/Menu/Size/Size.stories.svelte +37 -0
  42. package/dist/stories/components/{Form/SimpleSelect/Roundness/Roundness.stories.svelte.d.ts → Layout/Menu/Size/Size.stories.svelte.d.ts} +3 -3
  43. package/dist/stories/components/Layout/Paper/Color/Color.stories.svelte +1 -1
  44. package/dist/stories/components/Layout/Paper/Paper.stories.svelte +1 -1
  45. package/dist/stories/components/Layout/Paper/Paper.svelte.d.ts +5 -5
  46. package/dist/stories/components/Layout/Separator/Color/Color.stories.svelte +19 -0
  47. package/dist/stories/components/Layout/Separator/Color/Color.stories.svelte.d.ts +26 -0
  48. package/dist/stories/components/Layout/Separator/Separator.stories.svelte +26 -0
  49. package/dist/stories/components/Layout/Separator/Separator.stories.svelte.d.ts +21 -0
  50. package/dist/stories/components/Layout/Separator/Separator.svelte +66 -0
  51. package/dist/stories/components/Layout/Separator/Separator.svelte.d.ts +22 -0
  52. package/dist/stories/components/Layout/Separator/utils/scss/mixins.scss +24 -0
  53. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.stories.svelte +49 -0
  54. package/dist/stories/{components/Form/SimpleSelect/SimpleSelect.stories.svelte.d.ts → developer tools/components/DynamicInput/DynamicInput.stories.svelte.d.ts } +5 -7
  55. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte +92 -0
  56. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte.d.ts +60 -0
  57. package/dist/stories/{components/Form/SimpleSelect/Size/Size.stories.svelte → developer tools/components/DynamicInput/Size/Size.stories.svelte } +5 -8
  58. package/dist/stories/developer tools/components/DynamicInput/Size/Size.stories.svelte.d.ts +26 -0
  59. package/dist/stories/developer tools/components/InputEnclosure/InputEnclosure.svelte +6 -2
  60. package/dist/stories/developer tools/components/InputEnclosure/InputEnclosure.svelte.d.ts +1 -1
  61. package/dist/stories/developer tools/components/Popper/Popper.stories.svelte +119 -0
  62. package/dist/stories/developer tools/components/Popper/Popper.stories.svelte.d.ts +21 -0
  63. package/dist/stories/developer tools/components/Popper/Popper.svelte +77 -0
  64. package/dist/stories/developer tools/components/Popper/Popper.svelte.d.ts +50 -0
  65. package/dist/stories/developer tools/components/Popper/PopperPopup/PopperPopup.stories.svelte +60 -0
  66. package/dist/stories/developer tools/components/Popper/PopperPopup/PopperPopup.stories.svelte.d.ts +21 -0
  67. package/dist/stories/developer tools/components/Popper/PopperPopup/PopperPopup.svelte +66 -0
  68. package/dist/stories/developer tools/components/Popper/PopperPopup/PopperPopup.svelte.d.ts +34 -0
  69. package/dist/stories/developer tools/components/Popper/PopperPopup/utils/getPopupPosition.d.ts +21 -0
  70. package/dist/stories/developer tools/components/Popper/PopperPopup/utils/getPopupPosition.js +62 -0
  71. package/dist/stories/developer tools/components/Popper/Positions/AutoPosition/AutoPosition.stories.svelte +89 -0
  72. package/dist/stories/developer tools/components/Popper/Positions/AutoPosition/AutoPosition.stories.svelte.d.ts +18 -0
  73. package/dist/stories/developer tools/components/Popper/Positions/Positions.stories.svelte +111 -0
  74. package/dist/stories/developer tools/components/Popper/Positions/Positions.stories.svelte.d.ts +18 -0
  75. package/dist/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +3 -5
  76. package/dist/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +0 -4
  77. package/dist/stories/developer tools/components/UtilityButton/UtilityButton.svelte +5 -2
  78. package/dist/stories/developer tools/components/UtilityButton/UtilityButton.svelte.d.ts +1 -1
  79. package/dist/stories/developer tools/directives/clickOutside/clickOutside.d.ts +3 -0
  80. package/dist/stories/developer tools/directives/clickOutside/clickOutside.js +14 -0
  81. package/dist/stories/developer tools/directives/clickOutside/index.mdx +25 -0
  82. package/dist/styles/_z-index.css +9 -0
  83. package/dist/styles/global.css +1 -0
  84. package/dist/types/position.d.ts +4 -0
  85. package/dist/types/position.js +2 -0
  86. package/package.json +3 -3
  87. package/src/lib/index.ts +50 -9
  88. package/src/lib/stories/components/Form/Button/Button.svelte +14 -10
  89. package/src/lib/stories/components/Form/FormControl/FormControl.svelte +7 -4
  90. package/src/lib/stories/components/Form/Label/Label.svelte +4 -2
  91. package/src/lib/stories/components/Form/Message/Message.svelte +4 -2
  92. package/src/lib/stories/components/Form/PasswordInput/PasswordInput.svelte +48 -49
  93. package/src/lib/stories/components/Form/Select/Select.svelte +501 -0
  94. package/src/lib/stories/components/Form/TextInput/TextInput.svelte +32 -59
  95. package/src/lib/stories/components/Layout/Menu/Menu.svelte +65 -0
  96. package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.svelte +268 -0
  97. package/src/lib/stories/components/Layout/Paper/Paper.svelte +8 -9
  98. package/src/lib/stories/components/Layout/Separator/Separator.svelte +96 -0
  99. package/src/lib/stories/components/Layout/Separator/utils/scss/mixins.scss +24 -0
  100. package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.svelte +195 -0
  101. package/src/lib/stories/developer tools/components/InputEnclosure/InputEnclosure.svelte +5 -2
  102. package/src/lib/stories/developer tools/components/Popper/Popper.svelte +159 -0
  103. package/src/lib/stories/developer tools/components/Popper/PopperPopup/PopperPopup.svelte +120 -0
  104. package/src/lib/stories/developer tools/components/Popper/PopperPopup/utils/getPopupPosition.ts +87 -0
  105. package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.svelte +4 -2
  106. package/src/lib/stories/developer tools/directives/clickOutside/clickOutside.ts +17 -0
  107. package/src/lib/styles/_z-index.css +9 -0
  108. package/src/lib/styles/global.css +1 -0
  109. package/src/lib/types/position.ts +5 -0
  110. package/dist/stories/components/Form/SimpleSelect/Events/Events.stories.svelte +0 -47
  111. package/dist/stories/components/Form/SimpleSelect/Roundness/Roundness.stories.svelte +0 -24
  112. package/dist/stories/components/Form/SimpleSelect/SimpleSelect.stories.svelte +0 -57
  113. package/dist/stories/components/Form/SimpleSelect/SimpleSelect.svelte +0 -69
  114. package/dist/stories/components/Form/SimpleSelect/SimpleSelect.svelte.d.ts +0 -51
  115. package/dist/stories/components/Form/SimpleSelect/WithIcon/WithIcon.stories.svelte +0 -36
  116. package/src/lib/stories/components/Form/SimpleSelect/SimpleSelect.svelte +0 -160
  117. /package/dist/stories/components/Form/{SimpleSelect → Select}/Events/Events.stories.svelte.d.ts +0 -0
  118. /package/dist/stories/components/{Form/SimpleSelect → Layout/Menu/MenuItem}/Size/Size.stories.svelte.d.ts +0 -0
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Roundness: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Roundness = InstanceType<typeof Roundness>;
18
+ export default Roundness;
@@ -0,0 +1,114 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import Select, {} from './Select.svelte';
3
+ import { componentRoundnessArray } from '../../../../types/roundness.js';
4
+ import { componentSizeArray } from '../../../../types/size.js';
5
+ export const storySelectArgTypes = {
6
+ roundness: {
7
+ control: { type: 'select' },
8
+ options: componentRoundnessArray,
9
+ },
10
+ size: {
11
+ control: { type: 'select' },
12
+ options: componentSizeArray,
13
+ },
14
+ };
15
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
16
+ const { Story } = defineMeta({
17
+ component: Select,
18
+ tags: ['autodocs'],
19
+ argTypes: storySelectArgTypes,
20
+ parameters: {
21
+ docs: {
22
+ story: {
23
+ height: '400px',
24
+ inline: false,
25
+ },
26
+ },
27
+ },
28
+ });
29
+ export const selectOptions = [
30
+ {
31
+ value: 1,
32
+ label: 'One',
33
+ },
34
+ {
35
+ value: 2,
36
+ label: 'Two',
37
+ },
38
+ {
39
+ value: 3,
40
+ label: 'Three',
41
+ },
42
+ {
43
+ value: 4,
44
+ label: 'Four',
45
+ },
46
+ {
47
+ value: 5,
48
+ label: 'Five',
49
+ },
50
+ {
51
+ value: 6,
52
+ label: 'Six',
53
+ disabled: true,
54
+ },
55
+ {
56
+ value: 7,
57
+ label: 'Seven',
58
+ },
59
+ {
60
+ value: 8,
61
+ label: 'Eight',
62
+ },
63
+ {
64
+ value: 9,
65
+ label: 'Nine',
66
+ },
67
+ ];
68
+ const options = selectOptions;
69
+ let value = $state(options[0]);
70
+ </script>
71
+
72
+ <!-- Select with default style -->
73
+ <Story name="Default" asChild>
74
+ <Select {options} {value} onselect={(val: SelectOption) => (value = val)} />
75
+ </Story>
76
+
77
+ <Story name="Searchable" asChild>
78
+ <Select
79
+ {options}
80
+ {value}
81
+ searchable
82
+ optionsPlaceholder="No results"
83
+ onselect={(val: SelectOption) => (value = val)}
84
+ />
85
+ </Story>
86
+
87
+ <Story name="Clearable" asChild>
88
+ <Select
89
+ {options}
90
+ {value}
91
+ clearable
92
+ onselect={(val: SelectOption) => (value = val)}
93
+ onclear={() => (value = undefined)}
94
+ placeholder="Select option"
95
+ />
96
+ </Story>
97
+
98
+ <Story name="PopupMaxHeight" asChild>
99
+ <Select
100
+ {options}
101
+ {value}
102
+ onselect={(val: SelectOption) => (value = val)}
103
+ popupMaxHeight="200px"
104
+ />
105
+ </Story>
106
+
107
+ <!-- Format look and feel of input content. [More Customizations](?path=/docs/components-form-select-customize--docs) -->
108
+ <Story name="CustomInputContent" asChild>
109
+ <Select {options} {value} onselect={(val: SelectOption) => (value = val)}>
110
+ {#snippet customInputContent(selectedOption)}
111
+ {selectedOption.label} 💯💯💯
112
+ {/snippet}
113
+ </Select>
114
+ </Story>
@@ -0,0 +1,22 @@
1
+ import Select, { type SelectOption } from './Select.svelte';
2
+ import type { StoryBookArgTypes } from '../../../../storybook-types.js';
3
+ export declare const storySelectArgTypes: StoryBookArgTypes;
4
+ export declare const selectOptions: SelectOption[];
5
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
6
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
7
+ $$bindings?: Bindings;
8
+ } & Exports;
9
+ (internal: unknown, props: {
10
+ $$events?: Events;
11
+ $$slots?: Slots;
12
+ }): Exports & {
13
+ $set?: any;
14
+ $on?: any;
15
+ };
16
+ z_$$bindings?: Bindings;
17
+ }
18
+ declare const Select: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
19
+ [evt: string]: CustomEvent<any>;
20
+ }, {}, {}, string>;
21
+ type Select = InstanceType<typeof Select>;
22
+ export default Select;
@@ -0,0 +1,285 @@
1
+ <script lang="ts" module>export {};
2
+ </script>
3
+
4
+ <script lang="ts">import InputEnclosure from '../../../developer tools/components/InputEnclosure/InputEnclosure.svelte';
5
+ import UtilityButton from '../../../developer tools/components/UtilityButton/UtilityButton.svelte';
6
+ import Icon from '@iconify/svelte';
7
+ import { DynamicInput, Menu, MenuItem, Popper, } from '../../../../index.js';
8
+ let { size = 'normal', roundness = 1, outline = true, name, id, class: className = '', disabled = false, onchange, oninput, onselect, onblur, onfocus, onpaste, oncopy, oncut, before, after, error = false, value, placeholder, ref = $bindable(), readonly = false, searchable = false, clearable = false, onclear, options: optionsRaw, customInputContent: customInputContentInternal, customMenuItemContent: customMenuItemContentInternal, customPopupContent: customPopupContentInternal, customPlaceholderMenuItemContent: customPlaceholderMenuItemContentInternal, popupMaxHeight = '300px', paperProps, popperProps, menuProps, menuItemProps, optionsPlaceholder = 'No Options', } = $props();
9
+ let open = $state(false);
10
+ let onInputStart = $state(false);
11
+ const selectedOption = $derived(value);
12
+ let searchTerm = $state(value?.label.trim() || '');
13
+ let options = $state(optionsRaw);
14
+ let menuRef = $state(undefined);
15
+ let menuItemIndex = $state(0);
16
+ $effect(() => {
17
+ if (!onInputStart) {
18
+ options = optionsRaw;
19
+ return;
20
+ }
21
+ const searchTermSimplified = searchTerm.trim().toLowerCase();
22
+ if (!searchTermSimplified) {
23
+ options = optionsRaw;
24
+ return;
25
+ }
26
+ options = optionsRaw.filter((item) => item.label.trim().toLowerCase().includes(searchTermSimplified));
27
+ });
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ let customInputContentTyped = customInputContentInternal;
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ let customMenuItemContentTyped = customMenuItemContentInternal;
32
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
33
+ let customPopupContentTyped = customPopupContentInternal;
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ let customPlaceholderMenuItemContentTyped = customPlaceholderMenuItemContentInternal;
36
+ function closeMenu() {
37
+ open = false;
38
+ menuItemIndex = 0;
39
+ ref?.blur();
40
+ }
41
+ function openMenu() {
42
+ open = true;
43
+ const menuItemIndexNew = options.findIndex((item) => item.value === selectedOption?.value);
44
+ if (menuItemIndexNew < 0) {
45
+ menuItemIndex = 0;
46
+ }
47
+ else {
48
+ menuItemIndex = menuItemIndexNew;
49
+ }
50
+ }
51
+ function onfocusMod(e) {
52
+ openMenu();
53
+ if (onfocus) {
54
+ onfocus(e);
55
+ }
56
+ }
57
+ function onblurMod(e) {
58
+ if (onblur) {
59
+ onblur(e);
60
+ }
61
+ }
62
+ function onClickOutside() {
63
+ searchTerm = selectedOption?.label || '';
64
+ onInputStart = false;
65
+ closeMenu();
66
+ }
67
+ function onselectMod(val) {
68
+ searchTerm = val.label;
69
+ onInputStart = false;
70
+ closeMenu();
71
+ if (onselect) {
72
+ onselect(val);
73
+ }
74
+ }
75
+ function oninputMod(e) {
76
+ const target = e.target;
77
+ searchTerm = target.value;
78
+ onInputStart = true;
79
+ if (oninput) {
80
+ oninput(e);
81
+ }
82
+ }
83
+ function onclearMod(e) {
84
+ searchTerm = '';
85
+ onInputStart = false;
86
+ closeMenu();
87
+ if (onclear) {
88
+ onclear(e);
89
+ }
90
+ }
91
+ function onKeyBoardEnter(selectedItemIndex) {
92
+ const targetOption = options[selectedItemIndex];
93
+ if (!targetOption) {
94
+ return;
95
+ }
96
+ if (targetOption.disabled) {
97
+ return;
98
+ }
99
+ onselectMod(targetOption);
100
+ }
101
+ function onKeyboardNavigation(e) {
102
+ let keyHit = undefined;
103
+ if (!menuRef) {
104
+ return;
105
+ }
106
+ if (!open) {
107
+ return;
108
+ }
109
+ switch (e.key) {
110
+ case 'ArrowDown':
111
+ case 'ArrowUp':
112
+ case 'Enter':
113
+ keyHit = e.key;
114
+ e.preventDefault();
115
+ break;
116
+ default:
117
+ break;
118
+ }
119
+ if (!keyHit) {
120
+ return;
121
+ }
122
+ const listItems = menuRef.querySelectorAll(':scope > li.dodo-ui-MenuItem');
123
+ if (!listItems.length) {
124
+ return;
125
+ }
126
+ for (let index = 0; index < listItems.length; index++) {
127
+ const element = listItems[index];
128
+ element.classList.remove('hover');
129
+ }
130
+ let newMenuItemIndex = menuItemIndex;
131
+ if (keyHit === 'ArrowDown') {
132
+ if (listItems[newMenuItemIndex + 1]) {
133
+ newMenuItemIndex = newMenuItemIndex + 1;
134
+ }
135
+ else {
136
+ newMenuItemIndex = 0;
137
+ }
138
+ }
139
+ else if (keyHit === 'ArrowUp') {
140
+ if (listItems[newMenuItemIndex - 1]) {
141
+ newMenuItemIndex = newMenuItemIndex - 1;
142
+ }
143
+ else {
144
+ newMenuItemIndex = listItems.length - 1;
145
+ }
146
+ }
147
+ else if (keyHit === 'Enter') {
148
+ onKeyBoardEnter(newMenuItemIndex);
149
+ return;
150
+ }
151
+ const targetItem = listItems[newMenuItemIndex];
152
+ targetItem.classList.add('hover');
153
+ targetItem.focus();
154
+ targetItem.scrollIntoView({ block: 'nearest' });
155
+ menuItemIndex = newMenuItemIndex;
156
+ }
157
+ $effect(() => {
158
+ if (!menuRef) {
159
+ return;
160
+ }
161
+ if (!open) {
162
+ return;
163
+ }
164
+ const targetItem = menuRef.querySelector(':scope > li.dodo-ui-MenuItem.selected');
165
+ if (targetItem) {
166
+ targetItem.classList.add('hover');
167
+ targetItem.focus();
168
+ targetItem.scrollIntoView({ block: 'nearest' });
169
+ }
170
+ window.addEventListener('keydown', onKeyboardNavigation);
171
+ return () => {
172
+ window.removeEventListener('keydown', onKeyboardNavigation);
173
+ };
174
+ });
175
+ </script>
176
+
177
+ <div class={['dodo-ui-Select', className].join(' ')}>
178
+ <Popper fullWidth {open} {onClickOutside} {...popperProps} {popupMaxHeight} {paperProps}>
179
+ <div
180
+ class:outline
181
+ class:disabled
182
+ class:error
183
+ class={[
184
+ 'Select',
185
+ `size--${size}`,
186
+ `${open ? 'focused' : ''}`,
187
+ `roundness--${roundness}`,
188
+ className,
189
+ ].join(' ')}
190
+ >
191
+ <InputEnclosure
192
+ {outline}
193
+ {disabled}
194
+ {error}
195
+ focused={open}
196
+ {size}
197
+ {roundness}
198
+ {before}
199
+ {after}
200
+ >
201
+ <DynamicInput
202
+ type="text"
203
+ {name}
204
+ {id}
205
+ {disabled}
206
+ bind:ref
207
+ oninput={oninputMod}
208
+ {onchange}
209
+ onfocus={onfocusMod}
210
+ onblur={onblurMod}
211
+ {onpaste}
212
+ {oncopy}
213
+ {oncut}
214
+ {placeholder}
215
+ value={searchable ? searchTerm : selectedOption?.label}
216
+ {readonly}
217
+ variant={searchable ? 'input' : 'button'}
218
+ >
219
+ {#snippet customInputContent()}
220
+ {#if customInputContentTyped}
221
+ {@render customInputContentTyped(selectedOption)}
222
+ {:else}
223
+ {selectedOption?.label || placeholder}
224
+ {/if}
225
+ {/snippet}
226
+ </DynamicInput>
227
+
228
+ {#if selectedOption?.label && clearable && !disabled}
229
+ <div class:after class="SelectClear">
230
+ <UtilityButton {size} title="Clear" onclick={onclearMod}>
231
+ <Icon icon="material-symbols:close-small" width="24" height="24" />
232
+ </UtilityButton>
233
+ </div>
234
+ {/if}
235
+ </InputEnclosure>
236
+ </div>
237
+
238
+ {#snippet popupChildren()}
239
+ {#if customPopupContentTyped}
240
+ {@render customPopupContentTyped(options, selectedOption)}
241
+ {:else}
242
+ <Menu bind:ref={menuRef} {...menuProps}>
243
+ {#if options.length}
244
+ {#each options as option (option.value)}
245
+ <MenuItem
246
+ onclick={() => onselectMod(option)}
247
+ type="button"
248
+ disabled={option.disabled}
249
+ selected={selectedOption?.value === option.value}
250
+ {...menuItemProps}
251
+ >
252
+ {#if customMenuItemContentTyped}
253
+ {@render customMenuItemContentTyped(
254
+ option,
255
+ selectedOption?.value === option.value,
256
+ )}
257
+ {:else}
258
+ {option.label}
259
+ {/if}
260
+ </MenuItem>
261
+ {/each}
262
+ {:else}
263
+ <MenuItem type="text" disabled={true} {...menuItemProps}>
264
+ {#if customPlaceholderMenuItemContentTyped}
265
+ {@render customPlaceholderMenuItemContentTyped()}
266
+ {:else}
267
+ {optionsPlaceholder}
268
+ {/if}
269
+ </MenuItem>
270
+ {/if}
271
+ </Menu>
272
+ {/if}
273
+ {/snippet}
274
+ </Popper>
275
+ </div>
276
+
277
+ <style>.dodo-ui-Select .Select.size--normal .SelectClear.after {
278
+ margin-right: calc(var(--dodo-ui-space-small) * 2);
279
+ }
280
+ .dodo-ui-Select .Select.size--small .SelectClear.after {
281
+ margin-right: var(--dodo-ui-space);
282
+ }
283
+ .dodo-ui-Select .Select.size--large .SelectClear.after {
284
+ margin-right: calc(var(--dodo-ui-space) * 2);
285
+ }</style>
@@ -0,0 +1,87 @@
1
+ import type { ComponentSize } from '../../../../types/size.js';
2
+ import type { ComponentRoundness } from '../../../../types/roundness.js';
3
+ import type { Snippet } from 'svelte';
4
+ import type { ChangeEventHandler, ClipboardEventHandler, FocusEventHandler, FormEventHandler, MouseEventHandler } from 'svelte/elements';
5
+ export type SelectOption = {
6
+ value: string | number | boolean | null | undefined;
7
+ label: string;
8
+ disabled?: boolean;
9
+ };
10
+ export interface SelectProps {
11
+ /** How large should the button be? */
12
+ size?: ComponentSize;
13
+ /** want a searchable Select? */
14
+ options: SelectOption[];
15
+ /** want a searchable Select? */
16
+ searchable?: boolean;
17
+ /** want a clearable Select? */
18
+ clearable?: boolean;
19
+ /** onselect event handler */
20
+ onselect?: (val: SelectOption) => void;
21
+ /** onclear event handler */
22
+ onclear?: MouseEventHandler<HTMLButtonElement>;
23
+ /** Select ref */
24
+ ref?: HTMLInputElement | HTMLButtonElement;
25
+ /** How round should the border radius be? */
26
+ roundness?: ComponentRoundness;
27
+ /** Add a border around the button. Default True */
28
+ outline?: boolean;
29
+ /** Select value */
30
+ value: SelectOption | undefined;
31
+ /** How round should the border radius be? */
32
+ placeholder?: string;
33
+ /** Placeholder if there are no options found*/
34
+ optionsPlaceholder?: string;
35
+ /** disabled state */
36
+ disabled?: boolean;
37
+ /** Read only ? */
38
+ readonly?: boolean;
39
+ /** is there any associated Error ? */
40
+ error?: boolean;
41
+ /** Name */
42
+ name?: string;
43
+ /** Id */
44
+ id?: string;
45
+ /** Icon before button content */
46
+ before?: Snippet;
47
+ /** Icon after button content */
48
+ after?: Snippet;
49
+ /** Custom css class*/
50
+ class?: string;
51
+ /** onchange event handler */
52
+ onchange?: ChangeEventHandler<HTMLInputElement>;
53
+ /** oninput event handler */
54
+ oninput?: FormEventHandler<HTMLInputElement>;
55
+ /** onblur event handler */
56
+ onblur?: FocusEventHandler<HTMLInputElement | HTMLButtonElement>;
57
+ /** onfocus event handler */
58
+ onfocus?: FocusEventHandler<HTMLInputElement | HTMLButtonElement>;
59
+ /** onpaste event handler */
60
+ onpaste?: ClipboardEventHandler<HTMLInputElement>;
61
+ /** oncopy event handler */
62
+ oncopy?: ClipboardEventHandler<HTMLInputElement>;
63
+ /** oncut event handler */
64
+ oncut?: ClipboardEventHandler<HTMLInputElement>;
65
+ /** custom Content Formatting for variant button */
66
+ customInputContent?: (val: SelectOption) => Snippet;
67
+ /** custom Content Formatting for variant button */
68
+ customMenuItemContent?: (val: SelectOption, selected: boolean) => Snippet;
69
+ /** Custom Popup Content */
70
+ customPopupContent?: (options: SelectOption[], selectedOption: SelectOption) => Snippet;
71
+ /** custom Content Formatting for variant button */
72
+ customPlaceholderMenuItemContent?: () => Snippet;
73
+ /** PopperPopup Max height. Use css compatible value */
74
+ popupMaxHeight?: string;
75
+ /** PaperProps: Paper component props for Popup */
76
+ paperProps?: Partial<PaperProps>;
77
+ /** PopperProps: Popper component props */
78
+ popperProps?: Partial<PopperProps>;
79
+ /** MenuProps: Menu component props */
80
+ menuProps?: Partial<MenuProps>;
81
+ /** MenuItem: Menu component props */
82
+ menuItemProps?: Partial<MenuItemProps>;
83
+ }
84
+ import { type MenuItemProps, type MenuProps, type PaperProps, type PopperProps } from '../../../../index.js';
85
+ declare const Select: import("svelte").Component<SelectProps, {}, "ref">;
86
+ type Select = ReturnType<typeof Select>;
87
+ export default Select;
@@ -0,0 +1,24 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import Select, {} from '../Select.svelte';
3
+ import { selectOptions, storySelectArgTypes } from '../Select.stories.svelte';
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: Select,
7
+ tags: ['autodocs'],
8
+ argTypes: storySelectArgTypes,
9
+ parameters: {
10
+ docs: {
11
+ story: {
12
+ height: '400px',
13
+ inline: false,
14
+ },
15
+ },
16
+ },
17
+ });
18
+ const options = selectOptions;
19
+ let value = $state(options[0]);
20
+ </script>
21
+
22
+ <Story name="Normal" args={{ options, value }} />
23
+ <Story name="Small" args={{ options, value, size: 'small' }} />
24
+ <Story name="Large" args={{ options, value, size: 'large' }} />
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const Size: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Size = InstanceType<typeof Size>;
18
+ export default Size;
@@ -0,0 +1,39 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import Select, {} from '../Select.svelte';
3
+ import { selectOptions, storySelectArgTypes } from '../Select.stories.svelte';
4
+ import Icon from '@iconify/svelte';
5
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
6
+ const { Story } = defineMeta({
7
+ component: Select,
8
+ tags: ['autodocs'],
9
+ argTypes: storySelectArgTypes,
10
+ parameters: {
11
+ docs: {
12
+ story: {
13
+ height: '400px',
14
+ inline: false,
15
+ },
16
+ },
17
+ },
18
+ });
19
+ const options = selectOptions;
20
+ let value = $state(options[0]);
21
+ </script>
22
+
23
+ <!-- Select icon in front. -->
24
+ <Story name="Icon Before" asChild>
25
+ <Select {value} {options}>
26
+ {#snippet before()}
27
+ <Icon icon="material-symbols:content-copy" />
28
+ {/snippet}
29
+ </Select>
30
+ </Story>
31
+
32
+ <!-- Select icon in front. -->
33
+ <Story name="Icon After" asChild>
34
+ <Select {value} {options}>
35
+ {#snippet after()}
36
+ <Icon icon="material-symbols:download-2" />
37
+ {/snippet}
38
+ </Select>
39
+ </Story>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const WithIcon: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type WithIcon = InstanceType<typeof WithIcon>;
18
+ export default WithIcon;