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,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
|
+
}
|