revotech-ui-kit 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,130 @@
1
+ import { LitElement, html, css, nothing } from 'lit';
2
+ import { property, customElement } from 'lit/decorators.js';
3
+ import { cn } from '@/helpers';
4
+ import { TWStyles } from '@/styles';
5
+ import { CommandItem, CommandSeparator } from '@/components';
6
+
7
+ @customElement('rtg-command-input')
8
+ export class CommandInput extends LitElement {
9
+ @property({ type: String }) placeholder = 'Type a command or search...';
10
+
11
+ @property({ attribute: 'value', type: String }) _value = '';
12
+
13
+ static styles = [css``, TWStyles];
14
+
15
+ private get identifier() {
16
+ const parent =
17
+ this.parentElement?.shadowRoot?.querySelector('div[rtgcmd-root]');
18
+ if (parent) {
19
+ return `${parent.getAttribute('id')}i`;
20
+ }
21
+ return `rtgcmdrxi`;
22
+ }
23
+
24
+ private filterItems() {
25
+ const parent = this.parentElement;
26
+ if (parent) {
27
+ let isEmpty = true;
28
+ const groups = parent.querySelectorAll(
29
+ 'rtg-command-list > rtg-command-group'
30
+ );
31
+ if (groups) {
32
+ groups.forEach(group => {
33
+ let hidden = true;
34
+ const items = group.querySelectorAll('rtg-command-item');
35
+ if (items) {
36
+ items.forEach(item => {
37
+ const value = (item as CommandItem)?.value || '';
38
+ if (value.toLowerCase().includes(this._value.toLowerCase())) {
39
+ hidden = false;
40
+ isEmpty = false;
41
+ item.setAttribute('aria-hidden', 'false');
42
+ } else {
43
+ item.setAttribute('aria-hidden', 'true');
44
+ }
45
+ });
46
+ }
47
+ group.setAttribute('aria-hidden', hidden ? 'true' : 'false');
48
+ let separator = group.previousElementSibling as CommandSeparator;
49
+ if (separator) {
50
+ separator.setAttribute(
51
+ 'aria-hidden',
52
+ hidden ||
53
+ separator.previousElementSibling?.getAttribute(
54
+ 'aria-hidden'
55
+ ) === 'true'
56
+ ? 'true'
57
+ : 'false'
58
+ );
59
+ }
60
+ separator = group.nextElementSibling as CommandSeparator;
61
+ if (separator) {
62
+ separator.setAttribute(
63
+ 'aria-hidden',
64
+ hidden ||
65
+ separator.nextElementSibling?.getAttribute('aria-hidden') ===
66
+ 'true'
67
+ ? 'true'
68
+ : 'false'
69
+ );
70
+ }
71
+ });
72
+ }
73
+
74
+ const empty = parent.querySelector('rtg-command-empty');
75
+ if (empty) {
76
+ empty.setAttribute('aria-hidden', isEmpty ? 'false' : 'true');
77
+ }
78
+ }
79
+ }
80
+
81
+ private handleChange(e: Event) {
82
+ const input = e.target as HTMLInputElement;
83
+ if (input) {
84
+ this._value = input.value;
85
+ this.filterItems();
86
+ }
87
+ }
88
+
89
+ render() {
90
+ return html`
91
+ <div
92
+ class="${cn('flex items-center border-b px-3', this.className)}"
93
+ name="rtgcmd-input-container"
94
+ >
95
+ <svg
96
+ xmlns="http://www.w3.org/2000/svg"
97
+ width="24"
98
+ height="24"
99
+ viewBox="0 0 24 24"
100
+ fill="none"
101
+ stroke="currentColor"
102
+ stroke-width="2"
103
+ stroke-linecap="round"
104
+ stroke-linejoin="round"
105
+ class="mr-2 h-4 w-4 shrink-0 opacity-50"
106
+ >
107
+ <circle cx="11" cy="11" r="8"></circle>
108
+ <path d="m21 21-4.3-4.3"></path>
109
+ </svg>
110
+ <input
111
+ class="flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
112
+ placeholder="${this.placeholder}"
113
+ rtgcmd-input
114
+ @input="${this.handleChange}"
115
+ autocomplete="off"
116
+ autocorrect="off"
117
+ spellcheck="false"
118
+ aria-autocomplete="list"
119
+ role="combobox"
120
+ aria-expanded="true"
121
+ aria-controls=":r1oe:"
122
+ aria-labelledby=":r1of:"
123
+ id="${this.identifier}"
124
+ type="text"
125
+ data-value="${this._value}"
126
+ />
127
+ </div>
128
+ `;
129
+ }
130
+ }
@@ -0,0 +1 @@
1
+ export * from './command/command.molecules';
@@ -0,0 +1,247 @@
1
+ /* eslint-disable no-use-before-define */
2
+ import {
3
+ LitElement,
4
+ html,
5
+ css,
6
+ nothing,
7
+ PropertyValues,
8
+ PropertyValueMap,
9
+ ReactiveControllerHost,
10
+ } from 'lit';
11
+ import { customElement, property } from 'lit/decorators.js';
12
+ import { cn } from '@/helpers';
13
+ import { TWStyles } from '@/styles';
14
+
15
+ const STATE_OPEN = 'open';
16
+ const STATE_CLOSED = 'closed';
17
+
18
+ class PopoverController {
19
+ private host: ReactiveControllerHost;
20
+
21
+ pos = { x: 0, y: 0 };
22
+
23
+ _onMouseMove = ({ clientX, clientY }: MouseEvent) => {
24
+ this.pos = { x: clientX, y: clientY };
25
+ this.host.requestUpdate();
26
+ };
27
+
28
+ _onClick = (e: MouseEvent) => {
29
+ console.log(`click: ${e.target}`);
30
+ console.log(`pos: ${this.pos.x}`);
31
+ if (e.y < 100) {
32
+ const popover = (this.host as PopoverContent)?._popover;
33
+ if (popover && popover.state === STATE_OPEN) {
34
+ popover.state = STATE_CLOSED;
35
+ }
36
+ }
37
+ // this.host.requestUpdate();
38
+ };
39
+
40
+ _onScroll = (e: Event) => {
41
+ console.log(`scroll: ${e.target}`);
42
+ console.log(`pos: ${this.pos.y}`);
43
+ console.log(`pos: ${window.scrollY} ${window.innerHeight}`);
44
+ this.host.requestUpdate();
45
+ };
46
+
47
+ _onResize = (e: UIEvent) => {
48
+ console.log(`resize: ${e.target}`);
49
+ console.log(`pos: ${window.innerWidth} ${window.innerHeight}`);
50
+ this.host.requestUpdate();
51
+ };
52
+
53
+ constructor(host: ReactiveControllerHost) {
54
+ this.host = host;
55
+ host.addController(this);
56
+ }
57
+
58
+ hostConnected() {
59
+ window.addEventListener('mousemove', this._onMouseMove);
60
+ window.addEventListener('click', this._onClick);
61
+ window.addEventListener('scroll', this._onScroll);
62
+ window.addEventListener('resize', this._onResize);
63
+ }
64
+
65
+ hostDisconnected() {
66
+ window.removeEventListener('mousemove', this._onMouseMove);
67
+ window.removeEventListener('click', this._onClick);
68
+ window.removeEventListener('scroll', this._onScroll);
69
+ window.removeEventListener('resize', this._onResize);
70
+ }
71
+ }
72
+
73
+ @customElement('rtg-popover')
74
+ export class Popover extends LitElement {
75
+ static styles = [css``, TWStyles];
76
+
77
+ @property({ attribute: 'data-state', type: String }) state = STATE_CLOSED;
78
+
79
+ @property({ type: String }) align = 'center';
80
+
81
+ @property({ type: Number }) sideOffset = 0;
82
+
83
+ get _content(): PopoverContent | null {
84
+ const slot = this.shadowRoot?.querySelector('slot');
85
+ const children = slot?.assignedElements();
86
+ if (children) {
87
+ for (let index = 0; index < children.length; index++) {
88
+ if (children[index] instanceof PopoverContent) {
89
+ return children[index] as PopoverContent;
90
+ }
91
+ }
92
+ }
93
+
94
+ return null;
95
+ }
96
+
97
+ get _trigger(): PopoverTrigger | null {
98
+ const slot = this.shadowRoot?.querySelector('slot');
99
+ const children = slot?.assignedElements();
100
+ if (children) {
101
+ for (let index = 0; index < children.length; index++) {
102
+ if (children[index] instanceof PopoverTrigger) {
103
+ return children[index] as PopoverTrigger;
104
+ }
105
+ }
106
+ }
107
+
108
+ return null;
109
+ }
110
+
111
+ protected updated(_changedProperties: PropertyValues): void {
112
+ super.updated(_changedProperties);
113
+ const content = this._content;
114
+ if (content) {
115
+ content.dataset.state = this.state;
116
+ }
117
+ }
118
+
119
+ render() {
120
+ return html`
121
+ <div rtgpop-root>
122
+ <slot></slot>
123
+ </div>
124
+ `;
125
+ }
126
+ }
127
+
128
+ @customElement('rtg-popover-content')
129
+ export class PopoverContent extends LitElement {
130
+ static styles = [css``, TWStyles];
131
+
132
+ @property({ attribute: 'data-state', type: String }) state = STATE_CLOSED;
133
+
134
+ @property({ attribute: 'data-side', type: String }) side = 'bottom';
135
+
136
+ private controller = new PopoverController(this);
137
+
138
+ public get _popover(): Popover | null {
139
+ let parent = this.parentElement;
140
+
141
+ while (parent) {
142
+ if (parent instanceof Popover) {
143
+ return parent;
144
+ }
145
+ parent = parent.parentElement;
146
+ }
147
+ return parent;
148
+ }
149
+
150
+ public get _box(): DOMRect {
151
+ return this.firstElementChild!.getBoundingClientRect();
152
+ }
153
+
154
+ public get _triggerBox(): DOMRect {
155
+ return this._popover!._trigger!.getBoundingClientRect();
156
+ }
157
+
158
+ private handleCloseButtonClick = () => {
159
+ const popover = this._popover;
160
+ if (popover) {
161
+ popover.dataset.state = STATE_CLOSED;
162
+ }
163
+ };
164
+
165
+ render() {
166
+ let top = 0;
167
+ const box = this._box;
168
+ const triggerBox = this._triggerBox;
169
+ if (this.side === 'bottom') {
170
+ top = triggerBox.top + triggerBox.height;
171
+ if (top + box.height > window.innerHeight) {
172
+ top = triggerBox.top - box.height;
173
+ }
174
+ }
175
+
176
+ if (this.side === 'top') {
177
+ top = triggerBox.top - box.height;
178
+ if (top < 0) {
179
+ top = triggerBox.top + triggerBox.height;
180
+ }
181
+ }
182
+
183
+ return html`${this.state === STATE_OPEN
184
+ ? html`
185
+ <div
186
+ style="position: fixed; left: 0px; top: 0px; transform: translate(638px, ${top}px); min-width: max-content; --radix-popper-transform-origin: 50% 0px; z-index: 50; --radix-popper-available-width: ${window.innerWidth}px; --radix-popper-available-height: ${window.innerHeight}px; --radix-popper-anchor-width: 127.046875px; --radix-popper-anchor-height: 36px;"
187
+ >
188
+ <div
189
+ class="${cn(
190
+ 'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
191
+ this.className
192
+ )}"
193
+ rtgpop-content
194
+ >
195
+ <slot></slot>
196
+ </div>
197
+ </div>
198
+ `
199
+ : nothing}`;
200
+ }
201
+ }
202
+
203
+ @customElement('rtg-popover-trigger')
204
+ export class PopoverTrigger extends LitElement {
205
+ static styles = [css``, TWStyles];
206
+
207
+ private get _popover(): Popover | null {
208
+ let parent = this.parentElement;
209
+
210
+ while (parent) {
211
+ if (parent instanceof Popover) {
212
+ return parent;
213
+ }
214
+ parent = parent.parentElement;
215
+ }
216
+ return parent;
217
+ }
218
+
219
+ protected firstUpdated(
220
+ _changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
221
+ ): void {
222
+ super.firstUpdated(_changedProperties);
223
+ const slot = this.shadowRoot?.querySelector('slot');
224
+ const children = slot?.assignedElements();
225
+ if (children && children.length > 0) {
226
+ const button = children[0];
227
+
228
+ button.addEventListener('click', () => {
229
+ const popover = this._popover;
230
+ if (popover) {
231
+ popover._content!.dataset.side = 'top';
232
+ popover.dataset.state = STATE_OPEN;
233
+ popover.dataset.state = STATE_CLOSED;
234
+ popover.dataset.state = STATE_OPEN;
235
+ }
236
+ });
237
+ }
238
+ }
239
+
240
+ render() {
241
+ return html`
242
+ <div>
243
+ <slot></slot>
244
+ </div>
245
+ `;
246
+ }
247
+ }