@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.
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/stories/components/Form/Select/Customize/Customize.stories.svelte +16 -1
- package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +59 -0
- package/dist/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +54 -0
- package/dist/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte +83 -0
- package/dist/stories/components/Form/Select/Positions/Positions.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/Select/Select.svelte +107 -123
- package/dist/stories/components/Form/Select/Select.svelte.d.ts +15 -2
- package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +28 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +51 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte.d.ts +22 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +129 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte.d.ts +81 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +46 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +27 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
- package/dist/stories/components/Layout/Menu/MenuItem/MenuItem.svelte.d.ts +1 -1
- package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte +1 -0
- package/package.json +17 -18
- package/src/lib/index.ts +13 -0
- package/src/lib/stories/Home.mdx +59 -0
- package/src/lib/stories/assets/dark-theme-toggle.png +0 -0
- package/src/lib/stories/components/Form/Button/Button.stories.svelte +61 -0
- package/src/lib/stories/components/Form/Button/Color/Color.stories.svelte +43 -0
- package/src/lib/stories/components/Form/Button/Events/Events.stories.svelte +36 -0
- package/src/lib/stories/components/Form/Button/IconButton/IconButton.stories.svelte +43 -0
- package/src/lib/stories/components/Form/Button/Roundness/Roundness.stories.svelte +23 -0
- package/src/lib/stories/components/Form/Button/Size/Size.stories.svelte +16 -0
- package/src/lib/stories/components/Form/Button/Variant/Variant.stories.svelte +18 -0
- package/src/lib/stories/components/Form/FormControl/FormControl.stories.svelte +28 -0
- package/src/lib/stories/components/Form/Label/Label.stories.svelte +13 -0
- package/src/lib/stories/components/Form/Message/Color/Color.stories.svelte +36 -0
- package/src/lib/stories/components/Form/Message/Message.stories.svelte +27 -0
- package/src/lib/stories/components/Form/Message/Size/Size.stories.svelte +22 -0
- package/src/lib/stories/components/Form/PasswordInput/Events/Events.stories.svelte +110 -0
- package/src/lib/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +59 -0
- package/src/lib/stories/components/Form/PasswordInput/Roundness/Roundness.stories.svelte +20 -0
- package/src/lib/stories/components/Form/PasswordInput/Size/Size.stories.svelte +16 -0
- package/src/lib/stories/components/Form/PasswordInput/WithIcon/WithIcon.stories.svelte +31 -0
- package/src/lib/stories/components/Form/Select/Customize/Customize.stories.svelte +139 -0
- package/src/lib/stories/components/Form/Select/DropDownArrow/DropDownArrow.stories.svelte +63 -0
- package/src/lib/stories/components/Form/Select/Events/Events.stories.svelte +144 -0
- package/src/lib/stories/components/Form/Select/Options/OptionFormat.mdx +40 -0
- package/src/lib/stories/components/Form/Select/Positions/AutoPosition/AutoPosition.stories.svelte +58 -0
- package/src/lib/stories/components/Form/Select/Positions/Positions.stories.svelte +87 -0
- package/src/lib/stories/components/Form/Select/Roundness/Roundness.stories.svelte +32 -0
- package/src/lib/stories/components/Form/Select/Select.stories.svelte +121 -0
- package/src/lib/stories/components/Form/Select/Select.svelte +153 -146
- package/src/lib/stories/components/Form/Select/Size/Size.stories.svelte +28 -0
- package/src/lib/stories/components/Form/Select/WithIcon/WithIcon.stories.svelte +43 -0
- package/src/lib/stories/components/Form/TextInput/Events/Events.stories.svelte +97 -0
- package/src/lib/stories/components/Form/TextInput/Roundness/Roundness.stories.svelte +21 -0
- package/src/lib/stories/components/Form/TextInput/Size/Size.stories.svelte +17 -0
- package/src/lib/stories/components/Form/TextInput/TextInput.stories.svelte +43 -0
- package/src/lib/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte +47 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte +30 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.stories.svelte +56 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/DynamicMenu.svelte +262 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/Events/Events.stories.svelte +48 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/KeybaordNavigation/KeybaordNavigation.stories.svelte +29 -0
- package/src/lib/stories/components/Layout/Menu/DynamicMenu/Options/OptionFormat.mdx +72 -0
- package/src/lib/stories/components/Layout/Menu/Menu.stories.svelte +69 -0
- package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.stories.svelte +34 -0
- package/src/lib/stories/components/Layout/Menu/MenuItem/MenuItem.svelte +1 -1
- package/src/lib/stories/components/Layout/Menu/MenuItem/Size/Size.stories.svelte +16 -0
- package/src/lib/stories/components/Layout/Menu/MenuItem/Type/Type.stories.svelte +21 -0
- package/src/lib/stories/components/Layout/Menu/Size/Size.stories.svelte +37 -0
- package/src/lib/stories/components/Layout/Paper/Color/Color.stories.svelte +63 -0
- package/src/lib/stories/components/Layout/Paper/Paper.stories.svelte +50 -0
- package/src/lib/stories/components/Layout/Paper/Roundness/Roundness.stories.svelte +25 -0
- package/src/lib/stories/components/Layout/Paper/Shadow/Shadow.stories.svelte +24 -0
- package/src/lib/stories/components/Layout/Separator/Color/Color.stories.svelte +19 -0
- package/src/lib/stories/components/Layout/Separator/Separator.stories.svelte +30 -0
- package/src/lib/stories/developer tools/Intro.mdx +9 -0
- package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.stories.svelte +53 -0
- package/src/lib/stories/developer tools/components/DynamicInput/DynamicInput.svelte +1 -0
- package/src/lib/stories/developer tools/components/DynamicInput/Size/Size.stories.svelte +17 -0
- package/src/lib/stories/developer tools/components/InputEnclosure/InputEnclosure.stories.svelte +38 -0
- package/src/lib/stories/developer tools/components/InputEnclosure/Roundness/Roundness.stories.svelte +20 -0
- package/src/lib/stories/developer tools/components/InputEnclosure/Size/Size.stories.svelte +16 -0
- package/src/lib/stories/developer tools/components/InputEnclosure/WithIcon/WithIcon.stories.svelte +47 -0
- package/src/lib/stories/developer tools/components/Popper/Popper.stories.svelte +124 -0
- package/src/lib/stories/developer tools/components/Popper/PopperPopup/PopperPopup.stories.svelte +64 -0
- package/src/lib/stories/developer tools/components/Popper/Positions/AutoPosition/AutoPosition.stories.svelte +92 -0
- package/src/lib/stories/developer tools/components/Popper/Positions/Positions.stories.svelte +114 -0
- package/src/lib/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +25 -0
- package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +30 -0
- package/src/lib/stories/developer tools/directives/clickOutside/index.mdx +25 -0
- package/src/lib/stories/developer tools/philosophy/Colors/Colors.mdx +43 -0
- package/src/lib/stories/developer tools/philosophy/Colors/Colors.stories.svelte +22 -0
- package/src/lib/stories/developer tools/philosophy/Colors/Opacity.stories.svelte +11 -0
- 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>
|
package/dist/stories/components/Layout/Menu/DynamicMenu/Customize/Customize.stories.svelte.d.ts
ADDED
|
@@ -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
|
+
/>
|
package/package.json
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flightlesslabs/dodo-ui",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
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.
|
|
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';
|