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.
Files changed (82) hide show
  1. package/.editorconfig +29 -0
  2. package/.eslintrc +10 -0
  3. package/.storybook/main.ts +17 -0
  4. package/.storybook/preview-head.html +1 -0
  5. package/.storybook/preview.ts +17 -0
  6. package/LICENSE +21 -0
  7. package/README.md +30 -0
  8. package/assets/fonts/Geist/Geist-Black.otf +0 -0
  9. package/assets/fonts/Geist/Geist-Black.woff2 +0 -0
  10. package/assets/fonts/Geist/Geist-Bold.otf +0 -0
  11. package/assets/fonts/Geist/Geist-Bold.woff2 +0 -0
  12. package/assets/fonts/Geist/Geist-Light.otf +0 -0
  13. package/assets/fonts/Geist/Geist-Light.woff2 +0 -0
  14. package/assets/fonts/Geist/Geist-Medium.otf +0 -0
  15. package/assets/fonts/Geist/Geist-Medium.woff2 +0 -0
  16. package/assets/fonts/Geist/Geist-Regular.otf +0 -0
  17. package/assets/fonts/Geist/Geist-Regular.woff2 +0 -0
  18. package/assets/fonts/Geist/Geist-SemiBold.otf +0 -0
  19. package/assets/fonts/Geist/Geist-SemiBold.woff2 +0 -0
  20. package/assets/fonts/Geist/Geist-Thin.otf +0 -0
  21. package/assets/fonts/Geist/Geist-Thin.woff2 +0 -0
  22. package/assets/fonts/Geist/Geist-UltraBlack.otf +0 -0
  23. package/assets/fonts/Geist/Geist-UltraBlack.woff2 +0 -0
  24. package/assets/fonts/Geist/Geist-UltraLight.otf +0 -0
  25. package/assets/fonts/Geist/Geist-UltraLight.woff2 +0 -0
  26. package/assets/fonts/Geist/GeistVariableVF.ttf +0 -0
  27. package/assets/fonts/Geist/GeistVariableVF.woff2 +0 -0
  28. package/assets/fonts/Geist/LICENSE.TXT +92 -0
  29. package/assets/open-wc-logo.svg +29 -0
  30. package/index.html +362 -0
  31. package/package.json +117 -0
  32. package/rollup.config.js +71 -0
  33. package/src/components/atoms/button/button.atom.ts +39 -0
  34. package/src/components/atoms/button/button.stories.ts +186 -0
  35. package/src/components/atoms/button/button.style.ts +31 -0
  36. package/src/components/atoms/button/button.type.ts +10 -0
  37. package/src/components/atoms/checkbox/checkbox.atom.ts +62 -0
  38. package/src/components/atoms/checkbox/checkbox.stories.ts +42 -0
  39. package/src/components/atoms/command-empty/command-empty.atom.ts +44 -0
  40. package/src/components/atoms/command-group/command-group.atom.ts +60 -0
  41. package/src/components/atoms/command-item/command-item.atom.ts +74 -0
  42. package/src/components/atoms/command-list/command-list.atom.ts +37 -0
  43. package/src/components/atoms/command-separator/command-separator.atom.ts +42 -0
  44. package/src/components/atoms/dialog/dialog.atom.ts +301 -0
  45. package/src/components/atoms/dialog/dialog.stories.ts +86 -0
  46. package/src/components/atoms/index.ts +10 -0
  47. package/src/components/atoms/input/input.atom.ts +34 -0
  48. package/src/components/atoms/input/input.stories.ts +89 -0
  49. package/src/components/atoms/input/input.type.ts +24 -0
  50. package/src/components/atoms/label/label.atom.ts +40 -0
  51. package/src/components/atoms/label/label.stories.ts +18 -0
  52. package/src/components/atoms/label/label.style.ts +5 -0
  53. package/src/components/command/command.stories.ts +154 -0
  54. package/src/components/command/command.ts +391 -0
  55. package/src/components/index.ts +2 -0
  56. package/src/components/molecules/command/command.molecules.ts +31 -0
  57. package/src/components/molecules/command-input/command-input.atom.ts +130 -0
  58. package/src/components/molecules/index.ts +1 -0
  59. package/src/components/popover.ts +247 -0
  60. package/src/globals.css +1806 -0
  61. package/src/helpers/index.ts +2 -0
  62. package/src/helpers/mouse-conroller.helper.ts +42 -0
  63. package/src/helpers/style.helpers.ts +6 -0
  64. package/src/interfaces/actionable.interface.ts +6 -0
  65. package/src/interfaces/atomic.interface.ts +6 -0
  66. package/src/interfaces/changeable.interface.ts +14 -0
  67. package/src/interfaces/child-support-atomic.interface.ts +5 -0
  68. package/src/interfaces/index.ts +6 -0
  69. package/src/interfaces/intractable.interface.ts +6 -0
  70. package/src/interfaces/variant.interface.ts +3 -0
  71. package/src/lib/index.ts +0 -0
  72. package/src/lib/next/next.lib.ts +0 -0
  73. package/src/lib/react/react.lib.ts +0 -0
  74. package/src/styles/index.ts +1 -0
  75. package/src/styles/tw.styles.ts +1867 -0
  76. package/src/tailwind-lib.css +95 -0
  77. package/src/wc-ui-app.ts +81 -0
  78. package/tailwind.config.js +81 -0
  79. package/test/wc-ui-app.test.ts +22 -0
  80. package/tsconfig.json +25 -0
  81. package/web-dev-server.config.mjs +26 -0
  82. 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
+ };
@@ -0,0 +1,5 @@
1
+ import { cva } from 'class-variance-authority';
2
+
3
+ export const labelStyle = cva(
4
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
5
+ );