@iyulab/components 1.39.0 → 1.40.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/README.md +24 -0
  3. package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorate.js +1 -1
  4. package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorateMetadata.js +1 -1
  5. package/dist/_virtual/_glob-assets_raw/dark.css.e8ac080d.js +1 -1
  6. package/dist/_virtual/_glob-assets_raw/light.css.637cb2f8.js +1 -1
  7. package/dist/assets/locales/ar.json.js +6 -2
  8. package/dist/assets/locales/de.json.js +6 -2
  9. package/dist/assets/locales/en.json.js +6 -2
  10. package/dist/assets/locales/es.json.js +6 -2
  11. package/dist/assets/locales/fr.json.js +6 -2
  12. package/dist/assets/locales/id.json.js +6 -2
  13. package/dist/assets/locales/ja.json.js +6 -2
  14. package/dist/assets/locales/ko.json.js +6 -2
  15. package/dist/assets/locales/pt-BR.json.js +6 -2
  16. package/dist/assets/locales/ru.json.js +6 -2
  17. package/dist/assets/locales/th.json.js +6 -2
  18. package/dist/assets/locales/vi.json.js +6 -2
  19. package/dist/assets/locales/zh-CN.json.js +6 -2
  20. package/dist/assets/locales/zh-TW.json.js +6 -2
  21. package/dist/components/UFloatingElement.js +2 -2
  22. package/dist/components/UFormControlElement.js +2 -2
  23. package/dist/components/UOverlayElement.js +2 -2
  24. package/dist/components/alert/UAlert.js +2 -2
  25. package/dist/components/avatar/UAvatar.js +2 -2
  26. package/dist/components/badge/UBadge.js +2 -2
  27. package/dist/components/breadcrumb/UBreadcrumb.js +1 -1
  28. package/dist/components/breadcrumb/UBreadcrumb.styles.js +1 -1
  29. package/dist/components/breadcrumb-item/UBreadcrumbItem.js +2 -2
  30. package/dist/components/breadcrumb-item/UBreadcrumbItem.styles.js +1 -1
  31. package/dist/components/button/UButton.js +2 -2
  32. package/dist/components/button-group/UButtonGroup.js +2 -2
  33. package/dist/components/card/UCard.js +2 -2
  34. package/dist/components/carousel/UCarousel.js +2 -2
  35. package/dist/components/checkbox/UCheckbox.js +2 -2
  36. package/dist/components/checkbox/UCheckbox.styles.js +7 -1
  37. package/dist/components/chip/UChip.js +2 -2
  38. package/dist/components/chip/UChip.styles.js +7 -0
  39. package/dist/components/copy-button/UCopyButton.js +2 -2
  40. package/dist/components/date-picker/UDatePicker.js +2 -2
  41. package/dist/components/date-picker/UDatePicker.styles.js +2 -2
  42. package/dist/components/dialog/UDialog.js +2 -2
  43. package/dist/components/divider/UDivider.js +2 -2
  44. package/dist/components/divider/UDivider.styles.js +1 -1
  45. package/dist/components/drawer/UDrawer.js +2 -2
  46. package/dist/components/expander/UExpander.js +2 -2
  47. package/dist/components/expander/UExpander.styles.js +1 -1
  48. package/dist/components/field/UField.js +2 -2
  49. package/dist/components/field/UField.styles.js +1 -1
  50. package/dist/components/file-input/UFileInput.js +2 -2
  51. package/dist/components/file-input/UFileInput.styles.js +2 -2
  52. package/dist/components/form/UForm.js +2 -2
  53. package/dist/components/icon/UIcon.js +3 -3
  54. package/dist/components/icon-button/UIconButton.js +2 -2
  55. package/dist/components/input/UInput.d.ts +15 -1
  56. package/dist/components/input/UInput.js +62 -12
  57. package/dist/components/input/UInput.styles.js +25 -6
  58. package/dist/components/menu/UMenu.js +2 -2
  59. package/dist/components/menu-item/UMenuItem.js +2 -2
  60. package/dist/components/option/UOption.js +2 -2
  61. package/dist/components/panel/UPanel.js +2 -2
  62. package/dist/components/popover/UPopover.js +23 -7
  63. package/dist/components/progress-bar/UProgressBar.js +2 -2
  64. package/dist/components/progress-ring/UProgressRing.js +2 -2
  65. package/dist/components/radio/URadio.js +2 -2
  66. package/dist/components/rating/URating.js +2 -2
  67. package/dist/components/rating/URating.styles.js +6 -0
  68. package/dist/components/select/USelect.d.ts +7 -1
  69. package/dist/components/select/USelect.js +19 -8
  70. package/dist/components/select/USelect.styles.js +18 -5
  71. package/dist/components/skeleton/USkeleton.js +2 -2
  72. package/dist/components/slider/USlider.d.ts +3 -1
  73. package/dist/components/slider/USlider.js +2 -2
  74. package/dist/components/slider/USlider.styles.js +19 -2
  75. package/dist/components/spinner/USpinner.js +2 -2
  76. package/dist/components/split-panel/USplitPanel.d.ts +37 -2
  77. package/dist/components/split-panel/USplitPanel.js +120 -11
  78. package/dist/components/split-panel/USplitPanel.styles.js +37 -6
  79. package/dist/components/switch/USwitch.js +2 -2
  80. package/dist/components/switch/USwitch.styles.js +8 -3
  81. package/dist/components/tab/UTab.js +2 -2
  82. package/dist/components/tab/UTab.styles.js +1 -1
  83. package/dist/components/tab-panel/UTabPanel.js +3 -3
  84. package/dist/components/tag/UTag.js +2 -2
  85. package/dist/components/text/UText.js +2 -2
  86. package/dist/components/text/UText.styles.js +1 -1
  87. package/dist/components/textarea/UTextarea.d.ts +5 -0
  88. package/dist/components/textarea/UTextarea.js +2 -2
  89. package/dist/components/textarea/UTextarea.styles.js +6 -3
  90. package/dist/components/tooltip/UTooltip.js +2 -2
  91. package/dist/components/tree/UTree.js +2 -2
  92. package/dist/components/tree-item/UTreeItem.js +2 -2
  93. package/dist/components/tree-item/UTreeItem.styles.js +50 -13
  94. package/dist/styles/dark.css +4 -1
  95. package/dist/styles/light.css +7 -4
  96. package/dist/utilities/Locale.d.ts +1 -1
  97. package/dist/utilities/Toast.d.ts +34 -0
  98. package/dist/utilities/Toast.js +57 -0
  99. package/package.json +4 -4
  100. package/skills/iyulab-components/references/components/dialog.md +19 -0
  101. package/skills/iyulab-components/references/components/input.md +17 -0
  102. package/skills/iyulab-components/references/components/panel.md +12 -0
  103. package/skills/iyulab-components/references/components/select.md +9 -0
  104. package/skills/iyulab-components/references/components/slider.md +1 -1
  105. package/skills/iyulab-components/references/components/split-panel.md +41 -3
  106. package/skills/iyulab-components/references/components/tab-panel.md +18 -0
