@flightlesslabs/dodo-ui 0.7.2 → 0.9.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 +18 -2
- package/dist/index.js +11 -0
- package/dist/stories/components/Form/NumericInput/Events/Events.stories.svelte +126 -0
- package/dist/stories/components/Form/NumericInput/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/NumericInput/NumericInput.stories.svelte +79 -0
- package/dist/stories/components/Form/NumericInput/NumericInput.stories.svelte.d.ts +21 -0
- package/dist/stories/components/Form/NumericInput/NumericInput.svelte +161 -0
- package/dist/stories/components/Form/NumericInput/NumericInput.svelte.d.ts +69 -0
- package/dist/stories/components/Form/NumericInput/Validation/Validation.stories.svelte +84 -0
- package/dist/stories/components/Form/NumericInput/Validation/Validation.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/PasswordInput/Events/Events.stories.svelte +27 -6
- package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte +5 -3
- package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte.d.ts +7 -1
- 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/Events/Events.stories.svelte +27 -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 +110 -123
- package/dist/stories/components/Form/Select/Select.svelte.d.ts +22 -3
- package/dist/stories/components/Form/TextInput/Events/Events.stories.svelte +27 -0
- package/dist/stories/components/Form/TextInput/TextInput.svelte +5 -3
- package/dist/stories/components/Form/TextInput/TextInput.svelte.d.ts +10 -1
- 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 +23 -4
- package/dist/stories/developer tools/components/DynamicInput/DynamicInput.svelte.d.ts +13 -2
- package/dist/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte +115 -0
- package/dist/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.d.ts +13 -0
- package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.js +26 -0
- package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/index.mdx +20 -0
- package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/index.mdx +71 -0
- package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.d.ts +51 -0
- package/dist/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.js +96 -0
- package/dist/stories/developer tools/helpers/logger/index.mdx +63 -0
- package/dist/stories/developer tools/helpers/logger/logger.d.ts +24 -0
- package/dist/stories/developer tools/helpers/logger/logger.js +31 -0
- package/package.json +15 -17
- package/src/lib/index.ts +33 -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/NumericInput/Events/Events.stories.svelte +134 -0
- package/src/lib/stories/components/Form/NumericInput/NumericInput.stories.svelte +84 -0
- package/src/lib/stories/components/Form/NumericInput/NumericInput.svelte +286 -0
- package/src/lib/stories/components/Form/NumericInput/Validation/Validation.stories.svelte +87 -0
- package/src/lib/stories/components/Form/PasswordInput/Events/Events.stories.svelte +132 -0
- package/src/lib/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +59 -0
- package/src/lib/stories/components/Form/PasswordInput/PasswordInput.svelte +15 -3
- 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 +174 -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 +166 -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 +125 -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/TextInput.svelte +18 -3
- 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 +43 -3
- package/src/lib/stories/developer tools/components/DynamicInput/Events/Events.stories.svelte +121 -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/helpers/Numbers/cleanNumericString/cleanNumericString.ts +27 -0
- package/src/lib/stories/developer tools/helpers/Numbers/cleanNumericString/index.mdx +20 -0
- package/src/lib/stories/developer tools/helpers/Numbers/isValidNumberValue/index.mdx +71 -0
- package/src/lib/stories/developer tools/helpers/Numbers/isValidNumberValue/isValidNumberValue.ts +156 -0
- package/src/lib/stories/developer tools/helpers/logger/index.mdx +63 -0
- package/src/lib/stories/developer tools/helpers/logger/logger.ts +46 -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
|
@@ -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 === 'Escape') {
|
|
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
|
+
/>
|
|
@@ -3,7 +3,7 @@ export const dynamicInputVariantArray = ['input', 'button'];
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script lang="ts">"use strict";
|
|
6
|
-
let { type = 'text', name, id, class: className = '', disabled = false, onchange, oninput, onblur, onfocus, onpaste, oncopy, oncut, value = $bindable(), placeholder, ref = $bindable(), readonly = false, variant = 'input', size = 'normal', onclick, customInputContent, } = $props();
|
|
6
|
+
let { type = 'text', name, id, class: className = '', disabled = false, onchange, oninput, onblur, onfocus, onpaste, oncopy, oncut, onkeydown, onkeypress, onkeyup, value = $bindable(), focused = $bindable(), placeholder, ref = $bindable(), readonly = false, variant = 'input', size = 'normal', onclick, customInputContent, } = $props();
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
8
|
let customInputContentTyped = customInputContent;
|
|
9
9
|
function onclickMod(e) {
|
|
@@ -14,6 +14,18 @@ function onclickMod(e) {
|
|
|
14
14
|
onclick(e);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
+
function onfocusMod(e) {
|
|
18
|
+
focused = true;
|
|
19
|
+
if (onfocus) {
|
|
20
|
+
onfocus(e);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function onblurMod(e) {
|
|
24
|
+
focused = false;
|
|
25
|
+
if (onblur) {
|
|
26
|
+
onblur(e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
17
29
|
</script>
|
|
18
30
|
|
|
19
31
|
{#if variant === 'button'}
|
|
@@ -28,7 +40,11 @@ function onclickMod(e) {
|
|
|
28
40
|
].join(' ')}
|
|
29
41
|
bind:this={ref}
|
|
30
42
|
onclick={onclickMod}
|
|
31
|
-
{
|
|
43
|
+
{onkeydown}
|
|
44
|
+
{onkeypress}
|
|
45
|
+
{onkeyup}
|
|
46
|
+
onfocus={onfocusMod}
|
|
47
|
+
onblur={onblurMod}
|
|
32
48
|
{disabled}
|
|
33
49
|
>
|
|
34
50
|
{#if customInputContentTyped}
|
|
@@ -46,11 +62,14 @@ function onclickMod(e) {
|
|
|
46
62
|
{disabled}
|
|
47
63
|
{oninput}
|
|
48
64
|
{onchange}
|
|
49
|
-
{
|
|
50
|
-
{
|
|
65
|
+
onfocus={onfocusMod}
|
|
66
|
+
onblur={onblurMod}
|
|
51
67
|
{onpaste}
|
|
52
68
|
{oncopy}
|
|
53
69
|
{oncut}
|
|
70
|
+
{onkeydown}
|
|
71
|
+
{onkeypress}
|
|
72
|
+
{onkeyup}
|
|
54
73
|
{placeholder}
|
|
55
74
|
bind:value
|
|
56
75
|
bind:this={ref}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ComponentSize, type TextInputType } from '../../../../index.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { ChangeEventHandler, ClipboardEventHandler, FocusEventHandler, FormEventHandler, MouseEventHandler } from 'svelte/elements';
|
|
3
|
+
import type { ChangeEventHandler, ClipboardEventHandler, FocusEventHandler, FormEventHandler, KeyboardEventHandler, MouseEventHandler } from 'svelte/elements';
|
|
4
4
|
export type DynamicInputVariant = 'input' | 'button';
|
|
5
5
|
export declare const dynamicInputVariantArray: DynamicInputVariant[];
|
|
6
6
|
export type DynamicInputClickEvent = MouseEvent & {
|
|
@@ -9,6 +9,9 @@ export type DynamicInputClickEvent = MouseEvent & {
|
|
|
9
9
|
export type DynamicInputFocusEvent = FocusEvent & {
|
|
10
10
|
currentTarget: EventTarget & (HTMLInputElement | HTMLButtonElement);
|
|
11
11
|
};
|
|
12
|
+
export type DynamicInputKeyboardEvent = KeyboardEvent & {
|
|
13
|
+
currentTarget: EventTarget & (HTMLInputElement | HTMLButtonElement);
|
|
14
|
+
};
|
|
12
15
|
export interface DynamicInputProps {
|
|
13
16
|
/** How large should the button be? */
|
|
14
17
|
size?: ComponentSize;
|
|
@@ -18,6 +21,8 @@ export interface DynamicInputProps {
|
|
|
18
21
|
ref?: HTMLInputElement | HTMLButtonElement;
|
|
19
22
|
/** Input value */
|
|
20
23
|
value?: string | number;
|
|
24
|
+
/** is focused, set focused */
|
|
25
|
+
focused?: boolean;
|
|
21
26
|
/** variant */
|
|
22
27
|
variant?: DynamicInputVariant;
|
|
23
28
|
/** How round should the border radius be? */
|
|
@@ -52,9 +57,15 @@ export interface DynamicInputProps {
|
|
|
52
57
|
oncopy?: ClipboardEventHandler<HTMLInputElement>;
|
|
53
58
|
/** oncut event handler */
|
|
54
59
|
oncut?: ClipboardEventHandler<HTMLInputElement>;
|
|
60
|
+
/** onkeydown event handler */
|
|
61
|
+
onkeydown?: KeyboardEventHandler<HTMLInputElement | HTMLButtonElement>;
|
|
62
|
+
/** onkeypress event handler */
|
|
63
|
+
onkeypress?: KeyboardEventHandler<HTMLInputElement | HTMLButtonElement>;
|
|
64
|
+
/** onkeyup event handler */
|
|
65
|
+
onkeyup?: KeyboardEventHandler<HTMLInputElement | HTMLButtonElement>;
|
|
55
66
|
/** custom Content Formatting for variant button */
|
|
56
67
|
customInputContent?: (value: string | number) => Snippet;
|
|
57
68
|
}
|
|
58
|
-
declare const DynamicInput: import("svelte").Component<DynamicInputProps, {}, "ref" | "value">;
|
|
69
|
+
declare const DynamicInput: import("svelte").Component<DynamicInputProps, {}, "ref" | "focused" | "value">;
|
|
59
70
|
type DynamicInput = ReturnType<typeof DynamicInput>;
|
|
60
71
|
export default DynamicInput;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script module lang="ts">import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
2
|
+
import { storyDynamicInputArgTypes } from '../DynamicInput.stories.svelte';
|
|
3
|
+
import DynamicInput, {} from '../DynamicInput.svelte';
|
|
4
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
5
|
+
const { Story } = defineMeta({
|
|
6
|
+
component: DynamicInput,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
argTypes: storyDynamicInputArgTypes,
|
|
9
|
+
args: { value: 'Hello world!' },
|
|
10
|
+
});
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<Story
|
|
14
|
+
name="Input"
|
|
15
|
+
args={{
|
|
16
|
+
oninput: (e: Event) => {
|
|
17
|
+
const target = e.target as HTMLInputElement;
|
|
18
|
+
|
|
19
|
+
console.log('Input Event', target.value);
|
|
20
|
+
},
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
23
|
+
|
|
24
|
+
<Story
|
|
25
|
+
name="Change"
|
|
26
|
+
args={{
|
|
27
|
+
onchange: (e: Event) => {
|
|
28
|
+
const target = e.target as HTMLInputElement;
|
|
29
|
+
|
|
30
|
+
console.log('onChange Event', target.value);
|
|
31
|
+
},
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
<Story
|
|
36
|
+
name="Focus"
|
|
37
|
+
args={{
|
|
38
|
+
onfocus: (e: DynamicInputFocusEvent) => {
|
|
39
|
+
const target = e.target as HTMLInputElement;
|
|
40
|
+
|
|
41
|
+
console.log('onfocus Event', target);
|
|
42
|
+
},
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<Story
|
|
47
|
+
name="Blur"
|
|
48
|
+
args={{
|
|
49
|
+
onblur: (e: DynamicInputFocusEvent) => {
|
|
50
|
+
const target = e.target as HTMLInputElement;
|
|
51
|
+
|
|
52
|
+
console.log('onblur Event', target);
|
|
53
|
+
},
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
|
|
57
|
+
<Story
|
|
58
|
+
name="Copy"
|
|
59
|
+
args={{
|
|
60
|
+
oncopy: (e: TextInputClipboardEvent) => {
|
|
61
|
+
const target = e.target as HTMLInputElement;
|
|
62
|
+
|
|
63
|
+
console.log('oncopy Event', target);
|
|
64
|
+
},
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
<Story
|
|
69
|
+
name="Cut"
|
|
70
|
+
args={{
|
|
71
|
+
oncut: (e: TextInputClipboardEvent) => {
|
|
72
|
+
const target = e.target as HTMLInputElement;
|
|
73
|
+
|
|
74
|
+
console.log('oncut Event', target);
|
|
75
|
+
},
|
|
76
|
+
}}
|
|
77
|
+
/>
|
|
78
|
+
|
|
79
|
+
<Story
|
|
80
|
+
name="Paste"
|
|
81
|
+
args={{
|
|
82
|
+
onpaste: (e: TextInputClipboardEvent) => {
|
|
83
|
+
const target = e.target as HTMLInputElement;
|
|
84
|
+
|
|
85
|
+
console.log('onpaste Event', target);
|
|
86
|
+
},
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
|
|
90
|
+
<Story
|
|
91
|
+
name="KeyDown"
|
|
92
|
+
args={{
|
|
93
|
+
onkeydown: (e: DynamicInputKeyboardEvent) => {
|
|
94
|
+
console.log('onkeydown Event', e.key);
|
|
95
|
+
},
|
|
96
|
+
}}
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<Story
|
|
100
|
+
name="KeyPress"
|
|
101
|
+
args={{
|
|
102
|
+
onkeypress: (e: DynamicInputKeyboardEvent) => {
|
|
103
|
+
console.log('onkeypress Event', e.key);
|
|
104
|
+
},
|
|
105
|
+
}}
|
|
106
|
+
/>
|
|
107
|
+
|
|
108
|
+
<Story
|
|
109
|
+
name="KeyUp"
|
|
110
|
+
args={{
|
|
111
|
+
onkeyup: (e: DynamicInputKeyboardEvent) => {
|
|
112
|
+
console.log('onkeyup Event', e.key);
|
|
113
|
+
},
|
|
114
|
+
}}
|
|
115
|
+
/>
|
package/dist/stories/developer tools/components/DynamicInput/Events/Events.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 Events: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type Events = InstanceType<typeof Events>;
|
|
18
|
+
export default Events;
|
package/dist/stories/developer tools/helpers/Numbers/cleanNumericString/cleanNumericString.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleans the input string by removing all characters except numeric digits (0-9) and a single decimal point.
|
|
3
|
+
* Only the first decimal point is retained; all subsequent dots are removed.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} input - The input string to be cleaned.
|
|
6
|
+
* @returns {string} - A string containing only digits and at most one decimal point.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* cleanNumericString("abc123.45.67def"); // returns "123.4567"
|
|
10
|
+
* cleanNumericString("a1b2c3"); // returns "123"
|
|
11
|
+
* cleanNumericString("...12.3.4..5"); // returns "12.345"
|
|
12
|
+
*/
|
|
13
|
+
export default function cleanNumericString(input: string): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleans the input string by removing all characters except numeric digits (0-9) and a single decimal point.
|
|
3
|
+
* Only the first decimal point is retained; all subsequent dots are removed.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} input - The input string to be cleaned.
|
|
6
|
+
* @returns {string} - A string containing only digits and at most one decimal point.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* cleanNumericString("abc123.45.67def"); // returns "123.4567"
|
|
10
|
+
* cleanNumericString("a1b2c3"); // returns "123"
|
|
11
|
+
* cleanNumericString("...12.3.4..5"); // returns "12.345"
|
|
12
|
+
*/
|
|
13
|
+
export default function cleanNumericString(input) {
|
|
14
|
+
// Remove all characters except digits and dots
|
|
15
|
+
const filtered = input.replace(/[^0-9.]/g, '');
|
|
16
|
+
// Split by dot to separate parts
|
|
17
|
+
const parts = filtered.split('.');
|
|
18
|
+
if (parts.length === 1) {
|
|
19
|
+
// No dot present, just digits
|
|
20
|
+
return parts[0];
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Keep only first dot, join the rest parts without dots
|
|
24
|
+
return parts[0] + '.' + parts.slice(1).join('');
|
|
25
|
+
}
|
|
26
|
+
}
|