@simplysm/solid 13.0.96 → 13.0.97

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/solid",
3
- "version": "13.0.96",
3
+ "version": "13.0.97",
4
4
  "description": "Simplysm package - SolidJS library",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",
@@ -30,42 +30,35 @@
30
30
  "@solid-primitives/storage": "^4.3.4",
31
31
  "@solidjs/router": "^0.15.4",
32
32
  "@tabler/icons-solidjs": "^3.40.0",
33
- "@tiptap/core": "^3.20.1",
34
- "@tiptap/extension-color": "^3.20.1",
35
- "@tiptap/extension-highlight": "^3.20.1",
36
- "@tiptap/extension-image": "^3.20.1",
37
- "@tiptap/extension-table": "^3.20.1",
38
- "@tiptap/extension-table-cell": "^3.20.1",
39
- "@tiptap/extension-table-header": "^3.20.1",
40
- "@tiptap/extension-table-row": "^3.20.1",
41
- "@tiptap/extension-text-align": "^3.20.1",
42
- "@tiptap/extension-text-style": "^3.20.1",
43
- "@tiptap/pm": "^3.20.1",
44
- "@tiptap/starter-kit": "^3.20.1",
33
+ "@tiptap/core": "^3.20.4",
34
+ "@tiptap/extension-color": "^3.20.4",
35
+ "@tiptap/extension-highlight": "^3.20.4",
36
+ "@tiptap/extension-image": "^3.20.4",
37
+ "@tiptap/extension-table": "^3.20.4",
38
+ "@tiptap/extension-table-cell": "^3.20.4",
39
+ "@tiptap/extension-table-header": "^3.20.4",
40
+ "@tiptap/extension-table-row": "^3.20.4",
41
+ "@tiptap/extension-text-align": "^3.20.4",
42
+ "@tiptap/extension-text-style": "^3.20.4",
43
+ "@tiptap/pm": "^3.20.4",
44
+ "@tiptap/starter-kit": "^3.20.4",
45
45
  "bwip-js": "^4.8.0",
46
46
  "clsx": "^2.1.1",
47
47
  "consola": "^3.4.2",
48
+ "echarts": "^6.0.0",
48
49
  "html-to-image": "^1.11.13",
49
- "jspdf": "^4.2.0",
50
+ "jspdf": "^4.2.1",
50
51
  "solid-js": "^1.9.11",
51
52
  "solid-tiptap": "^0.8.0",
52
53
  "tabbable": "^6.4.0",
53
54
  "tailwind-merge": "^3.5.0",
54
55
  "tailwindcss": "^3.4.19",
55
- "@simplysm/core-browser": "13.0.96",
56
- "@simplysm/core-common": "13.0.96",
57
- "@simplysm/service-client": "13.0.96",
58
- "@simplysm/service-common": "13.0.96"
56
+ "@simplysm/core-browser": "13.0.97",
57
+ "@simplysm/core-common": "13.0.97",
58
+ "@simplysm/service-client": "13.0.97",
59
+ "@simplysm/service-common": "13.0.97"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@solidjs/testing-library": "^0.8.10"
62
- },
63
- "peerDependencies": {
64
- "echarts": "^6.0.0"
65
- },
66
- "peerDependenciesMeta": {
67
- "echarts": {
68
- "optional": true
69
- }
70
63
  }
71
64
  }
