@iyulab/modern-app 0.15.0 → 0.17.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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.17.0] - 2026-08-11
4
+
5
+ ### Added
6
+
7
+ - **`/react` subpath**, wrapping `SidebarLayout` and `Wizard` with `@lit/react`'s
8
+ `createComponent`. `Wizard` is the only component that dispatches a custom event
9
+ (`step-change`) — a raw custom element in JSX maps an `onStepChange` prop to a listener
10
+ for a literal `"StepChange"` DOM event, which `Wizard` never fires, so the event never
11
+ reaches a consumer without this wrapper. Both components also carry object/array
12
+ properties (`config`, `steps`) that a raw custom element handles correctly under React 19
13
+ (which assigns matching properties directly) but not under React 18 (where non-primitive
14
+ JSX attributes stringify) — the wrapper keeps that working on both. Every component in
15
+ this package (not just these two) also inherits an object-typed `styles` property from its
16
+ base class for part-level style overrides; on React 18 that still needs a ref without a
17
+ wrapper.
18
+
19
+ ## [0.16.0] - 2026-08-11
20
+
21
+ ### Changed
22
+
23
+ - **`SidebarLayout`'s main content area now ships a default padding**
24
+ (`var(--u-space-3xl, 32px)`) instead of none. Every consumer previously had to add this
25
+ themselves to keep route content off the viewport/sidebar edge. Full-bleed layouts (e.g. a
26
+ dashboard whose table should reach the panel edge) can still opt back to `0` via
27
+ `styles.main`. This is a visible rendering change for any consumer that never set
28
+ `styles.main` — hence the minor bump rather than a patch.
29
+
3
30
  ## [0.15.0] - 2026-08-11
4
31
 
5
32
  ### Added
