@iyulab/modern-app 0.18.11 → 0.18.17
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 +88 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.147.0 → _@oxc-project_runtime@0.148.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.147.0 → _@oxc-project_runtime@0.148.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/components/ActionBar.js +2 -2
- package/dist/components/EmptyState.js +2 -2
- package/dist/components/GroupBox.js +2 -2
- package/dist/components/InfoField.js +2 -2
- package/dist/components/InfoSection.js +2 -2
- package/dist/components/MasterDetailLayout.js +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/internals/StyledElement.js +2 -2
- package/dist/layouts/SidebarLayout.js +2 -2
- package/package.json +1 -1
- package/skills/modern-app/SKILL.md +1 -1
- package/skills/modern-app/references/api.md +107 -13
- package/skills/modern-app/references/layout.md +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.18.17] - 2026-09-03
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`AppConfig.auth` (the boot-time auth gate) and its `AuthGateConfig`/`AuthGateContext`
|
|
8
|
+
types were entirely undocumented in both reference docs** — the feature has a full worked
|
|
9
|
+
example in the README but no type reference anywhere a consumer would look one up. Also
|
|
10
|
+
documented `app.user` (the authenticated-user getter), and added `enter`/`initialLoad`/
|
|
11
|
+
`useIntercept` — three more real `AppConfig` fields missing specifically from
|
|
12
|
+
`skills/modern-app/references/api.md`.
|
|
13
|
+
- **`FallbackRouteConfig.title` was dropped by `0.18.13`**, which only touched the `render`
|
|
14
|
+
callback's context type and didn't notice it removed the field. Restored in both docs.
|
|
15
|
+
Found by a new internal tool (`type-doc-check.js`) that diffs hand-copied TS interface doc
|
|
16
|
+
snippets against source.
|
|
17
|
+
|
|
18
|
+
## [0.18.16] - 2026-09-03
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`ThemeInitOptions.store`'s type documented a `'sessionStorage'` value that has
|
|
23
|
+
never existed.** The field's real type is re-exported unchanged from
|
|
24
|
+
`@iyulab/components`' `BrowserStorageOptions`, which only supports
|
|
25
|
+
`'localStorage' | 'cookie'` — confirmed against `BrowserStorage.ts` and its test
|
|
26
|
+
suite, which uses `'sessionStorage'` specifically as the invalid-type negative
|
|
27
|
+
case. All three docs (`docs/theme.md`, `docs/configuration.md`,
|
|
28
|
+
`skills/modern-app/references/api.md`) listed it as valid.
|
|
29
|
+
|
|
30
|
+
## [0.18.15] - 2026-09-02
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **`NotificationOptions.position` documented only 4 of the 9 valid values in
|
|
35
|
+
four places** (`docs/notifications.md`, `docs/configuration.md`,
|
|
36
|
+
`skills/modern-app/references/api.md`, `skills/modern-app/SKILL.md`).
|
|
37
|
+
The field's actual type is `ToastPosition` (`@iyulab/components`, re-exported
|
|
38
|
+
unchanged) and `App.ts` passes `options` straight through to `Toast.*()` with
|
|
39
|
+
no restriction — `app.success(msg, { position: 'middle-center' })` genuinely
|
|
40
|
+
works today. Docs narrowed it to `'top-right' | 'top-left' | 'bottom-right'
|
|
41
|
+
| 'bottom-left'`, silently hiding `top-center`, `middle-left`,
|
|
42
|
+
`middle-center`, `middle-right`, and `bottom-center`.
|
|
43
|
+
|
|
44
|
+
## [0.18.14] - 2026-09-02
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- **`SidebarLayoutConfig`'s `mainAriaLabel` and `hasPermission` fields were
|
|
49
|
+
undocumented in all three reference docs** (`docs/layout.md`,
|
|
50
|
+
`docs/configuration.md`, `skills/modern-app/references/layout.md`). Both
|
|
51
|
+
are real, shipped features — `mainAriaLabel` sets the main nav landmark's
|
|
52
|
+
`aria-label`, `hasPermission` filters sidebar items by permission — and
|
|
53
|
+
the README already has a working usage example for `hasPermission`, but
|
|
54
|
+
a consumer reading only the type reference had no way to discover either
|
|
55
|
+
field. Added to all three snippets.
|
|
56
|
+
|
|
57
|
+
## [0.18.13] - 2026-09-02
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- **`RouteContext`'s documented field list had drifted independently of
|
|
62
|
+
`RouteConfig`'s.** `0.18.12` fixed `RouteConfig`'s snippet in two of three
|
|
63
|
+
docs but left `RouteContext` untouched everywhere, and `configuration.md`'s
|
|
64
|
+
`RouteConfig` snippet was missed entirely. `docs/configuration.md` and
|
|
65
|
+
`docs/routing.md` were both missing `origin`, `path`, and `hash`
|
|
66
|
+
(`routing.md` also missing `metadata`, despite `RouteConfig.metadata`'s own
|
|
67
|
+
doc comment on the line above pointing to it); `skills/modern-app/references/api.md`
|
|
68
|
+
was missing `origin`, `path`, `query`, `hash`, and `metadata` — a consumer
|
|
69
|
+
reading only that doc had no way to discover `ctx.query` exists at all.
|
|
70
|
+
`configuration.md`'s `RouteConfig` snippet gained `id`, `ignoreCase`, and
|
|
71
|
+
`children`, matching the other two docs. `FallbackRouteConfig`'s `render`
|
|
72
|
+
callback is now typed `RouteContext & { error: RouteError }` — what
|
|
73
|
+
`Router.ts` actually passes — instead of plain `RouteContext` or an
|
|
74
|
+
untyped prose note.
|
|
75
|
+
|
|
76
|
+
## [0.18.12] - 2026-09-01
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- **Routing docs never mentioned nested routes (`RouteConfig.children`).**
|
|
81
|
+
`@iyulab/router`'s `RouteConfig` supports it and its own README documents
|
|
82
|
+
it, but `modern-app`'s `docs/routing.md` and `skills/modern-app/references/api.md`
|
|
83
|
+
only reproduced a partial `RouteConfig` snippet that omitted `children`,
|
|
84
|
+
`id`, `ignoreCase`, and `enter`, and narrowed `path` to `string` only. A
|
|
85
|
+
consumer reading only `modern-app`'s docs had no way to discover the
|
|
86
|
+
feature and would flatten routes that share a layout into a single list.
|
|
87
|
+
Both docs now cover the full shape and link to `@iyulab/router`'s README
|
|
88
|
+
as the source of truth, and `docs/routing.md` gained a "Nested routes"
|
|
89
|
+
section with an example.
|
|
90
|
+
|
|
3
91
|
## [0.18.11] - 2026-09-01
|
|
4
92
|
|
|
5
93
|
### Changed
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.148.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.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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";
|
|
@@ -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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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";
|
|
@@ -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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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";
|
|
@@ -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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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";
|
|
@@ -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.148.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import t from "../_virtual/_@oxc-project_runtime@0.148.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,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.148.0/helpers/esm/decorateMetadata.js";
|
|
4
|
+
import r from "../_virtual/_@oxc-project_runtime@0.148.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 "../components/SidebarSection.js";
|
package/package.json
CHANGED
|
@@ -105,7 +105,7 @@ await app.warning('Check your input');
|
|
|
105
105
|
await app.error('Something went wrong');
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
`position` values: `'top-
|
|
108
|
+
`position` values: `'top-left'` | `'top-center'` | `'top-right'` | `'middle-left'` | `'middle-center'` | `'middle-right'` | `'bottom-left'` | `'bottom-center'` | `'bottom-right'`
|
|
109
109
|
`duration` default: `3000` ms
|
|
110
110
|
|
|
111
111
|
---
|
|
@@ -19,6 +19,18 @@ interface AppConfig {
|
|
|
19
19
|
/** Fallback rendered on 404 or unhandled errors. */
|
|
20
20
|
fallback?: FallbackRouteConfig;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Global auth/authorization guard, called before every navigation.
|
|
24
|
+
* `string` = redirect, `false` = cancel (403), `true`/undefined = proceed.
|
|
25
|
+
*/
|
|
26
|
+
enter?: (ctx: RouteContext) => Promise<string | boolean> | string | boolean;
|
|
27
|
+
|
|
28
|
+
/** Auto-navigate to the current URL on load. Default: true */
|
|
29
|
+
initialLoad?: boolean;
|
|
30
|
+
|
|
31
|
+
/** Intercept `<a>` tag clicks for client-side routing. Default: true */
|
|
32
|
+
useIntercept?: boolean;
|
|
33
|
+
|
|
22
34
|
/** Layout configuration. Currently only 'sidebar' is supported. */
|
|
23
35
|
layout: LayoutConfig;
|
|
24
36
|
|
|
@@ -27,6 +39,12 @@ interface AppConfig {
|
|
|
27
39
|
|
|
28
40
|
/** i18next options plus optional plugins array. Omit to skip i18n. */
|
|
29
41
|
i18n?: I18nInitOptions;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Boot-time auth gate. When set, resolves the session via `me()` before the app shell
|
|
45
|
+
* is built. Omit for full backward compatibility (no gate). See `AuthGateConfig` below.
|
|
46
|
+
*/
|
|
47
|
+
auth?: AuthGateConfig;
|
|
30
48
|
}
|
|
31
49
|
```
|
|
32
50
|
|
|
@@ -57,11 +75,10 @@ interface ThemeInitOptions {
|
|
|
57
75
|
* Persist the user's preference.
|
|
58
76
|
* Set to `false` to disable persistence.
|
|
59
77
|
* Default: localStorage with no prefix.
|
|
78
|
+
* `type: 'cookie'` also accepts path/domain/expires/sameSite/partitioned — see
|
|
79
|
+
* `@iyulab/components`'s `BrowserStorage` reference. No `'sessionStorage'` backend exists.
|
|
60
80
|
*/
|
|
61
|
-
store?: false | {
|
|
62
|
-
type: 'cookie' | 'localStorage' | 'sessionStorage';
|
|
63
|
-
prefix?: string;
|
|
64
|
-
};
|
|
81
|
+
store?: false | { type: 'localStorage'; prefix?: string } | { type: 'cookie'; prefix?: string };
|
|
65
82
|
|
|
66
83
|
/** Apply built-in CSS custom properties. Default: true */
|
|
67
84
|
useBuiltIn?: boolean;
|
|
@@ -72,13 +89,18 @@ interface ThemeInitOptions {
|
|
|
72
89
|
|
|
73
90
|
## `RouteConfig`
|
|
74
91
|
|
|
92
|
+
`RouteConfig` is re-exported unchanged from `@iyulab/router` — see its README for the full
|
|
93
|
+
reference. Supports `children: RouteConfig[]` for nested routes (a matched parent renders
|
|
94
|
+
its own `<u-outlet>` to host the matched child) — see `docs/routing.md`'s "Nested routes"
|
|
95
|
+
section for an example.
|
|
96
|
+
|
|
75
97
|
```typescript
|
|
76
98
|
interface RouteConfig {
|
|
77
99
|
/** Matches the root path (equivalent to `path: ''`). */
|
|
78
100
|
index?: boolean;
|
|
79
101
|
|
|
80
|
-
/** Path string
|
|
81
|
-
path?: string;
|
|
102
|
+
/** Path string or `URLPattern`. Supports `:param` segments. */
|
|
103
|
+
path?: string | URLPattern;
|
|
82
104
|
|
|
83
105
|
/** Sets `document.title` when the route activates. */
|
|
84
106
|
title?: string;
|
|
@@ -86,6 +108,26 @@ interface RouteConfig {
|
|
|
86
108
|
/** Force a re-render even if the path did not change. */
|
|
87
109
|
force?: boolean;
|
|
88
110
|
|
|
111
|
+
/** Case-insensitive path matching. Defaults to `false`. */
|
|
112
|
+
ignoreCase?: boolean;
|
|
113
|
+
|
|
114
|
+
/** Identifier used internally by the router (auto-generated if omitted). */
|
|
115
|
+
id?: string;
|
|
116
|
+
|
|
117
|
+
/** Metadata merged parent → child, exposed on `RouteContext.metadata`. */
|
|
118
|
+
metadata?: Record<string, unknown>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Guard called before this route activates.
|
|
122
|
+
* - Return a `string` to redirect.
|
|
123
|
+
* - Return `false` to cancel navigation.
|
|
124
|
+
* - Return `true` (or nothing) to proceed.
|
|
125
|
+
*/
|
|
126
|
+
enter?: (context: RouteContext) => Promise<string | boolean> | string | boolean;
|
|
127
|
+
|
|
128
|
+
/** Child routes, matched relative to this route's path. */
|
|
129
|
+
children?: RouteConfig[];
|
|
130
|
+
|
|
89
131
|
/** Render function. May be async. */
|
|
90
132
|
render: (context: RouteContext) => RenderResult | Promise<RenderResult>;
|
|
91
133
|
}
|
|
@@ -100,14 +142,29 @@ interface RouteContext {
|
|
|
100
142
|
/** Full URL string. */
|
|
101
143
|
href: string;
|
|
102
144
|
|
|
103
|
-
/**
|
|
104
|
-
|
|
145
|
+
/** Domain name portion of the URL (e.g. `https://example.com`). */
|
|
146
|
+
origin: string;
|
|
105
147
|
|
|
106
148
|
/** Configured basepath. */
|
|
107
149
|
basepath: string;
|
|
108
150
|
|
|
151
|
+
/** Full path including query string and hash. */
|
|
152
|
+
path: string;
|
|
153
|
+
|
|
154
|
+
/** Pathname portion of the URL. */
|
|
155
|
+
pathname: string;
|
|
156
|
+
|
|
109
157
|
/** Named URL parameters extracted from the path pattern. */
|
|
110
|
-
params: Record<string, string>;
|
|
158
|
+
params: Record<string, string | undefined>;
|
|
159
|
+
|
|
160
|
+
/** Parsed query string. `query.get('key')` returns `string | null`. */
|
|
161
|
+
query: URLSearchParams;
|
|
162
|
+
|
|
163
|
+
/** Hash portion of the URL, if present. */
|
|
164
|
+
hash?: string;
|
|
165
|
+
|
|
166
|
+
/** Metadata merged parent → child from the matched route chain. */
|
|
167
|
+
metadata: Record<string, unknown>;
|
|
111
168
|
|
|
112
169
|
/**
|
|
113
170
|
* Report loading progress (0–100).
|
|
@@ -123,12 +180,15 @@ interface RouteContext {
|
|
|
123
180
|
|
|
124
181
|
```typescript
|
|
125
182
|
interface FallbackRouteConfig {
|
|
126
|
-
|
|
183
|
+
/** Sets `document.title` when the fallback renders. */
|
|
184
|
+
title?: string;
|
|
185
|
+
|
|
186
|
+
render: (context: RouteContext & { error: RouteError }) => RenderResult | Promise<RenderResult>;
|
|
127
187
|
}
|
|
128
188
|
```
|
|
129
189
|
|
|
130
|
-
|
|
131
|
-
|
|
190
|
+
`RouteError` is importable from `@iyulab/router` (`code`/`original`/`timestamp` alongside the
|
|
191
|
+
inherited `message`) — always populated when the fallback fires.
|
|
132
192
|
|
|
133
193
|
---
|
|
134
194
|
|
|
@@ -149,7 +209,40 @@ type I18nInitOptions = i18next.InitOptions & {
|
|
|
149
209
|
interface NotificationOptions {
|
|
150
210
|
title?: string;
|
|
151
211
|
duration?: number; // milliseconds, default 3000
|
|
152
|
-
position?: 'top-
|
|
212
|
+
position?: 'top-left' | 'top-center' | 'top-right'
|
|
213
|
+
| 'middle-left' | 'middle-center' | 'middle-right'
|
|
214
|
+
| 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## `AuthGateConfig` / `AuthGateContext`
|
|
221
|
+
|
|
222
|
+
The framework owns only the orchestration (check → branch → reload) — session lookup/login itself
|
|
223
|
+
(HTTP), the user/permission shape, and mid-session 401 handling belong to the app (or
|
|
224
|
+
`@iyulab/enterprise`'s `createAuthClient`/`createODataService`).
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
interface AuthGateConfig {
|
|
228
|
+
/** Resolve the current session. Return a value for authenticated, `null`/`undefined` for not. */
|
|
229
|
+
me: () => Promise<unknown | null | undefined> | unknown | null | undefined;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Renders login UI into `context.root` when unauthenticated. Call `context.onSuccess()` on
|
|
233
|
+
* success. Return a cleanup function to have it called on app load/`unload`.
|
|
234
|
+
*/
|
|
235
|
+
renderLogin: (context: AuthGateContext) => (() => void) | void;
|
|
236
|
+
|
|
237
|
+
/** Called once authenticated, right before the app shell is built. */
|
|
238
|
+
onAuthenticated?: (user: unknown) => void | Promise<void>;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
interface AuthGateContext {
|
|
242
|
+
/** Root element to render the login UI into (same as `AppConfig.root`, default `document.body`). */
|
|
243
|
+
root: Element;
|
|
244
|
+
/** Call on successful login — the app (re)loads and the shell appears. */
|
|
245
|
+
onSuccess: () => void;
|
|
153
246
|
}
|
|
154
247
|
```
|
|
155
248
|
|
|
@@ -175,5 +268,6 @@ interface NotificationOptions {
|
|
|
175
268
|
| `config` | `AppConfig \| undefined` | Current config passed to `load()` |
|
|
176
269
|
| `router` | `Router \| undefined` | Underlying `@iyulab/router` instance |
|
|
177
270
|
| `screen` | `ScreenSize \| undefined` | Current responsive screen size |
|
|
271
|
+
| `user` | `unknown` | Authenticated user when the `auth` boot gate is used; `undefined` if unauthenticated or unused |
|
|
178
272
|
| `theme` | `Theme` (static) | Theme utility (`get`, `set`, `isInitialized`) |
|
|
179
273
|
| `i18n` | `i18next` | Raw i18next instance |
|
|
@@ -18,6 +18,12 @@ interface SidebarLayoutConfig {
|
|
|
18
18
|
/** Footer (bottom-pinned) items. */
|
|
19
19
|
footer?: SidebarItem[];
|
|
20
20
|
|
|
21
|
+
/** Accessible name for the main nav landmark (`<nav class="sidebar-main">`), reflected as `aria-label`. Unset by default. */
|
|
22
|
+
mainAriaLabel?: string;
|
|
23
|
+
|
|
24
|
+
/** Permission filter — hides items (and emptied section/groups) whose requirement fails. Unset shows everything. See "권한 기반 메뉴 필터" below. */
|
|
25
|
+
hasPermission?: (code: string) => boolean;
|
|
26
|
+
|
|
21
27
|
/** Per-part style overrides (CSS custom properties / inline styles). */
|
|
22
28
|
styles?: StyleMap<SidebarParts>;
|
|
23
29
|
}
|