@iyulab/modern-app 0.40.0 → 0.41.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 +23 -0
- package/dist/components/GroupBox.d.ts +10 -6
- package/dist/components/GroupBox.js +18 -7
- package/dist/internals/locale.d.ts +3 -0
- package/dist/internals/locale.js +3 -0
- package/dist/layouts/SidebarLayout.d.ts +5 -0
- package/dist/layouts/SidebarLayout.js +8 -6
- package/dist/layouts/SidebarLayout.styles.js +1 -1
- package/package.json +1 -1
- package/skills/modern-app/references/components/group-box.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.41.1] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
### Documentation
|
|
6
|
+
|
|
7
|
+
- The `level` row of the `u-group-box` reference had unescaped `|` in its type cell, which split the row into extra
|
|
8
|
+
columns and put a stale `3` in the default column — the level is derived when unset.
|
|
9
|
+
|
|
10
|
+
## [0.41.0] - 2026-10-07
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **`u-group-box` derives its heading level when `level` is unset** — `h2` for a box in no other `u-group-box`
|
|
15
|
+
(the usual place, directly under `u-page-header`'s `h1`), one level deeper than the nearest enclosing box otherwise
|
|
16
|
+
(shadow roots included, capped at `h6`). The default was `h3`, so the most common composition skipped a heading
|
|
17
|
+
level on every screen (axe `heading-order`). An explicit `level` still wins; an out-of-range one now falls back to
|
|
18
|
+
the derived level instead of `3`. A box under a heading of your own should set `level`.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **The sidebar layout's route-loading bar is out of the accessibility tree while idle, and named while it loads**
|
|
23
|
+
(new locale key `pageLoading` — en *Loading page*, ko *페이지 불러오는 중*). It was hidden with `opacity` only, so
|
|
24
|
+
every screen carried an unnamed progress bar for screen readers to meet (axe `aria-progressbar-name`).
|
|
25
|
+
|
|
3
26
|
## [0.40.0] - 2026-10-07
|
|
4
27
|
|
|
5
28
|
### Changed
|
|
@@ -43,14 +43,18 @@ export declare class GroupBox extends StyledElement<ElementParts> {
|
|
|
43
43
|
/** 본문 여백을 없앤다 — 표를 카드 가장자리까지 붙일 때. */
|
|
44
44
|
flush: boolean;
|
|
45
45
|
/**
|
|
46
|
-
* Heading level of the title in the document outline (`2`–`6
|
|
46
|
+
* Heading level of the title in the document outline (`2`–`6`).
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
48
|
+
* Unset, it follows the boxes around it: `2` for a box that sits in no other `u-group-box` — the
|
|
49
|
+
* usual place, directly under `u-page-header` (the page's `h1`) — and one deeper than the nearest
|
|
50
|
+
* enclosing box otherwise (shadow roots included), capped at `6`. Set it when the box sits under a
|
|
51
|
+
* heading of your own (a box under your `h2` section is `3`). This changes semantics only: the title
|
|
52
|
+
* keeps its visual size at every level. Out-of-range values fall back to the derived level.
|
|
52
53
|
*/
|
|
53
|
-
level
|
|
54
|
+
level?: GroupBoxLevel;
|
|
55
|
+
/** The level the title renders at — `level`, or the one derived from enclosing boxes. */
|
|
56
|
+
get headingLevel(): GroupBoxLevel;
|
|
57
|
+
connectedCallback(): void;
|
|
54
58
|
/**
|
|
55
59
|
* 액션 슬롯 배정 상태.
|
|
56
60
|
* ★종전에는 'render()' 안에서 'this.querySelector()' 로 라이트 DOM 을 읽었다. 그것은
|
|
@@ -7,25 +7,36 @@ import { html as a, nothing as o } from "lit";
|
|
|
7
7
|
import { customElement as s, property as c, state as l } from "lit/decorators.js";
|
|
8
8
|
import { html as u, literal as d } from "lit/static-html.js";
|
|
9
9
|
//#region src/components/GroupBox.ts
|
|
10
|
-
var f = {
|
|
10
|
+
var f, p = {
|
|
11
11
|
2: d`h2`,
|
|
12
12
|
3: d`h3`,
|
|
13
13
|
4: d`h4`,
|
|
14
14
|
5: d`h5`,
|
|
15
15
|
6: d`h6`
|
|
16
|
-
},
|
|
16
|
+
}, m = class extends n {
|
|
17
|
+
static {
|
|
18
|
+
f = this;
|
|
19
|
+
}
|
|
17
20
|
constructor(...e) {
|
|
18
|
-
super(...e), this.title = "", this.divider = !1, this.flush = !1, this.
|
|
21
|
+
super(...e), this.title = "", this.divider = !1, this.flush = !1, this.hasActions = !1;
|
|
19
22
|
}
|
|
20
23
|
static {
|
|
21
24
|
this.styles = [super.styles, i];
|
|
22
25
|
}
|
|
26
|
+
get headingLevel() {
|
|
27
|
+
if (this.level && p[this.level]) return this.level;
|
|
28
|
+
for (let e = this.parentNode; e; e = e instanceof ShadowRoot ? e.host : e.parentNode) if (e instanceof f) return Math.min(6, e.headingLevel + 1);
|
|
29
|
+
return 2;
|
|
30
|
+
}
|
|
31
|
+
connectedCallback() {
|
|
32
|
+
super.connectedCallback(), this.requestUpdate();
|
|
33
|
+
}
|
|
23
34
|
render() {
|
|
24
35
|
let e = !!this.title || !!this.description || this.hasActions;
|
|
25
36
|
return a`
|
|
26
37
|
<div class="header ${this.divider ? "divider" : ""} ${e ? "" : "empty"}" part="header">
|
|
27
38
|
<div class="titles">
|
|
28
|
-
${u`<${
|
|
39
|
+
${u`<${p[this.headingLevel]} class="title" part="title">${this.title}${this.title && this.meta ? a` <span class="meta" part="meta">${this.meta}</span>` : ""}</${p[this.headingLevel]}>`}
|
|
29
40
|
${this.description ? a`<p class="description" part="description">${this.description}</p>` : o}
|
|
30
41
|
</div>
|
|
31
42
|
<div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
|
|
@@ -38,9 +49,9 @@ var f = {
|
|
|
38
49
|
`;
|
|
39
50
|
}
|
|
40
51
|
};
|
|
41
|
-
t([c({ type: String }), e("design:type", Object)],
|
|
52
|
+
t([c({ type: String }), e("design:type", Object)], m.prototype, "title", void 0), t([c({ type: String }), e("design:type", String)], m.prototype, "meta", void 0), t([c({ type: String }), e("design:type", String)], m.prototype, "description", void 0), t([c({ type: Boolean }), e("design:type", Object)], m.prototype, "divider", void 0), t([c({ type: Boolean }), e("design:type", Object)], m.prototype, "flush", void 0), t([c({
|
|
42
53
|
type: Number,
|
|
43
54
|
reflect: !0
|
|
44
|
-
}), e("design:type", Object)],
|
|
55
|
+
}), e("design:type", Object)], m.prototype, "level", void 0), t([l(), e("design:type", Object)], m.prototype, "hasActions", void 0), m = f = t([s("u-group-box")], m);
|
|
45
56
|
//#endregion
|
|
46
|
-
export {
|
|
57
|
+
export { m as GroupBox };
|
|
@@ -17,6 +17,9 @@ export interface ModernAppLocaleStrings {
|
|
|
17
17
|
skipToContent: string;
|
|
18
18
|
/** Sidebar links with `target: '_blank'` — appended to the link's accessible name (visually hidden). */
|
|
19
19
|
opensInNewTab: string;
|
|
20
|
+
/** Sidebar layout — accessible name of the route-loading bar at the top of the content (it is hidden from
|
|
21
|
+
* assistive technology while idle). */
|
|
22
|
+
pageLoading: string;
|
|
20
23
|
/** Wizard — default Back/Next action labels ("Submit" wording is the consumer's call). */
|
|
21
24
|
wizardBack: string;
|
|
22
25
|
wizardNext: string;
|
package/dist/internals/locale.js
CHANGED
|
@@ -11,6 +11,7 @@ var t = {
|
|
|
11
11
|
toggleSidebar: "Toggle sidebar",
|
|
12
12
|
skipToContent: "Skip to main content",
|
|
13
13
|
opensInNewTab: "(opens in a new tab)",
|
|
14
|
+
pageLoading: "Loading page",
|
|
14
15
|
wizardBack: "Back",
|
|
15
16
|
wizardNext: "Next",
|
|
16
17
|
wizardStepAnnouncement: "Step {index} of {total}: {label}"
|
|
@@ -26,6 +27,7 @@ n.register("en", t), n.register("ko", {
|
|
|
26
27
|
toggleSidebar: "사이드바 열고 닫기",
|
|
27
28
|
skipToContent: "본문으로 건너뛰기",
|
|
28
29
|
opensInNewTab: "(새 창에서 열림)",
|
|
30
|
+
pageLoading: "페이지 불러오는 중",
|
|
29
31
|
wizardBack: "이전",
|
|
30
32
|
wizardNext: "다음",
|
|
31
33
|
wizardStepAnnouncement: "{total}단계 중 {index}단계: {label}"
|
|
@@ -59,6 +61,7 @@ function l(e) {
|
|
|
59
61
|
toggleSidebar: t("toggleSidebar"),
|
|
60
62
|
skipToContent: t("skipToContent"),
|
|
61
63
|
opensInNewTab: t("opensInNewTab"),
|
|
64
|
+
pageLoading: t("pageLoading"),
|
|
62
65
|
wizardBack: t("wizardBack"),
|
|
63
66
|
wizardNext: t("wizardNext"),
|
|
64
67
|
wizardStepAnnouncement: (t, n, r) => {
|
|
@@ -25,6 +25,11 @@ export declare class SidebarLayout extends StyledElement<SidebarParts> {
|
|
|
25
25
|
private static menuSeq;
|
|
26
26
|
/** notice 슬롯 배정 상태 — 비었으면 스택 자체가 자리를 차지하지 않는다. */
|
|
27
27
|
private hasNotice;
|
|
28
|
+
/**
|
|
29
|
+
* 라우트가 불러오는 중인가 — 본문 위 진행 막대를 보이고, 쉬는 동안은 보조기기에서도 뺀다. 종전에는 `opacity: 0` 으로만
|
|
30
|
+
* 숨어 이름 없는 진행 막대가 모든 화면의 접근성 트리에 떠 있었다(axe `aria-progressbar-name`).
|
|
31
|
+
*/
|
|
32
|
+
private routeLoading;
|
|
28
33
|
/**
|
|
29
34
|
* 오버레이를 연 컨트롤 — 닫힐 때 포커스를 되돌릴 곳.
|
|
30
35
|
* ★슬롯 배정 «시점» 에 잡는다. 렌더가 본문에 `inert` 를 걸면 그 컨트롤이 쥐던 포커스는
|
|
@@ -79,18 +79,18 @@ var N = class extends i {
|
|
|
79
79
|
C = this;
|
|
80
80
|
}
|
|
81
81
|
constructor(...t) {
|
|
82
|
-
super(...t), this.state = "default", this.counts = {}, this.locale = "", this.hasOverlay = !1, this.openMenu = null, this.menuIds = /* @__PURE__ */ new WeakMap(), this.hasNotice = !1, this.overlayTrigger = null, this.internals = typeof this.attachInternals == "function" ? this.attachInternals() : void 0, this.currentPath = null, this.unsizedWarnKey = `unsized:${++T}`, this.isMatchedLink = (e) => this.currentPath === null || !e ? !1 : (e = typeof e == "string" ? new URLPattern(e, window.location.origin) : e, e.test(this.currentPath, window.location.origin)), this.handleToggleButtonClick = () => {
|
|
82
|
+
super(...t), this.state = "default", this.counts = {}, this.locale = "", this.hasOverlay = !1, this.openMenu = null, this.menuIds = /* @__PURE__ */ new WeakMap(), this.hasNotice = !1, this.routeLoading = !1, this.overlayTrigger = null, this.internals = typeof this.attachInternals == "function" ? this.attachInternals() : void 0, this.currentPath = null, this.unsizedWarnKey = `unsized:${++T}`, this.isMatchedLink = (e) => this.currentPath === null || !e ? !1 : (e = typeof e == "string" ? new URLPattern(e, window.location.origin) : e, e.test(this.currentPath, window.location.origin)), this.handleToggleButtonClick = () => {
|
|
83
83
|
let t = this.screenSize ?? e.screen ?? "large";
|
|
84
84
|
t === "large" ? this.state = this.state === "default" ? "slim" : "default" : t === "medium" ? this.state = this.state === "slim" ? "modal" : "slim" : t === "small" ? this.state = this.state === "mobile" ? "mobile-open" : "mobile" : console.warn("Unknown screen size:", t);
|
|
85
85
|
}, this.handleBackdropClick = () => {
|
|
86
86
|
this.state = "slim";
|
|
87
87
|
}, this.handleRouteBegin = (e) => {
|
|
88
|
-
this.
|
|
88
|
+
this.routeLoading = !0, this.progressBarEl.value = 0, this.state === "modal" && (this.state = "slim"), this.state === "mobile-open" && (this.state = "mobile"), this.currentPath = e.context.path;
|
|
89
89
|
}, this.handleRouteProgress = (e) => {
|
|
90
90
|
this.progressBarEl.value = e.progress;
|
|
91
91
|
}, this.handleRouteDone = (e) => {
|
|
92
92
|
this.progressBarEl.value = 100, setTimeout(() => {
|
|
93
|
-
this.
|
|
93
|
+
this.routeLoading = !1;
|
|
94
94
|
}, 300);
|
|
95
95
|
let t = this.shadowRoot?.querySelector(".main");
|
|
96
96
|
t && (this.config?.scrollBehavior?.(e.context, t), this.focusRoute(t));
|
|
@@ -100,7 +100,7 @@ var N = class extends i {
|
|
|
100
100
|
t && this.focusContentStart(this.hasOverlay ? [] : this.routeContent(), t);
|
|
101
101
|
}, this.handleRouteError = (e) => {
|
|
102
102
|
this.progressBarEl.status = "error", this.progressBarEl.value = 100, setTimeout(() => {
|
|
103
|
-
this.
|
|
103
|
+
this.routeLoading = !1, this.progressBarEl.status = "default";
|
|
104
104
|
}, 300);
|
|
105
105
|
}, this.handleOverlaySlotChange = (e) => {
|
|
106
106
|
let t = o(e.target);
|
|
@@ -238,7 +238,9 @@ var N = class extends i {
|
|
|
238
238
|
<!-- Main Content -->
|
|
239
239
|
<div class="main-region">
|
|
240
240
|
<main class="main" part="main" scrollable tabindex="-1" @keydown=${this._handleMainKeydown}>
|
|
241
|
-
<u-progress-bar part="progress"
|
|
241
|
+
<u-progress-bar part="progress" class=${this.routeLoading ? "loading" : ""}
|
|
242
|
+
aria-hidden=${this.routeLoading ? d : "true"}
|
|
243
|
+
aria-label=${a(this.locale || void 0).pageLoading}></u-progress-bar>
|
|
242
244
|
|
|
243
245
|
<div class="main-content" part="main-content" ?inert=${this.hasOverlay}>
|
|
244
246
|
<div class="notices ${this.hasNotice ? "" : "empty"}" part="notices"
|
|
@@ -442,6 +444,6 @@ var N = class extends i {
|
|
|
442
444
|
r([p({
|
|
443
445
|
type: String,
|
|
444
446
|
reflect: !0
|
|
445
|
-
}), n("design:type", Object)], N.prototype, "state", void 0), r([p({ type: Object }), n("design:type", Object)], N.prototype, "config", void 0), r([p({ type: Object }), n("design:type", typeof Record > "u" ? Object : Record)], N.prototype, "counts", void 0), r([p({ type: String }), n("design:type", Object)], N.prototype, "locale", void 0), r([m("u-progress-bar"), n("design:type", S === void 0 ? Object : S)], N.prototype, "progressBarEl", void 0), r([h(), n("design:type", Object)], N.prototype, "hasOverlay", void 0), r([h(), n("design:type", Object)], N.prototype, "openMenu", void 0), r([h(), n("design:type", Object)], N.prototype, "hasNotice", void 0), r([h(), n("design:type", Object)], N.prototype, "currentPath", void 0), N = C = r([f("u-sidebar-layout")], N);
|
|
447
|
+
}), n("design:type", Object)], N.prototype, "state", void 0), r([p({ type: Object }), n("design:type", Object)], N.prototype, "config", void 0), r([p({ type: Object }), n("design:type", typeof Record > "u" ? Object : Record)], N.prototype, "counts", void 0), r([p({ type: String }), n("design:type", Object)], N.prototype, "locale", void 0), r([m("u-progress-bar"), n("design:type", S === void 0 ? Object : S)], N.prototype, "progressBarEl", void 0), r([h(), n("design:type", Object)], N.prototype, "hasOverlay", void 0), r([h(), n("design:type", Object)], N.prototype, "openMenu", void 0), r([h(), n("design:type", Object)], N.prototype, "hasNotice", void 0), r([h(), n("design:type", Object)], N.prototype, "routeLoading", void 0), r([h(), n("design:type", Object)], N.prototype, "currentPath", void 0), N = C = r([f("u-sidebar-layout")], N);
|
|
446
448
|
//#endregion
|
|
447
449
|
export { N as SidebarLayout };
|
|
@@ -359,7 +359,7 @@ var t = e`
|
|
|
359
359
|
transition: opacity var(--u-duration-slow, 320ms) ease, transform var(--u-duration-slow, 320ms) ease;
|
|
360
360
|
pointer-events: none;
|
|
361
361
|
}
|
|
362
|
-
.main u-progress-bar
|
|
362
|
+
.main u-progress-bar.loading {
|
|
363
363
|
opacity: 1;
|
|
364
364
|
transform: translateY(0);
|
|
365
365
|
}
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@ a left edge without any consumer CSS.
|
|
|
34
34
|
| `description` | `string` | — | | One line under the title — what the box holds or what its numbers are based on. Caption size, weak color. Opens the header on its own |
|
|
35
35
|
| `divider` | `boolean` | `false` | | Rule between header and body. Off by default — many rules make a screen noisy |
|
|
36
36
|
| `flush` | `boolean` | `false` | | Remove body padding, for tables and lists that draw their own edges |
|
|
37
|
-
| `level` | `2
|
|
37
|
+
| `level` | `2\|3\|4\|5\|6` | — | ✓ | Heading level of the title in the document outline. Unset: `2` for a box in no other `u-group-box` (directly under `u-page-header`, the page's `h1`), one deeper than the nearest enclosing box otherwise. Set it when the box sits under a heading of your own. Semantics only — the title looks the same at every level |
|
|
38
38
|
|
|
39
39
|
## CSS Parts
|
|
40
40
|
|