@flightlesslabs/dodo-ui 0.2.0 → 0.4.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 +15 -0
- package/dist/index.js +12 -0
- package/dist/stories/Home.mdx +1 -1
- package/dist/stories/components/Form/Button/Button.stories.svelte +10 -5
- package/dist/stories/components/Form/Button/Button.svelte +216 -208
- package/dist/stories/components/Form/Button/Button.svelte.d.ts +8 -3
- package/dist/stories/components/Form/Button/Events/Events.stories.svelte +40 -0
- package/dist/stories/components/Form/Button/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/Button/utils/scss/mixins.scss +21 -21
- package/dist/stories/components/Form/FormControl/FormControl.stories.svelte +27 -0
- package/dist/stories/components/Form/FormControl/FormControl.stories.svelte.d.ts +19 -0
- package/dist/stories/components/Form/FormControl/FormControl.svelte +34 -0
- package/dist/stories/components/Form/FormControl/FormControl.svelte.d.ts +20 -0
- package/dist/stories/components/Form/Label/Label.stories.svelte +21 -0
- package/dist/stories/components/Form/Label/Label.stories.svelte.d.ts +19 -0
- package/dist/stories/components/Form/Label/Label.svelte +19 -0
- package/dist/stories/components/Form/Label/Label.svelte.d.ts +18 -0
- package/dist/stories/components/Form/Message/Message.stories.svelte +46 -0
- package/dist/stories/components/Form/Message/Message.stories.svelte.d.ts +19 -0
- package/dist/stories/components/Form/Message/Message.svelte +39 -0
- package/dist/stories/components/Form/Message/Message.svelte.d.ts +17 -0
- package/dist/stories/components/Form/PasswordInput/Events/Events.stories.svelte +168 -0
- package/dist/stories/components/Form/PasswordInput/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +53 -0
- package/dist/stories/components/Form/PasswordInput/PasswordInput.stories.svelte.d.ts +21 -0
- package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte +196 -0
- package/dist/stories/components/Form/PasswordInput/PasswordInput.svelte.d.ts +63 -0
- package/dist/stories/components/Form/PasswordInput/Roundness/Roundness.stories.svelte +20 -0
- package/dist/stories/components/Form/{ExampleButton/ExampleButton.stories.svelte.d.ts → PasswordInput/Roundness/Roundness.stories.svelte.d.ts} +3 -4
- package/dist/stories/components/Form/PasswordInput/Size/Size.stories.svelte +16 -0
- package/dist/stories/components/Form/PasswordInput/Size/Size.stories.svelte.d.ts +26 -0
- package/dist/stories/components/Form/PasswordInput/WithIcon/WithIcon.stories.svelte +31 -0
- package/dist/stories/components/Form/PasswordInput/WithIcon/WithIcon.stories.svelte.d.ts +26 -0
- package/dist/stories/components/Form/TextInput/Events/Events.stories.svelte +148 -0
- package/dist/stories/components/Form/TextInput/Events/Events.stories.svelte.d.ts +18 -0
- package/dist/stories/components/Form/TextInput/Roundness/Roundness.stories.svelte +21 -0
- package/dist/stories/components/Form/TextInput/Roundness/Roundness.stories.svelte.d.ts +26 -0
- package/dist/stories/components/Form/TextInput/Size/Size.stories.svelte +17 -0
- package/dist/stories/components/Form/TextInput/Size/Size.stories.svelte.d.ts +26 -0
- package/dist/stories/components/Form/TextInput/TextInput.stories.svelte +37 -0
- package/dist/stories/components/Form/TextInput/TextInput.stories.svelte.d.ts +21 -0
- package/dist/stories/components/Form/TextInput/TextInput.svelte +168 -0
- package/dist/stories/components/Form/TextInput/TextInput.svelte.d.ts +60 -0
- package/dist/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte +47 -0
- package/dist/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte.d.ts +26 -0
- package/dist/stories/developer tools/Intro.mdx +7 -0
- package/dist/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +27 -0
- package/dist/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte.d.ts +26 -0
- package/dist/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +29 -0
- package/dist/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte.d.ts +21 -0
- package/dist/stories/developer tools/components/UtilityButton/UtilityButton.svelte +79 -0
- package/dist/stories/developer tools/components/UtilityButton/UtilityButton.svelte.d.ts +26 -0
- package/dist/styles/_components.css +8 -7
- package/dist/styles/_minimal-reset.css +3 -0
- package/dist/styles/global.css +1 -0
- package/package.json +30 -30
- package/src/lib/index.ts +26 -0
- package/src/lib/stories/components/Form/Button/Button.stories.svelte +10 -5
- package/src/lib/stories/components/Form/Button/Button.svelte +40 -24
- package/src/lib/stories/components/Form/Button/Events/Events.stories.svelte +42 -0
- package/src/lib/stories/components/Form/Button/utils/scss/mixins.scss +21 -21
- package/src/lib/stories/components/Form/FormControl/FormControl.stories.svelte +29 -0
- package/src/lib/stories/components/Form/FormControl/FormControl.svelte +67 -0
- package/src/lib/stories/components/Form/Label/Label.stories.svelte +23 -0
- package/src/lib/stories/components/Form/Label/Label.svelte +45 -0
- package/src/lib/stories/components/Form/Message/Message.stories.svelte +48 -0
- package/src/lib/stories/components/Form/Message/Message.svelte +71 -0
- package/src/lib/stories/components/Form/PasswordInput/Events/Events.stories.svelte +174 -0
- package/src/lib/stories/components/Form/PasswordInput/PasswordInput.stories.svelte +57 -0
- package/src/lib/stories/components/Form/PasswordInput/PasswordInput.svelte +338 -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/TextInput/Events/Events.stories.svelte +153 -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 +41 -0
- package/src/lib/stories/components/Form/TextInput/TextInput.svelte +301 -0
- package/src/lib/stories/components/Form/TextInput/WithIcon/WithIcon.stories.svelte +47 -0
- package/src/lib/stories/developer tools/Intro.mdx +7 -0
- package/src/lib/stories/developer tools/components/UtilityButton/Size/Size.stories.svelte +27 -0
- package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.stories.svelte +33 -0
- package/src/lib/stories/developer tools/components/UtilityButton/UtilityButton.svelte +128 -0
- package/src/lib/styles/_components.css +8 -7
- package/src/lib/styles/_minimal-reset.css +3 -0
- package/src/lib/styles/global.css +1 -0
- package/dist/stories/components/Form/ExampleButton/ExampleButton.stories.svelte +0 -30
- package/dist/stories/components/Form/ExampleButton/ExampleButton.svelte +0 -14
- package/dist/stories/components/Form/ExampleButton/ExampleButton.svelte.d.ts +0 -16
- package/dist/stories/components/Form/ExampleButton/button.css +0 -30
- package/src/lib/stories/components/Form/ExampleButton/ExampleButton.stories.svelte +0 -30
- package/src/lib/stories/components/Form/ExampleButton/ExampleButton.svelte +0 -29
- package/src/lib/stories/components/Form/ExampleButton/button.css +0 -30
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Message from './Message.svelte';
|
|
4
|
+
|
|
5
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
component: Message,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
argTypes: {
|
|
10
|
+
color: {
|
|
11
|
+
control: { type: 'select' },
|
|
12
|
+
options: ['default', 'primary', 'safe', 'warning', 'danger', 'info'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<!-- ⚠️ Test Message: Do not use! -->
|
|
19
|
+
<Story
|
|
20
|
+
name="Test Message"
|
|
21
|
+
args={{
|
|
22
|
+
_unsafeChildrenStringForTesting: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
|
|
26
|
+
<Story name="Default">
|
|
27
|
+
<Message>Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
28
|
+
</Story>
|
|
29
|
+
|
|
30
|
+
<Story name="Primary" args={{ color: 'primary' }}>
|
|
31
|
+
<Message color="primary">Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
32
|
+
</Story>
|
|
33
|
+
|
|
34
|
+
<Story name="Safe" args={{ color: 'safe' }}>
|
|
35
|
+
<Message color="safe">Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
36
|
+
</Story>
|
|
37
|
+
|
|
38
|
+
<Story name="Warning" args={{ color: 'warning' }}>
|
|
39
|
+
<Message color="warning">Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
40
|
+
</Story>
|
|
41
|
+
|
|
42
|
+
<Story name="Danger" args={{ color: 'danger' }}>
|
|
43
|
+
<Message color="danger">Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
44
|
+
</Story>
|
|
45
|
+
|
|
46
|
+
<Story name="Info" args={{ color: 'info' }}>
|
|
47
|
+
<Message color="info">Lorem ipsum dolor sit amet, consectetur adipiscing elit</Message>
|
|
48
|
+
</Story>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type MessageColor = 'default' | 'primary' | 'safe' | 'warning' | 'danger' | 'info';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
|
+
|
|
8
|
+
interface MessageProps {
|
|
9
|
+
/** Message contents goes here */
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
/** Message ref */
|
|
12
|
+
ref?: HTMLDivElement;
|
|
13
|
+
/** What color to use? */
|
|
14
|
+
color?: MessageColor;
|
|
15
|
+
/** Custom css class*/
|
|
16
|
+
class?: string;
|
|
17
|
+
/** Test: ⚠️ Unsafe Children String. Do Not use*/
|
|
18
|
+
_unsafeChildrenStringForTesting?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
children,
|
|
23
|
+
class: className = '',
|
|
24
|
+
color = 'default',
|
|
25
|
+
ref = $bindable<HTMLDivElement>(),
|
|
26
|
+
_unsafeChildrenStringForTesting,
|
|
27
|
+
}: MessageProps = $props();
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class={['dodo-ui-Message', `color--${color}`, className].join(' ')} bind:this={ref}>
|
|
31
|
+
{#if children}
|
|
32
|
+
{@render children()}
|
|
33
|
+
{:else if _unsafeChildrenStringForTesting}
|
|
34
|
+
{_unsafeChildrenStringForTesting}
|
|
35
|
+
{/if}
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<style lang="scss">
|
|
39
|
+
.dodo-ui-Message {
|
|
40
|
+
font-size: 1rem;
|
|
41
|
+
letter-spacing: 0.3px;
|
|
42
|
+
display: flex;
|
|
43
|
+
font-family: inherit;
|
|
44
|
+
|
|
45
|
+
&.color {
|
|
46
|
+
&--default {
|
|
47
|
+
color: var(--dodo-color-default-800);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&--primary {
|
|
51
|
+
color: var(--dodo-color-primary-600);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&--safe {
|
|
55
|
+
color: var(--dodo-color-safe-600);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&--warning {
|
|
59
|
+
color: var(--dodo-color-warning-600);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&--danger {
|
|
63
|
+
color: var(--dodo-color-danger-600);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&--info {
|
|
67
|
+
color: var(--dodo-color-info-600);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import { storyPasswordInputArgTypes } from '../PasswordInput.stories.svelte';
|
|
4
|
+
import PasswordInput, { type PasswordInputToggleEvent } from '../PasswordInput.svelte';
|
|
5
|
+
import type {
|
|
6
|
+
TextInputFocusEvent,
|
|
7
|
+
TextInputClipboardEvent,
|
|
8
|
+
} from '../../TextInput/TextInput.svelte';
|
|
9
|
+
|
|
10
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
11
|
+
const { Story } = defineMeta({
|
|
12
|
+
component: PasswordInput,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: storyPasswordInputArgTypes,
|
|
15
|
+
});
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<Story
|
|
19
|
+
name="Input"
|
|
20
|
+
args={{
|
|
21
|
+
oninput: (e: Event) => {
|
|
22
|
+
const target = e.target as HTMLInputElement;
|
|
23
|
+
|
|
24
|
+
console.log('Input Event', target.value);
|
|
25
|
+
},
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<PasswordInput
|
|
29
|
+
oninput={(e: Event) => {
|
|
30
|
+
const target = e.target as HTMLInputElement;
|
|
31
|
+
|
|
32
|
+
console.log('Input Event', target.value);
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
</Story>
|
|
36
|
+
|
|
37
|
+
<Story
|
|
38
|
+
name="Change"
|
|
39
|
+
args={{
|
|
40
|
+
onchange: (e: Event) => {
|
|
41
|
+
const target = e.target as HTMLInputElement;
|
|
42
|
+
|
|
43
|
+
console.log('onChange Event', target.value);
|
|
44
|
+
},
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<PasswordInput
|
|
48
|
+
onchange={(e: Event) => {
|
|
49
|
+
const target = e.target as HTMLInputElement;
|
|
50
|
+
|
|
51
|
+
console.log('onchange Event', target.value);
|
|
52
|
+
}}
|
|
53
|
+
/>
|
|
54
|
+
</Story>
|
|
55
|
+
|
|
56
|
+
<!-- `e: PasswordInputToggleEvent` -->
|
|
57
|
+
<Story
|
|
58
|
+
name="Toggle"
|
|
59
|
+
args={{
|
|
60
|
+
ontoggle: (e: PasswordInputToggleEvent) => {
|
|
61
|
+
const target = e.event.target as HTMLButtonElement;
|
|
62
|
+
|
|
63
|
+
console.log('ontoggle Event', e, target);
|
|
64
|
+
},
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<PasswordInput
|
|
68
|
+
ontoggle={(e: PasswordInputToggleEvent) => {
|
|
69
|
+
const target = e.event.target as HTMLButtonElement;
|
|
70
|
+
|
|
71
|
+
console.log('ontoggle Event', e, target);
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
</Story>
|
|
75
|
+
|
|
76
|
+
<!-- `e: TextInputFocusEvent` -->
|
|
77
|
+
<Story
|
|
78
|
+
name="Focus"
|
|
79
|
+
args={{
|
|
80
|
+
onfocus: (e: TextInputFocusEvent) => {
|
|
81
|
+
const target = e.target as HTMLInputElement;
|
|
82
|
+
|
|
83
|
+
console.log('onfocus Event', target);
|
|
84
|
+
},
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<PasswordInput
|
|
88
|
+
onfocus={(e: TextInputFocusEvent) => {
|
|
89
|
+
const target = e.target as HTMLInputElement;
|
|
90
|
+
|
|
91
|
+
console.log('onfocus Event', target);
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
</Story>
|
|
95
|
+
|
|
96
|
+
<!-- `e: TextInputFocusEvent` -->
|
|
97
|
+
<Story
|
|
98
|
+
name="Blur"
|
|
99
|
+
args={{
|
|
100
|
+
onblur: (e: TextInputFocusEvent) => {
|
|
101
|
+
const target = e.target as HTMLInputElement;
|
|
102
|
+
|
|
103
|
+
console.log('onblur Event', target);
|
|
104
|
+
},
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<PasswordInput
|
|
108
|
+
onblur={(e: TextInputFocusEvent) => {
|
|
109
|
+
const target = e.target as HTMLInputElement;
|
|
110
|
+
|
|
111
|
+
console.log('onblur Event', target);
|
|
112
|
+
}}
|
|
113
|
+
/>
|
|
114
|
+
</Story>
|
|
115
|
+
|
|
116
|
+
<!-- `e: TextInputClipboardEvent` -->
|
|
117
|
+
<Story
|
|
118
|
+
name="Copy"
|
|
119
|
+
args={{
|
|
120
|
+
oncopy: (e: TextInputClipboardEvent) => {
|
|
121
|
+
const target = e.target as HTMLInputElement;
|
|
122
|
+
|
|
123
|
+
console.log('oncopy Event', target);
|
|
124
|
+
},
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
<PasswordInput
|
|
128
|
+
oncopy={(e: TextInputClipboardEvent) => {
|
|
129
|
+
const target = e.target as HTMLInputElement;
|
|
130
|
+
|
|
131
|
+
console.log('oncopy Event', target);
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
</Story>
|
|
135
|
+
|
|
136
|
+
<!-- `e: TextInputClipboardEvent` -->
|
|
137
|
+
<Story
|
|
138
|
+
name="Cut"
|
|
139
|
+
args={{
|
|
140
|
+
oncut: (e: TextInputClipboardEvent) => {
|
|
141
|
+
const target = e.target as HTMLInputElement;
|
|
142
|
+
|
|
143
|
+
console.log('oncut Event', target);
|
|
144
|
+
},
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
<PasswordInput
|
|
148
|
+
oncut={(e: TextInputClipboardEvent) => {
|
|
149
|
+
const target = e.target as HTMLInputElement;
|
|
150
|
+
|
|
151
|
+
console.log('oncut Event', target);
|
|
152
|
+
}}
|
|
153
|
+
/>
|
|
154
|
+
</Story>
|
|
155
|
+
|
|
156
|
+
<!-- `e: TextInputClipboardEvent` -->
|
|
157
|
+
<Story
|
|
158
|
+
name="Paste"
|
|
159
|
+
args={{
|
|
160
|
+
onpaste: (e: TextInputClipboardEvent) => {
|
|
161
|
+
const target = e.target as HTMLInputElement;
|
|
162
|
+
|
|
163
|
+
console.log('onpaste Event', target);
|
|
164
|
+
},
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
<PasswordInput
|
|
168
|
+
onpaste={(e: TextInputClipboardEvent) => {
|
|
169
|
+
const target = e.target as HTMLInputElement;
|
|
170
|
+
|
|
171
|
+
console.log('onpaste Event', target);
|
|
172
|
+
}}
|
|
173
|
+
/>
|
|
174
|
+
</Story>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import PasswordInput from './PasswordInput.svelte';
|
|
4
|
+
import type { StoryBookArgTypes } from '$lib/storybook-types.js';
|
|
5
|
+
import Icon from '@iconify/svelte';
|
|
6
|
+
|
|
7
|
+
export const storyPasswordInputArgTypes: StoryBookArgTypes = {
|
|
8
|
+
roundness: {
|
|
9
|
+
control: { type: 'select' },
|
|
10
|
+
options: [false, '1x', '2x', '3x'],
|
|
11
|
+
},
|
|
12
|
+
size: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['normal', 'small', 'large'],
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
19
|
+
const { Story } = defineMeta({
|
|
20
|
+
component: PasswordInput,
|
|
21
|
+
tags: ['autodocs'],
|
|
22
|
+
argTypes: storyPasswordInputArgTypes,
|
|
23
|
+
args: { value: 'Hello world!' },
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<!-- PasswordInput with default style -->
|
|
28
|
+
<Story name="Default" />
|
|
29
|
+
|
|
30
|
+
<Story name="Placeholder" args={{ value: '', placeholder: 'Type something...' }} />
|
|
31
|
+
|
|
32
|
+
<Story name="No Outline" args={{ outline: false }} />
|
|
33
|
+
|
|
34
|
+
<Story name="Error" args={{ error: true }} />
|
|
35
|
+
|
|
36
|
+
<Story name="Disabled" args={{ disabled: true }} />
|
|
37
|
+
|
|
38
|
+
<!-- Disable password toggle -->
|
|
39
|
+
<Story name="No toggle" args={{ passwordToggle: false }} />
|
|
40
|
+
|
|
41
|
+
<!-- Show Password by default -->
|
|
42
|
+
<Story name="Show Password" args={{ passwordToggleState: true }} />
|
|
43
|
+
|
|
44
|
+
<Story name="Read only" args={{ readonly: true }} />
|
|
45
|
+
|
|
46
|
+
<!-- Show Password by default -->
|
|
47
|
+
<Story name="Custom toggle icon">
|
|
48
|
+
<PasswordInput value="Hello world!">
|
|
49
|
+
{#snippet customPasswordToggleIcon(toggle)}
|
|
50
|
+
{#if toggle}
|
|
51
|
+
<Icon icon="mingcute:eye-close-line" width="24" height="24" />
|
|
52
|
+
{:else}
|
|
53
|
+
<Icon icon="mingcute:eye-2-line" width="24" height="24" />
|
|
54
|
+
{/if}
|
|
55
|
+
{/snippet}
|
|
56
|
+
</PasswordInput>
|
|
57
|
+
</Story>
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type PasswordInputToggleEvent = {
|
|
3
|
+
event: Event;
|
|
4
|
+
toggle: boolean;
|
|
5
|
+
};
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
import type { ComponentSize } from '$lib/types.js';
|
|
10
|
+
import type { Snippet } from 'svelte';
|
|
11
|
+
import type {
|
|
12
|
+
ChangeEventHandler,
|
|
13
|
+
ClipboardEventHandler,
|
|
14
|
+
FocusEventHandler,
|
|
15
|
+
FormEventHandler,
|
|
16
|
+
} from 'svelte/elements';
|
|
17
|
+
import type { TextInputFocusEvent, TextInputRoundness } from '../TextInput/TextInput.svelte';
|
|
18
|
+
import Icon from '@iconify/svelte';
|
|
19
|
+
import UtilityButton from '$lib/stories/developer tools/components/UtilityButton/UtilityButton.svelte';
|
|
20
|
+
|
|
21
|
+
interface PasswordInputProps {
|
|
22
|
+
/** How large should the button be? */
|
|
23
|
+
size?: ComponentSize;
|
|
24
|
+
/** Input ref */
|
|
25
|
+
ref?: HTMLInputElement;
|
|
26
|
+
/** Toggle Password */
|
|
27
|
+
passwordToggle?: boolean;
|
|
28
|
+
/** Default Password Toggle State */
|
|
29
|
+
passwordToggleState?: boolean;
|
|
30
|
+
/** Toggle Password Icon */
|
|
31
|
+
customPasswordToggleIcon?: (toggle: boolean) => Snippet;
|
|
32
|
+
/** How round should the border radius be? */
|
|
33
|
+
roundness?: TextInputRoundness;
|
|
34
|
+
/** Add a border around the button. Default True */
|
|
35
|
+
outline?: boolean;
|
|
36
|
+
/** Input value */
|
|
37
|
+
value?: string;
|
|
38
|
+
/** How round should the border radius be? */
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
/** disabled state */
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
/** Read only ? */
|
|
43
|
+
readonly?: boolean;
|
|
44
|
+
/** is there any associated Error ? */
|
|
45
|
+
error?: boolean;
|
|
46
|
+
/** Name */
|
|
47
|
+
name?: string;
|
|
48
|
+
/** Id */
|
|
49
|
+
id?: string;
|
|
50
|
+
/** Icon before button content */
|
|
51
|
+
before?: Snippet;
|
|
52
|
+
/** Icon after button content */
|
|
53
|
+
after?: Snippet;
|
|
54
|
+
/** Custom css class*/
|
|
55
|
+
class?: string;
|
|
56
|
+
/** oninput event handler */
|
|
57
|
+
oninput?: FormEventHandler<HTMLInputElement>;
|
|
58
|
+
/** onchange event handler */
|
|
59
|
+
onchange?: ChangeEventHandler<HTMLInputElement>;
|
|
60
|
+
/** onblur event handler */
|
|
61
|
+
onblur?: FocusEventHandler<HTMLInputElement>;
|
|
62
|
+
/** onfocus event handler */
|
|
63
|
+
onfocus?: FocusEventHandler<HTMLInputElement>;
|
|
64
|
+
/** onpaste event handler */
|
|
65
|
+
onpaste?: ClipboardEventHandler<HTMLInputElement>;
|
|
66
|
+
/** oncopy event handler */
|
|
67
|
+
oncopy?: ClipboardEventHandler<HTMLInputElement>;
|
|
68
|
+
/** oncut event handler */
|
|
69
|
+
oncut?: ClipboardEventHandler<HTMLInputElement>;
|
|
70
|
+
/** ontoggle event handler */
|
|
71
|
+
ontoggle?: (e: PasswordInputToggleEvent) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let {
|
|
75
|
+
size = 'normal',
|
|
76
|
+
roundness = '1x',
|
|
77
|
+
outline = true,
|
|
78
|
+
name,
|
|
79
|
+
id,
|
|
80
|
+
class: className = '',
|
|
81
|
+
disabled = false,
|
|
82
|
+
oninput,
|
|
83
|
+
onchange,
|
|
84
|
+
onblur,
|
|
85
|
+
onfocus,
|
|
86
|
+
onpaste,
|
|
87
|
+
oncopy,
|
|
88
|
+
oncut,
|
|
89
|
+
before,
|
|
90
|
+
after,
|
|
91
|
+
customPasswordToggleIcon,
|
|
92
|
+
error = false,
|
|
93
|
+
passwordToggle = true,
|
|
94
|
+
passwordToggleState = $bindable<boolean>(),
|
|
95
|
+
value = $bindable<string>(),
|
|
96
|
+
placeholder,
|
|
97
|
+
ontoggle,
|
|
98
|
+
ref = $bindable<HTMLInputElement>(),
|
|
99
|
+
readonly = false,
|
|
100
|
+
}: PasswordInputProps = $props();
|
|
101
|
+
|
|
102
|
+
let focused: boolean = $state(false);
|
|
103
|
+
let toggle: boolean = $state(passwordToggleState);
|
|
104
|
+
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
let customPasswordToggleIconTyped = customPasswordToggleIcon as any;
|
|
107
|
+
|
|
108
|
+
function onfocusMod(e: TextInputFocusEvent) {
|
|
109
|
+
focused = true;
|
|
110
|
+
|
|
111
|
+
if (onfocus) {
|
|
112
|
+
onfocus(e);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function onblurMod(e: TextInputFocusEvent) {
|
|
117
|
+
focused = false;
|
|
118
|
+
|
|
119
|
+
if (onblur) {
|
|
120
|
+
onblur(e);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function ontoggleMod(e: Event) {
|
|
125
|
+
toggle = !toggle;
|
|
126
|
+
|
|
127
|
+
const customEvent: PasswordInputToggleEvent = {
|
|
128
|
+
event: e,
|
|
129
|
+
toggle,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (ontoggle) {
|
|
133
|
+
ontoggle(customEvent);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<div
|
|
139
|
+
class:outline
|
|
140
|
+
class:disabled
|
|
141
|
+
class:error
|
|
142
|
+
class:focused
|
|
143
|
+
class:toggle
|
|
144
|
+
class={['dodo-ui-PasswordInput', `size--${size}`, `roundness--${roundness}`, className].join(' ')}
|
|
145
|
+
>
|
|
146
|
+
{#if before}
|
|
147
|
+
<span class="content--before">
|
|
148
|
+
{@render before()}
|
|
149
|
+
</span>
|
|
150
|
+
{/if}
|
|
151
|
+
<input
|
|
152
|
+
type={passwordToggle && toggle ? 'text' : 'password'}
|
|
153
|
+
{name}
|
|
154
|
+
{id}
|
|
155
|
+
{disabled}
|
|
156
|
+
{oninput}
|
|
157
|
+
{onchange}
|
|
158
|
+
onfocus={onfocusMod}
|
|
159
|
+
onblur={onblurMod}
|
|
160
|
+
{onpaste}
|
|
161
|
+
{oncopy}
|
|
162
|
+
{oncut}
|
|
163
|
+
{placeholder}
|
|
164
|
+
bind:value
|
|
165
|
+
bind:this={ref}
|
|
166
|
+
{readonly}
|
|
167
|
+
/>
|
|
168
|
+
|
|
169
|
+
{#if passwordToggle && !disabled}
|
|
170
|
+
<UtilityButton {size} title="Toggle password" class="passwordToggle" onclick={ontoggleMod}>
|
|
171
|
+
{#if customPasswordToggleIcon}
|
|
172
|
+
{@render customPasswordToggleIconTyped(toggle)}
|
|
173
|
+
{:else if toggle}
|
|
174
|
+
<Icon icon="mdi:eye-off" width="24" height="24" />
|
|
175
|
+
{:else}
|
|
176
|
+
<Icon icon="mdi:eye" width="24" height="24" />
|
|
177
|
+
{/if}
|
|
178
|
+
</UtilityButton>
|
|
179
|
+
{/if}
|
|
180
|
+
|
|
181
|
+
{#if after}
|
|
182
|
+
<span class="content--after">
|
|
183
|
+
{@render after()}
|
|
184
|
+
</span>
|
|
185
|
+
{/if}
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
<style lang="scss">
|
|
189
|
+
:global(:root) {
|
|
190
|
+
--dodo-ui-PasswordInput-border-color: var(--dodo-color-default-500);
|
|
191
|
+
--dodo-ui-PasswordInput-focus-border-color: var(--dodo-color-primary-500);
|
|
192
|
+
--dodo-ui-PasswordInput-error-border-color: var(--dodo-color-danger-500);
|
|
193
|
+
|
|
194
|
+
--dodo-ui-PasswordInput-disabled-color: var(--dodo-color-default-400);
|
|
195
|
+
--dodo-ui-PasswordInput-disabled-bg: var(--dodo-color-default-200);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
:global(.dodo-theme--dark) {
|
|
199
|
+
--dodo-ui-PasswordInput-border-color: var(--dodo-color-default-600);
|
|
200
|
+
--dodo-ui-PasswordInput-focus-border-color: var(--dodo-color-primary-600);
|
|
201
|
+
--dodo-ui-PasswordInput-error-border-color: var(--dodo-color-danger-600);
|
|
202
|
+
|
|
203
|
+
--dodo-ui-PasswordInput-disabled-bg: var(--dodo-color-default-100);
|
|
204
|
+
--dodo-ui-PasswordInput-disabled-color: var(--dodo-color-default-500);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.dodo-ui-PasswordInput {
|
|
208
|
+
display: flex;
|
|
209
|
+
overflow: hidden;
|
|
210
|
+
color: var(--dodo-color-default-800);
|
|
211
|
+
transition: all 150ms;
|
|
212
|
+
border: 0;
|
|
213
|
+
|
|
214
|
+
input {
|
|
215
|
+
flex: 1;
|
|
216
|
+
border: 0;
|
|
217
|
+
outline: 0;
|
|
218
|
+
height: 100%;
|
|
219
|
+
background-color: transparent;
|
|
220
|
+
font-family: inherit;
|
|
221
|
+
color: inherit;
|
|
222
|
+
letter-spacing: 0.3px;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
&.outline {
|
|
226
|
+
border-style: solid;
|
|
227
|
+
border-width: var(--dodo-ui-element-border-width);
|
|
228
|
+
border-color: var(--dodo-ui-PasswordInput-border-color);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&.focused {
|
|
232
|
+
border-color: var(--dodo-ui-PasswordInput-focus-border-color);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&.error {
|
|
236
|
+
border-color: var(--dodo-ui-PasswordInput-error-border-color);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
&.disabled {
|
|
240
|
+
cursor: initial;
|
|
241
|
+
background-color: var(--dodo-ui-PasswordInput-disabled-bg);
|
|
242
|
+
color: var(--dodo-ui-PasswordInput-disabled-color);
|
|
243
|
+
border-color: var(--dodo-ui-PasswordInput-disabled-bg);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.content {
|
|
247
|
+
&--after,
|
|
248
|
+
&--before {
|
|
249
|
+
&:empty {
|
|
250
|
+
display: none;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
&--after,
|
|
255
|
+
&--before {
|
|
256
|
+
display: inline-flex;
|
|
257
|
+
height: 100%;
|
|
258
|
+
align-items: center;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
&.size {
|
|
263
|
+
&--normal {
|
|
264
|
+
height: var(--dodo-ui-element-height-normal);
|
|
265
|
+
input {
|
|
266
|
+
font-size: 1rem;
|
|
267
|
+
padding: 0 12px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.content {
|
|
271
|
+
&--before {
|
|
272
|
+
margin-left: 12px;
|
|
273
|
+
margin-right: -4px;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
&--after {
|
|
277
|
+
margin-right: 12px;
|
|
278
|
+
margin-left: -4px;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
&--small {
|
|
284
|
+
height: var(--dodo-ui-element-height-small);
|
|
285
|
+
input {
|
|
286
|
+
padding: 0 8px;
|
|
287
|
+
font-size: 0.9rem;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.content {
|
|
291
|
+
&--before {
|
|
292
|
+
margin-left: 8px;
|
|
293
|
+
margin-right: -2px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
&--after {
|
|
297
|
+
margin-right: 8px;
|
|
298
|
+
margin-left: -2px;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
&--large {
|
|
304
|
+
height: var(--dodo-ui-element-height-large);
|
|
305
|
+
input {
|
|
306
|
+
font-size: 1.1rem;
|
|
307
|
+
padding: 0 14px;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.content {
|
|
311
|
+
&--before {
|
|
312
|
+
margin-left: 14px;
|
|
313
|
+
margin-right: -4px;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
&--after {
|
|
317
|
+
margin-right: 14px;
|
|
318
|
+
margin-left: -4px;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
&.roundness {
|
|
325
|
+
&--1x {
|
|
326
|
+
border-radius: var(--dodo-ui-element-roundness-1x);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
&--2x {
|
|
330
|
+
border-radius: var(--dodo-ui-element-roundness-2x);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
&--3x {
|
|
334
|
+
border-radius: var(--dodo-ui-element-roundness-3x);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import PasswordInput from '../PasswordInput.svelte';
|
|
4
|
+
import { storyPasswordInputArgTypes } from '../PasswordInput.stories.svelte';
|
|
5
|
+
|
|
6
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
7
|
+
const { Story } = defineMeta({
|
|
8
|
+
component: PasswordInput,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
argTypes: storyPasswordInputArgTypes,
|
|
11
|
+
});
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<Story name="Roundness 1x" />
|
|
15
|
+
|
|
16
|
+
<Story name="Roundness 2x" args={{ roundness: '2x' }} />
|
|
17
|
+
|
|
18
|
+
<Story name="Roundness 3x" args={{ roundness: '3x' }} />
|
|
19
|
+
|
|
20
|
+
<Story name="Roundness False" args={{ roundness: false }} />
|