@iyulab/modern-app 0.43.0 → 0.44.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.44.1] - 2026-10-07
4
+
5
+ ### Fixed
6
+
7
+ - The master›detail examples (`docs/lob-primitives.md` and the `u-master-detail-layout` skill reference) read the
8
+ selection from `e.detail.selected`, which `u-rich-table`'s `selection-change` does not carry, and typed the event as
9
+ a `SelectionChangeEvent` that no package exports. They read `e.detail.selectedRows[0]`, typed by `RichTableEventMap`.
10
+
11
+ ## [0.44.0] - 2026-10-07
12
+
13
+ ### Added
14
+
15
+ - **`u-empty-state variant="error"`** — the list could not be loaded, a third fact next to `no-data` (create one)
16
+ and `no-results` (change the query); its next step is trying again. Its own default wording (English and Korean
17
+ built in, `errorTitle` / `errorDescription` for other languages), and its title is announced (`role="alert"`) —
18
+ the other two variants are not alarms and stay quiet. `variant` now reflects to the attribute.
19
+
3
20
  ## [0.43.0] - 2026-10-07
4
21
 
5
22
  ### Added
@@ -15,6 +15,10 @@ type ElementParts = 'host' | 'icon' | 'title' | 'description' | 'actions';
15
15
  * </u-empty-state>
16
16
  *
17
17
  * <u-empty-state variant="no-results"></u-empty-state>
18
+ *
19
+ * <u-empty-state variant="error" .description=${error.message}>
20
+ * <u-button slot="actions" @click=${retry}>Try again</u-button>
21
+ * </u-empty-state>
18
22
  * ```
19
23
  *
20
24
  * ⚠**기본 문구는 영어다** — 이 패키지는 범용 층이라 특정 언어를 기본값으로 가질 수 없다.
@@ -27,8 +31,11 @@ type ElementParts = 'host' | 'icon' | 'title' | 'description' | 'actions';
27
31
  */
28
32
  export declare class EmptyState extends StyledElement<ElementParts> {
29
33
  static styles: import('lit').CSSResultGroup[];
30
- /** `no-data` = 아직 없음 / `no-results` = 조건에 맞는 것이 없음. */
31
- variant: 'no-data' | 'no-results';
34
+ /**
35
+ * `no-data` = 아직 없음 / `no-results` = 조건에 맞는 것이 없음 / `error` = 불러오지 못함.
36
+ * 셋은 다음 행동이 다르다(만들기 · 조건 바꾸기 · 다시 시도) — `error` 의 제목은 보조기기에 알린다(`role="alert"`).
37
+ */
38
+ variant: 'no-data' | 'no-results' | 'error';
32
39
  /** 제목. 비우면 variant 기본 문구. */
33
40
  title: string;
34
41
  /** 보조 설명. 비우면 variant 기본 문구. */
@@ -16,7 +16,11 @@ var d = class extends n {
16
16
  }
17
17
  get defaults() {
18
18
  let e = r(this.locale || void 0);
19
- return this.variant === "no-results" ? {
19
+ return this.variant === "error" ? {
20
+ icon: "⚠️",
21
+ title: e.errorTitle,
22
+ description: e.errorDescription
23
+ } : this.variant === "no-results" ? {
20
24
  icon: "🔍",
21
25
  title: e.noResultsTitle,
22
26
  description: e.noResultsDescription
@@ -32,7 +36,7 @@ var d = class extends n {
32
36
  <div class="icon" part="icon" aria-hidden="true">
33
37
  <slot name="icon">${e.icon}</slot>
34
38
  </div>
35
- <p class="title" part="title">${this.title || e.title}</p>
39
+ <p class="title" part="title" role=${this.variant === "error" ? "alert" : s}>${this.title || e.title}</p>
36
40
  ${t ? o`<p class="description" part="description">${t}</p>` : s}
37
41
  <div class="actions ${this.hasActions ? "" : "empty"}" part="actions">
38
42
  <slot name="actions"
@@ -42,6 +46,9 @@ var d = class extends n {
42
46
  `;
43
47
  }
44
48
  };
45
- t([l({ type: String }), e("design:type", String)], d.prototype, "variant", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "title", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "description", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "locale", void 0), t([u(), e("design:type", Object)], d.prototype, "hasActions", void 0), d = t([c("u-empty-state")], d);
49
+ t([l({
50
+ type: String,
51
+ reflect: !0
52
+ }), e("design:type", String)], d.prototype, "variant", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "title", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "description", void 0), t([l({ type: String }), e("design:type", Object)], d.prototype, "locale", void 0), t([u(), e("design:type", Object)], d.prototype, "hasActions", void 0), d = t([c("u-empty-state")], d);
46
53
  //#endregion