@@ -6,14 +6,22 @@ import { UElement } from '../UElement.js';
6
6
  * @slot - 분할된 패널 요소들
7
7
  * @slot splitter - 핸들(스플리터) UI
8
8
  *
9
- * @cssprop --splitter-size - 스플리터 크기 (default: 4px)
9
+ * @cssprop --splitter-size - 보이는 구분선 두께 (default: 4px)
10
+ * @cssprop --splitter-hit-size - 포인터를 받는 핸들 영역의 두께 — 레이아웃 공간을 차지하므로 패널을
11
+ * 가리지 않는다. 실제 핸들 두께는 이 값과 `--splitter-size` 중 큰 쪽 (default: 24px — WCAG 2.5.8)
10
12
  * @cssprop --splitter-color - 스플리터 색상
11
13
  * @cssprop --splitter-color-hover - 스플리터 호버 색상
12
14
  * @cssprop --splitter-color-active - 스플리터 활성 색상
13
15
  *
14
16
  * @event shift-start - 구분선 이동 시작 시 발생
15
17
  * @event shift - 구분선 이동 중 발생
16
- * @event shift-end - 구분선 이동 완료 시 발생
18
+ * @event shift-end - 구분선 이동 완료 시 발생 (포인터·키보드 공통)
19
+ *
20
+ * 키보드(WAI-ARIA APG «Window Splitter»): 분할 핸들은 `role="separator"` 로 포커스를 받는다.
21
+ * 방향키(가로 배치는 ←/→, 세로 배치는 ↑/↓)로 앞 패널을 줄이거나 늘리고, Home/End 는 앞 패널을
22
+ * 최소/최대로, Enter 는 앞 패널을 접거나 접기 전 크기로 되돌린다. 키 입력 한 번은 하나의 완결된
23
+ * 이동이라 `shift-start`·`shift`·`shift-end` 를 연달아 낸다 — 비율을 저장하는 소비자는 포인터든
24
+ * 키보드든 `shift-end` 하나만 들으면 된다.
17
25
  */
