@flightlesslabs/dodo-ui 0.7.1 → 0.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.
Files changed (98) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +3 -0
  3. package/dist/stories/components/Form/Select/Customize/Customize.stories.svelte +16 -1
  4. package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +59 -0
  5. package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte.d.ts +18 -0
  6. package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +54 -0
  7. package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte.d.ts +18 -0
  8. package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte +83 -0
  9. package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte.d.ts +18 -0
  10. package/dist/stories/components/Form/Select/Select.svelte +107 -123
  11. package/dist/stories/components/Form/Select/Select.svelte.d.ts +15 -2
  12. package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +28 -0
  13. package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte.d.ts +18 -0
  14. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +51 -0
  15. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte.d.ts +22 -0
  16. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +129 -0
  17. package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte.d.ts +81 -0
  18. package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +46 -0
  19. package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte.d.ts +18 -0
  20. package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +27 -0
  21. package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte.d.ts +18 -0
  22. package/dist/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
  23. package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.svelte.d.ts +1 -1
  24. package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte +1 -0
  25. package/package.json +17 -18
  26. package/src/lib/index.ts +13 -0
  27. package/src/lib/stories/Home.mdx +59 -0
  28. package/src/lib/stories/assets/dark-theme-toggle.png +0 -0
  29. package/src/lib/stories/components/Form/Button/Button.stories.svelte +61 -0
  30. package/src/lib/stories/components/Form/Button/Color/Color.stories.svelte +43 -0
  31. package/src/lib/stories/components/Form/Button/Events/Events.stories.svelte +36 -0
  32. package/src/lib/stories/components/Form/Button/IconButton/IconButton.stories.svelte +43 -0
  33. package/src/lib/stories/components/Form/Button/Roundness/Roundness.stories.svelte +23 -0
  34. package/src/lib/stories/components/Form/Button/Size/Size.stories.svelte +16 -0
  35. package/src/lib/stories/components/Form/Button/Variant/Variant.stories.svelte +18 -0
  36. package/src/lib/stories/components/Form/FormControl/FormControl.stories.svelte +28 -0
  37. package/src/lib/stories/components/Form/Label/Label.stories.svelte +13 -0
  38. package/src/lib/stories/components/Form/Message/Color/Color.stories.svelte +36 -0
  39. package/src/lib/stories/components/Form/Message/Message.stories.svelte +27 -0
  40. package/src/lib/stories/components/Form/Message/Size/Size.stories.svelte +22 -0
  41. package/src/lib/stories/components/Form/PasswordInput/Events/Events.stories.svelte +110 -0
  42. package/src/lib/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +59 -0
  43. package/src/lib/stories/components/Form/PasswordInput/Roundness/Roundness.stories.svelte +20 -0
  44. package/src/lib/stories/components/Form/PasswordInput/Size/Size.stories.svelte +16 -0
  45. package/src/lib/stories/components/Form/PasswordInput/WithIcon/WithIcon.stories.svelte +31 -0
  46. package/src/lib/stories/components/Form/Select/Customize/Customize.stories.svelte +139 -0
  47. package/src/lib/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +63 -0
  48. package/src/lib/stories/components/Form/Select/Events/Events.stories.svelte +144 -0
  49. package/src/lib/stories/components/Form/Select/Options/OptionFormat.mdx +40 -0
  50. package/src/lib/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +58 -0
  51. package/src/lib/stories/components/Form/Select/Positions/Positions.stories.svelte +87 -0
  52. package/src/lib/stories/components/Form/Select/Roundness/Roundness.stories.svelte +32 -0
  53. package/src/lib/stories/components/Form/Select/Select.stories.svelte +121 -0
  54. package/src/lib/stories/components/Form/Select/Select.svelte +153 -146
  55. package/src/lib/stories/components/Form/Select/Size/Size.stories.svelte +28 -0
  56. package/src/lib/stories/components/Form/Select/WithIcon/WithIcon.stories.svelte +43 -0
  57. package/src/lib/stories/components/Form/TextInput/Events/Events.stories.svelte +97 -0
  58. package/src/lib/stories/components/Form/TextInput/Roundness/Roundness.stories.svelte +21 -0
  59. package/src/lib/stories/components/Form/TextInput/Size/Size.stories.svelte +17 -0
  60. package/src/lib/stories/components/Form/TextInput/TextInput.stories.svelte +43 -0
  61. package/src/lib/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte +47 -0
  62. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +30 -0
  63. package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +56 -0
  64. package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +262 -0
  65. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +48 -0
  66. package/src/lib/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +29 -0
  67. package/src/lib/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
  68. package/src/lib/stories/components/Layout/Menu/Menu.stories.svelte +69 -0
  69. package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.stories.svelte +34 -0
  70. package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.svelte +1 -1
  71. package/src/lib/stories/components/Layout/Menu/MenuItem/Size/Size.stories.svelte +16 -0
  72. package/src/lib/stories/components/Layout/Menu/MenuItem/Type/Type.stories.svelte +21 -0
  73. package/src/lib/stories/components/Layout/Menu/Size/Size.stories.svelte +37 -0
  74. package/src/lib/stories/components/Layout/Paper/Color/Color.stories.svelte +63 -0
  75. package/src/lib/stories/components/Layout/Paper/Paper.stories.svelte +50 -0
  76. package/src/lib/stories/components/Layout/Paper/Roundness/Roundness.stories.svelte +25 -0
  77. package/src/lib/stories/components/Layout/Paper/Shadow/Shadow.stories.svelte +24 -0
  78. package/src/lib/stories/components/Layout/Separator/Color/Color.stories.svelte +19 -0
  79. package/src/lib/stories/components/Layout/Separator/Separator.stories.svelte +30 -0
  80. package/src/lib/stories/developer tools/Intro.mdx +9 -0
  81. package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.stories.svelte +53 -0
  82. package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.svelte +1 -0
  83. package/src/lib/stories/developer tools/components/DynamicInput/Size/Size.stories.svelte +17 -0
  84. package/src/lib/stories/developer tools/components/InputEnclosure/InputEnclosure.stories.svelte +38 -0
  85. package/src/lib/stories/developer tools/components/InputEnclosure/Roundness/Roundness.stories.svelte +20 -0
  86. package/src/lib/stories/developer tools/components/InputEnclosure/Size/Size.stories.svelte +16 -0
  87. package/src/lib/stories/developer tools/components/InputEnclosure/WithIcon/WithIcon.stories.svelte +47 -0
  88. package/src/lib/stories/developer tools/components/Popper/Popper.stories.svelte +124 -0
  89. package/src/lib/stories/developer tools/components/Popper/PopperPopup/PopperPopup.stories.svelte +64 -0
  90. package/src/lib/stories/developer tools/components/Popper/Positions/AutoPosition/AutoPosition.stories.svelte +92 -0
  91. package/src/lib/stories/developer tools/components/Popper/Positions/Positions.stories.svelte +114 -0
  92. package/src/lib/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +25 -0
  93. package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +30 -0
  94. package/src/lib/stories/developer tools/directives/clickOutside/index.mdx +25 -0
  95. package/src/lib/stories/developer tools/philosophy/Colors/Colors.mdx +43 -0
  96. package/src/lib/stories/developer tools/philosophy/Colors/Colors.stories.svelte +22 -0
  97. package/src/lib/stories/developer tools/philosophy/Colors/Opacity.stories.svelte +11 -0
  98. package/src/lib/stories/developer tools/philosophy/Themes.mdx +23 -0