package/README.md DELETED
@@ -1,158 +0,0 @@
1
- # @simplysm/solid
2
-
3
- SolidJS + Tailwind CSS 기반 엔터프라이즈 UI 컴포넌트 라이브러리. 폼 컨트롤, 데이터 테이블, 다이얼로그, 알림, 테마, i18n, CRUD, 권한 관리 등 100+ 컴포넌트를 제공한다.
4
-
5
- ## 설치
6
-
7
- ```bash
8
- npm install @simplysm/solid
9
- ```
10
-
11
- **주요 의존성:** SolidJS, @solidjs/router, Tailwind CSS 3, Tiptap, Tabler Icons
12
- **선택 의존성:** echarts (ECharts 차트 사용 시)
13
-
14
- ## 문서
15
-
16
- | 카테고리 | 설명 |
17
- |---------|------|
18
- | [폼 컨트롤](docs/form-controls.md) | Button, TextInput, NumberInput, Select, Combobox, DatePicker, DateRangePicker, Checkbox, RadioGroup, CheckboxGroup, ColorPicker, RichTextEditor, Numpad, StatePreset 등 |
19
- | [레이아웃 & 데이터](docs/layout-data.md) | FormGroup, FormTable, Sidebar, Topbar, Table, DataSheet, List, Calendar, Kanban, Pagination 등 |
20
- | [디스플레이 & 피드백](docs/display-feedback.md) | Card, Alert, Icon, Link, Tag, Barcode, Echarts, Dialog, Dropdown, Collapse, Tabs, Notification, Busy, Progress, Print 등 |
21
- | [프로바이더 & 훅](docs/providers-hooks.md) | SystemProvider, ThemeProvider, I18nProvider, SharedDataProvider, useDialog, useBusy, useNotification, createAppStructure 등 |
22
- | [기능 컴포넌트](docs/features.md) | CrudSheet, CrudDetail, DataSelectButton, SharedDataSelect, SharedDataSelectButton, SharedDataSelectList, PermissionTable, AddressSearch 등 |
23
-
24
- ## 빠른 시작
25
-
26
- ### SystemProvider (권장)
27
-
28
- `SystemProvider`는 모든 필수 프로바이더를 한 번에 감싸는 편의 컴포넌트다.
29
-
30
- ```tsx
31
- import { SystemProvider } from "@simplysm/solid";
32
-
33
- function App() {
34
- return (
35
- <SystemProvider clientName="my-app" busyVariant="spinner">
36
- <MyPage />
37
- </SystemProvider>
38
- );
39
- }
40
- ```
41
-
42
- 내부적으로 다음 프로바이더를 순서대로 감싼다:
43
- `ConfigProvider` > `I18nProvider` > `SyncStorageProvider` > `LoggerProvider` > `NotificationProvider` > `ErrorLoggerProvider` > `PwaUpdateProvider` > `ClipboardProvider` > `ThemeProvider` > `ServiceClientProvider` > `SharedDataProvider` > `BusyProvider`
44
-
45
- ### 개별 프로바이더 조합
46
-
47
- ```tsx
48
- import { ThemeProvider, I18nProvider, NotificationProvider, BusyProvider } from "@simplysm/solid";
49
-
50
- function App() {
51
- return (
52
- <ThemeProvider>
53
- <I18nProvider>
54
- <NotificationProvider>
55
- <BusyProvider>
56
- <MyPage />
57
- </BusyProvider>
58
- </NotificationProvider>
59
- </I18nProvider>
60
- </ThemeProvider>
61
- );
62
- }
63
- ```
64
-
65
- ### 기본 폼 예제
66
-
67
- ```tsx
68
- import { createSignal } from "solid-js";
69
- import { Card, FormGroup, TextInput, Select, Button } from "@simplysm/solid";
70
-
71
- function MyPage() {
72
- const [name, setName] = createSignal("");
73
- const [role, setRole] = createSignal<string>();
74
-
75
- return (
76
- <Card>
77
- <FormGroup>
78
- <FormGroup.Item label="이름">
79
- <TextInput value={name()} onValueChange={setName} required />
80
- </FormGroup.Item>
81
- <FormGroup.Item label="역할">
82
- <Select
83
- value={role()}
84
- onValueChange={setRole}
85
- items={["admin", "user", "guest"]}
86
- renderValue={(item) => <span>{item}</span>}
87
- />
88
- </FormGroup.Item>
89
- </FormGroup>
90
- <Button theme="primary" onClick={() => save()}>저장</Button>
91
- </Card>
92
- );
93
- }
94
- ```
95
-
96
- ## 공통 타입
97
-
98
- ### ComponentSize
99
-
100
- 모든 폼 컨트롤과 대부분의 컴포넌트가 `size` prop을 지원한다.
101
-
102
- ```typescript
103
- type ComponentSize = "xs" | "sm" | "md" | "lg" | "xl";
104
- ```
105
-
106
- ### SemanticTheme
107
-
108
- 의미론적 색상 테마.
109
-
110
- ```typescript
111
- type SemanticTheme = "base" | "primary" | "success" | "warning" | "danger" | "info";
112
- ```
113
-
114
- ### 스타일 유틸리티
115
-
116
- Tailwind 클래스 프리셋. 테마 일관성을 위해 사용한다.
117
-
118
- ```typescript
119
- import { bg, border, text, pad, gap, themeTokens } from "@simplysm/solid";
120
-
121
- // 배경색
122
- bg.surface // bg-white dark:bg-base-900
123
- bg.muted // bg-base-100 dark:bg-base-800
124
- bg.subtle // bg-base-200 dark:bg-base-700
125
-
126
- // 테두리색
127
- border.default // border-base-200 dark:border-base-700
128
-
129
- // 텍스트색
130
- text.default // text-base-900 dark:text-base-100
131
- text.muted // text-base-400 dark:text-base-500
132
- text.placeholder // placeholder 전용
133
-
134
- // 패딩/갭 프리셋
135
- pad.xs // px-1 py-0
136
- pad.sm // px-1.5 py-0.5
137
- pad.md // px-2 py-1
138
- pad.lg // px-3 py-2
139
- pad.xl // px-4 py-3
140
-
141
- gap.xs // gap-0
142
- gap.sm // gap-0.5
143
- gap.md // gap-1
144
- gap.lg // gap-1.5
145
- gap.xl // gap-2
146
-
147
- // 테마 토큰 (semantic theme별 solid/light/text/hoverBg/border)
148
- themeTokens.primary.solid // bg-primary-500 text-white
149
- themeTokens.primary.solidHover // hover:bg-primary-600 dark:hover:bg-primary-400
150
- themeTokens.primary.light // bg-primary-100 text-primary-900
151
- themeTokens.primary.text // text-primary-600 dark:text-primary-400
152
- themeTokens.primary.hoverBg // hover:bg-primary-100 dark:hover:bg-primary-800/30
153
- themeTokens.primary.border // border-primary-300 dark:border-primary-600
154
- ```
155
-
156
- ### 라이트/다크 테마
157
-
158
- `ThemeProvider`와 `useTheme()` 훅으로 라이트/다크/시스템 모드를 제어한다. localStorage에 설정이 자동 저장된다.
@@ -1,404 +0,0 @@
1
- # 디스플레이 & 피드백
2
-
3
- ## Card
4
-
5
- 그림자와 호버 효과가 있는 카드 컨테이너. 페이드 인 애니메이션 포함.
6
-
7
- ```tsx
8
- import { Card } from "@simplysm/solid";
9
-
10
- <Card>카드 내용</Card>
11
- <Card class="p-4">커스텀 패딩</Card>
12
- ```
13
-
14
- `<div>` HTML 속성을 모두 상속한다.
15
-
16
- ---
17
-
18
- ## Alert
19
-
20
- 의미론적 테마의 알림 배너.
21
-
22
- ```tsx
23
- import { Alert } from "@simplysm/solid";
24
-
25
- <Alert theme="success">저장되었습니다.</Alert>
26
- <Alert theme="danger">오류가 발생했습니다.</Alert>
27
- <Alert theme="warning">주의가 필요합니다.</Alert>
28
- <Alert theme="info">참고 사항입니다.</Alert>
29
- ```
30
-
31
- | Prop | 타입 | 기본값 | 설명 |
32
- |------|------|--------|------|
33
- | `theme` | `SemanticTheme` | `"base"` | 색상 테마 |
34
-
35
- `<div>` HTML 속성을 모두 상속한다.
36
-
37
- ---
38
-
39
- ## Icon
40
-
41
- Tabler Icons 래퍼.
42
-
43
- ```tsx
44
- import { Icon } from "@simplysm/solid";
45
- import { IconUser, IconSettings } from "@tabler/icons-solidjs";
46
-
47
- <Icon icon={IconUser} size="1.5em" />
48
- <Icon icon={IconSettings} size={24} />
49
- ```
50
-
51
- | Prop | 타입 | 기본값 | 설명 |
52
- |------|------|--------|------|
53
- | `icon` | `Component<TablerIconProps>` | (필수) | Tabler 아이콘 컴포넌트 |
54
- | `size` | `string \| number` | `"1.25em"` | 아이콘 크기 |
55
-
56
- Tabler `IconProps`의 나머지 속성(`class`, `color` 등)을 모두 상속한다.
57
-
58
- ---
59
-
60
- ## Link
61
-
62
- 테마 색상의 링크 컴포넌트.
63
-
64
- ```tsx
65
- import { Link } from "@simplysm/solid";
66
-
67
- <Link href="/users">사용자 목록</Link>
68
- <Link theme="danger" onClick={handleDelete}>삭제</Link>
69
- <Link disabled>비활성 링크</Link>
70
- ```
71
-
72
- | Prop | 타입 | 기본값 | 설명 |
73
- |------|------|--------|------|
74
- | `theme` | `SemanticTheme` | `"primary"` | 색상 테마 |
75
- | `disabled` | `boolean` | `false` | 비활성화 |
76
-
77
- `<a>` HTML 속성을 모두 상속한다.
78
-
79
- ---
80
-
81
- ## Tag
82
-
83
- 테마 색상의 태그/배지.
84
-
85
- ```tsx
86
- import { Tag } from "@simplysm/solid";
87
-
88
- <Tag>기본</Tag>
89
- <Tag theme="primary">Primary</Tag>
90
- <Tag theme="success">완료</Tag>
91
- <Tag theme="danger">긴급</Tag>
92
- ```
93
-
94
- | Prop | 타입 | 기본값 | 설명 |
95
- |------|------|--------|------|
96
- | `theme` | `SemanticTheme` | `"base"` | 색상 테마 |
97
-
98
- `<span>` HTML 속성을 모두 상속한다.
99
-
100
- ---
101
-
102
- ## Barcode
103
-
104
- 바코드/QR 코드 생성 (bwip-js 기반).
105
-
106
- ```tsx
107
- import { Barcode } from "@simplysm/solid";
108
-
109
- <Barcode type="qrcode" value="https://example.com" />
110
- <Barcode type="code128" value="1234567890" />
111
- <Barcode type="ean13" value="4006381333931" />
112
- ```
113
-
114
- | Prop | 타입 | 설명 |
115
- |------|------|------|
116
- | `type` | `BarcodeType` | 바코드 타입 (필수). `"qrcode"`, `"code128"`, `"ean13"` 등 100+ 타입 |
117
- | `value` | `string` | 바코드 값 |
118
-
119
- `<div>` HTML 속성을 모두 상속한다.
120
-
121
- ---
122
-
123
- ## Echarts
124
-
125
- ECharts 차트 래퍼. 자동 리사이즈, 로딩 상태 지원. `echarts` peer dependency 필요.
126
-
127
- ```tsx
128
- import { Echarts } from "@simplysm/solid";
129
-
130
- <Echarts
131
- option={{
132
- xAxis: { type: "category", data: ["Mon", "Tue", "Wed"] },
133
- yAxis: { type: "value" },
134
- series: [{ data: [120, 200, 150], type: "bar" }],
135
- }}
136
- busy={loading()}
137
- />
138
- ```
139
-
140
- | Prop | 타입 | 설명 |
141
- |------|------|------|
142
- | `option` | `EChartsOption` | ECharts 옵션 (필수) |
143
- | `busy` | `boolean` | 로딩 상태 (`showLoading`/`hideLoading`) |
144
-
145
- `<div>` HTML 속성을 모두 상속한다. 내부적으로 SVG 렌더러를 사용하며, 컨테이너 크기 변경 시 자동 리사이즈한다.
146
-
147
- ---
148
-
149
- ## Dialog
150
-
151
- 모달/플로팅 다이얼로그. 리사이즈, 드래그, z-index 자동 관리.
152
-
153
- ```tsx
154
- import { Dialog } from "@simplysm/solid";
155
-
156
- <Dialog open={isOpen()} onOpenChange={setIsOpen} width="600px" resizable draggable>
157
- <Dialog.Header>제목</Dialog.Header>
158
- <div>내용</div>
159
- <Dialog.Action>
160
- <Button onClick={() => setIsOpen(false)}>닫기</Button>
161
- </Dialog.Action>
162
- </Dialog>
163
- ```
164
-
165
- | Prop | 타입 | 기본값 | 설명 |
166
- |------|------|--------|------|
167
- | `open` | `boolean` | | 열림 상태 |
168
- | `onOpenChange` | `(v: boolean) => void` | | 상태 콜백 |
169
- | `mode` | `"float" \| "fill"` | `"float"` | 모드 |
170
- | `resizable` | `boolean` | `false` | 리사이즈 가능 |
171
- | `draggable` | `boolean` | `false` | 드래그 가능 |
172
- | `width` | `string` | | 너비 |
173
- | `height` | `string` | | 높이 |
174
- | `closeOnEscape` | `boolean` | `true` | ESC 닫기 |
175
- | `beforeClose` | `() => boolean` | | 닫기 전 확인 (false 반환 시 취소) |
176
-
177
- ### 서브 컴포넌트
178
-
179
- | 컴포넌트 | 설명 |
180
- |----------|------|
181
- | `Dialog.Header` | 다이얼로그 헤더 (닫기 버튼 포함) |
182
- | `Dialog.Action` | 하단 액션 영역 |
183
-
184
- ### 프로그래밍 방식 다이얼로그
185
-
186
- ```tsx
187
- const dialog = useDialog();
188
-
189
- const result = await dialog.show(MyComponent, { data: "value" }, {
190
- header: "제목",
191
- width: "500px",
192
- resizable: true,
193
- });
194
- ```
195
-
196
- ---
197
-
198
- ## Dropdown
199
-
200
- 팝업 메뉴/드롭다운.
201
-
202
- ```tsx
203
- import { Dropdown } from "@simplysm/solid";
204
-
205
- <Dropdown>
206
- <Dropdown.Trigger>
207
- <Button>메뉴</Button>
208
- </Dropdown.Trigger>
209
- <Dropdown.Content>
210
- <div>메뉴 항목 1</div>
211
- <div>메뉴 항목 2</div>
212
- </Dropdown.Content>
213
- </Dropdown>
214
- ```
215
-
216
- | Prop | 타입 | 기본값 | 설명 |
217
- |------|------|--------|------|
218
- | `open` | `boolean` | | 열림 상태 |
219
- | `onOpenChange` | `(v: boolean) => void` | | 상태 콜백 |
220
- | `position` | `{ x: number; y: number }` | | 절대 위치 (컨텍스트 메뉴용) |
221
- | `maxHeight` | `number` | `300` | 최대 높이 (px) |
222
- | `disabled` | `boolean` | `false` | 비활성화 |
223
- | `keyboardNav` | `boolean` | `false` | 키보드 네비게이션 (Select 등에서 사용) |
224
-
225
- ### 서브 컴포넌트
226
-
227
- | 컴포넌트 | 설명 |
228
- |----------|------|
229
- | `Dropdown.Trigger` | 드롭다운 트리거 |
230
- | `Dropdown.Content` | 드롭다운 콘텐츠 |
231
-
232
- ---
233
-
234
- ## Collapse
235
-
236
- 접기/펼치기 (아코디언).
237
-
238
- ```tsx
239
- import { Collapse } from "@simplysm/solid";
240
-
241
- <Button aria-expanded={expanded()} onClick={() => setExpanded(!expanded())}>
242
- 토글
243
- </Button>
244
- <Collapse open={expanded()}>
245
- <div>접힌 내용</div>
246
- </Collapse>
247
- ```
248
-
249
- | Prop | 타입 | 기본값 | 설명 |
250
- |------|------|--------|------|
251
- | `open` | `boolean` | `false` | 열림 상태 |
252
-
253
- `<div>` HTML 속성을 모두 상속한다. 높이 애니메이션이 자동 적용된다.
254
-
255
- ---
256
-
257
- ## Tabs
258
-
259
- 탭 전환.
260
-
261
- ```tsx
262
- import { Tabs } from "@simplysm/solid";
263
-
264
- <Tabs value={tab()} onValueChange={setTab}>
265
- <Tabs.Tab value="info">정보</Tabs.Tab>
266
- <Tabs.Tab value="settings">설정</Tabs.Tab>
267
- </Tabs>
268
- ```
269
-
270
- | Prop (Tabs) | 타입 | 설명 |
271
- |------------|------|------|
272
- | `value` | `string` | 선택된 탭 값 |
273
- | `onValueChange` | `(v: string) => void` | 변경 콜백 |
274
- | `size` | `ComponentSize` | 크기 |
275
-
276
- | Prop (Tabs.Tab) | 타입 | 설명 |
277
- |-----------------|------|------|
278
- | `value` | `string` | 탭 식별 값 |
279
- | `disabled` | `boolean` | 비활성화 |
280
-
281
- ---
282
-
283
- ## Notification
284
-
285
- 알림 시스템. `NotificationProvider`로 감싸고 `useNotification()` 훅으로 사용.
286
-
287
- ```tsx
288
- import { NotificationProvider, useNotification, NotificationBell, NotificationBanner } from "@simplysm/solid";
289
-
290
- // 프로바이더 설정
291
- <NotificationProvider>
292
- <NotificationBanner />
293
- <NotificationBell />
294
- <App />
295
- </NotificationProvider>
296
-
297
- // 사용
298
- const noti = useNotification();
299
-
300
- noti.success("저장 완료", "데이터가 성공적으로 저장되었습니다.");
301
- noti.danger("오류", "서버 연결에 실패했습니다.");
302
- noti.info("안내", "새 버전이 있습니다.");
303
- noti.warning("경고", "저장되지 않은 변경사항이 있습니다.");
304
-
305
- // 에러 자동 처리
306
- noti.error(err, "작업 실패");
307
-
308
- // 업데이트
309
- const id = noti.info("업로드 중...");
310
- noti.update(id, { message: "업로드 완료!" });
311
-
312
- // 액션 버튼 포함 알림
313
- noti.info("업데이트 가능", "새 버전이 있습니다.", {
314
- action: {
315
- label: "새로고침",
316
- onClick: () => window.location.reload(),
317
- },
318
- });
319
-
320
- // 읽음 처리
321
- noti.markAsRead(id);
322
- noti.markAllAsRead();
323
- noti.clear();
324
- ```
325
-
326
- ---
327
-
328
- ## Busy
329
-
330
- 로딩 오버레이. 중첩 호출 지원.
331
-
332
- ```tsx
333
- import { BusyProvider, useBusy, BusyContainer } from "@simplysm/solid";
334
-
335
- <BusyProvider variant="spinner">
336
- <App />
337
- </BusyProvider>
338
-
339
- const busy = useBusy();
340
-
341
- busy.show("로딩 중...");
342
- // ... 작업 ...
343
- busy.hide();
344
-
345
- // 프로그레스 바
346
- busy.show("업로드 중...");
347
- busy.setProgress(50); // 50%
348
- busy.setProgress(100);
349
- busy.hide();
350
- ```
351
-
352
- ### BusyContainer
353
-
354
- 로컬 영역에 로딩 오버레이를 표시한다.
355
-
356
- ```tsx
357
- <BusyContainer busy={isLoading()} variant="bar">
358
- <div>컨텐츠</div>
359
- </BusyContainer>
360
- ```
361
-
362
- ---
363
-
364
- ## Progress
365
-
366
- 프로그레스 바.
367
-
368
- ```tsx
369
- import { Progress } from "@simplysm/solid";
370
-
371
- <Progress value={progress()} />
372
- <Progress value={75} theme="success" />
373
-
374
- // 커스텀 콘텐츠
375
- <Progress value={50} theme="primary" size="lg">
376
- <span>50% 완료</span>
377
- </Progress>
378
- ```
379
-
380
- | Prop | 타입 | 기본값 | 설명 |
381
- |------|------|--------|------|
382
- | `value` | `number` | (필수) | 진행률 (0-100) |
383
- | `theme` | `SemanticTheme` | `"primary"` | 색상 테마 |
384
- | `size` | `ComponentSize` | `"md"` | 크기 |
385
- | `inset` | `boolean` | `false` | 테두리 없음 |
386
-
387
- `<div>` HTML 속성을 모두 상속한다. children이 있으면 퍼센트 텍스트 대신 커스텀 콘텐츠를 표시한다.
388
-
389
- ---
390
-
391
- ## Print
392
-
393
- 인쇄 기능. `PrintProvider`로 감싸고 `usePrint()` 훅으로 사용.
394
-
395
- ```tsx
396
- import { PrintProvider, usePrint } from "@simplysm/solid";
397
-
398
- <PrintProvider>
399
- <App />
400
- </PrintProvider>
401
-
402
- const print = usePrint();
403
- // print 호출로 인쇄 다이얼로그 표시
404
- ```