@nurihaus/web-design-system 3.2.0 → 3.4.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.
Files changed (91) hide show
  1. package/README.md +36 -0
  2. package/dist/ai/components.md +123 -12
  3. package/dist/ai/tokens.md +2 -0
  4. package/dist/avatar.js +5 -5
  5. package/dist/bottom-nav.js +22 -8
  6. package/dist/breadcrumb.js +25 -10
  7. package/dist/check-box.js +24 -8
  8. package/dist/chip-group.js +21 -7
  9. package/dist/{chunk-563.js → chunk-1563.js} +26 -13
  10. package/dist/{chunk-657.js → chunk-1657.js} +2 -2
  11. package/dist/{chunk-777.js → chunk-2777.js} +2 -2
  12. package/dist/{chunk-558.js → chunk-4558.js} +2 -2
  13. package/dist/chunk-4560.js +77 -0
  14. package/dist/{chunk-917.js → chunk-4917.js} +2 -2
  15. package/dist/{chunk-77.js → chunk-5077.js} +2 -2
  16. package/dist/{chunk-149.js → chunk-6149.js} +2 -2
  17. package/dist/{chunk-302.js → chunk-6302.js} +2 -2
  18. package/dist/{chunk-364.js → chunk-6364.js} +2 -2
  19. package/dist/{chunk-713.js → chunk-6713.js} +2 -2
  20. package/dist/{chunk-298.js → chunk-7298.js} +2 -2
  21. package/dist/{chunk-653.js → chunk-7653.js} +7 -3
  22. package/dist/{chunk-739.js → chunk-7739.js} +2 -2
  23. package/dist/{chunk-309.js → chunk-8690.js} +2 -2
  24. package/dist/{chunk-933.js → chunk-8933.js} +2 -2
  25. package/dist/chunk-910.js +23 -10
  26. package/dist/{chunk-387.js → chunk-9387.js} +2 -2
  27. package/dist/{chunk-436.js → chunk-9436.js} +2 -2
  28. package/dist/{chunk-976.js → chunk-9976.js} +3 -3
  29. package/dist/collapsible-menu.js +25 -12
  30. package/dist/components/badge/badge-props.d.ts +4 -4
  31. package/dist/components/badge/badge.stories.d.ts +1 -1
  32. package/dist/components/bottom-nav/bottom-nav-type.d.ts +5 -2
  33. package/dist/components/breadcrumb/breadcrumb-type.d.ts +2 -1
  34. package/dist/components/button/button-props.d.ts +2 -2
  35. package/dist/components/button/button-type.d.ts +2 -1
  36. package/dist/components/button/button.stories.d.ts +1 -1
  37. package/dist/components/check-box/check-box-type.d.ts +2 -1
  38. package/dist/components/chip-group/chip-group-type.d.ts +2 -1
  39. package/dist/components/collapsible-menu/collapsible-menu-type.d.ts +2 -1
  40. package/dist/components/drawer/drawer-type.d.ts +2 -1
  41. package/dist/components/drop-down/drop-down-type.d.ts +2 -1
  42. package/dist/components/icon/icon-paths.d.ts +4 -0
  43. package/dist/components/icon/icon-props.d.ts +2 -2
  44. package/dist/components/icon/icon.stories.d.ts +2 -2
  45. package/dist/components/logging/log-context.d.ts +9 -0
  46. package/dist/components/logging/logging-type.d.ts +25 -0
  47. package/dist/components/logging/logging.d.ts +5 -0
  48. package/dist/components/logging/logging.stories.d.ts +18 -0
  49. package/dist/components/modal/modal-type.d.ts +2 -1
  50. package/dist/components/pagination/pagination-type.d.ts +2 -1
  51. package/dist/components/radio/radio-type.d.ts +3 -1
  52. package/dist/components/radio/radio.d.ts +2 -1
  53. package/dist/components/radio/radio.stories.d.ts +1 -1
  54. package/dist/components/switch/switch-type.d.ts +2 -1
  55. package/dist/components/table/table-type.d.ts +2 -1
  56. package/dist/components/tabs/tabs-type.d.ts +2 -1
  57. package/dist/components/text-area/text-area-type.d.ts +2 -1
  58. package/dist/components/text-field/text-field-type.d.ts +2 -1
  59. package/dist/components/toast/toast-type.d.ts +2 -1
  60. package/dist/components/toast/toast.stories.d.ts +3 -1
  61. package/dist/components/tooltip/tooltip-type.d.ts +2 -1
  62. package/dist/components.css +48 -0
  63. package/dist/cta-button.js +35 -20
  64. package/dist/data-table.js +19 -7
  65. package/dist/drawer.js +23 -9
  66. package/dist/drop-down.js +25 -9
  67. package/dist/helpers/hooks/useTrack.d.ts +3 -0
  68. package/dist/icon-text-badge.js +12 -10
  69. package/dist/icon-text-option-badge.js +6 -6
  70. package/dist/icon.js +5 -5
  71. package/dist/index.d.ts +2 -0
  72. package/dist/index.js +438 -81
  73. package/dist/loading.js +6 -6
  74. package/dist/logging.js +147 -0
  75. package/dist/modal-with-double-button.js +14 -12
  76. package/dist/modal.js +39 -26
  77. package/dist/option-badge.js +12 -10
  78. package/dist/pagination.js +23 -9
  79. package/dist/radio.js +24 -10
  80. package/dist/skeleton.js +4 -4
  81. package/dist/step-progress.js +3 -3
  82. package/dist/styles.css +42 -0
  83. package/dist/switch.js +24 -8
  84. package/dist/tabs.js +22 -6
  85. package/dist/text-area.js +30 -8
  86. package/dist/text-field.js +31 -9
  87. package/dist/text.js +5 -5
  88. package/dist/toast.js +32 -15
  89. package/dist/tokens.css +2 -0
  90. package/dist/tooltip.js +33 -18
  91. package/package.json +5 -1
package/README.md CHANGED
@@ -118,6 +118,42 @@ npm run tokens # figma.json → tokens/generated/{tokens.css, *.ts}
118
118
 
119
119
  새 서비스가 다른 의미 토큰 값(버튼 색 등)을 써야 하면 `tokens/figma.json` 에 `semantic_{이름}` 세트를 추가하고 `npm run tokens` 를 돌린다. `<html data-ds-theme="{이름}">` 로 고르는 테마가 생긴다. 자세한 규칙은 `docs/tokens.md`.
120
120
 
