@iyulab/components 0.1.5 → 0.1.7
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/CHANGELOG.md +18 -18
- package/LICENSE +20 -20
- package/README.md +33 -33
- package/dist/assets/icons/arrow-clockwise.svg.js +1 -1
- package/dist/assets/icons/arrow-down.svg.js +1 -1
- package/dist/assets/icons/arrow-up.svg.js +1 -1
- package/dist/assets/icons/ban.svg.js +1 -1
- package/dist/assets/icons/bell-fill.svg.js +1 -1
- package/dist/assets/icons/check-circle-fill.svg.js +1 -1
- package/dist/assets/icons/check-lg.svg.js +1 -1
- package/dist/assets/icons/chevron-down.svg.js +1 -1
- package/dist/assets/icons/chevron-left.svg.js +1 -1
- package/dist/assets/icons/chevron-right.svg.js +1 -1
- package/dist/assets/icons/chevron-up.svg.js +1 -1
- package/dist/assets/icons/copy.svg.js +1 -1
- package/dist/assets/icons/dash-lg.svg.js +1 -1
- package/dist/assets/icons/exclamation-circle-fill.svg.js +1 -1
- package/dist/assets/icons/exclamation-triangle-fill.svg.js +1 -1
- package/dist/assets/icons/eye-slash.svg.js +1 -1
- package/dist/assets/icons/eye.svg.js +1 -1
- package/dist/assets/icons/info-circle-fill.svg.js +1 -1
- package/dist/assets/icons/layout-sidebar.svg.js +1 -1
- package/dist/assets/icons/lightbulb-fill.svg.js +1 -1
- package/dist/assets/icons/lightbulb-off.svg.js +1 -1
- package/dist/assets/icons/lightbulb.svg.js +1 -1
- package/dist/assets/icons/mic-fill.svg.js +1 -1
- package/dist/assets/icons/mic-mute-fill.svg.js +1 -1
- package/dist/assets/icons/paperclip.svg.js +1 -1
- package/dist/assets/icons/pencil-square.svg.js +1 -1
- package/dist/assets/icons/plus-lg.svg.js +1 -1
- package/dist/assets/icons/search.svg.js +1 -1
- package/dist/assets/icons/speedometer.svg.js +1 -1
- package/dist/assets/icons/x-lg.svg.js +1 -1
- package/dist/assets/styles/dark.css +129 -129
- package/dist/assets/styles/dark.css.js +1 -1
- package/dist/assets/styles/light.css +129 -129
- package/dist/assets/styles/light.css.js +1 -1
- package/dist/components/FloatingElement.d.ts +84 -0
- package/dist/components/FloatingElement.js +166 -0
- package/dist/components/FloatingElement.styles.d.ts +1 -0
- package/dist/components/FloatingElement.styles.js +26 -0
- package/dist/components/context-menu/ContextMenu.d.ts +20 -39
- package/dist/components/context-menu/ContextMenu.js +92 -137
- package/dist/components/context-menu/ContextMenu.styles.js +3 -28
- package/dist/components/context-menu/index.d.ts +1 -1
- package/dist/components/dialog/Dialog.d.ts +14 -7
- package/dist/components/dialog/Dialog.js +88 -27
- package/dist/components/dialog/Dialog.styles.js +60 -11
- package/dist/components/divider/Divider.d.ts +5 -5
- package/dist/components/divider/Divider.js +17 -17
- package/dist/components/divider/Divider.styles.js +4 -6
- package/dist/components/dropdown-menu/DropdownMenu.d.ts +27 -0
- package/dist/components/dropdown-menu/DropdownMenu.js +135 -0
- package/dist/components/dropdown-menu/DropdownMenu.styles.d.ts +1 -0
- package/dist/components/dropdown-menu/DropdownMenu.styles.js +15 -0
- package/dist/components/dropdown-menu/index.d.ts +7 -0
- package/dist/components/dropdown-menu/index.js +5 -0
- package/dist/components/icon/Icon.js +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/input/Input.js +1 -1
- package/dist/components/input/Input.styles.js +5 -5
- package/dist/components/menu/Menu.d.ts +4 -15
- package/dist/components/menu/Menu.js +43 -28
- package/dist/components/menu/Menu.styles.js +7 -19
- package/dist/components/menu-item/MenuItem.d.ts +21 -12
- package/dist/components/menu-item/MenuItem.js +184 -15
- package/dist/components/menu-item/MenuItem.styles.js +6 -0
- package/dist/components/menu-item/index.js +5 -0
- package/dist/components/split-panel/SplitPanel.d.ts +10 -2
- package/dist/components/split-panel/SplitPanel.js +41 -22
- package/dist/components/split-panel/SplitPanel.styles.js +1 -16
- package/dist/components/tooltip/Tooltip.d.ts +9 -29
- package/dist/components/tooltip/Tooltip.js +27 -149
- package/dist/components/tooltip/Tooltip.styles.js +8 -22
- package/dist/index.js +4 -0
- package/dist/integrations/react/UDropdownMenu.d.ts +8 -0
- package/dist/integrations/react/UDropdownMenu.js +10 -0
- package/dist/integrations/react/index.d.ts +1 -0
- package/dist/integrations/react/index.js +1 -0
- package/dist/internals/node-helpers.d.ts +6 -1
- package/dist/internals/node-helpers.js +5 -6
- package/package.json +59 -59
|
@@ -7,13 +7,15 @@ import { BaseElement } from '../BaseElement.js';
|
|
|
7
7
|
export declare class Dialog extends BaseElement {
|
|
8
8
|
static styles: import('lit').CSSResultGroup[];
|
|
9
9
|
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
-
|
|
10
|
+
dialogEl: HTMLDivElement;
|
|
11
|
+
/** 모달 모드 활성화 (배경 차단 및 포커스 트랩) */
|
|
12
|
+
modal: boolean;
|
|
11
13
|
/** 다이얼로그가 열려있는지 여부 */
|
|
12
14
|
open: boolean;
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
|
|
15
|
+
/** 이벤트에 의한 다이얼로그 닫기 허용 여부 */
|
|
16
|
+
closable: boolean;
|
|
17
|
+
/** 타이틀 텍스트 */
|
|
18
|
+
heading: string;
|
|
17
19
|
connectedCallback(): void;
|
|
18
20
|
disconnectedCallback(): void;
|
|
19
21
|
protected updated(changedProperties: PropertyValues): void;
|
|
@@ -22,9 +24,14 @@ export declare class Dialog extends BaseElement {
|
|
|
22
24
|
show: () => Promise<void>;
|
|
23
25
|
/** 다이얼로그를 숨깁니다 */
|
|
24
26
|
hide: () => Promise<void>;
|
|
27
|
+
/** 패널을 흔드는 애니메이션을 재생합니다 */
|
|
28
|
+
private shake;
|
|
25
29
|
/** 오버레이 클릭 핸들러 */
|
|
26
|
-
private
|
|
30
|
+
private handleBackdropClick;
|
|
27
31
|
/** 키보드 이벤트 핸들러 */
|
|
28
|
-
private
|
|
32
|
+
private handleKeydown;
|
|
33
|
+
/** 포커스 트랩 핸들러 */
|
|
34
|
+
private handleFocusin;
|
|
29
35
|
private updateOpenState;
|
|
36
|
+
private updateModalState;
|
|
30
37
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
1
|
+
import { nothing, html } from 'lit';
|
|
2
2
|
import { query, property } from 'lit/decorators.js';
|
|
3
3
|
import { BaseElement } from '../BaseElement.js';
|
|
4
|
+
import { IconButton } from '../icon-button/IconButton.js';
|
|
4
5
|
import { styles } from './Dialog.styles.js';
|
|
5
6
|
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
@@ -15,30 +16,52 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
15
16
|
class Dialog extends BaseElement {
|
|
16
17
|
constructor() {
|
|
17
18
|
super(...arguments);
|
|
19
|
+
this.modal = true;
|
|
18
20
|
this.open = false;
|
|
19
|
-
this.
|
|
20
|
-
this.
|
|
21
|
+
this.closable = true;
|
|
22
|
+
this.heading = "";
|
|
21
23
|
/** 다이얼로그를 표시합니다 */
|
|
22
24
|
this.show = async () => {
|
|
23
|
-
this.open = true;
|
|
24
25
|
await this.updateComplete;
|
|
26
|
+
requestAnimationFrame(() => {
|
|
27
|
+
this.open = true;
|
|
28
|
+
});
|
|
25
29
|
};
|
|
26
30
|
/** 다이얼로그를 숨깁니다 */
|
|
27
31
|
this.hide = async () => {
|
|
28
32
|
await this.updateComplete;
|
|
29
|
-
|
|
33
|
+
requestAnimationFrame(() => {
|
|
34
|
+
this.open = false;
|
|
35
|
+
});
|
|
30
36
|
};
|
|
31
37
|
/** 오버레이 클릭 핸들러 */
|
|
32
|
-
this.
|
|
33
|
-
if (
|
|
34
|
-
this.
|
|
38
|
+
this.handleBackdropClick = (e) => {
|
|
39
|
+
if (e.target === this) {
|
|
40
|
+
if (this.closable) {
|
|
41
|
+
this.hide();
|
|
42
|
+
} else {
|
|
43
|
+
this.shake();
|
|
44
|
+
}
|
|
35
45
|
}
|
|
36
46
|
};
|
|
37
47
|
/** 키보드 이벤트 핸들러 */
|
|
38
|
-
this.
|
|
39
|
-
if (
|
|
48
|
+
this.handleKeydown = (e) => {
|
|
49
|
+
if (e.key === "Escape" && this.open) {
|
|
40
50
|
e.preventDefault();
|
|
41
|
-
this.
|
|
51
|
+
if (this.closable) {
|
|
52
|
+
this.hide();
|
|
53
|
+
} else {
|
|
54
|
+
this.shake();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/** 포커스 트랩 핸들러 */
|
|
59
|
+
this.handleFocusin = (e) => {
|
|
60
|
+
if (!this.modal || !this.open) return;
|
|
61
|
+
const target = e.target;
|
|
62
|
+
if (!this.contains(target)) {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
this.dialogEl.focus();
|
|
42
65
|
}
|
|
43
66
|
};
|
|
44
67
|
}
|
|
@@ -46,14 +69,17 @@ class Dialog extends BaseElement {
|
|
|
46
69
|
this.styles = [super.styles, styles];
|
|
47
70
|
}
|
|
48
71
|
static {
|
|
49
|
-
this.dependencies = {
|
|
72
|
+
this.dependencies = {
|
|
73
|
+
"u-icon-button": IconButton
|
|
74
|
+
};
|
|
50
75
|
}
|
|
51
76
|
connectedCallback() {
|
|
52
77
|
super.connectedCallback();
|
|
53
|
-
|
|
78
|
+
this.addEventListener("click", this.handleBackdropClick);
|
|
54
79
|
}
|
|
55
80
|
disconnectedCallback() {
|
|
56
|
-
window.removeEventListener("keydown", this.
|
|
81
|
+
window.removeEventListener("keydown", this.handleKeydown);
|
|
82
|
+
window.removeEventListener("focusin", this.handleFocusin);
|
|
57
83
|
super.disconnectedCallback();
|
|
58
84
|
}
|
|
59
85
|
updated(changedProperties) {
|
|
@@ -61,39 +87,74 @@ class Dialog extends BaseElement {
|
|
|
61
87
|
if (changedProperties.has("open")) {
|
|
62
88
|
this.updateOpenState(this.open);
|
|
63
89
|
}
|
|
90
|
+
if (changedProperties.has("modal")) {
|
|
91
|
+
this.updateModalState(this.modal);
|
|
92
|
+
}
|
|
64
93
|
}
|
|
65
94
|
render() {
|
|
66
95
|
return html`
|
|
67
|
-
<div class="
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
96
|
+
<div class="dialog scrollable" part="base" tabindex="-1">
|
|
97
|
+
|
|
98
|
+
${this.heading ? html`
|
|
99
|
+
<div class="header" part="header">
|
|
100
|
+
<span class="title" part="title">
|
|
101
|
+
${this.heading}
|
|
102
|
+
</span>
|
|
103
|
+
<u-icon-button class="close-btn" part="close-btn"
|
|
104
|
+
lib="internal"
|
|
105
|
+
name="x-lg"
|
|
106
|
+
borderless
|
|
107
|
+
@click=${() => this.hide()}
|
|
108
|
+
></u-icon-button>
|
|
109
|
+
</div>` : nothing}
|
|
110
|
+
|
|
111
|
+
<slot></slot>
|
|
112
|
+
|
|
73
113
|
</div>
|
|
74
114
|
`;
|
|
75
115
|
}
|
|
116
|
+
/** 패널을 흔드는 애니메이션을 재생합니다 */
|
|
117
|
+
shake() {
|
|
118
|
+
this.dialogEl.classList.add("shake");
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
this.dialogEl.classList.remove("shake");
|
|
121
|
+
}, 500);
|
|
122
|
+
}
|
|
76
123
|
updateOpenState(open) {
|
|
77
124
|
if (open) {
|
|
78
|
-
document.body.style.overflow = "hidden";
|
|
79
125
|
this.emit("u-show");
|
|
126
|
+
document.body.style.overflow = this.modal ? "hidden" : "";
|
|
80
127
|
} else {
|
|
81
|
-
document.body.style.overflow = "";
|
|
82
128
|
this.emit("u-hide");
|
|
129
|
+
document.body.style.overflow = "";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
updateModalState(modal) {
|
|
133
|
+
if (modal) {
|
|
134
|
+
window.addEventListener("keydown", this.handleKeydown);
|
|
135
|
+
window.addEventListener("focusin", this.handleFocusin);
|
|
136
|
+
document.body.style.overflow = this.open ? "hidden" : "";
|
|
137
|
+
} else {
|
|
138
|
+
window.removeEventListener("keydown", this.handleKeydown);
|
|
139
|
+
window.removeEventListener("focusin", this.handleFocusin);
|
|
140
|
+
document.body.style.overflow = "";
|
|
83
141
|
}
|
|
84
142
|
}
|
|
85
143
|
}
|
|
86
144
|
__decorateClass([
|
|
87
|
-
query(".
|
|
88
|
-
], Dialog.prototype, "
|
|
145
|
+
query(".dialog")
|
|
146
|
+
], Dialog.prototype, "dialogEl");
|
|
147
|
+
__decorateClass([
|
|
148
|
+
property({ type: Boolean, reflect: true })
|
|
149
|
+
], Dialog.prototype, "modal");
|
|
89
150
|
__decorateClass([
|
|
90
151
|
property({ type: Boolean, reflect: true })
|
|
91
152
|
], Dialog.prototype, "open");
|
|
92
153
|
__decorateClass([
|
|
93
154
|
property({ type: Boolean })
|
|
94
|
-
], Dialog.prototype, "
|
|
155
|
+
], Dialog.prototype, "closable");
|
|
95
156
|
__decorateClass([
|
|
96
|
-
property({ type:
|
|
97
|
-
], Dialog.prototype, "
|
|
157
|
+
property({ type: String })
|
|
158
|
+
], Dialog.prototype, "heading");
|
|
98
159
|
|
|
99
160
|
export { Dialog };
|
|
@@ -2,30 +2,79 @@ import { css } from 'lit';
|
|
|
2
2
|
|
|
3
3
|
const styles = css`
|
|
4
4
|
:host {
|
|
5
|
-
display: inline-block;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.overlay {
|
|
9
5
|
position: fixed;
|
|
10
6
|
z-index: 9999;
|
|
11
7
|
top: 0;
|
|
8
|
+
bottom: 0;
|
|
12
9
|
left: 0;
|
|
13
|
-
|
|
14
|
-
height: 100vh;
|
|
10
|
+
right: 0;
|
|
15
11
|
display: flex;
|
|
16
12
|
align-items: center;
|
|
17
13
|
justify-content: center;
|
|
14
|
+
background: transparent;
|
|
15
|
+
visibility: hidden;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
}
|
|
18
|
+
:host([open]) {
|
|
19
|
+
visibility: visible;
|
|
20
|
+
pointer-events: auto;
|
|
21
|
+
}
|
|
22
|
+
:host([modal]) {
|
|
18
23
|
background: var(--u-overlay-bg-color);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
.
|
|
26
|
+
.dialog {
|
|
27
|
+
position: relative;
|
|
22
28
|
display: block;
|
|
23
|
-
background: var(--u-panel-bg-color);
|
|
24
|
-
border: 1px solid var(--u-border-color);
|
|
25
|
-
border-radius: 6px;
|
|
26
29
|
max-width: 90vw;
|
|
27
30
|
max-height: 90vh;
|
|
28
|
-
|
|
31
|
+
padding: 20px;
|
|
32
|
+
border: 1px solid var(--u-border-color);
|
|
33
|
+
border-radius: 6px;
|
|
34
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
35
|
+
background: var(--u-panel-bg-color);
|
|
36
|
+
overflow: auto;
|
|
37
|
+
}
|
|
38
|
+
.dialog.shake {
|
|
39
|
+
animation: shake 0.5s cubic-bezier(0.36, 0.07, 0.19, 0.97);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.header {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: row;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: space-between;
|
|
47
|
+
font-size: 20px;
|
|
48
|
+
margin-bottom: 20px;
|
|
49
|
+
}
|
|
50
|
+
.header .title {
|
|
51
|
+
line-height: 1.2;
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* 페이드 인 및 스케일 업 애니메이션 */
|
|
56
|
+
@keyframes fadeout {
|
|
57
|
+
0% {
|
|
58
|
+
opacity: 0;
|
|
59
|
+
transform: scale(0.9);
|
|
60
|
+
}
|
|
61
|
+
100% {
|
|
62
|
+
opacity: 1;
|
|
63
|
+
transform: scale(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* 진동 애니메이션 */
|
|
68
|
+
@keyframes shake {
|
|
69
|
+
0%, 100% {
|
|
70
|
+
transform: translateX(0);
|
|
71
|
+
}
|
|
72
|
+
10%, 30%, 50%, 70%, 90% {
|
|
73
|
+
transform: translateX(-8px);
|
|
74
|
+
}
|
|
75
|
+
20%, 40%, 60%, 80% {
|
|
76
|
+
transform: translateX(8px);
|
|
77
|
+
}
|
|
29
78
|
}
|
|
30
79
|
`;
|
|
31
80
|
|
|
@@ -6,8 +6,8 @@ import { BaseElement } from '../BaseElement.js';
|
|
|
6
6
|
export declare class Divider extends BaseElement {
|
|
7
7
|
static styles: import('lit').CSSResultGroup[];
|
|
8
8
|
static dependencies: Record<string, typeof BaseElement>;
|
|
9
|
-
/** 마지막 마우스 위치를 저장합니다. */
|
|
10
|
-
private
|
|
9
|
+
/** 마지막 마우스 포인터 위치를 저장합니다. */
|
|
10
|
+
private prevPointerPosition;
|
|
11
11
|
/** 분할선이 움직이는지 여부를 나타냅니다. */
|
|
12
12
|
moving: boolean;
|
|
13
13
|
/** 분할 방향을 설정합니다. */
|
|
@@ -17,9 +17,9 @@ export declare class Divider extends BaseElement {
|
|
|
17
17
|
disconnectedCallback(): void;
|
|
18
18
|
render(): typeof nothing | import('lit-html').TemplateResult<1>;
|
|
19
19
|
/** 마우스 다운 이벤트 핸들러 */
|
|
20
|
-
private
|
|
20
|
+
private handleMousedown;
|
|
21
21
|
/** 마우스 무브 이벤트 핸들러 */
|
|
22
|
-
private
|
|
22
|
+
private handleMousemove;
|
|
23
23
|
/** 마우스 업 이벤트 핸들러 */
|
|
24
|
-
private
|
|
24
|
+
private handleMouseup;
|
|
25
25
|
}
|
|
@@ -15,38 +15,38 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
15
15
|
class Divider extends BaseElement {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(...arguments);
|
|
18
|
-
/** 마지막 마우스 위치를 저장합니다. */
|
|
19
|
-
this.
|
|
18
|
+
/** 마지막 마우스 포인터 위치를 저장합니다. */
|
|
19
|
+
this.prevPointerPosition = 0;
|
|
20
20
|
this.moving = false;
|
|
21
21
|
this.orientation = "horizontal";
|
|
22
22
|
this.movable = false;
|
|
23
23
|
/** 마우스 다운 이벤트 핸들러 */
|
|
24
|
-
this.
|
|
24
|
+
this.handleMousedown = (e) => {
|
|
25
25
|
e.preventDefault();
|
|
26
26
|
this.moving = true;
|
|
27
|
-
this.
|
|
27
|
+
this.prevPointerPosition = this.orientation === "horizontal" ? e.clientX : e.clientY;
|
|
28
28
|
this.emit("u-movestart");
|
|
29
|
-
document.addEventListener("mousemove", this.
|
|
30
|
-
document.addEventListener("mouseup", this.
|
|
29
|
+
document.addEventListener("mousemove", this.handleMousemove);
|
|
30
|
+
document.addEventListener("mouseup", this.handleMouseup);
|
|
31
31
|
document.body.style.userSelect = "none";
|
|
32
32
|
document.body.style.cursor = this.orientation === "horizontal" ? "col-resize" : "row-resize";
|
|
33
33
|
};
|
|
34
34
|
/** 마우스 무브 이벤트 핸들러 */
|
|
35
|
-
this.
|
|
35
|
+
this.handleMousemove = (e) => {
|
|
36
36
|
if (!this.moving) return;
|
|
37
37
|
e.preventDefault();
|
|
38
|
-
const
|
|
39
|
-
const delta =
|
|
38
|
+
const currentPointerPosition = this.orientation === "horizontal" ? e.clientX : e.clientY;
|
|
39
|
+
const delta = currentPointerPosition - this.prevPointerPosition;
|
|
40
40
|
this.emit("u-move", { delta });
|
|
41
|
-
this.
|
|
41
|
+
this.prevPointerPosition = currentPointerPosition;
|
|
42
42
|
};
|
|
43
43
|
/** 마우스 업 이벤트 핸들러 */
|
|
44
|
-
this.
|
|
44
|
+
this.handleMouseup = (_) => {
|
|
45
45
|
if (!this.moving) return;
|
|
46
46
|
this.moving = false;
|
|
47
47
|
this.emit("u-moveend");
|
|
48
|
-
document.removeEventListener("mousemove", this.
|
|
49
|
-
document.removeEventListener("mouseup", this.
|
|
48
|
+
document.removeEventListener("mousemove", this.handleMousemove);
|
|
49
|
+
document.removeEventListener("mouseup", this.handleMouseup);
|
|
50
50
|
document.body.style.userSelect = "";
|
|
51
51
|
document.body.style.cursor = "";
|
|
52
52
|
};
|
|
@@ -59,16 +59,16 @@ class Divider extends BaseElement {
|
|
|
59
59
|
}
|
|
60
60
|
disconnectedCallback() {
|
|
61
61
|
super.disconnectedCallback();
|
|
62
|
-
document.removeEventListener("mousemove", this.
|
|
63
|
-
document.removeEventListener("mouseup", this.
|
|
62
|
+
document.removeEventListener("mousemove", this.handleMousemove);
|
|
63
|
+
document.removeEventListener("mouseup", this.handleMouseup);
|
|
64
64
|
}
|
|
65
65
|
render() {
|
|
66
66
|
if (this.movable) {
|
|
67
67
|
return html`
|
|
68
|
-
<div class="handler"
|
|
68
|
+
<div class="handler" part="handler"
|
|
69
69
|
?moving=${this.moving}
|
|
70
70
|
orientation=${this.orientation}
|
|
71
|
-
@mousedown=${this.
|
|
71
|
+
@mousedown=${this.handleMousedown}
|
|
72
72
|
></div>
|
|
73
73
|
`;
|
|
74
74
|
} else {
|
|
@@ -9,19 +9,15 @@ const styles = css`
|
|
|
9
9
|
|
|
10
10
|
:host {
|
|
11
11
|
position: relative;
|
|
12
|
-
display: block;
|
|
13
|
-
flex-shrink: 0;
|
|
14
12
|
background-color: var(--u-neutral-200, #e5e7eb);
|
|
15
13
|
}
|
|
16
14
|
:host([orientation="horizontal"]) {
|
|
17
15
|
width: var(--divider-size, 2px);
|
|
18
|
-
height:
|
|
19
|
-
cursor: col-resize;
|
|
16
|
+
min-height: 0px;
|
|
20
17
|
}
|
|
21
18
|
:host([orientation="vertical"]) {
|
|
22
|
-
width:
|
|
19
|
+
min-width: 0px;
|
|
23
20
|
height: var(--divider-size, 2px);
|
|
24
|
-
cursor: row-resize;
|
|
25
21
|
}
|
|
26
22
|
|
|
27
23
|
.handler {
|
|
@@ -39,6 +35,7 @@ const styles = css`
|
|
|
39
35
|
transform: translateX(-50%);
|
|
40
36
|
width: var(--handler-size, 4px);
|
|
41
37
|
height: 100%;
|
|
38
|
+
cursor: col-resize;
|
|
42
39
|
}
|
|
43
40
|
.handler[orientation="vertical"] {
|
|
44
41
|
left: 0;
|
|
@@ -47,6 +44,7 @@ const styles = css`
|
|
|
47
44
|
transform: translateY(-50%);
|
|
48
45
|
width: 100%;
|
|
49
46
|
height: var(--handler-size, 4px);
|
|
47
|
+
cursor: row-resize;
|
|
50
48
|
}
|
|
51
49
|
.handler[moving],
|
|
52
50
|
.handler:hover {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PropertyValues } from 'lit';
|
|
2
|
+
import { BaseElement } from '../BaseElement.js';
|
|
3
|
+
import { FloatingElement } from '../FloatingElement.js';
|
|
4
|
+
export declare class DropdownMenu extends FloatingElement {
|
|
5
|
+
static styles: import('lit').CSSResultGroup[];
|
|
6
|
+
static dependencies: Record<string, typeof BaseElement>;
|
|
7
|
+
closeOnSelect: boolean;
|
|
8
|
+
closeOnCheck: boolean;
|
|
9
|
+
private onDocPointerDown;
|
|
10
|
+
private onWindowBlur;
|
|
11
|
+
private get menu();
|
|
12
|
+
connectedCallback(): void;
|
|
13
|
+
disconnectedCallback(): void;
|
|
14
|
+
protected updated(changed: PropertyValues): void;
|
|
15
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
16
|
+
show: () => Promise<void>;
|
|
17
|
+
hide: () => Promise<void>;
|
|
18
|
+
private attachAnchor;
|
|
19
|
+
private detachAnchor;
|
|
20
|
+
private onTriggerPointerDown;
|
|
21
|
+
private onTriggerKeydown;
|
|
22
|
+
private onSelect;
|
|
23
|
+
private onCheck;
|
|
24
|
+
private onRequestClose;
|
|
25
|
+
private attachDismiss;
|
|
26
|
+
private detachDismiss;
|
|
27
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import { FloatingElement } from '../FloatingElement.js';
|
|
4
|
+
import { Menu } from '../menu/Menu.js';
|
|
5
|
+
import { MenuItem } from '../menu-item/MenuItem.js';
|
|
6
|
+
import { styles } from './DropdownMenu.styles.js';
|
|
7
|
+
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
10
|
+
var result = void 0 ;
|
|
11
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
12
|
+
if (decorator = decorators[i])
|
|
13
|
+
result = (decorator(target, key, result) ) || result;
|
|
14
|
+
if (result) __defProp(target, key, result);
|
|
15
|
+
return result;
|
|
16
|
+
};
|
|
17
|
+
class DropdownMenu extends FloatingElement {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(...arguments);
|
|
20
|
+
this.closeOnSelect = true;
|
|
21
|
+
this.closeOnCheck = false;
|
|
22
|
+
this.onDocPointerDown = (e) => {
|
|
23
|
+
if (!this.visible) return;
|
|
24
|
+
const path = e.composedPath();
|
|
25
|
+
if (path.includes(this)) return;
|
|
26
|
+
if (this.anchor && path.includes(this.anchor)) return;
|
|
27
|
+
this.hide();
|
|
28
|
+
};
|
|
29
|
+
this.onWindowBlur = () => {
|
|
30
|
+
if (this.visible) this.hide();
|
|
31
|
+
};
|
|
32
|
+
this.show = async () => {
|
|
33
|
+
this.menu && (this.menu.open = true);
|
|
34
|
+
await super.show();
|
|
35
|
+
await this.menu?.focusFirstItem?.();
|
|
36
|
+
};
|
|
37
|
+
this.hide = async () => {
|
|
38
|
+
await super.hide();
|
|
39
|
+
this.menu && (this.menu.open = false);
|
|
40
|
+
this.querySelectorAll("u-menu-item").forEach((i) => i.closeSubmenu?.());
|
|
41
|
+
};
|
|
42
|
+
this.onTriggerPointerDown = async (e) => {
|
|
43
|
+
if (e.button !== 0) return;
|
|
44
|
+
if (this.visible) await this.hide();
|
|
45
|
+
else await this.show();
|
|
46
|
+
};
|
|
47
|
+
this.onTriggerKeydown = async (e) => {
|
|
48
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
if (!this.visible) await this.show();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
this.onSelect = async () => {
|
|
54
|
+
if (this.closeOnSelect) await this.hide();
|
|
55
|
+
};
|
|
56
|
+
this.onCheck = async () => {
|
|
57
|
+
if (this.closeOnCheck) await this.hide();
|
|
58
|
+
};
|
|
59
|
+
this.onRequestClose = async () => {
|
|
60
|
+
await this.hide();
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
static {
|
|
64
|
+
this.styles = [super.styles, styles];
|
|
65
|
+
}
|
|
66
|
+
static {
|
|
67
|
+
this.dependencies = {
|
|
68
|
+
"u-menu": Menu,
|
|
69
|
+
"u-menu-item": MenuItem
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
get menu() {
|
|
73
|
+
return this.querySelector("u-menu");
|
|
74
|
+
}
|
|
75
|
+
connectedCallback() {
|
|
76
|
+
super.connectedCallback();
|
|
77
|
+
this.placement ||= "bottom-start";
|
|
78
|
+
this.distance ||= 6;
|
|
79
|
+
this.addEventListener("u-select", this.onSelect);
|
|
80
|
+
this.addEventListener("u-check", this.onCheck);
|
|
81
|
+
this.addEventListener("u-request-close", this.onRequestClose);
|
|
82
|
+
}
|
|
83
|
+
disconnectedCallback() {
|
|
84
|
+
this.detachAnchor(this.anchor);
|
|
85
|
+
this.detachDismiss();
|
|
86
|
+
this.removeEventListener("u-select", this.onSelect);
|
|
87
|
+
this.removeEventListener("u-check", this.onCheck);
|
|
88
|
+
this.removeEventListener("u-request-close", this.onRequestClose);
|
|
89
|
+
super.disconnectedCallback();
|
|
90
|
+
}
|
|
91
|
+
updated(changed) {
|
|
92
|
+
super.updated(changed);
|
|
93
|
+
if (changed.has("anchor")) {
|
|
94
|
+
this.detachAnchor(changed.get("anchor"));
|
|
95
|
+
this.attachAnchor(this.anchor);
|
|
96
|
+
}
|
|
97
|
+
if (changed.has("visible")) {
|
|
98
|
+
if (this.visible) this.attachDismiss();
|
|
99
|
+
else this.detachDismiss();
|
|
100
|
+
if (this.anchor) {
|
|
101
|
+
this.anchor.setAttribute("aria-expanded", this.visible ? "true" : "false");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
render() {
|
|
106
|
+
return html`<slot></slot>`;
|
|
107
|
+
}
|
|
108
|
+
attachAnchor(target) {
|
|
109
|
+
if (!target) return;
|
|
110
|
+
target.setAttribute("aria-haspopup", "menu");
|
|
111
|
+
target.addEventListener("pointerdown", this.onTriggerPointerDown);
|
|
112
|
+
target.addEventListener("keydown", this.onTriggerKeydown);
|
|
113
|
+
}
|
|
114
|
+
detachAnchor(target) {
|
|
115
|
+
if (!target) return;
|
|
116
|
+
target.removeEventListener("pointerdown", this.onTriggerPointerDown);
|
|
117
|
+
target.removeEventListener("keydown", this.onTriggerKeydown);
|
|
118
|
+
}
|
|
119
|
+
attachDismiss() {
|
|
120
|
+
document.addEventListener("pointerdown", this.onDocPointerDown, true);
|
|
121
|
+
window.addEventListener("blur", this.onWindowBlur);
|
|
122
|
+
}
|
|
123
|
+
detachDismiss() {
|
|
124
|
+
document.removeEventListener("pointerdown", this.onDocPointerDown, true);
|
|
125
|
+
window.removeEventListener("blur", this.onWindowBlur);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
__decorateClass([
|
|
129
|
+
property({ type: Boolean })
|
|
130
|
+
], DropdownMenu.prototype, "closeOnSelect");
|
|
131
|
+
__decorateClass([
|
|
132
|
+
property({ type: Boolean })
|
|
133
|
+
], DropdownMenu.prototype, "closeOnCheck");
|
|
134
|
+
|
|
135
|
+
export { DropdownMenu };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import('lit').CSSResult;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
const styles = css`
|
|
4
|
+
:host {
|
|
5
|
+
opacity: 0;
|
|
6
|
+
transform: scale(0.98);
|
|
7
|
+
transition: opacity 0.12s ease, transform 0.12s ease;
|
|
8
|
+
}
|
|
9
|
+
:host([visible]) {
|
|
10
|
+
opacity: 1; /* FloatingElement의 0.8을 덮어씀 */
|
|
11
|
+
transform: scale(1);
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
export { styles };
|
|
@@ -28,6 +28,7 @@ class Icon extends BaseElement {
|
|
|
28
28
|
}
|
|
29
29
|
render() {
|
|
30
30
|
if (!this.name) return nothing;
|
|
31
|
+
console.log(this.library, this.name, "icon render");
|
|
31
32
|
return until(icons.resolve(this.library, this.name).then((html) => {
|
|
32
33
|
return this.validate(html) ? unsafeHTML(html) : nothing;
|
|
33
34
|
}), nothing);
|
|
@@ -4,11 +4,13 @@ export * from './context-menu';
|
|
|
4
4
|
export * from './copy-button';
|
|
5
5
|
export * from './dialog';
|
|
6
6
|
export * from './divider';
|
|
7
|
+
export * from './dropdown-menu';
|
|
7
8
|
export * from './form';
|
|
8
9
|
export * from './icon';
|
|
9
10
|
export * from './icon-button';
|
|
10
11
|
export * from './input';
|
|
11
12
|
export * from './menu';
|
|
13
|
+
export * from './menu-item';
|
|
12
14
|
export * from './progress-bar';
|
|
13
15
|
export * from './progress-ring';
|
|
14
16
|
export * from './spinner';
|