18
26
  export declare class USplitPanel extends UElement {
19
27
  static styles: import('lit').CSSResultGroup[];
@@ -30,8 +38,15 @@ export declare class USplitPanel extends UElement {
30
38
  private ghost?;
31
39
  private panels;
32
40
  private splitter?;
41
+ /** Enter 로 접은 핸들별 «접기 전 앞 패널 비율» — 다시 Enter 를 누르면 여기로 돌아간다. */
42
+ private collapsedFrom;
33
43
  private dragState;
34
44
  private get percentages();
45
+ /**
46
+ * 핸들 하나가 레이아웃에서 차지하는 두께(px). 렌더된 핸들을 재는 것이 정본이다 — CSS 가
47
+ * `max(--splitter-size, --splitter-hit-size)` 로 정하고 `rem` 등 어떤 단위든 올 수 있다.
48
+ * 아직 렌더되지 않았거나 숨겨져 0 이면 두 변수를 읽어 같은 규칙을 흉내 낸다.
49
+ */
35
50
  private get splitterSize();
36
51
  private get splitterCount();
37
52
  protected willUpdate(changedProperties: PropertyValues): void;
@@ -40,11 +55,31 @@ export declare class USplitPanel extends UElement {
40
55
  private handleSplitterSlotChange;
41
56
  private appendSplitters;
42
57
  private createSplitter;
58
+ /**
59
+ * 분할 핸들의 접근성 상태 — APG «Window Splitter». 핸들은 명령형으로 만들어 Lit 템플릿 밖에
60
+ * 있으므로, 비율·방향·비활성이 바뀔 때마다 여기서 다시 쓴다.
61
+ *
62
+ * 값은 **앞 패널(primary pane)의 몫**이다. 패널이 셋 이상이면 한 핸들은 이웃한 두 패널 사이만
63
+ * 옮기므로 최대값은 100 이 아니라 그 두 패널의 몫의 합이다.
64
+ */
65
+ private syncSplitterAria;
66
+ /** 방향키 한 번이 옮기는 앞 패널의 몫(나머지 공간 기준 %). */
67
+ private static readonly KEY_STEP;
68
+ private handleKeyDown;
43
69
  private updatePanelLayout;
44
70
  private handleDblClick;
45
71
  private handlePointerDown;
46
72
  private handlePointerMove;
47
73
  private handlePointerUp;
74
+ /**
75
+ * 패널 하나의 크기 — 비율은 «핸들을 뺀 나머지 공간»에 대한 몫이다.
76
+ *
77
+ * 🔴각 패널은 핸들 전체 두께 중 **자기 비율만큼**을 뺀다. 종전에는 핸들 몫을 패널 수로 똑같이
78
+ * 나눠 뺐는데(`p% - 핸들합/n`), 그 식은 비율이 균등할 때만 «나머지 공간의 p%» 와 같다. 드래그는
79
+ * 이동량을 나머지 공간 기준 비율로 바꾸므로(`availableSize`), 비율이 균등에서 멀어질수록 패널이
80
+ * 포인터보다 더 움직였다 — 핸들이 굵을수록 크게(24px 핸들이면 이동량의 약 9%).
81
+ */
82
+ private panelSize;
48
83
  private clampPair;
49
84
  }
50
85
  declare global {
@@ -1,12 +1,17 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import { arrayAttrConverter } from "../../utilities/converters.js";
5
+ import { Locale } from "../../utilities/Locale.js";
5
6
  import { styles } from "./USplitPanel.styles.js";
6
7
  import { html } from "lit";
7
8
  import { customElement, property, query } from "lit/decorators.js";
8
9
  //#region src/components/split-panel/USplitPanel.ts
10
+ var _USplitPanel;
9
11
  var USplitPanel = class USplitPanel extends UElement {
12
+ static {
13
+ _USplitPanel = this;
14
+ }
10
15
  constructor(..._args) {
11
16
  super(..._args);
12
17
  this.disabled = false;
@@ -15,6 +20,7 @@ var USplitPanel = class USplitPanel extends UElement {
15
20
  this.defaultRatio = [];
16
21
  this.ratio = [];
17
22
  this.panels = [];
23
+ this.collapsedFrom = /* @__PURE__ */ new Map();
18
24
  this.dragState = {
19
25
  index: -1,
20
26
  startPoint: 0,
@@ -33,6 +39,52 @@ var USplitPanel = class USplitPanel extends UElement {
33
39
  this.splitter = slot.assignedNodes({ flatten: true }).at(0);
34
40
  this.appendSplitters();
35
41
  };
42
+ this.handleKeyDown = (e) => {
43
+ if (this.disabled) return;
44
+ const i = Number(e.currentTarget.dataset.index);
45
+ const p = this.percentages;
46
+ if (p[i] === void 0 || p[i + 1] === void 0) return;
47
+ const pair = p[i] + p[i + 1];
48
+ const horizontal = this.orientation === "horizontal";
49
+ const rtl = horizontal && getComputedStyle(this).direction === "rtl";
50
+ const shrink = horizontal ? rtl ? "ArrowRight" : "ArrowLeft" : "ArrowUp";
51
+ const grow = horizontal ? rtl ? "ArrowLeft" : "ArrowRight" : "ArrowDown";
52
+ let a;
53
+ if (e.key === shrink) a = p[i] - _USplitPanel.KEY_STEP;
54
+ else if (e.key === grow) a = p[i] + _USplitPanel.KEY_STEP;
55
+ else if (e.key === "Home") a = 0;
56
+ else if (e.key === "End") a = pair;
57
+ else if (e.key === "Enter") {
58
+ const restore = this.collapsedFrom.get(i);
59
+ if (p[i] > 0) {
60
+ this.collapsedFrom.set(i, p[i]);
61
+ a = 0;
62
+ } else {
63
+ a = restore ?? pair / 2;
64
+ this.collapsedFrom.delete(i);
65
+ }
66
+ } else return;
67
+ e.preventDefault();
68
+ a = Math.round(Math.min(pair, Math.max(0, a)) * 1e6) / 1e6;
69
+ if (Math.abs(a - p[i]) < 1e-6) return;
70
+ if (e.key !== "Enter") this.collapsedFrom.delete(i);
71
+ const next = [...p];
72
+ next[i] = a;
73
+ next[i + 1] = pair - a;
74
+ const init = (ratio) => ({
75
+ bubbles: false,
76
+ composed: false,
77
+ detail: {
78
+ index: i,
79
+ ratio: [...ratio]
80
+ }
81
+ });
82
+ this.fire("shift-start", init(p));
83
+ this.ratio = next;
84
+ this.updatePanelLayout();
85
+ this.fire("shift", init(next));
86
+ this.fire("shift-end", init(next));
87
+ };
36
88
  this.handleDblClick = () => {
37
89
  if (this.disabled) return;
38
90
  this.ratio = this.defaultRatio.length === this.panels.length ? [...this.defaultRatio] : [];
@@ -91,9 +143,8 @@ var USplitPanel = class USplitPanel extends UElement {
91
143
  } else {
92
144
  const [aPercent, bPercent] = this.clampPair(this.dragState.percentages[aIdx] + deltaPercent, this.dragState.percentages[bIdx] - deltaPercent);
93
145
  const dim = this.orientation === "horizontal" ? "width" : "height";
94
- const offset = this.splitterSize * (this.splitterCount / this.panels.length);
95
- this.panels[aIdx].style[dim] = `calc(${aPercent}% - ${offset}px)`;
96
- this.panels[bIdx].style[dim] = `calc(${bPercent}% - ${offset}px)`;
146
+ this.panels[aIdx].style[dim] = this.panelSize(aPercent);
147
+ this.panels[bIdx].style[dim] = this.panelSize(bPercent);
97
148
  const newRatio = [...this.dragState.percentages];
98
149
  newRatio[aIdx] = aPercent;
99
150
  newRatio[bIdx] = bPercent;
@@ -143,7 +194,8 @@ var USplitPanel = class USplitPanel extends UElement {
143
194
  this.styles = [super.styles, styles];
144
195
  }
145
196
  get percentages() {
146
- const source = this.ratio.length === this.panels.length ? this.ratio : this.defaultRatio.length === this.panels.length ? this.defaultRatio : [];
197
+ const usable = (r) => r.length === this.panels.length && r.every((v) => Number.isFinite(v) && v >= 0) && r.some((v) => v > 0);
198
+ const source = usable(this.ratio) ? this.ratio : usable(this.defaultRatio) ? this.defaultRatio : [];
147
199
  if (source.length === this.panels.length) {
148
200
  const total = source.reduce((sum, s) => sum + s, 0);
149
201
  return source.map((s) => s / total * 100);
@@ -151,9 +203,21 @@ var USplitPanel = class USplitPanel extends UElement {
151
203
  const equals = 100 / this.panels.length;
152
204
  return this.panels.map(() => equals);
153
205
  }
206
+ /**
207
+ * 핸들 하나가 레이아웃에서 차지하는 두께(px). 렌더된 핸들을 재는 것이 정본이다 — CSS 가
208
+ * `max(--splitter-size, --splitter-hit-size)` 로 정하고 `rem` 등 어떤 단위든 올 수 있다.
209
+ * 아직 렌더되지 않았거나 숨겨져 0 이면 두 변수를 읽어 같은 규칙을 흉내 낸다.
210
+ */
154
211
  get splitterSize() {
155
- const sizeStr = getComputedStyle(this).getPropertyValue("--splitter-size").trim();
156
- return parseFloat(sizeStr) || 4;
212
+ const el = this.renderRoot?.querySelector(".splitter");
213
+ if (el) {
214
+ const r = el.getBoundingClientRect();
215
+ const measured = this.orientation === "horizontal" ? r.width : r.height;
216
+ if (measured > 0) return measured;
217
+ }
218
+ const style = getComputedStyle(this);
219
+ const read = (name, fallback) => parseFloat(style.getPropertyValue(name).trim()) || fallback;
220
+ return Math.max(read("--splitter-size", 4), read("--splitter-hit-size", 24));
157
221
  }
158
222
  get splitterCount() {
159
223
  return Math.max(0, this.panels.length - 1);
@@ -165,6 +229,7 @@ var USplitPanel = class USplitPanel extends UElement {
165
229
  "defaultRatio",
166
230
  "ratio"
167
231
  ].some((k) => changedProperties.has(k))) this.updatePanelLayout();
232
+ else if (changedProperties.has("disabled")) this.syncSplitterAria();
168
233
  }
169
234
  render() {
170
235
  return html`
@@ -185,6 +250,7 @@ var USplitPanel = class USplitPanel extends UElement {
185
250
  const splitter = this.createSplitter(i);
186
251
  root.insertBefore(splitter, ref);
187
252
  }
253
+ this.syncSplitterAria();
188
254
  }
189
255
  createSplitter(index) {
190
256
  const el = document.createElement("div");
@@ -193,24 +259,67 @@ var USplitPanel = class USplitPanel extends UElement {
193
259
  el.style.order = String(index * 2 + 1);
194
260
  el.dataset.index = String(index);
195
261
  if (this.splitter) el.appendChild(this.splitter.cloneNode(true));
262
+ el.setAttribute("role", "separator");
196
263
  el.addEventListener("pointerdown", this.handlePointerDown);
197
264
  el.addEventListener("dblclick", this.handleDblClick);
265
+ el.addEventListener("keydown", this.handleKeyDown);
198
266
  return el;
199
267
  }
268
+ /**
269
+ * 분할 핸들의 접근성 상태 — APG «Window Splitter». 핸들은 명령형으로 만들어 Lit 템플릿 밖에
270
+ * 있으므로, 비율·방향·비활성이 바뀔 때마다 여기서 다시 쓴다.
271
+ *
272
+ * 값은 **앞 패널(primary pane)의 몫**이다. 패널이 셋 이상이면 한 핸들은 이웃한 두 패널 사이만
273
+ * 옮기므로 최대값은 100 이 아니라 그 두 패널의 몫의 합이다.
274
+ */
275
+ syncSplitterAria() {
276
+ const root = this.renderRoot;
277
+ if (!root) return;
278
+ const p = this.percentages;
279
+ const round = (v) => String(Math.round(v * 10) / 10);
280
+ const label = Locale.getValue("resizePanels");
281
+ root.querySelectorAll(".splitter").forEach((el) => {
282
+ const i = Number(el.dataset.index);
283
+ el.setAttribute("aria-valuenow", round(p[i] ?? 0));
284
+ el.setAttribute("aria-valuemin", "0");
285
+ el.setAttribute("aria-valuemax", round((p[i] ?? 0) + (p[i + 1] ?? 0)));
286
+ el.setAttribute("aria-orientation", this.orientation === "horizontal" ? "vertical" : "horizontal");
287
+ el.setAttribute("aria-label", label);
288
+ el.tabIndex = this.disabled ? -1 : 0;
289
+ if (this.disabled) el.setAttribute("aria-disabled", "true");
290
+ else el.removeAttribute("aria-disabled");
291
+ const reflect = el;
292
+ if ("ariaControlsElements" in reflect && this.panels[i]) reflect.ariaControlsElements = [this.panels[i]];
293
+ });
294
+ }
295
+ static {
296
+ this.KEY_STEP = 5;
297
+ }
200
298
  updatePanelLayout() {
201
299
  if (this.panels.length === 0) return;
202
300
  const dim = this.orientation === "horizontal" ? "width" : "height";
203
301
  const otherDim = this.orientation === "horizontal" ? "height" : "width";
204
302
  const percentages = this.percentages;
205
- const splitterOffset = this.splitterSize * (this.splitterCount / this.panels.length);
206
303
  this.panels.forEach((panel, index) => {
207
- panel.style[dim] = `calc(${percentages[index]}% - ${splitterOffset}px)`;
304
+ panel.style[dim] = this.panelSize(percentages[index]);
208
305
  panel.style[otherDim] = "";
209
306
  panel.style.order = String(index * 2);
210
307
  panel.style.boxSizing = "border-box";
211
308
  panel.style.flexShrink = "0";
212
309
  panel.style.overflow = "auto";
213
310
  });
311
+ this.syncSplitterAria();
312
+ }
313
+ /**
314
+ * 패널 하나의 크기 — 비율은 «핸들을 뺀 나머지 공간»에 대한 몫이다.
315
+ *
316
+ * 🔴각 패널은 핸들 전체 두께 중 **자기 비율만큼**을 뺀다. 종전에는 핸들 몫을 패널 수로 똑같이
317
+ * 나눠 뺐는데(`p% - 핸들합/n`), 그 식은 비율이 균등할 때만 «나머지 공간의 p%» 와 같다. 드래그는
318
+ * 이동량을 나머지 공간 기준 비율로 바꾸므로(`availableSize`), 비율이 균등에서 멀어질수록 패널이
319
+ * 포인터보다 더 움직였다 — 핸들이 굵을수록 크게(24px 핸들이면 이동량의 약 9%).
320
+ */
321
+ panelSize(percent) {
322
+ return `calc(${percent}% - ${this.splitterSize * this.splitterCount * percent / 100}px)`;
214
323
  }
215
324
  clampPair(aRaw, bRaw) {
216
325
  const sum = aRaw + bRaw;
@@ -249,6 +358,6 @@ __decorate([property({
249
358
  converter: arrayAttrConverter(parseFloat)
250
359
  }), __decorateMetadata("design:type", Array)], USplitPanel.prototype, "ratio", void 0);
251
360
  __decorate([query(".splitter-ghost"), __decorateMetadata("design:type", typeof HTMLElement === "undefined" ? Object : HTMLElement)], USplitPanel.prototype, "ghost", void 0);
252
- USplitPanel = __decorate([customElement("u-split-panel")], USplitPanel);
361
+ USplitPanel = _USplitPanel = __decorate([customElement("u-split-panel")], USplitPanel);
253
362
  //#endregion
254
363
  export { USplitPanel };
@@ -3,9 +3,15 @@ import { css } from "lit";
3
3
  var styles = css`
4
4
  :host {
5
5
  --splitter-size: 4px;
6
+ --splitter-hit-size: 24px;
6
7
  --splitter-color: var(--u-neutral-200, #EEEEEE);
7
8
  --splitter-color-hover: var(--u-primary-color-weaker, #64B5F6);
8
9
  --splitter-color-active: var(--u-primary-color-strong, #1565C0);
10
+
11
+ /* The handle's box: the larger of the visible line and the pointer area. It takes real
12
+ layout space, so it never overlaps a panel — each panel is a scroll container and its
13
+ scrollbar sits right against the handle. */
14
+ --_splitter-box: max(var(--splitter-size), var(--splitter-hit-size));
9
15
  }
10
16
 
11
17
  :host {
@@ -27,7 +33,7 @@ var styles = css`
27
33
  opacity: 0.4;
28
34
  }
29
35
 
30
- /* Splitter */
36
+ /* Splitter — the box receives the pointer; the line inside it is what you see */
31
37
  .splitter {
32
38
  position: relative;
33
39
  z-index: 1;
@@ -35,24 +41,46 @@ var styles = css`
35
41
  display: flex;
36
42
  align-items: center;
37
43
  justify-content: center;
44
+ touch-action: none;
45
+ }
46
+ .splitter::before {
47
+ content: "";
48
+ position: absolute;
49
+ z-index: -1;
38
50
  background-color: var(--splitter-color);
39
51
  transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
40
- touch-action: none;
52
+ pointer-events: none;
41
53
  }
42
- .splitter:hover {
54
+ .splitter:hover::before {
43
55
  background-color: var(--splitter-color-hover);
44
56
  }
45
- .splitter:active {
57
+ .splitter:active::before,
58
+ .splitter:focus-visible::before {
46
59
  background-color: var(--splitter-color-active);
47
60
  }
61
+ /* The handle spans the host's full cross axis and the host clips overflow, so the base
62
+ focus ring (drawn 2px outside) would lose two of its sides. Draw it inside the box. */
63
+ .splitter:focus-visible {
64
+ outline-offset: -2px;
65
+ }
48
66
  :host([orientation="horizontal"]) .splitter {
49
- width: var(--splitter-size);
67
+ width: var(--_splitter-box);
50
68
  cursor: col-resize;
51
69
  }
70
+ :host([orientation="horizontal"]) .splitter::before {
71
+ inset-block: 0;
72
+ left: calc(50% - var(--splitter-size) / 2);
73
+ width: var(--splitter-size);
74
+ }
52
75
  :host([orientation="vertical"]) .splitter {
53
- height: var(--splitter-size);
76
+ height: var(--_splitter-box);
54
77
  cursor: row-resize;
55
78
  }
79
+ :host([orientation="vertical"]) .splitter::before {
80
+ inset-inline: 0;
81
+ top: calc(50% - var(--splitter-size) / 2);
82
+ height: var(--splitter-size);
83
+ }
56
84
 
57
85
  /* Ghost Splitter (lazy) */
58
86
  .splitter-ghost {
@@ -66,15 +94,18 @@ var styles = css`
66
94
  .splitter-ghost[active] {
67
95
  display: block;
68
96
  }
97
+ /* The ghost is placed at the box's leading edge; the margin centres it on the line. */
69
98
  :host([orientation="horizontal"]) .splitter-ghost {
70
99
  top: 0;
71
100
  width: var(--splitter-size);
72
101
  height: 100%;
102
+ margin-left: calc((var(--_splitter-box) - var(--splitter-size)) / 2);
73
103
  }
74
104
  :host([orientation="vertical"]) .splitter-ghost {
75
105
  left: 0;
76
106
  width: 100%;
77
107
  height: var(--splitter-size);
108
+ margin-top: calc((var(--_splitter-box) - var(--splitter-size)) / 2);
78
109
  }
79
110
  `;
80
111
  //#endregion
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
3
3
  import { UFormControlElement } from "../UFormControlElement.js";
4
4
  import { Locale } from "../../utilities/Locale.js";
5
5
  import { styles } from "./USwitch.styles.js";
@@ -21,6 +21,11 @@ var styles = css`
21
21
  :host {
22
22
  display: inline-flex;
23
23
  flex-direction: column;
24
+ /* WCAG 2.2 SC 2.5.8 — 트랙(--switch-track-height)의 시각 치수는 그대로 두고
25
+ 포인터 타깃만 24px 하한을 갖는다. UCheckbox 와 같은 처방이다.
26
+ ⚠이 주석에 백틱을 쓰면 css 템플릿이 그 자리에서 끝난다(sweep 의 「css 백틱」). */
27
+ min-block-size: 24px;
28
+ justify-content: center;
24
29
  color: var(--u-txt-color, #212121);
25
30
  font-size: inherit;
26
31
  font-family: var(--u-font-base);
@@ -108,7 +113,7 @@ var styles = css`
108
113
  .track-unchecked {
109
114
  opacity: 1;
110
115
  right: var(--switch-thumb-offset);
111
- color: var(--u-txt-color-weak, #757575);
116
+ color: var(--u-txt-color-weak, #616161);
112
117
  }
113
118
  :host([checked]) .track-unchecked {
114
119
  opacity: 0;
@@ -166,7 +171,7 @@ var styles = css`
166
171
  .thumb-unchecked {
167
172
  opacity: 1;
168
173
  transform: scale(1) rotate(0deg);
169
- color: var(--u-txt-color-weak, #757575);
174
+ color: var(--u-txt-color-weak, #616161);
170
175
  }
171
176
  :host([checked]) .thumb-unchecked {
172
177
  opacity: 0;
@@ -185,7 +190,7 @@ var styles = css`
185
190
 
186
191
  .description {
187
192
  margin-top: 0.5em;
188
- color: var(--u-txt-color-weak, #757575);
193
+ color: var(--u-txt-color-weak, #616161);
189
194
  font-size: 0.75em;
190
195
  line-height: 1.3;
191
196
  }
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import "../button/UButton.js";
5
5
  import "../icon/UIcon.js";
6
6
  import { styles } from "./UTab.styles.js";
@@ -7,7 +7,7 @@ var styles = css`
7
7
  display: inline-flex;
8
8
  font-size: 0.9em;
9
9
  font-weight: 500;
10
- color: var(--u-txt-color-weak, #757575);
10
+ color: var(--u-txt-color-weak, #616161);
11
11
  white-space: nowrap;
12
12
  user-select: none;
13
13
  cursor: pointer;
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import { UPanel } from "../panel/UPanel.js";
5
5
  import { UTab } from "../tab/UTab.js";
6
6
  import { styles } from "./UTabPanel.styles.js";
@@ -45,7 +45,7 @@ var UTabPanel = class UTabPanel extends UElement {
45
45
  const enabledTabs = this.tabs.filter((t) => !t.disabled);
46
46
  const currentIndex = enabledTabs.indexOf(e.currentTarget);
47
47
  if (currentIndex === -1) return;
48
- let targetIndex = -1;
48
+ let targetIndex;
49
49
  switch (e.key) {
50
50
  case this.isVertical ? "ArrowDown" : "ArrowRight":
51
51
  targetIndex = (currentIndex + 1) % enabledTabs.length;
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import "../icon/UIcon.js";
5
5
  import { statusIcon } from "../../utilities/statusIcon.js";
6
6
  import { styles } from "./UTag.styles.js";
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import { styles } from "./UText.styles.js";
5
5
  import { customElement, property } from "lit/decorators.js";
6
6
  import { html, literal } from "lit/static-html.js";
@@ -76,7 +76,7 @@ var styles = css`
76
76
  * 콜아웃 박스라 u-text 의 문제가 아니었다.
77
77
  */
78
78
  :host([tone="weak"]) {
79
- color: var(--u-txt-color-weak, #757575);
79
+ color: var(--u-txt-color-weak, #616161);
80
80
  }
81
81
 
82
82
  :host([tone="strong"]) {
@@ -11,6 +11,11 @@ type TextareaResize = 'none' | 'vertical' | 'horizontal' | 'both' | 'auto';
11
11
  * @csspart textarea - 실제 텍스트에어리어 요소
12
12
  * @csspart counter - 글자 수 표시 영역
13
13
  *
14
+ * @cssprop --u-textarea-display - 호스트의 display (기본값: inline-block). 폼/그리드 셀에서
15
+ * 컨테이너 폭을 채우려면 `block`으로 지정한다.
16
+ * @cssprop --u-textarea-width - 호스트의 width (기본값: auto). flex 컨테이너처럼 block만으로는
17
+ * 늘어나지 않는 맥락에서 `100%`로 지정한다.
18
+ *
14
19
  * @event input - 입력값이 변경될 때 발생
15
20
  * @event change - 값이 확정됐을 때 발생
16
21
  */
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
3
3
  import { UFormControlElement } from "../UFormControlElement.js";
4
4
  import { Locale } from "../../utilities/Locale.js";
5
5
  import "../field/UField.js";
@@ -2,7 +2,10 @@ import { css } from "lit";
2
2
  //#region src/components/textarea/UTextarea.styles.ts
3
3
  var styles = css`
4
4
  :host {
5
- display: inline-block;
5
+ /* 폼/그리드 셀에서 컨테이너 폭을 채우려면 소비자가 --u-textarea-display: block 을 준다.
6
+ flex 컨테이너처럼 block 만으로 늘어나지 않는 맥락을 위해 width 경로도 함께 연다. */
7
+ display: var(--u-textarea-display, inline-block);
8
+ width: var(--u-textarea-width, auto);
6
9
  color: var(--u-txt-color, #212121);
7
10
  font-size: inherit;
8
11
  font-family: var(--u-font-base);
@@ -117,7 +120,7 @@ var styles = css`
117
120
  word-wrap: break-word;
118
121
  }
119
122
  textarea::placeholder {
120
- color: var(--u-txt-color-weak, #757575);
123
+ color: var(--u-txt-color-weak, #616161);
121
124
  }
122
125
  textarea:disabled {
123
126
  cursor: not-allowed;
@@ -155,7 +158,7 @@ var styles = css`
155
158
  .counter {
156
159
  margin-top: 0.25em;
157
160
  text-align: right;
158
- color: var(--u-txt-color-weak, #757575);
161
+ color: var(--u-txt-color-weak, #616161);
159
162
  font-size: 0.75em;
160
163
  line-height: 1.2;
161
164
  }
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
3
3
  import { UFloatingElement } from "../UFloatingElement.js";
4
4
  import { styles } from "./UTooltip.styles.js";
5
5
  import { html } from "lit";
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import { UTreeItem } from "../tree-item/UTreeItem.js";
5
5
  import { styles } from "./UTree.styles.js";
6
6
  import { html } from "lit";
@@ -1,6 +1,6 @@
1
1
  import { UElement } from "../UElement.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
4
4
  import "../spinner/USpinner.js";
5
5
  import "../icon/UIcon.js";
6
6
  import { styles } from "./UTreeItem.styles.js";