121
+ ## 사용 로그
122
+
123
+ 컴포넌트가 사용자 상호작용을 이벤트로 내보내고, 어디로 보낼지는 앱이 정한다. 디자인시스템은 로그 수집기를 모른다.
124
+
125
+ 앱 루트에 `LogProvider` 를 한 번 둔다. `onEvent` 가 받은 이벤트를 앱의 로그 수집기로 보낸다.
126
+
127
+ ```tsx
128
+ import { LogProvider } from '@nurihaus/web-design-system/logging';
129
+
130
+ export default function App({ children }) {
131
+ return <LogProvider onEvent={(event) => console.log(event)}>{children}</LogProvider>;
132
+ }
133
+ ```
134
+
135
+ 컴포넌트에 `track` 을 준다. 누르면 `{ component: 'CTAButton', action: 'click', track: 'report/download', props: { format: 'csv' }, timestamp }` 가 `onEvent` 로 간다.
136
+
137
+ ```tsx
138
+ <CTAButton text='리포트 받기' track='report/download' trackProps={{ format: 'csv' }} />
139
+ ```
140
+
141
+ `track` 을 받는 컴포넌트는 CTAButton · DataTable(`click`), Modal · Drawer(`open` · `close`), Tabs · DropDown · ChipGroup · Radio · Checkbox · Switch · Pagination · TextField · TextArea(`change`), BottomNav · Breadcrumb · CollapsibleMenu(`navigate`), Toast · Tooltip(`show`) 다. `value` 에는 탭 id · 칩 id · 옵션 value 처럼 개발자가 정한 id 만 들어간다. TextField · TextArea 는 포커스가 빠질 때 값이 바뀌었으면 값 없이 `change` 를 한 번 보낸다. `LogProvider` 가 없거나 `track` 을 주지 않으면 아무것도 보내지 않는다.
142
+
143
+ 컴포넌트 밖의 로그는 `useLog` 로 남긴다.
144
+
145
+ ```tsx
146
+ import { useEffect } from 'react';
147
+
148
+ import { useLog } from '@nurihaus/web-design-system/logging';
149
+
150
+ const ReportPage = () => {
151
+ const log = useLog();
152
+ useEffect(() => log({ component: 'ReportPage', action: 'view', track: 'report/view' }), [log]);
153
+ // …
154
+ };
155
+ ```
156
+
121
157
  ## AI 설명서
122
158
 
123
159
  배포물의 `dist/ai/` 에 쓰는 쪽 AI 가 읽는 설명서가 들어 있다.
@@ -30,6 +30,26 @@ import '@nurihaus/web-design-system/components.css';
30
30
 
31
31
  **Tooltip 이 여러 개면 `TooltipProvider` 로 감싼다.** 앱 루트에 한 번 두면 된다. 조건이 맞을 때만 띄우려면 `open` 을 제어하지 말고 `disabled` 를 쓴다.
32
32
 
33
+ **사용 로그는 `track` 으로 남긴다.** 앱 루트에 `LogProvider` 를 한 번 두고 `onEvent` 에서 로그 수집기로 보낸다. 컴포넌트에 `track="report/download"` 처럼 개발자가 정한 이름을 주면 아래 상호작용이 이벤트로 나간다. `component` 는 컴포넌트의 displayName 이다(Checkbox 는 `'CheckBox'`).
34
+
35
+ | 컴포넌트 | 보내는 때 | action | value |
36
+ | --- | --- | --- | --- |
37
+ | CTAButton | 누를 때 | `click` | 없음 |
38
+ | DataTable | `onClickRow` 가 있는 헤더 칸을 누를 때 | `click` | 그 칸의 `id` |
39
+ | Modal · Drawer | 열고 닫을 때 | `open` · `close` | 없음 |
40
+ | Tabs · DropDown · ChipGroup · Radio | 고를 때 | `change` | 탭 id · 옵션 value · 칩 id · 선택지 id |
41
+ | Checkbox · Switch | 켜고 끌 때 | `change` | `'on'` · `'off'` |
42
+ | Pagination | 페이지가 바뀔 때 | `change` | 페이지 번호(문자열) |
43
+ | TextField · TextArea | 포커스가 빠질 때, 포커스를 받을 때와 값이 다르면 한 번 | `change` | 없음 |
44
+ | BottomNav | 탭을 누를 때 | `navigate` | 탭 id |
45
+ | Breadcrumb | 현재 위치가 아닌 링크를 누를 때 | `navigate` | 항목 `id` |
46
+ | CollapsibleMenu | 링크·버튼 항목을 고를 때. 그룹 여닫기는 보내지 않는다 | `navigate` | 항목 `key` |
47
+ | Toast · Tooltip | 뜰 때 | `show` | 없음 |
48
+
49
+ `value` 에는 개발자가 정한 id 만 들어가고 사용자가 입력한 글자는 들어가지 않는다. TextField · TextArea 가 값을 싣지 않는 것도 그래서다. 더 붙일 값은 `trackProps` 로 준다. `LogProvider` 가 없거나 `track` 이 없으면 아무것도 보내지 않는다. 컴포넌트 밖의 로그(화면 진입 등)는 `useLog` 를 쓴다.
50
+
51
+ Avatar · OptionBadge · IconTextBadge · IconTextOptionBadge · Skeleton · Text · Icon · StepProgress · Spinner · InlineLoading · OverlayLoading 은 상호작용 핸들러가 없어 `track` 을 받지 않는다. ModalWithDoubleButton 은 `left` · `right` 가 CTAButton props 라 거기에 `track` 을 준다.
52
+
33
53
  **없는 것은 지어내지 않는다.** 이 문서 끝의 "아직 없는 것" 표에 있는 컴포넌트는 없다. 없는 prop · variant · 토큰 이름도 만들지 않는다. 틀린 variant 나 size 값은 타입 오류가 난다.
34
54
 
35
55
  ## 목록