47
54
  export { d as EmptyState };
@@ -7,6 +7,9 @@ export interface ModernAppLocaleStrings {
7
7
  /** Empty state — records exist but the current query matched none. */
8
8
  noResultsTitle: string;
9
9
  noResultsDescription: string;
10
+ /** Empty state — the list could not be loaded (`variant="error"`). */
11
+ errorTitle: string;
12
+ errorDescription: string;
10
13
  /** Accessible label for an overlay-mode close button (master-detail layout, sidebar layout overlay). */
11
14
  detailClose: string;
12
15
  /** Sidebar layout — accessible label for the mobile-header menu toggle button. */
@@ -6,6 +6,8 @@ var t = {
6
6
  noDataDescription: "",
7
7
  noResultsTitle: "No matching results",
8
8
  noResultsDescription: "Try changing your search terms or filters.",
9
+ errorTitle: "Couldn’t load this list",
10
+ errorDescription: "Something went wrong while loading. Try again.",
9
11
  detailClose: "Close",
10
12
  toggleMobileMenu: "Toggle menu",
11
13
  toggleSidebar: "Toggle sidebar",
@@ -22,6 +24,8 @@ n.register("en", t), n.register("ko", {
22
24
  noDataDescription: "",
23
25
  noResultsTitle: "일치하는 결과가 없습니다",
24
26
  noResultsDescription: "검색어나 필터를 바꿔 보세요.",
27
+ errorTitle: "목록을 불러오지 못했습니다",
28
+ errorDescription: "불러오는 중 문제가 생겼습니다. 다시 시도해 주세요.",
25
29
  detailClose: "닫기",
26
30
  toggleMobileMenu: "메뉴 열고 닫기",
27
31
  toggleSidebar: "사이드바 열고 닫기",
@@ -56,6 +60,8 @@ function l(e) {
56
60
  noDataDescription: t("noDataDescription"),
57
61
  noResultsTitle: t("noResultsTitle"),
58
62
  noResultsDescription: t("noResultsDescription"),
63
+ errorTitle: t("errorTitle"),
64
+ errorDescription: t("errorDescription"),
59
65
  detailClose: t("detailClose"),
60
66
  toggleMobileMenu: t("toggleMobileMenu"),
61
67
  toggleSidebar: t("toggleSidebar"),
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.43.0",
4
+ "version": "0.44.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-framework",
@@ -15,6 +15,11 @@ for both and a user with a filter still applied reads it as *"my data disappeare
15
15
  </u-empty-state>
16
16
 
17
17
  <u-empty-state variant="no-results"></u-empty-state>
18
+
19
+ <!-- The list could not be loaded — the next step is trying again. The title is announced (role="alert"). -->
20
+ <u-empty-state variant="error" description="Request failed (503)">
21
+ <u-button slot="actions">Try again</u-button>
22
+ </u-empty-state>
18
23
  ```
19
24
 
20
25
  ## Slots
@@ -28,7 +33,7 @@ for both and a user with a filter still applied reads it as *"my data disappeare
28
33
 
29
34
  | Property | Type | Default | Reflect | Description |
30
35
  |----------|------|---------|---------|-------------|
31
- | `variant` | `'no-data'\|'no-results'` | `'no-data'` | | Which fact is being shown; changes the default wording |
36
+ | `variant` | `'no-data'\|'no-results'\|'error'` | `'no-data'` | ✓ | Which fact is being shown; changes the default wording. `error` (could not load) announces its title |
32
37
  | `title` | `string` | `''` | | Override the default title |
33
38
  | `description` | `string` | `''` | | Override the default description |
34
39
  | `locale` | `string` | `''` | | Locale tag override for built-in strings |
@@ -13,7 +13,7 @@ Swap the `detail` slot's content when the selection changes:
13
13
 
14
14
  ```html
15
15
  <u-master-detail-layout>
16
- <u-rich-table @selection-change=${e => (detail = renderRecord(e.detail.selected))}>
16
+ <u-rich-table @selection-change=${e => (detail = renderRecord(e.detail.selectedRows[0]))}>
17
17
  …
18
18
  </u-rich-table>
19
19
  <div slot="detail">${detail}</div>