@iyulab/components 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +242 -0
- package/LICENSE +1 -1
- package/README.md +33 -1
- package/dist/components/UOverlayElement.d.ts +18 -0
- package/dist/components/UOverlayElement.js +24 -0
- package/dist/components/badge/UBadge.d.ts +5 -0
- package/dist/components/badge/UBadge.js +9 -0
- package/dist/components/badge/UBadge.styles.js +6 -0
- package/dist/components/dialog/UDialog.styles.js +1 -1
- package/dist/components/drawer/UDrawer.styles.js +1 -1
- package/dist/components/expander/UExpander.d.ts +38 -0
- package/dist/components/expander/UExpander.js +78 -0
- package/dist/components/expander/UExpander.styles.d.ts +1 -0
- package/dist/components/expander/UExpander.styles.js +95 -0
- package/dist/components/field/UField.styles.js +15 -0
- package/dist/components/icon/UIcon.d.ts +17 -4
- package/dist/components/icon/UIcon.js +9 -6
- package/dist/components/panel/UPanel.d.ts +0 -2
- package/dist/components/panel/UPanel.js +0 -5
- package/dist/components/skeleton/USkeleton.d.ts +7 -0
- package/dist/components/skeleton/USkeleton.js +7 -1
- package/dist/components/skeleton/USkeleton.styles.js +64 -0
- package/dist/components/tab-panel/UTabPanel.d.ts +4 -2
- package/dist/components/tab-panel/UTabPanel.js +0 -5
- package/dist/components/tag/UTag.d.ts +7 -0
- package/dist/components/tag/UTag.js +10 -1
- package/dist/components/tag/UTag.styles.js +4 -0
- package/dist/components/text/UText.d.ts +38 -0
- package/dist/components/text/UText.js +45 -0
- package/dist/components/text/UText.styles.d.ts +1 -0
- package/dist/components/text/UText.styles.js +91 -0
- package/dist/components/tree/UTree.d.ts +4 -2
- package/dist/components/tree/UTree.js +0 -5
- package/dist/components/tree-item/UTreeItem.d.ts +4 -1
- package/dist/components/tree-item/UTreeItem.js +0 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/react/UExpander.d.ts +16 -0
- package/dist/react/UExpander.js +13 -0
- package/dist/react/UText.d.ts +12 -0
- package/dist/react/UText.js +10 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +2 -0
- package/dist/utilities/Dialog.js +1 -1
- package/dist/utilities/Locale.d.ts +34 -0
- package/dist/utilities/Locale.js +43 -6
- package/dist/utilities/Theme.d.ts +37 -0
- package/dist/utilities/Theme.js +65 -0
- package/dist/utilities/accent.d.ts +52 -0
- package/dist/utilities/accent.js +127 -0
- package/dist/utilities/icons.js +1 -1
- package/dist/utilities/statusIcon.d.ts +31 -0
- package/dist/utilities/statusIcon.js +34 -0
- package/package.json +5 -3
- package/skills/iyulab-components/SKILL.md +4 -1
- package/skills/iyulab-components/references/components/badge.md +2 -1
- package/skills/iyulab-components/references/components/button.md +3 -1
- package/skills/iyulab-components/references/components/copy-button.md +80 -0
- package/skills/iyulab-components/references/components/drawer.md +30 -0
- package/skills/iyulab-components/references/components/expander.md +70 -0
- package/skills/iyulab-components/references/components/icon.md +12 -0
- package/skills/iyulab-components/references/components/input.md +6 -0
- package/skills/iyulab-components/references/components/panel.md +6 -4
- package/skills/iyulab-components/references/components/skeleton.md +12 -0
- package/skills/iyulab-components/references/components/tab-panel.md +4 -5
- package/skills/iyulab-components/references/components/tag.md +18 -1
- package/skills/iyulab-components/references/components/text.md +79 -0
- package/skills/iyulab-components/references/components/textarea.md +5 -0
- package/skills/iyulab-components/references/components/tree.md +2 -4
- package/skills/iyulab-components/references/usage.md +73 -2
- package/skills/iyulab-components/references/utilities/theme.md +23 -4
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
//#region src/components/expander/UExpander.styles.ts
|
|
3
|
+
var styles = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
}
|
|
7
|
+
:host([disabled]) {
|
|
8
|
+
opacity: 0.5;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* ⚠테두리·면은 :host 가 아니라 내부 래퍼가 그린다 — :host 에 두면 소비 앱의 CSS
|
|
12
|
+
리셋(* { border: 0 })이 «에러 없이» 지운다(Tailwind preflight 가 가장 흔한 경우다).
|
|
13
|
+
이 리포는 그 결함을 9개 컴포넌트에서 이미 걷어냈고 회귀 테스트가 목록을 0 으로 잠근다
|
|
14
|
+
— tests/build/host-layout-reset.test.ts */
|
|
15
|
+
.frame {
|
|
16
|
+
border: 1px solid var(--u-border-color, #E0E0E0);
|
|
17
|
+
border-radius: var(--u-radius-md, 4px);
|
|
18
|
+
background-color: var(--u-bg-color, #FFFFFF);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.header {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 0.5rem;
|
|
25
|
+
width: 100%;
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
padding: var(--u-space-sm, 8px) var(--u-space-md, 12px);
|
|
28
|
+
border: none;
|
|
29
|
+
border-radius: inherit;
|
|
30
|
+
background: none;
|
|
31
|
+
color: var(--u-txt-color, #212121);
|
|
32
|
+
font: inherit;
|
|
33
|
+
font-size: var(--u-text-body-size, 14px);
|
|
34
|
+
font-weight: var(--u-text-subtitle-weight, 600);
|
|
35
|
+
text-align: start;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
}
|
|
38
|
+
.header:disabled {
|
|
39
|
+
cursor: default;
|
|
40
|
+
}
|
|
41
|
+
.header:focus-visible {
|
|
42
|
+
outline: 2px solid var(--u-primary-color-strong, #1565C0);
|
|
43
|
+
outline-offset: -2px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.icon {
|
|
47
|
+
flex: none;
|
|
48
|
+
color: var(--u-txt-color-weak, #757575);
|
|
49
|
+
transition: transform var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
|
|
50
|
+
}
|
|
51
|
+
:host([open]) .icon {
|
|
52
|
+
transform: rotate(90deg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.label {
|
|
56
|
+
flex: 1 1 auto;
|
|
57
|
+
min-width: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* 높이 애니메이션은 grid 트랙(0fr ↔ 1fr)으로 한다 — 콘텐츠 높이를 JS 로 재지 않는다.
|
|
61
|
+
⚠전환을 지원하지 않는 엔진에서는 «즉시» 열리고 닫힐 뿐 접힘 자체는 성립한다
|
|
62
|
+
(0fr 은 그 엔진에서도 유효한 트랙 크기다).
|
|
63
|
+
★visibility 를 함께 옮기는 것이 요점이다 — overflow: hidden 만으로는 접힌 콘텐츠가
|
|
64
|
+
여전히 접근성 트리와 탭 순서에 남는다. */
|
|
65
|
+
.content {
|
|
66
|
+
display: grid;
|
|
67
|
+
grid-template-rows: 0fr;
|
|
68
|
+
visibility: hidden;
|
|
69
|
+
transition:
|
|
70
|
+
grid-template-rows var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)),
|
|
71
|
+
visibility var(--u-duration-normal, 220ms);
|
|
72
|
+
}
|
|
73
|
+
:host([open]) .content {
|
|
74
|
+
grid-template-rows: 1fr;
|
|
75
|
+
visibility: visible;
|
|
76
|
+
}
|
|
77
|
+
.inner {
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
}
|
|
80
|
+
.body {
|
|
81
|
+
padding: 0 var(--u-space-md, 12px) var(--u-space-md, 12px);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* 이 전환은 «장식»이다 — 접힘/펼침의 결과는 정지 상태에서도 그대로 읽힌다.
|
|
85
|
+
⚠시트의 reduce 규칙(지속시간 축 0)에 기대지 않고 여기서도 누른다: 소비자가 토큰
|
|
86
|
+
시트를 로드하지 않으면 use-site 폴백 리터럴이 살아남아 그 규칙이 닿지 못한다. */
|
|
87
|
+
@media (prefers-reduced-motion: reduce) {
|
|
88
|
+
.icon,
|
|
89
|
+
.content {
|
|
90
|
+
transition-duration: 0s;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
//#endregion
|
|
95
|
+
export { styles };
|
|
@@ -15,6 +15,21 @@ var styles = css`
|
|
|
15
15
|
color: var(--u-danger-color-strong, #C62828);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/* 🔴**라벨을 단 컨트롤은 필드 폭을 채운다.**
|
|
19
|
+
컨트롤 자신의 기본값은 inline-block(자기 내용만큼)이 옳다 — 문장 안에 놓이는 경우가
|
|
20
|
+
있기 때문이다. 그러나 u-field 로 감싼 순간 그것은 **폼의 한 칸**이고, 칸마다 컨트롤이
|
|
21
|
+
제각각의 폭을 가지면 격자가 너덜너덜해진다. 실측: 같은 231px 칸 안에서 input 202 ·
|
|
22
|
+
select 71/92/108 · textarea 168 — **오른쪽 끝이 다섯 군데에서 다 달랐다.**
|
|
23
|
+
⇒ 라벨·설명·검증 문구의 배치를 책임지는 이 컴포넌트가 폭도 함께 정한다.
|
|
24
|
+
|
|
25
|
+
⚠소비자가 인라인 style 로 폭을 주면 그쪽이 이긴다(인라인 > ::slotted).
|
|
26
|
+
⚠이 주석에 백틱을 쓰지 말 것 — css 태그드 템플릿을 그 자리에서 끝낸다(이 파일이 실제로
|
|
27
|
+
그렇게 깨졌고, cycle-217 이 만든 타입 게이트가 잡았다). */
|
|
28
|
+
::slotted(*) {
|
|
29
|
+
width: 100%;
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
.header {
|
|
19
34
|
display: flex;
|
|
20
35
|
flex-direction: row;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { nothing } from 'lit';
|
|
2
1
|
import { UElement } from '../UElement.js';
|
|
3
2
|
export type IconLibrary = (string & {}) | "internal" | "tabler" | "heroicons" | "lucide" | "bootstrap";
|
|
4
3
|
/**
|
|
@@ -14,9 +13,23 @@ export declare class UIcon extends UElement {
|
|
|
14
13
|
lib?: IconLibrary;
|
|
15
14
|
/** 사용할 아이콘 이름을 지정합니다. */
|
|
16
15
|
name?: string;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/**
|
|
17
|
+
* 이름·URL 이 **해석되지 않을 때** 대신 그릴 SVG 원문.
|
|
18
|
+
*
|
|
19
|
+
* ★**«아이콘이 안 보인다»가 «자리 자체가 사라진다»가 되는 곳이 있다.** 사이드바가 접히면
|
|
20
|
+
* 라벨이 숨고 아이콘만 남는데, 그 아이콘이 해석에 실패하면 그 메뉴는 **누를 것이 없는
|
|
21
|
+
* 빈 줄**이 된다 — 이름이 잘못됐는지, 파일이 없는지, 아이콘을 안 준 것인지 화면에서
|
|
22
|
+
* 구분되지 않고 **탐색 수단이 통째로 사라진다.**
|
|
23
|
+
*
|
|
24
|
+
* ⇒ 그런 자리는 «없으면 안 그린다»가 아니라 **«없으면 대신 그린다»** 여야 한다.
|
|
25
|
+
* 해석 실패는 `name` 미지정 · 파일 없음(404) · SVG 파싱 실패를 **모두** 포함한다.
|
|
26
|
+
*
|
|
27
|
+
* ⚠소비자가 주는 값은 `sanitize()` 를 거친다(`name` 경로와 같은 처리).
|
|
28
|
+
*/
|
|
29
|
+
fallback?: string;
|
|
30
|
+
render(): import('lit-html/directive.js').DirectiveResult<typeof import('lit-html/directives/unsafe-html.js').UnsafeHTMLDirective>;
|
|
31
|
+
/** 해석 결과가 없으면 `fallback` 으로 대신한다. 둘 다 없을 때만 아무것도 그리지 않는다. */
|
|
32
|
+
private paint;
|
|
20
33
|
private resolve;
|
|
21
34
|
private sanitize;
|
|
22
35
|
}
|
|
@@ -14,13 +14,15 @@ var UIcon = class UIcon extends UElement {
|
|
|
14
14
|
}
|
|
15
15
|
render() {
|
|
16
16
|
if (this.src) return until(IconRegistry.resolveUrl(this.src).then((html) => {
|
|
17
|
-
|
|
18
|
-
return sanitized ? unsafeHTML(sanitized) : nothing;
|
|
17
|
+
return this.paint(this.sanitize(html));
|
|
19
18
|
}), nothing);
|
|
20
|
-
if (this.name) return until(this.resolve(this.name).then((html) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
if (this.name) return until(this.resolve(this.name).then((html) => this.paint(html)), nothing);
|
|
20
|
+
return this.paint(void 0);
|
|
21
|
+
}
|
|
22
|
+
/** 해석 결과가 없으면 `fallback` 으로 대신한다. 둘 다 없을 때만 아무것도 그리지 않는다. */
|
|
23
|
+
paint(html) {
|
|
24
|
+
const resolved = html ?? this.sanitize(this.fallback);
|
|
25
|
+
return resolved ? unsafeHTML(resolved) : nothing;
|
|
24
26
|
}
|
|
25
27
|
async resolve(name) {
|
|
26
28
|
let html = void 0;
|
|
@@ -50,6 +52,7 @@ var UIcon = class UIcon extends UElement {
|
|
|
50
52
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UIcon.prototype, "src", void 0);
|
|
51
53
|
__decorate([property({ type: String }), __decorateMetadata("design:type", Object)], UIcon.prototype, "lib", void 0);
|
|
52
54
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UIcon.prototype, "name", void 0);
|
|
55
|
+
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], UIcon.prototype, "fallback", void 0);
|
|
53
56
|
UIcon = __decorate([customElement("u-icon")], UIcon);
|
|
54
57
|
//#endregion
|
|
55
58
|
export { UIcon };
|
|
@@ -9,8 +9,6 @@ export declare class UPanel extends UElement {
|
|
|
9
9
|
static styles: import('lit').CSSResultGroup[];
|
|
10
10
|
/** 패널 비활성화 여부 */
|
|
11
11
|
disabled: boolean;
|
|
12
|
-
/** 패널 접기 가능 여부 */
|
|
13
|
-
collapsible: boolean;
|
|
14
12
|
/** 패널 고유값 (매칭 시 사용) */
|
|
15
13
|
value: string;
|
|
16
14
|
render(): import('lit-html').TemplateResult<1>;
|
|
@@ -9,7 +9,6 @@ var UPanel = class UPanel extends UElement {
|
|
|
9
9
|
constructor(..._args) {
|
|
10
10
|
super(..._args);
|
|
11
11
|
this.disabled = false;
|
|
12
|
-
this.collapsible = false;
|
|
13
12
|
this.value = "";
|
|
14
13
|
}
|
|
15
14
|
static {
|
|
@@ -23,10 +22,6 @@ __decorate([property({
|
|
|
23
22
|
type: Boolean,
|
|
24
23
|
reflect: true
|
|
25
24
|
}), __decorateMetadata("design:type", Object)], UPanel.prototype, "disabled", void 0);
|
|
26
|
-
__decorate([property({
|
|
27
|
-
type: Boolean,
|
|
28
|
-
reflect: true
|
|
29
|
-
}), __decorateMetadata("design:type", Object)], UPanel.prototype, "collapsible", void 0);
|
|
30
25
|
__decorate([property({
|
|
31
26
|
type: String,
|
|
32
27
|
reflect: true
|
|
@@ -22,6 +22,13 @@ export declare class USkeleton extends UElement {
|
|
|
22
22
|
width?: string;
|
|
23
23
|
/** 높이 (CSS 값) */
|
|
24
24
|
height?: string;
|
|
25
|
+
/**
|
|
26
|
+
* 여러 줄 자리표시자로 그릴 줄 수. **2 이상일 때만** 호스트가 «막대들의 통»이 되고,
|
|
27
|
+
* 마지막 줄은 짧게(`--skeleton-last-line-width`, 기본 60%) 그린다 — 문단의 끝을 그렇게 읽는다.
|
|
28
|
+
*
|
|
29
|
+
* ⚠**단일 막대(기본)의 모양은 바꾸지 않는다** — 이 속성이 없으면 종전과 완전히 같다.
|
|
30
|
+
*/
|
|
31
|
+
lines?: number;
|
|
25
32
|
protected updated(changedProperties: PropertyValues): void;
|
|
26
33
|
render(): import('lit-html').TemplateResult<1>;
|
|
27
34
|
}
|
|
@@ -20,7 +20,9 @@ var USkeleton = class USkeleton extends UElement {
|
|
|
20
20
|
if (changedProperties.has("height") && this.height) this.style.setProperty("--skeleton-height", this.height);
|
|
21
21
|
}
|
|
22
22
|
render() {
|
|
23
|
-
|
|
23
|
+
const n = this.lines ?? 0;
|
|
24
|
+
if (n < 2) return html`<slot></slot>`;
|
|
25
|
+
return html`${Array.from({ length: n }, () => html`<span class="line" part="line"></span>`)}`;
|
|
24
26
|
}
|
|
25
27
|
};
|
|
26
28
|
__decorate([property({
|
|
@@ -33,6 +35,10 @@ __decorate([property({
|
|
|
33
35
|
}), __decorateMetadata("design:type", Object)], USkeleton.prototype, "effect", void 0);
|
|
34
36
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], USkeleton.prototype, "width", void 0);
|
|
35
37
|
__decorate([property({ type: String }), __decorateMetadata("design:type", String)], USkeleton.prototype, "height", void 0);
|
|
38
|
+
__decorate([property({
|
|
39
|
+
type: Number,
|
|
40
|
+
reflect: true
|
|
41
|
+
}), __decorateMetadata("design:type", Number)], USkeleton.prototype, "lines", void 0);
|
|
36
42
|
USkeleton = __decorate([customElement("u-skeleton")], USkeleton);
|
|
37
43
|
//#endregion
|
|
38
44
|
export { USkeleton };
|
|
@@ -52,6 +52,70 @@ var styles = css`
|
|
|
52
52
|
transform: translateX(-100%);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/* === 여러 줄(lines) ===
|
|
56
|
+
기본(단일 막대)에서는 :host 자신이 막대다 — 그 모양을 바꾸지 않는다. lines 가 붙었을
|
|
57
|
+
때만 호스트가 «막대들의 통»이 되고, 색·모양·효과는 각 .line 이 받는다.
|
|
58
|
+
⚠마지막 줄을 짧게 만드는 것은 장식이 아니라 신호다 — 문단의 끝을 그렇게 읽는다. */
|
|
59
|
+
:host([lines]) {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
gap: var(--skeleton-line-gap, 0.5em);
|
|
63
|
+
height: auto;
|
|
64
|
+
background-color: transparent;
|
|
65
|
+
animation: none;
|
|
66
|
+
overflow: visible;
|
|
67
|
+
}
|
|
68
|
+
:host([lines])::after {
|
|
69
|
+
content: none;
|
|
70
|
+
}
|
|
71
|
+
:host([lines]) .line {
|
|
72
|
+
height: var(--skeleton-height);
|
|
73
|
+
background-color: var(--skeleton-color);
|
|
74
|
+
border-radius: inherit;
|
|
75
|
+
}
|
|
76
|
+
:host([lines]) .line:last-child {
|
|
77
|
+
width: var(--skeleton-last-line-width, 60%);
|
|
78
|
+
}
|
|
79
|
+
:host([lines][effect="pulse"]) .line {
|
|
80
|
+
animation: pulse 1.5s ease-in-out infinite;
|
|
81
|
+
}
|
|
82
|
+
:host([lines][effect="shimmer"]) .line {
|
|
83
|
+
position: relative;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
}
|
|
86
|
+
:host([lines][effect="shimmer"]) .line::after {
|
|
87
|
+
content: '';
|
|
88
|
+
position: absolute;
|
|
89
|
+
inset: 0;
|
|
90
|
+
background: linear-gradient(
|
|
91
|
+
90deg,
|
|
92
|
+
transparent,
|
|
93
|
+
var(--skeleton-shimmer-color),
|
|
94
|
+
transparent
|
|
95
|
+
);
|
|
96
|
+
animation: shimmer 1.5s infinite;
|
|
97
|
+
transform: translateX(-100%);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ★**장식만 멈춘다.**
|
|
101
|
+
시트의 reduce 규칙은 지속시간 축(--u-duration-*)을 0 으로 누르는 방식이라 animation
|
|
102
|
+
속성을 직접 쓰는 이 자리에는 닿지 않는다 — 그 규칙이 animation: none 으로 강제하지
|
|
103
|
+
않는 것은 의도다(로딩 스피너처럼 «회전 자체가 신호»인 움직임까지 죽이면 진행 여부를
|
|
104
|
+
알 수 없다).
|
|
105
|
+
|
|
106
|
+
스켈레톤은 다르다: **기본값이 이미 animation: none** 이고, 정지한 회색 블록이
|
|
107
|
+
«로딩 중»을 그대로 나른다. 즉 pulse/shimmer 는 **opt-in 장식**이고, WCAG 2.2.2 의
|
|
108
|
+
«움직임이 본질인 것» 예외에 해당하지 않는다.
|
|
109
|
+
⇒ 여기서만 멈춘다. u-spinner 는 건드리지 않는다. */
|
|
110
|
+
@media (prefers-reduced-motion: reduce) {
|
|
111
|
+
:host([effect="pulse"]),
|
|
112
|
+
:host([effect="shimmer"])::after,
|
|
113
|
+
:host([lines][effect="pulse"]) .line,
|
|
114
|
+
:host([lines][effect="shimmer"]) .line::after {
|
|
115
|
+
animation: none;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
55
119
|
@keyframes pulse {
|
|
56
120
|
0%, 100% {
|
|
57
121
|
opacity: 1;
|
|
@@ -29,8 +29,10 @@ export declare class UTabPanel extends UElement {
|
|
|
29
29
|
placement: TabPanelPlacement;
|
|
30
30
|
/** 선택된 탭값 */
|
|
31
31
|
value: string;
|
|
32
|
-
/**
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* 네이티브 전역 속성. ⚠**이 컴포넌트에 탭 재정렬 기능은 없다** — 브라우저의 드래그를
|
|
34
|
+
* 켤 뿐이고, 놓았을 때 순서를 바꾸는 코드는 존재한 적이 없다.
|
|
35
|
+
*/
|
|
34
36
|
draggable: boolean;
|
|
35
37
|
private tabs;
|
|
36
38
|
private panels;
|
|
@@ -14,7 +14,6 @@ var UTabPanel = class UTabPanel extends UElement {
|
|
|
14
14
|
this.variant = "line";
|
|
15
15
|
this.placement = "top";
|
|
16
16
|
this.value = "";
|
|
17
|
-
this.editable = false;
|
|
18
17
|
this.draggable = false;
|
|
19
18
|
this.tabs = [];
|
|
20
19
|
this.panels = [];
|
|
@@ -144,10 +143,6 @@ __decorate([property({
|
|
|
144
143
|
type: String,
|
|
145
144
|
reflect: true
|
|
146
145
|
}), __decorateMetadata("design:type", Object)], UTabPanel.prototype, "value", void 0);
|
|
147
|
-
__decorate([property({
|
|
148
|
-
type: Boolean,
|
|
149
|
-
reflect: true
|
|
150
|
-
}), __decorateMetadata("design:type", Object)], UTabPanel.prototype, "editable", void 0);
|
|
151
146
|
__decorate([property({
|
|
152
147
|
type: Boolean,
|
|
153
148
|
reflect: true
|
|
@@ -14,6 +14,7 @@ export type TagColor = "neutral" | "primary" | "info" | "success" | "warning" |
|
|
|
14
14
|
* @slot suffix - 태그 뒤에 표시할 콘텐츠
|
|
15
15
|
*
|
|
16
16
|
* @csspart content - 콘텐츠 영역
|
|
17
|
+
* @csspart icon - 상태 아이콘 (`icon` + 역할 색일 때만 렌더된다)
|
|
17
18
|
*
|
|
18
19
|
* @cssprop --tag-color - 텍스트 색상
|
|
19
20
|
* @cssprop --tag-bg-color - 배경 색상
|
|
@@ -31,6 +32,12 @@ export declare class UTag extends UElement {
|
|
|
31
32
|
color: TagColor;
|
|
32
33
|
/** 태그를 둥글게 표시합니다. */
|
|
33
34
|
rounded: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* 상태를 **색과 무관하게** 나르는 아이콘을 붙입니다(`info`·`success`·`warning`·`danger`).
|
|
37
|
+
* 색각 이상·흑백 인쇄에서 상태가 갈리게 하는 축입니다.
|
|
38
|
+
* 의미가 없는 색(`neutral`·`primary`·장식 축)에서는 아무것도 그리지 않습니다.
|
|
39
|
+
*/
|
|
40
|
+
icon: boolean;
|
|
34
41
|
render(): import('lit-html').TemplateResult<1>;
|
|
35
42
|
}
|
|
36
43
|
declare global {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { UElement } from "../UElement.js";
|
|
2
2
|
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
|
|
3
3
|
import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
|
|
4
|
+
import "../icon/UIcon.js";
|
|
5
|
+
import { statusIcon } from "../../utilities/statusIcon.js";
|
|
4
6
|
import { styles } from "./UTag.styles.js";
|
|
5
|
-
import { html } from "lit";
|
|
7
|
+
import { html, nothing } from "lit";
|
|
6
8
|
import { customElement, property } from "lit/decorators.js";
|
|
7
9
|
//#region src/components/tag/UTag.ts
|
|
8
10
|
var UTag = class UTag extends UElement {
|
|
@@ -11,13 +13,16 @@ var UTag = class UTag extends UElement {
|
|
|
11
13
|
this.variant = "filled";
|
|
12
14
|
this.color = "neutral";
|
|
13
15
|
this.rounded = false;
|
|
16
|
+
this.icon = false;
|
|
14
17
|
}
|
|
15
18
|
static {
|
|
16
19
|
this.styles = [super.styles, styles];
|
|
17
20
|
}
|
|
18
21
|
render() {
|
|
22
|
+
const iconName = this.icon ? statusIcon(this.color) : void 0;
|
|
19
23
|
return html`
|
|
20
24
|
<div class="base" part="base">
|
|
25
|
+
${iconName ? html`<u-icon class="icon" part="icon" lib="internal" name=${iconName}></u-icon>` : nothing}
|
|
21
26
|
<slot name="prefix"></slot>
|
|
22
27
|
<span class="content" part="content">
|
|
23
28
|
<slot></slot>
|
|
@@ -39,6 +44,10 @@ __decorate([property({
|
|
|
39
44
|
type: Boolean,
|
|
40
45
|
reflect: true
|
|
41
46
|
}), __decorateMetadata("design:type", Object)], UTag.prototype, "rounded", void 0);
|
|
47
|
+
__decorate([property({
|
|
48
|
+
type: Boolean,
|
|
49
|
+
reflect: true
|
|
50
|
+
}), __decorateMetadata("design:type", Object)], UTag.prototype, "icon", void 0);
|
|
42
51
|
UTag = __decorate([customElement("u-tag")], UTag);
|
|
43
52
|
//#endregion
|
|
44
53
|
export { UTag };
|
|
@@ -189,6 +189,10 @@ var styles = css`
|
|
|
189
189
|
border: 1px solid var(--tag-border-color);
|
|
190
190
|
border-radius: inherit;
|
|
191
191
|
}
|
|
192
|
+
/* 상태 아이콘 — .base 의 gap 이 간격을 정한다. */
|
|
193
|
+
.icon {
|
|
194
|
+
flex-shrink: 0;
|
|
195
|
+
}
|
|
192
196
|
:host([rounded]) {
|
|
193
197
|
border-radius: var(--u-radius-pill, 9999px);
|
|
194
198
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { UElement } from '../UElement.js';
|
|
2
|
+
export type TextVariant = "display" | "title" | "subtitle" | "body" | "label" | "caption" | "overline";
|
|
3
|
+
/** 중립 강조 축. **역할색이 아니다** — 역할색이 필요하면 그것은 별도 축이다. */
|
|
4
|
+
export type TextTone = "default" | "weak" | "strong" | "inverse";
|
|
5
|
+
/** 제목 단계. 값이 있으면 heading 으로 읽힌다. */
|
|
6
|
+
export type TextLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
7
|
+
/**
|
|
8
|
+
* 의미 타이포그래피 스케일(7단)을 마크업에서 쓰는 자리입니다.
|
|
9
|
+
*
|
|
10
|
+
* 시트는 단마다 **크기·굵기·행간·자간** 네 값을 갖고 있으나, 그 단을 *적용하는* 것이
|
|
11
|
+
* 없어 소비자는 자기 CSS 에서 타이포 토큰을 직접 참조해야 했습니다.
|
|
12
|
+
* 이 컴포넌트는 그 자리를 대신하며, **값을 새로 정의하지 않고 토큰만 읽습니다.**
|
|
13
|
+
*
|
|
14
|
+
* `level` 을 주면 섀도 루트에 실제 `<h1>`~`<h6>` 을 렌더하므로 heading 으로 읽힙니다
|
|
15
|
+
* (슬롯 텍스트가 접근가능 이름이 됩니다). 주지 않으면 `<p>` 입니다.
|
|
16
|
+
*
|
|
17
|
+
* ⚠ 시각 축(`variant`)과 의미 축(`level`)은 **독립**입니다 — 페이지의 두 번째 제목이
|
|
18
|
+
* 시각적으로 가장 클 수 있습니다(`level="2" variant="display"`).
|
|
19
|
+
*
|
|
20
|
+
* @slot - 텍스트 내용
|
|
21
|
+
*
|
|
22
|
+
* @csspart base - 렌더된 `<p>` 또는 `<h1>`~`<h6>` 요소
|
|
23
|
+
*/
|
|
24
|
+
export declare class UText extends UElement {
|
|
25
|
+
static styles: import('lit').CSSResultGroup[];
|
|
26
|
+
/** 의미 타이포그래피 단계 */
|
|
27
|
+
variant: TextVariant;
|
|
28
|
+
/** 중립 강조 축 (역할색이 아니다) */
|
|
29
|
+
tone: TextTone;
|
|
30
|
+
/** 제목 단계. 지정하면 heading 요소로 렌더된다 */
|
|
31
|
+
level?: TextLevel;
|
|
32
|
+
protected render(): import('lit-html').TemplateResult;
|
|
33
|
+
}
|
|
34
|
+
declare global {
|
|
35
|
+
interface HTMLElementTagNameMap {
|
|
36
|
+
'u-text': UText;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { UElement } from "../UElement.js";
|
|
2
|
+
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
|
|
3
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
|
|
4
|
+
import { styles } from "./UText.styles.js";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
|
+
import { html, literal } from "lit/static-html.js";
|
|
7
|
+
//#region src/components/text/UText.ts
|
|
8
|
+
var PARAGRAPH = literal`p`;
|
|
9
|
+
var HEADINGS = {
|
|
10
|
+
1: literal`h1`,
|
|
11
|
+
2: literal`h2`,
|
|
12
|
+
3: literal`h3`,
|
|
13
|
+
4: literal`h4`,
|
|
14
|
+
5: literal`h5`,
|
|
15
|
+
6: literal`h6`
|
|
16
|
+
};
|
|
17
|
+
var UText = class UText extends UElement {
|
|
18
|
+
constructor(..._args) {
|
|
19
|
+
super(..._args);
|
|
20
|
+
this.variant = "body";
|
|
21
|
+
this.tone = "default";
|
|
22
|
+
}
|
|
23
|
+
static {
|
|
24
|
+
this.styles = [super.styles, styles];
|
|
25
|
+
}
|
|
26
|
+
render() {
|
|
27
|
+
const tag = this.level && HEADINGS[this.level] ? HEADINGS[this.level] : PARAGRAPH;
|
|
28
|
+
return html`<${tag} class="text" part="base"><slot></slot></${tag}>`;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
__decorate([property({
|
|
32
|
+
type: String,
|
|
33
|
+
reflect: true
|
|
34
|
+
}), __decorateMetadata("design:type", Object)], UText.prototype, "variant", void 0);
|
|
35
|
+
__decorate([property({
|
|
36
|
+
type: String,
|
|
37
|
+
reflect: true
|
|
38
|
+
}), __decorateMetadata("design:type", Object)], UText.prototype, "tone", void 0);
|
|
39
|
+
__decorate([property({
|
|
40
|
+
type: Number,
|
|
41
|
+
reflect: true
|
|
42
|
+
}), __decorateMetadata("design:type", Object)], UText.prototype, "level", void 0);
|
|
43
|
+
UText = __decorate([customElement("u-text")], UText);
|
|
44
|
+
//#endregion
|
|
45
|
+
export { UText };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const styles: import('lit').CSSResult;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
//#region src/components/text/UText.styles.ts
|
|
3
|
+
var styles = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
color: var(--u-txt-color, #212121);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* 기본은 body 다. :host([variant="body"]) 규칙을 따로 두지 않는 이유는
|
|
11
|
+
* 값이 같기 때문이며, 부수 효과로 **알 수 없는 variant 가 body 로 흐른다**
|
|
12
|
+
* (조용히 폰트가 사라지는 것보다 낫다).
|
|
13
|
+
*/
|
|
14
|
+
.text {
|
|
15
|
+
margin: 0;
|
|
16
|
+
font-family: inherit;
|
|
17
|
+
font-size: var(--u-text-body-size, 14px);
|
|
18
|
+
font-weight: var(--u-text-body-weight, 400);
|
|
19
|
+
line-height: var(--u-text-body-leading, 1.6);
|
|
20
|
+
letter-spacing: var(--u-text-body-tracking, 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:host([variant="display"]) .text {
|
|
24
|
+
font-size: var(--u-text-display-size, 26px);
|
|
25
|
+
font-weight: var(--u-text-display-weight, 700);
|
|
26
|
+
line-height: var(--u-text-display-leading, 1.4);
|
|
27
|
+
letter-spacing: var(--u-text-display-tracking, -0.02em);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host([variant="title"]) .text {
|
|
31
|
+
font-size: var(--u-text-title-size, 20px);
|
|
32
|
+
font-weight: var(--u-text-title-weight, 700);
|
|
33
|
+
line-height: var(--u-text-title-leading, 1.45);
|
|
34
|
+
letter-spacing: var(--u-text-title-tracking, -0.01em);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:host([variant="subtitle"]) .text {
|
|
38
|
+
font-size: var(--u-text-subtitle-size, 16px);
|
|
39
|
+
font-weight: var(--u-text-subtitle-weight, 600);
|
|
40
|
+
line-height: var(--u-text-subtitle-leading, 1.5);
|
|
41
|
+
letter-spacing: var(--u-text-subtitle-tracking, 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:host([variant="label"]) .text {
|
|
45
|
+
font-size: var(--u-text-label-size, 13px);
|
|
46
|
+
font-weight: var(--u-text-label-weight, 600);
|
|
47
|
+
line-height: var(--u-text-label-leading, 1.5);
|
|
48
|
+
letter-spacing: var(--u-text-label-tracking, 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:host([variant="caption"]) .text {
|
|
52
|
+
font-size: var(--u-text-caption-size, 12px);
|
|
53
|
+
font-weight: var(--u-text-caption-weight, 400);
|
|
54
|
+
line-height: var(--u-text-caption-leading, 1.5);
|
|
55
|
+
letter-spacing: var(--u-text-caption-tracking, 0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* ⚠ overline 에 text-transform: uppercase 를 붙이지 않는다.
|
|
60
|
+
*
|
|
61
|
+
* 눈썹 텍스트의 관습이긴 하나 ⑴시트가 정의하는 것은 네 속성뿐이라 다섯 번째를 여기서
|
|
62
|
+
* 정하면 이 컴포넌트가 «두 번째 정의처»가 되고 ⑵소비자가 쓴 글자를 조용히 바꾸며
|
|
63
|
+
* ⑶CJK 에는 아무 효과가 없어 **같은 단이 언어에 따라 다르게 보인다.**
|
|
64
|
+
* 대문자가 필요한 자리는 그 자리가 정한다.
|
|
65
|
+
*/
|
|
66
|
+
:host([variant="overline"]) .text {
|
|
67
|
+
font-size: var(--u-text-overline-size, 11px);
|
|
68
|
+
font-weight: var(--u-text-overline-weight, 700);
|
|
69
|
+
line-height: var(--u-text-overline-leading, 1.45);
|
|
70
|
+
letter-spacing: var(--u-text-overline-tracking, 0.06em);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* tone 은 **중립 강조 축**이다 — 역할색(info/success/danger…)이 아니다.
|
|
75
|
+
* 소비앱 실측에서 나온 색 다섯 중 셋이 이 축이었고, 나머지 둘은 링크와
|
|
76
|
+
* 콜아웃 박스라 u-text 의 문제가 아니었다.
|
|
77
|
+
*/
|
|
78
|
+
:host([tone="weak"]) {
|
|
79
|
+
color: var(--u-txt-color-weak, #757575);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:host([tone="strong"]) {
|
|
83
|
+
color: var(--u-txt-color-strong, #000000);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:host([tone="inverse"]) {
|
|
87
|
+
color: var(--u-txt-color-inverse, #FFFFFF);
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
//#endregion
|
|
91
|
+
export { styles };
|
|
@@ -34,9 +34,11 @@ export declare class UTree extends UElement {
|
|
|
34
34
|
checkCascade: boolean;
|
|
35
35
|
/** 트리 펼치기 트리거 방식 */
|
|
36
36
|
trigger: TreeItemTrigger;
|
|
37
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* 네이티브 전역 속성. ⚠**이 컴포넌트에 드래그 앤드 드롭 구현은 없다** — 브라우저의
|
|
39
|
+
* 드래그를 켤 뿐이고, 드롭을 받아 트리를 재배치하는 코드는 존재한 적이 없다.
|
|
40
|
+
*/
|
|
38
41
|
draggable: boolean;
|
|
39
|
-
droppable: boolean;
|
|
40
42
|
private expandIcon?;
|
|
41
43
|
private collapseIcon?;
|
|
42
44
|
private anchor;
|
|
@@ -16,7 +16,6 @@ var UTree = class UTree extends UElement {
|
|
|
16
16
|
this.checkCascade = false;
|
|
17
17
|
this.trigger = "item";
|
|
18
18
|
this.draggable = false;
|
|
19
|
-
this.droppable = false;
|
|
20
19
|
this.anchor = null;
|
|
21
20
|
this._items = [];
|
|
22
21
|
this.handleSlotChange = (e) => {
|
|
@@ -300,10 +299,6 @@ __decorate([property({
|
|
|
300
299
|
type: Boolean,
|
|
301
300
|
reflect: true
|
|
302
301
|
}), __decorateMetadata("design:type", Boolean)], UTree.prototype, "draggable", void 0);
|
|
303
|
-
__decorate([property({
|
|
304
|
-
type: Boolean,
|
|
305
|
-
reflect: true
|
|
306
|
-
}), __decorateMetadata("design:type", Boolean)], UTree.prototype, "droppable", void 0);
|
|
307
302
|
__decorate([state(), __decorateMetadata("design:type", typeof Node === "undefined" ? Object : Node)], UTree.prototype, "expandIcon", void 0);
|
|
308
303
|
__decorate([state(), __decorateMetadata("design:type", typeof Node === "undefined" ? Object : Node)], UTree.prototype, "collapseIcon", void 0);
|
|
309
304
|
UTree = __decorate([customElement("u-tree")], UTree);
|
|
@@ -35,8 +35,11 @@ export declare class UTreeItem extends UElement {
|
|
|
35
35
|
trigger: TreeItemTrigger;
|
|
36
36
|
/** 아이템의 고유값 */
|
|
37
37
|
value: string;
|
|
38
|
+
/**
|
|
39
|
+
* 네이티브 전역 속성. ⚠**드롭을 받아 트리를 재배치하는 구현은 없다** — `UTree` 의 같은
|
|
40
|
+
* 속성과 같은 상태다.
|
|
41
|
+
*/
|
|
38
42
|
draggable: boolean;
|
|
39
|
-
droppable: boolean;
|
|
40
43
|
leaf: boolean;
|
|
41
44
|
depth: number;
|
|
42
45
|
selected: boolean;
|