@@ -66,6 +86,7 @@ import '@nurihaus/web-design-system/components.css';
66
86
  - [BottomNav](#bottomnav)
67
87
  - [StepProgress](#stepprogress)
68
88
  - [ChipGroup](#chipgroup)
89
+ - [LogProvider](#logprovider)
69
90
 
70
91
  ## Avatar
71
92
 
@@ -102,12 +123,15 @@ import { CTAButton } from '@nurihaus/web-design-system/cta-button'; // 이 컴
102
123
  import { CTAButton } from '@nurihaus/web-design-system'; // 루트. 첫 로드 JS 가 커진다
103
124
  ```
104
125
 
105
- **언제 쓴다.** 저장, 확인, 다음 단계처럼 사용자가 실행하는 동작 버튼에 쓴다. `variant`로 강조 단계를 고르고, `loading`이 true면 `text` 대신 Spinner가 표시된다.
126
+ **언제 쓴다.** 저장, 확인, 다음 단계처럼 사용자가 실행하는 동작 버튼에 쓴다. `variant`로 강조 단계를 고르고, `loading`이 true면 `text` 대신 Spinner가 표시된다. Google·Apple·Facebook 로그인 버튼은 `variant="social"`(흰 바탕·검정 글자, 공급자 가이드)에 공급자 로고를 `leftIcon`으로 준다.
106
127
 
107
128
  **쓰지 않는다.** 확인과 취소 두 버튼을 가진 대화상자는 버튼을 직접 배치하지 말고 ModalWithDoubleButton을 쓴다. 화면 안의 패널 전환은 Tabs, 사이드 메뉴 항목은 CollapsibleMenu를 쓴다.
108
129
 
109
130
  ```tsx
110
- <CTAButton variant="primary" size="m" text="저장" onClick={() => {}} />
131
+ <>
132
+ <CTAButton variant="primary" size="m" text="저장" onClick={() => {}} />
133
+ <CTAButton variant="social" size="l" text="Google로 계속하기" leftIcon={<img src="/icons/google.svg" alt="" />} />
134
+ </>
111
135
  ```
112
136
 
113
137
  ### props
@@ -115,11 +139,13 @@ import { CTAButton } from '@nurihaus/web-design-system'; // 루트.
115
139
  | prop | 타입 | 필수 | 기본값 |
116
140
  | --- | --- | --- | --- |
117
141
  | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | | `'m'` |
142
+ | `track` | `string` | | |
118
143
  | `text` | `ReactNode` | 예 | |
119
- | `variant` | `'neutral' \| 'primary' \| 'outlined' \| 'secondary' \| 'ghost' \| 'confirm'` | | `'primary'` |
144
+ | `variant` | `'neutral' \| 'primary' \| 'outlined' \| 'secondary' \| 'ghost' \| 'confirm' \| 'social'` | | `'primary'` |
120
145
  | `leftIcon` | `ReactNode` | | |
121
146
  | `rightIcon` | `ReactNode` | | |
122
147
  | `loading` | `boolean` | | |
148
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
123
149
 
124
150
  이 밖에 React·HTML 기본 속성 276개를 받는다.
125
151
 
@@ -130,19 +156,23 @@ import { OptionBadge } from '@nurihaus/web-design-system/option-badge'; // 이
130
156
  import { OptionBadge } from '@nurihaus/web-design-system'; // 루트. 첫 로드 JS 가 커진다
131
157
  ```
132
158
 
133
- **언제 쓴다.** 상태값이나 분류처럼 짧은 값 하나(`option`)를 라벨로 보여줄 때 쓴다. `variant`로 색을 고른다(`neutral`·`primary`·`danger`·`outlined`). 색 prop 은 없다. `tooltip`을 주면 마우스를 올렸을 때 설명이 뜬다.
159
+ **언제 쓴다.** 상태값이나 분류처럼 짧은 값 하나(`option`)를 라벨로 보여줄 때 쓴다. `variant`로 색을 고른다(`neutral`·`primary`·`danger`·`outlined`). 색 prop 은 없다. `tooltip`을 주면 마우스를 올렸을 때 설명이 뜬다. 버튼 같은 대상의 모서리에 늘 떠 있는 말풍선(예: 로그인 버튼의 "최근 사용")은 `variant="callout"`이다 — 꼬리가 아래 왼쪽을 가리키고, 자리(`position: absolute` 와 위치)는 쓰는 쪽이 `className`으로 정한다.
134
160
 
135
161
  **쓰지 않는다.** 아이콘이 함께 필요하면 IconTextBadge를, 아이콘과 텍스트 오른쪽에 수치 같은 부가 값까지 붙여야 하면 IconTextOptionBadge를 쓴다. 클릭 동작이 필요한 요소에는 CTAButton을 쓴다.
136
162
 
137
163
  ```tsx
138
- <OptionBadge option="진행 중" variant="primary" size="s" width="fit-content" />
164
+ <>
165
+ <OptionBadge option="진행 중" variant="primary" size="s" width="fit-content" />
166
+ {/* 자리는 쓰는 쪽 CSS: 감싼 요소 position: relative, .last-used { position: absolute; top: -12px; right: 14px; } */}
167
+ <OptionBadge option="최근 사용" variant="callout" size="xs" width="fit-content" className="last-used" />
168
+ </>
139
169
  ```
140
170
 
141
171
  ### props
142
172
 
143
173
  | prop | 타입 | 필수 | 기본값 |
144
174
  | --- | --- | --- | --- |
145
- | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined'` | | `'neutral'` |
175
+ | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined' \| 'callout'` | | `'neutral'` |
146
176
  | `width` | `string \| number` | | `'100%'` |
147
177
  | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | | `'xl'` |
148
178
  | `option` | `ReactNode` | 예 | |
@@ -178,7 +208,7 @@ import { IconTextBadge } from '@nurihaus/web-design-system'; // 루
178
208
 
179
209
  | prop | 타입 | 필수 | 기본값 |
180
210
  | --- | --- | --- | --- |
181
- | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined'` | | `'neutral'` |
211
+ | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined' \| 'callout'` | | `'neutral'` |
182
212
  | `width` | `string \| number` | | `'100%'` |
183
213
  | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | | `'xl'` |
184
214
  | `icon` | `ReactNode` | 예 | |
@@ -215,7 +245,7 @@ import { IconTextOptionBadge } from '@nurihaus/web-design-system'; /
215
245
 
216
246
  | prop | 타입 | 필수 | 기본값 |
217
247
  | --- | --- | --- | --- |
218
- | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined'` | | `'neutral'` |
248
+ | `variant` | `'neutral' \| 'primary' \| 'danger' \| 'outlined' \| 'callout'` | | `'neutral'` |
219
249
  | `width` | `string \| number` | | `'100%'` |
220
250
  | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | | `'xl'` |
221
251
  | `icon` | `ReactNode` | 예 | |
@@ -235,6 +265,8 @@ import { DataTable } from '@nurihaus/web-design-system'; // 루트.
235
265
 
236
266
  **언제 쓴다.** 여러 레코드를 열 단위로 나열하는 목록 화면에 쓴다. 이름과 달리 `rows`는 헤더 열 정의(`id`, 헤더 내용)이고 `columns`는 데이터 행 배열이며, 각 데이터 행은 `rows`의 모든 `id`를 키로 가진다. 열 너비는 셀 내용의 너비를 따르므로 같은 열의 헤더와 셀 내용에 같은 너비를 준다.
237
267
 
268
+ `track`을 주면 `onClickRow`가 있는 `rows` 항목(헤더 칸)을 누를 때 `click`과 그 `id`를 `value`에 담아 사용 로그로 보낸다. `onClickRow`가 없는 칸과 본문 셀은 보내지 않는다.
269
+
238
270
  **쓰지 않는다.** 정렬, 페이지네이션, 행 선택, 빈 상태 표시는 내장되어 있지 않으므로 데이터를 바깥에서 가공해 넘기고 빈 목록은 따로 그린다. 헤더는 위에 고정되고 `fixedRowsIndex`로 왼쪽 열을 고정할 수 있지만, 그 외의 표 동작이 필요하면 직접 만든다.
239
271
 
240
272
  ```tsx
@@ -264,6 +296,8 @@ import { DataTable } from '@nurihaus/web-design-system'; // 루트.
264
296
  | `rowHeight` | `number` | | `60` |
265
297
  | `cellHeight` | `number` | | |
266
298
  | `className` | `string` | | |
299
+ | `track` | `string` | | |
300
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
267
301
 
268
302
  이 밖에 React·HTML 기본 속성 2개를 받는다.
269
303
 
@@ -276,6 +310,8 @@ import { TextField } from '@nurihaus/web-design-system'; // 루트.
276
310
 
277
311
  **언제 쓴다.** 한 줄 텍스트를 입력받을 때 쓴다. 위 라벨(`title`), 아래 안내 문구(`helperText`), 좌우 아이콘을 함께 붙일 수 있고, `isError`가 true면 `helperText`가 오류 스타일로 바뀐다.
278
312
 
313
+ `track`을 주면 포커스가 빠질 때 값이 포커스를 받을 때와 다르면 `change`를 한 번 사용 로그로 보낸다. 값은 싣지 않는다. 사용자가 입력한 글자는 로그에 들어가지 않는다.
314
+
279
315
  **쓰지 않는다.** 여러 줄 입력은 지원하지 않는다(`<input>`만 렌더한다). 정해진 값 중에서 고르는 입력은 DropDown이나 Radio를 쓴다.
280
316
 
281
317
  ```tsx
@@ -297,11 +333,13 @@ import { TextField } from '@nurihaus/web-design-system'; // 루트.
297
333
  | `className` | `string` | | |
298
334
  | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | 예 | `'s'` |
299
335
  | `title` | `ReactNode` | | |
336
+ | `track` | `string` | | |
300
337
  | `name` | `string` | 예 | |
301
338
  | `value` | `string` | | |
302
339
  | `defaultValue` | `string` | | |
303
340
  | `leftIcon` | `ReactNode` | | |
304
341
  | `rightIcon` | `ReactNode` | | |
342
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
305
343
  | `width` | `string \| number` | 예 | `'100%'` |
306
344
  | `helperText` | `ReactNode` | | |
307
345
  | `isError` | `boolean` | | |
@@ -317,6 +355,8 @@ import { Radio } from '@nurihaus/web-design-system'; // 루트. 첫
317
355
 
318
356
  **언제 쓴다.** 몇 개의 선택지를 모두 펼쳐 보여주고 그중 하나만 고르게 할 때 쓴다. 선택 상태는 항상 부모가 가지므로 `onChange`에서 받은 id로 `selected`를 갱신해야 선택이 바뀐다.
319
357
 
358
+ `track`을 주면 선택지를 누를 때 `change`와 그 선택지 `id`를 `value`에 담아 사용 로그로 보낸다.
359
+
320
360
  **쓰지 않는다.** 여러 개를 동시에 고르면 Checkbox를 쓴다. 선택지가 많아 모두 펼치기 어려우면 DropDown을 쓴다.
321
361
 
322
362
  ```tsx
@@ -338,6 +378,8 @@ import { Radio } from '@nurihaus/web-design-system'; // 루트. 첫
338
378
  | `options` | `{ id: string; label: ReactNode; disabled?: boolean \| undefined; }[]` | 예 | |
339
379
  | `selected` | `string \| null` | | |
340
380
  | `onChange` | `((id: string \| null) => void)` | | |
381
+ | `track` | `string` | | |
382
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
341
383
 
342
384
  이 밖에 React·HTML 기본 속성 2개를 받는다.
343
385
 
@@ -350,6 +392,8 @@ import { Checkbox } from '@nurihaus/web-design-system'; // 루트.
350
392
 
351
393
  **언제 쓴다.** 동의 여부처럼 켜고 끄는 값 하나를 받거나, 목록의 항목을 각각 독립적으로 선택할 때 쓴다. `onChange`는 바뀐 체크 상태(boolean)를 받는다.
352
394
 
395
+ `track`을 주면 체크 상태가 바뀔 때마다 `change`와 `'on'`·`'off'`를 `value`에 담아 사용 로그로 보낸다. 이벤트의 `component`는 displayName 인 `'CheckBox'`다.
396
+
353
397
  **쓰지 않는다.** 여러 선택지 중 하나만 골라야 하면 Radio를, 목록에서 값 하나를 고르면 DropDown을 쓴다.
354
398
 
355
399
  ```tsx
@@ -368,6 +412,8 @@ import { Checkbox } from '@nurihaus/web-design-system'; // 루트.
368
412
  | `onChange` | `((checked: boolean) => void)` | | |
369
413
  | `id` | `string` | 예 | |
370
414
  | `disabled` | `boolean` | | |
415
+ | `track` | `string` | | |
416
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
371
417
 
372
418
  이 밖에 React·HTML 기본 속성 2개를 받는다.
373
419
 
@@ -380,6 +426,8 @@ import { Switch } from '@nurihaus/web-design-system'; // 루트. 첫
380
426
 
381
427
  **언제 쓴다.** 알림 켜기처럼 켜고 끄는 설정 하나를 바로 반영할 때 쓴다. `onChange`는 바뀐 켜짐 상태(boolean)를 받는다. `className`·`style`은 루트 버튼에 붙는다. `label`을 주지 않으면 `aria-label`로 이름을 준다.
382
428
 
429
+ `track`을 주면 켜짐 상태가 바뀔 때마다 `change`와 `'on'`·`'off'`를 `value`에 담아 사용 로그로 보낸다.
430
+
383
431
  **쓰지 않는다.** 제출 버튼을 눌러야 반영되는 폼 항목이나 동의 여부는 Checkbox를, 여러 선택지 중 하나는 Radio를 쓴다.
384
432
 
385
433
  ```tsx
@@ -393,10 +441,12 @@ import { Switch } from '@nurihaus/web-design-system'; // 루트. 첫
393
441
  | `className` | `string` | | |
394
442
  | `size` | `'s' \| 'm' \| 'l'` | | `'m'` |
395
443
  | `label` | `ReactNode` | | |
444
+ | `track` | `string` | | |
396
445
  | `disabled` | `boolean` | | |
397
446
  | `defaultChecked` | `boolean` | | |
398
447
  | `id` | `string` | 예 | |
399
448
  | `onChange` | `((checked: boolean) => void)` | | |
449
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
400
450
  | `checked` | `boolean` | | |
401
451
 
402
452
  이 밖에 React·HTML 기본 속성 270개를 받는다.
@@ -410,6 +460,8 @@ import { TextArea } from '@nurihaus/web-design-system'; // 루트.
410
460
 
411
461
  **언제 쓴다.** 메모·설명처럼 여러 줄 텍스트를 입력받을 때 쓴다. 위 라벨(`title`), 아래 안내 문구(`helperText`)를 함께 붙일 수 있고, `isError`가 true면 `helperText`가 오류 스타일로 바뀐다. 높이는 `rows`가 정하고 `size`는 글자 크기와 안쪽 여백만 바꾼다. `resize`는 `'vertical'`(기본)·`'none'` 중 고른다. `className`·`style`은 textarea를 감싸는 테두리 요소에 붙고, `ref`는 textarea 요소를 가리킨다.
412
462
 
463
+ `track`을 주면 포커스가 빠질 때 값이 포커스를 받을 때와 다르면 `change`를 한 번 사용 로그로 보낸다. 값은 싣지 않는다. 사용자가 입력한 글자는 로그에 들어가지 않는다.
464
+
413
465
  **쓰지 않는다.** 한 줄 입력은 TextField를 쓴다. 정해진 값 중에서 고르는 입력은 DropDown이나 Radio를 쓴다.
414
466
 
415
467
  ```tsx
@@ -423,9 +475,11 @@ import { TextArea } from '@nurihaus/web-design-system'; // 루트.
423
475
  | `className` | `string` | | |
424
476
  | `size` | `'s' \| 'm'` | | `'s'` |
425
477
  | `title` | `ReactNode` | | |
478
+ | `track` | `string` | | |
426
479
  | `name` | `string` | 예 | |
427
480
  | `value` | `string` | | |
428
481
  | `defaultValue` | `string` | | |
482
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
429
483
  | `width` | `string \| number` | | `'100%'` |
430
484
  | `resize` | `'none' \| 'vertical'` | | `'vertical'` |
431
485
  | `helperText` | `ReactNode` | | |
@@ -455,8 +509,10 @@ import { Toast } from '@nurihaus/web-design-system'; // 루트. 첫
455
509
  | `className` | `string` | | |
456
510
  | `style` | `CSSProperties` | | |
457
511
  | `title` | `ReactNode` | 예 | |
512
+ | `track` | `string` | | |
458
513
  | `onPause` | `(() => void)` | | |
459
514
  | `variant` | `'secondary' \| 'default' \| 'success' \| 'warning' \| 'error'` | | `'default'` |
515
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
460
516
  | `onResume` | `(() => void)` | | |
461
517
  | `open` | `boolean` | | |
462
518
  | `defaultOpen` | `boolean` | | |
@@ -503,6 +559,8 @@ import { Pagination } from '@nurihaus/web-design-system'; // 루트.
503
559
 
504
560
  **언제 쓴다.** 목록이나 검색 결과가 여러 페이지로 나뉘어 있고 사용자가 번호로 페이지를 고를 때 쓴다. `totalPages`는 필수다. 현재 페이지는 `page`(controlled)·`defaultPage`(uncontrolled)로 주고, `onPageChange`는 새 페이지 번호(1부터)를 받는다. 1과 마지막 페이지는 항상 보이고, 현재 페이지 양옆 `siblingCount`(기본 1)개를 보이며 사이가 벌어지면 `…`를 넣는다. `className`·`style`은 루트 `nav`에 붙는다. `aria-label`을 주면 nav 이름을 바꾼다(기본 "페이지 탐색").
505
561
 
562
+ `track`을 주면 페이지가 바뀔 때 `change`와 새 페이지 번호(문자열)를 `value`에 담아 사용 로그로 보낸다. 현재 페이지를 다시 누르면 보내지 않는다.
563
+
506
564
  **쓰지 않는다.** 스크롤로 계속 불러오는 목록이나 "더 보기" 버튼으로 이어 붙이는 목록에는 쓰지 않는다. 화면 안의 내용 영역을 바꾸는 탭 전환은 Tabs를 쓴다.
507
565
 
508
566
  ```tsx
@@ -514,7 +572,9 @@ import { Pagination } from '@nurihaus/web-design-system'; // 루트.
514
572
  | prop | 타입 | 필수 | 기본값 |
515
573
  | --- | --- | --- | --- |
516
574
  | `size` | `'s' \| 'm'` | | `'m'` |
575
+ | `track` | `string` | | |
517
576
  | `disabled` | `boolean` | | |
577
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
518
578
  | `page` | `number` | | |
519
579
  | `totalPages` | `number` | 예 | |
520
580
  | `defaultPage` | `number` | | |
@@ -562,6 +622,8 @@ import { Modal } from '@nurihaus/web-design-system'; // 루트. 첫
562
622
  | `onOpenChange` | `((open: boolean) => void)` | | |
563
623
  | `className` | `string` | | |
564
624
  | `style` | `CSSProperties` | | |
625
+ | `track` | `string` | | |
626
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
565
627
 
566
628
  이 밖에 React·HTML 기본 속성 2개를 받는다.
567
629
 
@@ -599,6 +661,8 @@ import { Drawer } from '@nurihaus/web-design-system'; // 루트. 첫
599
661
  | `onOpenChange` | `((open: boolean) => void)` | | |
600
662
  | `className` | `string` | | |
601
663
  | `style` | `CSSProperties` | | |
664
+ | `track` | `string` | | |
665
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
602
666
 
603
667
  이 밖에 React·HTML 기본 속성 2개를 받는다.
604
668
 
@@ -638,6 +702,8 @@ import { Breadcrumb } from '@nurihaus/web-design-system'; // 루트.
638
702
 
639
703
  **언제 쓴다.** 계층이 있는 화면에서 현재 위치와 상위 경로를 한 줄로 보여 줄 때 쓴다. `items`의 마지막 항목이 현재 위치라 링크가 아니고 `aria-current="page"`가 붙는다. `href`가 있는 항목은 `<a>` 링크로, `onItemClick`은 클릭한 항목의 `id`를 받는다. Next.js 나 React Router 안에서는 `linkComponent={Link}`를 넘겨 라우터 링크로 그린다. 넘기지 않으면 일반 `<a>`라 페이지가 새로 고쳐진다. `className`·`style`은 `nav` 루트에 붙는다.
640
704
 
705
+ `track`을 주면 링크 항목을 누를 때 `navigate`와 그 항목의 `id`를 `value`에 담아 사용 로그로 보낸다. 마지막(현재 위치) 항목은 링크가 아니라 보내지 않는다.
706
+
641
707
  **쓰지 않는다.** 같은 깊이의 화면을 오가는 데는 Tabs를, 사이드바 메뉴에는 CollapsibleMenu를 쓴다. 계층이 한 단계뿐이면 쓰지 않는다.
642
708
 
643
709
  ```tsx
@@ -661,6 +727,8 @@ import { Breadcrumb } from '@nurihaus/web-design-system'; // 루트.
661
727
  | `linkComponent` | `ElementType` | | |
662
728
  | `className` | `string` | | |
663
729
  | `style` | `CSSProperties` | | |
730
+ | `track` | `string` | | |
731
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
664
732
 
665
733
  이 밖에 React·HTML 기본 속성 2개를 받는다.
666
734
 
@@ -714,6 +782,8 @@ import { DropDown } from '@nurihaus/web-design-system'; // 루트.
714
782
  | `position` | `'popper' \| 'item-aligned'` | | |
715
783
  | `className` | `string` | | |
716
784
  | `style` | `CSSProperties` | | |
785
+ | `track` | `string` | | |
786
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
717
787
 
718
788
  이 밖에 React·HTML 기본 속성 2개를 받는다.
719
789
 
@@ -726,6 +796,8 @@ import { CollapsibleMenu } from '@nurihaus/web-design-system'; //
726
796
 
727
797
  **언제 쓴다.** 사이드바 같은 세로 내비게이션 메뉴에 쓴다. `children`이 있는 항목은 펼치고 접는 그룹이 되고, 없는 항목은 `href`가 있으면 링크, 없으면 버튼으로 렌더되며, `activeKey` 항목과 그 상위 그룹이 강조된다. 링크는 기본으로 `<a>`다. 라우터의 링크로 바꾸려면 `linkComponent`에 넘긴다. 받는 props는 `href`·`className`·`children`·`onClick`·`aria-current`·`aria-disabled`이고, 그대로 링크에 전달하면 된다.
728
798
 
799
+ `track`을 주면 링크·버튼 항목을 고를 때 `navigate`와 그 항목의 `key`를 `value`에 담아 사용 로그로 보낸다. 그룹을 펼치고 접는 것은 보내지 않는다.
800
+
729
801
  **쓰지 않는다.** 같은 화면 안에서 패널을 바꾸는 용도는 Tabs를 쓴다. 본문 콘텐츠를 접고 펼치는 아코디언 용도로는 쓰지 않는다(`<nav>`로 렌더된다). 값을 고르는 폼 입력은 DropDown을 쓴다.
730
802
 
731
803
  Next.js 에서는 `next/link` 의 `Link` 를 그대로 넘긴다.
@@ -770,6 +842,8 @@ import Link from 'next/link';
770
842
  | `linkComponent` | `ComponentType<CollapsibleMenuLinkProps>` | | |
771
843
  | `className` | `string` | | |
772
844
  | `style` | `CSSProperties` | | |
845
+ | `track` | `string` | | |
846
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
773
847
 
774
848
  이 밖에 React·HTML 기본 속성 2개를 받는다.
775
849
 
@@ -813,6 +887,8 @@ import { Tooltip } from '@nurihaus/web-design-system'; // 루트.
813
887
 
814
888
  **언제 쓴다.** 아이콘이나 짧은 라벨에 마우스를 올렸을 때 짧은 설명을 띄울 때 쓴다. `trigger`에는 DOM 요소 하나(예: `<span>`)를 넘기고 `direction`으로 뜨는 방향을 고른다. 조건이 맞을 때만 띄우려면 `open`을 제어하지 말고 `disabled`를 쓴다(예: 사이드바가 접혔을 때만 `disabled={!collapsed}`). `disabled`이면 `trigger`만 그려 툴팁이 열린 채 남지 않는다.
815
889
 
890
+ `track`을 주면 툴팁이 열릴 때 `show`를 사용 로그로 보낸다. 닫힐 때와 `disabled`일 때는 보내지 않는다.
891
+
816
892
  **쓰지 않는다.** 툴팁 안에 링크나 버튼처럼 클릭할 내용을 넣지 않는다. 툴팁 위로 마우스를 옮기면 닫힌다. 배지에 설명을 붙일 때는 OptionBadge, IconTextBadge의 `tooltip` prop을 쓴다.
817
893
 
818
894
  ```tsx
@@ -832,6 +908,8 @@ import { Tooltip } from '@nurihaus/web-design-system'; // 루트.
832
908
  | `onOpenChange` | `((open: boolean) => void)` | | |
833
909
  | `delayDuration` | `number` | | |
834
910
  | `disableHoverableContent` | `boolean` | | |
911
+ | `track` | `string` | | |
912
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
835
913
 
836
914
  이 밖에 React·HTML 기본 속성 2개를 받는다.
837
915
 
@@ -895,6 +973,8 @@ import { Tabs } from '@nurihaus/web-design-system'; // 루트. 첫
895
973
  | `onValueChange` | `((id: TabsValue) => void)` | | |
896
974
  | `className` | `string` | | |
897
975
  | `style` | `CSSProperties` | | |
976
+ | `track` | `string` | | |
977
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
898
978
 
899
979
  이 밖에 React·HTML 기본 속성 2개를 받는다.
900
980
 
@@ -1035,7 +1115,7 @@ import { Icon } from '@nurihaus/web-design-system/icon'; // 이 컴포넌트
1035
1115
  import { Icon } from '@nurihaus/web-design-system'; // 루트. 첫 로드 JS 가 커진다
1036
1116
  ```
1037
1117
 
1038
- **언제 쓴다.** 화면에 아이콘을 그릴 때 쓴다. 모양은 Phosphor(MIT) 에서 고른 것만 있고, `name` 으로 고른다. 색은 글자색(`currentColor`)을 따르므로 감싼 요소의 `color` 로 바꾼다. 꺼진 상태는 선(`weight="regular"`, 기본), 켜진 상태나 강조는 채움(`weight="fill"`)을 쓴다. 크기는 `s`(18) · `m`(20) · `l`(24, 기본). `className`·`style` 은 `<svg>` 에 붙는다.
1118
+ **언제 쓴다.** 화면에 아이콘을 그릴 때 쓴다. 모양은 Phosphor(MIT) 에서 고른 것만 있고, `name` 으로 고른다. 색은 글자색(`currentColor`)을 따르므로 감싼 요소의 `color` 로 바꾼다. 꺼진 상태는 선(`weight="regular"`, 기본), 켜진 상태나 강조는 채움(`weight="fill"`)을 쓴다. 크기는 `xs`(16) · `s`(18) · `m`(20) · `l`(24, 기본) · `xl`(32). `className`·`style` 은 `<svg>` 에 붙는다.
1039
1119
 
1040
1120
  글자 없이 아이콘만으로 뜻을 전하면(닫기 버튼 등) `label` 을 준다. 없으면 화면 낭독기가 건너뛴다.
1041
1121
 
@@ -1059,9 +1139,9 @@ import { Icon } from '@nurihaus/web-design-system'; // 루트. 첫
1059
1139
 
1060
1140
  | prop | 타입 | 필수 | 기본값 |
1061
1141
  | --- | --- | --- | --- |
1062
- | `size` | `'s' \| 'm' \| 'l'` | | `'l'` |
1142
+ | `size` | `'xs' \| 's' \| 'm' \| 'l' \| 'xl'` | | `'l'` |
1063
1143
  | `label` | `string` | | |
1064
- | `name` | `'link' \| 'image' \| 'x' \| 'warning' \| 'house' \| 'megaphone-simple' \| 'chats-circle' \| 'user-circle' \| 'bell' \| 'caret-left' \| 'magnifying-glass' \| 'dots-three' \| 'gear-six' \| 'chat-circle' \| 'paper-plane-tilt' \| 'plus' \| 'camera' \| 'video-camera' \| 'upload-simple' \| 'calendar-blank' \| 'clock' \| 'map-pin' \| 'truck' \| 'ticket' \| 'qr-code' \| 'sparkle' \| 'gift' \| 'wallet' \| 'bank' \| 'credit-card' \| 'check-circle' \| 'check' \| 'info' \| 'question' \| 'lock' \| 'pencil-simple' \| 'trash' \| 'copy' \| 'share-network' \| 'eye' \| 'sliders-horizontal' \| 'heart' \| 'star' \| 'globe' \| 'sign-out' \| 'caret-right' \| 'arrow-right' \| 'instagram-logo' \| 'tiktok-logo' \| 'youtube-logo'` | 예 | |
1144
+ | `name` | `'link' \| 'image' \| 'x' \| 'warning' \| 'house' \| 'megaphone-simple' \| 'chats-circle' \| 'user-circle' \| 'bell' \| 'caret-left' \| 'magnifying-glass' \| 'dots-three' \| 'gear-six' \| 'chat-circle' \| 'paper-plane-tilt' \| 'plus' \| 'camera' \| 'video-camera' \| 'play' \| 'upload-simple' \| 'calendar-blank' \| 'clock' \| 'map-pin' \| 'truck' \| 'ticket' \| 'qr-code' \| 'sparkle' \| 'gift' \| 'wallet' \| 'bank' \| 'credit-card' \| 'check-circle' \| 'check' \| 'info' \| 'question' \| 'lock' \| 'pencil-simple' \| 'trash' \| 'copy' \| 'share-network' \| 'eye' \| 'sliders-horizontal' \| 'heart' \| 'star' \| 'globe' \| 'sign-out' \| 'caret-right' \| 'arrow-right' \| 'instagram-logo' \| 'tiktok-logo' \| 'youtube-logo'` | 예 | |
1065
1145
  | `weight` | `'fill' \| 'regular'` | | |
1066
1146
 
1067
1147
  이 밖에 React·HTML 기본 속성 474개를 받는다.
@@ -1077,7 +1157,7 @@ import { BottomNav } from '@nurihaus/web-design-system'; // 루트.
1077
1157
 
1078
1158
  화면 아래에 고정(`position: fixed`)되고 내용 위에 떠 있다. 화면 본문은 아래를 `calc(var(--bottom-nav-space) + env(safe-area-inset-bottom))` 만큼 비워 마지막 내용이 가려지지 않게 한다. `className`·`style` 은 `<nav>` 에 붙는다.
1079
1159
 
1080
- 링크는 기본으로 `<a>` 다. 라우터의 링크로 바꾸려면 `linkComponent` 에 넘긴다. 받는 props 는 `href`·`className`·`children`·`aria-current` 이고, 그대로 링크에 전달하면 된다.
1160
+ 링크는 기본으로 `<a>` 다. 라우터의 링크로 바꾸려면 `linkComponent` 에 넘긴다. 받는 props 는 `href`·`className`·`children`·`aria-current`·`onClick` 이고, 그대로 링크에 전달하면 된다. `onClick` 을 빠뜨리면 `track` 로그가 나가지 않는다.
1081
1161
 
1082
1162
  배지는 `badge` 로 단다. `count` 가 없으면 점, 있으면 숫자(99 넘으면 99+)다. `label` 은 화면 낭독기가 읽는 말이다.
1083
1163
 
@@ -1114,6 +1194,8 @@ import Link from 'next/link';
1114
1194
  | `linkComponent` | `ComponentType<BottomNavLinkProps>` | | |
1115
1195
  | `className` | `string` | | |
1116
1196
  | `style` | `CSSProperties` | | |
1197
+ | `track` | `string` | | |
1198
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
1117
1199
 
1118
1200
  이 밖에 React·HTML 기본 속성 2개를 받는다.
1119
1201
 
@@ -1186,9 +1268,38 @@ import { ChipGroup } from '@nurihaus/web-design-system'; // 루트.
1186
1268
  | `label` | `string` | 예 | |
1187
1269
  | `className` | `string` | | |
1188
1270
  | `style` | `CSSProperties` | | |
1271
+ | `track` | `string` | | |
1272
+ | `trackProps` | `Record<string, string \| number \| boolean>` | | |
1189
1273
 
1190
1274
  이 밖에 React·HTML 기본 속성 2개를 받는다.
1191
1275
 
1276
+ ## LogProvider
1277
+
1278
+ ```ts
1279
+ import { LogProvider } from '@nurihaus/web-design-system/logging'; // 이 컴포넌트만 싣는다 (권장)
1280
+ import { LogProvider } from '@nurihaus/web-design-system'; // 루트. 첫 로드 JS 가 커진다
1281
+ ```
1282
+
1283
+ **언제 쓴다.** 앱 루트에 한 번 두고 사용 로그를 받는다. 디자인시스템 컴포넌트에 `track` 을 주면 그 컴포넌트의 상호작용이 이벤트 하나(`LogEvent`)로 `onEvent` 에 온다. 이벤트를 어느 로그 수집기로 보낼지는 `onEvent` 안에서 앱이 정한다. `onEvent` 가 던져도 화면 동작은 멈추지 않는다.
1284
+ `track` 에는 `'report/download'` 처럼 개발자가 정한 이름을 쓴다. 이벤트의 `value` 에는 탭 id·칩 id·옵션 value 처럼 개발자가 정한 id 만 들어가고 사용자가 입력한 글자는 들어가지 않는다. 더 붙일 값은 `trackProps` 로 명시한다.
1285
+ LogProvider 가 없거나 `track` 을 주지 않으면 아무것도 보내지 않는다.
1286
+ 컴포넌트 밖의 로그(화면 진입, 직접 만든 요소)는 `useLog()` 가 돌려주는 함수에 `{ component, action, track }` 을 넘긴다. `timestamp` 는 자동으로 붙는다.
1287
+
1288
+ **쓰지 않는다.** 에러 보고에 쓰지 않는다. 에러는 앱의 에러 처리에서 따로 남긴다. 화면마다 LogProvider 를 겹쳐 두지 않는다. 안쪽 Provider 가 바깥 것을 가린다.
1289
+
1290
+ ```tsx
1291
+ <LogProvider onEvent={(event) => console.log(event)}>
1292
+ <CTAButton text="리포트 받기" track="report/download" trackProps={{ format: "csv" }} />
1293
+ </LogProvider>
1294
+ ```
1295
+
1296
+ ### props
1297
+
1298
+ | prop | 타입 | 필수 | 기본값 |
1299
+ | --- | --- | --- | --- |
1300
+ | `onEvent` | `(event: LogEvent) => void` | 예 | |
1301
+ | `children` | `ReactNode` | | |
1302
+
1192
1303
  ## 아직 없는 것
1193
1304
 
1194
1305
  아래는 디자인 시스템에 없다. 비슷한 이름의 컴포넌트를 지어내 import 하지 않는다.
package/dist/ai/tokens.md CHANGED
@@ -355,9 +355,11 @@
355
355
  | `--bottom-nav-badge-count` | `18px` | 폭 |
356
356
  | `--glass-blur` | `18px` | 폭 |
357
357
  | `--step-bar-height` | `4px` | 진행 단계 바 |
358
+ | `--icon-size-xs` | `16px` | 그 밖의 치수 |
358
359
  | `--icon-size-s` | `18px` | 그 밖의 치수 |
359
360
  | `--icon-size-m` | `20px` | 그 밖의 치수 |
360
361
  | `--icon-size-l` | `24px` | 그 밖의 치수 |
362
+ | `--icon-size-xl` | `32px` | 그 밖의 치수 |
361
363
  | `--tooltip-arrow` | `8px` | 그 밖의 치수 |
362
364
  | `--spinner-stroke` | `3px` | 그 밖의 치수 |
363
365
  | `--overlay-spinner-size` | `64px` | 그 밖의 치수 |
package/dist/avatar.js CHANGED
@@ -280,7 +280,7 @@ module.exports = x({ ["jsx"]: () => (__WEBPACK_EXTERNAL_MODULE_react_jsx_runtime
280
280
  /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
281
281
  /******/ // [resolve, Promise] = chunk loading, 0 = chunk loaded
282
282
  /******/ var installedChunks = {
283
- /******/ 716: 0
283
+ /******/ 8716: 0
284
284
  /******/ };
285
285
  /******/
286
286
  /******/ var installChunk = (data) => {
@@ -320,17 +320,17 @@ module.exports = x({ ["jsx"]: () => (__WEBPACK_EXTERNAL_MODULE_react_jsx_runtime
320
320
  /******/
321
321
  /************************************************************************/
322
322
  /******/
323
- /******/ import * as __webpack_chunk_1__ from "./chunk-364.js";
323
+ /******/ import * as __webpack_chunk_1__ from "./chunk-6364.js";
324
324
  /******/ __nuri_require__.C(__webpack_chunk_1__);
325
- /******/ import * as __webpack_chunk_2__ from "./chunk-777.js";
325
+ /******/ import * as __webpack_chunk_2__ from "./chunk-2777.js";
326
326
  /******/ __nuri_require__.C(__webpack_chunk_2__);
327
- /******/ import * as __webpack_chunk_3__ from "./chunk-298.js";
327
+ /******/ import * as __webpack_chunk_3__ from "./chunk-7298.js";
328
328
  /******/ __nuri_require__.C(__webpack_chunk_3__);
329
329
  /******/
330
330
  /******/ // startup
331
331
  /******/ // Load entry module and return exports
332
332
  /******/ // This entry module depends on other loaded chunks and execution need to be delayed
333
- /******/ var __webpack_exports__ = __nuri_require__.O(undefined, [364,777,298], () => (__nuri_require__(5468)))
333
+ /******/ var __webpack_exports__ = __nuri_require__.O(undefined, [6364,2777,7298], () => (__nuri_require__(5468)))
334
334
  /******/ __webpack_exports__ = __nuri_require__.O(__webpack_exports__);
335
335
  /******/ const __webpack_exports__default = __webpack_exports__.A;
336
336
  /******/ export { __webpack_exports__default as default };
@@ -17,6 +17,8 @@ __nuri_require__.d(__webpack_exports__, {
17
17
  var jsx_runtime_ = __nuri_require__(612);
18
18
  // EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react","module":"react"}
19
19
  var external_root_React_commonjs2_react_commonjs_react_amd_react_module_react_ = __nuri_require__(1041);
20
+ // EXTERNAL MODULE: ./helpers/hooks/useTrack.ts
21
+ var useTrack = __nuri_require__(4560);
20
22
  // EXTERNAL MODULE: ./helpers/utils/classNames.js
21
23
  var classNames = __nuri_require__(3274);
22
24
  // EXTERNAL MODULE: ./helpers/utils/getMergedProps.ts
@@ -118,6 +120,7 @@ var bottom_nav_assign = undefined && undefined.__assign || function () {
118
120
 
119
121
 
120
122
 
123
+
121
124
  var Anchor = function Anchor(props) {
122
125
  return (0,jsx_runtime_.jsx)("a", bottom_nav_assign({}, props));
123
126
  };
@@ -130,7 +133,13 @@ var BottomNav = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_rea
130
133
  items = _a.items,
131
134
  value = _a.value,
132
135
  label = _a.label,
133
- linkComponent = _a.linkComponent;
136
+ linkComponent = _a.linkComponent,
137
+ track = _a.track,
138
+ trackProps = _a.trackProps;
139
+ var emit = (0,useTrack/* useTrack */.n)('BottomNav', {
140
+ track: track,
141
+ trackProps: trackProps
142
+ });
134
143
  var Link = linkComponent !== null && linkComponent !== void 0 ? linkComponent : Anchor;
135
144
  var activeIndex = items.findIndex(function (item) {
136
145
  return item.id === value;
@@ -153,6 +162,9 @@ var BottomNav = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_rea
153
162
  className: itemClassName,
154
163
  href: item.href,
155
164
  "aria-current": isActive ? 'page' : undefined,
165
+ onClick: function onClick() {
166
+ return emit('navigate', item.id);
167
+ },
156
168
  children: [(0,jsx_runtime_.jsx)("span", {
157
169
  className: 'bottom-nav-label',
158
170
  children: item.label
@@ -244,7 +256,7 @@ var x = (y) => {
244
256
  var x = {}; __nuri_require__.d(x, y); return x
245
257
  }
246
258
  var y = (x) => (() => (x))
247
- module.exports = x({ ["forwardRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.forwardRef) });
259
+ module.exports = x({ ["createContext"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.createContext), ["forwardRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.forwardRef), ["useCallback"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useCallback), ["useContext"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useContext), ["useRef"]: () => (__WEBPACK_EXTERNAL_MODULE_react__.useRef) });
248
260
 
249
261
  /***/ },
250
262
 
@@ -349,8 +361,8 @@ module.exports = x({ ["jsx"]: () => (__WEBPACK_EXTERNAL_MODULE_react_jsx_runtime
349
361
  /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
350
362
  /******/ // [resolve, Promise] = chunk loading, 0 = chunk loaded
351
363
  /******/ var installedChunks = {
352
- /******/ 480: 0,
353
- /******/ 918: 0
364
+ /******/ 918: 0,
365
+ /******/ 6480: 0
354
366
  /******/ };
355
367
  /******/
356
368
  /******/ var installChunk = (data) => {
@@ -390,17 +402,19 @@ module.exports = x({ ["jsx"]: () => (__WEBPACK_EXTERNAL_MODULE_react_jsx_runtime
390
402
  /******/
391
403
  /************************************************************************/
392
404
  /******/
393
- /******/ import * as __webpack_chunk_1__ from "./chunk-364.js";
405
+ /******/ import * as __webpack_chunk_1__ from "./chunk-6364.js";
394
406
  /******/ __nuri_require__.C(__webpack_chunk_1__);
395
- /******/ import * as __webpack_chunk_2__ from "./chunk-298.js";
407
+ /******/ import * as __webpack_chunk_2__ from "./chunk-4560.js";
396
408
  /******/ __nuri_require__.C(__webpack_chunk_2__);
397
- /******/ import * as __webpack_chunk_3__ from "./chunk-653.js";
409
+ /******/ import * as __webpack_chunk_3__ from "./chunk-7298.js";
398
410
  /******/ __nuri_require__.C(__webpack_chunk_3__);
411
+ /******/ import * as __webpack_chunk_4__ from "./chunk-7653.js";
412
+ /******/ __nuri_require__.C(__webpack_chunk_4__);
399
413
  /******/
400
414
  /******/ // startup
401
415
  /******/ // Load entry module and return exports
402
416
  /******/ // This entry module depends on other loaded chunks and execution need to be delayed
403
- /******/ var __webpack_exports__ = __nuri_require__.O(undefined, [364,298,653], () => (__nuri_require__(1768)))
417
+ /******/ var __webpack_exports__ = __nuri_require__.O(undefined, [6364,4560,7298,7653], () => (__nuri_require__(1768)))
404
418
  /******/ __webpack_exports__ = __nuri_require__.O(__webpack_exports__);
405
419
  /******/ const __webpack_exports__default = __webpack_exports__.A;
406
420
  /******/ export { __webpack_exports__default as default };