@iyulab/modern-app 0.19.5 → 0.19.6
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 +22 -0
- package/dist/App.js +16 -3
- package/dist/components/MasterDetailLayout.js +1 -1
- package/dist/components/MasterDetailLayout.styles.js +19 -0
- package/dist/layouts/SidebarLayout.styles.js +26 -0
- package/package.json +1 -1
- package/skills/modern-app/references/components/master-detail-layout.md +8 -0
- package/skills/modern-app/references/layout.md +25 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.19.6] - 2026-09-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Printing an `app.load()` screen printed the sidebar and cut the page off after one sheet.** The
|
|
8
|
+
shell is a viewport-height box whose `main` area scrolls, and `app.load()` pinned `document.body`
|
|
9
|
+
to `100vh` with inline styles — on paper the sidebar took a third of the width and anything below
|
|
10
|
+
the first page's height was lost. `u-sidebar-layout` now has print rules: the sidebar, mobile
|
|
11
|
+
header, modal backdrop and progress bar are hidden, the host is no longer a fixed-height box, and
|
|
12
|
+
`main` stops scrolling and drops its screen padding (page margins come from `@page`), so content
|
|
13
|
+
flows across pages. A part can be brought back on paper with
|
|
14
|
+
`@media print { u-sidebar-layout::part(sidebar) { display: flex; } }`.
|
|
15
|
+
- **A narrow `u-master-detail-layout` printed its overlay detail cut off at the master's height**,
|
|
16
|
+
with the close button on the page. In overlay mode the detail is an absolutely positioned box
|
|
17
|
+
over the master; on print it now returns to the flow and prints in full, instead of the covered
|
|
18
|
+
master and without the close button. An empty detail still prints the master.
|
|
19
|
+
- **`document.body` sizing from `app.load()` could only be overridden with `!important`.** It is now
|
|
20
|
+
a document stylesheet instead of inline styles — `margin: 0` always, `width: 100vw; height: 100vh`
|
|
21
|
+
on screen only — at zero specificity, so any `body { … }` rule of your own takes precedence. The
|
|
22
|
+
sheet is adopted (`document.adoptedStyleSheets`), so it is not blocked by a CSP that disallows
|
|
23
|
+
inline styles.
|
|
24
|
+
|
|
3
25
|
## [0.19.5] - 2026-09-15
|
|
4
26
|
|
|
5
27
|
### Fixed
|
package/dist/App.js
CHANGED
|
@@ -4,7 +4,20 @@ import { Router as n } from "@iyulab/router";
|
|
|
4
4
|
import { setDefaultBaseUrl as r } from "@iyulab/components/dist/utilities/icons.js";
|
|
5
5
|
import { Theme as i } from "@iyulab/components/dist/utilities/Theme.js";
|
|
6
6
|
import { Toast as a } from "@iyulab/components/dist/utilities/Toast.js";
|
|
7
|
-
|
|
7
|
+
//#region src/App.ts
|
|
8
|
+
var o = "\n:where(body) { margin: 0; }\n@media screen {\n :where(body) { width: 100vw; height: 100vh; }\n}\n", s;
|
|
9
|
+
function c() {
|
|
10
|
+
if (!s) {
|
|
11
|
+
if ("adoptedStyleSheets" in document && typeof CSSStyleSheet < "u" && typeof CSSStyleSheet.prototype.replaceSync == "function") {
|
|
12
|
+
let e = new CSSStyleSheet();
|
|
13
|
+
e.replaceSync(o), document.adoptedStyleSheets = [...document.adoptedStyleSheets, e], s = e;
|
|
14
|
+
} else {
|
|
15
|
+
let e = document.createElement("style");
|
|
16
|
+
e.textContent = o, document.head.prepend(e), s = e;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
var l = class o {
|
|
8
21
|
constructor() {}
|
|
9
22
|
static get instance() {
|
|
10
23
|
return o._instance ||= new o(), o._instance;
|
|
@@ -84,7 +97,7 @@ var o = class o {
|
|
|
84
97
|
await a.error(e, { ...t });
|
|
85
98
|
}
|
|
86
99
|
async createLayout(e, t) {
|
|
87
|
-
e === document.body && (
|
|
100
|
+
e === document.body && c();
|
|
88
101
|
let n;
|
|
89
102
|
if (t.type === "sidebar") {
|
|
90
103
|
let { SidebarLayout: e } = await import("./layouts/SidebarLayout.js"), r = new e();
|
|
@@ -94,4 +107,4 @@ var o = class o {
|
|
|
94
107
|
}
|
|
95
108
|
}.instance;
|
|
96
109
|
//#endregion
|
|
97
|
-
export {
|
|
110
|
+
export { l as app };
|
|
@@ -36,7 +36,7 @@ var u = class extends n {
|
|
|
36
36
|
}
|
|
37
37
|
render() {
|
|
38
38
|
return o`
|
|
39
|
-
<div class="master" part="master"><slot></slot></div>
|
|
39
|
+
<div class="master ${this.hasDetail ? "covered" : ""}" part="master"><slot></slot></div>
|
|
40
40
|
<div class="divider ${this.hasDetail ? "" : "empty"}" part="divider"></div>
|
|
41
41
|
<div class="detail ${this.hasDetail ? "" : "empty"}" part="detail">
|
|
42
42
|
<u-button class="detail-close" part="detail-close" variant="ghost"
|
|
@@ -67,6 +67,25 @@ var t = e`
|
|
|
67
67
|
:host([overlay]) .detail-close {
|
|
68
68
|
display: inline-flex;
|
|
69
69
|
}
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
* 인쇄 — 오버레이 모드의 detail 은 host 전체를 덮는 절대배치 상자라, 높이가 master 내용에
|
|
73
|
+
* 묶이고(그 밖은 잘린다) 닫기 버튼까지 종이에 찍힌다. 화면에 보이는 것(detail)을 흐름에
|
|
74
|
+
* 되돌려 전부 인쇄한다 — 덮여 있던 master 는 찍지 않는다. detail 이 비어 있으면 master 가
|
|
75
|
+
* 화면 그대로 인쇄된다(covered 는 detail 이 채워졌을 때만 붙는다).
|
|
76
|
+
* 나란히 배치 모드는 바꾸지 않는다 — 두 판이 부모 높이를 따라 풀린다.
|
|
77
|
+
*/
|
|
78
|
+
@media print {
|
|
79
|
+
.detail-close,
|
|
80
|
+
:host([overlay]) .detail-close,
|
|
81
|
+
:host([overlay]) .master.covered {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
:host([overlay]) .detail {
|
|
85
|
+
position: static;
|
|
86
|
+
box-shadow: none;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
70
89
|
`;
|
|
71
90
|
//#endregion
|
|
72
91
|
export { t as styles };
|
|
@@ -221,6 +221,32 @@ var t = e`
|
|
|
221
221
|
bottom: 0;
|
|
222
222
|
background: var(--u-overlay-bg-color, rgba(0, 0, 0, 0.5));
|
|
223
223
|
}
|
|
224
|
+
|
|
225
|
+
/*
|
|
226
|
+
* 인쇄 — 화면의 «뷰포트를 채우는 고정 상자 + 스크롤하는 본문» 모델을 풀어 준다.
|
|
227
|
+
* 그대로 두면 사이드바가 종이에 찍히고, 본문이 스크롤 컨테이너라 첫 쪽 높이 밖이 잘린다.
|
|
228
|
+
* ★!important 를 쓰지 않는다 — 섀도 안의 important 선언은 바깥 ::part 의 important 보다 이겨
|
|
229
|
+
* 소비자가 인쇄물에 크롬을 되살릴 길(::part(sidebar) 재정의)을 막는다. 대가로 config.styles 의
|
|
230
|
+
* 인라인 스타일은 이 규칙보다 앞선다(그 자리에 높이·overflow 를 적는 소비자는 드물다).
|
|
231
|
+
* ⚠본문 패딩도 푼다 — 종이의 여백은 @page 가 준다. 화면 여백이 그 위에 겹치면 폭을 잃는다.
|
|
232
|
+
*/
|
|
233
|
+
@media print {
|
|
234
|
+
:host {
|
|
235
|
+
display: block;
|
|
236
|
+
height: auto;
|
|
237
|
+
overflow: visible;
|
|
238
|
+
}
|
|
239
|
+
.sidebar,
|
|
240
|
+
.mobile-header,
|
|
241
|
+
.backdrop,
|
|
242
|
+
.main u-progress-bar {
|
|
243
|
+
display: none;
|
|
244
|
+
}
|
|
245
|
+
.main {
|
|
246
|
+
padding: 0;
|
|
247
|
+
overflow: visible;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
224
250
|
`;
|
|
225
251
|
//#endregion
|
|
226
252
|
export { t as styles };
|
package/package.json
CHANGED
|
@@ -51,6 +51,14 @@ constrained.
|
|
|
51
51
|
.page { height: 100%; } /* or any constrained height on the parent */
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
## Printing
|
|
55
|
+
|
|
56
|
+
On print media the panes follow what was on screen. Side by side, both panes print and grow
|
|
57
|
+
with their content once the page shell releases its height (`u-sidebar-layout` does on print).
|
|
58
|
+
In overlay mode, a filled detail prints in full, in flow, instead of the covered master, and the
|
|
59
|
+
close button is not printed; with the detail empty, the master prints. The overlay state is the
|
|
60
|
+
one measured on screen when printing starts.
|
|
61
|
+
|
|
54
62
|
## Slots
|
|
55
63
|
|
|
56
64
|
| Name | Description |
|
|
@@ -265,17 +265,39 @@ Parts available for `styles` overrides on the root layout:
|
|
|
265
265
|
|
|
266
266
|
`<u-sidebar-layout>` is a shell: `:host` is `height: 100%` with `overflow: hidden`, so **its
|
|
267
267
|
height comes from the parent** — it never sizes itself. `app.load()` covers the default case: when
|
|
268
|
-
`root` is `document.body` it
|
|
268
|
+
`root` is `document.body` it gives the body `margin: 0`, and on screen `width: 100vw; height: 100vh`.
|
|
269
|
+
These come from a document stylesheet at zero specificity, not inline styles — any `body { … }`
|
|
270
|
+
rule of your own wins.
|
|
269
271
|
|
|
270
272
|
⚠ **A custom `root` receives no styling.** Hand it a container with no height of its own and
|
|
271
273
|
`height: 100%` has nothing to resolve against: the shell renders at whatever its own chrome
|
|
272
274
|
resolves to (measured: about 133px) instead of filling the screen — with no error and nothing in
|
|
273
|
-
the console. Give that container a height:
|
|
275
|
+
the console. Give that container a height — for screen only, so printing is not cut at one page:
|
|
274
276
|
|
|
275
277
|
```css
|
|
276
|
-
|
|
278
|
+
@media screen {
|
|
279
|
+
#app { height: 100vh; } /* or 100%, inside an already-constrained ancestor */
|
|
280
|
+
}
|
|
277
281
|
```
|
|
278
282
|
|
|
283
|
+
## Printing
|
|
284
|
+
|
|
285
|
+
On print media the shell drops its app chrome and lets the content flow across pages: the
|
|
286
|
+
`sidebar`, `mobile-header`, modal backdrop and `progress` bar are hidden, the host is no longer a
|
|
287
|
+
fixed-height box, and `main` stops being a scroll container and loses its screen padding (page
|
|
288
|
+
margins come from `@page`). Nothing to configure.
|
|
289
|
+
|
|
290
|
+
To keep a piece of chrome on paper, restore it through its part:
|
|
291
|
+
|
|
292
|
+
```css
|
|
293
|
+
@media print {
|
|
294
|
+
u-sidebar-layout::part(sidebar) { display: flex; }
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
⚠ Heights or `overflow` set through `layout.styles` are inline styles and still apply when
|
|
299
|
+
printing — scope such values to the screen in your own CSS instead.
|
|
300
|
+
|
|
279
301
|
## Responsive behaviour
|
|
280
302
|
|
|
281
303
|
| Screen width | Sidebar state |
|