@@ -7,6 +7,7 @@ export type SelectOption = {
7
7
  label: string;
8
8
  disabled?: boolean;
9
9
  };
10
+ export type SelectDropdownArrowPosition = false | 'before' | 'after';
10
11
  export interface SelectProps {
11
12
  /** How large should the button be? */
12
13
  size?: ComponentSize;
@@ -67,7 +68,7 @@ export interface SelectProps {
67
68
  /** custom Content Formatting for variant button */
68
69
  customMenuItemContent?: (val: SelectOption, selected: boolean) => Snippet;
69
70
  /** Custom Popup Content */
70
- customPopupContent?: (options: SelectOption[], selectedOption: SelectOption) => Snippet;
71
+ customPopupContent?: (options: SelectOption[], selectedOption: SelectOption, onselect: (val: SelectOption) => void) => Snippet;
71
72
  /** custom Content Formatting for variant button */
72
73
  customPlaceholderMenuItemContent?: () => Snippet;
73
74
  /** PopperPopup Max height. Use css compatible value */
@@ -80,8 +81,20 @@ export interface SelectProps {
80
81
  menuProps?: Partial<MenuProps>;
81
82
  /** MenuItem: Menu component props */
82
83
  menuItemProps?: Partial<MenuItemProps>;
84
+ /** Dropdown Arrow Icon */
85
+ customDropdownArrowIcon?: (open: boolean) => Snippet;
86
+ /** Select Dropdown Arrow Position */
87
+ dropdownArrowPosition?: SelectDropdownArrowPosition;
88
+ /** Popup stick horizontally */
89
+ popupPositionX?: PositionX;
90
+ /** Popup stick vertically */
91
+ popupPositionY?: PositionY;
92
+ /** Lock positions, disable auto top, bottom position based */
93
+ lockPoistions?: boolean;
94
+ /** Popper Height For Vertical Position, default 300 */
95
+ popperHeightForVerticalPosition?: number;
83
96
  }
84
- import { type MenuItemProps, type MenuProps, type PaperProps, type PopperProps } from '../../../../index.js';
97
+ import { type MenuItemProps, type MenuProps, type PaperProps, type PopperProps, type PositionX, type PositionY } from '../../../../index.js';
85
98
  declare const Select: import("svelte").Component<SelectProps, {}, "ref">;
86
99
  type Select = ReturnType<typeof Select>;
87
100
  export default Select;
@@ -0,0 +1,28 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import DynamicMenu from '../DynamicMenu.svelte';
3
+ import { dynamicMenuItemOptions, storyDynamicMenuArgTypes } from '../DynamicMenu.stories.svelte';
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: DynamicMenu,
7
+ tags: ['autodocs'],
8
+ argTypes: storyDynamicMenuArgTypes,
9
+ });
10
+ </script>
11
+
12
+ <!-- Custom Menu Item Content -->
13
+ <Story name="CustomMenuItemContent" asChild>
14
+ <DynamicMenu options={dynamicMenuItemOptions}>
15
+ {#snippet customMenuItemContent(option, selectedOption)}
16
+ {selectedOption?.id === option.id ? '✅' : ''} {option.label} 💯💯💯
17
+ {/snippet}
18
+ </DynamicMenu>
19
+ </Story>
20
+
21
+ <!-- Custom Menu Item Placeholder Content -->
22
+ <Story name="CustomPlaceholderMenuItemContent" asChild>
23
+ <DynamicMenu options={[]} showOptionsPlaceholder>
24
+ {#snippet customPlaceholderMenuItemContent()}
25
+ No dice 💯💯💯
26
+ {/snippet}
27
+ </DynamicMenu>
28
+ </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 Customize: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Customize = InstanceType<typeof Customize>;
18
+ export default Customize;
@@ -0,0 +1,51 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import DynamicMenu, {} from './DynamicMenu.svelte';
3
+ export const storyDynamicMenuArgTypes = {};
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: DynamicMenu,
7
+ tags: ['autodocs'],
8
+ argTypes: storyDynamicMenuArgTypes,
9
+ });
10
+ export const dynamicMenuItemOptions = [
11
+ {
12
+ id: '1',
13
+ label: 'One',
14
+ },
15
+ {
16
+ id: '2',
17
+ label: 'Two',
18
+ },
19
+ {
20
+ id: '3',
21
+ label: 'Three',
22
+ },
23
+ {
24
+ id: '4',
25
+ label: 'Four',
26
+ },
27
+ {
28
+ id: '5',
29
+ label: 'Five',
30
+ },
31
+ {
32
+ id: '6',
33
+ disabled: true,
34
+ label: 'Five',
35
+ },
36
+ ];
37
+ </script>
38
+
39
+ <!-- Default DynamicMenu -->
40
+ <Story name="Default" args={{ options: dynamicMenuItemOptions }} />
41
+
42
+ <!-- Selected Option -->
43
+ <Story
44
+ name="SelectedOption"
45
+ args={{ options: dynamicMenuItemOptions, selectedOption: dynamicMenuItemOptions[1] }}
46
+ />
47
+
48
+ <Story
49
+ name="ShowPlaceholder"
50
+ args={{ options: [], showOptionsPlaceholder: true, optionsPlaceholder: 'No content found.' }}
51
+ />
@@ -0,0 +1,22 @@
1
+ import DynamicMenu, { type DynamicMenuItemOption } from './DynamicMenu.svelte';
2
+ import type { StoryBookArgTypes } from '../../../../../storybook-types.js';
3
+ export declare const storyDynamicMenuArgTypes: StoryBookArgTypes;
4
+ export declare const dynamicMenuItemOptions: DynamicMenuItemOption[];
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 DynamicMenu: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
19
+ [evt: string]: CustomEvent<any>;
20
+ }, {}, {}, string>;
21
+ type DynamicMenu = InstanceType<typeof DynamicMenu>;
22
+ export default DynamicMenu;
@@ -0,0 +1,129 @@
1
+ <script lang="ts" module>export {};
2
+ </script>
3
+
4
+ <script lang="ts">import Menu from '../Menu.svelte';
5
+ import { MenuItem } from '../../../../../index.js';
6
+ let { id, class: className = '', ref = $bindable(), size, separator, width, height, options, selectedOption, customMenuItemContent, customPlaceholderMenuItemContent, menuItemProps, keyboardNavigation = false, onEnter, onEsc, onclick, showOptionsPlaceholder = false, optionsPlaceholder = 'No options found', } = $props();
7
+ let menuItemIndex = $state(0);
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ let customMenuItemContentTyped = customMenuItemContent;
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ let customPlaceholderMenuItemContentTyped = customPlaceholderMenuItemContent;
12
+ function onKeyboardNavigation(e) {
13
+ let keyHit = undefined;
14
+ if (!ref) {
15
+ return;
16
+ }
17
+ switch (e.key) {
18
+ case 'ArrowDown':
19
+ case 'ArrowUp':
20
+ keyHit = e.key;
21
+ e.preventDefault();
22
+ break;
23
+ case 'Enter':
24
+ case 'Esc':
25
+ keyHit = e.key;
26
+ break;
27
+ default:
28
+ break;
29
+ }
30
+ if (!keyHit) {
31
+ return;
32
+ }
33
+ if (keyHit === 'Enter') {
34
+ if (onEnter) {
35
+ onEnter(e, menuItemIndex);
36
+ }
37
+ return;
38
+ }
39
+ else if (keyHit === 'Esc') {
40
+ if (onEsc) {
41
+ onEsc(e, menuItemIndex);
42
+ }
43
+ return;
44
+ }
45
+ const listItems = ref.querySelectorAll(':scope > li.dodo-ui-MenuItem');
46
+ if (!listItems.length) {
47
+ return;
48
+ }
49
+ for (let index = 0; index < listItems.length; index++) {
50
+ const element = listItems[index];
51
+ element.classList.remove('hover');
52
+ }
53
+ let newMenuItemIndex = menuItemIndex;
54
+ if (keyHit === 'ArrowDown') {
55
+ if (listItems[newMenuItemIndex + 1]) {
56
+ newMenuItemIndex = newMenuItemIndex + 1;
57
+ }
58
+ else {
59
+ newMenuItemIndex = 0;
60
+ }
61
+ }
62
+ else if (keyHit === 'ArrowUp') {
63
+ if (listItems[newMenuItemIndex - 1]) {
64
+ newMenuItemIndex = newMenuItemIndex - 1;
65
+ }
66
+ else {
67
+ newMenuItemIndex = listItems.length - 1;
68
+ }
69
+ }
70
+ const targetItem = listItems[newMenuItemIndex];
71
+ targetItem.classList.add('hover');
72
+ targetItem.focus();
73
+ targetItem.scrollIntoView({ block: 'nearest' });
74
+ menuItemIndex = newMenuItemIndex;
75
+ }
76
+ $effect(() => {
77
+ if (!keyboardNavigation) {
78
+ return;
79
+ }
80
+ const targetItem = ref.querySelector(':scope > li.dodo-ui-MenuItem.selected');
81
+ if (targetItem) {
82
+ const selectedIndex = options?.findIndex((option) => option.id === selectedOption?.id);
83
+ if (selectedIndex !== undefined && selectedIndex >= 0) {
84
+ menuItemIndex = selectedIndex;
85
+ }
86
+ targetItem.focus();
87
+ targetItem.scrollIntoView({ block: 'nearest' });
88
+ }
89
+ window.addEventListener('keydown', onKeyboardNavigation);
90
+ return () => {
91
+ window.removeEventListener('keydown', onKeyboardNavigation);
92
+ };
93
+ });
94
+ </script>
95
+
96
+ <Menu
97
+ class={['dodo-ui-DynamicMenu', className].join(' ')}
98
+ {id}
99
+ {size}
100
+ {width}
101
+ {height}
102
+ {separator}
103
+ bind:ref
104
+ >
105
+ {#if options?.length}
106
+ {#each options as option (option.id)}
107
+ <MenuItem
108
+ {...option}
109
+ selected={selectedOption?.id === option.id}
110
+ onclick={(e) => (onclick ? onclick(e, option) : undefined)}
111
+ {...menuItemProps}
112
+ >
113
+ {#if customMenuItemContentTyped}
114
+ {@render customMenuItemContentTyped(option, selectedOption)}
115
+ {:else}
116
+ {option.label || ''}
117
+ {/if}
118
+ </MenuItem>
119
+ {/each}
120
+ {:else if showOptionsPlaceholder}
121
+ <MenuItem type="text" disabled={true} {...menuItemProps}>
122
+ {#if customPlaceholderMenuItemContentTyped}
123
+ {@render customPlaceholderMenuItemContentTyped()}
124
+ {:else}
125
+ {optionsPlaceholder}
126
+ {/if}
127
+ </MenuItem>
128
+ {/if}
129
+ </Menu>
@@ -0,0 +1,81 @@
1
+ import type { ComponentSize } from '../../../../../types/size.js';
2
+ import type { MenuItemProps, MenuItemType } from '../MenuItem/MenuItem.svelte';
3
+ export type DynamicMenuItemOption<TMeta = unknown> = {
4
+ id: string;
5
+ /** label */
6
+ label?: string;
7
+ /** Custom Metadata */
8
+ meta?: TMeta;
9
+ /** Menu Item type */
10
+ type?: MenuItemType;
11
+ /** Menu Separator */
12
+ separator?: boolean;
13
+ /** How large should the Menu Items be? */
14
+ size?: ComponentSize;
15
+ /** The onclick event handler */
16
+ onclick?: MouseEventHandler<HTMLButtonElement>;
17
+ /** disabled state */
18
+ disabled?: boolean;
19
+ /** link href */
20
+ href?: string;
21
+ /** Link button: download */
22
+ download?: any;
23
+ /** Link button: hreflang */
24
+ hreflang?: string | undefined | null;
25
+ /** Link button: media */
26
+ media?: string | undefined | null;
27
+ /** Link button: ping */
28
+ ping?: string | undefined | null;
29
+ /** Link button: rel */
30
+ rel?: string | undefined | null;
31
+ /** Link button: target */
32
+ target?: ButtonLinkTarget;
33
+ /** Link button: Type */
34
+ anchorMediaType?: string | undefined | null;
35
+ /** Link button: referrerpolicy */
36
+ referrerpolicy?: ButtonLinkReferrerpolicy;
37
+ };
38
+ export interface DynamicMenuProps {
39
+ /** Menu ref */
40
+ ref?: HTMLUListElement;
41
+ /** Custom css class */
42
+ class?: string;
43
+ /** Menu Width */
44
+ width?: string;
45
+ /** Menu Height */
46
+ height?: string;
47
+ /** How large should the Menu Items be? */
48
+ size?: ComponentSize;
49
+ /** Menu Separator */
50
+ separator?: boolean;
51
+ /** Id */
52
+ id?: string;
53
+ /** Options */
54
+ options?: DynamicMenuItemOption[];
55
+ /** Selected Option */
56
+ selectedOption?: DynamicMenuItemOption;
57
+ /** Custom Menu Item Content */
58
+ customMenuItemContent?: (option: DynamicMenuItemOption, selectedOption?: DynamicMenuItemOption) => Snippet;
59
+ /** Show Placeholder if no options */
60
+ showOptionsPlaceholder?: boolean;
61
+ /** placeholder Text if no options */
62
+ optionsPlaceholder?: string;
63
+ /** Custom Menu Item Placeholder Content */
64
+ customPlaceholderMenuItemContent?: () => Snippet;
65
+ /** MenuItem: Menu component props */
66
+ menuItemProps?: Partial<MenuItemProps>;
67
+ /** Enable Keyboard Navigation */
68
+ keyboardNavigation?: boolean;
69
+ /** Keyboard Navigation onEnter */
70
+ onEnter?: (e: KeyboardEvent, menuItemIndex: number) => void;
71
+ /** Keyboard Navigation onEsc */
72
+ onEsc?: (e: KeyboardEvent, menuItemIndex: number) => void;
73
+ /** On menu item click */
74
+ onclick?: (e: MouseEvent, option: DynamicMenuItemOption) => void;
75
+ }
76
+ import type { MouseEventHandler } from 'svelte/elements';
77
+ import type { ButtonLinkReferrerpolicy, ButtonLinkTarget } from '../../../Form/Button/Button.svelte';
78
+ import type { Snippet } from 'svelte';
79
+ declare const DynamicMenu: import("svelte").Component<DynamicMenuProps, {}, "ref">;
80
+ type DynamicMenu = ReturnType<typeof DynamicMenu>;
81
+ export default DynamicMenu;
@@ -0,0 +1,46 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import { dynamicMenuItemOptions, storyDynamicMenuArgTypes } from '../DynamicMenu.stories.svelte';
3
+ import DynamicMenu, {} from '../DynamicMenu.svelte';
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: DynamicMenu,
7
+ tags: ['autodocs'],
8
+ argTypes: storyDynamicMenuArgTypes,
9
+ });
10
+ </script>
11
+
12
+ <!-- Menu Item onclick -->
13
+ <Story name="onclick" asChild>
14
+ <DynamicMenu
15
+ keyboardNavigation
16
+ options={dynamicMenuItemOptions}
17
+ onclick={(e: MouseEvent, option: DynamicMenuItemOption) => {
18
+ e.preventDefault();
19
+ console.log(option);
20
+ }}
21
+ />
22
+ </Story>
23
+
24
+ <!-- KeyboardNavigation Event: onEnter -->
25
+ <Story name="onEnter" asChild>
26
+ <DynamicMenu
27
+ keyboardNavigation
28
+ options={dynamicMenuItemOptions}
29
+ onEnter={(e: KeyboardEvent, menuItemIndex: number) => {
30
+ e.preventDefault();
31
+ console.log(menuItemIndex);
32
+ }}
33
+ />
34
+ </Story>
35
+
36
+ <!-- KeyboardNavigation Event: onEsc -->
37
+ <Story name="onEsc" asChild>
38
+ <DynamicMenu
39
+ keyboardNavigation
40
+ options={dynamicMenuItemOptions}
41
+ onEsc={(e: KeyboardEvent, menuItemIndex: number) => {
42
+ e.preventDefault();
43
+ console.log(menuItemIndex);
44
+ }}
45
+ />
46
+ </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 Events: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type Events = InstanceType<typeof Events>;
18
+ export default Events;
@@ -0,0 +1,27 @@
1
+ <script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
2
+ import DynamicMenu from '../DynamicMenu.svelte';
3
+ import { dynamicMenuItemOptions, storyDynamicMenuArgTypes } from '../DynamicMenu.stories.svelte';
4
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
5
+ const { Story } = defineMeta({
6
+ component: DynamicMenu,
7
+ tags: ['autodocs'],
8
+ argTypes: storyDynamicMenuArgTypes,
9
+ });
10
+ </script>
11
+
12
+ <!-- KeyboardNavigationOn -->
13
+ <Story
14
+ name="KeyboardNavigationOn"
15
+ args={{
16
+ options: dynamicMenuItemOptions,
17
+ keyboardNavigation: true,
18
+ onEnter: (e: KeyboardEvent, menuItemIndex: number) => {
19
+ e.preventDefault();
20
+ console.log(menuItemIndex);
21
+ },
22
+ onEsc: (e: KeyboardEvent, menuItemIndex: number) => {
23
+ e.preventDefault();
24
+ console.log(menuItemIndex);
25
+ },
26
+ }}
27
+ />
@@ -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 KeybaordNavigation: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type KeybaordNavigation = InstanceType<typeof KeybaordNavigation>;
18
+ export default KeybaordNavigation;
@@ -0,0 +1,72 @@
1
+ import { Source } from '@storybook/blocks';
2
+
3
+ # Option Format
4
+
5
+ ## DynamicMenuItemOption
6
+
7
+ <Source
8
+ dark
9
+ language="ts"
10
+ code={`
11
+ type DynamicMenuItemOption<TMeta = unknown> = {
12
+ id: string;
13
+ /** label */
14
+ label?: string;
15
+ /** Custom Metadata */
16
+ meta?: TMeta;
17
+ /** Menu Item type */
18
+ type?: MenuItemType;
19
+ /** Menu Separator */
20
+ separator?: boolean;
21
+ /** How large should the Menu Items be? */
22
+ size?: ComponentSize;
23
+ /** The onclick event handler */
24
+ onclick?: MouseEventHandler<HTMLButtonElement>;
25
+ /** disabled state */
26
+ disabled?: boolean;
27
+ /** link href */
28
+ href?: string;
29
+ /** Link button: download */
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ download?: any;
32
+ /** Link button: hreflang */
33
+ hreflang?: string | undefined | null;
34
+ /** Link button: media */
35
+ media?: string | undefined | null;
36
+ /** Link button: ping */
37
+ ping?: string | undefined | null;
38
+ /** Link button: rel */
39
+ rel?: string | undefined | null;
40
+ /** Link button: target */
41
+ target?: ButtonLinkTarget;
42
+ /** Link button: Type */
43
+ anchorMediaType?: string | undefined | null;
44
+ /** Link button: referrerpolicy */
45
+ referrerpolicy?: ButtonLinkReferrerpolicy;
46
+ };
47
+ `}
48
+ />
49
+
50
+ ## Example values
51
+
52
+ <Source
53
+ dark
54
+ language="ts"
55
+ code={`
56
+ const options: DynamicMenuItemOption[] = [
57
+ {
58
+ id: '1',
59
+ label: 'One',
60
+ },
61
+ {
62
+ id: '2',
63
+ label: 'Two',
64
+ },
65
+ {
66
+ id: '3',
67
+ label: 'Three',
68
+ disabled: true,
69
+ },
70
+ ];
71
+ `}
72
+ />
@@ -14,7 +14,7 @@ export interface MenuItemProps {
14
14
  id?: string;
15
15
  /** Menu Item type */
16
16
  type?: MenuItemType;
17
- /** Menu Item type */
17
+ /** selected */
18
18
  selected?: boolean;
19
19
  /** Separator */
20
20
  separator?: boolean;
@@ -28,6 +28,7 @@ function onclickMod(e) {
28
28
  ].join(' ')}
29
29
  bind:this={ref}
30
30
  onclick={onclickMod}
31
+ {onfocus}
31
32
  {onblur}
32
33
  {disabled}
33
34
  >
package/package.json CHANGED
@@ -1,19 +1,6 @@
1
1
  {
2
2
  "name": "@flightlesslabs/dodo-ui",
3
- "version": "0.7.1",
4
- "scripts": {
5
- "build": "vite build && pnpm run prepack",
6
- "preview": "vite preview",
7
- "prepare": "svelte-kit sync || echo ''",
8
- "prepack": "svelte-kit sync && svelte-package && publint",
9
- "svelte-check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
10
- "format": "prettier --write .",
11
- "lint": "prettier --check . && eslint .",
12
- "dev": "storybook dev -p 6006",
13
- "build-storybook": "storybook build && touch ./storybook-static/.nojekyll",
14
- "check": "pnpm run svelte-check && eslint . && pnpm run lint",
15
- "check:fix": "pnpm run svelte-check && eslint . && pnpm run format"
16
- },
3
+ "version": "0.8.0",
17
4
  "homepage": "https://flightlesslabs.github.io/dodo-ui",
18
5
  "repository": {
19
6
  "type": "git",
@@ -29,7 +16,8 @@
29
16
  "!src/lib/**/*.spec.*",
30
17
  "!src/lib/stories/**/*.stories.*",
31
18
  "!src/lib/stories/**/*.mdx",
32
- "!src/lib/stories/assets",
19
+ "!src/lib/stories/assets/**/*.png",
20
+ "!src/lib/stories/assets/**/*.jpg",
33
21
  "!src/lib/stories/philosophy"
34
22
  ],
35
23
  "sideEffects": [
@@ -69,7 +57,7 @@
69
57
  "eslint": "^9.27.0",
70
58
  "eslint-config-prettier": "^10.1.5",
71
59
  "eslint-plugin-svelte": "^3.9.0",
72
- "globals": "^16.1.0",
60
+ "globals": "^16.2.0",
73
61
  "playwright": "^1.52.0",
74
62
  "prettier": "^3.5.3",
75
63
  "prettier-plugin-svelte": "^3.4.0",
@@ -77,7 +65,7 @@
77
65
  "sass": "^1.89.0",
78
66
  "storybook": "^8.6.14",
79
67
  "storybook-dark-mode": "^4.0.2",
80
- "svelte": "^5.32.1",
68
+ "svelte": "^5.33.2",
81
69
  "svelte-check": "^4.2.1",
82
70
  "svelte-preprocess": "^6.0.3",
83
71
  "typescript": "^5.8.3",
@@ -94,5 +82,16 @@
94
82
  },
95
83
  "dependencies": {
96
84
  "@iconify/svelte": "^5.0.0"
85
+ },
86
+ "scripts": {
87
+ "build": "vite build && pnpm run prepack",
88
+ "preview": "vite preview",
89
+ "svelte-check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
90
+ "format": "prettier --write .",
91
+ "lint": "prettier --check . && eslint .",
92
+ "dev": "storybook dev -p 6006",
93
+ "build-storybook": "storybook build && touch ./storybook-static/.nojekyll",
94
+ "check": "pnpm run svelte-check && eslint . && pnpm run lint",
95
+ "check:fix": "pnpm run svelte-check && eslint . && pnpm run format"
97
96
  }
98
- }
97
+ }
package/src/lib/index.ts CHANGED
@@ -79,6 +79,14 @@ export type { FormControlProps } from '$lib/stories/components/Form/FormControl/
79
79
  export { default as Message } from '$lib/stories/components/Form/Message/Message.svelte';
80
80
  export type { MessageProps } from '$lib/stories/components/Form/Message/Message.svelte';
81
81
 
82
+ /** Form: Select */
83
+ export { default as Select } from '$lib/stories/components/Form/Select/Select.svelte';
84
+ export type {
85
+ SelectOption,
86
+ SelectDropdownArrowPosition,
87
+ SelectProps,
88
+ } from '$lib/stories/components/Form/Select/Select.svelte';
89
+
82
90
  /** Layout: Paper */
83
91
  export { default as Paper } from '$lib/stories/components/Layout/Paper/Paper.svelte';
84
92
  export type { PaperColor, PaperProps } from '$lib/stories/components/Layout/Paper/Paper.svelte';
@@ -98,3 +106,8 @@ export type {
98
106
  MenuItemType,
99
107
  MenuItemProps,
100
108
  } from '$lib/stories/components/Layout/Menu/MenuItem/MenuItem.svelte';
109
+ export { default as DynamicMenu } from '$lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte';
110
+ export type {
111
+ DynamicMenuItemOption,
112
+ DynamicMenuProps,
113
+ } from '$lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte';