@iyulab/components 0.1.2 → 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 -11
- 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 +4 -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 +27 -0
- package/dist/components/progress-bar/ProgressBar.js +99 -0
- package/dist/components/progress-bar/ProgressBar.styles.d.ts +1 -0
- package/dist/components/progress-bar/ProgressBar.styles.js +73 -0
- package/dist/components/progress-bar/index.d.ts +7 -0
- package/dist/components/progress-ring/ProgressRing.d.ts +3 -1
- package/dist/components/progress-ring/ProgressRing.js +18 -15
- 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 +37 -0
- package/dist/components/tree/Tree.js +131 -0
- package/dist/components/tree/Tree.styles.d.ts +1 -0
- package/dist/components/tree/Tree.styles.js +26 -0
- package/dist/components/tree/index.d.ts +3 -0
- package/dist/components/tree-item/TreeItem.d.ts +33 -0
- package/dist/components/tree-item/TreeItem.js +131 -0
- package/dist/components/tree-item/TreeItem.styles.d.ts +1 -0
- package/dist/components/tree-item/TreeItem.styles.js +66 -0
- package/dist/components/tree-item/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/integrations/react/UDivider.d.ts +8 -0
- package/dist/integrations/react/UDivider.js +10 -0
- package/dist/integrations/react/UProgressBar.d.ts +8 -0
- package/dist/integrations/react/UProgressBar.js +10 -0
- package/dist/integrations/react/UTree.d.ts +8 -0
- package/dist/integrations/react/UTree.js +10 -0
- package/dist/integrations/react/UTreeItem.d.ts +8 -0
- package/dist/integrations/react/UTreeItem.js +10 -0
- package/dist/integrations/react/index.d.ts +4 -0
- package/dist/integrations/react/index.js +4 -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 +18 -15
- 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
|
@@ -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,25 +78,30 @@ 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);
|
|
88
86
|
super.disconnectedCallback();
|
|
89
87
|
}
|
|
88
|
+
willUpdate(changedProperties) {
|
|
89
|
+
super.willUpdate(changedProperties);
|
|
90
|
+
if (changedProperties.has("triggerSelectors") && this.triggerSelectors) {
|
|
91
|
+
this.triggers = findElementsBy(this, this.triggerSelectors);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
90
94
|
updated(changedProperties) {
|
|
91
95
|
super.updated(changedProperties);
|
|
92
|
-
if (changedProperties.has("triggers")
|
|
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 };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BaseElement } from '../BaseElement.js';
|
|
2
|
+
import { TreeItem } from '../tree-item/TreeItem.js';
|
|
3
|
+
/**
|
|
4
|
+
* Tree 컴포넌트는 계층적 데이터 구조를 표시하는 트리 뷰를 제공합니다.
|
|
5
|
+
* u-tree-item 컴포넌트를 자식으로 사용하여 중첩된 구조를 구성할 수 있습니다.
|
|
6
|
+
*/
|
|
7
|
+
export declare class Tree extends BaseElement {
|
|
8
|
+
static styles: import('lit').CSSResultGroup[];
|
|
9
|
+
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
+
private selectedItems;
|
|
11
|
+
treeItems: TreeItem[];
|
|
12
|
+
/** 트리가 비활성화 상태인지 여부입니다. */
|
|
13
|
+
disabled: boolean;
|
|
14
|
+
/** 다중 선택을 허용할지 여부입니다. */
|
|
15
|
+
multiple: boolean;
|
|
16
|
+
/** 선택 가능한 트리인지 여부입니다. */
|
|
17
|
+
selectable: boolean;
|
|
18
|
+
connectedCallback(): void;
|
|
19
|
+
disconnectedCallback(): void;
|
|
20
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
21
|
+
/** 트리 항목 선택 이벤트를 처리합니다. */
|
|
22
|
+
private handleItemSelect;
|
|
23
|
+
/** 트리 항목 확장/축소 이벤트를 처리합니다. */
|
|
24
|
+
private handleItemToggle;
|
|
25
|
+
/**
|
|
26
|
+
* 선택된 모든 항목을 반환합니다.
|
|
27
|
+
*/
|
|
28
|
+
getSelectedItems(): TreeItem[];
|
|
29
|
+
/**
|
|
30
|
+
* 모든 선택을 해제합니다.
|
|
31
|
+
*/
|
|
32
|
+
clearSelection(): void;
|
|
33
|
+
/**
|
|
34
|
+
* 재귀적으로 모든 TreeItem을 가져옵니다.
|
|
35
|
+
*/
|
|
36
|
+
private getAllTreeItems;
|
|
37
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { queryAssignedElements, property } from 'lit/decorators.js';
|
|
3
|
+
import { BaseElement } from '../BaseElement.js';
|
|
4
|
+
import { TreeItem } from '../tree-item/TreeItem.js';
|
|
5
|
+
import { styles } from './Tree.styles.js';
|
|
6
|
+
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
9
|
+
var result = void 0 ;
|
|
10
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
|
+
if (decorator = decorators[i])
|
|
12
|
+
result = (decorator(target, key, result) ) || result;
|
|
13
|
+
if (result) __defProp(target, key, result);
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
class Tree extends BaseElement {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.selectedItems = /* @__PURE__ */ new Set();
|
|
20
|
+
this.disabled = false;
|
|
21
|
+
this.multiple = false;
|
|
22
|
+
this.selectable = true;
|
|
23
|
+
/** 트리 항목 선택 이벤트를 처리합니다. */
|
|
24
|
+
this.handleItemSelect = (e) => {
|
|
25
|
+
if (!this.selectable || this.disabled) {
|
|
26
|
+
e.stopPropagation();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const item = e.detail.item;
|
|
30
|
+
if (!this.multiple) {
|
|
31
|
+
this.selectedItems.forEach((selectedItem) => {
|
|
32
|
+
if (selectedItem !== item) {
|
|
33
|
+
selectedItem.selected = false;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
this.selectedItems.clear();
|
|
37
|
+
}
|
|
38
|
+
if (item.selected) {
|
|
39
|
+
this.selectedItems.add(item);
|
|
40
|
+
} else {
|
|
41
|
+
this.selectedItems.delete(item);
|
|
42
|
+
}
|
|
43
|
+
this.emit("u-tree-select", {
|
|
44
|
+
value: item.value,
|
|
45
|
+
item,
|
|
46
|
+
selectedItems: Array.from(this.selectedItems)
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
/** 트리 항목 확장/축소 이벤트를 처리합니다. */
|
|
50
|
+
this.handleItemToggle = (e) => {
|
|
51
|
+
if (this.disabled) {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const item = e.detail.item;
|
|
56
|
+
this.emit("u-tree-toggle", {
|
|
57
|
+
expanded: item.expanded,
|
|
58
|
+
item
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
static {
|
|
63
|
+
this.styles = [super.styles, styles];
|
|
64
|
+
}
|
|
65
|
+
static {
|
|
66
|
+
this.dependencies = {
|
|
67
|
+
"u-tree-item": TreeItem
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
connectedCallback() {
|
|
71
|
+
super.connectedCallback();
|
|
72
|
+
this.setAttribute("role", "tree");
|
|
73
|
+
this.addEventListener("u-select", this.handleItemSelect);
|
|
74
|
+
this.addEventListener("u-toggle", this.handleItemToggle);
|
|
75
|
+
}
|
|
76
|
+
disconnectedCallback() {
|
|
77
|
+
super.disconnectedCallback();
|
|
78
|
+
this.removeEventListener("u-select", this.handleItemSelect);
|
|
79
|
+
this.removeEventListener("u-toggle", this.handleItemToggle);
|
|
80
|
+
}
|
|
81
|
+
render() {
|
|
82
|
+
return html`
|
|
83
|
+
<div class="container">
|
|
84
|
+
<slot></slot>
|
|
85
|
+
</div>
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 선택된 모든 항목을 반환합니다.
|
|
90
|
+
*/
|
|
91
|
+
getSelectedItems() {
|
|
92
|
+
return Array.from(this.selectedItems);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 모든 선택을 해제합니다.
|
|
96
|
+
*/
|
|
97
|
+
clearSelection() {
|
|
98
|
+
this.selectedItems.forEach((item) => {
|
|
99
|
+
item.selected = false;
|
|
100
|
+
});
|
|
101
|
+
this.selectedItems.clear();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 재귀적으로 모든 TreeItem을 가져옵니다.
|
|
105
|
+
*/
|
|
106
|
+
getAllTreeItems(items = this.treeItems) {
|
|
107
|
+
let allItems = [];
|
|
108
|
+
items.forEach((item) => {
|
|
109
|
+
if (item instanceof TreeItem) {
|
|
110
|
+
allItems.push(item);
|
|
111
|
+
const childItems = this.getAllTreeItems(item.childrenItems);
|
|
112
|
+
allItems = allItems.concat(childItems);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
return allItems;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
__decorateClass([
|
|
119
|
+
queryAssignedElements({ selector: "u-tree-item" })
|
|
120
|
+
], Tree.prototype, "treeItems");
|
|
121
|
+
__decorateClass([
|
|
122
|
+
property({ type: Boolean, reflect: true })
|
|
123
|
+
], Tree.prototype, "disabled");
|
|
124
|
+
__decorateClass([
|
|
125
|
+
property({ type: Boolean })
|
|
126
|
+
], Tree.prototype, "multiple");
|
|
127
|
+
__decorateClass([
|
|
128
|
+
property({ type: Boolean })
|
|
129
|
+
], Tree.prototype, "selectable");
|
|
130
|
+
|
|
131
|
+
export { Tree };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import('lit').CSSResult;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
const styles = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
min-width: 0;
|
|
7
|
+
width: 100%;
|
|
8
|
+
padding: 4px;
|
|
9
|
+
background-color: transparent;
|
|
10
|
+
border-radius: 4px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:host([disabled]) {
|
|
14
|
+
opacity: 0.5;
|
|
15
|
+
pointer-events: none;
|
|
16
|
+
cursor: not-allowed;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.container {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
gap: 2px;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
export { styles };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PropertyValues } from 'lit';
|
|
2
|
+
import { BaseElement } from '../BaseElement.js';
|
|
3
|
+
/**
|
|
4
|
+
* TreeItem 컴포넌트는 트리의 개별 노드를 나타냅니다.
|
|
5
|
+
* u-tree 컴포넌트와 함께 사용되며, 중첩된 구조를 지원합니다.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TreeItem extends BaseElement {
|
|
8
|
+
static styles: import('lit').CSSResultGroup[];
|
|
9
|
+
static dependencies: Record<string, typeof BaseElement>;
|
|
10
|
+
headerEl: HTMLElement;
|
|
11
|
+
childrenItems: TreeItem[];
|
|
12
|
+
/** 트리 항목이 리프 노드인지 여부입니다. */
|
|
13
|
+
leaf: boolean;
|
|
14
|
+
/** 트리 항목의 들여쓰기 레벨입니다. */
|
|
15
|
+
level: number;
|
|
16
|
+
/** 트리 항목이 비활성화 상태인지 여부입니다. */
|
|
17
|
+
disabled: boolean;
|
|
18
|
+
/** 트리 항목이 선택된 상태인지 여부입니다. */
|
|
19
|
+
selected: boolean;
|
|
20
|
+
/** 트리 항목이 확장된 상태인지 여부입니다. */
|
|
21
|
+
expanded: boolean;
|
|
22
|
+
/** 트리 항목의 값입니다. */
|
|
23
|
+
value: string;
|
|
24
|
+
connectedCallback(): void;
|
|
25
|
+
protected updated(changedProperties: PropertyValues): void;
|
|
26
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
27
|
+
/** 슬롯 변경 시 헤더용 노드와 자식 노드 분리 */
|
|
28
|
+
private handleSlotChange;
|
|
29
|
+
/** 자식 슬롯 변경 시 자식 노드 재설정 */
|
|
30
|
+
private handleChildrenSlotChange;
|
|
31
|
+
/** 헤더 클릭 이벤트를 처리합니다. */
|
|
32
|
+
private handleHeaderClick;
|
|
33
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { query, queryAssignedElements, state, property } from 'lit/decorators.js';
|
|
3
|
+
import { BaseElement } from '../BaseElement.js';
|
|
4
|
+
import { Icon } from '../icon/Icon.js';
|
|
5
|
+
import { styles } from './TreeItem.styles.js';
|
|
6
|
+
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
9
|
+
var result = void 0 ;
|
|
10
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
|
+
if (decorator = decorators[i])
|
|
12
|
+
result = (decorator(target, key, result) ) || result;
|
|
13
|
+
if (result) __defProp(target, key, result);
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
const _TreeItem = class _TreeItem extends BaseElement {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.leaf = true;
|
|
20
|
+
this.level = 0;
|
|
21
|
+
this.disabled = false;
|
|
22
|
+
this.selected = false;
|
|
23
|
+
this.expanded = false;
|
|
24
|
+
this.value = "";
|
|
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
|
+
};
|
|
42
|
+
/** 헤더 클릭 이벤트를 처리합니다. */
|
|
43
|
+
this.handleHeaderClick = (e) => {
|
|
44
|
+
if (this.disabled) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
e.stopPropagation();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
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 });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
static {
|
|
59
|
+
this.styles = [super.styles, styles];
|
|
60
|
+
}
|
|
61
|
+
static {
|
|
62
|
+
this.dependencies = {
|
|
63
|
+
"u-icon": Icon
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
connectedCallback() {
|
|
67
|
+
super.connectedCallback();
|
|
68
|
+
this.setAttribute("role", "treeitem");
|
|
69
|
+
this.setAttribute("tabindex", this.disabled ? "-1" : "0");
|
|
70
|
+
}
|
|
71
|
+
updated(changedProperties) {
|
|
72
|
+
super.updated(changedProperties);
|
|
73
|
+
if (changedProperties.has("disabled")) {
|
|
74
|
+
this.setAttribute("tabindex", this.disabled ? "-1" : "0");
|
|
75
|
+
this.setAttribute("aria-disabled", this.disabled ? "true" : "false");
|
|
76
|
+
}
|
|
77
|
+
if (changedProperties.has("expanded")) {
|
|
78
|
+
this.setAttribute("aria-expanded", this.expanded ? "true" : "false");
|
|
79
|
+
}
|
|
80
|
+
if (changedProperties.has("selected")) {
|
|
81
|
+
this.setAttribute("aria-selected", this.selected ? "true" : "false");
|
|
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
|
+
}
|
|
87
|
+
}
|
|
88
|
+
render() {
|
|
89
|
+
return html`
|
|
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>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="children" ?hidden=${!this.expanded}>
|
|
100
|
+
<slot name="children" @slotchange=${this.handleChildrenSlotChange}></slot>
|
|
101
|
+
</div>
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
__decorateClass([
|
|
106
|
+
query(".header")
|
|
107
|
+
], _TreeItem.prototype, "headerEl");
|
|
108
|
+
__decorateClass([
|
|
109
|
+
queryAssignedElements({ slot: "children", selector: "u-tree-item", flatten: true })
|
|
110
|
+
], _TreeItem.prototype, "childrenItems");
|
|
111
|
+
__decorateClass([
|
|
112
|
+
state()
|
|
113
|
+
], _TreeItem.prototype, "leaf");
|
|
114
|
+
__decorateClass([
|
|
115
|
+
state()
|
|
116
|
+
], _TreeItem.prototype, "level");
|
|
117
|
+
__decorateClass([
|
|
118
|
+
property({ type: Boolean, reflect: true })
|
|
119
|
+
], _TreeItem.prototype, "disabled");
|
|
120
|
+
__decorateClass([
|
|
121
|
+
property({ type: Boolean, reflect: true })
|
|
122
|
+
], _TreeItem.prototype, "selected");
|
|
123
|
+
__decorateClass([
|
|
124
|
+
property({ type: Boolean, reflect: true })
|
|
125
|
+
], _TreeItem.prototype, "expanded");
|
|
126
|
+
__decorateClass([
|
|
127
|
+
property({ type: String })
|
|
128
|
+
], _TreeItem.prototype, "value");
|
|
129
|
+
let TreeItem = _TreeItem;
|
|
130
|
+
|
|
131
|
+
export { TreeItem };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import('lit').CSSResult;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
const styles = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
|
|
7
|
+
--indent-size: 20px;
|
|
8
|
+
}
|
|
9
|
+
:host([disabled]) {
|
|
10
|
+
opacity: 0.5;
|
|
11
|
+
pointer-events: none;
|
|
12
|
+
cursor: not-allowed;
|
|
13
|
+
}
|
|
14
|
+
:host([disabled]) .header {
|
|
15
|
+
cursor: not-allowed;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.header {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: row;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 6px;
|
|
24
|
+
padding: 6px 8px;
|
|
25
|
+
line-height: 1.5;
|
|
26
|
+
border-radius: 4px;
|
|
27
|
+
background-color: transparent;
|
|
28
|
+
transition: background-color 0.2s ease;
|
|
29
|
+
user-select: none;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
}
|
|
32
|
+
:host(:not([disabled])) .header:hover {
|
|
33
|
+
background-color: var(--u-bg-color-hover, #f5f5f5);
|
|
34
|
+
}
|
|
35
|
+
:host([selected]) .header {
|
|
36
|
+
color: var(--u-blue-600, #0066cc);
|
|
37
|
+
background-color: var(--u-blue-0, #e8f4f8);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.expand-icon {
|
|
41
|
+
transition: transform 0.2s ease, color 0.2s ease;
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
slot[name="prefix"],
|
|
46
|
+
slot[name="suffix"] {
|
|
47
|
+
display: inline-flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
}
|
|
51
|
+
slot:not([name]) {
|
|
52
|
+
flex: 1;
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: flex-start;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
text-overflow: ellipsis;
|
|
58
|
+
white-space: nowrap;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.children {
|
|
62
|
+
display: block;
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
export { styles };
|
package/dist/index.js
CHANGED
|
@@ -2,16 +2,20 @@ export { Alert } from './components/alert/Alert.js';
|
|
|
2
2
|
export { Button } from './components/button/Button.js';
|
|
3
3
|
export { ContextMenu } from './components/context-menu/ContextMenu.js';
|
|
4
4
|
export { Dialog } from './components/dialog/Dialog.js';
|
|
5
|
+
export { Divider } from './components/divider/Divider.js';
|
|
5
6
|
export { Form } from './components/form/Form.js';
|
|
6
7
|
export { Icon } from './components/icon/Icon.js';
|
|
7
8
|
export { IconButton } from './components/icon-button/IconButton.js';
|
|
8
9
|
export { Input } from './components/input/Input.js';
|
|
9
10
|
export { Menu } from './components/menu/Menu.js';
|
|
10
11
|
export { Panel } from './components/panel/Panel.js';
|
|
12
|
+
export { ProgressBar } from './components/progress-bar/ProgressBar.js';
|
|
11
13
|
export { ProgressRing } from './components/progress-ring/ProgressRing.js';
|
|
12
14
|
export { Spinner } from './components/spinner/Spinner.js';
|
|
13
15
|
export { SplitPanel } from './components/split-panel/SplitPanel.js';
|
|
14
16
|
export { Tooltip } from './components/tooltip/Tooltip.js';
|
|
17
|
+
export { Tree } from './components/tree/Tree.js';
|
|
18
|
+
export { TreeItem } from './components/tree-item/TreeItem.js';
|
|
15
19
|
export { BrowserStorage } from './utilities/BrowserStorage.js';
|
|
16
20
|
export { getPropertyMeta, propertyMeta, setPropertyMeta } from './utilities/decorators.js';
|
|
17
21
|
export { notifier } from './utilities/notifier.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Divider } from '../../components/divider/index';
|
|
3
|
+
|
|
4
|
+
export declare const UDivider: React.ForwardRefExoticComponent<
|
|
5
|
+
Partial<Divider> & React.HTMLAttributes<Divider>
|
|
6
|
+
>;
|
|
7
|
+
|
|
8
|
+
export type UDividerProps = React.ComponentProps<typeof UDivider>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createComponent } from '@lit/react';
|
|
3
|
+
import { Divider } from '../../components/divider/index';
|
|
4
|
+
|
|
5
|
+
export const UDivider = createComponent({
|
|
6
|
+
react: React,
|
|
7
|
+
tagName: 'u-divider',
|
|
8
|
+
elementClass: Divider,
|
|
9
|
+
events: {}
|
|
10
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ProgressBar } from '../../components/progress-bar/index';
|
|
3
|
+
|
|
4
|
+
export declare const UProgressBar: React.ForwardRefExoticComponent<
|
|
5
|
+
Partial<ProgressBar> & React.HTMLAttributes<ProgressBar>
|
|
6
|
+
>;
|
|
7
|
+
|
|
8
|
+
export type UProgressBarProps = React.ComponentProps<typeof UProgressBar>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createComponent } from '@lit/react';
|
|
3
|
+
import { ProgressBar } from '../../components/progress-bar/index';
|
|
4
|
+
|
|
5
|
+
export const UProgressBar = createComponent({
|
|
6
|
+
react: React,
|
|
7
|
+
tagName: 'u-progress-bar',
|
|
8
|
+
elementClass: ProgressBar,
|
|
9
|
+
events: {}
|
|
10
|
+
});
|