@iyulab/components 0.1.3 → 0.1.4
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 -15
- 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/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/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 +125 -125
- package/dist/assets/styles/dark.css.js +1 -1
- package/dist/assets/styles/light.css +126 -126
- package/dist/assets/styles/light.css.js +1 -1
- package/dist/components/BaseElement.styles.js +0 -1
- package/dist/components/divider/Divider.d.ts +25 -0
- package/dist/components/divider/Divider.js +89 -0
- package/dist/components/{split-panel/Splitter.styles.js → divider/Divider.styles.js} +20 -10
- package/dist/components/divider/index.d.ts +7 -0
- package/dist/components/icon/Icon.d.ts +3 -7
- package/dist/components/icon/Icon.js +8 -15
- package/dist/components/index.d.ts +1 -0
- package/dist/components/panel/Panel.d.ts +0 -1
- package/dist/components/panel/Panel.js +0 -4
- package/dist/components/progress-bar/ProgressBar.d.ts +1 -1
- package/dist/components/progress-ring/ProgressRing.js +3 -1
- package/dist/components/split-panel/SplitPanel.d.ts +8 -12
- package/dist/components/split-panel/SplitPanel.js +63 -88
- package/dist/components/split-panel/SplitPanel.styles.js +16 -1
- package/dist/components/tooltip/Tooltip.d.ts +8 -12
- package/dist/components/tooltip/Tooltip.js +39 -38
- package/dist/components/tooltip/Tooltip.styles.js +4 -4
- package/dist/components/tree/Tree.d.ts +2 -14
- package/dist/components/tree/Tree.js +9 -49
- package/dist/components/tree/Tree.styles.js +5 -5
- package/dist/components/tree-item/TreeItem.d.ts +10 -29
- package/dist/components/tree-item/TreeItem.js +63 -95
- package/dist/components/tree-item/TreeItem.styles.js +10 -41
- package/dist/index.js +1 -0
- package/dist/integrations/react/UDivider.d.ts +8 -0
- package/dist/integrations/react/UDivider.js +10 -0
- package/dist/integrations/react/index.d.ts +1 -0
- package/dist/integrations/react/index.js +1 -0
- package/dist/internals/icon-helpers.d.ts +32 -0
- package/dist/internals/{icons.js → icon-helpers.js} +10 -4
- package/dist/internals/index.d.ts +1 -1
- package/dist/utilities/theme.js +16 -13
- package/package.json +57 -57
- package/dist/components/split-panel/SplitPanel.types.d.ts +0 -2
- package/dist/components/split-panel/Splitter.d.ts +0 -17
- package/dist/components/split-panel/Splitter.js +0 -45
- package/dist/internals/icons.d.ts +0 -6
- /package/dist/components/{split-panel/Splitter.styles.d.ts → divider/Divider.styles.d.ts} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BaseElement } from '../BaseElement.js';
|
|
2
|
-
import { PanelOrientation } from './SplitPanel.types.js';
|
|
3
2
|
/**
|
|
4
3
|
* SplitPanel 컴포넌트는 화면을 여러 개의 패널로 분할하여 표시합니다.
|
|
5
4
|
*/
|
|
@@ -7,20 +6,17 @@ export declare class SplitPanel extends BaseElement {
|
|
|
7
6
|
static styles: import('lit').CSSResultGroup[];
|
|
8
7
|
static dependencies: Record<string, typeof BaseElement>;
|
|
9
8
|
private panels;
|
|
10
|
-
private
|
|
11
|
-
private
|
|
12
|
-
private
|
|
13
|
-
private totalSize;
|
|
14
|
-
private startPosition;
|
|
15
|
-
private startRatio;
|
|
9
|
+
private dividers;
|
|
10
|
+
private panelSizes;
|
|
11
|
+
private panelAdjustSizes;
|
|
16
12
|
/** 분할 방향을 설정합니다. 'horizontal'은 좌우 분할, 'vertical'은 상하 분할입니다. */
|
|
17
|
-
orientation:
|
|
13
|
+
orientation: 'horizontal' | 'vertical';
|
|
18
14
|
/** 초기 패널 크기 비율을 설정합니다. (예: [30, 70]은 첫 번째 패널이 30%, 두 번째 패널이 70%를 차지) */
|
|
19
|
-
|
|
15
|
+
initialRatio: number[];
|
|
20
16
|
disconnectedCallback(): void;
|
|
21
17
|
render(): import('lit-html').TemplateResult<1>;
|
|
18
|
+
private getDividerSize;
|
|
22
19
|
private handleSlotChange;
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
private handleMouseUp;
|
|
20
|
+
/** 디바이더 드래그 이벤트 핸들러 */
|
|
21
|
+
private handleDividerDrag;
|
|
26
22
|
}
|
|
@@ -2,8 +2,8 @@ import { html } from 'lit';
|
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
3
|
import { arrayAttributeConverter } from '../../internals/attribute-converters.js';
|
|
4
4
|
import { BaseElement } from '../BaseElement.js';
|
|
5
|
+
import { Divider } from '../divider/Divider.js';
|
|
5
6
|
import { Panel } from '../panel/Panel.js';
|
|
6
|
-
import { Splitter } from './Splitter.js';
|
|
7
7
|
import { styles } from './SplitPanel.styles.js';
|
|
8
8
|
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
@@ -19,14 +19,11 @@ class SplitPanel extends BaseElement {
|
|
|
19
19
|
constructor() {
|
|
20
20
|
super(...arguments);
|
|
21
21
|
this.panels = [];
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
this.totalSize = 0;
|
|
26
|
-
this.startPosition = 0;
|
|
27
|
-
this.startRatio = [];
|
|
22
|
+
this.dividers = [];
|
|
23
|
+
this.panelSizes = [];
|
|
24
|
+
this.panelAdjustSizes = [];
|
|
28
25
|
this.orientation = "horizontal";
|
|
29
|
-
this.
|
|
26
|
+
this.initialRatio = [];
|
|
30
27
|
this.handleSlotChange = async (e) => {
|
|
31
28
|
const slot = e.target;
|
|
32
29
|
const childrens = slot.assignedElements({ flatten: true });
|
|
@@ -34,83 +31,61 @@ class SplitPanel extends BaseElement {
|
|
|
34
31
|
if (this.panels.length === panels.length && this.panels.every((p, i) => p === panels[i])) {
|
|
35
32
|
return;
|
|
36
33
|
}
|
|
37
|
-
this.splitters.forEach((splitter) => splitter.remove());
|
|
38
|
-
this.splitters = [];
|
|
39
34
|
this.panels = panels;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
splitter.orientation = this.orientation;
|
|
46
|
-
splitter.addEventListener("mousedown", this.handleMouseDown);
|
|
47
|
-
this.splitters.push(splitter);
|
|
48
|
-
panel.after(splitter);
|
|
49
|
-
});
|
|
50
|
-
if (this.ratio.length === panels.length) {
|
|
51
|
-
const totalRatio = this.ratio.reduce((sum, r) => sum + r, 0);
|
|
52
|
-
panels.forEach((panel, i) => {
|
|
53
|
-
const panelRatio = this.ratio[i] / totalRatio * 100;
|
|
54
|
-
panel.style.flex = `${panelRatio} 1 0%`;
|
|
55
|
-
});
|
|
56
|
-
return;
|
|
35
|
+
this.dividers.forEach((divider) => divider.remove());
|
|
36
|
+
this.dividers = [];
|
|
37
|
+
if (this.initialRatio.length === panels.length) {
|
|
38
|
+
const totalRatio = this.initialRatio.reduce((sum, r) => sum + r, 0);
|
|
39
|
+
this.panelSizes = this.initialRatio.map((r) => r / totalRatio * 100);
|
|
57
40
|
} else {
|
|
58
|
-
panels.
|
|
59
|
-
|
|
60
|
-
});
|
|
41
|
+
const equalRatio = 100 / panels.length;
|
|
42
|
+
this.panelSizes = panels.map(() => equalRatio);
|
|
61
43
|
}
|
|
44
|
+
this.panelAdjustSizes = panels.map(() => 0);
|
|
45
|
+
const property2 = this.orientation === "horizontal" ? "width" : "height";
|
|
46
|
+
const dividerSize = this.getDividerSize();
|
|
47
|
+
panels.forEach((panel, index) => {
|
|
48
|
+
const ratio = this.panelSizes[index];
|
|
49
|
+
panel.style.flex = "none";
|
|
50
|
+
panel.style[property2] = index === 0 || index === panels.length - 1 ? `calc(${ratio}% - ${dividerSize / 2}px)` : `calc(${ratio}% - ${dividerSize}px)`;
|
|
51
|
+
if (index === panels.length - 1) return;
|
|
52
|
+
const divider = new Divider();
|
|
53
|
+
divider.orientation = this.orientation;
|
|
54
|
+
divider.draggable = true;
|
|
55
|
+
divider.addEventListener("u-drag", this.handleDividerDrag);
|
|
56
|
+
this.dividers.push(divider);
|
|
57
|
+
panel.after(divider);
|
|
58
|
+
});
|
|
62
59
|
this.requestUpdate();
|
|
63
60
|
await this.updateComplete;
|
|
64
61
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const currentPosition = this.orientation === "horizontal" ? e.clientX : e.clientY;
|
|
90
|
-
const deltaPixels = currentPosition - this.startPosition;
|
|
91
|
-
const splitterIndex = this.splitters.indexOf(this.currentSplitter);
|
|
92
|
-
if (splitterIndex === -1) return;
|
|
93
|
-
const prevPanel = this.panels[splitterIndex];
|
|
94
|
-
const nextPanel = this.panels[splitterIndex + 1];
|
|
95
|
-
if (!prevPanel || !nextPanel) return;
|
|
96
|
-
const deltaRatio = deltaPixels / this.totalSize * 100;
|
|
97
|
-
const prevRatio = this.startRatio[splitterIndex] + deltaRatio;
|
|
98
|
-
const nextRatio = this.startRatio[splitterIndex + 1] - deltaRatio;
|
|
99
|
-
if (prevRatio < 0 || nextRatio < 0) return;
|
|
100
|
-
prevPanel.style.flex = `${prevRatio} 1 0%`;
|
|
101
|
-
nextPanel.style.flex = `${nextRatio} 1 0%`;
|
|
102
|
-
};
|
|
103
|
-
this.handleMouseUp = (_e) => {
|
|
104
|
-
if (!this.isDragging) return;
|
|
105
|
-
this.isDragging = false;
|
|
106
|
-
if (this.currentSplitter) {
|
|
107
|
-
this.currentSplitter.dragging = false;
|
|
108
|
-
this.currentSplitter = null;
|
|
62
|
+
/** 디바이더 드래그 이벤트 핸들러 */
|
|
63
|
+
this.handleDividerDrag = (event) => {
|
|
64
|
+
const divider = event.target;
|
|
65
|
+
const delta = event.detail.delta;
|
|
66
|
+
const index = this.dividers.indexOf(divider);
|
|
67
|
+
if (index === -1) return;
|
|
68
|
+
const prevPanel = this.panels[index];
|
|
69
|
+
const nextPanel = this.panels[index + 1];
|
|
70
|
+
const property2 = this.orientation === "horizontal" ? "width" : "height";
|
|
71
|
+
const prevPanelSize = this.panelSizes[index];
|
|
72
|
+
const nextPanelSize = this.panelSizes[index + 1];
|
|
73
|
+
const prevAdjSize = this.panelAdjustSizes[index] || 0;
|
|
74
|
+
const nextAdjSize = this.panelAdjustSizes[index + 1] || 0;
|
|
75
|
+
if (delta === 0) return;
|
|
76
|
+
if (delta > 0) {
|
|
77
|
+
const prevNewAdjSize = prevAdjSize + delta;
|
|
78
|
+
const nextNewAdjSize = nextAdjSize - delta;
|
|
79
|
+
this.panelAdjustSizes[index] = prevNewAdjSize;
|
|
80
|
+
this.panelAdjustSizes[index + 1] = nextNewAdjSize;
|
|
81
|
+
} else {
|
|
82
|
+
const prevNewAdjSize = prevAdjSize + delta;
|
|
83
|
+
const nextNewAdjSize = nextAdjSize - delta;
|
|
84
|
+
this.panelAdjustSizes[index] = prevNewAdjSize;
|
|
85
|
+
this.panelAdjustSizes[index + 1] = nextNewAdjSize;
|
|
109
86
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
document.body.style.userSelect = "";
|
|
113
|
-
document.body.style.cursor = "";
|
|
87
|
+
prevPanel.style[property2] = `calc(${prevPanelSize}% - ${this.getDividerSize() / 2}px + ${this.panelAdjustSizes[index]}px)`;
|
|
88
|
+
nextPanel.style[property2] = `calc(${nextPanelSize}% - ${this.getDividerSize() / 2}px + ${this.panelAdjustSizes[index + 1]}px)`;
|
|
114
89
|
};
|
|
115
90
|
}
|
|
116
91
|
static {
|
|
@@ -118,17 +93,12 @@ class SplitPanel extends BaseElement {
|
|
|
118
93
|
}
|
|
119
94
|
static {
|
|
120
95
|
this.dependencies = {
|
|
121
|
-
"u-
|
|
122
|
-
"u-
|
|
96
|
+
"u-divider": Divider,
|
|
97
|
+
"u-panel": Panel
|
|
123
98
|
};
|
|
124
99
|
}
|
|
125
100
|
disconnectedCallback() {
|
|
126
|
-
|
|
127
|
-
document.removeEventListener("mouseup", this.handleMouseUp);
|
|
128
|
-
this.splitters.forEach((splitter) => {
|
|
129
|
-
splitter.removeEventListener("mousedown", this.handleMouseDown);
|
|
130
|
-
splitter.remove();
|
|
131
|
-
});
|
|
101
|
+
this.dividers.forEach((divider) => divider.remove());
|
|
132
102
|
super.disconnectedCallback();
|
|
133
103
|
}
|
|
134
104
|
render() {
|
|
@@ -136,12 +106,17 @@ class SplitPanel extends BaseElement {
|
|
|
136
106
|
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
137
107
|
`;
|
|
138
108
|
}
|
|
109
|
+
// Get divider size from CSS variable
|
|
110
|
+
getDividerSize() {
|
|
111
|
+
const sizeStr = getComputedStyle(this).getPropertyValue("--divider-size").trim();
|
|
112
|
+
return parseFloat(sizeStr) || 2;
|
|
113
|
+
}
|
|
139
114
|
}
|
|
140
115
|
__decorateClass([
|
|
141
116
|
property({ type: String, reflect: true })
|
|
142
117
|
], SplitPanel.prototype, "orientation");
|
|
143
118
|
__decorateClass([
|
|
144
|
-
property({ type: Array, converter: arrayAttributeConverter(parseFloat) })
|
|
145
|
-
], SplitPanel.prototype, "
|
|
119
|
+
property({ type: Array, attribute: "initial-ratio", converter: arrayAttributeConverter(parseFloat) })
|
|
120
|
+
], SplitPanel.prototype, "initialRatio");
|
|
146
121
|
|
|
147
122
|
export { SplitPanel };
|
|
@@ -3,17 +3,32 @@ import { css } from 'lit';
|
|
|
3
3
|
const styles = css`
|
|
4
4
|
:host {
|
|
5
5
|
position: relative;
|
|
6
|
-
display:
|
|
6
|
+
display: block;
|
|
7
7
|
width: 100%;
|
|
8
8
|
height: 100%;
|
|
9
9
|
overflow: hidden;
|
|
10
|
+
|
|
11
|
+
--divider-size: 2px;
|
|
12
|
+
--divider-color: var(--u-neutral-200, #d1d5db);
|
|
13
|
+
--divider-handle-size: 4px;
|
|
14
|
+
--divider-handle-color: var(--u-blue-500, #3b82f6);
|
|
10
15
|
}
|
|
11
16
|
:host([orientation="horizontal"]) {
|
|
17
|
+
display: flex;
|
|
12
18
|
flex-direction: row;
|
|
13
19
|
}
|
|
14
20
|
:host([orientation="vertical"]) {
|
|
21
|
+
display: flex;
|
|
15
22
|
flex-direction: column;
|
|
16
23
|
}
|
|
24
|
+
|
|
25
|
+
::slotted(u-divider) {
|
|
26
|
+
background-color: var(--divider-color, var(--u-neutral-200, #d1d5db));
|
|
27
|
+
|
|
28
|
+
--divider-size: var(--divider-size, 2px);
|
|
29
|
+
--handler-size: var(--divider-handle-size, 4px);
|
|
30
|
+
--handler-color: var(--divider-handle-color, var(--u-blue-500, #3b82f6));
|
|
31
|
+
}
|
|
17
32
|
`;
|
|
18
33
|
|
|
19
34
|
export { styles };
|
|
@@ -7,38 +7,34 @@ import { BaseElement } from '../BaseElement.js';
|
|
|
7
7
|
export declare class Tooltip extends BaseElement {
|
|
8
8
|
static styles: import('lit').CSSResultGroup[];
|
|
9
9
|
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
-
/** 슬롯이 비어있는지 여부를 나타냅니다. */
|
|
11
|
-
private isSlotEmpty;
|
|
12
10
|
/** 툴팁이 연결될 대상 엘리먼트입니다. 지정하지 않으면 부모 엘리먼트가 대상이 됩니다. */
|
|
13
11
|
triggers: HTMLElement[];
|
|
14
12
|
/** 트리거 셀렉터 문자열입니다. 이 속성을 사용하여 트리거 엘리먼트를 지정할 수 있습니다. */
|
|
15
13
|
triggerSelectors?: string;
|
|
16
|
-
/** 현재 툴팁이 열려있는지 여부를 나타냅니다. */
|
|
17
|
-
open: boolean;
|
|
18
14
|
/** 'fixed' 위치에서 포지션을 계산할지 여부를 설정합니다. 기본값은 false입니다. */
|
|
19
15
|
hoist: boolean;
|
|
20
16
|
/** 툴팁이 나타날 위치를 설정합니다. */
|
|
21
17
|
placement?: Placement;
|
|
22
18
|
/** 툴팁의 위치에서 대상 엘리먼트까지의 거리를 픽셀단위로 설정합니다. 기본값은 8입니다. */
|
|
23
19
|
distance: number;
|
|
20
|
+
/** 툴팁의 표시 딜레이 시간을 밀리초 단위로 설정합니다. 기본값은 0입니다. */
|
|
21
|
+
delay: number;
|
|
22
|
+
constructor();
|
|
24
23
|
connectedCallback(): void;
|
|
25
24
|
disconnectedCallback(): void;
|
|
26
25
|
protected willUpdate(changedProperties: PropertyValues): void;
|
|
26
|
+
protected updated(changedProperties: PropertyValues): void;
|
|
27
27
|
render(): import('lit-html').TemplateResult<1>;
|
|
28
28
|
/** 툴팁을 표시합니다. */
|
|
29
|
-
show: (
|
|
29
|
+
show: (event: Event) => Promise<void>;
|
|
30
30
|
/** 툴팁을 숨깁니다. */
|
|
31
|
-
hide: (
|
|
31
|
+
hide: (event: Event) => Promise<void>;
|
|
32
32
|
/** 대상 엘리먼트에 툴팁 이벤트를 바인딩 합니다. */
|
|
33
33
|
private attachTriggers;
|
|
34
34
|
/** 대상 엘리먼트에 바인딩된 툴팁 이벤트를 제거합니다. */
|
|
35
35
|
private detachTriggers;
|
|
36
36
|
/**
|
|
37
|
-
|
|
38
|
-
*/
|
|
39
|
-
private getTransformOrigin;
|
|
40
|
-
/**
|
|
41
|
-
* slot에 콘텐츠가 존재하는지 확인합니다.
|
|
37
|
+
* 툴팁이 나타날 위치에 따라 transform-origin 값을 반환합니다.
|
|
42
38
|
*/
|
|
43
|
-
private
|
|
39
|
+
private getTransformOrigin;
|
|
44
40
|
}
|
|
@@ -16,59 +16,55 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
16
16
|
};
|
|
17
17
|
class Tooltip extends BaseElement {
|
|
18
18
|
constructor() {
|
|
19
|
-
super(
|
|
20
|
-
/** 슬롯이 비어있는지 여부를 나타냅니다. */
|
|
21
|
-
this.isSlotEmpty = true;
|
|
19
|
+
super();
|
|
22
20
|
this.triggers = [];
|
|
23
|
-
this.open = false;
|
|
24
21
|
this.hoist = false;
|
|
25
22
|
this.distance = 8;
|
|
23
|
+
this.delay = 0;
|
|
26
24
|
/** 툴팁을 표시합니다. */
|
|
27
|
-
this.show = async (
|
|
25
|
+
this.show = async (event) => {
|
|
28
26
|
await this.updateComplete;
|
|
29
|
-
const trigger =
|
|
30
|
-
if (
|
|
27
|
+
const trigger = event?.currentTarget;
|
|
28
|
+
if (trigger instanceof HTMLElement === false) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
31
|
const middleware = [
|
|
32
32
|
offset({ mainAxis: this.distance }),
|
|
33
33
|
shift(),
|
|
34
34
|
flip()
|
|
35
35
|
];
|
|
36
|
-
if (!this.placement)
|
|
36
|
+
if (!this.placement) {
|
|
37
37
|
middleware.push(autoPlacement());
|
|
38
|
+
}
|
|
38
39
|
const position = await computePosition(trigger, this, {
|
|
40
|
+
strategy: this.hoist ? "fixed" : "absolute",
|
|
39
41
|
placement: this.placement,
|
|
40
|
-
middleware
|
|
41
|
-
strategy: this.hoist ? "fixed" : "absolute"
|
|
42
|
+
middleware
|
|
42
43
|
});
|
|
43
44
|
Object.assign(this.style, {
|
|
44
45
|
left: `${position.x}px`,
|
|
45
46
|
top: `${position.y}px`,
|
|
46
47
|
transformOrigin: this.getTransformOrigin(position.placement)
|
|
47
48
|
});
|
|
48
|
-
|
|
49
|
+
if (this.delay > 0) {
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, this.delay));
|
|
51
|
+
}
|
|
49
52
|
requestAnimationFrame(() => {
|
|
50
|
-
this.open
|
|
53
|
+
this.setAttribute("open", "");
|
|
51
54
|
});
|
|
52
55
|
};
|
|
53
56
|
/** 툴팁을 숨깁니다. */
|
|
54
|
-
this.hide = async (
|
|
57
|
+
this.hide = async (event) => {
|
|
55
58
|
await this.updateComplete;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.handleSlotChange = (e) => {
|
|
64
|
-
const slot = e.target;
|
|
65
|
-
const nodes = slot.assignedNodes({ flatten: true }) ?? [];
|
|
66
|
-
this.isSlotEmpty = !nodes.some((node) => {
|
|
67
|
-
if (node.nodeType === Node.ELEMENT_NODE) return true;
|
|
68
|
-
if (node.nodeType === Node.TEXT_NODE && node.textContent?.trim()) return true;
|
|
69
|
-
return false;
|
|
70
|
-
});
|
|
59
|
+
if ("relatedTarget" in event) {
|
|
60
|
+
const relatedTarget = event["relatedTarget"];
|
|
61
|
+
if (this.contains(relatedTarget)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this.removeAttribute("open");
|
|
71
66
|
};
|
|
67
|
+
this.setAttribute("tabindex", "0");
|
|
72
68
|
}
|
|
73
69
|
static {
|
|
74
70
|
this.styles = [super.styles, styles];
|
|
@@ -82,6 +78,8 @@ class Tooltip extends BaseElement {
|
|
|
82
78
|
const parent = getParentElement(this);
|
|
83
79
|
if (parent) this.triggers = [parent];
|
|
84
80
|
}
|
|
81
|
+
this.addEventListener("mouseleave", this.hide);
|
|
82
|
+
this.addEventListener("focusout", this.hide);
|
|
85
83
|
}
|
|
86
84
|
disconnectedCallback() {
|
|
87
85
|
this.detachTriggers(this.triggers);
|
|
@@ -89,18 +87,21 @@ class Tooltip extends BaseElement {
|
|
|
89
87
|
}
|
|
90
88
|
willUpdate(changedProperties) {
|
|
91
89
|
super.willUpdate(changedProperties);
|
|
92
|
-
if (changedProperties.has("
|
|
90
|
+
if (changedProperties.has("triggerSelectors") && this.triggerSelectors) {
|
|
91
|
+
this.triggers = findElementsBy(this, this.triggerSelectors);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
updated(changedProperties) {
|
|
95
|
+
super.updated(changedProperties);
|
|
96
|
+
if (changedProperties.has("triggers")) {
|
|
93
97
|
const oldTriggers = changedProperties.get("triggers");
|
|
94
98
|
this.detachTriggers(oldTriggers);
|
|
95
99
|
this.attachTriggers(this.triggers);
|
|
96
100
|
}
|
|
97
|
-
if (changedProperties.has("triggerSelectors") && this.triggerSelectors) {
|
|
98
|
-
this.triggers = findElementsBy(this, this.triggerSelectors);
|
|
99
|
-
}
|
|
100
101
|
}
|
|
101
102
|
render() {
|
|
102
103
|
return html`
|
|
103
|
-
<slot
|
|
104
|
+
<slot></slot>
|
|
104
105
|
`;
|
|
105
106
|
}
|
|
106
107
|
/** 대상 엘리먼트에 툴팁 이벤트를 바인딩 합니다. */
|
|
@@ -124,8 +125,8 @@ class Tooltip extends BaseElement {
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
/**
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
* 툴팁이 나타날 위치에 따라 transform-origin 값을 반환합니다.
|
|
129
|
+
*/
|
|
129
130
|
getTransformOrigin(placement) {
|
|
130
131
|
switch (placement) {
|
|
131
132
|
case "top":
|
|
@@ -155,9 +156,6 @@ __decorateClass([
|
|
|
155
156
|
__decorateClass([
|
|
156
157
|
property({ type: String, attribute: "trigger-selectors" })
|
|
157
158
|
], Tooltip.prototype, "triggerSelectors");
|
|
158
|
-
__decorateClass([
|
|
159
|
-
property({ type: Boolean, reflect: true })
|
|
160
|
-
], Tooltip.prototype, "open");
|
|
161
159
|
__decorateClass([
|
|
162
160
|
property({ type: Boolean, reflect: true })
|
|
163
161
|
], Tooltip.prototype, "hoist");
|
|
@@ -167,5 +165,8 @@ __decorateClass([
|
|
|
167
165
|
__decorateClass([
|
|
168
166
|
property({ type: Number })
|
|
169
167
|
], Tooltip.prototype, "distance");
|
|
168
|
+
__decorateClass([
|
|
169
|
+
property({ type: Number })
|
|
170
|
+
], Tooltip.prototype, "delay");
|
|
170
171
|
|
|
171
172
|
export { Tooltip };
|
|
@@ -6,9 +6,9 @@ const styles = css`
|
|
|
6
6
|
z-index: 1000;
|
|
7
7
|
top: 0;
|
|
8
8
|
left: 0;
|
|
9
|
+
|
|
9
10
|
display: block;
|
|
10
11
|
width: max-content;
|
|
11
|
-
|
|
12
12
|
padding: 8px;
|
|
13
13
|
color: var(--u-tooltip-text-color);
|
|
14
14
|
font-family: var(--u-font-modern, inherit);
|
|
@@ -23,14 +23,14 @@ const styles = css`
|
|
|
23
23
|
transform: scale(0);
|
|
24
24
|
transition: opacity 0.15s ease, transform 0.15s ease;
|
|
25
25
|
}
|
|
26
|
+
:host([hoist]) {
|
|
27
|
+
position: fixed;
|
|
28
|
+
}
|
|
26
29
|
:host([open]) {
|
|
27
30
|
opacity: 0.8;
|
|
28
31
|
transform: scale(1);
|
|
29
32
|
pointer-events: auto;
|
|
30
33
|
}
|
|
31
|
-
:host([hoist]) {
|
|
32
|
-
position: fixed;
|
|
33
|
-
}
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
36
|
export { styles };
|
|
@@ -7,33 +7,21 @@ import { TreeItem } from '../tree-item/TreeItem.js';
|
|
|
7
7
|
export declare class Tree extends BaseElement {
|
|
8
8
|
static styles: import('lit').CSSResultGroup[];
|
|
9
9
|
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
+
private selectedItems;
|
|
11
|
+
treeItems: TreeItem[];
|
|
10
12
|
/** 트리가 비활성화 상태인지 여부입니다. */
|
|
11
13
|
disabled: boolean;
|
|
12
14
|
/** 다중 선택을 허용할지 여부입니다. */
|
|
13
15
|
multiple: boolean;
|
|
14
16
|
/** 선택 가능한 트리인지 여부입니다. */
|
|
15
17
|
selectable: boolean;
|
|
16
|
-
private treeItems;
|
|
17
|
-
private selectedItems;
|
|
18
18
|
connectedCallback(): void;
|
|
19
19
|
disconnectedCallback(): void;
|
|
20
20
|
render(): import('lit-html').TemplateResult<1>;
|
|
21
|
-
/** 슬롯 변경 이벤트를 처리합니다. */
|
|
22
|
-
private handleSlotChange;
|
|
23
|
-
/** 트리 항목의 레벨을 업데이트합니다. */
|
|
24
|
-
private updateTreeItemsLevel;
|
|
25
21
|
/** 트리 항목 선택 이벤트를 처리합니다. */
|
|
26
22
|
private handleItemSelect;
|
|
27
23
|
/** 트리 항목 확장/축소 이벤트를 처리합니다. */
|
|
28
24
|
private handleItemToggle;
|
|
29
|
-
/**
|
|
30
|
-
* 모든 트리 항목을 확장합니다.
|
|
31
|
-
*/
|
|
32
|
-
expandAll(): void;
|
|
33
|
-
/**
|
|
34
|
-
* 모든 트리 항목을 축소합니다.
|
|
35
|
-
*/
|
|
36
|
-
collapseAll(): void;
|
|
37
25
|
/**
|
|
38
26
|
* 선택된 모든 항목을 반환합니다.
|
|
39
27
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
|
-
import {
|
|
2
|
+
import { queryAssignedElements, property } from 'lit/decorators.js';
|
|
3
3
|
import { BaseElement } from '../BaseElement.js';
|
|
4
4
|
import { TreeItem } from '../tree-item/TreeItem.js';
|
|
5
5
|
import { styles } from './Tree.styles.js';
|
|
@@ -16,14 +16,10 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
16
16
|
class Tree extends BaseElement {
|
|
17
17
|
constructor() {
|
|
18
18
|
super(...arguments);
|
|
19
|
+
this.selectedItems = /* @__PURE__ */ new Set();
|
|
19
20
|
this.disabled = false;
|
|
20
21
|
this.multiple = false;
|
|
21
22
|
this.selectable = true;
|
|
22
|
-
this.selectedItems = /* @__PURE__ */ new Set();
|
|
23
|
-
/** 슬롯 변경 이벤트를 처리합니다. */
|
|
24
|
-
this.handleSlotChange = () => {
|
|
25
|
-
this.updateTreeItemsLevel();
|
|
26
|
-
};
|
|
27
23
|
/** 트리 항목 선택 이벤트를 처리합니다. */
|
|
28
24
|
this.handleItemSelect = (e) => {
|
|
29
25
|
if (!this.selectable || this.disabled) {
|
|
@@ -84,42 +80,11 @@ class Tree extends BaseElement {
|
|
|
84
80
|
}
|
|
85
81
|
render() {
|
|
86
82
|
return html`
|
|
87
|
-
<div class="
|
|
88
|
-
<slot
|
|
83
|
+
<div class="container">
|
|
84
|
+
<slot></slot>
|
|
89
85
|
</div>
|
|
90
86
|
`;
|
|
91
87
|
}
|
|
92
|
-
/** 트리 항목의 레벨을 업데이트합니다. */
|
|
93
|
-
updateTreeItemsLevel(items = this.treeItems, level = 0) {
|
|
94
|
-
items.forEach((item) => {
|
|
95
|
-
if (item instanceof TreeItem) {
|
|
96
|
-
item.level = level;
|
|
97
|
-
const childrenSlot = item.shadowRoot?.querySelector('slot[name="children"]');
|
|
98
|
-
if (childrenSlot) {
|
|
99
|
-
const children = childrenSlot.assignedElements();
|
|
100
|
-
if (children.length > 0) {
|
|
101
|
-
this.updateTreeItemsLevel(children, level + 1);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 모든 트리 항목을 확장합니다.
|
|
109
|
-
*/
|
|
110
|
-
expandAll() {
|
|
111
|
-
this.getAllTreeItems().forEach((item) => {
|
|
112
|
-
item.expand();
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* 모든 트리 항목을 축소합니다.
|
|
117
|
-
*/
|
|
118
|
-
collapseAll() {
|
|
119
|
-
this.getAllTreeItems().forEach((item) => {
|
|
120
|
-
item.collapse();
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
88
|
/**
|
|
124
89
|
* 선택된 모든 항목을 반환합니다.
|
|
125
90
|
*/
|
|
@@ -143,18 +108,16 @@ class Tree extends BaseElement {
|
|
|
143
108
|
items.forEach((item) => {
|
|
144
109
|
if (item instanceof TreeItem) {
|
|
145
110
|
allItems.push(item);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
const children = childrenSlot.assignedElements();
|
|
149
|
-
if (children.length > 0) {
|
|
150
|
-
allItems = allItems.concat(this.getAllTreeItems(children));
|
|
151
|
-
}
|
|
152
|
-
}
|
|
111
|
+
const childItems = this.getAllTreeItems(item.childrenItems);
|
|
112
|
+
allItems = allItems.concat(childItems);
|
|
153
113
|
}
|
|
154
114
|
});
|
|
155
115
|
return allItems;
|
|
156
116
|
}
|
|
157
117
|
}
|
|
118
|
+
__decorateClass([
|
|
119
|
+
queryAssignedElements({ selector: "u-tree-item" })
|
|
120
|
+
], Tree.prototype, "treeItems");
|
|
158
121
|
__decorateClass([
|
|
159
122
|
property({ type: Boolean, reflect: true })
|
|
160
123
|
], Tree.prototype, "disabled");
|
|
@@ -164,8 +127,5 @@ __decorateClass([
|
|
|
164
127
|
__decorateClass([
|
|
165
128
|
property({ type: Boolean })
|
|
166
129
|
], Tree.prototype, "selectable");
|
|
167
|
-
__decorateClass([
|
|
168
|
-
queryAssignedElements({ selector: "u-tree-item" })
|
|
169
|
-
], Tree.prototype, "treeItems");
|
|
170
130
|
|
|
171
131
|
export { Tree };
|
|
@@ -3,8 +3,11 @@ import { css } from 'lit';
|
|
|
3
3
|
const styles = css`
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
6
|
-
width: 100%;
|
|
7
6
|
min-width: 0;
|
|
7
|
+
width: 100%;
|
|
8
|
+
padding: 4px;
|
|
9
|
+
background-color: transparent;
|
|
10
|
+
border-radius: 4px;
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
:host([disabled]) {
|
|
@@ -13,13 +16,10 @@ const styles = css`
|
|
|
13
16
|
cursor: not-allowed;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
.
|
|
19
|
+
.container {
|
|
17
20
|
display: flex;
|
|
18
21
|
flex-direction: column;
|
|
19
22
|
gap: 2px;
|
|
20
|
-
padding: 4px;
|
|
21
|
-
background-color: transparent;
|
|
22
|
-
border-radius: 4px;
|
|
23
23
|
}
|
|
24
24
|
`;
|
|
25
25
|
|