package/README.md CHANGED
@@ -173,6 +173,38 @@ await app.load({
173
173
  - `hasPermission` 미지정 시 필터링하지 않는다(모든 항목 표시 — 하위호환).
174
174
  - 순수 헬퍼 `filterSidebarItems(items, hasPermission)` 를 직접 재사용할 수도 있다.
175
175
 
176
+ ## React
177
+
178
+ A `@lit/react`-based wrapper for `SidebarLayout` and `Wizard` is available under `/react`.
179
+ Every other exported component works as a plain custom element in JSX; these two specifically
180
+ need the wrapper because `Wizard` dispatches a `step-change` custom event (a raw element maps
181
+ `onStepChange` to a literal `"StepChange"` DOM event it never fires) and both carry object/array
182
+ properties that a raw element only handles correctly under React 19.
183
+
184
+ `@lit/react` and `react` are optional peer dependencies — install them to use this subpath:
185
+
186
+ ```bash
187
+ npm install @iyulab/modern-app @lit/react react
188
+ ```
189
+
190
+ ```tsx
191
+ import { SidebarLayout, Wizard, type SidebarItem, type WizardStep } from '@iyulab/modern-app/react';
192
+
193
+ const main: SidebarItem[] = [{ type: 'link', label: 'Home', href: '/' }];
194
+ const steps: WizardStep[] = [{ id: 'info', label: 'Info' }, { id: 'review', label: 'Review' }];
195
+
196
+ export function App() {
197
+ return (
198
+ <SidebarLayout config={{ type: 'sidebar', title: 'My App', main }}>
199
+ <Wizard steps={steps} active={0} onStepChange={(e) => console.log(e.detail)}>
200
+ <section>Info panel</section>
201
+ <section>Review panel</section>
202
+ </Wizard>
203
+ </SidebarLayout>
204
+ );
205
+ }
206
+ ```
207
+
176
208
  ## Documentation
177
209
 
178
210
  | Guide | Description |
@@ -4,7 +4,7 @@ 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";
6
6
  import { customElement as a, property as o } from "lit/decorators.js";
7
- import { formatCurrency as s, formatDate as c, formatNumber as l } from "@iyulab/components";
7
+ import { formatCurrency as s, formatDate as c, formatNumber as l } from "@iyulab/components/dist/utilities/format.js";
8
8
  //#region src/components/InfoField.ts
9
9
  function u(e) {
10
10
  return e === "up" ? "positive" : e === "down" ? "negative" : "neutral";
@@ -165,10 +165,19 @@ var t = e`
165
165
  display: none;
166
166
  }
167
167
 
168
- /* Main Content */
168
+ /* Main Content
169
+ * ★기본 패딩을 준다 — 라우트 콘텐츠가 뷰포트/사이드바 경계에 그대로 맞닿아 모든
170
+ * 소비자가 같은 배선을 재구현하던 문제였다. 값은 이 라이브러리의 spacing 스케일
171
+ * 상단 근처(3xl)에서 골랐다 — LOB 화면의 표준 여백으로 쓰기에 과하지 않은 최대값.
172
+ * ⚠«패딩 박스» 기준 절대배치는 이 padding 의 영향을 받지 않는다 — 바로 아래
173
+ * u-progress-bar 가 top/left/right:0 으로 여전히 테두리에 꽉 차게 붙는 이유다
174
+ * (CSS 2.1 §10.6.4: 절대배치 자손의 containing block 은 가장 가까운 positioned
175
+ * 조상의 «패딩 박스»이고, 그 경계는 조상 자신의 padding 값에 밀리지 않는다).
176
+ * 풀블리드를 원하는 소비자는 layout.styles.main = { padding: '0' } 로 되돌린다. */
169
177
  .main {
170
178
  position: relative;
171
179
  flex: 1;
180
+ padding: var(--u-space-3xl, 32px);
172
181
  background: var(--u-bg-color, #FFFFFF);
173
182
  overflow: auto;
174
183
  outline: none;
@@ -6,6 +6,10 @@ import { SidebarGroupConfig } from '../components/SidebarGroup';
6
6
  import { SidebarButtonConfig } from '../components/SidebarButton';
7
7
  import { SidebarPermissionGuard } from './SidebarPermission';
8
8
  export type { SidebarPermissionGuard } from './SidebarPermission';
9
+ export type { SidebarLinkConfig } from '../components/SidebarLink';
10
+ export type { SidebarSectionConfig } from '../components/SidebarSection';
11
+ export type { SidebarGroupConfig } from '../components/SidebarGroup';
12
+ export type { SidebarButtonConfig } from '../components/SidebarButton';
9
13
  /** 사이드바 레이아웃 컴포넌트의 요소(part) 타입 */
10
14
  export type SidebarParts = 'host' | 'mobile-header' | 'sidebar' | 'sidebar-header' | 'sidebar-main' | 'sidebar-footer' | 'main' | 'progress';
11
15
  /** 사이드바 상태 타입 */
@@ -0,0 +1,25 @@
1
+ import { default as React } from 'react';
2
+ import { EventName } from '@lit/react';
3
+ import { SidebarLayout as SidebarLayoutElement } from './layouts/SidebarLayout.js';
4
+ import { Wizard as WizardElement, WizardStepChangeDetail } from './components/Wizard.js';
5
+ /**
6
+ * React wrapper for `<u-sidebar-layout>`. `config` is an `@property({ type: Object })` —
7
+ * a raw custom element handles that correctly under React 19 (property assignment) but not
8
+ * React 18 (JSX attributes stringify), so this wrapper keeps `config` working on both.
9
+ */
10
+ export declare const SidebarLayout: import('@lit/react').ReactWebComponent<SidebarLayoutElement, {}>;
11
+ export type SidebarLayoutProps = React.ComponentProps<typeof SidebarLayout>;
12
+ /**
13
+ * React wrapper for `<u-wizard>`. `Wizard` dispatches a `step-change` custom event, but a raw
14
+ * custom element in JSX maps `onStepChange` to a listener for a literal `"StepChange"` DOM
15
+ * event — one `Wizard` never fires — so the event never reaches a consumer without this
16
+ * wrapper's `events` mapping. `steps` is also an `@property({ type: Array })`, which the
17
+ * wrapper keeps working on React 18 the same way it does for `SidebarLayout`'s `config`.
18
+ */
19
+ export declare const Wizard: import('@lit/react').ReactWebComponent<WizardElement, {
20
+ onStepChange: EventName<CustomEvent<WizardStepChangeDetail>>;
21
+ }>;
22
+ export type WizardProps = React.ComponentProps<typeof Wizard>;
23
+ export type { SidebarLayoutElement, WizardElement };
24
+ export type { SidebarLayoutConfig, SidebarItem, SidebarLogoConfig, SidebarLinkConfig, SidebarSectionConfig, SidebarGroupConfig, SidebarButtonConfig, SidebarHtmlConfig, } from './layouts/SidebarLayout.types.js';
25
+ export type { WizardStep, WizardStepState, WizardStepChangeDetail } from './components/Wizard.js';
package/dist/react.js ADDED
@@ -0,0 +1,18 @@
1
+ import { Wizard as e } from "./components/Wizard.js";
2
+ import { SidebarLayout as t } from "./layouts/SidebarLayout.js";
3
+ import n from "react";
4
+ import { createComponent as r } from "@lit/react";
5
+ //#region src/react.ts
6
+ var i = r({
7
+ react: n,
8
+ tagName: "u-sidebar-layout",
9
+ elementClass: t,
10
+ events: {}
11
+ }), a = r({
12
+ react: n,
13
+ tagName: "u-wizard",
14
+ elementClass: e,
15
+ events: { onStepChange: "step-change" }
16
+ });
17
+ //#endregion
18
+ export { i as SidebarLayout, a as Wizard };
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.15.0",
4
+ "version": "0.17.0",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-framework",
@@ -32,13 +32,19 @@
32
32
  "./dist/index.js",
33
33
  "./src/index.ts",
34
34
  "./dist/layouts/*.js",
35
- "./src/layouts/*.ts"
35
+ "./src/layouts/*.ts",
36
+ "./dist/react.js",
37
+ "./src/react.ts"
36
38
  ],
37
39
  "exports": {
38
40
  ".": {
39
41
  "types": "./dist/index.d.ts",
40
42
  "import": "./dist/index.js"
41
43
  },
44
+ "./react": {
45
+ "types": "./dist/react.d.ts",
46
+ "import": "./dist/react.js"
47
+ },
42
48
  "./dist/*": {
43
49
  "types": "./dist/*.d.ts",
44
50
  "import": "./dist/*"
@@ -58,10 +64,27 @@
58
64
  "i18next": "^26.3.6",
59
65
  "lit": "^3.3.3"
60
66
  },
67
+ "peerDependencies": {
68
+ "@lit/react": ">=1.0.8",
69
+ "react": ">=18.0.0"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "@lit/react": {
73
+ "optional": true
74
+ },
75
+ "react": {
76
+ "optional": true
77
+ }
78
+ },
61
79
  "devDependencies": {
80
+ "@lit/react": "^1.0.8",
62
81
  "@types/node": "^26.1.1",
82
+ "@types/react": "^19.2.14",
83
+ "@types/react-dom": "^19.2.3",
63
84
  "@vitest/browser-playwright": "^4.1.10",
64
85
  "happy-dom": "^20.10.6",
86
+ "react": "^19.2.7",
87
+ "react-dom": "^19.2.7",
65
88
  "typescript": "^5.9.3",
66
89
  "vite": "^8.1.4",
67
90
  "vite-plugin-dts": "^5.0.3",
@@ -44,11 +44,11 @@ configurable breakpoint means measuring the host's own width in JavaScript and r
44
44
 
45
45
  ## Properties
46
46
 
47
- | Property | Attribute | Type | Default | Description |
48
- |----------|-----------|------|---------|-------------|
49
- | `masterSize` | `master-size` | `string` (CSS length) | `'22rem'` | Fixed width of the master pane |
50
- | `overlayBreakpoint` | `overlay-breakpoint` | `number` (px) | `760` | Below this self width, detail becomes a full overlay |
51
- | `locale` | `locale` | `string` | `''` | Language tag for the close button's accessible label |
47
+ | Property | Type | Default | Reflect | Description |
48
+ |----------|------|---------|---------|-------------|
49
+ | `masterSize` | `string` | `'22rem'` | | Fixed width of the master pane, a CSS length (`master-size`) |
50
+ | `overlayBreakpoint` | `number` | `760` | | Below this self width in px, detail becomes a full overlay (`overlay-breakpoint`) |
51
+ | `locale` | `string` | `''` | | Language tag for the close button's accessible label |
52
52
 
53
53
  ## Events
54
54