revotech-ui-kit 0.0.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/.editorconfig +29 -0
- package/.eslintrc +10 -0
- package/.storybook/main.ts +17 -0
- package/.storybook/preview-head.html +1 -0
- package/.storybook/preview.ts +17 -0
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/assets/fonts/Geist/Geist-Black.otf +0 -0
- package/assets/fonts/Geist/Geist-Black.woff2 +0 -0
- package/assets/fonts/Geist/Geist-Bold.otf +0 -0
- package/assets/fonts/Geist/Geist-Bold.woff2 +0 -0
- package/assets/fonts/Geist/Geist-Light.otf +0 -0
- package/assets/fonts/Geist/Geist-Light.woff2 +0 -0
- package/assets/fonts/Geist/Geist-Medium.otf +0 -0
- package/assets/fonts/Geist/Geist-Medium.woff2 +0 -0
- package/assets/fonts/Geist/Geist-Regular.otf +0 -0
- package/assets/fonts/Geist/Geist-Regular.woff2 +0 -0
- package/assets/fonts/Geist/Geist-SemiBold.otf +0 -0
- package/assets/fonts/Geist/Geist-SemiBold.woff2 +0 -0
- package/assets/fonts/Geist/Geist-Thin.otf +0 -0
- package/assets/fonts/Geist/Geist-Thin.woff2 +0 -0
- package/assets/fonts/Geist/Geist-UltraBlack.otf +0 -0
- package/assets/fonts/Geist/Geist-UltraBlack.woff2 +0 -0
- package/assets/fonts/Geist/Geist-UltraLight.otf +0 -0
- package/assets/fonts/Geist/Geist-UltraLight.woff2 +0 -0
- package/assets/fonts/Geist/GeistVariableVF.ttf +0 -0
- package/assets/fonts/Geist/GeistVariableVF.woff2 +0 -0
- package/assets/fonts/Geist/LICENSE.TXT +92 -0
- package/assets/open-wc-logo.svg +29 -0
- package/index.html +362 -0
- package/package.json +117 -0
- package/rollup.config.js +71 -0
- package/src/components/atoms/button/button.atom.ts +39 -0
- package/src/components/atoms/button/button.stories.ts +186 -0
- package/src/components/atoms/button/button.style.ts +31 -0
- package/src/components/atoms/button/button.type.ts +10 -0
- package/src/components/atoms/checkbox/checkbox.atom.ts +62 -0
- package/src/components/atoms/checkbox/checkbox.stories.ts +42 -0
- package/src/components/atoms/command-empty/command-empty.atom.ts +44 -0
- package/src/components/atoms/command-group/command-group.atom.ts +60 -0
- package/src/components/atoms/command-item/command-item.atom.ts +74 -0
- package/src/components/atoms/command-list/command-list.atom.ts +37 -0
- package/src/components/atoms/command-separator/command-separator.atom.ts +42 -0
- package/src/components/atoms/dialog/dialog.atom.ts +301 -0
- package/src/components/atoms/dialog/dialog.stories.ts +86 -0
- package/src/components/atoms/index.ts +10 -0
- package/src/components/atoms/input/input.atom.ts +34 -0
- package/src/components/atoms/input/input.stories.ts +89 -0
- package/src/components/atoms/input/input.type.ts +24 -0
- package/src/components/atoms/label/label.atom.ts +40 -0
- package/src/components/atoms/label/label.stories.ts +18 -0
- package/src/components/atoms/label/label.style.ts +5 -0
- package/src/components/command/command.stories.ts +154 -0
- package/src/components/command/command.ts +391 -0
- package/src/components/index.ts +2 -0
- package/src/components/molecules/command/command.molecules.ts +31 -0
- package/src/components/molecules/command-input/command-input.atom.ts +130 -0
- package/src/components/molecules/index.ts +1 -0
- package/src/components/popover.ts +247 -0
- package/src/globals.css +1806 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/mouse-conroller.helper.ts +42 -0
- package/src/helpers/style.helpers.ts +6 -0
- package/src/interfaces/actionable.interface.ts +6 -0
- package/src/interfaces/atomic.interface.ts +6 -0
- package/src/interfaces/changeable.interface.ts +14 -0
- package/src/interfaces/child-support-atomic.interface.ts +5 -0
- package/src/interfaces/index.ts +6 -0
- package/src/interfaces/intractable.interface.ts +6 -0
- package/src/interfaces/variant.interface.ts +3 -0
- package/src/lib/index.ts +0 -0
- package/src/lib/next/next.lib.ts +0 -0
- package/src/lib/react/react.lib.ts +0 -0
- package/src/styles/index.ts +1 -0
- package/src/styles/tw.styles.ts +1867 -0
- package/src/tailwind-lib.css +95 -0
- package/src/wc-ui-app.ts +81 -0
- package/tailwind.config.js +81 -0
- package/test/wc-ui-app.test.ts +22 -0
- package/tsconfig.json +25 -0
- package/web-dev-server.config.mjs +26 -0
- package/web-test-runner.config.mjs +41 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
/* eslint-disable no-use-before-define */
|
2
|
+
import {
|
3
|
+
LitElement,
|
4
|
+
html,
|
5
|
+
css,
|
6
|
+
PropertyValueMap,
|
7
|
+
nothing,
|
8
|
+
PropertyValues,
|
9
|
+
} from 'lit';
|
10
|
+
import { customElement, property } from 'lit/decorators.js';
|
11
|
+
import { cn } from '@/helpers';
|
12
|
+
import { TWStyles } from '@/styles';
|
13
|
+
|
14
|
+
const STATE_OPEN = 'open';
|
15
|
+
const STATE_CLOSED = 'closed';
|
16
|
+
|
17
|
+
@customElement('rtg-dialog')
|
18
|
+
export class Dialog extends LitElement {
|
19
|
+
static styles = [css``, TWStyles];
|
20
|
+
|
21
|
+
@property({ attribute: 'data-state', type: String }) state = STATE_CLOSED;
|
22
|
+
|
23
|
+
private get _content(): DialogContent | null {
|
24
|
+
const slot = this.shadowRoot?.querySelector('slot');
|
25
|
+
const children = slot?.assignedElements();
|
26
|
+
if (children) {
|
27
|
+
for (let index = 0; index < children.length; index++) {
|
28
|
+
if (children[index] instanceof DialogContent) {
|
29
|
+
return children[index] as DialogContent;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
return null;
|
35
|
+
}
|
36
|
+
|
37
|
+
protected updated(_changedProperties: PropertyValues): void {
|
38
|
+
super.updated(_changedProperties);
|
39
|
+
const content = this._content;
|
40
|
+
if (content) {
|
41
|
+
content.dataset.state = this.state;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
render() {
|
46
|
+
return html`
|
47
|
+
<div rtgdlg-root>
|
48
|
+
${this.state === STATE_OPEN
|
49
|
+
? html` <rtg-dialog-overlay></rtg-dialog-overlay>`
|
50
|
+
: nothing}
|
51
|
+
<slot></slot>
|
52
|
+
</div>
|
53
|
+
`;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
@customElement('rtg-dialog-content')
|
58
|
+
export class DialogContent extends LitElement {
|
59
|
+
static styles = [css``, TWStyles];
|
60
|
+
|
61
|
+
@property({ attribute: 'data-state', type: String }) state = STATE_CLOSED;
|
62
|
+
|
63
|
+
private get _dialog(): Dialog | null {
|
64
|
+
let parent = this.parentElement;
|
65
|
+
|
66
|
+
while (parent) {
|
67
|
+
if (parent instanceof Dialog) {
|
68
|
+
return parent;
|
69
|
+
}
|
70
|
+
parent = parent.parentElement;
|
71
|
+
}
|
72
|
+
return parent;
|
73
|
+
}
|
74
|
+
|
75
|
+
private handleCloseButtonClick = () => {
|
76
|
+
const dialog = this._dialog;
|
77
|
+
if (dialog) {
|
78
|
+
dialog.dataset.state = STATE_CLOSED;
|
79
|
+
}
|
80
|
+
};
|
81
|
+
|
82
|
+
render() {
|
83
|
+
return html`${this.state === STATE_OPEN
|
84
|
+
? html`
|
85
|
+
<div
|
86
|
+
class="${cn(
|
87
|
+
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
88
|
+
this.className
|
89
|
+
)}"
|
90
|
+
rtgdlg-content
|
91
|
+
>
|
92
|
+
<slot></slot>
|
93
|
+
<button
|
94
|
+
type="button"
|
95
|
+
@click="${this.handleCloseButtonClick}"
|
96
|
+
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
97
|
+
>
|
98
|
+
<svg
|
99
|
+
xmlns="http://www.w3.org/2000/svg"
|
100
|
+
width="24"
|
101
|
+
height="24"
|
102
|
+
viewBox="0 0 24 24"
|
103
|
+
fill="none"
|
104
|
+
stroke="currentColor"
|
105
|
+
stroke-width="2"
|
106
|
+
stroke-linecap="round"
|
107
|
+
stroke-linejoin="round"
|
108
|
+
class="h-4 w-4"
|
109
|
+
>
|
110
|
+
<path d="M18 6 6 18"></path>
|
111
|
+
<path d="m6 6 12 12"></path></svg
|
112
|
+
><span class="sr-only">Close</span>
|
113
|
+
</button>
|
114
|
+
</div>
|
115
|
+
`
|
116
|
+
: nothing}`;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
@customElement('rtg-dialog-overlay')
|
121
|
+
export class DialogOverlay extends LitElement {
|
122
|
+
static styles = [css``, TWStyles];
|
123
|
+
|
124
|
+
render() {
|
125
|
+
return html`
|
126
|
+
<div
|
127
|
+
class="${cn(
|
128
|
+
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
129
|
+
this.className
|
130
|
+
)}"
|
131
|
+
></div>
|
132
|
+
`;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
@customElement('rtg-dialog-header')
|
137
|
+
export class DialogHeader extends LitElement {
|
138
|
+
static styles = [css``, TWStyles];
|
139
|
+
|
140
|
+
@property({ attribute: 'title', type: String }) _title = '';
|
141
|
+
|
142
|
+
@property({ type: String }) description = '';
|
143
|
+
|
144
|
+
render() {
|
145
|
+
return html`
|
146
|
+
<div
|
147
|
+
class="${cn(
|
148
|
+
'flex flex-col space-y-1.5 text-center sm:text-left',
|
149
|
+
this.className
|
150
|
+
)}"
|
151
|
+
>
|
152
|
+
<h2
|
153
|
+
class="${cn(
|
154
|
+
'text-lg font-semibold leading-none tracking-tight',
|
155
|
+
this.className
|
156
|
+
)}"
|
157
|
+
>
|
158
|
+
${this._title}
|
159
|
+
</h2>
|
160
|
+
<p class="${cn('text-sm text-muted-foreground', this.className)}">
|
161
|
+
${this.description}
|
162
|
+
</p>
|
163
|
+
</div>
|
164
|
+
`;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
@customElement('rtg-dialog-footer')
|
169
|
+
export class DialogFooter extends LitElement {
|
170
|
+
static styles = [css``, TWStyles];
|
171
|
+
|
172
|
+
render() {
|
173
|
+
return html`
|
174
|
+
<div
|
175
|
+
class="${cn(
|
176
|
+
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
177
|
+
this.className
|
178
|
+
)}"
|
179
|
+
>
|
180
|
+
<slot></slot>
|
181
|
+
</div>
|
182
|
+
`;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
// @customElement('rtg-dialog-title')
|
187
|
+
// export class DialogTitle extends LitElement {
|
188
|
+
// static styles = [css``, TWStyles];
|
189
|
+
|
190
|
+
// render() {
|
191
|
+
// return html`
|
192
|
+
// <h2
|
193
|
+
// class="${cn(
|
194
|
+
// 'text-lg font-semibold leading-none tracking-tight',
|
195
|
+
// this.className
|
196
|
+
// )}"
|
197
|
+
// >
|
198
|
+
// <slot></slot>
|
199
|
+
// </h2>
|
200
|
+
// `;
|
201
|
+
// }
|
202
|
+
// }
|
203
|
+
|
204
|
+
// @customElement('rtg-dialog-description')
|
205
|
+
// export class DialogDescription extends LitElement {
|
206
|
+
// static styles = [css``, TWStyles];
|
207
|
+
|
208
|
+
// render() {
|
209
|
+
// return html`
|
210
|
+
// <p class="${cn('text-sm text-muted-foreground', this.className)}">
|
211
|
+
// <slot></slot>
|
212
|
+
// </p>
|
213
|
+
// `;
|
214
|
+
// }
|
215
|
+
// }
|
216
|
+
|
217
|
+
@customElement('rtg-dialog-trigger')
|
218
|
+
export class DialogTrigger extends LitElement {
|
219
|
+
static styles = [css``, TWStyles];
|
220
|
+
|
221
|
+
private get _dialog(): Dialog | null {
|
222
|
+
let parent = this.parentElement;
|
223
|
+
|
224
|
+
while (parent) {
|
225
|
+
if (parent instanceof Dialog) {
|
226
|
+
return parent;
|
227
|
+
}
|
228
|
+
parent = parent.parentElement;
|
229
|
+
}
|
230
|
+
return parent;
|
231
|
+
}
|
232
|
+
|
233
|
+
protected firstUpdated(
|
234
|
+
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
235
|
+
): void {
|
236
|
+
super.firstUpdated(_changedProperties);
|
237
|
+
const slot = this.shadowRoot?.querySelector('slot');
|
238
|
+
const children = slot?.assignedElements();
|
239
|
+
if (children && children.length > 0) {
|
240
|
+
const button = children[0];
|
241
|
+
|
242
|
+
button.addEventListener('click', () => {
|
243
|
+
const dialog = this._dialog;
|
244
|
+
if (dialog) {
|
245
|
+
dialog.dataset.state = STATE_OPEN;
|
246
|
+
}
|
247
|
+
});
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
render() {
|
252
|
+
return html`
|
253
|
+
<div>
|
254
|
+
<slot></slot>
|
255
|
+
</div>
|
256
|
+
`;
|
257
|
+
}
|
258
|
+
}
|
259
|
+
|
260
|
+
@customElement('rtg-dialog-close')
|
261
|
+
export class DialogClose extends LitElement {
|
262
|
+
static styles = [css``, TWStyles];
|
263
|
+
|
264
|
+
private get _dialog(): Dialog | null {
|
265
|
+
let parent = this.parentElement;
|
266
|
+
|
267
|
+
while (parent) {
|
268
|
+
if (parent instanceof Dialog) {
|
269
|
+
return parent;
|
270
|
+
}
|
271
|
+
parent = parent.parentElement;
|
272
|
+
}
|
273
|
+
return parent;
|
274
|
+
}
|
275
|
+
|
276
|
+
protected firstUpdated(
|
277
|
+
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
278
|
+
): void {
|
279
|
+
super.firstUpdated(_changedProperties);
|
280
|
+
const slot = this.shadowRoot?.querySelector('slot');
|
281
|
+
const children = slot?.assignedElements();
|
282
|
+
if (children && children.length > 0) {
|
283
|
+
const button = children[0];
|
284
|
+
|
285
|
+
button.addEventListener('click', () => {
|
286
|
+
const dialog = this._dialog;
|
287
|
+
if (dialog) {
|
288
|
+
dialog.dataset.state = STATE_CLOSED;
|
289
|
+
}
|
290
|
+
});
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
render() {
|
295
|
+
return html`
|
296
|
+
<div>
|
297
|
+
<slot></slot>
|
298
|
+
</div>
|
299
|
+
`;
|
300
|
+
}
|
301
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import { html } from 'lit';
|
2
|
+
import { Meta, StoryObj } from '@storybook/web-components';
|
3
|
+
import '../input/input.atom';
|
4
|
+
import './dialog.atom';
|
5
|
+
|
6
|
+
const meta: Meta = {
|
7
|
+
component: 'components/dialog',
|
8
|
+
};
|
9
|
+
|
10
|
+
export default meta;
|
11
|
+
type Story = StoryObj;
|
12
|
+
|
13
|
+
export const ConfirmationDialog: Story = {
|
14
|
+
render: () =>
|
15
|
+
html`<div class="flex flex-nowrap">
|
16
|
+
<div class="flex flex-wrap space-x-4 gap-5 mx-3">
|
17
|
+
<rtg-dialog>
|
18
|
+
<rtg-dialog-trigger>
|
19
|
+
<rtg-button>Open Dialog</rtg-button>
|
20
|
+
</rtg-dialog-trigger>
|
21
|
+
<rtg-dialog-content>
|
22
|
+
<rtg-dialog-header title="Are you absolutely sure?" description="This action cannot be undone. This will permanently delete your
|
23
|
+
content.">
|
24
|
+
<rtg-dialog-title>Are you absolutely sure?</rtg-dialog-title>
|
25
|
+
<rtg-dialog-description>
|
26
|
+
This action cannot be undone. This will permanently delete your
|
27
|
+
content.</rtg-dialog-description
|
28
|
+
>
|
29
|
+
</rtg-dialog-header>
|
30
|
+
<rtg-dialog-footer>
|
31
|
+
<div class="flex w-full justify-between space-x-1">
|
32
|
+
<rtg-dialog-close><rtg-button variant="secondary">Close</rtg-button></rtg-dialog-close>
|
33
|
+
<div class="justify-end">
|
34
|
+
<rtg-button variant="destructive">Delete</rtg-button>
|
35
|
+
<rtg-button>Cancel</rtg-button>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</rtg-dialog-content>
|
39
|
+
</rtg-dialog>
|
40
|
+
</div>
|
41
|
+
</div>`,
|
42
|
+
};
|
43
|
+
|
44
|
+
export const ModalForm: Story = {
|
45
|
+
render: () => html`
|
46
|
+
<rtg-dialog>
|
47
|
+
<rtg-dialog-trigger>
|
48
|
+
<rtg-button variant="outline">Edit Profile</rtg-button>
|
49
|
+
</rtg-dialog-trigger>
|
50
|
+
<rtg-dialog-content class="sm:max-w-[425px]">
|
51
|
+
<rtg-dialog-header title="Edit Profile" description="Make changes to your profile here. Click save when you're done.">
|
52
|
+
<!-- <rtg-dialog-title>Edit Profile</rtg-dialog-title>
|
53
|
+
<rtg-dialog-description>
|
54
|
+
Make changes to your profile here. Click save when you're done.</rtg-dialog-description
|
55
|
+
> -->
|
56
|
+
</rtg-dialog-header>
|
57
|
+
<div class="grid gap-4 py-4">
|
58
|
+
<div class="grid grid-cols-4 items-center gap-4">
|
59
|
+
<rtg-label for="name" class="text-right">
|
60
|
+
Name
|
61
|
+
</rtg-label>
|
62
|
+
<rtg-input
|
63
|
+
id="name"
|
64
|
+
defaultValue="Pedro Duarte"
|
65
|
+
class="col-span-3"
|
66
|
+
>
|
67
|
+
</rtg-input>
|
68
|
+
</div>
|
69
|
+
<div class="grid grid-cols-4 items-center gap-4">
|
70
|
+
<rtg-label for="username" class="text-right">
|
71
|
+
Username
|
72
|
+
</rtg-label>
|
73
|
+
<rtg-input
|
74
|
+
id="username"
|
75
|
+
defaultValue="@peduarte"
|
76
|
+
class="col-span-3"
|
77
|
+
>
|
78
|
+
</rtg-input>
|
79
|
+
</div>
|
80
|
+
</div>
|
81
|
+
<rtg-dialog-footer>
|
82
|
+
<rtg-button type="submit" class="w-full sm:w-min">Save changes</rtg-button>
|
83
|
+
</rtg-dialog-content>
|
84
|
+
</rtg-dialog>
|
85
|
+
`,
|
86
|
+
};
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export * from './button/button.atom';
|
2
|
+
export * from './checkbox/checkbox.atom';
|
3
|
+
export * from './dialog/dialog.atom';
|
4
|
+
export * from './input/input.atom';
|
5
|
+
export * from './label/label.atom';
|
6
|
+
export * from './command-empty/command-empty.atom';
|
7
|
+
export * from './command-group/command-group.atom';
|
8
|
+
export * from './command-item/command-item.atom';
|
9
|
+
export * from './command-list/command-list.atom';
|
10
|
+
export * from './command-separator/command-separator.atom';
|
@@ -0,0 +1,34 @@
|
|
1
|
+
/* eslint-disable lit/no-value-attribute */
|
2
|
+
import { LitElement, html, css } from 'lit';
|
3
|
+
import { property, customElement } from 'lit/decorators.js';
|
4
|
+
import { cn } from '@/helpers';
|
5
|
+
import { TWStyles } from '@/styles';
|
6
|
+
import { InputType } from './input.type';
|
7
|
+
|
8
|
+
@customElement('rtg-input')
|
9
|
+
export class Input extends LitElement {
|
10
|
+
@property({ type: Boolean }) disabled = false;
|
11
|
+
|
12
|
+
@property({ type: String }) type: InputType = 'text';
|
13
|
+
|
14
|
+
@property({ type: String }) placeholder = '';
|
15
|
+
|
16
|
+
@property({ type: String }) defaultValue = '';
|
17
|
+
|
18
|
+
static styles = [css``, TWStyles];
|
19
|
+
|
20
|
+
render() {
|
21
|
+
return html`
|
22
|
+
<input
|
23
|
+
type="${this.type}"
|
24
|
+
placeholder="${this.placeholder}"
|
25
|
+
?disabled=${this.disabled}
|
26
|
+
class="${cn(
|
27
|
+
'flex h-8 w-full rounded-sm border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
|
28
|
+
this.className
|
29
|
+
)}"
|
30
|
+
value="${this.defaultValue}"
|
31
|
+
/>
|
32
|
+
`;
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import { html } from 'lit';
|
2
|
+
import { Meta, StoryFn } from '@storybook/web-components';
|
3
|
+
import './input.atom';
|
4
|
+
import '../label/label.atom';
|
5
|
+
import '../button/button.atom';
|
6
|
+
|
7
|
+
export default {
|
8
|
+
title: 'Components/Input',
|
9
|
+
component: 'rtg-input',
|
10
|
+
tags: ['autodocs'],
|
11
|
+
argTypes: {
|
12
|
+
disabled: { control: 'boolean' },
|
13
|
+
type: { control: 'text' },
|
14
|
+
placeholder: { control: 'text' },
|
15
|
+
defaultValue: { control: 'text' },
|
16
|
+
},
|
17
|
+
} as Meta;
|
18
|
+
|
19
|
+
const InputTemplate: StoryFn = args =>
|
20
|
+
html`<rtg-input ...=${args}></rtg-input>`;
|
21
|
+
const TemplateWithLabel: StoryFn = args => html`
|
22
|
+
<rtg-label for="picture">${args.label}</rtg-label>
|
23
|
+
<rtg-input
|
24
|
+
type=${args.type}
|
25
|
+
?disabled=${args.disabled}
|
26
|
+
placeholder=${args.placeholder}
|
27
|
+
></rtg-input>
|
28
|
+
`;
|
29
|
+
const TemplateWithButton: StoryFn = args => html`
|
30
|
+
<div style="display:flex">
|
31
|
+
<rtg-input
|
32
|
+
id=${args.id}
|
33
|
+
type=${args.type}
|
34
|
+
placeholder=${args.placeholder}
|
35
|
+
class="min-w-80"
|
36
|
+
></rtg-input>
|
37
|
+
<rtg-button
|
38
|
+
style="margin-inline-start:4px"
|
39
|
+
size="default"
|
40
|
+
onclick="javascript:alert('Hello!')"
|
41
|
+
>${args.ButtonLabel}</rtg-button
|
42
|
+
>
|
43
|
+
</div>
|
44
|
+
`;
|
45
|
+
|
46
|
+
export const Default = InputTemplate.bind({});
|
47
|
+
Default.args = {
|
48
|
+
disabled: false,
|
49
|
+
type: 'text',
|
50
|
+
placeholder: 'Enter text',
|
51
|
+
defaultValue: '',
|
52
|
+
};
|
53
|
+
|
54
|
+
export const Email = TemplateWithLabel.bind({});
|
55
|
+
Email.args = {
|
56
|
+
label: 'Email address',
|
57
|
+
disabled: false,
|
58
|
+
type: 'email',
|
59
|
+
placeholder: 'Enter email',
|
60
|
+
defaultValue: '',
|
61
|
+
};
|
62
|
+
|
63
|
+
export const Password = TemplateWithLabel.bind({});
|
64
|
+
Password.args = {
|
65
|
+
label: 'Password',
|
66
|
+
disabled: false,
|
67
|
+
type: 'password',
|
68
|
+
placeholder: 'Enter password',
|
69
|
+
defaultValue: '',
|
70
|
+
};
|
71
|
+
|
72
|
+
export const File = TemplateWithLabel.bind({});
|
73
|
+
File.args = {
|
74
|
+
disabled: false,
|
75
|
+
type: 'file',
|
76
|
+
label: 'Picture',
|
77
|
+
placeholder: '',
|
78
|
+
defaultValue: '',
|
79
|
+
};
|
80
|
+
|
81
|
+
export const InputWithButton = TemplateWithButton.bind({});
|
82
|
+
InputWithButton.args = {
|
83
|
+
id: 'id',
|
84
|
+
ButtonLabel: 'Subscribe',
|
85
|
+
disabled: false,
|
86
|
+
type: 'email',
|
87
|
+
placeholder: 'Email',
|
88
|
+
defaultValue: '',
|
89
|
+
};
|
@@ -0,0 +1,24 @@
|
|
1
|
+
export type InputType =
|
2
|
+
| 'hidden'
|
3
|
+
| 'text'
|
4
|
+
| 'search'
|
5
|
+
| 'tel'
|
6
|
+
| 'url'
|
7
|
+
| 'email'
|
8
|
+
| 'password'
|
9
|
+
| 'datetime'
|
10
|
+
| 'date'
|
11
|
+
| 'month'
|
12
|
+
| 'week'
|
13
|
+
| 'time'
|
14
|
+
| 'datetime-local'
|
15
|
+
| 'number'
|
16
|
+
| 'range'
|
17
|
+
| 'color'
|
18
|
+
| 'checkbox'
|
19
|
+
| 'radio'
|
20
|
+
| 'file'
|
21
|
+
| 'submit'
|
22
|
+
| 'image'
|
23
|
+
| 'reset'
|
24
|
+
| 'button';
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
2
|
+
import { property, customElement } from 'lit/decorators.js';
|
3
|
+
import { cva } from 'class-variance-authority';
|
4
|
+
import { cn } from '@/helpers';
|
5
|
+
import { TWStyles } from '@/styles';
|
6
|
+
import { labelStyle } from './label.style';
|
7
|
+
|
8
|
+
@customElement('rtg-label')
|
9
|
+
export class Label extends LitElement {
|
10
|
+
static labelVariants = labelStyle;
|
11
|
+
|
12
|
+
@property({ type: String }) for = '';
|
13
|
+
|
14
|
+
static styles = [css``, TWStyles];
|
15
|
+
|
16
|
+
private _onClick(e: Event) {
|
17
|
+
if (e.defaultPrevented) return;
|
18
|
+
const target = document.getElementById(this.for);
|
19
|
+
if (target) {
|
20
|
+
target.click();
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
render() {
|
25
|
+
return html`
|
26
|
+
<label
|
27
|
+
for="${this.for}"
|
28
|
+
@click="${this._onClick}"
|
29
|
+
@keydown="${this._onClick}"
|
30
|
+
class="${cn(
|
31
|
+
Label.labelVariants({
|
32
|
+
className: this.className,
|
33
|
+
})
|
34
|
+
)}"
|
35
|
+
>
|
36
|
+
<slot></slot>
|
37
|
+
</label>
|
38
|
+
`;
|
39
|
+
}
|
40
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { html } from 'lit';
|
2
|
+
import { Meta, StoryFn } from '@storybook/web-components';
|
3
|
+
import './label.atom';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
title: 'Components/Label',
|
7
|
+
component: 'rtg-label',
|
8
|
+
tags: ['autodocs'],
|
9
|
+
} as Meta;
|
10
|
+
|
11
|
+
const Template: StoryFn = (args: any) =>
|
12
|
+
html` <rtg-label for=${args.for}>${args.label}</rtg-label>`;
|
13
|
+
|
14
|
+
export const Default = Template.bind({});
|
15
|
+
Default.args = {
|
16
|
+
for: 'id',
|
17
|
+
label: 'Email address',
|
18
|
+
};
|