@iyulab/components 1.39.0 → 1.40.1
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 +173 -0
- package/README.md +24 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/_virtual/_glob-assets_raw/dark.css.e8ac080d.js +1 -1
- package/dist/_virtual/_glob-assets_raw/light.css.637cb2f8.js +1 -1
- package/dist/assets/locales/ar.json.js +6 -2
- package/dist/assets/locales/de.json.js +6 -2
- package/dist/assets/locales/en.json.js +6 -2
- package/dist/assets/locales/es.json.js +6 -2
- package/dist/assets/locales/fr.json.js +6 -2
- package/dist/assets/locales/id.json.js +6 -2
- package/dist/assets/locales/ja.json.js +6 -2
- package/dist/assets/locales/ko.json.js +6 -2
- package/dist/assets/locales/pt-BR.json.js +6 -2
- package/dist/assets/locales/ru.json.js +6 -2
- package/dist/assets/locales/th.json.js +6 -2
- package/dist/assets/locales/vi.json.js +6 -2
- package/dist/assets/locales/zh-CN.json.js +6 -2
- package/dist/assets/locales/zh-TW.json.js +6 -2
- package/dist/components/UFloatingElement.js +2 -2
- package/dist/components/UFormControlElement.js +2 -2
- package/dist/components/UOverlayElement.js +2 -2
- package/dist/components/alert/UAlert.js +2 -2
- package/dist/components/avatar/UAvatar.js +2 -2
- package/dist/components/badge/UBadge.js +2 -2
- package/dist/components/breadcrumb/UBreadcrumb.js +1 -1
- package/dist/components/breadcrumb/UBreadcrumb.styles.js +1 -1
- package/dist/components/breadcrumb-item/UBreadcrumbItem.js +2 -2
- package/dist/components/breadcrumb-item/UBreadcrumbItem.styles.js +1 -1
- package/dist/components/button/UButton.js +2 -2
- package/dist/components/button-group/UButtonGroup.js +2 -2
- package/dist/components/card/UCard.js +2 -2
- package/dist/components/carousel/UCarousel.js +2 -2
- package/dist/components/checkbox/UCheckbox.js +2 -2
- package/dist/components/checkbox/UCheckbox.styles.js +7 -1
- package/dist/components/chip/UChip.js +2 -2
- package/dist/components/chip/UChip.styles.js +7 -0
- package/dist/components/copy-button/UCopyButton.js +2 -2
- package/dist/components/date-picker/UDatePicker.js +2 -2
- package/dist/components/date-picker/UDatePicker.styles.js +2 -2
- package/dist/components/dialog/UDialog.js +2 -2
- package/dist/components/divider/UDivider.js +2 -2
- package/dist/components/divider/UDivider.styles.js +1 -1
- package/dist/components/drawer/UDrawer.js +2 -2
- package/dist/components/expander/UExpander.js +2 -2
- package/dist/components/expander/UExpander.styles.js +1 -1
- package/dist/components/field/UField.js +2 -2
- package/dist/components/field/UField.styles.js +1 -1
- package/dist/components/file-input/UFileInput.js +2 -2
- package/dist/components/file-input/UFileInput.styles.js +2 -2
- package/dist/components/form/UForm.js +2 -2
- package/dist/components/icon/UIcon.js +13 -6
- package/dist/components/icon-button/UIconButton.js +2 -2
- package/dist/components/input/UInput.d.ts +15 -1
- package/dist/components/input/UInput.js +62 -12
- package/dist/components/input/UInput.styles.js +25 -6
- package/dist/components/menu/UMenu.js +2 -2
- package/dist/components/menu-item/UMenuItem.js +2 -2
- package/dist/components/option/UOption.js +2 -2
- package/dist/components/panel/UPanel.js +2 -2
- package/dist/components/popover/UPopover.js +23 -7
- package/dist/components/progress-bar/UProgressBar.js +2 -2
- package/dist/components/progress-ring/UProgressRing.js +2 -2
- package/dist/components/radio/URadio.js +2 -2
- package/dist/components/rating/URating.js +2 -2
- package/dist/components/rating/URating.styles.js +6 -0
- package/dist/components/select/USelect.d.ts +7 -1
- package/dist/components/select/USelect.js +19 -8
- package/dist/components/select/USelect.styles.js +18 -5
- package/dist/components/skeleton/USkeleton.js +2 -2
- package/dist/components/slider/USlider.d.ts +3 -1
- package/dist/components/slider/USlider.js +2 -2
- package/dist/components/slider/USlider.styles.js +19 -2
- package/dist/components/spinner/USpinner.js +2 -2
- package/dist/components/split-panel/USplitPanel.d.ts +43 -2
- package/dist/components/split-panel/USplitPanel.js +127 -11
- package/dist/components/split-panel/USplitPanel.styles.js +37 -6
- package/dist/components/switch/USwitch.js +2 -2
- package/dist/components/switch/USwitch.styles.js +8 -3
- package/dist/components/tab/UTab.js +2 -2
- package/dist/components/tab/UTab.styles.js +1 -1
- package/dist/components/tab-panel/UTabPanel.js +3 -3
- package/dist/components/tag/UTag.js +2 -2
- package/dist/components/text/UText.js +2 -2
- package/dist/components/text/UText.styles.js +1 -1
- package/dist/components/textarea/UTextarea.d.ts +5 -0
- package/dist/components/textarea/UTextarea.js +2 -2
- package/dist/components/textarea/UTextarea.styles.js +6 -3
- package/dist/components/tooltip/UTooltip.js +2 -2
- package/dist/components/tree/UTree.js +2 -2
- package/dist/components/tree-item/UTreeItem.js +2 -2
- package/dist/components/tree-item/UTreeItem.styles.js +50 -13
- package/dist/styles/dark.css +4 -1
- package/dist/styles/light.css +7 -4
- package/dist/utilities/Locale.d.ts +1 -1
- package/dist/utilities/Toast.d.ts +34 -0
- package/dist/utilities/Toast.js +57 -0
- package/dist/utilities/devWarning.d.ts +17 -0
- package/dist/utilities/devWarning.js +5 -0
- package/package.json +4 -4
- package/skills/iyulab-components/references/components/dialog.md +19 -0
- package/skills/iyulab-components/references/components/input.md +17 -0
- package/skills/iyulab-components/references/components/panel.md +12 -0
- package/skills/iyulab-components/references/components/select.md +9 -0
- package/skills/iyulab-components/references/components/slider.md +1 -1
- package/skills/iyulab-components/references/components/split-panel.md +41 -3
- package/skills/iyulab-components/references/components/tab-panel.md +18 -0
|
@@ -58,49 +58,86 @@ var styles = css`
|
|
|
58
58
|
white-space: nowrap;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/* ── toggler ──
|
|
61
|
+
/* ── toggler ──
|
|
62
|
+
The box that takes the pointer is 24x24 (WCAG 2.2 SC 2.5.8); the square you see is still
|
|
63
|
+
18x18, drawn by the pseudo-element. The negative margins give the extra 3px on each side
|
|
64
|
+
back, so the glyph, the label and the row height sit exactly where they did — the extra
|
|
65
|
+
area lands on the header's own padding and the gap before the label, never on another
|
|
66
|
+
target. */
|
|
62
67
|
.prefix-toggler {
|
|
68
|
+
position: relative;
|
|
69
|
+
box-sizing: border-box;
|
|
63
70
|
flex-shrink: 0;
|
|
64
|
-
margin
|
|
71
|
+
margin: -3px 1px -3px -3px;
|
|
65
72
|
display: inline-flex;
|
|
66
73
|
align-items: center;
|
|
67
74
|
justify-content: center;
|
|
68
|
-
width:
|
|
69
|
-
height:
|
|
75
|
+
width: 24px;
|
|
76
|
+
height: 24px;
|
|
77
|
+
}
|
|
78
|
+
.prefix-toggler::before {
|
|
79
|
+
content: "";
|
|
80
|
+
position: absolute;
|
|
81
|
+
inset: 3px;
|
|
70
82
|
border-radius: var(--u-radius-sm, 3px);
|
|
83
|
+
transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
|
|
84
|
+
}
|
|
85
|
+
.prefix-toggler > * {
|
|
86
|
+
position: relative;
|
|
71
87
|
}
|
|
72
88
|
.prefix-toggler u-icon {
|
|
73
89
|
font-size: 12px;
|
|
74
90
|
pointer-events: none;
|
|
75
91
|
}
|
|
76
|
-
:host(:not([disabled])[trigger="icon"]) .prefix-toggler:hover,
|
|
77
|
-
:host(:not([disabled])[trigger="icon"]:focus-visible) .prefix-toggler {
|
|
92
|
+
:host(:not([disabled])[trigger="icon"]) .prefix-toggler:hover::before,
|
|
93
|
+
:host(:not([disabled])[trigger="icon"]:focus-visible) .prefix-toggler::before {
|
|
78
94
|
background-color: var(--u-bg-color-hover, #F5F5F5);
|
|
79
95
|
}
|
|
96
|
+
/* A checkable row puts the checkbox 4px after the toggle. Centred 24px areas for both would
|
|
97
|
+
overlap by 3px, so here the toggle takes its extra width entirely on the left (header
|
|
98
|
+
padding), and the padding keeps the glyph centred on its visible square. */
|
|
99
|
+
:host([checkable]) .prefix-toggler {
|
|
100
|
+
margin: -3px 4px -3px -6px;
|
|
101
|
+
padding-left: 6px;
|
|
102
|
+
}
|
|
103
|
+
:host([checkable]) .prefix-toggler::before {
|
|
104
|
+
inset: 3px 0 3px 6px;
|
|
105
|
+
}
|
|
80
106
|
|
|
81
|
-
/* ── checkbox ──
|
|
107
|
+
/* ── checkbox ──
|
|
108
|
+
Same split as the toggle: a 24x24 box takes the pointer, the 16x16 box you see is the
|
|
109
|
+
pseudo-element, and the negative margins keep every visible edge where it was. */
|
|
82
110
|
.prefix-checkbox {
|
|
111
|
+
position: relative;
|
|
112
|
+
box-sizing: border-box;
|
|
83
113
|
flex-shrink: 0;
|
|
84
|
-
margin
|
|
114
|
+
margin: -4px 0 -4px -4px;
|
|
85
115
|
display: inline-flex;
|
|
86
116
|
align-items: center;
|
|
87
117
|
justify-content: center;
|
|
88
|
-
width:
|
|
89
|
-
height:
|
|
118
|
+
width: 24px;
|
|
119
|
+
height: 24px;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
}
|
|
122
|
+
.prefix-checkbox::before {
|
|
123
|
+
content: "";
|
|
124
|
+
position: absolute;
|
|
125
|
+
inset: 4px;
|
|
126
|
+
box-sizing: border-box;
|
|
90
127
|
border-radius: var(--u-radius-sm, 3px);
|
|
91
128
|
border: 1.5px solid var(--u-input-border-color, #E0E0E0);
|
|
92
129
|
background-color: transparent;
|
|
93
130
|
transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), border-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
|
|
94
|
-
cursor: pointer;
|
|
95
131
|
}
|
|
96
132
|
.prefix-checkbox u-icon {
|
|
133
|
+
position: relative;
|
|
97
134
|
visibility: hidden;
|
|
98
135
|
font-size: 12px;
|
|
99
136
|
color: #fff;
|
|
100
137
|
pointer-events: none;
|
|
101
138
|
}
|
|
102
|
-
.prefix-checkbox[checked],
|
|
103
|
-
.prefix-checkbox[indeterminate] {
|
|
139
|
+
.prefix-checkbox[checked]::before,
|
|
140
|
+
.prefix-checkbox[indeterminate]::before {
|
|
104
141
|
border-color: var(--tree-item-color);
|
|
105
142
|
background-color: var(--tree-item-color);
|
|
106
143
|
}
|
package/dist/styles/dark.css
CHANGED
|
@@ -242,7 +242,10 @@
|
|
|
242
242
|
--u-txt-color-hover: var(--u-primary-color-strong);
|
|
243
243
|
--u-txt-color-active: var(--u-primary-color-strong);
|
|
244
244
|
--u-txt-color-disabled: var(--u-neutral-500);
|
|
245
|
-
|
|
245
|
+
/* 라이트와 같은 기준 — 놓이는 모든 면에서 AA. neutral-700(#8A8A8A)은 바탕 5.43 ·
|
|
246
|
+
올림면(neutral-300) 4.16 · active 면(neutral-400) 3.15 로 미달이었다.
|
|
247
|
+
neutral-800(#B0B0B0) = 8.64 · 6.62 · 5.01. 본문(neutral-900)과의 대비비 1.46. */
|
|
248
|
+
--u-txt-color-weak: var(--u-neutral-800);
|
|
246
249
|
--u-txt-color-strong: var(--u-neutral-1000);
|
|
247
250
|
|
|
248
251
|
--u-link-txt-color: var(--u-primary-color-strong);
|
package/dist/styles/light.css
CHANGED
|
@@ -252,10 +252,13 @@
|
|
|
252
252
|
--u-txt-color-hover: var(--u-primary-color-strong);
|
|
253
253
|
--u-txt-color-active: var(--u-primary-color-strong);
|
|
254
254
|
--u-txt-color-disabled: var(--u-neutral-400);
|
|
255
|
-
/*
|
|
256
|
-
neutral-600(#757575)
|
|
257
|
-
|
|
258
|
-
|
|
255
|
+
/* 보조 텍스트는 «놓이는 모든 면»에서 AA(4.5)를 받쳐야 한다 — 바탕만이 아니다.
|
|
256
|
+
neutral-600(#757575)은 바탕 4.61 에서만 통과하고 올림면(neutral-50) 4.41 ·
|
|
257
|
+
active 면(neutral-200) 3.97 로 미달이었다(표 머리·카드 위 보조 텍스트).
|
|
258
|
+
neutral-700(#616161) = 바탕 6.19 · 올림면 5.93 · active 5.34.
|
|
259
|
+
본문(neutral-900)과의 대비비는 2.60 으로, 보조 텍스트를 모든 표면 위에서
|
|
260
|
+
읽히게 보장하는 흔한 디자인 시스템 기준(본문 대비 약 1.3~1.8)보다 위계가 넓다. */
|
|
261
|
+
--u-txt-color-weak: var(--u-neutral-700);
|
|
259
262
|
--u-txt-color-strong: var(--u-neutral-1000);
|
|
260
263
|
|
|
261
264
|
--u-link-txt-color: var(--u-primary-color-strong);
|
|
@@ -12,7 +12,7 @@ export type SupportedLocale = 'en' | 'ko' | 'ja' | 'zh-CN' | 'zh-TW' | 'es' | 'f
|
|
|
12
12
|
/** 내장 로케일은 자동완성되지만, 임의의 BCP47 태그도 그대로 받는다. */
|
|
13
13
|
export type LocaleTag = SupportedLocale | (string & {});
|
|
14
14
|
/** 라이브러리가 제공하는 chrome 문자열 키. 지금은 검증 메시지뿐이지만 이후 다른 UI 문구도 추가될 수 있다. */
|
|
15
|
-
export type LocaleMessageKey = 'valueMissing' | 'badInput' | 'typeMismatch' | 'patternMismatch' | 'rangeUnderflow' | 'rangeOverflow' | 'stepMismatch' | 'tooShort' | 'tooLong' | 'increment' | 'decrement' | 'clear' | 'today' | 'time' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide' | 'chooseDate' | 'previousMonth' | 'nextMonth' | 'close' | 'copy' | 'copied' | 'chooseFile' | 'noFileChosen' | 'filesSelected';
|
|
15
|
+
export type LocaleMessageKey = 'valueMissing' | 'badInput' | 'typeMismatch' | 'patternMismatch' | 'rangeUnderflow' | 'rangeOverflow' | 'stepMismatch' | 'tooShort' | 'tooLong' | 'increment' | 'decrement' | 'clear' | 'today' | 'time' | 'showPassword' | 'hidePassword' | 'previousSlide' | 'nextSlide' | 'goToSlide' | 'chooseDate' | 'previousMonth' | 'nextMonth' | 'close' | 'copy' | 'copied' | 'chooseFile' | 'noFileChosen' | 'filesSelected' | 'resizePanels' | 'search';
|
|
16
16
|
type LocaleTable = Record<LocaleMessageKey, string>;
|
|
17
17
|
/**
|
|
18
18
|
* 한 패키지(또는 앱 영역)의 문자열 묶음.
|
|
@@ -68,4 +68,38 @@ export declare class Toast {
|
|
|
68
68
|
* 않는다**. 낡은 항목은 버리고 새로 만든다.
|
|
69
69
|
*/
|
|
70
70
|
private static getOrCreateContainer;
|
|
71
|
+
/**
|
|
72
|
+
* 알림 컨테이너를 **네이티브 top layer** 로 올린다(`popover="manual"`).
|
|
73
|
+
*
|
|
74
|
+
* ## 왜 — z-index 로는 원리적으로 닿지 않는 자리가 있다
|
|
75
|
+
*
|
|
76
|
+
* `OverlayManager` 의 «이름 있는 띠» 계약은 **우리 오버레이보다 위**를 보장한다(실측:
|
|
77
|
+
* 컨테이너 `z-index: 11000`). 그러나 ***top layer 는 z-index 축 밖에 있다*** — 소비앱이
|
|
78
|
+
* 네이티브 `<dialog>.showModal()` 을 열면 그 다이얼로그는 **어떤 z-index 보다도 위**에
|
|
79
|
+
* 서고, 우리 토스트는 가려진다. 실측(cycle-477, 크로미움 `elementFromPoint`):
|
|
80
|
+
*
|
|
81
|
+
* ```
|
|
82
|
+
* containerZIndex 11000 · notificationZIndex 11000 · hitTag "DIALOG" · toastReachable false
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* 알림 채널의 제1원칙이 ***«지각되지 않는 경보는 경보가 아니다»*** 이므로, 그 채널은 겹침을
|
|
86
|
+
* **다투지 않고** 전용 층을 가져야 한다. `popover="manual"` 은 dismiss 계약도 포커스 트랩도
|
|
87
|
+
* 걸지 않고 **top layer 승격만** 하므로 이 표면에 정확히 맞는다.
|
|
88
|
+
*
|
|
89
|
+
* ## ⚠ 범위 — `document.body` 컨테이너만이다
|
|
90
|
+
*
|
|
91
|
+
* `target` 이 주어진 컨테이너는 `position: absolute` 로 **그 엘리먼트 기준**으로 놓인다.
|
|
92
|
+
* top layer 원소는 조상의 배치 문맥에서 떨어져 나오므로 그 좌표계가 통째로 깨진다 ⇒
|
|
93
|
+
* 타깃 기준 컨테이너는 **종전 z-index 경로를 그대로 쓴다.** 이것이 시범 범위이고,
|
|
94
|
+
* 오버레이 전면 전환(`u-dialog`·`u-drawer` 등)은 별개 결정이다(`ROADMAP.md` §C-B).
|
|
95
|
+
*
|
|
96
|
+
* ## ⚠ z-index 를 지우지 않는다
|
|
97
|
+
*
|
|
98
|
+
* `showPopover` 가 없는 브라우저(또는 호출이 거부되는 상태)에서는 **아무 일도 일어나지
|
|
99
|
+
* 않고 종전 동작이 그대로 남아야** 한다 — 그래서 승격은 순수 «추가»이고, 실패는 조용히
|
|
100
|
+
* 삼킨다(알림을 띄우려다 예외를 던지는 것은 이 표면에서 최악의 실패다).
|
|
101
|
+
*/
|
|
102
|
+
private static preparePopover;
|
|
103
|
+
/** 연결된 뒤에만 부를 수 있다 — 실패하면 종전 동작(z-index 띠)으로 조용히 돌아간다. */
|
|
104
|
+
private static showTopLayer;
|
|
71
105
|
}
|
package/dist/utilities/Toast.js
CHANGED
|
@@ -93,6 +93,7 @@ var Toast = class {
|
|
|
93
93
|
container.style.display = "flex";
|
|
94
94
|
container.style.gap = "10px";
|
|
95
95
|
const isTargeted = target !== document.body;
|
|
96
|
+
const popoverReady = isTargeted ? false : this.preparePopover(container);
|
|
96
97
|
if (isTargeted) {
|
|
97
98
|
container.style.position = "absolute";
|
|
98
99
|
if (getComputedStyle(target).position === "static") target.style.position = "relative";
|
|
@@ -122,9 +123,65 @@ var Toast = class {
|
|
|
122
123
|
}
|
|
123
124
|
container.style.transform = transformParts.length ? transformParts.join(" ") : "";
|
|
124
125
|
target.appendChild(container);
|
|
126
|
+
if (popoverReady) this.showTopLayer(container);
|
|
125
127
|
byPosition.set(position, container);
|
|
126
128
|
return container;
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* 알림 컨테이너를 **네이티브 top layer** 로 올린다(`popover="manual"`).
|
|
132
|
+
*
|
|
133
|
+
* ## 왜 — z-index 로는 원리적으로 닿지 않는 자리가 있다
|
|
134
|
+
*
|
|
135
|
+
* `OverlayManager` 의 «이름 있는 띠» 계약은 **우리 오버레이보다 위**를 보장한다(실측:
|
|
136
|
+
* 컨테이너 `z-index: 11000`). 그러나 ***top layer 는 z-index 축 밖에 있다*** — 소비앱이
|
|
137
|
+
* 네이티브 `<dialog>.showModal()` 을 열면 그 다이얼로그는 **어떤 z-index 보다도 위**에
|
|
138
|
+
* 서고, 우리 토스트는 가려진다. 실측(cycle-477, 크로미움 `elementFromPoint`):
|
|
139
|
+
*
|
|
140
|
+
* ```
|
|
141
|
+
* containerZIndex 11000 · notificationZIndex 11000 · hitTag "DIALOG" · toastReachable false
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* 알림 채널의 제1원칙이 ***«지각되지 않는 경보는 경보가 아니다»*** 이므로, 그 채널은 겹침을
|
|
145
|
+
* **다투지 않고** 전용 층을 가져야 한다. `popover="manual"` 은 dismiss 계약도 포커스 트랩도
|
|
146
|
+
* 걸지 않고 **top layer 승격만** 하므로 이 표면에 정확히 맞는다.
|
|
147
|
+
*
|
|
148
|
+
* ## ⚠ 범위 — `document.body` 컨테이너만이다
|
|
149
|
+
*
|
|
150
|
+
* `target` 이 주어진 컨테이너는 `position: absolute` 로 **그 엘리먼트 기준**으로 놓인다.
|
|
151
|
+
* top layer 원소는 조상의 배치 문맥에서 떨어져 나오므로 그 좌표계가 통째로 깨진다 ⇒
|
|
152
|
+
* 타깃 기준 컨테이너는 **종전 z-index 경로를 그대로 쓴다.** 이것이 시범 범위이고,
|
|
153
|
+
* 오버레이 전면 전환(`u-dialog`·`u-drawer` 등)은 별개 결정이다(`ROADMAP.md` §C-B).
|
|
154
|
+
*
|
|
155
|
+
* ## ⚠ z-index 를 지우지 않는다
|
|
156
|
+
*
|
|
157
|
+
* `showPopover` 가 없는 브라우저(또는 호출이 거부되는 상태)에서는 **아무 일도 일어나지
|
|
158
|
+
* 않고 종전 동작이 그대로 남아야** 한다 — 그래서 승격은 순수 «추가»이고, 실패는 조용히
|
|
159
|
+
* 삼킨다(알림을 띄우려다 예외를 던지는 것은 이 표면에서 최악의 실패다).
|
|
160
|
+
*/
|
|
161
|
+
static preparePopover(container) {
|
|
162
|
+
if (typeof container.showPopover !== "function") return false;
|
|
163
|
+
container.setAttribute("popover", "manual");
|
|
164
|
+
container.style.inset = "auto";
|
|
165
|
+
container.style.margin = "0";
|
|
166
|
+
container.style.border = "none";
|
|
167
|
+
container.style.padding = "0";
|
|
168
|
+
container.style.background = "transparent";
|
|
169
|
+
container.style.color = "inherit";
|
|
170
|
+
container.style.overflow = "visible";
|
|
171
|
+
container.style.width = "auto";
|
|
172
|
+
container.style.height = "auto";
|
|
173
|
+
container.style.maxWidth = "none";
|
|
174
|
+
container.style.maxHeight = "none";
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
/** 연결된 뒤에만 부를 수 있다 — 실패하면 종전 동작(z-index 띠)으로 조용히 돌아간다. */
|
|
178
|
+
static showTopLayer(container) {
|
|
179
|
+
try {
|
|
180
|
+
container.showPopover();
|
|
181
|
+
} catch {
|
|
182
|
+
container.removeAttribute("popover");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
128
185
|
};
|
|
129
186
|
//#endregion
|
|
130
187
|
export { Toast };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 개발 모드 «사용 안내» 경고 — 오류 경로가 아닌, ***조용히 틀리는*** 상태를 한 번 알린다.
|
|
3
|
+
*
|
|
4
|
+
* 이 패키지에는 같은 모양의 경고가 이미 있다(`UElement.warnIfTokensMissing` — 토큰 시트 부재).
|
|
5
|
+
* 공통 규약: `[@iyulab/components]` 네임스페이스 · 개발 모드에서만(`import.meta.env.DEV`) ·
|
|
6
|
+
* 같은 키로는 **한 번만** · 무엇이 틀렸는지가 아니라 **무엇을 하면 되는지**를 적는다.
|
|
7
|
+
*
|
|
8
|
+
* 이 파일이 생긴 계기: 소비앱의 메뉴 30개가 해석되지 않는 아이콘 이름으로 **한꺼번에 같은
|
|
9
|
+
* 큐브 폴백**을 그렸는데 신호가 0 이었다(docket #265 R3). 폴백은 의도된 것이라(접힌 사이드바에서
|
|
10
|
+
* 아이콘이 없으면 메뉴가 «높이만 있는 빈 줄» 이 된다) 제거가 답이 아니다 — **없는 것은 경고다.**
|
|
11
|
+
* 같은 부류가 셋 더 있었다: 높이 제약이 없어 18px 로 붕괴하는 `u-split-panel`, 가상화가 꺼지는
|
|
12
|
+
* `flex-table`, 133px 로 앉는 `modern-app` 셸 — 모두 «에러 없이 틀린 화면» 이다(HD-61 ⒝).
|
|
13
|
+
*/
|
|
14
|
+
/** `key` 당 한 번만, 개발 모드에서만 `console.warn` 한다. 프로덕션 빌드에서는 호출 자체가 no-op 이다. */
|
|
15
|
+
export declare function devWarnOnce(key: string, message: string): void;
|
|
16
|
+
/** 테스트용 — 가드를 비운다. */
|
|
17
|
+
export declare function resetDevWarnings(): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/components",
|
|
3
3
|
"description": "web-components library based on lit-element made by iyulab",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.40.1",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"components",
|
|
@@ -83,16 +83,16 @@
|
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"@eslint/js": "^
|
|
86
|
+
"@eslint/js": "^10.0.1",
|
|
87
87
|
"@types/node": "^26.1.1",
|
|
88
88
|
"@types/react": "^19.2.14",
|
|
89
89
|
"@vitest/browser-playwright": "^4.1.10",
|
|
90
|
-
"eslint": "^
|
|
90
|
+
"eslint": "^10.1.0",
|
|
91
91
|
"eslint-plugin-lit": "^2.3.1",
|
|
92
92
|
"globals": "^17.7.0",
|
|
93
93
|
"happy-dom": "^20.10.6",
|
|
94
94
|
"react": "^19.2.7",
|
|
95
|
-
"typescript": "^
|
|
95
|
+
"typescript": "^6.0.2",
|
|
96
96
|
"typescript-eslint": "^8.64.0",
|
|
97
97
|
"vite": "^8.1.4",
|
|
98
98
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -25,6 +25,25 @@ For programmatic usage (`Dialog.alert`, `Dialog.confirm`, `Dialog.prompt`), see
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
+
## Sizing
|
|
29
|
+
|
|
30
|
+
The panel is **content-sized, capped at 90%** of the dialog's own box — 90% of the height and of
|
|
31
|
+
the width. Measured in an 896px-tall viewport: a short dialog renders a 235px panel, and the same
|
|
32
|
+
dialog carrying 3,000px of body content stops at 806px.
|
|
33
|
+
|
|
34
|
+
Past that cap the **body is the only scroll region**. The `header` and `footer` slots are
|
|
35
|
+
`flex-shrink: 0`, so the title and the actions stay visible however long the content grows.
|
|
36
|
+
|
|
37
|
+
There is no size property. To make the dialog smaller than 90% of the viewport, give the **host** a
|
|
38
|
+
height — that is what the 90% is measured against:
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
u-dialog { height: 400px; } /* the panel then caps at 360px */
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
⚠ That lever only shrinks: a height on the host lowers the panel's maximum, it does not reserve a
|
|
45
|
+
panel of that size. A short dialog stays short.
|
|
46
|
+
|
|
28
47
|
## Slots
|
|
29
48
|
|
|
30
49
|
| Name | Description |
|
|
@@ -81,6 +81,23 @@ for a KRW amount) is the consumer's call — the library does not infer one from
|
|
|
81
81
|
| `input` | Fires on every keystroke |
|
|
82
82
|
| `change` | Fires when value is committed |
|
|
83
83
|
|
|
84
|
+
## Form submission
|
|
85
|
+
|
|
86
|
+
Pressing Enter in the field submits its `<form>`, as in a native text field (HTML implicit
|
|
87
|
+
submission): the form's first submit button is activated — `<button type="submit">` or
|
|
88
|
+
`<u-button type="submit">`; a disabled one does nothing — and with no submit button the form is
|
|
89
|
+
submitted only when it has no other single-line field. Enter that confirms an IME composition,
|
|
90
|
+
Enter with a modifier key, and Enter on a highlighted suggestion (`u-option`) do not submit.
|
|
91
|
+
Call `preventDefault()` on the `keydown` to cancel it. Do not also submit on Enter yourself.
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<form @submit=${onSubmit}>
|
|
95
|
+
<u-input name="user" required></u-input>
|
|
96
|
+
<u-input name="password" type="password" required></u-input>
|
|
97
|
+
<u-button type="submit">Sign in</u-button>
|
|
98
|
+
</form>
|
|
99
|
+
```
|
|
100
|
+
|
|
84
101
|
## Methods
|
|
85
102
|
|
|
86
103
|
| Method | Description |
|
|
@@ -26,6 +26,18 @@ General-purpose content panel. Matches a tab or tree node when using `value`.
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
+
## Sizing
|
|
30
|
+
|
|
31
|
+
`u-panel` has `overflow: auto` and no height of its own, so it behaves two ways — both intended:
|
|
32
|
+
|
|
33
|
+
- **No height** — it grows with its content. Nothing is clipped and no scrollbar appears.
|
|
34
|
+
- **A height (or a height-bearing parent)** — it becomes the scroll container for its content.
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<u-panel style="height: 240px">…</u-panel> <!-- scrolls its content -->
|
|
38
|
+
<u-panel>…</u-panel> <!-- grows with its content -->
|
|
39
|
+
```
|
|
40
|
+
|
|
29
41
|
## Slots
|
|
30
42
|
|
|
31
43
|
| Name | Description |
|
|
@@ -70,6 +70,15 @@ Dropdown select with single or multiple selection, search, and clear support. Fo
|
|
|
70
70
|
| `focus(options?)` | Focus the trigger |
|
|
71
71
|
| `blur()` | Blur the trigger |
|
|
72
72
|
|
|
73
|
+
## Keyboard & accessibility
|
|
74
|
+
|
|
75
|
+
The trigger is a `role="combobox"`. Without `searchable` the dropdown holds a `role="listbox"`
|
|
76
|
+
and opening it focuses the first option. With `searchable` the dropdown is a `role="dialog"`
|
|
77
|
+
(named by `label`, or "Search") that holds the search field and the listbox; opening it focuses
|
|
78
|
+
the search field, so typing filters at once. From the search field `ArrowDown`/`ArrowUp` move to
|
|
79
|
+
the first/last visible option; on an option, arrows, `Home`/`End`, `Enter`/`Space` (select) and
|
|
80
|
+
`Escape` (close) work as usual.
|
|
81
|
+
|
|
73
82
|
## CSS Parts
|
|
74
83
|
|
|
75
84
|
| Part | Description |
|
|
@@ -84,7 +84,7 @@ Range slider. Single-thumb or dual-thumb (range) mode. Supports marks, value dis
|
|
|
84
84
|
| `--slider-fill-color` | Track fill color |
|
|
85
85
|
| `--slider-track-height` | Track height |
|
|
86
86
|
| `--slider-track-color` | Track background color |
|
|
87
|
-
| `--slider-thumb-size` | Thumb diameter |
|
|
87
|
+
| `--slider-thumb-size` | Thumb diameter (**visible circle only** — the pointer target keeps a 24x24 floor per WCAG 2.2 SC 2.5.8, so lowering this does not shrink it) |
|
|
88
88
|
| `--slider-thumb-color` | Thumb fill color |
|
|
89
89
|
| `--slider-thumb-border-color` | Thumb border color |
|
|
90
90
|
| `--slider-mark-size` | Mark dot size |
|
|
@@ -15,7 +15,7 @@ Resizable two-panel layout. Drag the splitter to adjust panel sizes.
|
|
|
15
15
|
</u-split-panel>
|
|
16
16
|
|
|
17
17
|
<!-- Vertical split -->
|
|
18
|
-
<u-split-panel orientation="vertical" default-ratio="
|
|
18
|
+
<u-split-panel orientation="vertical" default-ratio="30,70" style="height: 400px;">
|
|
19
19
|
<div>Top panel</div>
|
|
20
20
|
<div>Bottom panel</div>
|
|
21
21
|
</u-split-panel>
|
|
@@ -30,6 +30,27 @@ Resizable two-panel layout. Drag the splitter to adjust panel sizes.
|
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
|
+
## Sizing
|
|
34
|
+
|
|
35
|
+
**Give the host a height.** This is a shell: `:host` is `height: 100%` with `overflow: hidden`,
|
|
36
|
+
so the panels divide whatever height the host has — and an unconstrained host has none to divide.
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<u-split-panel style="height: 400px">…</u-split-panel>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
⚠ Leave the height off — or nest the component in a container that has no height of its own — and
|
|
43
|
+
it collapses to a thin strip (measured: 18px, with 900px-tall panel content), the content is
|
|
44
|
+
clipped by `overflow: hidden`, and there is no scrollbar to reach it. No error, nothing in the
|
|
45
|
+
console. Every example below assumes a height on the host for this reason.
|
|
46
|
+
|
|
47
|
+
A height-bearing ancestor works the same way (measured):
|
|
48
|
+
|
|
49
|
+
```css
|
|
50
|
+
.page { height: 100%; display: flex; flex-direction: column; }
|
|
51
|
+
.page u-split-panel { flex: 1 1 auto; min-height: 0; }
|
|
52
|
+
```
|
|
53
|
+
|
|
33
54
|
## Slots
|
|
34
55
|
|
|
35
56
|
| Name | Description |
|
|
@@ -42,7 +63,7 @@ Resizable two-panel layout. Drag the splitter to adjust panel sizes.
|
|
|
42
63
|
| Property | Type | Default | Reflect | Description |
|
|
43
64
|
|----------|------|---------|---------|-------------|
|
|
44
65
|
| `orientation` | `'horizontal'\|'vertical'` | `'horizontal'` | ✓ | Split direction |
|
|
45
|
-
| `defaultRatio` | `number[]` | `[]` | ✓ | Initial size ratios
|
|
66
|
+
| `defaultRatio` | `number[]` | `[]` | ✓ | Initial size ratios. Attribute form is comma-separated, without brackets: `default-ratio="30,70"`. Ratios are shares of the space between the handles |
|
|
46
67
|
| `ratio` | `number[]` | `[]` | ✓ | Current size ratios |
|
|
47
68
|
| `disabled` | `boolean` | `false` | ✓ | Prevent resizing |
|
|
48
69
|
| `lazy` | `boolean` | `false` | ✓ | Show preview while dragging, commit on release |
|
|
@@ -55,11 +76,28 @@ Resizable two-panel layout. Drag the splitter to adjust panel sizes.
|
|
|
55
76
|
| `shift` | Dragging in progress |
|
|
56
77
|
| `shift-end` | Drag ends |
|
|
57
78
|
|
|
79
|
+
## Keyboard & Accessibility
|
|
80
|
+
|
|
81
|
+
Each handle is a focusable `role="separator"` following the WAI-ARIA APG *Window Splitter*
|
|
82
|
+
pattern. Its value is the share of the panel **before** it (`aria-valuenow`, `0` to the combined
|
|
83
|
+
share of the two panels it sits between — `100` with two panels), and it is named by the
|
|
84
|
+
`resizePanels` locale message.
|
|
85
|
+
|
|
86
|
+
| Key | Effect |
|
|
87
|
+
|-----|--------|
|
|
88
|
+
| `←` / `→` (horizontal) · `↑` / `↓` (vertical) | Shrink / grow the panel before the handle by 5% |
|
|
89
|
+
| `Home` / `End` | Give the panel before the handle its smallest / largest size |
|
|
90
|
+
| `Enter` | Collapse the panel before the handle; press again to restore its previous size |
|
|
91
|
+
|
|
92
|
+
In a right-to-left layout `←` still moves the handle left. A keyboard change fires `shift-start`,
|
|
93
|
+
`shift` and `shift-end` in turn, so listening to `shift-end` alone covers both pointer and keyboard.
|
|
94
|
+
|
|
58
95
|
## CSS Custom Properties
|
|
59
96
|
|
|
60
97
|
| Property | Description |
|
|
61
98
|
|----------|-------------|
|
|
62
|
-
| `--splitter-size` |
|
|
99
|
+
| `--splitter-size` | Thickness of the visible line (default `4px`) |
|
|
100
|
+
| `--splitter-hit-size` | Thickness of the area that takes the pointer (default `24px`, WCAG 2.5.8). It occupies layout space between the panels, so it never covers a panel's scrollbar. The handle is the larger of the two; set it to `var(--splitter-size)` for a flush handle |
|
|
63
101
|
| `--splitter-color` | Splitter default color |
|
|
64
102
|
| `--splitter-color-hover` | Splitter color on hover |
|
|
65
103
|
| `--splitter-color-active` | Splitter color while dragging |
|
|
@@ -32,6 +32,24 @@ Tab-based content switcher. Pair each `u-tab` with a `u-panel` of the same `valu
|
|
|
32
32
|
|
|
33
33
|
## u-tab-panel
|
|
34
34
|
|
|
35
|
+
### Sizing
|
|
36
|
+
|
|
37
|
+
`u-tab-panel` is a flex shell with no height of its own, so it behaves two ways — both intended:
|
|
38
|
+
|
|
39
|
+
- **No height** — it grows with the active panel's content; nothing is clipped and no scrollbar
|
|
40
|
+
appears (measured: a 900px panel under a `top` tab bar gives a 935px-tall component — the 34px bar
|
|
41
|
+
plus the content).
|
|
42
|
+
- **A height, or a height-bearing parent** — the **content area** becomes the scroll region and the
|
|
43
|
+
tab bar keeps its place (measured: 300px tall → a 265px content area with 635px to scroll).
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<u-tab-panel style="height: 300px">…</u-tab-panel>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The tab bar scrolls on its own axis when the tabs overflow it — horizontally for `placement="top"`
|
|
50
|
+
and `"bottom"`, vertically for `"left"` and `"right"` — so a long tab list never pushes the content
|
|
51
|
+
out of the component.
|
|
52
|
+
|
|
35
53
|
### Slots
|
|
36
54
|
|
|
37
55
|
| Name | Description |
|