@iyulab/components 0.1.3 → 0.1.5
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 +129 -125
- package/dist/assets/styles/dark.css.js +1 -1
- package/dist/assets/styles/light.css +129 -126
- package/dist/assets/styles/light.css.js +1 -1
- package/dist/components/BaseElement.styles.js +2 -3
- package/dist/components/alert/Alert.d.ts +8 -4
- package/dist/components/alert/Alert.js +24 -15
- package/dist/components/alert/Alert.styles.js +32 -39
- package/dist/components/alert/index.js +5 -0
- package/dist/components/button/Button.js +4 -2
- package/dist/components/button/Button.styles.js +13 -20
- package/dist/components/button/index.js +5 -0
- package/dist/components/context-menu/index.js +5 -0
- package/dist/components/copy-button/CopyButton.d.ts +7 -3
- package/dist/components/copy-button/CopyButton.js +69 -0
- package/dist/components/copy-button/CopyButton.styles.js +17 -0
- package/dist/components/copy-button/index.js +5 -0
- package/dist/components/dialog/index.js +5 -0
- 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} +25 -13
- package/dist/components/divider/index.d.ts +7 -0
- package/dist/components/divider/index.js +5 -0
- package/dist/components/form/Form.d.ts +3 -1
- package/dist/components/form/Form.js +3 -1
- package/dist/components/form/Form.styles.js +1 -0
- package/dist/components/form/index.js +5 -0
- package/dist/components/icon/Icon.d.ts +6 -16
- package/dist/components/icon/Icon.js +17 -40
- package/dist/components/icon/Icon.styles.js +1 -1
- package/dist/components/icon/index.js +5 -0
- package/dist/components/icon-button/IconButton.d.ts +3 -3
- package/dist/components/icon-button/IconButton.js +6 -6
- package/dist/components/icon-button/IconButton.styles.js +14 -29
- package/dist/components/icon-button/index.js +5 -0
- package/dist/components/index.d.ts +2 -1
- package/dist/components/input/Input.d.ts +14 -13
- package/dist/components/input/Input.js +56 -55
- package/dist/components/input/Input.styles.js +52 -54
- package/dist/components/input/index.js +5 -0
- package/dist/components/menu/index.js +5 -0
- package/dist/components/progress-bar/ProgressBar.d.ts +2 -2
- package/dist/components/progress-bar/ProgressBar.js +2 -2
- package/dist/components/progress-bar/ProgressBar.styles.js +10 -10
- package/dist/components/progress-bar/index.js +5 -0
- package/dist/components/progress-ring/ProgressRing.d.ts +2 -2
- package/dist/components/progress-ring/ProgressRing.js +9 -6
- package/dist/components/progress-ring/ProgressRing.styles.js +8 -9
- package/dist/components/progress-ring/index.js +5 -0
- package/dist/components/spinner/Spinner.styles.js +5 -3
- package/dist/components/spinner/index.js +5 -0
- package/dist/components/split-panel/SplitPanel.d.ts +8 -12
- package/dist/components/split-panel/SplitPanel.js +64 -91
- package/dist/components/split-panel/SplitPanel.styles.js +16 -1
- package/dist/components/split-panel/index.js +5 -0
- package/dist/components/tooltip/Tooltip.d.ts +8 -12
- package/dist/components/tooltip/Tooltip.js +39 -38
- package/dist/components/tooltip/Tooltip.styles.js +5 -5
- package/dist/components/tooltip/index.js +5 -0
- 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/index.js +5 -0
- 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/components/tree-item/index.js +5 -0
- package/dist/index.js +25 -5
- 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 -1
- package/dist/integrations/react/index.js +1 -1
- package/dist/internals/index.d.ts +0 -1
- package/dist/utilities/decorators.js +2 -0
- package/dist/utilities/icons.d.ts +46 -0
- package/dist/{internals → utilities}/icons.js +74 -2
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/notifier.d.ts +17 -7
- package/dist/utilities/notifier.js +51 -41
- package/dist/utilities/theme.d.ts +15 -20
- package/dist/utilities/theme.js +36 -29
- package/package.json +59 -58
- package/dist/components/panel/Panel.d.ts +0 -10
- package/dist/components/panel/Panel.js +0 -21
- package/dist/components/panel/Panel.styles.js +0 -12
- package/dist/components/panel/index.d.ts +0 -7
- 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/components/split-panel/Splitter.styles.d.ts +0 -1
- package/dist/integrations/react/UPanel.d.ts +0 -8
- package/dist/integrations/react/UPanel.js +0 -10
- package/dist/internals/icons.d.ts +0 -6
- /package/dist/components/{panel/Panel.styles.d.ts → divider/Divider.styles.d.ts} +0 -0
|
@@ -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,11 +6,11 @@ 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
|
-
color: var(--u-tooltip-
|
|
13
|
+
color: var(--u-tooltip-txt-color);
|
|
14
14
|
font-family: var(--u-font-modern, inherit);
|
|
15
15
|
font-size: 14px;
|
|
16
16
|
line-height: 1.5;
|
|
@@ -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
|
|
|
@@ -7,46 +7,27 @@ import { BaseElement } from '../BaseElement.js';
|
|
|
7
7
|
export declare class TreeItem extends BaseElement {
|
|
8
8
|
static styles: import('lit').CSSResultGroup[];
|
|
9
9
|
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
+
headerEl: HTMLElement;
|
|
11
|
+
childrenItems: TreeItem[];
|
|
12
|
+
/** 트리 항목이 리프 노드인지 여부입니다. */
|
|
13
|
+
leaf: boolean;
|
|
14
|
+
/** 트리 항목의 들여쓰기 레벨입니다. */
|
|
15
|
+
level: number;
|
|
10
16
|
/** 트리 항목이 비활성화 상태인지 여부입니다. */
|
|
11
17
|
disabled: boolean;
|
|
12
18
|
/** 트리 항목이 선택된 상태인지 여부입니다. */
|
|
13
19
|
selected: boolean;
|
|
14
20
|
/** 트리 항목이 확장된 상태인지 여부입니다. */
|
|
15
21
|
expanded: boolean;
|
|
16
|
-
/** 트리 항목이 리프 노드인지 여부입니다. */
|
|
17
|
-
leaf: boolean;
|
|
18
|
-
/** 트리 항목의 들여쓰기 레벨입니다. */
|
|
19
|
-
level: number;
|
|
20
22
|
/** 트리 항목의 값입니다. */
|
|
21
23
|
value: string;
|
|
22
|
-
/** 트리 항목의 아이콘입니다. */
|
|
23
|
-
icon: string;
|
|
24
|
-
private hasChildren;
|
|
25
24
|
connectedCallback(): void;
|
|
26
25
|
protected updated(changedProperties: PropertyValues): void;
|
|
27
26
|
render(): import('lit-html').TemplateResult<1>;
|
|
28
|
-
/**
|
|
29
|
-
private
|
|
30
|
-
/**
|
|
31
|
-
private
|
|
27
|
+
/** 슬롯 변경 시 헤더용 노드와 자식 노드 분리 */
|
|
28
|
+
private handleSlotChange;
|
|
29
|
+
/** 자식 슬롯 변경 시 자식 노드 재설정 */
|
|
30
|
+
private handleChildrenSlotChange;
|
|
32
31
|
/** 헤더 클릭 이벤트를 처리합니다. */
|
|
33
32
|
private handleHeaderClick;
|
|
34
|
-
/** 확장/축소 아이콘 클릭 이벤트를 처리합니다. */
|
|
35
|
-
private handleExpandClick;
|
|
36
|
-
/** 슬롯 변경 시 자식 노드 확인 */
|
|
37
|
-
private handleSlotChange;
|
|
38
|
-
/** 자식 노드가 있는지 확인합니다. */
|
|
39
|
-
private checkForChildren;
|
|
40
|
-
/**
|
|
41
|
-
* 트리 항목을 확장합니다.
|
|
42
|
-
*/
|
|
43
|
-
expand(): void;
|
|
44
|
-
/**
|
|
45
|
-
* 트리 항목을 축소합니다.
|
|
46
|
-
*/
|
|
47
|
-
collapse(): void;
|
|
48
|
-
/**
|
|
49
|
-
* 트리 항목의 확장 상태를 토글합니다.
|
|
50
|
-
*/
|
|
51
|
-
toggle(): void;
|
|
52
33
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { html
|
|
2
|
-
import {
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { query, queryAssignedElements, state, property } from 'lit/decorators.js';
|
|
3
3
|
import { BaseElement } from '../BaseElement.js';
|
|
4
|
+
import { Icon } from '../icon/Icon.js';
|
|
4
5
|
import { styles } from './TreeItem.styles.js';
|
|
5
6
|
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
@@ -12,17 +13,32 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
12
13
|
if (result) __defProp(target, key, result);
|
|
13
14
|
return result;
|
|
14
15
|
};
|
|
15
|
-
class
|
|
16
|
+
const _TreeItem = class _TreeItem extends BaseElement {
|
|
16
17
|
constructor() {
|
|
17
18
|
super(...arguments);
|
|
19
|
+
this.leaf = true;
|
|
20
|
+
this.level = 0;
|
|
18
21
|
this.disabled = false;
|
|
19
22
|
this.selected = false;
|
|
20
23
|
this.expanded = false;
|
|
21
|
-
this.leaf = false;
|
|
22
|
-
this.level = 0;
|
|
23
24
|
this.value = "";
|
|
24
|
-
|
|
25
|
-
this.
|
|
25
|
+
/** 슬롯 변경 시 헤더용 노드와 자식 노드 분리 */
|
|
26
|
+
this.handleSlotChange = (e) => {
|
|
27
|
+
const slot = e.target;
|
|
28
|
+
const nodes = slot.assignedNodes({ flatten: true });
|
|
29
|
+
nodes.forEach((node) => {
|
|
30
|
+
if (node instanceof _TreeItem) {
|
|
31
|
+
node.setAttribute("slot", "children");
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
/** 자식 슬롯 변경 시 자식 노드 재설정 */
|
|
36
|
+
this.handleChildrenSlotChange = () => {
|
|
37
|
+
this.leaf = this.childrenItems.length === 0;
|
|
38
|
+
this.childrenItems.forEach((child) => {
|
|
39
|
+
child.level = this.level + 1;
|
|
40
|
+
});
|
|
41
|
+
};
|
|
26
42
|
/** 헤더 클릭 이벤트를 처리합니다. */
|
|
27
43
|
this.handleHeaderClick = (e) => {
|
|
28
44
|
if (this.disabled) {
|
|
@@ -30,34 +46,27 @@ class TreeItem extends BaseElement {
|
|
|
30
46
|
e.stopPropagation();
|
|
31
47
|
return;
|
|
32
48
|
}
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (this.disabled || this.leaf || !this.hasChildren) {
|
|
40
|
-
return;
|
|
49
|
+
if (this.leaf) {
|
|
50
|
+
this.selected = true;
|
|
51
|
+
this.emit("u-select", { value: this.value, item: this });
|
|
52
|
+
} else {
|
|
53
|
+
this.expanded = !this.expanded;
|
|
54
|
+
this.emit("u-toggle", { expanded: this.expanded, item: this });
|
|
41
55
|
}
|
|
42
|
-
this.expanded = !this.expanded;
|
|
43
|
-
this.emit("u-toggle", { expanded: this.expanded, item: this });
|
|
44
|
-
};
|
|
45
|
-
/** 슬롯 변경 시 자식 노드 확인 */
|
|
46
|
-
this.handleSlotChange = () => {
|
|
47
|
-
this.checkForChildren();
|
|
48
56
|
};
|
|
49
57
|
}
|
|
50
58
|
static {
|
|
51
59
|
this.styles = [super.styles, styles];
|
|
52
60
|
}
|
|
53
61
|
static {
|
|
54
|
-
this.dependencies = {
|
|
62
|
+
this.dependencies = {
|
|
63
|
+
"u-icon": Icon
|
|
64
|
+
};
|
|
55
65
|
}
|
|
56
66
|
connectedCallback() {
|
|
57
67
|
super.connectedCallback();
|
|
58
68
|
this.setAttribute("role", "treeitem");
|
|
59
69
|
this.setAttribute("tabindex", this.disabled ? "-1" : "0");
|
|
60
|
-
this.checkForChildren();
|
|
61
70
|
}
|
|
62
71
|
updated(changedProperties) {
|
|
63
72
|
super.updated(changedProperties);
|
|
@@ -66,98 +75,57 @@ class TreeItem extends BaseElement {
|
|
|
66
75
|
this.setAttribute("aria-disabled", this.disabled ? "true" : "false");
|
|
67
76
|
}
|
|
68
77
|
if (changedProperties.has("expanded")) {
|
|
69
|
-
this.setAttribute("aria-expanded", this.
|
|
78
|
+
this.setAttribute("aria-expanded", this.expanded ? "true" : "false");
|
|
70
79
|
}
|
|
71
80
|
if (changedProperties.has("selected")) {
|
|
72
81
|
this.setAttribute("aria-selected", this.selected ? "true" : "false");
|
|
73
82
|
}
|
|
83
|
+
if (changedProperties.has("level")) {
|
|
84
|
+
this.setAttribute("aria-level", String(this.level + 1));
|
|
85
|
+
this.headerEl.style.paddingLeft = `calc(${this.level} * var(--indent-size, 20px))`;
|
|
86
|
+
}
|
|
74
87
|
}
|
|
75
88
|
render() {
|
|
76
89
|
return html`
|
|
77
|
-
<div class="header" @click=${this.handleHeaderClick}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
<div class="header" @click=${this.handleHeaderClick}>
|
|
91
|
+
<u-icon class="expand-icon"
|
|
92
|
+
?hidden=${this.leaf}
|
|
93
|
+
name=${this.expanded ? "chevron-down" : "chevron-right"}
|
|
94
|
+
></u-icon>
|
|
95
|
+
<slot name="prefix"></slot>
|
|
96
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
97
|
+
<slot name="suffix"></slot>
|
|
84
98
|
</div>
|
|
85
99
|
<div class="children" ?hidden=${!this.expanded}>
|
|
86
|
-
<slot name="children" @slotchange=${this.
|
|
100
|
+
<slot name="children" @slotchange=${this.handleChildrenSlotChange}></slot>
|
|
87
101
|
</div>
|
|
88
102
|
`;
|
|
89
103
|
}
|
|
90
|
-
|
|
91
|
-
renderExpandIcon() {
|
|
92
|
-
if (this.leaf || !this.hasChildren) {
|
|
93
|
-
return html`<span class="expand-icon placeholder"></span>`;
|
|
94
|
-
}
|
|
95
|
-
return html`
|
|
96
|
-
<span class="expand-icon" @click=${this.handleExpandClick}>
|
|
97
|
-
${this.expanded ? "▼" : "▶"}
|
|
98
|
-
</span>
|
|
99
|
-
`;
|
|
100
|
-
}
|
|
101
|
-
/** 커스텀 아이콘을 렌더링합니다. */
|
|
102
|
-
renderIcon() {
|
|
103
|
-
if (!this.icon) {
|
|
104
|
-
return nothing;
|
|
105
|
-
}
|
|
106
|
-
return html`<span class="icon">${this.icon}</span>`;
|
|
107
|
-
}
|
|
108
|
-
/** 자식 노드가 있는지 확인합니다. */
|
|
109
|
-
checkForChildren() {
|
|
110
|
-
const childrenSlot = this.shadowRoot?.querySelector('slot[name="children"]');
|
|
111
|
-
const children = childrenSlot?.assignedElements() || [];
|
|
112
|
-
this.hasChildren = children.length > 0;
|
|
113
|
-
this.setAttribute("aria-expanded", this.hasChildren ? String(this.expanded) : "false");
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* 트리 항목을 확장합니다.
|
|
117
|
-
*/
|
|
118
|
-
expand() {
|
|
119
|
-
if (!this.leaf && this.hasChildren) {
|
|
120
|
-
this.expanded = true;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* 트리 항목을 축소합니다.
|
|
125
|
-
*/
|
|
126
|
-
collapse() {
|
|
127
|
-
this.expanded = false;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 트리 항목의 확장 상태를 토글합니다.
|
|
131
|
-
*/
|
|
132
|
-
toggle() {
|
|
133
|
-
if (!this.leaf && this.hasChildren) {
|
|
134
|
-
this.expanded = !this.expanded;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
104
|
+
};
|
|
138
105
|
__decorateClass([
|
|
139
|
-
|
|
140
|
-
],
|
|
106
|
+
query(".header")
|
|
107
|
+
], _TreeItem.prototype, "headerEl");
|
|
141
108
|
__decorateClass([
|
|
142
|
-
|
|
143
|
-
],
|
|
109
|
+
queryAssignedElements({ slot: "children", selector: "u-tree-item", flatten: true })
|
|
110
|
+
], _TreeItem.prototype, "childrenItems");
|
|
144
111
|
__decorateClass([
|
|
145
|
-
|
|
146
|
-
],
|
|
112
|
+
state()
|
|
113
|
+
], _TreeItem.prototype, "leaf");
|
|
114
|
+
__decorateClass([
|
|
115
|
+
state()
|
|
116
|
+
], _TreeItem.prototype, "level");
|
|
147
117
|
__decorateClass([
|
|
148
118
|
property({ type: Boolean, reflect: true })
|
|
149
|
-
],
|
|
119
|
+
], _TreeItem.prototype, "disabled");
|
|
150
120
|
__decorateClass([
|
|
151
|
-
property({ type:
|
|
152
|
-
],
|
|
121
|
+
property({ type: Boolean, reflect: true })
|
|
122
|
+
], _TreeItem.prototype, "selected");
|
|
153
123
|
__decorateClass([
|
|
154
|
-
property({ type:
|
|
155
|
-
],
|
|
124
|
+
property({ type: Boolean, reflect: true })
|
|
125
|
+
], _TreeItem.prototype, "expanded");
|
|
156
126
|
__decorateClass([
|
|
157
127
|
property({ type: String })
|
|
158
|
-
],
|
|
159
|
-
|
|
160
|
-
state()
|
|
161
|
-
], TreeItem.prototype, "hasChildren");
|
|
128
|
+
], _TreeItem.prototype, "value");
|
|
129
|
+
let TreeItem = _TreeItem;
|
|
162
130
|
|
|
163
131
|
export { TreeItem };
|