@iyulab/components 1.46.0 → 1.47.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 +54 -0
- 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/components/UOverlayElement.js +8 -4
- package/dist/components/date-picker/UDatePicker.d.ts +4 -0
- package/dist/components/input/UInput.d.ts +9 -1
- package/dist/components/input/UInput.js +5 -2
- package/dist/components/select/USelect.styles.js +3 -0
- package/dist/components/tag/UTag.d.ts +1 -1
- package/dist/components/tag/UTag.styles.js +10 -0
- package/dist/index.js +2 -2
- package/dist/styles/dark.css +18 -1
- package/dist/styles/light.css +21 -1
- package/dist/utilities/Dialog.d.ts +8 -1
- package/dist/utilities/Dialog.js +4 -1
- package/dist/utilities/elements.d.ts +14 -0
- package/dist/utilities/elements.js +39 -1
- package/package.json +1 -1
- package/skills/iyulab-components/references/components/drawer.md +1 -1
- package/skills/iyulab-components/references/components/input.md +1 -1
- package/skills/iyulab-components/references/components/tag.md +6 -2
- package/skills/iyulab-components/references/utilities/dialog.md +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.47.1] - 2026-09-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`u-dialog` / `u-drawer` initial focus now reaches the control you asked for.** Three cases
|
|
8
|
+
sent it to the first tabbable element instead (often the close button):
|
|
9
|
+
- **`<u-input autofocus>`** (and any control component) — the component host was handed to the
|
|
10
|
+
focus trap, which does not count a host as focusable and fell back. The overlay now focuses the
|
|
11
|
+
target itself, so the component forwards focus to its inner field.
|
|
12
|
+
- **A form component slotted into the overlay** — `[autofocus]` and the first input control were
|
|
13
|
+
looked up with `querySelector`, which stops at shadow roots. The search now goes through them.
|
|
14
|
+
- **A `u-select` before the target** — once the search goes through shadow roots it must not stop
|
|
15
|
+
at the closed popover every `u-select` keeps inside (it carries an `autofocus` attribute of its
|
|
16
|
+
own). Only elements that can actually take focus are candidates.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`querySelectorDeep(roots, selectors, accept?)` and `isFocusCandidate(el)`** in
|
|
21
|
+
`utilities/elements` — the shadow-piercing lookup and the focusability test the overlays use,
|
|
22
|
+
for other layers that place initial focus the same way.
|
|
23
|
+
|
|
24
|
+
## [1.47.0] - 2026-09-28
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- **Chart palette tokens `--u-chart-color-1` … `--u-chart-color-8`** — eight series colours, in a
|
|
29
|
+
fixed order, checked together for lightness, colour-vision-deficiency separation and (dark)
|
|
30
|
+
contrast, in both sheets. See "Chart palette" in `docs/theming.md`.
|
|
31
|
+
- **`Dialog.confirm(message, { confirmColor })`** and **`DialogAction.color`**. Confirming an
|
|
32
|
+
action that cannot be undone had no way to say so — the confirm button was always the default
|
|
33
|
+
colour. `confirmColor: 'danger'` draws it in `danger`.
|
|
34
|
+
- **`u-tag color="gray"`** — a colourless label on the decorative axis. `neutral`, the default,
|
|
35
|
+
follows the brand colour, so there was no way to draw a gray tag: a "Pending" status tag came out
|
|
36
|
+
the same blue as an `info` "Shipped" next to it. `gray` reads the neutral ramp and, like the
|
|
37
|
+
other decorative colours, ignores re-branding.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **`--u-font-mono` lists `Consolas`** after `Cascadia Code`, so Windows installs without Cascadia
|
|
42
|
+
get a code face instead of `Courier New`.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **An empty `u-select` is as tall as a filled one.** With no value and no placeholder, its display
|
|
47
|
+
area had no line box, so the control was shorter than a `u-select` with a value — and shorter
|
|
48
|
+
than a `u-input` beside it in the same form row, which knocked the labels out of line.
|
|
49
|
+
- **`u-input` commits its value before `Enter` submits the form.** `change` used to fire only on
|
|
50
|
+
blur, so pressing `Enter` in a form submitted it first and committed the value afterwards — a
|
|
51
|
+
form that reads values from `change` (the usual React `onChange` wiring) submitted empty fields,
|
|
52
|
+
and a sign-in form typed and sent with `Enter` failed. `change` now follows the native input: it
|
|
53
|
+
fires on `Enter` and on blur, before the submit, and only when the value changed.
|
|
54
|
+
⚠A blur that did not change the value no longer fires `change`. If you relied on that, listen
|
|
55
|
+
for `blur` (or `focusout`) instead.
|
|
56
|
+
|
|
3
57
|
## [1.46.0] - 2026-09-24
|
|
4
58
|
|
|
5
59
|
### Changed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region \0glob-assets_raw/dark.css.e8ac080d
|
|
2
|
-
var dark_css_default = ":root[theme=\"dark\"] {\n color-scheme: dark;\n\n /* Neutral Colors */\n --u-neutral-0: #000000;\n --u-neutral-50: #0A0A0A;\n --u-neutral-100: #121212;\n --u-neutral-200: #1E1E1E;\n --u-neutral-300: #2A2A2A;\n --u-neutral-400: #3D3D3D;\n --u-neutral-500: #525252;\n --u-neutral-600: #6E6E6E;\n --u-neutral-700: #8A8A8A;\n --u-neutral-800: #B0B0B0;\n --u-neutral-900: #D4D4D4;\n --u-neutral-1000: #FFFFFF;\n\n /* Blue Colors */\n --u-blue-0: #030D1A;\n --u-blue-100: #061629;\n --u-blue-200: #0A223B;\n --u-blue-300: #103150;\n --u-blue-400: #174167;\n --u-blue-500: #205281;\n --u-blue-600: #2A659D;\n --u-blue-700: #3678B8;\n --u-blue-800: #478DCE;\n --u-blue-900: #5DA2DF;\n --u-blue-1000: #79BBEA;\n\n /* Green Colors */\n --u-green-0: #06140C;\n --u-green-100: #0A2114;\n --u-green-200: #10301D;\n --u-green-300: #164228;\n --u-green-400: #1F5535;\n --u-green-500: #2A6942;\n --u-green-600: #367E50;\n --u-green-700: #4A9563;\n --u-green-800: #63AB7A;\n --u-green-900: #80BE97;\n --u-green-1000: #9BCFB1;\n\n /* Yellow Colors */\n --u-yellow-0: #1C1300;\n --u-yellow-100: #2D1E00;\n --u-yellow-200: #402B00;\n --u-yellow-300: #553900;\n --u-yellow-400: #6B4900;\n --u-yellow-500: #825A00;\n --u-yellow-600: #9A6C00;\n --u-yellow-700: #B08012;\n --u-yellow-800: #C69635;\n --u-yellow-900: #D9AD5A;\n --u-yellow-1000: #E8C57F;\n\n /* Red Colors */\n --u-red-0: #1C0707;\n --u-red-100: #2C0B0B;\n --u-red-200: #3E1111;\n --u-red-300: #541818;\n --u-red-400: #6C2020;\n --u-red-500: #852A2A;\n --u-red-600: #A13535;\n --u-red-700: #B94949;\n --u-red-800: #CB6262;\n --u-red-900: #D98383;\n --u-red-1000: #E7A2A2;\n\n /* Orange Colors */\n --u-orange-0: #1D0E00;\n --u-orange-100: #2F1700;\n --u-orange-200: #421F00;\n --u-orange-300: #582A00;\n --u-orange-400: #703600;\n --u-orange-500: #8A4500;\n --u-orange-600: #A55600;\n --u-orange-700: #BD6A18;\n --u-orange-800: #D1823C;\n --u-orange-900: #E19D67;\n --u-orange-1000: #EDB992;\n\n /* Teal Colors */\n --u-teal-0: #041411;\n --u-teal-100: #07201B;\n --u-teal-200: #0B2E28;\n --u-teal-300: #10403A;\n --u-teal-400: #16544D;\n --u-teal-500: #1E6860;\n --u-teal-600: #297D74;\n --u-teal-700: #3A9389;\n --u-teal-800: #54A89F;\n --u-teal-900: #73BBB3;\n --u-teal-1000: #93CBC5;\n\n /* Cyan Colors */\n --u-cyan-0: #041318;\n --u-cyan-100: #071F29;\n --u-cyan-200: #0B2D3A;\n --u-cyan-300: #104050;\n --u-cyan-400: #165469;\n --u-cyan-500: #1E6A82;\n --u-cyan-600: #287F9C;\n --u-cyan-700: #3995B5;\n --u-cyan-800: #53AACC;\n --u-cyan-900: #73BEDD;\n --u-cyan-1000: #95CFE8;\n\n /* Purple Colors */\n --u-purple-0: #150A22;\n --u-purple-100: #220F36;\n --u-purple-200: #31164B;\n --u-purple-300: #432064;\n --u-purple-400: #572B80;\n --u-purple-500: #6C379C;\n --u-purple-600: #8245B7;\n --u-purple-700: #975BCB;\n --u-purple-800: #AB79D9;\n --u-purple-900: #BD99E2;\n --u-purple-1000: #CEB8EA;\n\n /* Pink Colors */\n --u-pink-0: #1F0A14;\n --u-pink-100: #310F20;\n --u-pink-200: #451532;\n --u-pink-300: #5C1D45;\n --u-pink-400: #74285A;\n --u-pink-500: #8F336F;\n --u-pink-600: #AB4187;\n --u-pink-700: #C0569D;\n --u-pink-800: #D174B3;\n --u-pink-900: #E095C7;\n --u-pink-1000: #EBB5D9;\n\n /* ==========================================================================\n Role Colors — 의미 역할 층\n 컴포넌트는 팔레트 프리미티브가 아니라 이 층을 참조한다.\n 브랜드 색 교체는 아래 25개만 재정의하면 시맨틱 층까지 따라온다.\n\n 단은 '강도' 축이다 (weakest -> strong). 용도(배경/테두리/텍스트)는\n 소비처가 정한다 -- 단을 속성에 묶으면 primary 버튼의 배경이 어느\n 단인지 같은 모순이 생긴다.\n\n ★**다만 두 단은 용도가 확정돼 있다** — 대비 요구가 서로 다르기 때문이다.\n `-color` = **면**. `--u-*-txt-color` 가 그 위에 얹히므로 on-color 기준 4.5.\n `-strong` = **글자·아이콘**. `--u-bg-color` 위에 놓이므로 바탕 기준 4.5.\n 라이트에서는 바탕도 on-color 도 흰색이라 두 요구가 한 조건으로 합쳐지지만,\n **다크에서는 정반대 방향**이다(바탕 #121212 · on-color #FFFFFF). 바탕에서 읽히는\n 밝은 단은 흰 글자를 못 받고, 흰 글자를 받는 어두운 단은 바탕에서 안 읽힌다.\n ⇒ 다크에서 `-color` 와 `-strong` 이 두 단 벌어지는 것이 그 결과다.\n `tests/build/token-contrast.test.ts` 가 값을 지킨다.\n ========================================================================== */\n\n /* primary — 브랜드 · 강조 · 포커스 · 링크 */\n --u-primary-color-weakest: var(--u-blue-200);\n --u-primary-color-weaker: var(--u-blue-300);\n --u-primary-color-weak: var(--u-blue-500);\n --u-primary-color: var(--u-blue-600); /* 면: 흰 글자 6.09 ✓ */\n --u-primary-color-strong: var(--u-blue-800); /* 글자: 바탕 5.32 ✓ (700 은 4.05 ✗) */\n\n /* info — 정보 안내 (primary 와 기본값은 같으나 역할이 다르다 — 브랜딩은 primary 만 바꾼다) */\n --u-info-color-weakest: var(--u-blue-200);\n --u-info-color-weaker: var(--u-blue-300);\n --u-info-color-weak: var(--u-blue-500);\n --u-info-color: var(--u-blue-600);\n --u-info-color-strong: var(--u-blue-800);\n\n /* success — 성공 · 완료 */\n --u-success-color-weakest: var(--u-green-200);\n --u-success-color-weaker: var(--u-green-300);\n --u-success-color-weak: var(--u-green-500);\n --u-success-color: var(--u-green-600);\n --u-success-color-strong: var(--u-green-700);\n\n /* warning — 주의 */\n --u-warning-color-weakest: var(--u-yellow-200);\n --u-warning-color-weaker: var(--u-yellow-300);\n --u-warning-color-weak: var(--u-yellow-500);\n --u-warning-color: var(--u-yellow-600);\n --u-warning-color-strong: var(--u-yellow-700);\n\n /* danger — 오류 · 위험 · 유효성 실패 */\n --u-danger-color-weakest: var(--u-red-200);\n --u-danger-color-weaker: var(--u-red-300);\n --u-danger-color-weak: var(--u-red-500);\n --u-danger-color: var(--u-red-600); /* 면: 흰 글자 6.83 ✓ */\n --u-danger-color-strong: var(--u-red-800); /* 글자: 바탕 4.87 ✓ (700 은 3.67 ✗) */\n /* Text Colors */\n --u-txt-color: var(--u-neutral-900);\n --u-txt-color-inverse: var(--u-neutral-100);\n\n /* 유채색 배경 위의 글자 — warning 만 다르다(light.css 참조). */\n --u-primary-txt-color: #FFFFFF;\n --u-info-txt-color: #FFFFFF;\n --u-success-txt-color: #FFFFFF;\n --u-danger-txt-color: #FFFFFF;\n /* ★라이트 시트와 같은 이유로 중립 최상단을 쓴다 — 다크에서는 그 값이 #FFFFFF 라\n 결과가 종전과 같다(4.65 ✓). 리터럴 대신 토큰을 쓰는 이유는 라이트에서 뒤집히기\n 때문이다(#000000). 두 시트가 같은 선언이 되어 어긋날 자리가 없어진다. */\n --u-warning-txt-color: var(--u-neutral-1000);\n --u-txt-color-hover: var(--u-primary-color-strong);\n --u-txt-color-active: var(--u-primary-color-strong);\n --u-txt-color-disabled: var(--u-neutral-500);\n /* 라이트와 같은 기준 — 놓이는 모든 면에서 AA. neutral-700(#8A8A8A)은 바탕 5.43 ·\n 올림면(neutral-300) 4.16 · active 면(neutral-400) 3.15 로 미달이었다.\n neutral-800(#B0B0B0) = 8.64 · 6.62 · 5.01. 본문(neutral-900)과의 대비비 1.46. */\n --u-txt-color-weak: var(--u-neutral-800);\n --u-txt-color-strong: var(--u-neutral-1000);\n\n --u-link-txt-color: var(--u-primary-color-strong);\n --u-tooltip-txt-color: var(--u-neutral-100);\n\n /* Icon Colors */\n --u-icon-color: var(--u-neutral-800);\n --u-icon-color-inverse: var(--u-neutral-100);\n --u-icon-color-hover: var(--u-primary-color-strong);\n --u-icon-color-active: var(--u-primary-color-strong);\n --u-icon-color-disabled: var(--u-neutral-500);\n\n /* Border Colors\n ★`-weak` 는 `neutral-300` 일 수 없다 — `--u-bg-color-raised` 가 같은 단이라, 올림면(사이드바·\n 표 머리/행·마스터-디테일 구분선) 위에 그리는 약한 선이 **면과 같은 색**(대비 1.00)이 되어\n 화면에서 사라진다. 라이트는 200 단이 올림면(50)과 떨어져 있어 보인다. 램프에서 올림면(300)\n 위로 올릴 수 있는 다음 단이 400 뿐이라 `-weak` 는 이 테마에서 `--u-border-color` 와 같은\n 단이다 — 다크에서는 «약함/보통» 두 단이 하나로 합쳐지지만, 종전 `-weak` 는 그것이 쓰이는\n 면 위에서 애초에 구별되지 않았다. */\n --u-border-color: var(--u-neutral-400);\n --u-border-color-weak: var(--u-neutral-400);\n --u-border-color-strong: var(--u-neutral-500);\n --u-border-color-hover: var(--u-neutral-500);\n\n /* ★상태 테두리는 `-strong` 단이다 — light.css 의 같은 자리 주석 참조.\n 이 테마가 실제로 미달이었다: focus 2.74 · invalid 2.44 → 4.74 / 4.34. */\n --u-input-border-color: var(--u-neutral-400);\n --u-input-border-color-hover: var(--u-neutral-500);\n --u-input-border-color-focus: var(--u-primary-color-strong);\n --u-input-border-color-invalid: var(--u-danger-color-strong);\n\n /* Background Colors */\n --u-bg-color: var(--u-neutral-100);\n --u-bg-color-inverse: var(--u-neutral-0);\n --u-bg-color-hover: var(--u-neutral-300);\n --u-bg-color-active: var(--u-neutral-400);\n --u-bg-color-disabled: var(--u-neutral-100);\n\n /* 면 높이 — 상세는 light.css 참조. 다크는 **바탕보다 밝은 쪽**이 위다.\n neutral-300(#2A2A2A)은 바탕(#121212) 대비 1.42 로, 소비 측이 오버라이드로 쓰던\n neutral-200(1.15)보다 실제로 더 잘 구분된다 — 그 오버라이드가 해결하려던 증상이\n *\"툴바·헤더가 배경에 묻힌다\"* 였다. */\n --u-bg-color-raised: var(--u-neutral-300);\n\n /* ★올림면 위의 hover — `--u-bg-color-hover`(전역, 바탕면 전용)와 값이 같아서\n («둘 다 neutral-300») 카드·표 머리 위에 마우스를 올려도 아무 일도 안 일어났다\n (소비자 실측). 전역 토큰 하나로는 \"지금 위에 있는 면\"을\n 알 방법이 없어(참조 지점마다 계산 기준이 다를 수 없다) **전용 토큰**을 신설한다.\n\n ⚠**A안**(`raised`를 neutral-200으로) — 과거에 거부된 값(위 주석). **B안**(전역\n `hover`를 neutral-400으로) — `--u-bg-color-active` 와 충돌해 결함이 다른 쌍으로\n 옮겨간다. ⇒ hover 는 본래 \"현재 면보다 한 단 위\"이지 절대 단이 아니므로\n `color-mix()` 로 raised 자신을 기준 삼아 상대 계산한다.\n\n N=6% 는 raised(L≈0.023)와 active(L≈0.047, neutral-400) 사이 대비 계산으로 골랐다 —\n 결과 L≈0.038, raised 대비 ≈1.21(라이트의 기존 \"약한\" 1.04보다 뚜렷하고, `bg→raised`\n 의 기존 1.31 과 비슷한 체감), active 와는 값이 달라 겹치지 않는다(≈#373737 vs\n active #3D3D3D). N 을 더 올리면(≈10%+) active 를 넘어서 순서가 뒤집힌다 — 확인함. */\n --u-bg-color-raised-hover: color-mix(in srgb, var(--u-bg-color-raised), white 6%);\n\n /* 유채색 표면 — 라이트와 **같은 단이 아니라 같은 세기**로 짝지었다(light.css 참조).\n 팔레트 유채색 틴트가 다크에서 짓눌리므로 한 단 위를 쓴다. green 은 대칭이라 그대로. */\n --u-primary-bg-color: var(--u-blue-100);\n --u-info-bg-color: var(--u-blue-100);\n --u-success-bg-color: var(--u-green-0);\n --u-danger-bg-color: var(--u-red-100);\n /* warning 합류 — 라이트는 yellow-200 이다(단 이름이 다른 이유는 light.css 참조). */\n --u-warning-bg-color: var(--u-yellow-100);\n\n --u-input-bg-color: var(--u-neutral-200);\n --u-panel-bg-color: var(--u-neutral-200);\n --u-overlay-bg-color: rgba(0, 0, 0, 0.7);\n --u-tooltip-bg-color: rgba(255, 255, 255, 0.85);\n\n /* Shadow Colors */\n --u-shadow-color-weaker: rgba(0, 0, 0, 0.15);\n --u-shadow-color-weak: rgba(0, 0, 0, 0.25);\n --u-shadow-color-normal: rgba(0, 0, 0, 0.35);\n --u-shadow-color-strong: rgba(0, 0, 0, 0.45);\n --u-shadow-color-stronger: rgba(0, 0, 0, 0.60);\n\n /* Elevation Scale — 근거는 light.css 의 같은 자리 주석 참조.\n ★다크는 알파가 3배 가까이 진하다 — 리터럴로 흩어져 있던 종전에는 이 차이가\n 적용되지 않아 다크에서 그림자가 사실상 보이지 않았다. */\n --u-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 1px rgba(0, 0, 0, 0.14); /* = shadow-color-weak */\n --u-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.18); /* = shadow-color-normal */\n --u-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.22); /* = shadow-color-strong */\n --u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.30); /* = shadow-color-stronger */\n\n\n /* Scrollbar Colors */\n --u-scrollbar-color: var(--u-neutral-500);\n --u-scrollbar-color-hover: var(--u-neutral-600);\n --u-scrollbar-track-color: transparent;\n}\n\n/* ==========================================================================\n ★모드와 무관한 스케일 — 반경·여백·글자 스케일·모션·글꼴.\n 값이 light.css 와 **같다.** 그런데 위 블록(`:root[theme=\"dark\"]`, 특이도 0,1,1)에 두면\n `:root`(0,1,0)로 이 토큰을 덮는 **모든 층**(하우스 프리셋·소비자 브랜드 시트)이 다크\n 모드에서만 **로드 순서와 무관하게** 진다 — 에러도 경고도 없이, 색은 정상으로 바뀌므로\n «다크가 잘 된다» 로 보인다. `:where()` 로 특이도를 `:root` 와 같게 두면 층 모델이 라이트와\n 똑같이 로드 순서로 선다.\n ⚠이 블록을 지우지 말 것 — 이 시트만 쓰는 «고정 다크 디자인» 소비자(docs/theming.md)는\n 이 토큰들을 여기서 받는다. 두 시트를 함께 쓸 때는 값이 같으므로 어느 쪽이 이겨도 같다.\n ========================================================================== */\n:root:where([theme=\"dark\"]) {\n /* ==========================================================================\n Radius Scale — 모서리 반경\n 리터럴을 흩뿌리면 값이 갈린다(실제로 pill 이 999px/9999px 두 표기로 나뉘어 있었다).\n ========================================================================== */\n --u-radius-none: 0;\n --u-radius-sm: 3px;\n --u-radius-md: 4px;\n --u-radius-lg: 6px;\n --u-radius-xl: 8px;\n /* ★상단 2단은 **면(surface)용**이다 — 카드·패널·대화상자처럼 큰 사각형은 컨트롤과\n 같은 반경을 쓰면 각져 보인다. 기존 5단은 **컨트롤용**이고 값을 바꾸지 않는다\n (바꾸면 모든 소비자의 버튼·입력이 동시에 움직인다). */\n --u-radius-2xl: 12px;\n --u-radius-3xl: 16px;\n --u-radius-pill: 9999px;\n --u-radius-circle: 50%;\n\n /* ==========================================================================\n Space Scale — 컨테이너·오버레이의 절대 여백\n ⚠**여백은 하나의 축이 아니다.** 이 스케일은 컨테이너/오버레이의 **레이아웃 여백**만\n 담당한다. 폼·인라인 요소의 `em` 여백은 상속된 `font-size` 에 비례하는 것이 의도이므로\n **여기로 흡수하지 않는다.** 반경과 마찬가지로 테마와 무관하므로 두 시트가 같다.\n 축 구분과 근거는 docs/design-tokens.md 참조.\n ========================================================================== */\n --u-space-3xs: 2px;\n --u-space-2xs: 4px;\n --u-space-xs: 6px;\n --u-space-sm: 8px;\n --u-space-md: 12px;\n --u-space-lg: 16px;\n /* ★상단 4단은 **화면 리듬**이다 — 카드 안쪽 여백(20~24)·섹션 간격(24~32)·페이지 여백\n (32~40). 종전에는 이 구간이 통째로 비어 있어 소비자가 전부 리터럴로 적었고,\n 그래서 앱마다 화면 밀도가 달라졌다. `lg`(16px) 이하는 **요소 사이**, `xl` 이상은\n **영역 사이**로 나눠 쓴다.\n ⚠`xs: 6px` 는 4px 격자에서 벗어나 있으나 **바꾸지 않는다** — 이미 배선된 컨트롤\n 여백이 전부 움직인다. 신규 단은 전부 4의 배수로 둔다. */\n --u-space-xl: 20px;\n --u-space-2xl: 24px;\n --u-space-3xl: 32px;\n --u-space-4xl: 40px;\n\n /* ==========================================================================\n Type Scale — 글자 크기·굵기·행간·자간의 **한 벌**\n ★**크기만 주면 스케일이 되지 않는다.** 소비자가 크기만 받고 굵기·행간을 각자 정하면\n 결국 화면마다 다른 위계가 생긴다 — 그래서 네 값을 **단 단위로 묶어** 낸다.\n\n 단 이름은 크기가 아니라 **역할**이다(`lg`/`xl` 이 아니라 `title`/`label`). 역할로 두면\n 소비자가 *\"어느 크기를 쓸까\"* 가 아니라 *\"이 글자는 무엇인가\"* 를 묻게 된다.\n\n ★**한글 기준으로 값을 골랐다**:\n ⑴ 행간은 **1.4 이상**. 라틴 관례(1.2)는 한글에서 답답하다 — 받침 때문에 글자 상자가\n 세로로 꽉 차 있어 라틴과 같은 행간이면 줄이 붙어 보인다.\n ⑵ 자간은 **0 이 기본**이고 큰 제목만 **음수**. 한글에 양수 자간(letter-spacing)을 주면\n 가독성이 떨어진다 — 라틴 소문자 조판 관례를 그대로 옮기면 안 되는 자리다.\n ⑶ `overline` 에만 양수 자간을 둔다. 그 단은 **영문·숫자 라벨**을 전제한 자리이고,\n 한글을 넣을 소비자는 자간을 0 으로 덮어야 한다(문서에 명시).\n\n ⚠**`text-transform` 은 토큰으로 내지 않는다.** 한글에는 대문자가 없어 `uppercase` 가\n 아무 효과가 없고, 영문이 섞이면 그것만 커져 오히려 어수선해진다.\n ========================================================================== */\n --u-text-display-size: 26px;\n --u-text-display-weight: 700;\n --u-text-display-leading: 1.4;\n --u-text-display-tracking: -0.02em;\n\n --u-text-title-size: 20px;\n --u-text-title-weight: 700;\n --u-text-title-leading: 1.45;\n --u-text-title-tracking: -0.01em;\n\n --u-text-subtitle-size: 16px;\n --u-text-subtitle-weight: 600;\n --u-text-subtitle-leading: 1.5;\n --u-text-subtitle-tracking: 0;\n\n --u-text-body-size: 14px;\n --u-text-body-weight: 400;\n --u-text-body-leading: 1.6;\n --u-text-body-tracking: 0;\n\n --u-text-label-size: 13px;\n --u-text-label-weight: 600;\n --u-text-label-leading: 1.5;\n --u-text-label-tracking: 0;\n\n --u-text-caption-size: 12px;\n --u-text-caption-weight: 400;\n --u-text-caption-leading: 1.5;\n --u-text-caption-tracking: 0;\n\n --u-text-overline-size: 11px;\n --u-text-overline-weight: 700;\n --u-text-overline-leading: 1.45;\n --u-text-overline-tracking: 0.06em;\n\n /* ==========================================================================\n Motion — 지속시간·이징\n ★값이 없으면 앱마다 다른 속도가 생기고, `prefers-reduced-motion` 은 **반드시**\n 빠뜨리는 앱이 나온다. 축을 여기 두고 존중 규칙은 아래 미디어 쿼리가 진다.\n ========================================================================== */\n --u-duration-instant: 80ms;\n --u-duration-fast: 140ms;\n --u-duration-normal: 220ms;\n --u-duration-slow: 320ms;\n --u-ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --u-ease-decelerate: cubic-bezier(0, 0, 0, 1);\n --u-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);\n\n /* ==========================================================================\n Font Styles\n ★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**\n 종전 스택(`-apple-system, Segoe UI, Noto Sans, Helvetica, Arial`)에는 **한중일 글립을\n 가진 폰트가 하나도 없었다.** Windows 에서 한글은 `Segoe UI` 에 없으므로 UA 가 임의로\n 맑은 고딕을 고르고, macOS 는 `-apple-system` 이 Apple SD Gothic Neo 를 준다 ⇒ **같은 앱이\n OS 마다 다른 글꼴로 렌더**됐다. 폴백을 명시하면 그 선택이 결정적이 된다.\n ⚠**웹폰트를 로드하지 않는다.** 라이브러리가 네트워크 요청을 만들면 소비자의 CSP·\n 오프라인 환경을 깬다. 스택 맨 앞의 `Pretendard` 는 **소비자가 로드했을 때만** 잡히는\n 선택적 이름이다(없으면 조용히 다음으로 넘어간다).\n ========================================================================== */\n --u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';\n --u-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;\n --u-font-serif: 'Georgia', 'Times New Roman', Times, serif;\n --u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;\n --u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --u-font-rounded: 'Nunito', 'Quicksand', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n\n/* ★`prefers-reduced-motion` — light.css 와 같은 규칙을 이 시트도 진다. 이 시트만 쓰는\n 소비자가 있고, 두 시트를 함께 쓸 때는 어느 시트가 뒤에 오든 **마지막 선언이 이 0ms**\n 가 되도록 각 시트가 자기 블록 뒤에 둔다. 종전에는 지속시간이 위 (0,1,1) 블록에 있어\n 다크 모드에서 «동작 줄이기» 설정이 **무시됐다.** */\n@media (prefers-reduced-motion: reduce) {\n :root:where([theme=\"dark\"]) {\n --u-duration-instant: 0ms;\n --u-duration-fast: 0ms;\n --u-duration-normal: 0ms;\n --u-duration-slow: 0ms;\n }\n}\n";
|
|
2
|
+
var dark_css_default = ":root[theme=\"dark\"] {\n color-scheme: dark;\n\n /* Neutral Colors */\n --u-neutral-0: #000000;\n --u-neutral-50: #0A0A0A;\n --u-neutral-100: #121212;\n --u-neutral-200: #1E1E1E;\n --u-neutral-300: #2A2A2A;\n --u-neutral-400: #3D3D3D;\n --u-neutral-500: #525252;\n --u-neutral-600: #6E6E6E;\n --u-neutral-700: #8A8A8A;\n --u-neutral-800: #B0B0B0;\n --u-neutral-900: #D4D4D4;\n --u-neutral-1000: #FFFFFF;\n\n /* Blue Colors */\n --u-blue-0: #030D1A;\n --u-blue-100: #061629;\n --u-blue-200: #0A223B;\n --u-blue-300: #103150;\n --u-blue-400: #174167;\n --u-blue-500: #205281;\n --u-blue-600: #2A659D;\n --u-blue-700: #3678B8;\n --u-blue-800: #478DCE;\n --u-blue-900: #5DA2DF;\n --u-blue-1000: #79BBEA;\n\n /* Green Colors */\n --u-green-0: #06140C;\n --u-green-100: #0A2114;\n --u-green-200: #10301D;\n --u-green-300: #164228;\n --u-green-400: #1F5535;\n --u-green-500: #2A6942;\n --u-green-600: #367E50;\n --u-green-700: #4A9563;\n --u-green-800: #63AB7A;\n --u-green-900: #80BE97;\n --u-green-1000: #9BCFB1;\n\n /* Yellow Colors */\n --u-yellow-0: #1C1300;\n --u-yellow-100: #2D1E00;\n --u-yellow-200: #402B00;\n --u-yellow-300: #553900;\n --u-yellow-400: #6B4900;\n --u-yellow-500: #825A00;\n --u-yellow-600: #9A6C00;\n --u-yellow-700: #B08012;\n --u-yellow-800: #C69635;\n --u-yellow-900: #D9AD5A;\n --u-yellow-1000: #E8C57F;\n\n /* Red Colors */\n --u-red-0: #1C0707;\n --u-red-100: #2C0B0B;\n --u-red-200: #3E1111;\n --u-red-300: #541818;\n --u-red-400: #6C2020;\n --u-red-500: #852A2A;\n --u-red-600: #A13535;\n --u-red-700: #B94949;\n --u-red-800: #CB6262;\n --u-red-900: #D98383;\n --u-red-1000: #E7A2A2;\n\n /* Orange Colors */\n --u-orange-0: #1D0E00;\n --u-orange-100: #2F1700;\n --u-orange-200: #421F00;\n --u-orange-300: #582A00;\n --u-orange-400: #703600;\n --u-orange-500: #8A4500;\n --u-orange-600: #A55600;\n --u-orange-700: #BD6A18;\n --u-orange-800: #D1823C;\n --u-orange-900: #E19D67;\n --u-orange-1000: #EDB992;\n\n /* Teal Colors */\n --u-teal-0: #041411;\n --u-teal-100: #07201B;\n --u-teal-200: #0B2E28;\n --u-teal-300: #10403A;\n --u-teal-400: #16544D;\n --u-teal-500: #1E6860;\n --u-teal-600: #297D74;\n --u-teal-700: #3A9389;\n --u-teal-800: #54A89F;\n --u-teal-900: #73BBB3;\n --u-teal-1000: #93CBC5;\n\n /* Cyan Colors */\n --u-cyan-0: #041318;\n --u-cyan-100: #071F29;\n --u-cyan-200: #0B2D3A;\n --u-cyan-300: #104050;\n --u-cyan-400: #165469;\n --u-cyan-500: #1E6A82;\n --u-cyan-600: #287F9C;\n --u-cyan-700: #3995B5;\n --u-cyan-800: #53AACC;\n --u-cyan-900: #73BEDD;\n --u-cyan-1000: #95CFE8;\n\n /* Purple Colors */\n --u-purple-0: #150A22;\n --u-purple-100: #220F36;\n --u-purple-200: #31164B;\n --u-purple-300: #432064;\n --u-purple-400: #572B80;\n --u-purple-500: #6C379C;\n --u-purple-600: #8245B7;\n --u-purple-700: #975BCB;\n --u-purple-800: #AB79D9;\n --u-purple-900: #BD99E2;\n --u-purple-1000: #CEB8EA;\n\n /* Pink Colors */\n --u-pink-0: #1F0A14;\n --u-pink-100: #310F20;\n --u-pink-200: #451532;\n --u-pink-300: #5C1D45;\n --u-pink-400: #74285A;\n --u-pink-500: #8F336F;\n --u-pink-600: #AB4187;\n --u-pink-700: #C0569D;\n --u-pink-800: #D174B3;\n --u-pink-900: #E095C7;\n --u-pink-1000: #EBB5D9;\n\n /* ==========================================================================\n Role Colors — 의미 역할 층\n 컴포넌트는 팔레트 프리미티브가 아니라 이 층을 참조한다.\n 브랜드 색 교체는 아래 25개만 재정의하면 시맨틱 층까지 따라온다.\n\n 단은 '강도' 축이다 (weakest -> strong). 용도(배경/테두리/텍스트)는\n 소비처가 정한다 -- 단을 속성에 묶으면 primary 버튼의 배경이 어느\n 단인지 같은 모순이 생긴다.\n\n ★**다만 두 단은 용도가 확정돼 있다** — 대비 요구가 서로 다르기 때문이다.\n `-color` = **면**. `--u-*-txt-color` 가 그 위에 얹히므로 on-color 기준 4.5.\n `-strong` = **글자·아이콘**. `--u-bg-color` 위에 놓이므로 바탕 기준 4.5.\n 라이트에서는 바탕도 on-color 도 흰색이라 두 요구가 한 조건으로 합쳐지지만,\n **다크에서는 정반대 방향**이다(바탕 #121212 · on-color #FFFFFF). 바탕에서 읽히는\n 밝은 단은 흰 글자를 못 받고, 흰 글자를 받는 어두운 단은 바탕에서 안 읽힌다.\n ⇒ 다크에서 `-color` 와 `-strong` 이 두 단 벌어지는 것이 그 결과다.\n `tests/build/token-contrast.test.ts` 가 값을 지킨다.\n ========================================================================== */\n\n /* primary — 브랜드 · 강조 · 포커스 · 링크 */\n --u-primary-color-weakest: var(--u-blue-200);\n --u-primary-color-weaker: var(--u-blue-300);\n --u-primary-color-weak: var(--u-blue-500);\n --u-primary-color: var(--u-blue-600); /* 면: 흰 글자 6.09 ✓ */\n --u-primary-color-strong: var(--u-blue-800); /* 글자: 바탕 5.32 ✓ (700 은 4.05 ✗) */\n\n /* info — 정보 안내 (primary 와 기본값은 같으나 역할이 다르다 — 브랜딩은 primary 만 바꾼다) */\n --u-info-color-weakest: var(--u-blue-200);\n --u-info-color-weaker: var(--u-blue-300);\n --u-info-color-weak: var(--u-blue-500);\n --u-info-color: var(--u-blue-600);\n --u-info-color-strong: var(--u-blue-800);\n\n /* success — 성공 · 완료 */\n --u-success-color-weakest: var(--u-green-200);\n --u-success-color-weaker: var(--u-green-300);\n --u-success-color-weak: var(--u-green-500);\n --u-success-color: var(--u-green-600);\n --u-success-color-strong: var(--u-green-700);\n\n /* warning — 주의 */\n --u-warning-color-weakest: var(--u-yellow-200);\n --u-warning-color-weaker: var(--u-yellow-300);\n --u-warning-color-weak: var(--u-yellow-500);\n --u-warning-color: var(--u-yellow-600);\n --u-warning-color-strong: var(--u-yellow-700);\n\n /* danger — 오류 · 위험 · 유효성 실패 */\n --u-danger-color-weakest: var(--u-red-200);\n --u-danger-color-weaker: var(--u-red-300);\n --u-danger-color-weak: var(--u-red-500);\n --u-danger-color: var(--u-red-600); /* 면: 흰 글자 6.83 ✓ */\n --u-danger-color-strong: var(--u-red-800); /* 글자: 바탕 4.87 ✓ (700 은 3.67 ✗) */\n /* Text Colors */\n --u-txt-color: var(--u-neutral-900);\n --u-txt-color-inverse: var(--u-neutral-100);\n\n /* 유채색 배경 위의 글자 — warning 만 다르다(light.css 참조). */\n --u-primary-txt-color: #FFFFFF;\n --u-info-txt-color: #FFFFFF;\n --u-success-txt-color: #FFFFFF;\n --u-danger-txt-color: #FFFFFF;\n /* ★라이트 시트와 같은 이유로 중립 최상단을 쓴다 — 다크에서는 그 값이 #FFFFFF 라\n 결과가 종전과 같다(4.65 ✓). 리터럴 대신 토큰을 쓰는 이유는 라이트에서 뒤집히기\n 때문이다(#000000). 두 시트가 같은 선언이 되어 어긋날 자리가 없어진다. */\n --u-warning-txt-color: var(--u-neutral-1000);\n --u-txt-color-hover: var(--u-primary-color-strong);\n --u-txt-color-active: var(--u-primary-color-strong);\n --u-txt-color-disabled: var(--u-neutral-500);\n /* 라이트와 같은 기준 — 놓이는 모든 면에서 AA. neutral-700(#8A8A8A)은 바탕 5.43 ·\n 올림면(neutral-300) 4.16 · active 면(neutral-400) 3.15 로 미달이었다.\n neutral-800(#B0B0B0) = 8.64 · 6.62 · 5.01. 본문(neutral-900)과의 대비비 1.46. */\n --u-txt-color-weak: var(--u-neutral-800);\n --u-txt-color-strong: var(--u-neutral-1000);\n\n --u-link-txt-color: var(--u-primary-color-strong);\n --u-tooltip-txt-color: var(--u-neutral-100);\n\n /* Icon Colors */\n --u-icon-color: var(--u-neutral-800);\n --u-icon-color-inverse: var(--u-neutral-100);\n --u-icon-color-hover: var(--u-primary-color-strong);\n --u-icon-color-active: var(--u-primary-color-strong);\n --u-icon-color-disabled: var(--u-neutral-500);\n\n /* Border Colors\n ★`-weak` 는 `neutral-300` 일 수 없다 — `--u-bg-color-raised` 가 같은 단이라, 올림면(사이드바·\n 표 머리/행·마스터-디테일 구분선) 위에 그리는 약한 선이 **면과 같은 색**(대비 1.00)이 되어\n 화면에서 사라진다. 라이트는 200 단이 올림면(50)과 떨어져 있어 보인다. 램프에서 올림면(300)\n 위로 올릴 수 있는 다음 단이 400 뿐이라 `-weak` 는 이 테마에서 `--u-border-color` 와 같은\n 단이다 — 다크에서는 «약함/보통» 두 단이 하나로 합쳐지지만, 종전 `-weak` 는 그것이 쓰이는\n 면 위에서 애초에 구별되지 않았다. */\n --u-border-color: var(--u-neutral-400);\n --u-border-color-weak: var(--u-neutral-400);\n --u-border-color-strong: var(--u-neutral-500);\n --u-border-color-hover: var(--u-neutral-500);\n\n /* ★상태 테두리는 `-strong` 단이다 — light.css 의 같은 자리 주석 참조.\n 이 테마가 실제로 미달이었다: focus 2.74 · invalid 2.44 → 4.74 / 4.34. */\n --u-input-border-color: var(--u-neutral-400);\n --u-input-border-color-hover: var(--u-neutral-500);\n --u-input-border-color-focus: var(--u-primary-color-strong);\n --u-input-border-color-invalid: var(--u-danger-color-strong);\n\n /* Background Colors */\n --u-bg-color: var(--u-neutral-100);\n --u-bg-color-inverse: var(--u-neutral-0);\n --u-bg-color-hover: var(--u-neutral-300);\n --u-bg-color-active: var(--u-neutral-400);\n --u-bg-color-disabled: var(--u-neutral-100);\n\n /* 면 높이 — 상세는 light.css 참조. 다크는 **바탕보다 밝은 쪽**이 위다.\n neutral-300(#2A2A2A)은 바탕(#121212) 대비 1.42 로, 소비 측이 오버라이드로 쓰던\n neutral-200(1.15)보다 실제로 더 잘 구분된다 — 그 오버라이드가 해결하려던 증상이\n *\"툴바·헤더가 배경에 묻힌다\"* 였다. */\n --u-bg-color-raised: var(--u-neutral-300);\n\n /* ★올림면 위의 hover — `--u-bg-color-hover`(전역, 바탕면 전용)와 값이 같아서\n («둘 다 neutral-300») 카드·표 머리 위에 마우스를 올려도 아무 일도 안 일어났다\n (소비자 실측). 전역 토큰 하나로는 \"지금 위에 있는 면\"을\n 알 방법이 없어(참조 지점마다 계산 기준이 다를 수 없다) **전용 토큰**을 신설한다.\n\n ⚠**A안**(`raised`를 neutral-200으로) — 과거에 거부된 값(위 주석). **B안**(전역\n `hover`를 neutral-400으로) — `--u-bg-color-active` 와 충돌해 결함이 다른 쌍으로\n 옮겨간다. ⇒ hover 는 본래 \"현재 면보다 한 단 위\"이지 절대 단이 아니므로\n `color-mix()` 로 raised 자신을 기준 삼아 상대 계산한다.\n\n N=6% 는 raised(L≈0.023)와 active(L≈0.047, neutral-400) 사이 대비 계산으로 골랐다 —\n 결과 L≈0.038, raised 대비 ≈1.21(라이트의 기존 \"약한\" 1.04보다 뚜렷하고, `bg→raised`\n 의 기존 1.31 과 비슷한 체감), active 와는 값이 달라 겹치지 않는다(≈#373737 vs\n active #3D3D3D). N 을 더 올리면(≈10%+) active 를 넘어서 순서가 뒤집힌다 — 확인함. */\n --u-bg-color-raised-hover: color-mix(in srgb, var(--u-bg-color-raised), white 6%);\n\n /* 유채색 표면 — 라이트와 **같은 단이 아니라 같은 세기**로 짝지었다(light.css 참조).\n 팔레트 유채색 틴트가 다크에서 짓눌리므로 한 단 위를 쓴다. green 은 대칭이라 그대로. */\n --u-primary-bg-color: var(--u-blue-100);\n --u-info-bg-color: var(--u-blue-100);\n --u-success-bg-color: var(--u-green-0);\n --u-danger-bg-color: var(--u-red-100);\n /* warning 합류 — 라이트는 yellow-200 이다(단 이름이 다른 이유는 light.css 참조). */\n --u-warning-bg-color: var(--u-yellow-100);\n\n --u-input-bg-color: var(--u-neutral-200);\n --u-panel-bg-color: var(--u-neutral-200);\n --u-overlay-bg-color: rgba(0, 0, 0, 0.7);\n --u-tooltip-bg-color: rgba(255, 255, 255, 0.85);\n\n /* Shadow Colors */\n --u-shadow-color-weaker: rgba(0, 0, 0, 0.15);\n --u-shadow-color-weak: rgba(0, 0, 0, 0.25);\n --u-shadow-color-normal: rgba(0, 0, 0, 0.35);\n --u-shadow-color-strong: rgba(0, 0, 0, 0.45);\n --u-shadow-color-stronger: rgba(0, 0, 0, 0.60);\n\n /* Elevation Scale — 근거는 light.css 의 같은 자리 주석 참조.\n ★다크는 알파가 3배 가까이 진하다 — 리터럴로 흩어져 있던 종전에는 이 차이가\n 적용되지 않아 다크에서 그림자가 사실상 보이지 않았다. */\n --u-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 1px rgba(0, 0, 0, 0.14); /* = shadow-color-weak */\n --u-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.18); /* = shadow-color-normal */\n --u-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.22); /* = shadow-color-strong */\n --u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.30); /* = shadow-color-stronger */\n\n\n /* ==========================================================================\n Chart categorical palette — 다크 면(#121212 · 올림면 #2A2A2A)에 대해 **따로 고른** 여덟 칸\n ★램프를 참조하지 않는 이유: 다크 장식 램프는 채도가 낮아(면 위 배지·태그용) 차트 계열로는\n 회색처럼 읽힌다 — 램프의 단 조합 39만 가지 중 검증을 통과한 것이 없었다. 그래서 라이트\n 여덟 칸과 **같은 색상·순서**를 OKLCH 밝기만 다크 대역으로 옮겨 잡았다.\n 검증: 밝기 0.48–0.67 · 채도 ≥ 0.1 · 색각 이상 이웃 ΔE ≥ 9.5 · 정상 시각 이웃 ΔE ≥ 25.1 ·\n 두 면 모두 대비 ≥ 3:1. 순서는 light.css 와 같다.\n ========================================================================== */\n --u-chart-color-1: #247EDB;\n --u-chart-color-2: #D03E73;\n --u-chart-color-3: #0DA1B2;\n --u-chart-color-4: #ED5711;\n --u-chart-color-5: #059183;\n --u-chart-color-6: #D96D04;\n --u-chart-color-7: #AE48CB;\n --u-chart-color-8: #4AA74D;\n\n /* Scrollbar Colors */\n --u-scrollbar-color: var(--u-neutral-500);\n --u-scrollbar-color-hover: var(--u-neutral-600);\n --u-scrollbar-track-color: transparent;\n}\n\n/* ==========================================================================\n ★모드와 무관한 스케일 — 반경·여백·글자 스케일·모션·글꼴.\n 값이 light.css 와 **같다.** 그런데 위 블록(`:root[theme=\"dark\"]`, 특이도 0,1,1)에 두면\n `:root`(0,1,0)로 이 토큰을 덮는 **모든 층**(하우스 프리셋·소비자 브랜드 시트)이 다크\n 모드에서만 **로드 순서와 무관하게** 진다 — 에러도 경고도 없이, 색은 정상으로 바뀌므로\n «다크가 잘 된다» 로 보인다. `:where()` 로 특이도를 `:root` 와 같게 두면 층 모델이 라이트와\n 똑같이 로드 순서로 선다.\n ⚠이 블록을 지우지 말 것 — 이 시트만 쓰는 «고정 다크 디자인» 소비자(docs/theming.md)는\n 이 토큰들을 여기서 받는다. 두 시트를 함께 쓸 때는 값이 같으므로 어느 쪽이 이겨도 같다.\n ========================================================================== */\n:root:where([theme=\"dark\"]) {\n /* ==========================================================================\n Radius Scale — 모서리 반경\n 리터럴을 흩뿌리면 값이 갈린다(실제로 pill 이 999px/9999px 두 표기로 나뉘어 있었다).\n ========================================================================== */\n --u-radius-none: 0;\n --u-radius-sm: 3px;\n --u-radius-md: 4px;\n --u-radius-lg: 6px;\n --u-radius-xl: 8px;\n /* ★상단 2단은 **면(surface)용**이다 — 카드·패널·대화상자처럼 큰 사각형은 컨트롤과\n 같은 반경을 쓰면 각져 보인다. 기존 5단은 **컨트롤용**이고 값을 바꾸지 않는다\n (바꾸면 모든 소비자의 버튼·입력이 동시에 움직인다). */\n --u-radius-2xl: 12px;\n --u-radius-3xl: 16px;\n --u-radius-pill: 9999px;\n --u-radius-circle: 50%;\n\n /* ==========================================================================\n Space Scale — 컨테이너·오버레이의 절대 여백\n ⚠**여백은 하나의 축이 아니다.** 이 스케일은 컨테이너/오버레이의 **레이아웃 여백**만\n 담당한다. 폼·인라인 요소의 `em` 여백은 상속된 `font-size` 에 비례하는 것이 의도이므로\n **여기로 흡수하지 않는다.** 반경과 마찬가지로 테마와 무관하므로 두 시트가 같다.\n 축 구분과 근거는 docs/design-tokens.md 참조.\n ========================================================================== */\n --u-space-3xs: 2px;\n --u-space-2xs: 4px;\n --u-space-xs: 6px;\n --u-space-sm: 8px;\n --u-space-md: 12px;\n --u-space-lg: 16px;\n /* ★상단 4단은 **화면 리듬**이다 — 카드 안쪽 여백(20~24)·섹션 간격(24~32)·페이지 여백\n (32~40). 종전에는 이 구간이 통째로 비어 있어 소비자가 전부 리터럴로 적었고,\n 그래서 앱마다 화면 밀도가 달라졌다. `lg`(16px) 이하는 **요소 사이**, `xl` 이상은\n **영역 사이**로 나눠 쓴다.\n ⚠`xs: 6px` 는 4px 격자에서 벗어나 있으나 **바꾸지 않는다** — 이미 배선된 컨트롤\n 여백이 전부 움직인다. 신규 단은 전부 4의 배수로 둔다. */\n --u-space-xl: 20px;\n --u-space-2xl: 24px;\n --u-space-3xl: 32px;\n --u-space-4xl: 40px;\n\n /* ==========================================================================\n Type Scale — 글자 크기·굵기·행간·자간의 **한 벌**\n ★**크기만 주면 스케일이 되지 않는다.** 소비자가 크기만 받고 굵기·행간을 각자 정하면\n 결국 화면마다 다른 위계가 생긴다 — 그래서 네 값을 **단 단위로 묶어** 낸다.\n\n 단 이름은 크기가 아니라 **역할**이다(`lg`/`xl` 이 아니라 `title`/`label`). 역할로 두면\n 소비자가 *\"어느 크기를 쓸까\"* 가 아니라 *\"이 글자는 무엇인가\"* 를 묻게 된다.\n\n ★**한글 기준으로 값을 골랐다**:\n ⑴ 행간은 **1.4 이상**. 라틴 관례(1.2)는 한글에서 답답하다 — 받침 때문에 글자 상자가\n 세로로 꽉 차 있어 라틴과 같은 행간이면 줄이 붙어 보인다.\n ⑵ 자간은 **0 이 기본**이고 큰 제목만 **음수**. 한글에 양수 자간(letter-spacing)을 주면\n 가독성이 떨어진다 — 라틴 소문자 조판 관례를 그대로 옮기면 안 되는 자리다.\n ⑶ `overline` 에만 양수 자간을 둔다. 그 단은 **영문·숫자 라벨**을 전제한 자리이고,\n 한글을 넣을 소비자는 자간을 0 으로 덮어야 한다(문서에 명시).\n\n ⚠**`text-transform` 은 토큰으로 내지 않는다.** 한글에는 대문자가 없어 `uppercase` 가\n 아무 효과가 없고, 영문이 섞이면 그것만 커져 오히려 어수선해진다.\n ========================================================================== */\n --u-text-display-size: 26px;\n --u-text-display-weight: 700;\n --u-text-display-leading: 1.4;\n --u-text-display-tracking: -0.02em;\n\n --u-text-title-size: 20px;\n --u-text-title-weight: 700;\n --u-text-title-leading: 1.45;\n --u-text-title-tracking: -0.01em;\n\n --u-text-subtitle-size: 16px;\n --u-text-subtitle-weight: 600;\n --u-text-subtitle-leading: 1.5;\n --u-text-subtitle-tracking: 0;\n\n --u-text-body-size: 14px;\n --u-text-body-weight: 400;\n --u-text-body-leading: 1.6;\n --u-text-body-tracking: 0;\n\n --u-text-label-size: 13px;\n --u-text-label-weight: 600;\n --u-text-label-leading: 1.5;\n --u-text-label-tracking: 0;\n\n --u-text-caption-size: 12px;\n --u-text-caption-weight: 400;\n --u-text-caption-leading: 1.5;\n --u-text-caption-tracking: 0;\n\n --u-text-overline-size: 11px;\n --u-text-overline-weight: 700;\n --u-text-overline-leading: 1.45;\n --u-text-overline-tracking: 0.06em;\n\n /* ==========================================================================\n Motion — 지속시간·이징\n ★값이 없으면 앱마다 다른 속도가 생기고, `prefers-reduced-motion` 은 **반드시**\n 빠뜨리는 앱이 나온다. 축을 여기 두고 존중 규칙은 아래 미디어 쿼리가 진다.\n ========================================================================== */\n --u-duration-instant: 80ms;\n --u-duration-fast: 140ms;\n --u-duration-normal: 220ms;\n --u-duration-slow: 320ms;\n --u-ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --u-ease-decelerate: cubic-bezier(0, 0, 0, 1);\n --u-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);\n\n /* ==========================================================================\n Font Styles\n ★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**\n 종전 스택(`-apple-system, Segoe UI, Noto Sans, Helvetica, Arial`)에는 **한중일 글립을\n 가진 폰트가 하나도 없었다.** Windows 에서 한글은 `Segoe UI` 에 없으므로 UA 가 임의로\n 맑은 고딕을 고르고, macOS 는 `-apple-system` 이 Apple SD Gothic Neo 를 준다 ⇒ **같은 앱이\n OS 마다 다른 글꼴로 렌더**됐다. 폴백을 명시하면 그 선택이 결정적이 된다.\n ⚠**웹폰트를 로드하지 않는다.** 라이브러리가 네트워크 요청을 만들면 소비자의 CSP·\n 오프라인 환경을 깬다. 스택 맨 앞의 `Pretendard` 는 **소비자가 로드했을 때만** 잡히는\n 선택적 이름이다(없으면 조용히 다음으로 넘어간다).\n ========================================================================== */\n --u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';\n --u-font-mono: ui-monospace, 'Cascadia Code', Consolas, 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;\n --u-font-serif: 'Georgia', 'Times New Roman', Times, serif;\n --u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;\n --u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --u-font-rounded: 'Nunito', 'Quicksand', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n\n/* ★`prefers-reduced-motion` — light.css 와 같은 규칙을 이 시트도 진다. 이 시트만 쓰는\n 소비자가 있고, 두 시트를 함께 쓸 때는 어느 시트가 뒤에 오든 **마지막 선언이 이 0ms**\n 가 되도록 각 시트가 자기 블록 뒤에 둔다. 종전에는 지속시간이 위 (0,1,1) 블록에 있어\n 다크 모드에서 «동작 줄이기» 설정이 **무시됐다.** */\n@media (prefers-reduced-motion: reduce) {\n :root:where([theme=\"dark\"]) {\n --u-duration-instant: 0ms;\n --u-duration-fast: 0ms;\n --u-duration-normal: 0ms;\n --u-duration-slow: 0ms;\n }\n}\n";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { dark_css_default as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region \0glob-assets_raw/light.css.637cb2f8
|
|
2
|
-
var light_css_default = ":root {\n color-scheme: light;\n\n /* Neutral Colors */\n --u-neutral-0: #FFFFFF;\n --u-neutral-50: #FAFAFA;\n --u-neutral-100: #F5F5F5;\n --u-neutral-200: #EEEEEE;\n --u-neutral-300: #E0E0E0;\n --u-neutral-400: #BDBDBD;\n --u-neutral-500: #9E9E9E;\n --u-neutral-600: #757575;\n --u-neutral-700: #616161;\n --u-neutral-800: #424242;\n --u-neutral-900: #212121;\n --u-neutral-1000: #000000;\n\n /* Blue Colors */\n --u-blue-0: #E3F2FD;\n --u-blue-100: #BBDEFB;\n --u-blue-200: #90CAF9;\n --u-blue-300: #64B5F6;\n --u-blue-400: #42A5F5;\n --u-blue-500: #2196F3;\n --u-blue-600: #1E88E5;\n --u-blue-700: #1976D2;\n --u-blue-800: #1565C0;\n --u-blue-900: #0D47A1;\n --u-blue-1000: #062A5E;\n\n /* Green Colors */\n --u-green-0: #E8F5E9;\n --u-green-100: #C8E6C9;\n --u-green-200: #A5D6A7;\n --u-green-300: #81C784;\n --u-green-400: #66BB6A;\n --u-green-500: #4CAF50;\n --u-green-600: #43A047;\n --u-green-700: #388E3C;\n --u-green-800: #2E7D32;\n --u-green-900: #1B5E20;\n --u-green-1000: #0F3A12;\n\n /* Yellow Colors */\n --u-yellow-0: #FFFDE7;\n --u-yellow-100: #FFF9C4;\n --u-yellow-200: #FFF59D;\n --u-yellow-300: #FFF176;\n --u-yellow-400: #FFEE58;\n --u-yellow-500: #FFEB3B;\n --u-yellow-600: #FDD835;\n --u-yellow-700: #FBC02D;\n --u-yellow-800: #F9A825;\n --u-yellow-900: #F57F17;\n --u-yellow-1000: #8A4A00;\n\n /* Red Colors */\n --u-red-0: #FFEBEE;\n --u-red-100: #FFCDD2;\n --u-red-200: #EF9A9A;\n --u-red-300: #E57373;\n --u-red-400: #EF5350;\n --u-red-500: #F44336;\n --u-red-600: #E53935;\n --u-red-700: #D32F2F;\n --u-red-800: #C62828;\n --u-red-900: #B71C1C;\n --u-red-1000: #6B0F0F;\n\n /* Orange Colors */\n --u-orange-0: #FFF3E0;\n --u-orange-100: #FFE0B2;\n --u-orange-200: #FFCC80;\n --u-orange-300: #FFB74D;\n --u-orange-400: #FFA726;\n --u-orange-500: #FF9800;\n --u-orange-600: #FB8C00;\n --u-orange-700: #F57C00;\n --u-orange-800: #EF6C00;\n --u-orange-900: #E65100;\n --u-orange-1000: #8C3100;\n\n /* Teal Colors */\n --u-teal-0: #E0F2F1;\n --u-teal-100: #B2DFDB;\n --u-teal-200: #80CBC4;\n --u-teal-300: #4DB6AC;\n --u-teal-400: #26A69A;\n --u-teal-500: #009688;\n --u-teal-600: #00897B;\n --u-teal-700: #00796B;\n --u-teal-800: #00695C;\n --u-teal-900: #004D40;\n --u-teal-1000: #002E26;\n\n /* Cyan Colors */\n --u-cyan-0: #E0F7FA;\n --u-cyan-100: #B2EBF2;\n --u-cyan-200: #80DEEA;\n --u-cyan-300: #4DD0E1;\n --u-cyan-400: #26C6DA;\n --u-cyan-500: #00BCD4;\n --u-cyan-600: #00ACC1;\n --u-cyan-700: #0097A7;\n --u-cyan-800: #00838F;\n --u-cyan-900: #006064;\n --u-cyan-1000: #003A3D;\n\n /* Purple Colors */\n --u-purple-0: #F3E5F5;\n --u-purple-100: #E1BEE7;\n --u-purple-200: #CE93D8;\n --u-purple-300: #BA68C8;\n --u-purple-400: #AB47BC;\n --u-purple-500: #9C27B0;\n --u-purple-600: #8E24AA;\n --u-purple-700: #7B1FA2;\n --u-purple-800: #6A1B9A;\n --u-purple-900: #4A148C;\n --u-purple-1000: #2C0B54;\n\n /* Pink Colors */\n --u-pink-0: #FCE4EC;\n --u-pink-100: #F8BBD0;\n --u-pink-200: #F48FB1;\n --u-pink-300: #F06292;\n --u-pink-400: #EC407A;\n --u-pink-500: #E91E63;\n --u-pink-600: #D81B60;\n --u-pink-700: #C2185B;\n --u-pink-800: #AD1457;\n --u-pink-900: #880E4F;\n --u-pink-1000: #520830;\n\n /* ==========================================================================\n Role Colors — 의미 역할 층\n 컴포넌트는 팔레트 프리미티브가 아니라 이 층을 참조한다.\n 브랜드 색 교체는 아래 25개만 재정의하면 시맨틱 층까지 따라온다.\n\n 단은 '강도' 축이다 (weakest -> strong). 용도(배경/테두리/텍스트)는\n 소비처가 정한다 -- 단을 속성에 묶으면 primary 버튼의 배경이 어느\n 단인지 같은 모순이 생긴다.\n ========================================================================== */\n\n /* ★단이 팔레트 shade 와 1:1 이 아니다 — **대비로 고른다.**\n `-color` 는 `--u-*-txt-color` 를 받는 면이고 `-strong` 은 바탕 위의 글자다.\n 라이트에서는 바탕도 on-color 도 흰색이라 두 요구가 `contrast(shade, #FFF) ≥ 4.5`\n 하나로 합쳐지고, 그 단이 계열마다 다르다(blue 700 · red 700 · green 800).\n Material 램프는 휘도가 아니라 색상 기준으로 만들어져 있어서 단 번호가 세기를\n 보장하지 않는다 — 값은 `tests/build/token-contrast.test.ts` 가 지킨다. */\n\n /* primary — 브랜드 · 강조 · 포커스 · 링크 */\n --u-primary-color-weakest: var(--u-blue-200);\n --u-primary-color-weaker: var(--u-blue-300);\n --u-primary-color-weak: var(--u-blue-500);\n --u-primary-color: var(--u-blue-700); /* 4.60 ✓ (600 은 3.68 ✗) */\n --u-primary-color-strong: var(--u-blue-800); /* 5.75 ✓ */\n\n /* info — 정보 안내 (primary 와 기본값은 같으나 역할이 다르다 — 브랜딩은 primary 만 바꾼다) */\n --u-info-color-weakest: var(--u-blue-200);\n --u-info-color-weaker: var(--u-blue-300);\n --u-info-color-weak: var(--u-blue-500);\n --u-info-color: var(--u-blue-700);\n --u-info-color-strong: var(--u-blue-800);\n\n /* success — 성공 · 완료\n ⚠green 은 700 도 4.12 로 미달이라 두 단을 건너뛴다. 계열마다 통과 단이 다른 것이\n 이 층의 정상 상태다(단 번호를 맞추면 대비가 어긋난다). */\n --u-success-color-weakest: var(--u-green-200);\n --u-success-color-weaker: var(--u-green-300);\n --u-success-color-weak: var(--u-green-500);\n --u-success-color: var(--u-green-800); /* 5.13 ✓ (600=3.30 · 700=4.12 ✗) */\n --u-success-color-strong: var(--u-green-900); /* 7.87 ✓ */\n\n /* warning — 주의 */\n --u-warning-color-weakest: var(--u-yellow-200);\n --u-warning-color-weaker: var(--u-yellow-300);\n --u-warning-color-weak: var(--u-yellow-500);\n --u-warning-color: var(--u-yellow-600);\n /* ★다른 계열은 -strong 이 shade-800~900 인데 warning 만 1000 이다 — 노랑 램프는\n 900 까지도 흰 바탕 2.65 로 미달이고, 1000(#8A4A00)에서 처음 6.86 이 된다.\n 그 값은 갈색에 가깝지만, 이 단의 용도는 **면이 아니라 글자·아이콘**이므로 색상보다\n 가독성이 먼저다(경고 문구를 어두운 호박색으로 쓰는 것은 보편 관행이다). */\n --u-warning-color-strong: var(--u-yellow-1000);\n\n /* danger — 오류 · 위험 · 유효성 실패 */\n --u-danger-color-weakest: var(--u-red-200);\n --u-danger-color-weaker: var(--u-red-300);\n --u-danger-color-weak: var(--u-red-500);\n --u-danger-color: var(--u-red-700); /* 4.98 ✓ (600 은 4.23 ✗ — 오류 문구가 이 단이었다) */\n --u-danger-color-strong: var(--u-red-800); /* 5.62 ✓ */\n /* ==========================================================================\n Radius Scale — 모서리 반경\n 리터럴을 흩뿌리면 값이 갈린다(실제로 pill 이 999px/9999px 두 표기로 나뉘어 있었다).\n ========================================================================== */\n --u-radius-none: 0;\n --u-radius-sm: 3px;\n --u-radius-md: 4px;\n --u-radius-lg: 6px;\n --u-radius-xl: 8px;\n /* ★상단 2단은 **면(surface)용**이다 — 카드·패널·대화상자처럼 큰 사각형은 컨트롤과\n 같은 반경을 쓰면 각져 보인다. 기존 5단은 **컨트롤용**이고 값을 바꾸지 않는다\n (바꾸면 모든 소비자의 버튼·입력이 동시에 움직인다). */\n --u-radius-2xl: 12px;\n --u-radius-3xl: 16px;\n --u-radius-pill: 9999px;\n --u-radius-circle: 50%;\n\n /* ==========================================================================\n Space Scale — 컨테이너·오버레이의 절대 여백\n ⚠**여백은 하나의 축이 아니다.** 이 스케일은 컨테이너/오버레이(카드·대화상자·드로어·\n 알림·메뉴·툴팁 등)의 **레이아웃 여백**만 담당한다. 폼·인라인 요소의 `em` 여백은\n 상속된 `font-size` 에 비례하는 것이 의도이므로 **여기로 흡수하지 않는다** —\n 흡수하면 타이포를 키운 소비자의 여백이 따라 커지지 않는다.\n 축 구분과 근거는 docs/design-tokens.md 참조.\n ========================================================================== */\n --u-space-3xs: 2px;\n --u-space-2xs: 4px;\n --u-space-xs: 6px;\n --u-space-sm: 8px;\n --u-space-md: 12px;\n --u-space-lg: 16px;\n /* ★상단 4단은 **화면 리듬**이다 — 카드 안쪽 여백(20~24)·섹션 간격(24~32)·페이지 여백\n (32~40). 종전에는 이 구간이 통째로 비어 있어 소비자가 전부 리터럴로 적었고,\n 그래서 앱마다 화면 밀도가 달라졌다. `lg`(16px) 이하는 **요소 사이**, `xl` 이상은\n **영역 사이**로 나눠 쓴다.\n ⚠`xs: 6px` 는 4px 격자에서 벗어나 있으나 **바꾸지 않는다** — 이미 배선된 컨트롤\n 여백이 전부 움직인다. 신규 단은 전부 4의 배수로 둔다. */\n --u-space-xl: 20px;\n --u-space-2xl: 24px;\n --u-space-3xl: 32px;\n --u-space-4xl: 40px;\n\n /* Text Colors */\n --u-txt-color: var(--u-neutral-900);\n --u-txt-color-inverse: var(--u-neutral-0);\n /* 유채색 배경 위의 글자. --u-txt-color-inverse 는 다크에서 neutral-100(#121212)이라\n 유채색 버튼 위에서 읽히지 않는다. 브랜드 색을 바꾸는 소비자가 전경색도 함께\n 조절할 수 있도록 별도 이름을 준다.\n ⚠이 토큰이 흰색이라는 것과 그 위의 배경이 AA 를 받친다는 것은 별개다 —\n 라이트 팔레트의 shade-600 은 8색 중 6색이 흰 글자로 AA 에 미달한다(미해결). */\n --u-primary-txt-color: #FFFFFF;\n --u-info-txt-color: #FFFFFF;\n --u-success-txt-color: #FFFFFF;\n --u-danger-txt-color: #FFFFFF;\n /* ★warning 만 어둡다 — 취향이 아니라 측정이다. 노랑은 **어떤 단도** 흰 글자로 AA 를\n 받치지 못한다(라이트 최대 2.65 @900, 그마저 갈색). 다른 넷처럼 단을 옮기는 수단이\n 없으므로 전경을 뒤집는다. `--u-neutral-1000` 은 라이트 #000000 / 다크 #FFFFFF 이라\n 한 줄로 양 테마를 만족한다(라이트 15.05 · 다크 4.65). */\n --u-warning-txt-color: var(--u-neutral-1000);\n\n --u-txt-color-hover: var(--u-primary-color-strong);\n --u-txt-color-active: var(--u-primary-color-strong);\n --u-txt-color-disabled: var(--u-neutral-400);\n /* 보조 텍스트는 «놓이는 모든 면»에서 AA(4.5)를 받쳐야 한다 — 바탕만이 아니다.\n neutral-600(#757575)은 바탕 4.61 에서만 통과하고 올림면(neutral-50) 4.41 ·\n active 면(neutral-200) 3.97 로 미달이었다(표 머리·카드 위 보조 텍스트).\n neutral-700(#616161) = 바탕 6.19 · 올림면 5.93 · active 5.34.\n 본문(neutral-900)과의 대비비는 2.60 으로, 보조 텍스트를 모든 표면 위에서\n 읽히게 보장하는 흔한 디자인 시스템 기준(본문 대비 약 1.3~1.8)보다 위계가 넓다. */\n --u-txt-color-weak: var(--u-neutral-700);\n --u-txt-color-strong: var(--u-neutral-1000);\n\n --u-link-txt-color: var(--u-primary-color-strong);\n --u-tooltip-txt-color: var(--u-neutral-0);\n\n /* Icon Colors */\n --u-icon-color: var(--u-neutral-700);\n --u-icon-color-inverse: var(--u-neutral-0);\n --u-icon-color-hover: var(--u-primary-color-strong);\n --u-icon-color-active: var(--u-primary-color-strong);\n --u-icon-color-disabled: var(--u-neutral-400);\n\n /* Border Colors */\n --u-border-color: var(--u-neutral-300);\n --u-border-color-weak: var(--u-neutral-200);\n --u-border-color-strong: var(--u-neutral-400);\n --u-border-color-hover: var(--u-neutral-400);\n\n /* ★상태 테두리는 `-strong` 단이다 — 면이 아니라 **면 위에 그리는 선**이기 때문이다.\n 1.16.0 이 가른 용도(`-color` = 면 / `-strong` = 면·바탕 위)에 이 자리가 맞춰지지\n 않아 다크에서 미달이었다: focus 2.74 · invalid 2.44 (WCAG 1.4.11 기준 3.0).\n `-strong` 으로 옮기면 다크 4.74 / 4.34, 라이트 5.75 / 5.62 — 두 테마 모두 단조 상승. */\n --u-input-border-color: var(--u-neutral-300);\n --u-input-border-color-hover: var(--u-neutral-400);\n --u-input-border-color-focus: var(--u-primary-color-strong);\n --u-input-border-color-invalid: var(--u-danger-color-strong);\n\n /* Background Colors */\n --u-bg-color: var(--u-neutral-0);\n --u-bg-color-inverse: var(--u-neutral-900);\n --u-bg-color-hover: var(--u-neutral-100);\n --u-bg-color-active: var(--u-neutral-200);\n --u-bg-color-disabled: var(--u-neutral-50);\n\n /* ★면 높이 — 바탕에 인접해 있으면서 한 단 구분되는 크롬 면(툴바·표 헤더·푸터).\n 상호작용 상태(-hover/-active/-disabled)와 **다른 축**이다. 상태 이름에 높이를\n 얹으면 의미가 어긋난다.\n `--u-panel-bg-color` 와도 다르다 — 그쪽은 **떠 있는 패널**(카드·대화상자·메뉴)이라\n 라이트에서 페이지와 같은 흰색이고 그림자가 높이를 나른다. 크롬 면은 그림자가 없어\n 라이트에서도 틴트가 필요하다.\n ⚠한 단만 정의한다. 두 단째의 실측 수요는 라이트 한쪽뿐이었다(다크에서는 소비 측\n 오버라이드가 두 값을 같은 단으로 합치고 있었다). */\n --u-bg-color-raised: var(--u-neutral-50);\n\n /* ⚠**라이트는 전역 hover 에 그대로 별칭한다 — 결손이 아니라 실측 결론이다**\n (dark.css 의 같은 자리 참조). 두 시트는 각각 완결적이어야 한다는\n 불변식(`token-fallbacks.test.ts` 「키 패리티」)이 있어 다크에만 선언할 수 없다.\n 라이트 팔레트는 raised(250)·hover(245)·active(238) 가 12단 안에 몰려 있어\n (L≈0.956/0.913/0.855) 셋과 겹치지 않는 네 번째 단을 넣을 여유가 없다 — 대비를\n 조금만 올려도(≈1.10) active 와 거의 붙고(≈1단 차), 더 올리면 순서가 뒤집힌다.\n 다크와 달리 raised(250)≠hover(245) 라 «완전히 안 움직이는» 결함이 아니었으므로\n (약한 대비 1.04 로 이미 알려진 채로 남는다 — 같은 초안이 지적한 곁가지),\n 새 단을 억지로 만들지 않고 기존 hover 를 그대로 쓴다. */\n --u-bg-color-raised-hover: var(--u-bg-color-hover);\n \n /* 유채색 표면 — 정보/성공/위험 상태의 '면'.\n 역할 층의 유채색은 전경 5단뿐이라, 상태 배경이 필요한 컴포넌트는 팔레트를 직접\n 읽고 다크를 손으로 보정해야 했다. 팔레트의 유채색 틴트는 다크에서 짓눌리므로\n (바탕 대비 델타의 다크/라이트 비 — 청색 0.38~0.54) 두 테마가 **같은 단이 아니라\n 같은 세기**가 되도록 짝지었다. 실측 비: blue 1.09 · red 1.12 · green 0.91.\n\n ★**warning 이 합류했다(1.16.0 → 1.17.0).** 종전에는 *\"세기를 맞출 단 짝이 없다\"* 며\n 빠져 있었는데, 그 판정은 **shade-0 짝만** 재고 있었다. 노랑만 한 단 내려 잡으면\n 라이트 쪽 세기가 맞는다 — 바탕 대비 휘도 델타 실측:\n blue-0 0.131 · red-0 0.132 · green-0 0.117 · **yellow-200 0.110** (yellow-0 은 0.027)\n ⚠단 이름이 계열마다 다른 것(yellow 만 200)은 이 층의 정상 상태다. 라이트 팔레트는\n 휘도 순이 아니므로 같은 단 번호가 같은 세기를 뜻하지 않는다. */\n --u-primary-bg-color: var(--u-blue-0);\n --u-info-bg-color: var(--u-blue-0);\n --u-success-bg-color: var(--u-green-0);\n --u-danger-bg-color: var(--u-red-0);\n --u-warning-bg-color: var(--u-yellow-200);\n\n --u-input-bg-color: var(--u-neutral-0);\n --u-panel-bg-color: var(--u-neutral-0);\n --u-overlay-bg-color: rgba(0, 0, 0, 0.5);\n --u-tooltip-bg-color: rgba(0, 0, 0, 0.75);\n\n /* Shadow Colors */\n --u-shadow-color-weaker: rgba(0, 0, 0, 0.04);\n --u-shadow-color-weak: rgba(0, 0, 0, 0.08);\n --u-shadow-color-normal: rgba(0, 0, 0, 0.12);\n --u-shadow-color-strong: rgba(0, 0, 0, 0.16);\n --u-shadow-color-stronger: rgba(0, 0, 0, 0.24);\n\n /* ==========================================================================\n Elevation Scale — 높이(그림자)\n\n ★색 축은 있었지만 **높이 축이 없었다.** 그 결과 컴포넌트가 그림자를 리터럴로\n 썼고, 같은 리듬을 의도한 자리에 서로 다른 값 11가지가 생겼다(카드 .1 vs 캐러셀\n .15 — 둘 다 \"표면에 얹힌 카드\"인데 알파가 다르다).\n\n ⚠**그리고 그 리터럴들은 테마를 몰랐다** — `rgba(0,0,0,.1)` 은 다크 바탕에서\n 거의 보이지 않는다. 이 축을 경유하면 다크의 진한 알파(.25~.60)를 자동으로 받는다.\n\n ⚠**알파를 `--u-shadow-color-*` 로 중첩하지 않고 인라인한다.** use-site 폴백\n 생성기는 합성 값을 리터럴로 다루므로, 중첩하면 `var(--u-shadow-md, 0 2px 8px\n var(--u-shadow-color-normal))` 처럼 **폴백 안에 또 토큰이 들어간다** — 시트가\n 없을 때 그 폴백도 함께 무효가 되어 그림자가 통째로 사라진다.\n 두 축의 알파가 어긋나지 않는지는 `tests/build/elevation-scale.test.ts` 가 지킨다.\n ========================================================================== */\n --u-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04); /* = shadow-color-weak — 표면에 얹힌 작은 컨트롤(탭·손잡이) */\n --u-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.05); /* = shadow-color-normal — 카드·표면 */\n --u-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.06); /* = shadow-color-strong — 떠 있는 레이어(드롭다운·알림) */\n --u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.24), 0 2px 6px rgba(0, 0, 0, 0.08); /* = shadow-color-stronger — 모달·최상위(대화상자·툴팁) */\n\n\n /* ==========================================================================\n Type Scale — 글자 크기·굵기·행간·자간의 **한 벌**\n ★**크기만 주면 스케일이 되지 않는다.** 소비자가 크기만 받고 굵기·행간을 각자 정하면\n 결국 화면마다 다른 위계가 생긴다 — 그래서 네 값을 **단 단위로 묶어** 낸다.\n\n 단 이름은 크기가 아니라 **역할**이다(`lg`/`xl` 이 아니라 `title`/`label`). 역할로 두면\n 소비자가 *\"어느 크기를 쓸까\"* 가 아니라 *\"이 글자는 무엇인가\"* 를 묻게 된다.\n\n ★**한글 기준으로 값을 골랐다**:\n ⑴ 행간은 **1.4 이상**. 라틴 관례(1.2)는 한글에서 답답하다 — 받침 때문에 글자 상자가\n 세로로 꽉 차 있어 라틴과 같은 행간이면 줄이 붙어 보인다.\n ⑵ 자간은 **0 이 기본**이고 큰 제목만 **음수**. 한글에 양수 자간(letter-spacing)을 주면\n 가독성이 떨어진다 — 라틴 소문자 조판 관례를 그대로 옮기면 안 되는 자리다.\n ⑶ `overline` 에만 양수 자간을 둔다. 그 단은 **영문·숫자 라벨**을 전제한 자리이고,\n 한글을 넣을 소비자는 자간을 0 으로 덮어야 한다(문서에 명시).\n\n ⚠**`text-transform` 은 토큰으로 내지 않는다.** 한글에는 대문자가 없어 `uppercase` 가\n 아무 효과가 없고, 영문이 섞이면 그것만 커져 오히려 어수선해진다.\n ========================================================================== */\n --u-text-display-size: 26px;\n --u-text-display-weight: 700;\n --u-text-display-leading: 1.4;\n --u-text-display-tracking: -0.02em;\n\n --u-text-title-size: 20px;\n --u-text-title-weight: 700;\n --u-text-title-leading: 1.45;\n --u-text-title-tracking: -0.01em;\n\n --u-text-subtitle-size: 16px;\n --u-text-subtitle-weight: 600;\n --u-text-subtitle-leading: 1.5;\n --u-text-subtitle-tracking: 0;\n\n --u-text-body-size: 14px;\n --u-text-body-weight: 400;\n --u-text-body-leading: 1.6;\n --u-text-body-tracking: 0;\n\n --u-text-label-size: 13px;\n --u-text-label-weight: 600;\n --u-text-label-leading: 1.5;\n --u-text-label-tracking: 0;\n\n --u-text-caption-size: 12px;\n --u-text-caption-weight: 400;\n --u-text-caption-leading: 1.5;\n --u-text-caption-tracking: 0;\n\n --u-text-overline-size: 11px;\n --u-text-overline-weight: 700;\n --u-text-overline-leading: 1.45;\n --u-text-overline-tracking: 0.06em;\n\n /* ==========================================================================\n Motion — 지속시간·이징\n ★값이 없으면 앱마다 다른 속도가 생기고, `prefers-reduced-motion` 은 **반드시**\n 빠뜨리는 앱이 나온다. 축을 여기 두고 존중 규칙은 아래 미디어 쿼리가 진다.\n ========================================================================== */\n --u-duration-instant: 80ms;\n --u-duration-fast: 140ms;\n --u-duration-normal: 220ms;\n --u-duration-slow: 320ms;\n --u-ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --u-ease-decelerate: cubic-bezier(0, 0, 0, 1);\n --u-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);\n\n /* Scrollbar Colors */\n --u-scrollbar-color: var(--u-neutral-400);\n --u-scrollbar-color-hover: var(--u-neutral-500);\n --u-scrollbar-track-color: transparent;\n\n /* ==========================================================================\n Font Styles\n ★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**\n 종전 스택(`-apple-system, Segoe UI, Noto Sans, Helvetica, Arial`)에는 **한중일 글립을\n 가진 폰트가 하나도 없었다.** Windows 에서 한글은 `Segoe UI` 에 없으므로 UA 가 임의로\n 맑은 고딕을 고르고, macOS 는 `-apple-system` 이 Apple SD Gothic Neo 를 준다 ⇒ **같은 앱이\n OS 마다 다른 글꼴로 렌더**됐다. 폴백을 명시하면 그 선택이 결정적이 된다.\n ⚠**웹폰트를 로드하지 않는다.** 라이브러리가 네트워크 요청을 만들면 소비자의 CSP·\n 오프라인 환경을 깬다. 스택 맨 앞의 `Pretendard` 는 **소비자가 로드했을 때만** 잡히는\n 선택적 이름이다(없으면 조용히 다음으로 넘어간다).\n ========================================================================== */\n --u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';\n --u-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;\n --u-font-serif: 'Georgia', 'Times New Roman', Times, serif;\n --u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;\n --u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --u-font-rounded: 'Nunito', 'Quicksand', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n\n/* ==========================================================================\n ★`prefers-reduced-motion` 존중 — **라이브러리가 진다.**\n 소비자마다 각자 처리하게 두면 반드시 빠뜨리는 앱이 나온다(그리고 그 앱은\n 접근성 감사 전까지 아무도 모른다). 지속시간 축을 0 으로 눌러 두면 이 축을\n 경유하는 모든 애니메이션이 함께 멈춘다.\n ⚠`animation: none` 으로 강제하지 않는다 — 로딩 스피너처럼 **의미를 나르는**\n 움직임까지 죽이면 사용자가 진행 중인지 알 수 없게 된다.\n ========================================================================== */\n@media (prefers-reduced-motion: reduce) {\n :root {\n --u-duration-instant: 0ms;\n --u-duration-fast: 0ms;\n --u-duration-normal: 0ms;\n --u-duration-slow: 0ms;\n }\n}\n";
|
|
2
|
+
var light_css_default = ":root {\n color-scheme: light;\n\n /* Neutral Colors */\n --u-neutral-0: #FFFFFF;\n --u-neutral-50: #FAFAFA;\n --u-neutral-100: #F5F5F5;\n --u-neutral-200: #EEEEEE;\n --u-neutral-300: #E0E0E0;\n --u-neutral-400: #BDBDBD;\n --u-neutral-500: #9E9E9E;\n --u-neutral-600: #757575;\n --u-neutral-700: #616161;\n --u-neutral-800: #424242;\n --u-neutral-900: #212121;\n --u-neutral-1000: #000000;\n\n /* Blue Colors */\n --u-blue-0: #E3F2FD;\n --u-blue-100: #BBDEFB;\n --u-blue-200: #90CAF9;\n --u-blue-300: #64B5F6;\n --u-blue-400: #42A5F5;\n --u-blue-500: #2196F3;\n --u-blue-600: #1E88E5;\n --u-blue-700: #1976D2;\n --u-blue-800: #1565C0;\n --u-blue-900: #0D47A1;\n --u-blue-1000: #062A5E;\n\n /* Green Colors */\n --u-green-0: #E8F5E9;\n --u-green-100: #C8E6C9;\n --u-green-200: #A5D6A7;\n --u-green-300: #81C784;\n --u-green-400: #66BB6A;\n --u-green-500: #4CAF50;\n --u-green-600: #43A047;\n --u-green-700: #388E3C;\n --u-green-800: #2E7D32;\n --u-green-900: #1B5E20;\n --u-green-1000: #0F3A12;\n\n /* Yellow Colors */\n --u-yellow-0: #FFFDE7;\n --u-yellow-100: #FFF9C4;\n --u-yellow-200: #FFF59D;\n --u-yellow-300: #FFF176;\n --u-yellow-400: #FFEE58;\n --u-yellow-500: #FFEB3B;\n --u-yellow-600: #FDD835;\n --u-yellow-700: #FBC02D;\n --u-yellow-800: #F9A825;\n --u-yellow-900: #F57F17;\n --u-yellow-1000: #8A4A00;\n\n /* Red Colors */\n --u-red-0: #FFEBEE;\n --u-red-100: #FFCDD2;\n --u-red-200: #EF9A9A;\n --u-red-300: #E57373;\n --u-red-400: #EF5350;\n --u-red-500: #F44336;\n --u-red-600: #E53935;\n --u-red-700: #D32F2F;\n --u-red-800: #C62828;\n --u-red-900: #B71C1C;\n --u-red-1000: #6B0F0F;\n\n /* Orange Colors */\n --u-orange-0: #FFF3E0;\n --u-orange-100: #FFE0B2;\n --u-orange-200: #FFCC80;\n --u-orange-300: #FFB74D;\n --u-orange-400: #FFA726;\n --u-orange-500: #FF9800;\n --u-orange-600: #FB8C00;\n --u-orange-700: #F57C00;\n --u-orange-800: #EF6C00;\n --u-orange-900: #E65100;\n --u-orange-1000: #8C3100;\n\n /* Teal Colors */\n --u-teal-0: #E0F2F1;\n --u-teal-100: #B2DFDB;\n --u-teal-200: #80CBC4;\n --u-teal-300: #4DB6AC;\n --u-teal-400: #26A69A;\n --u-teal-500: #009688;\n --u-teal-600: #00897B;\n --u-teal-700: #00796B;\n --u-teal-800: #00695C;\n --u-teal-900: #004D40;\n --u-teal-1000: #002E26;\n\n /* Cyan Colors */\n --u-cyan-0: #E0F7FA;\n --u-cyan-100: #B2EBF2;\n --u-cyan-200: #80DEEA;\n --u-cyan-300: #4DD0E1;\n --u-cyan-400: #26C6DA;\n --u-cyan-500: #00BCD4;\n --u-cyan-600: #00ACC1;\n --u-cyan-700: #0097A7;\n --u-cyan-800: #00838F;\n --u-cyan-900: #006064;\n --u-cyan-1000: #003A3D;\n\n /* Purple Colors */\n --u-purple-0: #F3E5F5;\n --u-purple-100: #E1BEE7;\n --u-purple-200: #CE93D8;\n --u-purple-300: #BA68C8;\n --u-purple-400: #AB47BC;\n --u-purple-500: #9C27B0;\n --u-purple-600: #8E24AA;\n --u-purple-700: #7B1FA2;\n --u-purple-800: #6A1B9A;\n --u-purple-900: #4A148C;\n --u-purple-1000: #2C0B54;\n\n /* Pink Colors */\n --u-pink-0: #FCE4EC;\n --u-pink-100: #F8BBD0;\n --u-pink-200: #F48FB1;\n --u-pink-300: #F06292;\n --u-pink-400: #EC407A;\n --u-pink-500: #E91E63;\n --u-pink-600: #D81B60;\n --u-pink-700: #C2185B;\n --u-pink-800: #AD1457;\n --u-pink-900: #880E4F;\n --u-pink-1000: #520830;\n\n /* ==========================================================================\n Role Colors — 의미 역할 층\n 컴포넌트는 팔레트 프리미티브가 아니라 이 층을 참조한다.\n 브랜드 색 교체는 아래 25개만 재정의하면 시맨틱 층까지 따라온다.\n\n 단은 '강도' 축이다 (weakest -> strong). 용도(배경/테두리/텍스트)는\n 소비처가 정한다 -- 단을 속성에 묶으면 primary 버튼의 배경이 어느\n 단인지 같은 모순이 생긴다.\n ========================================================================== */\n\n /* ★단이 팔레트 shade 와 1:1 이 아니다 — **대비로 고른다.**\n `-color` 는 `--u-*-txt-color` 를 받는 면이고 `-strong` 은 바탕 위의 글자다.\n 라이트에서는 바탕도 on-color 도 흰색이라 두 요구가 `contrast(shade, #FFF) ≥ 4.5`\n 하나로 합쳐지고, 그 단이 계열마다 다르다(blue 700 · red 700 · green 800).\n Material 램프는 휘도가 아니라 색상 기준으로 만들어져 있어서 단 번호가 세기를\n 보장하지 않는다 — 값은 `tests/build/token-contrast.test.ts` 가 지킨다. */\n\n /* primary — 브랜드 · 강조 · 포커스 · 링크 */\n --u-primary-color-weakest: var(--u-blue-200);\n --u-primary-color-weaker: var(--u-blue-300);\n --u-primary-color-weak: var(--u-blue-500);\n --u-primary-color: var(--u-blue-700); /* 4.60 ✓ (600 은 3.68 ✗) */\n --u-primary-color-strong: var(--u-blue-800); /* 5.75 ✓ */\n\n /* info — 정보 안내 (primary 와 기본값은 같으나 역할이 다르다 — 브랜딩은 primary 만 바꾼다) */\n --u-info-color-weakest: var(--u-blue-200);\n --u-info-color-weaker: var(--u-blue-300);\n --u-info-color-weak: var(--u-blue-500);\n --u-info-color: var(--u-blue-700);\n --u-info-color-strong: var(--u-blue-800);\n\n /* success — 성공 · 완료\n ⚠green 은 700 도 4.12 로 미달이라 두 단을 건너뛴다. 계열마다 통과 단이 다른 것이\n 이 층의 정상 상태다(단 번호를 맞추면 대비가 어긋난다). */\n --u-success-color-weakest: var(--u-green-200);\n --u-success-color-weaker: var(--u-green-300);\n --u-success-color-weak: var(--u-green-500);\n --u-success-color: var(--u-green-800); /* 5.13 ✓ (600=3.30 · 700=4.12 ✗) */\n --u-success-color-strong: var(--u-green-900); /* 7.87 ✓ */\n\n /* warning — 주의 */\n --u-warning-color-weakest: var(--u-yellow-200);\n --u-warning-color-weaker: var(--u-yellow-300);\n --u-warning-color-weak: var(--u-yellow-500);\n --u-warning-color: var(--u-yellow-600);\n /* ★다른 계열은 -strong 이 shade-800~900 인데 warning 만 1000 이다 — 노랑 램프는\n 900 까지도 흰 바탕 2.65 로 미달이고, 1000(#8A4A00)에서 처음 6.86 이 된다.\n 그 값은 갈색에 가깝지만, 이 단의 용도는 **면이 아니라 글자·아이콘**이므로 색상보다\n 가독성이 먼저다(경고 문구를 어두운 호박색으로 쓰는 것은 보편 관행이다). */\n --u-warning-color-strong: var(--u-yellow-1000);\n\n /* danger — 오류 · 위험 · 유효성 실패 */\n --u-danger-color-weakest: var(--u-red-200);\n --u-danger-color-weaker: var(--u-red-300);\n --u-danger-color-weak: var(--u-red-500);\n --u-danger-color: var(--u-red-700); /* 4.98 ✓ (600 은 4.23 ✗ — 오류 문구가 이 단이었다) */\n --u-danger-color-strong: var(--u-red-800); /* 5.62 ✓ */\n /* ==========================================================================\n Radius Scale — 모서리 반경\n 리터럴을 흩뿌리면 값이 갈린다(실제로 pill 이 999px/9999px 두 표기로 나뉘어 있었다).\n ========================================================================== */\n --u-radius-none: 0;\n --u-radius-sm: 3px;\n --u-radius-md: 4px;\n --u-radius-lg: 6px;\n --u-radius-xl: 8px;\n /* ★상단 2단은 **면(surface)용**이다 — 카드·패널·대화상자처럼 큰 사각형은 컨트롤과\n 같은 반경을 쓰면 각져 보인다. 기존 5단은 **컨트롤용**이고 값을 바꾸지 않는다\n (바꾸면 모든 소비자의 버튼·입력이 동시에 움직인다). */\n --u-radius-2xl: 12px;\n --u-radius-3xl: 16px;\n --u-radius-pill: 9999px;\n --u-radius-circle: 50%;\n\n /* ==========================================================================\n Space Scale — 컨테이너·오버레이의 절대 여백\n ⚠**여백은 하나의 축이 아니다.** 이 스케일은 컨테이너/오버레이(카드·대화상자·드로어·\n 알림·메뉴·툴팁 등)의 **레이아웃 여백**만 담당한다. 폼·인라인 요소의 `em` 여백은\n 상속된 `font-size` 에 비례하는 것이 의도이므로 **여기로 흡수하지 않는다** —\n 흡수하면 타이포를 키운 소비자의 여백이 따라 커지지 않는다.\n 축 구분과 근거는 docs/design-tokens.md 참조.\n ========================================================================== */\n --u-space-3xs: 2px;\n --u-space-2xs: 4px;\n --u-space-xs: 6px;\n --u-space-sm: 8px;\n --u-space-md: 12px;\n --u-space-lg: 16px;\n /* ★상단 4단은 **화면 리듬**이다 — 카드 안쪽 여백(20~24)·섹션 간격(24~32)·페이지 여백\n (32~40). 종전에는 이 구간이 통째로 비어 있어 소비자가 전부 리터럴로 적었고,\n 그래서 앱마다 화면 밀도가 달라졌다. `lg`(16px) 이하는 **요소 사이**, `xl` 이상은\n **영역 사이**로 나눠 쓴다.\n ⚠`xs: 6px` 는 4px 격자에서 벗어나 있으나 **바꾸지 않는다** — 이미 배선된 컨트롤\n 여백이 전부 움직인다. 신규 단은 전부 4의 배수로 둔다. */\n --u-space-xl: 20px;\n --u-space-2xl: 24px;\n --u-space-3xl: 32px;\n --u-space-4xl: 40px;\n\n /* Text Colors */\n --u-txt-color: var(--u-neutral-900);\n --u-txt-color-inverse: var(--u-neutral-0);\n /* 유채색 배경 위의 글자. --u-txt-color-inverse 는 다크에서 neutral-100(#121212)이라\n 유채색 버튼 위에서 읽히지 않는다. 브랜드 색을 바꾸는 소비자가 전경색도 함께\n 조절할 수 있도록 별도 이름을 준다.\n ⚠이 토큰이 흰색이라는 것과 그 위의 배경이 AA 를 받친다는 것은 별개다 —\n 라이트 팔레트의 shade-600 은 8색 중 6색이 흰 글자로 AA 에 미달한다(미해결). */\n --u-primary-txt-color: #FFFFFF;\n --u-info-txt-color: #FFFFFF;\n --u-success-txt-color: #FFFFFF;\n --u-danger-txt-color: #FFFFFF;\n /* ★warning 만 어둡다 — 취향이 아니라 측정이다. 노랑은 **어떤 단도** 흰 글자로 AA 를\n 받치지 못한다(라이트 최대 2.65 @900, 그마저 갈색). 다른 넷처럼 단을 옮기는 수단이\n 없으므로 전경을 뒤집는다. `--u-neutral-1000` 은 라이트 #000000 / 다크 #FFFFFF 이라\n 한 줄로 양 테마를 만족한다(라이트 15.05 · 다크 4.65). */\n --u-warning-txt-color: var(--u-neutral-1000);\n\n --u-txt-color-hover: var(--u-primary-color-strong);\n --u-txt-color-active: var(--u-primary-color-strong);\n --u-txt-color-disabled: var(--u-neutral-400);\n /* 보조 텍스트는 «놓이는 모든 면»에서 AA(4.5)를 받쳐야 한다 — 바탕만이 아니다.\n neutral-600(#757575)은 바탕 4.61 에서만 통과하고 올림면(neutral-50) 4.41 ·\n active 면(neutral-200) 3.97 로 미달이었다(표 머리·카드 위 보조 텍스트).\n neutral-700(#616161) = 바탕 6.19 · 올림면 5.93 · active 5.34.\n 본문(neutral-900)과의 대비비는 2.60 으로, 보조 텍스트를 모든 표면 위에서\n 읽히게 보장하는 흔한 디자인 시스템 기준(본문 대비 약 1.3~1.8)보다 위계가 넓다. */\n --u-txt-color-weak: var(--u-neutral-700);\n --u-txt-color-strong: var(--u-neutral-1000);\n\n --u-link-txt-color: var(--u-primary-color-strong);\n --u-tooltip-txt-color: var(--u-neutral-0);\n\n /* Icon Colors */\n --u-icon-color: var(--u-neutral-700);\n --u-icon-color-inverse: var(--u-neutral-0);\n --u-icon-color-hover: var(--u-primary-color-strong);\n --u-icon-color-active: var(--u-primary-color-strong);\n --u-icon-color-disabled: var(--u-neutral-400);\n\n /* Border Colors */\n --u-border-color: var(--u-neutral-300);\n --u-border-color-weak: var(--u-neutral-200);\n --u-border-color-strong: var(--u-neutral-400);\n --u-border-color-hover: var(--u-neutral-400);\n\n /* ★상태 테두리는 `-strong` 단이다 — 면이 아니라 **면 위에 그리는 선**이기 때문이다.\n 1.16.0 이 가른 용도(`-color` = 면 / `-strong` = 면·바탕 위)에 이 자리가 맞춰지지\n 않아 다크에서 미달이었다: focus 2.74 · invalid 2.44 (WCAG 1.4.11 기준 3.0).\n `-strong` 으로 옮기면 다크 4.74 / 4.34, 라이트 5.75 / 5.62 — 두 테마 모두 단조 상승. */\n --u-input-border-color: var(--u-neutral-300);\n --u-input-border-color-hover: var(--u-neutral-400);\n --u-input-border-color-focus: var(--u-primary-color-strong);\n --u-input-border-color-invalid: var(--u-danger-color-strong);\n\n /* Background Colors */\n --u-bg-color: var(--u-neutral-0);\n --u-bg-color-inverse: var(--u-neutral-900);\n --u-bg-color-hover: var(--u-neutral-100);\n --u-bg-color-active: var(--u-neutral-200);\n --u-bg-color-disabled: var(--u-neutral-50);\n\n /* ★면 높이 — 바탕에 인접해 있으면서 한 단 구분되는 크롬 면(툴바·표 헤더·푸터).\n 상호작용 상태(-hover/-active/-disabled)와 **다른 축**이다. 상태 이름에 높이를\n 얹으면 의미가 어긋난다.\n `--u-panel-bg-color` 와도 다르다 — 그쪽은 **떠 있는 패널**(카드·대화상자·메뉴)이라\n 라이트에서 페이지와 같은 흰색이고 그림자가 높이를 나른다. 크롬 면은 그림자가 없어\n 라이트에서도 틴트가 필요하다.\n ⚠한 단만 정의한다. 두 단째의 실측 수요는 라이트 한쪽뿐이었다(다크에서는 소비 측\n 오버라이드가 두 값을 같은 단으로 합치고 있었다). */\n --u-bg-color-raised: var(--u-neutral-50);\n\n /* ⚠**라이트는 전역 hover 에 그대로 별칭한다 — 결손이 아니라 실측 결론이다**\n (dark.css 의 같은 자리 참조). 두 시트는 각각 완결적이어야 한다는\n 불변식(`token-fallbacks.test.ts` 「키 패리티」)이 있어 다크에만 선언할 수 없다.\n 라이트 팔레트는 raised(250)·hover(245)·active(238) 가 12단 안에 몰려 있어\n (L≈0.956/0.913/0.855) 셋과 겹치지 않는 네 번째 단을 넣을 여유가 없다 — 대비를\n 조금만 올려도(≈1.10) active 와 거의 붙고(≈1단 차), 더 올리면 순서가 뒤집힌다.\n 다크와 달리 raised(250)≠hover(245) 라 «완전히 안 움직이는» 결함이 아니었으므로\n (약한 대비 1.04 로 이미 알려진 채로 남는다 — 같은 초안이 지적한 곁가지),\n 새 단을 억지로 만들지 않고 기존 hover 를 그대로 쓴다. */\n --u-bg-color-raised-hover: var(--u-bg-color-hover);\n \n /* 유채색 표면 — 정보/성공/위험 상태의 '면'.\n 역할 층의 유채색은 전경 5단뿐이라, 상태 배경이 필요한 컴포넌트는 팔레트를 직접\n 읽고 다크를 손으로 보정해야 했다. 팔레트의 유채색 틴트는 다크에서 짓눌리므로\n (바탕 대비 델타의 다크/라이트 비 — 청색 0.38~0.54) 두 테마가 **같은 단이 아니라\n 같은 세기**가 되도록 짝지었다. 실측 비: blue 1.09 · red 1.12 · green 0.91.\n\n ★**warning 이 합류했다(1.16.0 → 1.17.0).** 종전에는 *\"세기를 맞출 단 짝이 없다\"* 며\n 빠져 있었는데, 그 판정은 **shade-0 짝만** 재고 있었다. 노랑만 한 단 내려 잡으면\n 라이트 쪽 세기가 맞는다 — 바탕 대비 휘도 델타 실측:\n blue-0 0.131 · red-0 0.132 · green-0 0.117 · **yellow-200 0.110** (yellow-0 은 0.027)\n ⚠단 이름이 계열마다 다른 것(yellow 만 200)은 이 층의 정상 상태다. 라이트 팔레트는\n 휘도 순이 아니므로 같은 단 번호가 같은 세기를 뜻하지 않는다. */\n --u-primary-bg-color: var(--u-blue-0);\n --u-info-bg-color: var(--u-blue-0);\n --u-success-bg-color: var(--u-green-0);\n --u-danger-bg-color: var(--u-red-0);\n --u-warning-bg-color: var(--u-yellow-200);\n\n --u-input-bg-color: var(--u-neutral-0);\n --u-panel-bg-color: var(--u-neutral-0);\n --u-overlay-bg-color: rgba(0, 0, 0, 0.5);\n --u-tooltip-bg-color: rgba(0, 0, 0, 0.75);\n\n /* Shadow Colors */\n --u-shadow-color-weaker: rgba(0, 0, 0, 0.04);\n --u-shadow-color-weak: rgba(0, 0, 0, 0.08);\n --u-shadow-color-normal: rgba(0, 0, 0, 0.12);\n --u-shadow-color-strong: rgba(0, 0, 0, 0.16);\n --u-shadow-color-stronger: rgba(0, 0, 0, 0.24);\n\n /* ==========================================================================\n Elevation Scale — 높이(그림자)\n\n ★색 축은 있었지만 **높이 축이 없었다.** 그 결과 컴포넌트가 그림자를 리터럴로\n 썼고, 같은 리듬을 의도한 자리에 서로 다른 값 11가지가 생겼다(카드 .1 vs 캐러셀\n .15 — 둘 다 \"표면에 얹힌 카드\"인데 알파가 다르다).\n\n ⚠**그리고 그 리터럴들은 테마를 몰랐다** — `rgba(0,0,0,.1)` 은 다크 바탕에서\n 거의 보이지 않는다. 이 축을 경유하면 다크의 진한 알파(.25~.60)를 자동으로 받는다.\n\n ⚠**알파를 `--u-shadow-color-*` 로 중첩하지 않고 인라인한다.** use-site 폴백\n 생성기는 합성 값을 리터럴로 다루므로, 중첩하면 `var(--u-shadow-md, 0 2px 8px\n var(--u-shadow-color-normal))` 처럼 **폴백 안에 또 토큰이 들어간다** — 시트가\n 없을 때 그 폴백도 함께 무효가 되어 그림자가 통째로 사라진다.\n 두 축의 알파가 어긋나지 않는지는 `tests/build/elevation-scale.test.ts` 가 지킨다.\n ========================================================================== */\n --u-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04); /* = shadow-color-weak — 표면에 얹힌 작은 컨트롤(탭·손잡이) */\n --u-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.05); /* = shadow-color-normal — 카드·표면 */\n --u-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.06); /* = shadow-color-strong — 떠 있는 레이어(드롭다운·알림) */\n --u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.24), 0 2px 6px rgba(0, 0, 0, 0.08); /* = shadow-color-stronger — 모달·최상위(대화상자·툴팁) */\n\n\n /* ==========================================================================\n Type Scale — 글자 크기·굵기·행간·자간의 **한 벌**\n ★**크기만 주면 스케일이 되지 않는다.** 소비자가 크기만 받고 굵기·행간을 각자 정하면\n 결국 화면마다 다른 위계가 생긴다 — 그래서 네 값을 **단 단위로 묶어** 낸다.\n\n 단 이름은 크기가 아니라 **역할**이다(`lg`/`xl` 이 아니라 `title`/`label`). 역할로 두면\n 소비자가 *\"어느 크기를 쓸까\"* 가 아니라 *\"이 글자는 무엇인가\"* 를 묻게 된다.\n\n ★**한글 기준으로 값을 골랐다**:\n ⑴ 행간은 **1.4 이상**. 라틴 관례(1.2)는 한글에서 답답하다 — 받침 때문에 글자 상자가\n 세로로 꽉 차 있어 라틴과 같은 행간이면 줄이 붙어 보인다.\n ⑵ 자간은 **0 이 기본**이고 큰 제목만 **음수**. 한글에 양수 자간(letter-spacing)을 주면\n 가독성이 떨어진다 — 라틴 소문자 조판 관례를 그대로 옮기면 안 되는 자리다.\n ⑶ `overline` 에만 양수 자간을 둔다. 그 단은 **영문·숫자 라벨**을 전제한 자리이고,\n 한글을 넣을 소비자는 자간을 0 으로 덮어야 한다(문서에 명시).\n\n ⚠**`text-transform` 은 토큰으로 내지 않는다.** 한글에는 대문자가 없어 `uppercase` 가\n 아무 효과가 없고, 영문이 섞이면 그것만 커져 오히려 어수선해진다.\n ========================================================================== */\n --u-text-display-size: 26px;\n --u-text-display-weight: 700;\n --u-text-display-leading: 1.4;\n --u-text-display-tracking: -0.02em;\n\n --u-text-title-size: 20px;\n --u-text-title-weight: 700;\n --u-text-title-leading: 1.45;\n --u-text-title-tracking: -0.01em;\n\n --u-text-subtitle-size: 16px;\n --u-text-subtitle-weight: 600;\n --u-text-subtitle-leading: 1.5;\n --u-text-subtitle-tracking: 0;\n\n --u-text-body-size: 14px;\n --u-text-body-weight: 400;\n --u-text-body-leading: 1.6;\n --u-text-body-tracking: 0;\n\n --u-text-label-size: 13px;\n --u-text-label-weight: 600;\n --u-text-label-leading: 1.5;\n --u-text-label-tracking: 0;\n\n --u-text-caption-size: 12px;\n --u-text-caption-weight: 400;\n --u-text-caption-leading: 1.5;\n --u-text-caption-tracking: 0;\n\n --u-text-overline-size: 11px;\n --u-text-overline-weight: 700;\n --u-text-overline-leading: 1.45;\n --u-text-overline-tracking: 0.06em;\n\n /* ==========================================================================\n Motion — 지속시간·이징\n ★값이 없으면 앱마다 다른 속도가 생기고, `prefers-reduced-motion` 은 **반드시**\n 빠뜨리는 앱이 나온다. 축을 여기 두고 존중 규칙은 아래 미디어 쿼리가 진다.\n ========================================================================== */\n --u-duration-instant: 80ms;\n --u-duration-fast: 140ms;\n --u-duration-normal: 220ms;\n --u-duration-slow: 320ms;\n --u-ease-standard: cubic-bezier(0.2, 0, 0, 1);\n --u-ease-decelerate: cubic-bezier(0, 0, 0, 1);\n --u-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);\n\n /* Scrollbar Colors */\n --u-scrollbar-color: var(--u-neutral-400);\n --u-scrollbar-color-hover: var(--u-neutral-500);\n --u-scrollbar-track-color: transparent;\n\n /* ==========================================================================\n Chart categorical palette — 차트 «계열» 색(범주형), 순서가 곧 계약이다\n ★여덟 칸이 **한 벌로** 검증됐다(dataviz 검증기, 흰 면 · 올림면): OKLCH 밝기 대역 0.43–0.77 ·\n 채도 하한 0.1 · 색각 이상(적·녹) 이웃 ΔE ≥ 12.7 · 정상 시각 이웃 ΔE ≥ 28.1. 순서를 바꾸거나\n 한 칸만 갈아 끼우면 그 검증이 깨진다 — 리브랜딩은 여덟 칸을 함께 다시 고른다.\n ★1번이 브랜드 파랑과 같은 단(blue-700)이라 계열 하나짜리 차트는 제품 색으로 그려진다.\n 그러나 역할 토큰(--u-primary-color)을 참조하지 **않는다** — 브랜드를 바꿨을 때 1번만 움직이면\n 나머지 일곱과의 구별이 검증 밖으로 나간다(장식 축과 같은 면역).\n ⚠상태색(success·danger 등)과 겹치지 않는 단을 골랐다(green-600 ≠ success green-800 · 빨강 없음).\n ⚠6번(yellow-900)은 흰 면 대비 2.65:1 — 범례·직접 레이블·표 보기가 함께 있어야 한다.\n ========================================================================== */\n --u-chart-color-1: var(--u-blue-700);\n --u-chart-color-2: var(--u-pink-800);\n --u-chart-color-3: var(--u-cyan-700);\n --u-chart-color-4: var(--u-orange-900);\n --u-chart-color-5: var(--u-teal-500);\n --u-chart-color-6: var(--u-yellow-900);\n --u-chart-color-7: var(--u-purple-600);\n --u-chart-color-8: var(--u-green-600);\n\n /* ==========================================================================\n Font Styles\n ★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**\n 종전 스택(`-apple-system, Segoe UI, Noto Sans, Helvetica, Arial`)에는 **한중일 글립을\n 가진 폰트가 하나도 없었다.** Windows 에서 한글은 `Segoe UI` 에 없으므로 UA 가 임의로\n 맑은 고딕을 고르고, macOS 는 `-apple-system` 이 Apple SD Gothic Neo 를 준다 ⇒ **같은 앱이\n OS 마다 다른 글꼴로 렌더**됐다. 폴백을 명시하면 그 선택이 결정적이 된다.\n ⚠**웹폰트를 로드하지 않는다.** 라이브러리가 네트워크 요청을 만들면 소비자의 CSP·\n 오프라인 환경을 깬다. 스택 맨 앞의 `Pretendard` 는 **소비자가 로드했을 때만** 잡히는\n 선택적 이름이다(없으면 조용히 다음으로 넘어간다).\n ========================================================================== */\n --u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';\n --u-font-mono: ui-monospace, 'Cascadia Code', Consolas, 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;\n --u-font-serif: 'Georgia', 'Times New Roman', Times, serif;\n --u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;\n --u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --u-font-rounded: 'Nunito', 'Quicksand', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n}\n\n/* ==========================================================================\n ★`prefers-reduced-motion` 존중 — **라이브러리가 진다.**\n 소비자마다 각자 처리하게 두면 반드시 빠뜨리는 앱이 나온다(그리고 그 앱은\n 접근성 감사 전까지 아무도 모른다). 지속시간 축을 0 으로 눌러 두면 이 축을\n 경유하는 모든 애니메이션이 함께 멈춘다.\n ⚠`animation: none` 으로 강제하지 않는다 — 로딩 스피너처럼 **의미를 나르는**\n 움직임까지 죽이면 사용자가 진행 중인지 알 수 없게 된다.\n ========================================================================== */\n@media (prefers-reduced-motion: reduce) {\n :root {\n --u-duration-instant: 0ms;\n --u-duration-fast: 0ms;\n --u-duration-normal: 0ms;\n --u-duration-slow: 0ms;\n }\n}\n";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { light_css_default as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { UElement } from "./UElement.js";
|
|
2
|
+
import { isFocusCandidate, querySelectorDeep } from "../utilities/elements.js";
|
|
2
3
|
import __decorateMetadata from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
3
4
|
import __decorate from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
4
5
|
import { OverlayManager } from "../utilities/OverlayManager.js";
|
|
@@ -129,10 +130,13 @@ var UOverlayElement = class extends UElement {
|
|
|
129
130
|
* (`tests/browser/overlay-initial-focus.browser.test.ts` 가 둘 다 감시한다.)
|
|
130
131
|
*/
|
|
131
132
|
resolveInitialFocus() {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
const content = Array.from(this.children);
|
|
134
|
+
const target = querySelectorDeep(content, "[autofocus]", isFocusCandidate) ?? querySelectorDeep(content, "input, select, textarea, u-input, u-textarea, u-select, u-checkbox, u-radio, u-switch, u-slider", isFocusCandidate);
|
|
135
|
+
if (!target) return void 0;
|
|
136
|
+
target.focus();
|
|
137
|
+
let active = document.activeElement;
|
|
138
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
139
|
+
for (let n = active; n; n = n.parentNode ?? n.host ?? null) if (n === target) return false;
|
|
136
140
|
}
|
|
137
141
|
/** 오버레이가 닫힐 때 설정을 해제합니다. */
|
|
138
142
|
cleanup() {
|
|
@@ -35,6 +35,10 @@ export type DatePickerMode = 'date' | 'datetime';
|
|
|
35
35
|
* @csspart calendar-footer - the row holding the "today"/"clear" quick-action buttons
|
|
36
36
|
* @csspart calendar-time - the row holding the time-of-day input (datetime mode only)
|
|
37
37
|
*
|
|
38
|
+
* @cssprop --u-date-picker-display - host `display` (default: inline-block). Set `block` to fill
|
|
39
|
+
* the container width in forms and grid cells.
|
|
40
|
+
* @cssprop --u-date-picker-width - host `width` (default: auto). Set `100%` where `block` alone
|
|
41
|
+
* does not stretch the host (e.g. inside a flex container).
|
|
38
42
|
* @cssprop --date-picker-popover-width - width of the calendar popover (default: 296px, independent of trigger width — a fixed-width calendar reads more naturally)
|
|
39
43
|
*
|
|
40
44
|
* @event change - fires when the user clicks a date cell, confirms via keyboard, changes the
|
|
@@ -33,7 +33,7 @@ export type InputVariant = 'outlined' | 'filled' | 'underlined' | 'borderless';
|
|
|
33
33
|
* @cssprop --input-popover-max-height - 드롭다운 팝오버의 최대 높이 (기본값: 50vh)
|
|
34
34
|
*
|
|
35
35
|
* @event input - 입력값이 변경될 때 발생
|
|
36
|
-
* @event change - 값이 확정됐을 때 발생
|
|
36
|
+
* @event change - 값이 확정됐을 때 발생 — Enter 또는 blur 에서, 값이 바뀐 경우에만(네이티브 입력과 같다)
|
|
37
37
|
*/
|
|
38
38
|
export declare class UInput extends UFormControlElement<string> {
|
|
39
39
|
static styles: import('lit').CSSResultGroup[];
|
|
@@ -99,6 +99,14 @@ export declare class UInput extends UFormControlElement<string> {
|
|
|
99
99
|
private handleCompositionStart;
|
|
100
100
|
private handleCompositionEnd;
|
|
101
101
|
private handleInputInput;
|
|
102
|
+
/**
|
|
103
|
+
* 호스트의 `change` 는 **내부 네이티브 입력의 `change` 를 그대로 옮긴다** — 커밋 시점을 흉내 내지 않고 브라우저에 맡긴다.
|
|
104
|
+
*
|
|
105
|
+
* 네이티브 단일 행 입력은 값이 바뀐 채 **Enter 를 누르거나 포커스를 잃을 때** `change` 를 낸다. 종전에는 blur 에서만
|
|
106
|
+
* 직접 디스패치해 ⑴Enter 로 암묵 제출할 때 `change` 가 **제출 뒤에야**(blur 시점) 나갔고 — `change` 로 값을 드는 폼이
|
|
107
|
+
* 빈 값으로 제출됐다 — ⑵값을 바꾸지 않은 blur 에도 `change` 를 냈다. 암묵 제출은 한 틱 뒤에 판정하므로(아래) 네이티브
|
|
108
|
+
* 순서(`change` → `submit`)가 그대로 선다.
|
|
109
|
+
*/
|
|
102
110
|
private handleInputChange;
|
|
103
111
|
private handleInputBlur;
|
|
104
112
|
private handleInputKeydown;
|
|
@@ -50,8 +50,7 @@ var UInput = class UInput extends UFormControlElement {
|
|
|
50
50
|
};
|
|
51
51
|
this.handleInputChange = (e) => {
|
|
52
52
|
e.stopPropagation();
|
|
53
|
-
|
|
54
|
-
this.handleInputBlur = (_) => {
|
|
53
|
+
if (this.composing) return;
|
|
55
54
|
this.value = this.inputEl?.value || "";
|
|
56
55
|
if (!this.novalidate) this.validate();
|
|
57
56
|
this.dispatchEvent(new Event("change", {
|
|
@@ -59,6 +58,10 @@ var UInput = class UInput extends UFormControlElement {
|
|
|
59
58
|
composed: true
|
|
60
59
|
}));
|
|
61
60
|
};
|
|
61
|
+
this.handleInputBlur = (_) => {
|
|
62
|
+
this.value = this.inputEl?.value || "";
|
|
63
|
+
if (!this.novalidate) this.validate();
|
|
64
|
+
};
|
|
62
65
|
this.handleInputKeydown = (e) => {
|
|
63
66
|
if (e.key === "Enter") {
|
|
64
67
|
this.handleImplicitSubmission(e);
|
|
@@ -131,6 +131,9 @@ var styles = css`
|
|
|
131
131
|
flex: 1;
|
|
132
132
|
min-width: 0;
|
|
133
133
|
line-height: 1.5;
|
|
134
|
+
/* 비어 있어도(값 없음 · 플레이스홀더 없음) 한 줄 높이 — 종전에는 줄 상자가 없어 빈 선택이
|
|
135
|
+
값이 있는 선택보다, 그리고 같은 행의 u-input 보다 낮았고 라벨 기준선이 어긋났다. */
|
|
136
|
+
min-block-size: 1.5em;
|
|
134
137
|
white-space: nowrap;
|
|
135
138
|
overflow: hidden;
|
|
136
139
|
text-overflow: ellipsis;
|
|
@@ -5,7 +5,7 @@ export type TagVariant = "solid" | "surface" | "filled" | "outlined";
|
|
|
5
5
|
* 말하고 리브랜딩을 따라오며 대비 계약을 물려받는다. **장식 축**(`blue`·`purple` …)은
|
|
6
6
|
* *색 자체*를 말하고 리브랜딩에 의도적으로 면역이다.
|
|
7
7
|
*/
|
|
8
|
-
export type TagColor = "neutral" | "primary" | "info" | "success" | "warning" | "danger" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink";
|
|
8
|
+
export type TagColor = "neutral" | "primary" | "info" | "success" | "warning" | "danger" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink" | "gray";
|
|
9
9
|
/**
|
|
10
10
|
* 레이블, 카테고리, 상태 등을 표시하는 태그 컴포넌트입니다.
|
|
11
11
|
*
|
|
@@ -66,6 +66,16 @@ var styles = css`
|
|
|
66
66
|
아래 9개 규칙이 hue 슬롯을 채우고, variant 규칙이 그것을 소비한다.
|
|
67
67
|
슬롯이 비면(color="neutral") variant 규칙의 폴백 = 브랜드 경로를 탄다.
|
|
68
68
|
========================================================================== */
|
|
69
|
+
/* gray — 장식 축의 무채색. «neutral» 은 브랜드 경로(위 주석)라 «회색 레이블» 을 낼 방법이 없었다
|
|
70
|
+
(«대기 중» 같은 상태가 «info» 와 같은 파랑으로 칠해졌다). 중립 램프를 읽되 명도 때문에 두 자리를
|
|
71
|
+
한 단 진하게 쓴다: solid 면은 흰 글자 대비로 700, 연한 면은 흰 바탕·올림면과 구별되게 200. */
|
|
72
|
+
:host([color="gray"]) {
|
|
73
|
+
--tag-hue-solid: var(--u-neutral-700, #616161);
|
|
74
|
+
--tag-hue-line: var(--u-neutral-300, #E0E0E0);
|
|
75
|
+
--tag-hue-surface: var(--u-neutral-200, #EEEEEE);
|
|
76
|
+
--tag-hue-text: var(--u-neutral-800, #424242);
|
|
77
|
+
--tag-hue-text-outlined: var(--u-neutral-700, #616161);
|
|
78
|
+
}
|
|
69
79
|
:host([color="blue"]) {
|
|
70
80
|
--tag-hue-solid: var(--u-blue-500, #2196F3);
|
|
71
81
|
--tag-hue-line: var(--u-blue-300, #64B5F6);
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UElement } from "./components/UElement.js";
|
|
2
|
-
import { getParentElement, isCoarsePointer, querySelectorAllWithin, querySelectorWithin } from "./utilities/elements.js";
|
|
2
|
+
import { getParentElement, isCoarsePointer, isFocusCandidate, querySelectorAllWithin, querySelectorDeep, querySelectorWithin } from "./utilities/elements.js";
|
|
3
3
|
import { UFloatingElement } from "./components/UFloatingElement.js";
|
|
4
4
|
import { UFormControlElement } from "./components/UFormControlElement.js";
|
|
5
5
|
import { OverlayManager } from "./utilities/OverlayManager.js";
|
|
@@ -59,4 +59,4 @@ import { BrowserStorage } from "./utilities/BrowserStorage.js";
|
|
|
59
59
|
import { Dialog } from "./utilities/Dialog.js";
|
|
60
60
|
import { Theme } from "./utilities/Theme.js";
|
|
61
61
|
import { Toast } from "./utilities/Toast.js";
|
|
62
|
-
export { ALERT_STATUSES, BrowserStorage, Dialog, IconCache, IconRegistry, Locale, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UCopyButton, UDatePicker, UDialog, UDivider, UDrawer, UElement, UExpander, UField, UFileInput, UFloatingElement, UForm, UFormControlElement, UIcon, UIconButton, UInput, UMenu, UMenuItem, UOption, UOverlayElement, UPanel, UPopover, UProgressBar, UProgressRing, URadio, URating, USelect, USkeleton, USlider, USpinner, USplitPanel, USwitch, UTab, UTabPanel, UTag, UText, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, createDevWarner, dateAttrConverter, devWarnOnce, formatCurrency, formatDate, formatNumber, getDefaultBaseUrl, getParentElement, isCoarsePointer, jsonAttrConverter, querySelectorAllWithin, querySelectorWithin, resetDevWarnings, setDefaultBaseUrl, urlAttrConverter };
|
|
62
|
+
export { ALERT_STATUSES, BrowserStorage, Dialog, IconCache, IconRegistry, Locale, OverlayManager, Theme, Toast, UAlert, UAvatar, UBadge, UBreadcrumb, UBreadcrumbItem, UButton, UButtonGroup, UCard, UCarousel, UCheckbox, UChip, UCopyButton, UDatePicker, UDialog, UDivider, UDrawer, UElement, UExpander, UField, UFileInput, UFloatingElement, UForm, UFormControlElement, UIcon, UIconButton, UInput, UMenu, UMenuItem, UOption, UOverlayElement, UPanel, UPopover, UProgressBar, UProgressRing, URadio, URating, USelect, USkeleton, USlider, USpinner, USplitPanel, USwitch, UTab, UTabPanel, UTag, UText, UTextarea, UTooltip, UTree, UTreeItem, arrayAttrConverter, booleanAttrConverter, createDevWarner, dateAttrConverter, devWarnOnce, formatCurrency, formatDate, formatNumber, getDefaultBaseUrl, getParentElement, isCoarsePointer, isFocusCandidate, jsonAttrConverter, querySelectorAllWithin, querySelectorDeep, querySelectorWithin, resetDevWarnings, setDefaultBaseUrl, urlAttrConverter };
|
package/dist/styles/dark.css
CHANGED
|
@@ -295,6 +295,23 @@
|
|
|
295
295
|
--u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.30); /* = shadow-color-stronger */
|
|
296
296
|
|
|
297
297
|
|
|
298
|
+
/* ==========================================================================
|
|
299
|
+
Chart categorical palette — 다크 면(#121212 · 올림면 #2A2A2A)에 대해 **따로 고른** 여덟 칸
|
|
300
|
+
★램프를 참조하지 않는 이유: 다크 장식 램프는 채도가 낮아(면 위 배지·태그용) 차트 계열로는
|
|
301
|
+
회색처럼 읽힌다 — 램프의 단 조합 39만 가지 중 검증을 통과한 것이 없었다. 그래서 라이트
|
|
302
|
+
여덟 칸과 **같은 색상·순서**를 OKLCH 밝기만 다크 대역으로 옮겨 잡았다.
|
|
303
|
+
검증: 밝기 0.48–0.67 · 채도 ≥ 0.1 · 색각 이상 이웃 ΔE ≥ 9.5 · 정상 시각 이웃 ΔE ≥ 25.1 ·
|
|
304
|
+
두 면 모두 대비 ≥ 3:1. 순서는 light.css 와 같다.
|
|
305
|
+
========================================================================== */
|
|
306
|
+
--u-chart-color-1: #247EDB;
|
|
307
|
+
--u-chart-color-2: #D03E73;
|
|
308
|
+
--u-chart-color-3: #0DA1B2;
|
|
309
|
+
--u-chart-color-4: #ED5711;
|
|
310
|
+
--u-chart-color-5: #059183;
|
|
311
|
+
--u-chart-color-6: #D96D04;
|
|
312
|
+
--u-chart-color-7: #AE48CB;
|
|
313
|
+
--u-chart-color-8: #4AA74D;
|
|
314
|
+
|
|
298
315
|
/* Scrollbar Colors */
|
|
299
316
|
--u-scrollbar-color: var(--u-neutral-500);
|
|
300
317
|
--u-scrollbar-color-hover: var(--u-neutral-600);
|
|
@@ -432,7 +449,7 @@
|
|
|
432
449
|
선택적 이름이다(없으면 조용히 다음으로 넘어간다).
|
|
433
450
|
========================================================================== */
|
|
434
451
|
--u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
|
|
435
|
-
--u-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;
|
|
452
|
+
--u-font-mono: ui-monospace, 'Cascadia Code', Consolas, 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;
|
|
436
453
|
--u-font-serif: 'Georgia', 'Times New Roman', Times, serif;
|
|
437
454
|
--u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
|
|
438
455
|
--u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
package/dist/styles/light.css
CHANGED
|
@@ -438,6 +438,26 @@
|
|
|
438
438
|
--u-scrollbar-color-hover: var(--u-neutral-500);
|
|
439
439
|
--u-scrollbar-track-color: transparent;
|
|
440
440
|
|
|
441
|
+
/* ==========================================================================
|
|
442
|
+
Chart categorical palette — 차트 «계열» 색(범주형), 순서가 곧 계약이다
|
|
443
|
+
★여덟 칸이 **한 벌로** 검증됐다(dataviz 검증기, 흰 면 · 올림면): OKLCH 밝기 대역 0.43–0.77 ·
|
|
444
|
+
채도 하한 0.1 · 색각 이상(적·녹) 이웃 ΔE ≥ 12.7 · 정상 시각 이웃 ΔE ≥ 28.1. 순서를 바꾸거나
|
|
445
|
+
한 칸만 갈아 끼우면 그 검증이 깨진다 — 리브랜딩은 여덟 칸을 함께 다시 고른다.
|
|
446
|
+
★1번이 브랜드 파랑과 같은 단(blue-700)이라 계열 하나짜리 차트는 제품 색으로 그려진다.
|
|
447
|
+
그러나 역할 토큰(--u-primary-color)을 참조하지 **않는다** — 브랜드를 바꿨을 때 1번만 움직이면
|
|
448
|
+
나머지 일곱과의 구별이 검증 밖으로 나간다(장식 축과 같은 면역).
|
|
449
|
+
⚠상태색(success·danger 등)과 겹치지 않는 단을 골랐다(green-600 ≠ success green-800 · 빨강 없음).
|
|
450
|
+
⚠6번(yellow-900)은 흰 면 대비 2.65:1 — 범례·직접 레이블·표 보기가 함께 있어야 한다.
|
|
451
|
+
========================================================================== */
|
|
452
|
+
--u-chart-color-1: var(--u-blue-700);
|
|
453
|
+
--u-chart-color-2: var(--u-pink-800);
|
|
454
|
+
--u-chart-color-3: var(--u-cyan-700);
|
|
455
|
+
--u-chart-color-4: var(--u-orange-900);
|
|
456
|
+
--u-chart-color-5: var(--u-teal-500);
|
|
457
|
+
--u-chart-color-6: var(--u-yellow-900);
|
|
458
|
+
--u-chart-color-7: var(--u-purple-600);
|
|
459
|
+
--u-chart-color-8: var(--u-green-600);
|
|
460
|
+
|
|
441
461
|
/* ==========================================================================
|
|
442
462
|
Font Styles
|
|
443
463
|
★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**
|
|
@@ -450,7 +470,7 @@
|
|
|
450
470
|
선택적 이름이다(없으면 조용히 다음으로 넘어간다).
|
|
451
471
|
========================================================================== */
|
|
452
472
|
--u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
|
|
453
|
-
--u-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;
|
|
473
|
+
--u-font-mono: ui-monospace, 'Cascadia Code', Consolas, 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;
|
|
454
474
|
--u-font-serif: 'Georgia', 'Times New Roman', Times, serif;
|
|
455
475
|
--u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
|
|
456
476
|
--u-font-modern: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit';
|
|
2
2
|
import { DialogPlacement } from '../components/dialog/UDialog.js';
|
|
3
|
-
import { ButtonVariant } from '../components/button/UButton.js';
|
|
3
|
+
import { ButtonColor, ButtonVariant } from '../components/button/UButton.js';
|
|
4
4
|
/** 공통 Dialog 옵션 */
|
|
5
5
|
export interface DialogOptions {
|
|
6
6
|
/** 다이얼로그를 표시할 대상 엘리먼트, 지정 시 contained 모드로 동작 */
|
|
@@ -26,6 +26,11 @@ export interface ConfirmDialogOptions extends DialogOptions {
|
|
|
26
26
|
confirmLabel?: string;
|
|
27
27
|
/** 취소 버튼 텍스트 (기본: 현재 로케일의 `cancel` — 영어는 'Cancel') */
|
|
28
28
|
cancelLabel?: string;
|
|
29
|
+
/**
|
|
30
|
+
* 확인 버튼의 색. 되돌릴 수 없는 동작(삭제·취소)을 확인할 때 `'danger'` — 그 확인 버튼이 화면에서
|
|
31
|
+
* 파괴적 동작이 solid 로 칠해지는 유일한 자리가 된다. 기본은 버튼의 기본색.
|
|
32
|
+
*/
|
|
33
|
+
confirmColor?: ButtonColor;
|
|
29
34
|
}
|
|
30
35
|
/** Prompt Dialog 옵션 */
|
|
31
36
|
export interface PromptDialogOptions extends ConfirmDialogOptions {
|
|
@@ -51,6 +56,8 @@ export interface DialogAction {
|
|
|
51
56
|
value: string;
|
|
52
57
|
/** 버튼 스타일 */
|
|
53
58
|
variant?: ButtonVariant;
|
|
59
|
+
/** 버튼 색 (기본: 버튼의 기본색) */
|
|
60
|
+
color?: ButtonColor;
|
|
54
61
|
}
|
|
55
62
|
/**
|
|
56
63
|
* Dialog 유틸리티 클래스입니다.
|
package/dist/utilities/Dialog.js
CHANGED
|
@@ -3,6 +3,7 @@ import { Locale } from "./Locale.js";
|
|
|
3
3
|
import { UDialog } from "../components/dialog/UDialog.js";
|
|
4
4
|
import "../components/input/UInput.js";
|
|
5
5
|
import { html, nothing, render } from "lit";
|
|
6
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
6
7
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
7
8
|
//#region src/utilities/Dialog.ts
|
|
8
9
|
/**
|
|
@@ -35,7 +36,8 @@ var Dialog = class {
|
|
|
35
36
|
variant: "outlined"
|
|
36
37
|
}, {
|
|
37
38
|
label: options?.confirmLabel || Locale.getValue("confirm"),
|
|
38
|
-
value: "confirm"
|
|
39
|
+
value: "confirm",
|
|
40
|
+
color: options?.confirmColor
|
|
39
41
|
}]
|
|
40
42
|
}) === "confirm";
|
|
41
43
|
}
|
|
@@ -95,6 +97,7 @@ var Dialog = class {
|
|
|
95
97
|
${actions.map((action) => html`
|
|
96
98
|
<u-button
|
|
97
99
|
variant=${action.variant || "solid"}
|
|
100
|
+
color=${ifDefined(action.color)}
|
|
98
101
|
@click=${() => {
|
|
99
102
|
closeValue = action.value;
|
|
100
103
|
dialog.hide();
|
|
@@ -21,3 +21,17 @@ export declare function querySelectorAllWithin(element: Element, selectors: stri
|
|
|
21
21
|
* 컴포넌트가 이를 구분하지 않으면 열리자마자 닫히는 결함으로 이어집니다(모바일 실측).
|
|
22
22
|
*/
|
|
23
23
|
export declare function isCoarsePointer(event: PointerEvent): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 포커스를 «받을 수 있는» 요소인가 — 초기 포커스 후보를 고를 때 쓴다.
|
|
26
|
+
* 네이티브 포커스 요소 · `focus()` 를 재정의한(안쪽으로 넘겨 주는) 컴포넌트 · `tabindex` 를 가진 요소이고,
|
|
27
|
+
* 비활성·`inert`·안 보임이 아니어야 한다. 걸러진 호스트는 그 안쪽(섀도 루트)에서 계속 찾는다.
|
|
28
|
+
* `u-select` 의 섀도에는 속성 `autofocus` 를 가진 닫힌 `u-popover` 가 늘 있다 — 이것을 집으면
|
|
29
|
+
* 포커스가 아무 데도 가지 않는다.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isFocusCandidate(el: Element): el is HTMLElement;
|
|
32
|
+
/**
|
|
33
|
+
* `roots` 와 그 자손에서(열린 섀도 루트 안쪽까지) `selectors` 에 맞는 첫 요소를 문서 순서로 찾는다.
|
|
34
|
+
* 섀도 루트 안은 호스트 자리에서 이어서 본다 — `querySelector` 는 섀도 경계에서 멈추므로,
|
|
35
|
+
* 슬롯 자식이 컴포넌트면 그 템플릿 안의 요소를 못 찾는다. `accept` 가 거른 요소도 그 안쪽은 계속 본다.
|
|
36
|
+
*/
|
|
37
|
+
export declare function querySelectorDeep(roots: Iterable<Element>, selectors: string, accept?: (el: Element) => boolean): HTMLElement | null;
|
|
@@ -42,5 +42,43 @@ function querySelectorAllWithin(element, selectors) {
|
|
|
42
42
|
function isCoarsePointer(event) {
|
|
43
43
|
return event.pointerType === "touch" || event.pointerType === "pen";
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* 포커스를 «받을 수 있는» 요소인가 — 초기 포커스 후보를 고를 때 쓴다.
|
|
47
|
+
* 네이티브 포커스 요소 · `focus()` 를 재정의한(안쪽으로 넘겨 주는) 컴포넌트 · `tabindex` 를 가진 요소이고,
|
|
48
|
+
* 비활성·`inert`·안 보임이 아니어야 한다. 걸러진 호스트는 그 안쪽(섀도 루트)에서 계속 찾는다.
|
|
49
|
+
* `u-select` 의 섀도에는 속성 `autofocus` 를 가진 닫힌 `u-popover` 가 늘 있다 — 이것을 집으면
|
|
50
|
+
* 포커스가 아무 데도 가지 않는다.
|
|
51
|
+
*/
|
|
52
|
+
function isFocusCandidate(el) {
|
|
53
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
54
|
+
const native = el.matches("input:not([type=\"hidden\"]), select, textarea, button, a[href], [contenteditable=\"\"], [contenteditable=\"true\"]");
|
|
55
|
+
const forwards = el.focus !== HTMLElement.prototype.focus;
|
|
56
|
+
if (!native && !forwards && !el.hasAttribute("tabindex")) return false;
|
|
57
|
+
if (el.matches(":disabled") || el.hasAttribute("disabled") || el.closest("[inert]")) return false;
|
|
58
|
+
return typeof el.checkVisibility === "function" ? el.checkVisibility() : true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* `roots` 와 그 자손에서(열린 섀도 루트 안쪽까지) `selectors` 에 맞는 첫 요소를 문서 순서로 찾는다.
|
|
62
|
+
* 섀도 루트 안은 호스트 자리에서 이어서 본다 — `querySelector` 는 섀도 경계에서 멈추므로,
|
|
63
|
+
* 슬롯 자식이 컴포넌트면 그 템플릿 안의 요소를 못 찾는다. `accept` 가 거른 요소도 그 안쪽은 계속 본다.
|
|
64
|
+
*/
|
|
65
|
+
function querySelectorDeep(roots, selectors, accept = () => true) {
|
|
66
|
+
const visit = (start) => {
|
|
67
|
+
const walker = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENT);
|
|
68
|
+
for (let el = walker.currentNode; el; el = walker.nextNode()) {
|
|
69
|
+
if (el.matches(selectors) && accept(el)) return el;
|
|
70
|
+
if (el.shadowRoot) for (const child of Array.from(el.shadowRoot.children)) {
|
|
71
|
+
const found = visit(child);
|
|
72
|
+
if (found) return found;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
};
|
|
77
|
+
for (const root of roots) {
|
|
78
|
+
const found = visit(root);
|
|
79
|
+
if (found) return found;
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
45
83
|
//#endregion
|
|
46
|
-
export { getParentElement, isCoarsePointer, querySelectorAllWithin, querySelectorWithin };
|
|
84
|
+
export { getParentElement, isCoarsePointer, isFocusCandidate, querySelectorAllWithin, querySelectorDeep, querySelectorWithin };
|
package/package.json
CHANGED
|
@@ -92,7 +92,7 @@ whole contract. Measured in a real browser
|
|
|
92
92
|
|
|
93
93
|
| Requirement | How it is met |
|
|
94
94
|
|---|---|
|
|
95
|
-
| Focus the first input on open, restore the trigger on close | `[autofocus]` → first input control → first tabbable; focus is returned by the trap |
|
|
95
|
+
| Focus the first input on open, restore the trigger on close | `[autofocus]` → first input control → first tabbable, searched through shadow roots (a form component slotted in works the same); focus is returned by the trap |
|
|
96
96
|
| Body scrolls, footer stays visible | `part="body"` is `flex: 1; overflow: auto`; the `footer` slot is `flex-shrink: 0` |
|
|
97
97
|
| Focus cannot leave the panel | `mode="modal"` (default) activates the focus trap |
|
|
98
98
|
| `Esc` closes, background scroll is locked | `closeOn` defaults to `['escape','backdrop','button']` |
|
|
@@ -79,7 +79,7 @@ for a KRW amount) is the consumer's call — the library does not infer one from
|
|
|
79
79
|
| Event | Description |
|
|
80
80
|
|-------|-------------|
|
|
81
81
|
| `input` | Fires on every keystroke |
|
|
82
|
-
| `change` | Fires when value is committed |
|
|
82
|
+
| `change` | Fires when the value is committed — on `Enter` or on blur, and only if it changed (like a native `<input>`). On `Enter` inside a form it fires before the form submits |
|
|
83
83
|
|
|
84
84
|
## Form submission
|
|
85
85
|
|
|
@@ -37,7 +37,7 @@ For interactive chips (selectable/removable), use [`u-chip`](./chip.md) instead.
|
|
|
37
37
|
| Property | Type | Default | Reflect | Description |
|
|
38
38
|
|----------|------|---------|---------|-------------|
|
|
39
39
|
| `variant` | `'solid'\|'surface'\|'filled'\|'outlined'` | `'filled'` | ✓ | Visual style |
|
|
40
|
-
| `color` | `'neutral'\|'primary'\|'info'\|'success'\|'warning'\|'danger'\|'blue'\|'green'\|'yellow'\|'red'\|'orange'\|'teal'\|'cyan'\|'purple'\|'pink'` | `'neutral'` | ✓ | Color |
|
|
40
|
+
| `color` | `'neutral'\|'primary'\|'info'\|'success'\|'warning'\|'danger'\|'blue'\|'green'\|'yellow'\|'red'\|'orange'\|'teal'\|'cyan'\|'purple'\|'pink'\|'gray'` | `'neutral'` | ✓ | Color |
|
|
41
41
|
| `rounded` | `boolean` | `false` | ✓ | Pill shape |
|
|
42
42
|
| `icon` | `boolean` | `false` | ✓ | Adds a status icon so the meaning survives without color (`info`/`success`/`warning`/`danger` only) |
|
|
43
43
|
|
|
@@ -53,7 +53,11 @@ For interactive chips (selectable/removable), use [`u-chip`](./chip.md) instead.
|
|
|
53
53
|
|
|
54
54
|
`color` carries **two** axes. The **role** axis (`primary`·`info`·`success`·`warning`·`danger`)
|
|
55
55
|
means *semantics* — it follows re-branding and inherits the contrast contract. The **decorative**
|
|
56
|
-
axis (`blue`·`purple` …) means *the color itself* and is deliberately immune to re-branding.
|
|
56
|
+
axis (`blue`·`purple` … `gray`) means *the color itself* and is deliberately immune to re-branding.
|
|
57
|
+
|
|
58
|
+
`neutral` (the default) is **not gray** — it follows the brand colour, so a default tag matches the
|
|
59
|
+
product. For a label that should carry no colour at all — a status such as "Pending" next to an
|
|
60
|
+
`info` "Shipped" — use `gray`.
|
|
57
61
|
|
|
58
62
|
`icon` only applies to the four **status** roles — `neutral` and `primary` are not states, and the
|
|
59
63
|
decorative axis carries no meaning, so no icon is drawn there.
|
|
@@ -16,6 +16,11 @@ await Dialog.alert('Operation completed.');
|
|
|
16
16
|
const confirmed = await Dialog.confirm('Delete this item?');
|
|
17
17
|
if (confirmed) deleteItem();
|
|
18
18
|
|
|
19
|
+
// Confirming something that cannot be undone — the confirm button is drawn in `danger`
|
|
20
|
+
const ok = await Dialog.confirm('Cancel order G-2026-0512? This cannot be undone.', {
|
|
21
|
+
confirmLabel: 'Cancel order', cancelLabel: 'Keep order', confirmColor: 'danger',
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
// Prompt — returns entered string or null if cancelled
|
|
20
25
|
const name = await Dialog.prompt('Enter your name:', { defaultValue: 'Alice' });
|
|
21
26
|
|
|
@@ -57,6 +62,7 @@ interface DialogOptions {
|
|
|
57
62
|
interface ConfirmDialogOptions extends DialogOptions {
|
|
58
63
|
confirmLabel?: string; // default: the active locale's `confirm` (en: 'Confirm')
|
|
59
64
|
cancelLabel?: string; // default: the active locale's `cancel` (en: 'Cancel')
|
|
65
|
+
confirmColor?: ButtonColor; // e.g. 'danger' for an irreversible action — default: the button's default
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
interface PromptDialogOptions extends ConfirmDialogOptions {
|
|
@@ -74,5 +80,6 @@ interface DialogAction {
|
|
|
74
80
|
label: string;
|
|
75
81
|
value: string;
|
|
76
82
|
variant?: ButtonVariant;
|
|
83
|
+
color?: ButtonColor;
|
|
77
84
|
}
|
|
78
85
|
```
|