@iyulab/modern-app 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/README.md +27 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.151.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.151.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/components/ActionBar.js +2 -2
- package/dist/components/EmptyState.d.ts +3 -3
- package/dist/components/EmptyState.js +2 -2
- package/dist/components/GroupBox.d.ts +11 -2
- package/dist/components/GroupBox.js +4 -4
- package/dist/components/GroupBox.styles.js +8 -0
- package/dist/components/InfoField.js +2 -2
- package/dist/components/InfoSection.js +2 -2
- package/dist/components/MasterDetailLayout.d.ts +1 -1
- package/dist/components/MasterDetailLayout.js +2 -2
- package/dist/components/PageHeader.d.ts +2 -2
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/SidebarButton.js +2 -2
- package/dist/components/SidebarGroup.js +2 -2
- package/dist/components/SidebarLink.js +2 -2
- package/dist/components/SidebarSection.js +2 -2
- package/dist/components/Wizard.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -12
- package/dist/internals/StyledElement.js +2 -2
- package/dist/internals/locale.d.ts +16 -27
- package/dist/internals/locale.js +59 -19
- package/dist/layouts/SidebarLayout.d.ts +1 -1
- package/dist/layouts/SidebarLayout.js +2 -2
- package/package.json +2 -2
- package/skills/modern-app/SKILL.md +27 -0
- package/skills/modern-app/references/components/empty-state.md +2 -1
- package/skills/modern-app/references/components/group-box.md +4 -1
- package/skills/modern-app/references/components/info-field.md +4 -0
- package/skills/modern-app/references/components/page-header.md +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.27.0] - 2026-09-24
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`u-group-box[meta]` — secondary text beside the title.** List-like sections of a detail screen
|
|
8
|
+
almost always carry a count (`3 items`, `2/5 done`), and with `title` being a plain string the
|
|
9
|
+
count was drawn at the title's size, weight and color, so the section name and its current
|
|
10
|
+
state read as one heading. `meta` draws that text one step below the title — body size and
|
|
11
|
+
weight, weak color, tabular figures — on the same baseline. It sits inside the heading, so the
|
|
12
|
+
heading's accessible name includes it. It is not drawn without a `title`. New `meta` part.
|
|
13
|
+
- **Korean built-in strings.** 0.26.0 moved the language choice to `Locale.set()`, but the namespace
|
|
14
|
+
held only an English table, so an app that already called `Locale.set('ko')` still got the
|
|
15
|
+
sidebar toggle's and overlay close button's accessible names, the back link, empty-state copy and
|
|
16
|
+
wizard labels in English. A Korean table now ships alongside English — the same scope as
|
|
17
|
+
`@iyulab/flex-table`. English stays the default; a Korean registration of your own overrides only
|
|
18
|
+
the keys it gives.
|
|
19
|
+
|
|
20
|
+
## [0.26.0] - 2026-09-23
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- 🔴 **Built-in strings follow `Locale` of `@iyulab/components` — the language is chosen once, with
|
|
25
|
+
`Locale.set()`.** This package kept a registry of its own (`registerLocale`/`setDefaultLocale`)
|
|
26
|
+
while the primitives and `@iyulab/flex-table` follow `Locale`, so an app that set the language
|
|
27
|
+
once got the shell's `Toggle sidebar`/`Toggle menu`/`Close` labels, the back link and empty-state
|
|
28
|
+
copy in English in the middle of a translated screen — silently. The strings now live in a
|
|
29
|
+
`Locale.namespace('modern-app')`, and resolve through the same chain as the primitives (so
|
|
30
|
+
`lang="zh"` reaches a `zh-CN` table). An element's own `locale` attribute still overrides the
|
|
31
|
+
active language for that element.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **`modernAppLocale`** — the namespace handle, for translations:
|
|
36
|
+
`modernAppLocale.register('ko', { back: '뒤로' })`, the same shape as `flexTableLocale.register`.
|
|
37
|
+
`wizardStepAnnouncement` is a template there (`'{total}단계 중 {index}단계: {label}'`).
|
|
38
|
+
**`ModernAppMessageKey`** is its key type.
|
|
39
|
+
|
|
40
|
+
### Deprecated
|
|
41
|
+
|
|
42
|
+
- **`registerLocale` and `setDefaultLocale`.** Both keep working: `registerLocale` forwards to
|
|
43
|
+
the namespace (a function-valued `wizardStepAnnouncement` still works), and a `setDefaultLocale()`
|
|
44
|
+
call still takes precedence over `Locale` until it is called with `undefined` — an app that
|
|
45
|
+
calls both with the same language sees no change and can drop `setDefaultLocale` at its leisure.
|
|
46
|
+
|
|
47
|
+
⚠ **Requires `@iyulab/components` 1.45.0** (for `LocaleNamespace.textIn`, which resolves an
|
|
48
|
+
element's own `locale`).
|
|
49
|
+
|
|
3
50
|
## [0.25.0] - 2026-09-23
|
|
4
51
|
|
|
5
52
|
### Added
|
package/README.md
CHANGED
|
@@ -118,6 +118,33 @@ import { translate } from '@iyulab/modern-app';
|
|
|
118
118
|
html`<p>${translate('common::greeting')}</p>`;
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
+
### Built-in strings
|
|
122
|
+
|
|
123
|
+
The package's own strings — the page header's back link, empty-state copy, the shell's toggle and
|
|
124
|
+
close labels, the wizard's buttons and step announcement — live in the `modern-app` namespace of
|
|
125
|
+
`@iyulab/components`' `Locale`. English and Korean are built in, English being the default; pick the
|
|
126
|
+
language once, with `Locale.set()` — the primitives and `@iyulab/flex-table` follow the same call.
|
|
127
|
+
Register other languages, or your own wording, in the same namespace:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { Locale } from '@iyulab/components';
|
|
131
|
+
import { modernAppLocale } from '@iyulab/modern-app';
|
|
132
|
+
|
|
133
|
+
Locale.set('ko'); // built-in Korean — nothing to register
|
|
134
|
+
|
|
135
|
+
modernAppLocale.register('ja', {
|
|
136
|
+
back: '戻る',
|
|
137
|
+
toggleSidebar: 'サイドバーの切り替え',
|
|
138
|
+
wizardStepAnnouncement: 'ステップ {index}/{total}: {label}',
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
A partial table is enough — untranslated keys fall back to English, and a registration for a
|
|
143
|
+
built-in language overrides only the keys it gives. An element's own `locale`
|
|
144
|
+
attribute overrides the active language for that element. `registerLocale`/`setDefaultLocale` still
|
|
145
|
+
work but are deprecated: a `setDefaultLocale()` call takes precedence over `Locale` until it is
|
|
146
|
+
called with `undefined`.
|
|
147
|
+
|
|
121
148
|
### 부팅 인증 게이트 (`auth`)
|
|
122
149
|
|
|
123
150
|
셸을 만들기 전에 세션을 판정한다. 소비앱이 `app.load()` 앞단에 손으로 짜던 "me 조회 → 미인증이면 로그인, 인증이면 앱 로드" 게이트를 표준화한다. 세션 조회/로그인 HTTP 는 `@iyulab/enterprise` 의 `createAuthClient` 가, 세션-중 401 은 `createODataService` 의 `onUnauthorized` 가 담당한다(프레임워크는 오케스트레이션만 소유).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
|
|
2
2
|
function e(e, t, n, r) {
|
|
3
3
|
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
4
4
|
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorateMetadata.js
|
|
2
2
|
function e(e, t) {
|
|
3
3
|
if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
|
|
4
4
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { slotHasContent as r } from "../internals/slotted.js";
|
|
5
5
|
import { styles as i } from "./ActionBar.styles.js";
|
|
@@ -19,7 +19,7 @@ type ElementParts = 'host' | 'icon' | 'title' | 'description' | 'actions';
|
|
|
19
19
|
* ```
|
|
20
20
|
*
|
|
21
21
|
* ⚠**기본 문구는 영어다** — 이 패키지는 범용 층이라 특정 언어를 기본값으로 가질 수 없다.
|
|
22
|
-
*
|
|
22
|
+
* 한국어 표는 내장돼 있고(언어는 `Locale.set()`), 다른 언어는 `modernAppLocale.register(lang, …)` 로 소비자가 등록한다. 화면별로 덮으려면
|
|
23
23
|
* `title`·`description` 을 준다.
|
|
24
24
|
*
|
|
25
25
|
* ★이 줄은 «한국어다»라고 적혀 있었고 **같은 파일의 `locale` 프로퍼티 주석이 «영어다»라고
|
|
@@ -35,9 +35,9 @@ export declare class EmptyState extends StyledElement<ElementParts> {
|
|
|
35
35
|
/** 보조 설명. 비우면 variant 기본 문구. */
|
|
36
36
|
description: string;
|
|
37
37
|
/**
|
|
38
|
-
* 언어
|
|
38
|
+
* 언어 태그 — 이 요소만 문서와 다른 언어로 쓸 때. 비우면 `Locale` 의 활성 로케일.
|
|
39
39
|
* ⚠기본 문구는 영어다 — 이 패키지는 범용 층이라 특정 언어를 기본값으로 가질 수 없다.
|
|
40
|
-
*
|
|
40
|
+
* 한국어 표는 내장돼 있다 — 다른 언어는 `modernAppLocale.register(lang, …)` 로 소비자가 등록한다.
|
|
41
41
|
*/
|
|
42
42
|
locale: string;
|
|
43
43
|
/** 액션 슬롯 배정 상태 — CSS `:has()` 로는 알 수 없다(`internals/slotted.ts` 참조). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { getLocaleStrings as r } from "../internals/locale.js";
|
|
5
5
|
import { slotHasContent as i } from "../internals/slotted.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StyledElement } from '../internals/StyledElement.js';
|
|
2
2
|
import { default as React } from 'react';
|
|
3
|
-
type ElementParts = 'host' | 'header' | 'title' | 'actions' | 'body';
|
|
3
|
+
type ElementParts = 'host' | 'header' | 'title' | 'meta' | 'actions' | 'body';
|
|
4
4
|
/** 제목 단계 — 페이지 제목(h1)은 `u-page-header` 몫이라 2 부터다. */
|
|
5
5
|
export type GroupBoxLevel = 2 | 3 | 4 | 5 | 6;
|
|
6
6
|
/**
|
|
@@ -18,13 +18,21 @@ export type GroupBoxLevel = 2 | 3 | 4 | 5 | 6;
|
|
|
18
18
|
* </u-group-box>
|
|
19
19
|
* ```
|
|
20
20
|
*
|
|
21
|
-
* 오버라이드: `part`(host·header·title·actions·body) + slot 치환.
|
|
21
|
+
* 오버라이드: `part`(host·header·title·meta·actions·body) + slot 치환.
|
|
22
22
|
* `divider` 속성으로 제목과 본문 사이 구분선을 켠다(기본 꺼짐 — 선이 많으면 화면이 시끄럽다).
|
|
23
23
|
*/
|
|
24
24
|
export declare class GroupBox extends StyledElement<ElementParts> {
|
|
25
25
|
static styles: import('lit').CSSResultGroup[];
|
|
26
26
|
/** 카드 제목. 비우면 헤더 자체를 렌더하지 않는다. */
|
|
27
27
|
title: string;
|
|
28
|
+
/**
|
|
29
|
+
* Secondary text shown after the title — a count, progress or short status
|
|
30
|
+
* (`3 items`, `2/5 done`), drawn one step below the title: body size and weight, weak color.
|
|
31
|
+
*
|
|
32
|
+
* It sits inside the title's heading, so the heading's accessible name reads it too. Not drawn
|
|
33
|
+
* without a `title`: it describes the title.
|
|
34
|
+
*/
|
|
35
|
+
meta?: string;
|
|
28
36
|
/** 제목과 본문 사이에 구분선을 넣는다. */
|
|
29
37
|
divider: boolean;
|
|
30
38
|
/** 본문 여백을 없앤다 — 표를 카드 가장자리까지 붙일 때. */
|
|
@@ -60,6 +68,7 @@ declare module 'react' {
|
|
|
60
68
|
divider?: boolean;
|
|
61
69
|
flush?: boolean;
|
|
62
70
|
level?: GroupBoxLevel;
|
|
71
|
+
meta?: string;
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { slotHasContent as r } from "../internals/slotted.js";
|
|
5
5
|
import { styles as i } from "./GroupBox.styles.js";
|
|
@@ -24,7 +24,7 @@ var d = {
|
|
|
24
24
|
let e = !!this.title || this.hasActions;
|
|
25
25
|
return a`
|
|
26
26
|
<div class="header ${this.divider ? "divider" : ""} ${e ? "" : "empty"}" part="header">
|
|
27
|
-
${l`<${d[this.level] ?? d[3]} class="title" part="title">${this.title}</${d[this.level] ?? d[3]}>`}
|
|
27
|
+
${l`<${d[this.level] ?? d[3]} class="title" part="title">${this.title}${this.title && this.meta ? a` <span class="meta" part="meta">${this.meta}</span>` : ""}</${d[this.level] ?? d[3]}>`}
|
|
28
28
|
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
29
29
|
<slot name="actions"
|
|
30
30
|
@slotchange=${(e) => this.hasActions = r(e.target)}
|
|
@@ -35,7 +35,7 @@ var d = {
|
|
|
35
35
|
`;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
-
t([s({ type: String }), e("design:type", Object)], f.prototype, "title", void 0), t([s({ type: Boolean }), e("design:type", Object)], f.prototype, "divider", void 0), t([s({ type: Boolean }), e("design:type", Object)], f.prototype, "flush", void 0), t([s({
|
|
38
|
+
t([s({ type: String }), e("design:type", Object)], f.prototype, "title", void 0), t([s({ type: String }), e("design:type", String)], f.prototype, "meta", void 0), t([s({ type: Boolean }), e("design:type", Object)], f.prototype, "divider", void 0), t([s({ type: Boolean }), e("design:type", Object)], f.prototype, "flush", void 0), t([s({
|
|
39
39
|
type: Number,
|
|
40
40
|
reflect: !0
|
|
41
41
|
}), e("design:type", Object)], f.prototype, "level", void 0), t([c(), e("design:type", Object)], f.prototype, "hasActions", void 0), f = t([o("u-group-box")], f);
|
|
@@ -42,6 +42,14 @@ var t = e`
|
|
|
42
42
|
letter-spacing: var(--u-text-subtitle-tracking, 0);
|
|
43
43
|
color: var(--u-txt-color, #212121);
|
|
44
44
|
}
|
|
45
|
+
/* 제목 옆 보조 메타(건수·진척) — 제목보다 한 단 아래. 헤딩 안의 인라인이라 기준선을 공유하고,
|
|
46
|
+
접근성 이름에도 함께 읽힌다. 숫자가 바뀌어도 폭이 흔들리지 않게 고정폭 숫자. */
|
|
47
|
+
.meta {
|
|
48
|
+
font-size: var(--u-text-body-size, 14px);
|
|
49
|
+
font-weight: var(--u-text-body-weight, 400);
|
|
50
|
+
color: var(--u-txt-color-weak, #616161);
|
|
51
|
+
font-variant-numeric: tabular-nums;
|
|
52
|
+
}
|
|
45
53
|
|
|
46
54
|
.actions {
|
|
47
55
|
flex: 0 0 auto;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { styles as r } from "./InfoField.styles.js";
|
|
5
5
|
import { html as i } from "lit";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { styles as r } from "./InfoSection.styles.js";
|
|
5
5
|
import { html as i } from "lit";
|
|
@@ -47,7 +47,7 @@ export declare class MasterDetailLayout extends StyledElement<ElementParts> {
|
|
|
47
47
|
*/
|
|
48
48
|
overlayBreakpoint: number;
|
|
49
49
|
/**
|
|
50
|
-
* 언어
|
|
50
|
+
* 언어 태그 — 이 요소만 문서와 다른 언어로 쓸 때. 비우면 `Locale` 의 활성 로케일.
|
|
51
51
|
* 닫기 버튼의 접근성 라벨에만 쓰인다.
|
|
52
52
|
*/
|
|
53
53
|
locale: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { getLocaleStrings as r } from "../internals/locale.js";
|
|
5
5
|
import { slotHasContent as i } from "../internals/slotted.js";
|
|
@@ -33,10 +33,10 @@ export declare class PageHeader extends StyledElement<ElementParts> {
|
|
|
33
33
|
/**
|
|
34
34
|
* 뒤로가기 링크 문구. 비우면 locale 레지스트리 값, 그것도 없으면 **영어**(`Back`).
|
|
35
35
|
* ⚠이 패키지는 범용 층이라 특정 언어를 기본값으로 가질 수 없다 —
|
|
36
|
-
*
|
|
36
|
+
* 한국어 표는 내장돼 있다 — 다른 언어는 `modernAppLocale.register(lang, { back: … })` 로 소비자가 등록한다.
|
|
37
37
|
*/
|
|
38
38
|
backLabel: string;
|
|
39
|
-
/** 언어
|
|
39
|
+
/** 언어 태그 — 이 요소만 문서와 다른 언어로 쓸 때. 비우면 `Locale` 의 활성 로케일. */
|
|
40
40
|
locale: string;
|
|
41
41
|
/**
|
|
42
42
|
* 슬롯 배정 상태. ★CSS 로는 알 수 없다 — `<slot>` 자신이 자식이라 `:has(*)` 가
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { getLocaleStrings as r } from "../internals/locale.js";
|
|
5
5
|
import { slotHasContent as i } from "../internals/slotted.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { DEFAULT_NAV_ICON as r } from "../internals/nav-icon.js";
|
|
5
5
|
import { styles as i } from "./SidebarButton.styles.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { DEFAULT_NAV_ICON as r } from "../internals/nav-icon.js";
|
|
5
5
|
import { SidebarLink as i } from "./SidebarLink.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { DEFAULT_NAV_ICON as r } from "../internals/nav-icon.js";
|
|
5
5
|
import { styles as i } from "./SidebarLink.styles.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { styles as r } from "./SidebarSection.styles.js";
|
|
5
5
|
import { html as i } from "lit";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { StyledElement as n } from "../internals/StyledElement.js";
|
|
4
4
|
import { getLocaleStrings as r } from "../internals/locale.js";
|
|
5
5
|
import { styles as i } from "./Wizard.styles.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export { MasterDetailLayout } from './components/MasterDetailLayout.js';
|
|
|
15
15
|
export { Wizard } from './components/Wizard.js';
|
|
16
16
|
export type { WizardStep, WizardStepState, WizardStepChangeDetail } from './components/Wizard.js';
|
|
17
17
|
export { translate } from './translate.js';
|
|
18
|
-
export { registerLocale, setDefaultLocale, getLocaleStrings, getDefaultLocale, } from './internals/locale.js';
|
|
19
|
-
export type { ModernAppLocaleStrings } from './internals/locale.js';
|
|
18
|
+
export { modernAppLocale, registerLocale, setDefaultLocale, getLocaleStrings, getDefaultLocale, } from './internals/locale.js';
|
|
19
|
+
export type { ModernAppLocaleStrings, ModernAppMessageKey } from './internals/locale.js';
|
|
20
20
|
export { ScreenObserver } from './internals/ScreenObserver.js';
|
|
21
21
|
export type { ScreenSize, ScreenObserverConfig, ScreenResizeEvent } from './internals/ScreenObserver.js';
|
|
22
22
|
export { app };
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ScreenObserver as e } from "./internals/ScreenObserver.js";
|
|
2
2
|
import { app as t } from "./App.js";
|
|
3
3
|
import { filterSidebarItems as n } from "./layouts/filterSidebarItems.js";
|
|
4
|
-
import { getDefaultLocale as r, getLocaleStrings as i,
|
|
5
|
-
import { PageHeader as
|
|
6
|
-
import { GroupBox as
|
|
7
|
-
import { InfoSection as
|
|
8
|
-
import { InfoField as
|
|
9
|
-
import { EmptyState as
|
|
10
|
-
import { ActionBar as
|
|
11
|
-
import { MasterDetailLayout as
|
|
12
|
-
import { Wizard as
|
|
13
|
-
import { translate as
|
|
4
|
+
import { getDefaultLocale as r, getLocaleStrings as i, modernAppLocale as a, registerLocale as o, setDefaultLocale as s } from "./internals/locale.js";
|
|
5
|
+
import { PageHeader as c } from "./components/PageHeader.js";
|
|
6
|
+
import { GroupBox as l } from "./components/GroupBox.js";
|
|
7
|
+
import { InfoSection as u } from "./components/InfoSection.js";
|
|
8
|
+
import { InfoField as d, isBlank as f } from "./components/InfoField.js";
|
|
9
|
+
import { EmptyState as p } from "./components/EmptyState.js";
|
|
10
|
+
import { ActionBar as m } from "./components/ActionBar.js";
|
|
11
|
+
import { MasterDetailLayout as h } from "./components/MasterDetailLayout.js";
|
|
12
|
+
import { Wizard as g } from "./components/Wizard.js";
|
|
13
|
+
import { translate as _ } from "./translate.js";
|
|
14
14
|
//#region src/index.ts
|
|
15
|
-
var
|
|
15
|
+
var v = t;
|
|
16
16
|
//#endregion
|
|
17
|
-
export {
|
|
17
|
+
export { m as ActionBar, p as EmptyState, l as GroupBox, d as InfoField, u as InfoSection, h as MasterDetailLayout, c as PageHeader, e as ScreenObserver, g as Wizard, t as app, v as default, n as filterSidebarItems, r as getDefaultLocale, i as getLocaleStrings, f as isBlank, a as modernAppLocale, o as registerLocale, s as setDefaultLocale, _ as translate };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import t from "../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import e from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
3
3
|
import { property as n } from "lit/decorators.js";
|
|
4
4
|
import { UElement as r } from "@iyulab/components/dist/components/UElement.js";
|
|
5
5
|
//#region src/internals/StyledElement.ts
|
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight locale registry for modern-app chrome strings.
|
|
3
|
-
*
|
|
4
|
-
* Scope: library-internal chrome strings only (empty-state copy, back label).
|
|
5
|
-
* NOT a general i18n framework — the app's own content is the app's business.
|
|
6
|
-
*
|
|
7
|
-
* ★**English is the built-in default.** This package sits in the *generic* layer
|
|
8
|
-
* (see the three-layer split: `components` = neutral primitives, `modern-app` =
|
|
9
|
-
* what a modern app usually provides, `enterprise` = iyulab house style).
|
|
10
|
-
* A generic layer that ships Korean defaults excludes every non-Korean consumer —
|
|
11
|
-
* the same objection this repo raised against baking a house aesthetic into
|
|
12
|
-
* `components`. Language excludes harder than aesthetics: an odd-looking default
|
|
13
|
-
* is awkward, an unreadable one is unusable.
|
|
14
|
-
*
|
|
15
|
-
* Mirrors the registry already established in `u-widgets` — one pattern, not two.
|
|
16
|
-
*
|
|
17
|
-
* registerLocale('ko', { back: '뒤로', noDataTitle: '아직 등록된 항목이 없습니다' });
|
|
18
|
-
* setDefaultLocale('ko');
|
|
19
|
-
*/
|
|
20
1
|
export interface ModernAppLocaleStrings {
|
|
21
2
|
/** Back button label in the page header. */
|
|
22
3
|
back: string;
|
|
@@ -39,18 +20,26 @@ export interface ModernAppLocaleStrings {
|
|
|
39
20
|
wizardStepAnnouncement: (index: number, total: number, label: string) => string;
|
|
40
21
|
}
|
|
41
22
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
23
|
+
* Keys of the `modern-app` namespace. All strings — `wizardStepAnnouncement` is a template with
|
|
24
|
+
* `{index}`, `{total}` and `{label}` placeholders (`'Step {index} of {total}: {label}'`).
|
|
25
|
+
*/
|
|
26
|
+
export type ModernAppMessageKey = keyof ModernAppLocaleStrings;
|
|
27
|
+
/** The `modern-app` chrome-string namespace. Register translations here; pick the language with `Locale.set()`. */
|
|
28
|
+
export declare const modernAppLocale: import('@iyulab/components/dist/utilities/Locale.js').LocaleNamespace<keyof ModernAppLocaleStrings>;
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated Register with `modernAppLocale.register(lang, strings)` and choose the language with
|
|
31
|
+
* `Locale.set()`. This forwards to the namespace; a function-valued `wizardStepAnnouncement` keeps
|
|
32
|
+
* working (the namespace form is a `{index}`/`{total}`/`{label}` template).
|
|
44
33
|
*/
|
|
45
34
|
export declare function registerLocale(lang: string, strings: Partial<ModernAppLocaleStrings>): void;
|
|
46
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated Choose the language with `Locale.set()` of `@iyulab/components` — this package now
|
|
37
|
+
* follows it. When called, this still takes precedence over `Locale` for elements without their
|
|
38
|
+
* own `locale`; `setDefaultLocale(undefined)` hands the choice back to `Locale`.
|
|
39
|
+
*/
|
|
47
40
|
export declare function setDefaultLocale(lang: string | undefined): void;
|
|
48
41
|
/**
|
|
49
|
-
* Resolve
|
|
50
|
-
*
|
|
51
|
-
* Order: exact match (`ko-KR`) → base language (`ko`) → English.
|
|
52
|
-
* ⚠The base-language step matters: consumers register `ko` but browsers report
|
|
53
|
-
* `ko-KR`, and without it every registration would silently miss.
|
|
42
|
+
* Resolve every chrome string for a language tag (empty → `setDefaultLocale` → active `Locale`).
|
|
54
43
|
*/
|
|
55
44
|
export declare function getLocaleStrings(lang?: string): ModernAppLocaleStrings;
|
|
56
45
|
/** The English defaults — for tests and reference. */
|
package/dist/internals/locale.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { Locale as e } from "@iyulab/components/dist/utilities/Locale.js";
|
|
1
2
|
//#region src/internals/locale.ts
|
|
2
|
-
var
|
|
3
|
+
var t = {
|
|
3
4
|
back: "Back",
|
|
4
5
|
noDataTitle: "Nothing here yet",
|
|
5
6
|
noDataDescription: "",
|
|
@@ -10,26 +11,65 @@ var e = {
|
|
|
10
11
|
toggleSidebar: "Toggle sidebar",
|
|
11
12
|
wizardBack: "Back",
|
|
12
13
|
wizardNext: "Next",
|
|
13
|
-
wizardStepAnnouncement:
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
wizardStepAnnouncement: "Step {index} of {total}: {label}"
|
|
15
|
+
}, n = e.namespace("modern-app");
|
|
16
|
+
n.register("en", t), n.register("ko", {
|
|
17
|
+
back: "뒤로",
|
|
18
|
+
noDataTitle: "아직 항목이 없습니다",
|
|
19
|
+
noDataDescription: "",
|
|
20
|
+
noResultsTitle: "일치하는 결과가 없습니다",
|
|
21
|
+
noResultsDescription: "검색어나 필터를 바꿔 보세요.",
|
|
22
|
+
detailClose: "닫기",
|
|
23
|
+
toggleMobileMenu: "메뉴 열고 닫기",
|
|
24
|
+
toggleSidebar: "사이드바 열고 닫기",
|
|
25
|
+
wizardBack: "이전",
|
|
26
|
+
wizardNext: "다음",
|
|
27
|
+
wizardStepAnnouncement: "{total}단계 중 {index}단계: {label}"
|
|
28
|
+
});
|
|
29
|
+
var r, i = /* @__PURE__ */ new Map(), a = "\0modern-app:announcer:";
|
|
30
|
+
function o(e, t) {
|
|
31
|
+
let { wizardStepAnnouncement: r, ...o } = t, s = { ...o };
|
|
32
|
+
if (r) {
|
|
33
|
+
let t = e.toLowerCase();
|
|
34
|
+
i.set(t, r), s.wizardStepAnnouncement = a + t;
|
|
35
|
+
}
|
|
36
|
+
n.register(e, s);
|
|
37
|
+
}
|
|
38
|
+
function s(e) {
|
|
39
|
+
r = e;
|
|
20
40
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
41
|
+
function c(e, t, i) {
|
|
42
|
+
let a = n.textIn(e || r, t, i);
|
|
43
|
+
return a === t ? "" : a;
|
|
23
44
|
}
|
|
24
|
-
function
|
|
25
|
-
let
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
function l(e) {
|
|
46
|
+
let t = (t) => c(e, t);
|
|
47
|
+
return {
|
|
48
|
+
back: t("back"),
|
|
49
|
+
noDataTitle: t("noDataTitle"),
|
|
50
|
+
noDataDescription: t("noDataDescription"),
|
|
51
|
+
noResultsTitle: t("noResultsTitle"),
|
|
52
|
+
noResultsDescription: t("noResultsDescription"),
|
|
53
|
+
detailClose: t("detailClose"),
|
|
54
|
+
toggleMobileMenu: t("toggleMobileMenu"),
|
|
55
|
+
toggleSidebar: t("toggleSidebar"),
|
|
56
|
+
wizardBack: t("wizardBack"),
|
|
57
|
+
wizardNext: t("wizardNext"),
|
|
58
|
+
wizardStepAnnouncement: (t, n, r) => {
|
|
59
|
+
let o = c(e, "wizardStepAnnouncement", {
|
|
60
|
+
index: t,
|
|
61
|
+
total: n,
|
|
62
|
+
label: r
|
|
63
|
+
});
|
|
64
|
+
return o.startsWith(a) ? i.get(o.slice(22))(t, n, r) : o;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
30
67
|
}
|
|
31
|
-
function
|
|
32
|
-
return {
|
|
68
|
+
function u() {
|
|
69
|
+
return {
|
|
70
|
+
...t,
|
|
71
|
+
wizardStepAnnouncement: (e, t, n) => `Step ${e} of ${t}: ${n}`
|
|
72
|
+
};
|
|
33
73
|
}
|
|
34
74
|
//#endregion
|
|
35
|
-
export {
|
|
75
|
+
export { u as getDefaultLocale, l as getLocaleStrings, n as modernAppLocale, o as registerLocale, s as setDefaultLocale };
|
|
@@ -9,7 +9,7 @@ export declare class SidebarLayout extends StyledElement<SidebarParts> {
|
|
|
9
9
|
state: SidebarState;
|
|
10
10
|
/** 사이드바 레이아웃 설정 */
|
|
11
11
|
config?: SidebarLayoutConfig;
|
|
12
|
-
/** 크롬 문자열(토글 버튼 접근성 라벨 등) 로케일 — `
|
|
12
|
+
/** 크롬 문자열(토글 버튼 접근성 라벨 등) 로케일 — 이 요소만 다른 언어로 쓸 때. 비우면 `Locale` 의 활성 로케일 */
|
|
13
13
|
locale: string;
|
|
14
14
|
progressBarEl: UProgressBar;
|
|
15
15
|
/** overlay 슬롯 배정 상태 — CSS `:has()`로는 알 수 없다(`internals/slotted.ts` 참조). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { app as e } from "../App.js";
|
|
2
2
|
import { filterSidebarItems as t } from "./filterSidebarItems.js";
|
|
3
|
-
import n from "../_virtual/_@oxc-project_runtime@0.
|
|
4
|
-
import r from "../_virtual/_@oxc-project_runtime@0.
|
|
3
|
+
import n from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
|
|
4
|
+
import r from "../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
|
|
5
5
|
import { StyledElement as i } from "../internals/StyledElement.js";
|
|
6
6
|
import { getLocaleStrings as a } from "../internals/locale.js";
|
|
7
7
|
import { slotHasContent as o } from "../internals/slotted.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/modern-app",
|
|
3
3
|
"description": "web-framework by iyulab based on lit-element",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.27.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"web-framework",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"lit": "^3.3.3"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@iyulab/components": ">=1.
|
|
67
|
+
"@iyulab/components": ">=1.45.0",
|
|
68
68
|
"@lit/react": ">=1.0.8",
|
|
69
69
|
"react": ">=18.0.0"
|
|
70
70
|
},
|
|
@@ -141,6 +141,33 @@ html`<p>${translate('namespace::greeting')}</p>`;
|
|
|
141
141
|
// layout: { main: [{ type: 'link', label: translate('nav::home'), href: '/' }] }
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
### Built-in strings (`modernAppLocale`)
|
|
145
|
+
|
|
146
|
+
The package's own strings — the page header's back link, empty-state copy, the shell's toggle and
|
|
147
|
+
close labels, the wizard's buttons and step announcement — live in the `modern-app` namespace of
|
|
148
|
+
`@iyulab/components`' `Locale`. English and Korean are built in, English being the default; pick the
|
|
149
|
+
language once, with `Locale.set()` — the primitives and `@iyulab/flex-table` follow the same call.
|
|
150
|
+
Register other languages, or your own wording, in the same namespace:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { Locale } from '@iyulab/components';
|
|
154
|
+
import { modernAppLocale } from '@iyulab/modern-app';
|
|
155
|
+
|
|
156
|
+
Locale.set('ko'); // built-in Korean — nothing to register
|
|
157
|
+
|
|
158
|
+
modernAppLocale.register('ja', {
|
|
159
|
+
back: '戻る',
|
|
160
|
+
toggleSidebar: 'サイドバーの切り替え',
|
|
161
|
+
wizardStepAnnouncement: 'ステップ {index}/{total}: {label}',
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
A partial table is enough — untranslated keys fall back to English, and a registration for a
|
|
166
|
+
built-in language overrides only the keys it gives. An element's own `locale`
|
|
167
|
+
attribute overrides the active language for that element. `registerLocale`/`setDefaultLocale` still
|
|
168
|
+
work but are deprecated: a `setDefaultLocale()` call takes precedence over `Locale` until it is
|
|
169
|
+
called with `undefined`.
|
|
170
|
+
|
|
144
171
|
---
|
|
145
172
|
|
|
146
173
|
## Sidebar Layout
|
|
@@ -54,5 +54,6 @@ for both and a user with a filter still applied reads it as *"my data disappeare
|
|
|
54
54
|
| `--u-space-lg` | Actions row top spacing |
|
|
55
55
|
| `--u-space-sm` | Gap between actions |
|
|
56
56
|
|
|
57
|
-
⚠ Default wording is **English
|
|
57
|
+
⚠ Default wording is **English**, with Korean built in — choose the language with `Locale.set()` of
|
|
58
|
+
`@iyulab/components`, register others with `modernAppLocale.register(lang, …)`, or pass
|
|
58
59
|
`title`/`description` per screen.
|
|
@@ -9,7 +9,7 @@ trailing actions*, and assembling that by hand is how title sizes, padding, and
|
|
|
9
9
|
up different on every screen.
|
|
10
10
|
|
|
11
11
|
```html
|
|
12
|
-
<u-group-box title="Receivables">
|
|
12
|
+
<u-group-box title="Receivables" meta="3 items">
|
|
13
13
|
<a slot="actions" href="/receivables">Payments</a>
|
|
14
14
|
…body…
|
|
15
15
|
</u-group-box>
|
|
@@ -30,6 +30,7 @@ a left edge without any consumer CSS.
|
|
|
30
30
|
| Property | Type | Default | Reflect | Description |
|
|
31
31
|
|----------|------|---------|---------|-------------|
|
|
32
32
|
| `title` | `string` | `''` | | Header title |
|
|
33
|
+
| `meta` | `string` | — | | Secondary text after the title — a count, progress or short status (`3 items`, `2/5 done`), one step below the title: body size and weight, weak color, tabular figures. It sits inside the heading, so the heading's accessible name includes it. Not drawn without `title` |
|
|
33
34
|
| `divider` | `boolean` | `false` | | Rule between header and body. Off by default — many rules make a screen noisy |
|
|
34
35
|
| `flush` | `boolean` | `false` | | Remove body padding, for tables and lists that draw their own edges |
|
|
35
36
|
| `level` | `2|3|4|5|6` | `3` | ✓ | Heading level of the title in the document outline. Set `2` for a box directly under `u-page-header` (the page's `h1`), so the outline does not skip a level. Semantics only — the title looks the same at every level |
|
|
@@ -39,6 +40,7 @@ a left edge without any consumer CSS.
|
|
|
39
40
|
| Part | Description |
|
|
40
41
|
|------|-------------|
|
|
41
42
|
| `header` · `title` · `actions` | Header row |
|
|
43
|
+
| `meta` | Secondary text inside the title |
|
|
42
44
|
| `body` | Body wrapper |
|
|
43
45
|
|
|
44
46
|
## CSS Custom Properties
|
|
@@ -49,6 +51,7 @@ a left edge without any consumer CSS.
|
|
|
49
51
|
| `--u-text-subtitle-weight` | Title font weight |
|
|
50
52
|
| `--u-text-subtitle-leading` | Title line height |
|
|
51
53
|
| `--u-text-subtitle-tracking` | Title letter spacing |
|
|
54
|
+
| `--u-text-body-size` / `--u-text-body-weight` / `--u-txt-color-weak` | `meta` size, weight and color |
|
|
52
55
|
| `--u-bg-color-raised` | Surface background |
|
|
53
56
|
| `--u-border-color-weak` | Border and header divider color |
|
|
54
57
|
| `--u-radius-2xl` | Corner radius |
|
|
@@ -73,6 +73,10 @@ stay level:
|
|
|
73
73
|
blank="No downtime recorded for the failures"></u-info-field>
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
`tone` colors a blank value too, so a reason that needs attention takes `tone="negative"`. Set it
|
|
77
|
+
conditionally (`tone=${mttr == null ? 'negative' : undefined}`) — otherwise the value is toned
|
|
78
|
+
as well once it exists.
|
|
79
|
+
|
|
76
80
|
## CSS Parts
|
|
77
81
|
|
|
78
82
|
| Part | Description |
|
|
@@ -58,5 +58,5 @@ screens nobody opens.
|
|
|
58
58
|
| `--u-space-2xs` | Title-to-subtitle spacing |
|
|
59
59
|
| `--u-space-3xs` | Back-arrow-to-label spacing |
|
|
60
60
|
|
|
61
|
-
⚠ Built-in strings default to **English
|
|
62
|
-
|
|
61
|
+
⚠ Built-in strings default to **English**, with Korean built in — choose the language with
|
|
62
|
+
`Locale.set()` of `@iyulab/components`. Register others with `modernAppLocale.register(lang, { back: … })`.
|