jongsultest 0.1.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 (83) hide show
  1. package/dist/index.d.mts +339 -0
  2. package/dist/index.d.ts +339 -0
  3. package/dist/index.js +1280 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +1234 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/package.json +59 -0
  8. package/src/atoms/Badge.stories.tsx +136 -0
  9. package/src/atoms/Badge.tsx +46 -0
  10. package/src/atoms/Button.stories.tsx +142 -0
  11. package/src/atoms/Button.tsx +50 -0
  12. package/src/atoms/ComboboxAutocomplete.stories.tsx +43 -0
  13. package/src/atoms/ComboboxAutocomplete.tsx +6 -0
  14. package/src/atoms/ComboboxSelect.stories.tsx +56 -0
  15. package/src/atoms/ComboboxSelect.tsx +6 -0
  16. package/src/atoms/DateTimePicker.stories.tsx +42 -0
  17. package/src/atoms/DateTimePicker.tsx +6 -0
  18. package/src/atoms/Icon.stories.tsx +86 -0
  19. package/src/atoms/Icon.tsx +81 -0
  20. package/src/atoms/IconButton.stories.tsx +59 -0
  21. package/src/atoms/IconButton.tsx +19 -0
  22. package/src/atoms/InputColor.stories.tsx +42 -0
  23. package/src/atoms/InputColor.tsx +6 -0
  24. package/src/atoms/InputDatePicker.stories.tsx +55 -0
  25. package/src/atoms/InputDatePicker.tsx +6 -0
  26. package/src/atoms/InputFile.stories.tsx +57 -0
  27. package/src/atoms/InputFile.tsx +15 -0
  28. package/src/atoms/InputNumber.stories.tsx +58 -0
  29. package/src/atoms/InputNumber.tsx +15 -0
  30. package/src/atoms/InputPassword.stories.tsx +42 -0
  31. package/src/atoms/InputPassword.tsx +24 -0
  32. package/src/atoms/InputRadio.stories.tsx +65 -0
  33. package/src/atoms/InputRadio.tsx +19 -0
  34. package/src/atoms/InputSegmentedControl.stories.tsx +44 -0
  35. package/src/atoms/InputSegmentedControl.tsx +15 -0
  36. package/src/atoms/InputSwitch.stories.tsx +45 -0
  37. package/src/atoms/InputSwitch.tsx +23 -0
  38. package/src/atoms/InputSwitchInTable.stories.tsx +43 -0
  39. package/src/atoms/InputSwitchInTable.tsx +35 -0
  40. package/src/atoms/InputText.stories.tsx +42 -0
  41. package/src/atoms/InputText.tsx +7 -0
  42. package/src/atoms/InputTextarea.stories.tsx +50 -0
  43. package/src/atoms/InputTextarea.tsx +6 -0
  44. package/src/atoms/index.ts +20 -0
  45. package/src/atoms/inputClassNames.ts +20 -0
  46. package/src/blocks/Accordion.stories.tsx +102 -0
  47. package/src/blocks/Accordion.tsx +124 -0
  48. package/src/blocks/AccordionDraggable.stories.tsx +169 -0
  49. package/src/blocks/AccordionDraggable.tsx +200 -0
  50. package/src/blocks/BoxContainer.stories.tsx +34 -0
  51. package/src/blocks/BoxContainer.tsx +16 -0
  52. package/src/blocks/DataTable.tsx +127 -0
  53. package/src/blocks/DescriptionRow.stories.tsx +34 -0
  54. package/src/blocks/DescriptionRow.tsx +22 -0
  55. package/src/blocks/EditorLayout.stories.tsx +79 -0
  56. package/src/blocks/EditorLayout.tsx +43 -0
  57. package/src/blocks/ImageUpload.tsx +292 -0
  58. package/src/blocks/LabeledField.stories.tsx +34 -0
  59. package/src/blocks/LabeledField.tsx +31 -0
  60. package/src/blocks/MediDrawer.stories.tsx +58 -0
  61. package/src/blocks/MediDrawer.tsx +34 -0
  62. package/src/blocks/Modal.stories.tsx +42 -0
  63. package/src/blocks/Modal.tsx +31 -0
  64. package/src/blocks/ModalDeleteConfirm.stories.tsx +31 -0
  65. package/src/blocks/ModalDeleteConfirm.tsx +56 -0
  66. package/src/blocks/ModalTokenExpired.tsx +52 -0
  67. package/src/blocks/NavigationBanner.tsx +100 -0
  68. package/src/blocks/PageHeader.tsx +24 -0
  69. package/src/blocks/PageLoading.stories.tsx +22 -0
  70. package/src/blocks/PageLoading.tsx +19 -0
  71. package/src/blocks/PageTitle.stories.tsx +39 -0
  72. package/src/blocks/PageTitle.tsx +25 -0
  73. package/src/blocks/Pagination.tsx +49 -0
  74. package/src/blocks/Panel.stories.tsx +84 -0
  75. package/src/blocks/Panel.tsx +97 -0
  76. package/src/blocks/SectionGroupWithTitle.stories.tsx +24 -0
  77. package/src/blocks/SectionGroupWithTitle.tsx +21 -0
  78. package/src/blocks/Table.tsx +114 -0
  79. package/src/blocks/TagInput.stories.tsx +74 -0
  80. package/src/blocks/TagInput.tsx +93 -0
  81. package/src/blocks/index.ts +25 -0
  82. package/src/index.ts +51 -0
  83. package/src/utils/file.ts +7 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1234 @@
1
+ import { Accordion as Accordion$1, Radio, Button as Button$1, TextInput, PasswordInput, NumberInput, ColorInput, FileInput, Textarea, Switch, Box, SegmentedControl, Select, Autocomplete, Badge as Badge$1, ActionIcon, Text, Table as Table$1, Group, Pagination as Pagination$1, Stack, Image, FileButton, Title, LoadingOverlay, Paper, Grid, Modal as Modal$1, Divider, Checkbox } from '@mantine/core';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { IconAlertCircle, IconCheck, IconX, IconChevronLeft, IconChevronRight, IconUpload, IconArrowLeft, IconPlus } from '@tabler/icons-react';
4
+ import { DatePickerInput, DateTimePicker as DateTimePicker$1 } from '@mantine/dates';
5
+ import clsx from 'clsx';
6
+ import { useState, useEffect, useMemo } from 'react';
7
+ import { notifications } from '@mantine/notifications';
8
+ import { useRouter } from 'next/navigation';
9
+ import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
10
+
11
+ var __defProp = Object.defineProperty;
12
+ var __defProps = Object.defineProperties;
13
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
14
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
17
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
18
+ var __spreadValues = (a, b) => {
19
+ for (var prop in b || (b = {}))
20
+ if (__hasOwnProp.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ if (__getOwnPropSymbols)
23
+ for (var prop of __getOwnPropSymbols(b)) {
24
+ if (__propIsEnum.call(b, prop))
25
+ __defNormalProp(a, prop, b[prop]);
26
+ }
27
+ return a;
28
+ };
29
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
30
+ var __objRest = (source, exclude) => {
31
+ var target = {};
32
+ for (var prop in source)
33
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
34
+ target[prop] = source[prop];
35
+ if (source != null && __getOwnPropSymbols)
36
+ for (var prop of __getOwnPropSymbols(source)) {
37
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
38
+ target[prop] = source[prop];
39
+ }
40
+ return target;
41
+ };
42
+ var COMMON_STYLES = {
43
+ "--button-fz": "14px",
44
+ "--button-radius": "6px"
45
+ };
46
+ var SIZE_STYLES = {
47
+ xs: {
48
+ "--button-height": "24px",
49
+ "--button-padding-x": "6px"
50
+ },
51
+ sm: {
52
+ "--button-height": "38px",
53
+ "--button-padding-x": "16px"
54
+ },
55
+ md: {
56
+ "--button-height": "40px",
57
+ "--button-padding-x": "24px"
58
+ }
59
+ };
60
+ var getVariantStyles = (variant, color) => {
61
+ if (variant === "outline" && color === "gray") {
62
+ return { color: "var(--color-body)", borderColor: "var(--color-gray-3)" };
63
+ }
64
+ if (variant === "default") {
65
+ return { backgroundColor: "var(--mantine-color-blue-6)", color: "#FFFFFF", border: "none" };
66
+ }
67
+ if (variant === "light" && !color) {
68
+ return { backgroundColor: "var(--color-button-light)", color: "var(--color-body)", border: "none" };
69
+ }
70
+ return {};
71
+ };
72
+ var Button = (_a) => {
73
+ var _b = _a, { style } = _b, props = __objRest(_b, ["style"]);
74
+ var _a2;
75
+ const sizeVars = (_a2 = SIZE_STYLES[props.size]) != null ? _a2 : SIZE_STYLES.md;
76
+ const variantStyles = getVariantStyles(props.variant, props.color);
77
+ return /* @__PURE__ */ jsx(
78
+ Button$1,
79
+ __spreadProps(__spreadValues({}, props), {
80
+ classNames: { label: "!font-bold" },
81
+ style: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, COMMON_STYLES), sizeVars), variantStyles), style)
82
+ })
83
+ );
84
+ };
85
+
86
+ // src/atoms/inputClassNames.ts
87
+ var inputClassNames = {
88
+ input: `!rounded-[8px] !border-input
89
+ !text-sm !h-12
90
+
91
+ data-[error=true]:!border-error-line
92
+ data-[error=true]:!border-2
93
+ data-[error=true]:!bg-error-fill
94
+ data-[error=true]:!text-body
95
+
96
+ data-[disabled=true]:!text-body
97
+ data-[disabled=true]:!bg-disabled-input
98
+ data-[disabled=true]:!opacity-100
99
+ data-[disabled=true]:!border-default
100
+ `,
101
+ label: "!text-sm !text-[#999] !font-bold !tracking-tight !mb-2",
102
+ placeholder: "!text-sm !tracking-normal",
103
+ error: "!mt-2 !ml-2",
104
+ description: "!-mt-[.5px] !mb-2",
105
+ root: "!leading-0"
106
+ };
107
+ var InputText = (props) => {
108
+ return /* @__PURE__ */ jsx(TextInput, __spreadValues({ classNames: inputClassNames }, props));
109
+ };
110
+ var InputPassword = (props) => {
111
+ const { error } = props;
112
+ return /* @__PURE__ */ jsx(
113
+ PasswordInput,
114
+ __spreadValues({
115
+ classNames: inputClassNames,
116
+ error: typeof error === "string" ? /* @__PURE__ */ jsxs("span", { className: "flex items-start gap-2", children: [
117
+ /* @__PURE__ */ jsx(IconAlertCircle, { size: 16, className: "mt-[2px] shrink-0" }),
118
+ /* @__PURE__ */ jsx("span", { children: error })
119
+ ] }) : error
120
+ }, props)
121
+ );
122
+ };
123
+ var InputNumber = (props) => {
124
+ return /* @__PURE__ */ jsx(
125
+ NumberInput,
126
+ __spreadValues({
127
+ classNames: __spreadProps(__spreadValues({}, inputClassNames), {
128
+ controls: "!h-8 !border-input",
129
+ control: "!border-input"
130
+ })
131
+ }, props)
132
+ );
133
+ };
134
+ var InputColor = (props) => {
135
+ return /* @__PURE__ */ jsx(ColorInput, __spreadValues({ classNames: inputClassNames }, props));
136
+ };
137
+ var InputFile = ((props) => {
138
+ return /* @__PURE__ */ jsx(FileInput, __spreadValues({ classNames: inputClassNames }, props));
139
+ });
140
+ var InputDatePicker = (props) => {
141
+ return /* @__PURE__ */ jsx(DatePickerInput, __spreadProps(__spreadValues({ classNames: inputClassNames }, props), { valueFormat: "YYYY-MM-DD" }));
142
+ };
143
+ var InputTextarea = (props) => {
144
+ return /* @__PURE__ */ jsx(Textarea, __spreadValues({ classNames: __spreadProps(__spreadValues({}, inputClassNames), { input: `${inputClassNames.input} !py-3` }) }, props));
145
+ };
146
+ var RadioBase = (props) => {
147
+ return /* @__PURE__ */ jsx(Radio, __spreadValues({}, props));
148
+ };
149
+ var RadioGroup = (props) => {
150
+ return /* @__PURE__ */ jsx(Radio.Group, __spreadValues({ classNames: { label: inputClassNames.label } }, props));
151
+ };
152
+ var InputRadio = Object.assign(RadioBase, {
153
+ Group: RadioGroup
154
+ });
155
+ var InputSwitch = (_a) => {
156
+ var _b = _a, { checked, style, classNames } = _b, props = __objRest(_b, ["checked", "style", "classNames"]);
157
+ return /* @__PURE__ */ jsx(
158
+ Switch,
159
+ __spreadProps(__spreadValues({
160
+ checked,
161
+ thumbIcon: /* @__PURE__ */ jsx(IconCheck, { size: 10, color: "white", stroke: 3 })
162
+ }, props), {
163
+ style: __spreadValues(__spreadValues({}, typeof style === "object" && style || {}), !checked && { "--switch-thumb-start": "6px" }),
164
+ classNames: __spreadValues({
165
+ thumb: "!w-[10px] !h-[10px] text-white",
166
+ label: "!text-gray-6 !font-medium"
167
+ }, classNames)
168
+ })
169
+ );
170
+ };
171
+ var InputSwitchInTable = ({
172
+ status,
173
+ onStatusChange,
174
+ id,
175
+ activeValue = "ACTIVE",
176
+ inactiveValue = "HIDDEN",
177
+ activeLabel = "\uD65C\uC131",
178
+ inactiveLabel = "\uC228\uAE40"
179
+ }) => {
180
+ const isActive = status === activeValue;
181
+ return /* @__PURE__ */ jsx(Box, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
182
+ InputSwitch,
183
+ {
184
+ checked: isActive,
185
+ onChange: () => onStatusChange(id, isActive ? inactiveValue : activeValue),
186
+ size: "sm",
187
+ classNames: { label: "!font-semibold" }
188
+ }
189
+ ) });
190
+ };
191
+ var InputSegmentedControl = (props) => {
192
+ return /* @__PURE__ */ jsx(
193
+ SegmentedControl,
194
+ __spreadValues({
195
+ classNames: {
196
+ root: "p-2! rounded-md!",
197
+ // 루트
198
+ control: "",
199
+ // 버튼
200
+ label: "h-10 px-4 text-sm",
201
+ // 텍스트 패딩/타이포
202
+ innerLabel: "leading-9 color-white"
203
+ // 선택 인디케이터 높이도 같이
204
+ }
205
+ }, props)
206
+ );
207
+ };
208
+ var ComboboxSelect = (props) => {
209
+ return /* @__PURE__ */ jsx(Select, __spreadValues({ classNames: inputClassNames }, props));
210
+ };
211
+ var ComboboxAutocomplete = (props) => {
212
+ return /* @__PURE__ */ jsx(Autocomplete, __spreadValues({ classNames: inputClassNames }, props));
213
+ };
214
+ var DateTimePicker = (props) => {
215
+ return /* @__PURE__ */ jsx(DateTimePicker$1, __spreadValues({ classNames: inputClassNames }, props));
216
+ };
217
+ var REMOVE_ABLE_BADGE_STYLES = {
218
+ light: "gray",
219
+ blue: "gray"
220
+ // blue 임시 작업 blue 인 경우 생기면 컬러 변경 하셔도 됩니다.
221
+ };
222
+ var Badge = (_a) => {
223
+ var _b = _a, {
224
+ className,
225
+ classNames,
226
+ isRemoveAble = false,
227
+ onRemove
228
+ } = _b, props = __objRest(_b, [
229
+ "className",
230
+ "classNames",
231
+ "isRemoveAble",
232
+ "onRemove"
233
+ ]);
234
+ var _a2;
235
+ return /* @__PURE__ */ jsx(
236
+ Badge$1,
237
+ __spreadProps(__spreadValues({}, props), {
238
+ className,
239
+ classNames: __spreadProps(__spreadValues({}, classNames), {
240
+ label: clsx("!text-xs !font-semibold", classNames == null ? void 0 : classNames.label)
241
+ }),
242
+ rightSection: props.rightSection || (isRemoveAble ? /* @__PURE__ */ jsx(
243
+ ActionIcon,
244
+ {
245
+ size: "xs",
246
+ variant: "transparent",
247
+ color: REMOVE_ABLE_BADGE_STYLES[(_a2 = props.variant) != null ? _a2 : "blue"],
248
+ onClick: onRemove,
249
+ children: /* @__PURE__ */ jsx(IconX, { size: 12 })
250
+ }
251
+ ) : void 0),
252
+ styles: {
253
+ root: {
254
+ "--mantine-color-gray-light-color": "var(--color-body)",
255
+ "--mantine-color-green-light-color": "#166534"
256
+ }
257
+ }
258
+ })
259
+ );
260
+ };
261
+ var IconButton = (_a) => {
262
+ var _b = _a, { icon: Icon, iconSize, iconColor, disabled, children } = _b, props = __objRest(_b, ["icon", "iconSize", "iconColor", "disabled", "children"]);
263
+ return /* @__PURE__ */ jsx(ActionIcon, __spreadProps(__spreadValues({ variant: "subtle", color: "gray", disabled }, props), { children: Icon ? /* @__PURE__ */ jsx(Icon, { size: iconSize, color: iconColor, disabled }) : children }));
264
+ };
265
+ var colorPreset = {
266
+ red: "#FF4242",
267
+ white: "#FFFFFF",
268
+ gray: "#666666",
269
+ disabled: "#DDDDDD"
270
+ };
271
+ var resolveColor = (color) => {
272
+ var _a;
273
+ return (_a = colorPreset[color]) != null ? _a : color;
274
+ };
275
+ var PlusIcon = ({ size = 20, color = "gray", disabled }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
276
+ /* @__PURE__ */ jsx("circle", { cx: "10", cy: "10", r: "10", fill: disabled ? resolveColor("disabled") : resolveColor(color) }),
277
+ /* @__PURE__ */ jsx("path", { d: "M10 5.5V14.5M14.5 10L5.5 10", stroke: "white", strokeWidth: "1.2", strokeLinecap: "round" })
278
+ ] });
279
+ var TrashIcon = ({ size = 20, color = "gray" }) => {
280
+ const c = resolveColor(color);
281
+ return /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
282
+ /* @__PURE__ */ jsx(
283
+ "path",
284
+ {
285
+ d: "M14 4.5V2C14 1.72386 13.7761 1.5 13.5 1.5H6.5C6.22386 1.5 6 1.72386 6 2V4.5",
286
+ stroke: c,
287
+ strokeWidth: "1.2"
288
+ }
289
+ ),
290
+ /* @__PURE__ */ jsx("path", { d: "M2 4H18", stroke: c, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }),
291
+ /* @__PURE__ */ jsx(
292
+ "path",
293
+ {
294
+ d: "M4 7.00028V17C4 17.5523 4.44772 18 5 18H15C15.5523 18 16 17.5523 16 17V7",
295
+ stroke: c,
296
+ strokeWidth: "1.2",
297
+ strokeLinecap: "round"
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsx("path", { d: "M8 7V13", stroke: c, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }),
301
+ /* @__PURE__ */ jsx("path", { d: "M12 7V13", stroke: c, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
302
+ ] });
303
+ };
304
+ var GripVerticalIcon = ({ size = 20, color = "gray" }) => {
305
+ const c = resolveColor(color);
306
+ return /* @__PURE__ */ jsxs(
307
+ "svg",
308
+ {
309
+ xmlns: "http://www.w3.org/2000/svg",
310
+ width: size,
311
+ height: size,
312
+ viewBox: "0 0 20 20",
313
+ fill: "none",
314
+ className: "cursor-grab",
315
+ children: [
316
+ /* @__PURE__ */ jsx("rect", { x: "6.5", y: "3.5", width: "1.2", height: "1.2", rx: "0.6", stroke: c }),
317
+ /* @__PURE__ */ jsx("rect", { x: "6.5", y: "9.39844", width: "1.2", height: "1.2", rx: "0.6", stroke: c }),
318
+ /* @__PURE__ */ jsx("rect", { x: "6.5", y: "15.3008", width: "1.2", height: "1.2", rx: "0.6", stroke: c }),
319
+ /* @__PURE__ */ jsx("rect", { x: "12.3008", y: "3.5", width: "1.2", height: "1.2", rx: "0.6", stroke: c }),
320
+ /* @__PURE__ */ jsx("rect", { x: "12.3008", y: "9.39844", width: "1.2", height: "1.2", rx: "0.6", stroke: c }),
321
+ /* @__PURE__ */ jsx("rect", { x: "12.3008", y: "15.3008", width: "1.2", height: "1.2", rx: "0.6", stroke: c })
322
+ ]
323
+ }
324
+ );
325
+ };
326
+ var ChevronDownIcon = ({ size = 20, color = "#191919" }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
327
+ "path",
328
+ {
329
+ d: "M16 7L10.0007 13L4 7",
330
+ stroke: resolveColor(color),
331
+ strokeWidth: "1.2",
332
+ strokeLinecap: "round",
333
+ strokeLinejoin: "round"
334
+ }
335
+ ) });
336
+ function Table({
337
+ columns,
338
+ data,
339
+ rowKey,
340
+ emptyMessage = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
341
+ highlightOnHover = false,
342
+ onRowClick
343
+ }) {
344
+ const getRowKey = (row, index) => {
345
+ if (!rowKey) return String(index);
346
+ if (typeof rowKey === "function") return rowKey(row, index);
347
+ return String(row[rowKey]);
348
+ };
349
+ const getCellValue = (row, column, index) => {
350
+ if (column.render) {
351
+ return column.render(row, index);
352
+ }
353
+ if (column.accessor) {
354
+ return row[column.accessor];
355
+ }
356
+ return null;
357
+ };
358
+ if (data.length === 0) {
359
+ return /* @__PURE__ */ jsx(Box, { py: "xl", style: { textAlign: "center" }, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: emptyMessage }) });
360
+ }
361
+ return /* @__PURE__ */ jsxs(
362
+ Table$1,
363
+ {
364
+ highlightOnHover,
365
+ verticalSpacing: "md",
366
+ classNames: {
367
+ table: "!border-default !overflow-hidden !border-separate",
368
+ thead: "!bg-gray-0",
369
+ th: "!text-center !border-b !border-default",
370
+ td: "!text-center !border-b !border-default"
371
+ },
372
+ children: [
373
+ /* @__PURE__ */ jsx(Table$1.Thead, { children: /* @__PURE__ */ jsx(Table$1.Tr, { children: columns.map((column) => /* @__PURE__ */ jsx(
374
+ Table$1.Th,
375
+ {
376
+ style: {
377
+ textAlign: column.align || "left",
378
+ width: column.width
379
+ },
380
+ children: column.header
381
+ },
382
+ column.id
383
+ )) }) }),
384
+ /* @__PURE__ */ jsx(Table$1.Tbody, { children: data.map((row, index) => /* @__PURE__ */ jsx(
385
+ Table$1.Tr,
386
+ {
387
+ onClick: () => onRowClick == null ? void 0 : onRowClick(row, index),
388
+ style: { cursor: onRowClick ? "pointer" : void 0 },
389
+ children: columns.map((column) => /* @__PURE__ */ jsx(
390
+ Table$1.Td,
391
+ {
392
+ style: {
393
+ textAlign: column.align || "left",
394
+ width: column.width
395
+ },
396
+ children: getCellValue(row, column, index)
397
+ },
398
+ column.id
399
+ ))
400
+ },
401
+ getRowKey(row, index)
402
+ )) })
403
+ ]
404
+ }
405
+ );
406
+ }
407
+ function Pagination({
408
+ total,
409
+ page,
410
+ onChange,
411
+ siblings = 1,
412
+ boundaries = 1,
413
+ size = "sm",
414
+ withEdges = true,
415
+ position = "center"
416
+ }) {
417
+ if (total <= 0) return null;
418
+ return /* @__PURE__ */ jsx(Group, { justify: position, mt: "xl", children: /* @__PURE__ */ jsx(
419
+ Pagination$1,
420
+ {
421
+ total,
422
+ value: page,
423
+ onChange,
424
+ siblings,
425
+ boundaries,
426
+ size,
427
+ withEdges
428
+ }
429
+ ) });
430
+ }
431
+ function Accordion({
432
+ items,
433
+ defaultOpen = [],
434
+ multiple = true,
435
+ variant = "separated",
436
+ onChange
437
+ }) {
438
+ if (multiple) {
439
+ return /* @__PURE__ */ jsx(
440
+ Accordion$1,
441
+ {
442
+ variant,
443
+ multiple: true,
444
+ defaultValue: defaultOpen,
445
+ chevron: /* @__PURE__ */ jsx(ChevronDownIcon, {}),
446
+ styles: accordionStyles,
447
+ onChange,
448
+ classNames: { label: "!py-4" },
449
+ children: items.map((item) => /* @__PURE__ */ jsx(AccordionItem, { item }, item.id))
450
+ }
451
+ );
452
+ }
453
+ return /* @__PURE__ */ jsx(
454
+ Accordion$1,
455
+ {
456
+ variant,
457
+ defaultValue: defaultOpen[0],
458
+ chevron: /* @__PURE__ */ jsx(ChevronDownIcon, {}),
459
+ styles: accordionStyles,
460
+ onChange,
461
+ children: items.map((item) => /* @__PURE__ */ jsx(AccordionItem, { item }, item.id))
462
+ }
463
+ );
464
+ }
465
+ function AccordionItem({ item }) {
466
+ return /* @__PURE__ */ jsxs(Accordion$1.Item, { value: item.id, children: [
467
+ /* @__PURE__ */ jsx(Accordion$1.Control, { disabled: item.disabled, icon: item.icon, children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", style: { flex: 1 }, children: [
468
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: item.title }),
469
+ item.rightSection && /* @__PURE__ */ jsx("div", { onClick: (e) => e.stopPropagation(), children: item.rightSection })
470
+ ] }) }),
471
+ /* @__PURE__ */ jsx(Accordion$1.Panel, { children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
472
+ item.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: item.description }),
473
+ item.content
474
+ ] }) })
475
+ ] });
476
+ }
477
+ var accordionStyles = {
478
+ control: { padding: "17px 24px" },
479
+ item: { "--item-filled-color": "#F3F9FF" }
480
+ };
481
+ Accordion.Root = ((props) => /* @__PURE__ */ jsx(Accordion$1, __spreadValues({ chevron: /* @__PURE__ */ jsx(ChevronDownIcon, {}), styles: accordionStyles }, props)));
482
+ Accordion.Item = Accordion$1.Item;
483
+ Accordion.Control = Accordion$1.Control;
484
+ Accordion.Panel = Accordion$1.Panel;
485
+ function NavigationBanner({
486
+ items,
487
+ currentIndex: controlledIndex,
488
+ onIndexChange,
489
+ imageSize = 275,
490
+ emptyText = "\uC774\uBBF8\uC9C0\uB97C \uCD94\uAC00\uD558\uC138\uC694",
491
+ showNavigation = true,
492
+ className
493
+ }) {
494
+ const [internalIndex, setInternalIndex] = useState(0);
495
+ const currentIndex = controlledIndex != null ? controlledIndex : internalIndex;
496
+ const setCurrentIndex = onIndexChange != null ? onIndexChange : setInternalIndex;
497
+ useEffect(() => {
498
+ if (currentIndex >= items.length && items.length > 0) {
499
+ setCurrentIndex(items.length - 1);
500
+ }
501
+ }, [items.length, currentIndex, setCurrentIndex]);
502
+ const isItems = items.length > 0;
503
+ const currentItem = items[currentIndex];
504
+ const isMultiple = items.length > 1;
505
+ const handlePrev = () => {
506
+ const newIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1;
507
+ setCurrentIndex(newIndex);
508
+ };
509
+ const handleNext = () => {
510
+ const newIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0;
511
+ setCurrentIndex(newIndex);
512
+ };
513
+ return /* @__PURE__ */ jsxs(Box, { className, children: [
514
+ /* @__PURE__ */ jsx(Box, { className: "overflow-hidden rounded-sm bg-gray-100", style: { width: imageSize, height: imageSize }, children: isItems && currentItem ? /* @__PURE__ */ jsx("img", { src: currentItem.image, alt: currentItem.title, className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsx(Box, { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: emptyText }) }) }),
515
+ showNavigation && /* @__PURE__ */ jsxs(Group, { justify: "center", gap: "md", mt: "sm", style: { width: imageSize }, children: [
516
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", color: "gray", size: "sm", onClick: handlePrev, disabled: !isMultiple, children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 18 }) }),
517
+ /* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, className: "flex-1 text-center tracking-wider uppercase", lineClamp: 1, children: (currentItem == null ? void 0 : currentItem.title) || "\uC81C\uBAA9 \uC5C6\uC74C" }),
518
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", color: "gray", size: "sm", onClick: handleNext, disabled: !isMultiple, children: /* @__PURE__ */ jsx(IconChevronRight, { size: 18 }) })
519
+ ] })
520
+ ] });
521
+ }
522
+
523
+ // src/utils/file.ts
524
+ function readFileAsDataURL(file) {
525
+ return new Promise((resolve) => {
526
+ const reader = new FileReader();
527
+ reader.onloadend = () => resolve(reader.result);
528
+ reader.readAsDataURL(file);
529
+ });
530
+ }
531
+ function DeleteIndicator({ onClick }) {
532
+ return /* @__PURE__ */ jsx(
533
+ ActionIcon,
534
+ {
535
+ size: 18,
536
+ radius: "xl",
537
+ color: "red",
538
+ variant: "filled",
539
+ style: { position: "absolute", top: -6, right: -6, zIndex: 10 },
540
+ className: "shadow-sm",
541
+ onClick: (e) => {
542
+ e.stopPropagation();
543
+ onClick();
544
+ },
545
+ children: /* @__PURE__ */ jsx(IconX, { size: 10, stroke: 3 })
546
+ }
547
+ );
548
+ }
549
+ function validateImageDimensions(file, maxW, maxH) {
550
+ if (!maxW && !maxH) return Promise.resolve(true);
551
+ return new Promise((resolve) => {
552
+ const img = new window.Image();
553
+ img.onload = () => {
554
+ URL.revokeObjectURL(img.src);
555
+ const isWidthOk = !maxW || img.naturalWidth <= maxW;
556
+ const isHeightOk = !maxH || img.naturalHeight <= maxH;
557
+ resolve(isWidthOk && isHeightOk);
558
+ };
559
+ img.onerror = () => {
560
+ URL.revokeObjectURL(img.src);
561
+ resolve(false);
562
+ };
563
+ img.src = URL.createObjectURL(file);
564
+ });
565
+ }
566
+ function ImageUpload({
567
+ value,
568
+ onChange,
569
+ maxCount,
570
+ variant = "gallery",
571
+ previewWidth = 80,
572
+ previewHeight,
573
+ previewFit = "cover",
574
+ label,
575
+ buttonText = "\uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC",
576
+ placeholder = "No Image",
577
+ description,
578
+ accept = "image/png,image/jpeg,image/gif",
579
+ showCount = false,
580
+ maxWidth,
581
+ maxHeight
582
+ }) {
583
+ const effectiveHeight = previewHeight != null ? previewHeight : previewWidth;
584
+ const [dimensionError, setDimensionError] = useState(null);
585
+ const buildDimensionErrorMessage = () => {
586
+ if (maxWidth && maxHeight) return `\uC774\uBBF8\uC9C0 \uD06C\uAE30\uB294 \uCD5C\uB300 ${maxWidth}x${maxHeight}px \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`;
587
+ if (maxWidth) return `\uC774\uBBF8\uC9C0 \uAC00\uB85C \uD06C\uAE30\uB294 \uCD5C\uB300 ${maxWidth}px \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`;
588
+ return `\uC774\uBBF8\uC9C0 \uC138\uB85C \uD06C\uAE30\uB294 \uCD5C\uB300 ${maxHeight}px \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`;
589
+ };
590
+ const MAX_FILE_SIZE = 20 * 1024 * 1024;
591
+ const handleFileSelect = async (file) => {
592
+ if (!file) return;
593
+ if (file.size > MAX_FILE_SIZE) {
594
+ notifications.show({ title: "\uC5C5\uB85C\uB4DC \uC2E4\uD328", message: "\uD30C\uC77C \uD06C\uAE30\uB294 20MB \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.", color: "red" });
595
+ return;
596
+ }
597
+ setDimensionError(null);
598
+ const isValid = await validateImageDimensions(file, maxWidth, maxHeight);
599
+ if (!isValid) {
600
+ const msg = buildDimensionErrorMessage();
601
+ setDimensionError(msg);
602
+ notifications.show({ title: "\uC5C5\uB85C\uB4DC \uC2E4\uD328", message: msg, color: "red" });
603
+ return;
604
+ }
605
+ const src = await readFileAsDataURL(file);
606
+ if (maxCount === 1) {
607
+ onChange([src]);
608
+ } else {
609
+ onChange([...value, src]);
610
+ }
611
+ };
612
+ const handleMultipleFileSelect = async (files) => {
613
+ if (!files || files.length === 0) return;
614
+ setDimensionError(null);
615
+ const sizeOverCount = files.filter((f) => f.size > MAX_FILE_SIZE).length;
616
+ const sizeValidFiles = files.filter((f) => f.size <= MAX_FILE_SIZE);
617
+ if (sizeOverCount > 0) {
618
+ notifications.show({
619
+ title: "\uC5C5\uB85C\uB4DC \uC2E4\uD328",
620
+ message: `${sizeOverCount}\uAC1C\uC758 \uD30C\uC77C\uC774 20MB\uB97C \uCD08\uACFC\uD558\uC5EC \uC81C\uC678\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`,
621
+ color: "red"
622
+ });
623
+ }
624
+ if (sizeValidFiles.length === 0) return;
625
+ const validFiles = [];
626
+ for (const file of sizeValidFiles) {
627
+ const isValid = await validateImageDimensions(file, maxWidth, maxHeight);
628
+ if (isValid) {
629
+ validFiles.push(file);
630
+ }
631
+ }
632
+ if (validFiles.length < sizeValidFiles.length) {
633
+ const msg = buildDimensionErrorMessage();
634
+ setDimensionError(msg);
635
+ notifications.show({
636
+ title: "\uC5C5\uB85C\uB4DC \uC2E4\uD328",
637
+ message: `${sizeValidFiles.length - validFiles.length}\uAC1C\uC758 \uC774\uBBF8\uC9C0\uAC00 \uD06C\uAE30 \uC81C\uD55C\uC744 \uCD08\uACFC\uD558\uC5EC \uC81C\uC678\uB418\uC5C8\uC2B5\uB2C8\uB2E4. ${msg}`,
638
+ color: "red"
639
+ });
640
+ }
641
+ if (validFiles.length === 0) return;
642
+ const results = await Promise.all(validFiles.map(readFileAsDataURL));
643
+ onChange([...value, ...results]);
644
+ };
645
+ const handleRemove = (index) => {
646
+ onChange(value.filter((_, i) => i !== index));
647
+ };
648
+ const isAdd = maxCount === void 0 || value.length < maxCount;
649
+ if (variant === "gallery") {
650
+ return /* @__PURE__ */ jsxs(Box, { children: [
651
+ /* @__PURE__ */ jsxs(Box, { style: { display: "flex", flexWrap: "wrap", gap: 12, paddingTop: 6, paddingRight: 6 }, children: [
652
+ value.map((src, index) => /* @__PURE__ */ jsxs(Box, { style: { position: "relative", width: previewWidth, height: effectiveHeight }, children: [
653
+ /* @__PURE__ */ jsx(Image, { src, alt: "", w: previewWidth, h: effectiveHeight, fit: previewFit, radius: "sm" }),
654
+ /* @__PURE__ */ jsx(DeleteIndicator, { onClick: () => handleRemove(index) })
655
+ ] }, index)),
656
+ isAdd && /* @__PURE__ */ jsx(FileButton, { onChange: handleFileSelect, accept, children: (props) => /* @__PURE__ */ jsx(
657
+ Box,
658
+ __spreadProps(__spreadValues({}, props), {
659
+ className: "flex cursor-pointer items-center justify-center rounded border-2 border-dashed border-gray-300 hover:border-blue-400",
660
+ style: { width: previewWidth, height: effectiveHeight },
661
+ children: /* @__PURE__ */ jsx(IconPlus, { size: 24, className: "text-gray-400" })
662
+ })
663
+ ) })
664
+ ] }),
665
+ showCount && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "xs", children: [
666
+ "\uB4F1\uB85D\uB41C \uC0AC\uC9C4: ",
667
+ value.length,
668
+ "\uC7A5"
669
+ ] }),
670
+ description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mt: "xs", children: description }),
671
+ dimensionError && /* @__PURE__ */ jsx(Text, { size: "xs", c: "red", mt: "xs", children: dimensionError })
672
+ ] });
673
+ }
674
+ if (variant === "area") {
675
+ return /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center", children: [
676
+ /* @__PURE__ */ jsx(FileButton, { onChange: handleFileSelect, accept, children: (props) => /* @__PURE__ */ jsxs(
677
+ Box,
678
+ __spreadProps(__spreadValues({
679
+ style: { position: "relative", width: previewWidth, height: effectiveHeight }
680
+ }, props), {
681
+ children: [
682
+ /* @__PURE__ */ jsx(
683
+ Box,
684
+ {
685
+ className: "flex h-full w-full cursor-pointer items-center justify-center overflow-hidden rounded-md border border-gray-200 bg-gray-50 transition-colors hover:border-blue-400 hover:bg-gray-100",
686
+ children: value[0] ? /* @__PURE__ */ jsx(Image, { src: value[0], alt: "", fit: previewFit, className: "p-4" }) : /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-1", children: [
687
+ /* @__PURE__ */ jsx(IconUpload, { size: 20, className: "text-gray-400" }),
688
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", className: "font-medium", children: placeholder })
689
+ ] })
690
+ }
691
+ ),
692
+ value[0] && /* @__PURE__ */ jsx(DeleteIndicator, { onClick: () => onChange([]) })
693
+ ]
694
+ })
695
+ ) }),
696
+ description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mt: "xs", children: description }),
697
+ dimensionError && /* @__PURE__ */ jsx(Text, { size: "xs", c: "red", mt: "xs", children: dimensionError })
698
+ ] });
699
+ }
700
+ const isMultiple = maxCount === void 0 || maxCount > 1;
701
+ return /* @__PURE__ */ jsxs(Box, { children: [
702
+ isMultiple ? /* @__PURE__ */ jsx(
703
+ InputFile,
704
+ {
705
+ label,
706
+ placeholder: "\uC774\uBBF8\uC9C0\uB97C \uC120\uD0DD\uD558\uC138\uC694",
707
+ accept,
708
+ leftSection: /* @__PURE__ */ jsx(IconUpload, { size: 16 }),
709
+ onChange: handleMultipleFileSelect,
710
+ multiple: true,
711
+ value: []
712
+ }
713
+ ) : /* @__PURE__ */ jsx(
714
+ InputFile,
715
+ {
716
+ label,
717
+ placeholder: "\uC774\uBBF8\uC9C0\uB97C \uC120\uD0DD\uD558\uC138\uC694",
718
+ accept,
719
+ leftSection: /* @__PURE__ */ jsx(IconUpload, { size: 16 }),
720
+ onChange: handleFileSelect
721
+ }
722
+ ),
723
+ value.length > 0 && /* @__PURE__ */ jsx(Box, { style: { display: "flex", flexWrap: "wrap", gap: 12, paddingTop: 6, paddingRight: 6, marginTop: 8 }, children: value.map((src, index) => /* @__PURE__ */ jsxs(Box, { style: { position: "relative", width: previewWidth, height: effectiveHeight }, children: [
724
+ /* @__PURE__ */ jsx(Image, { src, alt: "", w: previewWidth, h: effectiveHeight, fit: previewFit, radius: "sm" }),
725
+ /* @__PURE__ */ jsx(DeleteIndicator, { onClick: () => handleRemove(index) })
726
+ ] }, index)) }),
727
+ showCount && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "xs", children: [
728
+ value.length,
729
+ "\uAC1C\uC758 \uC774\uBBF8\uC9C0\uAC00 \uB4F1\uB85D\uB418\uC5C8\uC2B5\uB2C8\uB2E4."
730
+ ] }),
731
+ description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mt: "xs", children: description }),
732
+ dimensionError && /* @__PURE__ */ jsx(Text, { size: "xs", c: "red", mt: "xs", children: dimensionError })
733
+ ] });
734
+ }
735
+ function PageTitle(_a) {
736
+ var _b = _a, {
737
+ title,
738
+ subText,
739
+ rightContent,
740
+ leftContent
741
+ } = _b, props = __objRest(_b, [
742
+ "title",
743
+ "subText",
744
+ "rightContent",
745
+ "leftContent"
746
+ ]);
747
+ return /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "end", mb: "xl", children: [
748
+ leftContent,
749
+ /* @__PURE__ */ jsxs(Title, __spreadProps(__spreadValues({ order: 2, c: "var(--color-brand-dark)" }, props), { children: [
750
+ title,
751
+ subText && /* @__PURE__ */ jsx(Text, { size: "md", c: "var(--color-subtitle)", mt: "5", children: subText })
752
+ ] })),
753
+ rightContent
754
+ ] });
755
+ }
756
+ function PageLoading({ bg = "transparent" }) {
757
+ return /* @__PURE__ */ jsx(Box, { pos: "fixed", top: 0, left: "var(--sidebar-width)", right: 0, bottom: 0, style: { zIndex: 400 }, children: /* @__PURE__ */ jsx(
758
+ LoadingOverlay,
759
+ {
760
+ visible: true,
761
+ overlayProps: {
762
+ backgroundOpacity: bg === "transparent" ? 0 : 1,
763
+ color: bg
764
+ }
765
+ }
766
+ ) });
767
+ }
768
+ var Panel = (_a) => {
769
+ var _b = _a, {
770
+ title,
771
+ totalCount,
772
+ description,
773
+ children,
774
+ headerRightContent,
775
+ contentBottomPadding = 40,
776
+ footer
777
+ } = _b, props = __objRest(_b, [
778
+ "title",
779
+ "totalCount",
780
+ "description",
781
+ "children",
782
+ "headerRightContent",
783
+ "contentBottomPadding",
784
+ "footer"
785
+ ]);
786
+ return /* @__PURE__ */ jsxs(Paper, __spreadProps(__spreadValues({ bg: "white", radius: "lg", shadow: "xs", className: "border-default border-1" }, props), { children: [
787
+ title && /* @__PURE__ */ jsxs("div", { className: "px-[30px]", children: [
788
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", gap: "xs", py: "24", children: [
789
+ /* @__PURE__ */ jsxs(Group, { align: "baseline", gap: "10", children: [
790
+ /* @__PURE__ */ jsx(Title, { c: "blue", order: 2, fz: 20, fw: 700, lh: "2", children: title }),
791
+ totalCount && /* @__PURE__ */ jsx(Text, { c: "blue", size: "20", lh: "1", children: totalCount })
792
+ ] }),
793
+ headerRightContent
794
+ ] }),
795
+ description && /* @__PURE__ */ jsx(Text, { c: "#666", fz: 14, fw: 400, lh: "160%", mb: "24", children: description })
796
+ ] }),
797
+ /* @__PURE__ */ jsx("div", { className: "px-[30px]", style: { paddingBottom: `${contentBottomPadding}px` }, children }),
798
+ footer && /* @__PURE__ */ jsx("div", { className: "border-gray-2 border-t px-[30px] py-5", children: footer })
799
+ ] }));
800
+ };
801
+ function Section({ title, children }) {
802
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6 last:mb-0", children: [
803
+ title && /* @__PURE__ */ jsx(Text, { c: "blue", fz: 20, fw: 700, lh: "2", py: "24", children: title }),
804
+ children
805
+ ] });
806
+ }
807
+ Panel.Section = Section;
808
+ function BoxContainer({ children }) {
809
+ return /* @__PURE__ */ jsx(
810
+ Box,
811
+ {
812
+ component: "main",
813
+ style: {
814
+ flexGrow: 1,
815
+ padding: 24
816
+ },
817
+ children
818
+ }
819
+ );
820
+ }
821
+ function EditorLayout({
822
+ leftPanel,
823
+ centerPanel,
824
+ rightPanel,
825
+ leftSpan = 2,
826
+ centerSpan = 5,
827
+ rightSpan = 5
828
+ }) {
829
+ return /* @__PURE__ */ jsxs(Grid, { gutter: "md", children: [
830
+ /* @__PURE__ */ jsx(Grid.Col, { span: leftSpan, children: leftPanel }),
831
+ /* @__PURE__ */ jsx(Grid.Col, { span: centerSpan, children: centerPanel }),
832
+ /* @__PURE__ */ jsx(Grid.Col, { span: rightSpan, children: rightPanel })
833
+ ] });
834
+ }
835
+ function Modal(_a) {
836
+ var _b = _a, {
837
+ opened,
838
+ onClose,
839
+ title,
840
+ size,
841
+ styles,
842
+ children
843
+ } = _b, props = __objRest(_b, [
844
+ "opened",
845
+ "onClose",
846
+ "title",
847
+ "size",
848
+ "styles",
849
+ "children"
850
+ ]);
851
+ var _a2, _b2, _c, _d;
852
+ return /* @__PURE__ */ jsx(
853
+ Modal$1,
854
+ __spreadProps(__spreadValues({
855
+ opened,
856
+ onClose,
857
+ title,
858
+ size,
859
+ styles
860
+ }, props), {
861
+ classNames: __spreadProps(__spreadValues({}, props.classNames), {
862
+ header: "!-mt-8 !p-6",
863
+ title: `text-center !font-bold ${(_b2 = (_a2 = props.classNames) == null ? void 0 : _a2.title) != null ? _b2 : ""}`,
864
+ body: `!p-6 ${(_d = (_c = props.classNames) == null ? void 0 : _c.body) != null ? _d : ""}`
865
+ }),
866
+ children
867
+ })
868
+ );
869
+ }
870
+ function ModalDeleteConfirm({ opened, onClose, onConfirm, message }) {
871
+ return /* @__PURE__ */ jsx(
872
+ Modal,
873
+ {
874
+ opened,
875
+ onClose,
876
+ size: "md",
877
+ centered: true,
878
+ withCloseButton: false,
879
+ classNames: { body: "text-center" },
880
+ children: /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-5", children: [
881
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-red-50", children: /* @__PURE__ */ jsx("i", { className: "text-error text-2xl", "data-fa-i2svg": "", children: /* @__PURE__ */ jsx(
882
+ "svg",
883
+ {
884
+ width: "24",
885
+ height: "24",
886
+ "aria-hidden": "true",
887
+ focusable: "false",
888
+ xmlns: "http://www.w3.org/2000/svg",
889
+ viewBox: "0 0 448 512",
890
+ children: /* @__PURE__ */ jsx(
891
+ "path",
892
+ {
893
+ fill: "currentColor",
894
+ d: "M135.2 17.7C140.6 6.8 151.7 0 163.8 0H284.2c12.1 0 23.2 6.8 28.6 17.7L320 32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32h96l7.2-14.3zM32 128H416V448c0 35.3-28.7 64-64 64H96c-35.3 0-64-28.7-64-64V128zm96 64c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16V432c0 8.8 7.2 16 16 16s16-7.2 16-16V208c0-8.8-7.2-16-16-16z"
895
+ }
896
+ )
897
+ }
898
+ ) }) }),
899
+ /* @__PURE__ */ jsx("h3", { className: "text-xl leading-tight font-bold text-gray-900", children: "\uC815\uB9D0 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?" }),
900
+ message && /* @__PURE__ */ jsx("p", { className: "-mt-2 text-sm leading-relaxed text-gray-600", children: message }),
901
+ /* @__PURE__ */ jsxs(Group, { justify: "center", gap: "xs", children: [
902
+ /* @__PURE__ */ jsx(Button, { variant: "outline", color: "gray", size: "md", onClick: onClose, children: "\uCDE8\uC18C" }),
903
+ /* @__PURE__ */ jsx(Button, { variant: "filled", color: "red", size: "md", onClick: onConfirm, children: "\uC0AD\uC81C" })
904
+ ] })
905
+ ] })
906
+ }
907
+ );
908
+ }
909
+ function ModalTokenExpired() {
910
+ const [isOpened, setIsOpened] = useState(false);
911
+ useEffect(() => {
912
+ const handleTokenExpired = () => {
913
+ setIsOpened(true);
914
+ setTimeout(() => {
915
+ localStorage.removeItem("accessToken");
916
+ localStorage.removeItem("tokenExpiresAt");
917
+ localStorage.removeItem("featureVersion");
918
+ localStorage.removeItem("units");
919
+ window.location.href = "/login";
920
+ }, 3e3);
921
+ };
922
+ window.addEventListener("token-expired", handleTokenExpired);
923
+ return () => window.removeEventListener("token-expired", handleTokenExpired);
924
+ }, []);
925
+ return /* @__PURE__ */ jsx(Modal, { opened: isOpened, onClose: () => {
926
+ }, withCloseButton: false, centered: true, size: "sm", zIndex: 1e3, children: /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-5", children: [
927
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-red-50", children: /* @__PURE__ */ jsx("i", { className: "text-error text-2xl", "data-fa-i2svg": "", children: /* @__PURE__ */ jsxs(
928
+ "svg",
929
+ {
930
+ xmlns: "http://www.w3.org/2000/svg",
931
+ width: "32",
932
+ height: "32",
933
+ viewBox: "0 0 24 24",
934
+ fill: "currentColor",
935
+ className: "icon icon-tabler icons-tabler-filled icon-tabler-exclamation-circle",
936
+ children: [
937
+ /* @__PURE__ */ jsx("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
938
+ /* @__PURE__ */ jsx("path", { d: "M17 3.34a10 10 0 1 1 -15 8.66l.005 -.324a10 10 0 0 1 14.995 -8.336m-5 11.66a1 1 0 0 0 -1 1v.01a1 1 0 0 0 2 0v-.01a1 1 0 0 0 -1 -1m0 -7a1 1 0 0 0 -1 1v4a1 1 0 0 0 2 0v-4a1 1 0 0 0 -1 -1" })
939
+ ]
940
+ }
941
+ ) }) }),
942
+ /* @__PURE__ */ jsxs(Text, { ta: "center", fw: 600, size: "lg", mb: "xs", children: [
943
+ "\uD1A0\uD070\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4 ",
944
+ /* @__PURE__ */ jsx("br", {}),
945
+ "\uC7A0\uC2DC \uD6C4 \uB85C\uADF8\uC778 \uD398\uC774\uC9C0\uB85C \uC774\uB3D9\uD569\uB2C8\uB2E4."
946
+ ] })
947
+ ] }) });
948
+ }
949
+ function DataTable({
950
+ columns,
951
+ data,
952
+ getRowId,
953
+ onRowClick,
954
+ rowsPerPageOptions = [5, 10, 25, 50],
955
+ defaultRowsPerPage = 10,
956
+ style,
957
+ containerStyle,
958
+ rowStyle,
959
+ emptyMessage = "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
960
+ }) {
961
+ const [page, setPage] = useState(1);
962
+ const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);
963
+ const [mounted, setMounted] = useState(false);
964
+ useEffect(() => {
965
+ setMounted(true);
966
+ }, []);
967
+ const paginatedData = useMemo(() => {
968
+ const startIndex = (page - 1) * rowsPerPage;
969
+ const endIndex = startIndex + rowsPerPage;
970
+ return data.slice(startIndex, endIndex);
971
+ }, [data, page, rowsPerPage]);
972
+ const totalPages = Math.ceil(data.length / rowsPerPage);
973
+ const handleRowClick = (row) => {
974
+ if (onRowClick) {
975
+ onRowClick(row);
976
+ }
977
+ };
978
+ return /* @__PURE__ */ jsxs(Paper, { shadow: "xs", p: "md", mt: "md", style: containerStyle, children: [
979
+ /* @__PURE__ */ jsxs(Table$1, { style, highlightOnHover: !!onRowClick, children: [
980
+ /* @__PURE__ */ jsx(Table$1.Thead, { children: /* @__PURE__ */ jsx(Table$1.Tr, { children: columns.map((column) => /* @__PURE__ */ jsx(
981
+ Table$1.Th,
982
+ {
983
+ style: __spreadValues({
984
+ minWidth: column.minWidth,
985
+ fontWeight: "bold",
986
+ textAlign: column.align || "left"
987
+ }, column.headerStyle),
988
+ children: column.label
989
+ },
990
+ column.id
991
+ )) }) }),
992
+ /* @__PURE__ */ jsx(Table$1.Tbody, { children: paginatedData.length === 0 ? /* @__PURE__ */ jsx(Table$1.Tr, { children: /* @__PURE__ */ jsx(Table$1.Td, { colSpan: columns.length, style: { textAlign: "center", padding: "32px" }, children: emptyMessage }) }) : paginatedData.map((row, index) => /* @__PURE__ */ jsx(
993
+ Table$1.Tr,
994
+ {
995
+ onClick: () => handleRowClick(row),
996
+ style: __spreadValues({
997
+ cursor: onRowClick ? "pointer" : "default"
998
+ }, rowStyle),
999
+ children: columns.map((column) => {
1000
+ const value = row[column.id];
1001
+ return /* @__PURE__ */ jsxs(
1002
+ Table$1.Td,
1003
+ {
1004
+ suppressHydrationWarning: true,
1005
+ style: __spreadValues({
1006
+ textAlign: column.align || "left"
1007
+ }, column.style),
1008
+ children: [
1009
+ column.id === "no" ? mounted ? (page - 1) * rowsPerPage + index + 1 : null : null,
1010
+ column.id !== "no" && (column.format ? column.format(value, row) : value)
1011
+ ]
1012
+ },
1013
+ column.id
1014
+ );
1015
+ })
1016
+ },
1017
+ getRowId(row)
1018
+ )) })
1019
+ ] }),
1020
+ /* @__PURE__ */ jsx(Box, { mt: "md", className: "flex justify-end", children: /* @__PURE__ */ jsx(Pagination$1, { value: page, onChange: setPage, total: totalPages }) })
1021
+ ] });
1022
+ }
1023
+ function PageHeader({ headerText, back }) {
1024
+ const router = useRouter();
1025
+ const handleBack = () => {
1026
+ router.back();
1027
+ };
1028
+ return /* @__PURE__ */ jsxs(Box, { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1029
+ back && /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "lg", onClick: handleBack, children: /* @__PURE__ */ jsx(IconArrowLeft, { size: 20 }) }),
1030
+ /* @__PURE__ */ jsx(Title, { order: 2, children: headerText })
1031
+ ] });
1032
+ }
1033
+ var SectionGroupWithTitle = ({ title, children }) => {
1034
+ return /* @__PURE__ */ jsxs(Box, { children: [
1035
+ /* @__PURE__ */ jsx(Text, { fw: 600, mb: "sm", children: title }),
1036
+ /* @__PURE__ */ jsx(Divider, { mb: "xs" }),
1037
+ children
1038
+ ] });
1039
+ };
1040
+ var SectionGroupWithTitle_default = SectionGroupWithTitle;
1041
+ function TagInput({
1042
+ label,
1043
+ placeholder,
1044
+ items,
1045
+ onAdd,
1046
+ onRemove,
1047
+ badgeVariant = "filled",
1048
+ badgeColor = "blue"
1049
+ }) {
1050
+ const [inputValue, setInputValue] = useState("");
1051
+ const handleAdd = () => {
1052
+ if (!inputValue.trim()) return;
1053
+ const values = inputValue.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
1054
+ onAdd(values);
1055
+ setInputValue("");
1056
+ };
1057
+ return /* @__PURE__ */ jsxs(Box, { children: [
1058
+ /* @__PURE__ */ jsx(
1059
+ InputText,
1060
+ {
1061
+ size: "xs",
1062
+ label,
1063
+ placeholder,
1064
+ value: inputValue,
1065
+ onChange: (e) => setInputValue(e.currentTarget.value),
1066
+ onKeyDown: (e) => {
1067
+ if (e.key === "Enter" && !e.nativeEvent.isComposing) {
1068
+ e.preventDefault();
1069
+ handleAdd();
1070
+ }
1071
+ },
1072
+ rightSection: /* @__PURE__ */ jsx(Button, { size: "xs", variant: "light", onClick: handleAdd, children: /* @__PURE__ */ jsx(IconPlus, { size: 10 }) }),
1073
+ rightSectionWidth: 27,
1074
+ mb: "xs"
1075
+ }
1076
+ ),
1077
+ items.length > 0 && /* @__PURE__ */ jsx(Group, { gap: 4, children: items.map((item) => /* @__PURE__ */ jsx(
1078
+ Badge,
1079
+ {
1080
+ size: "sm",
1081
+ variant: badgeVariant,
1082
+ color: badgeColor,
1083
+ h: "24",
1084
+ rightSection: /* @__PURE__ */ jsx(
1085
+ ActionIcon,
1086
+ {
1087
+ size: 14,
1088
+ variant: "transparent",
1089
+ c: badgeVariant === "light" ? "gray" : "white",
1090
+ onClick: () => onRemove(item.id),
1091
+ children: /* @__PURE__ */ jsx(IconX, { size: 10 })
1092
+ }
1093
+ ),
1094
+ children: item.label
1095
+ },
1096
+ item.id
1097
+ )) })
1098
+ ] });
1099
+ }
1100
+ function StrictModeDroppable(_a) {
1101
+ var _b = _a, { children } = _b, props = __objRest(_b, ["children"]);
1102
+ const [isEnabled, setIsEnabled] = useState(false);
1103
+ useEffect(() => {
1104
+ const animation = requestAnimationFrame(() => setIsEnabled(true));
1105
+ return () => {
1106
+ cancelAnimationFrame(animation);
1107
+ setIsEnabled(false);
1108
+ };
1109
+ }, []);
1110
+ if (!isEnabled) return null;
1111
+ return /* @__PURE__ */ jsx(Droppable, __spreadProps(__spreadValues({}, props), { children }));
1112
+ }
1113
+ function AccordionDraggable({
1114
+ items,
1115
+ droppableId = "draggable-accordion",
1116
+ activeId = null,
1117
+ onActiveChange,
1118
+ onReorder,
1119
+ onDelete,
1120
+ onRequiredChange,
1121
+ onUsedChange,
1122
+ emptyMessage = "\uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
1123
+ showDeleteButton = true,
1124
+ showRequiredToggle = false,
1125
+ showUsedToggle = false,
1126
+ draggingBgColor = "var(--color-dragging)"
1127
+ }) {
1128
+ if (items.length === 0) {
1129
+ return /* @__PURE__ */ jsx(Box, { style: { padding: 40, textAlign: "center" }, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", children: emptyMessage }) });
1130
+ }
1131
+ return /* @__PURE__ */ jsx(DragDropContext, { onDragEnd: onReorder, children: /* @__PURE__ */ jsx(StrictModeDroppable, { droppableId, children: (provided) => /* @__PURE__ */ jsx(Box, __spreadProps(__spreadValues({ ref: provided.innerRef }, provided.droppableProps), { children: /* @__PURE__ */ jsxs(
1132
+ Accordion.Root,
1133
+ {
1134
+ variant: "separated",
1135
+ value: activeId,
1136
+ onChange: onActiveChange,
1137
+ classNames: { label: "!py-0", content: "!p-6 !pb-10" },
1138
+ children: [
1139
+ items.map((item, index) => /* @__PURE__ */ jsx(Draggable, { draggableId: item.id, index, children: (provided2) => {
1140
+ var _a, _b;
1141
+ return /* @__PURE__ */ jsx(
1142
+ Box,
1143
+ __spreadProps(__spreadValues({
1144
+ ref: provided2.innerRef
1145
+ }, provided2.draggableProps), {
1146
+ style: __spreadProps(__spreadValues({}, provided2.draggableProps.style), {
1147
+ marginBottom: 8
1148
+ }),
1149
+ children: /* @__PURE__ */ jsxs(
1150
+ Accordion.Item,
1151
+ {
1152
+ value: item.id,
1153
+ "data-active": activeId === item.id || void 0,
1154
+ style: { backgroundColor: draggingBgColor },
1155
+ className: "group data-[active]:!bg-[var(--color-active,transparent)]",
1156
+ children: [
1157
+ /* @__PURE__ */ jsx(
1158
+ Accordion.Control,
1159
+ {
1160
+ icon: item.icon,
1161
+ className: "group-data-[active]:!border-b group-data-[active]:!border-gray-200",
1162
+ children: /* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", style: { width: "100%" }, children: [
1163
+ /* @__PURE__ */ jsx("span", __spreadProps(__spreadValues({}, provided2.dragHandleProps), { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(GripVerticalIcon, {}) })),
1164
+ /* @__PURE__ */ jsx(Text, { fw: 500, className: "flex-1 !text-[15px]", children: item.title }),
1165
+ item.rightSection && /* @__PURE__ */ jsx(
1166
+ Box,
1167
+ {
1168
+ onClick: (e) => e.stopPropagation(),
1169
+ style: {
1170
+ marginRight: 16,
1171
+ padding: "4px 8px",
1172
+ borderRadius: 4,
1173
+ backgroundColor: "var(--color-right-section)"
1174
+ },
1175
+ children: item.rightSection
1176
+ }
1177
+ ),
1178
+ (showRequiredToggle || showUsedToggle) && !item.rightSection && /* @__PURE__ */ jsxs(
1179
+ Group,
1180
+ {
1181
+ gap: "sm",
1182
+ wrap: "nowrap",
1183
+ className: "mr-6 h-5 border-r border-[#E1E4E8] pr-6",
1184
+ onClick: (e) => e.stopPropagation(),
1185
+ children: [
1186
+ showUsedToggle && onUsedChange && /* @__PURE__ */ jsx(
1187
+ Checkbox,
1188
+ {
1189
+ checked: (_a = item.isUsed) != null ? _a : false,
1190
+ onChange: (e) => onUsedChange(item.id, e.currentTarget.checked),
1191
+ label: "\uC0AC\uC6A9"
1192
+ }
1193
+ ),
1194
+ showRequiredToggle && onRequiredChange && /* @__PURE__ */ jsx(
1195
+ Checkbox,
1196
+ {
1197
+ checked: (_b = item.isRequired) != null ? _b : false,
1198
+ onChange: (e) => onRequiredChange(item.id, e.currentTarget.checked),
1199
+ label: "\uD544\uC218"
1200
+ }
1201
+ )
1202
+ ]
1203
+ }
1204
+ ),
1205
+ showDeleteButton && onDelete && !item.rightSection && /* @__PURE__ */ jsx(
1206
+ "span",
1207
+ {
1208
+ className: "mr-6 h-5 border-r border-[#E1E4E8] pr-6",
1209
+ onClick: (e) => {
1210
+ e.stopPropagation();
1211
+ onDelete(item.id);
1212
+ },
1213
+ children: /* @__PURE__ */ jsx(TrashIcon, { color: "red" })
1214
+ }
1215
+ )
1216
+ ] })
1217
+ }
1218
+ ),
1219
+ /* @__PURE__ */ jsx(Accordion.Panel, { children: /* @__PURE__ */ jsx(Stack, { gap: "24", children: item.content }) })
1220
+ ]
1221
+ }
1222
+ )
1223
+ })
1224
+ );
1225
+ } }, item.id)),
1226
+ provided.placeholder
1227
+ ]
1228
+ }
1229
+ ) })) }) });
1230
+ }
1231
+
1232
+ export { Accordion, AccordionDraggable, Badge, BoxContainer, Button, ChevronDownIcon, ComboboxAutocomplete, ComboboxSelect, DataTable, DateTimePicker, EditorLayout, GripVerticalIcon, IconButton, ImageUpload, InputColor, InputDatePicker, InputFile, InputNumber, InputPassword, InputRadio, InputSegmentedControl, InputSwitch, InputSwitchInTable, InputText, InputTextarea, Modal, ModalDeleteConfirm, ModalTokenExpired, NavigationBanner, PageHeader, PageLoading, PageTitle, Pagination, Panel, PlusIcon, SectionGroupWithTitle_default as SectionGroupWithTitle, Table, TagInput, TrashIcon, inputClassNames, readFileAsDataURL };
1233
+ //# sourceMappingURL=index.mjs.map
1234
+ //# sourceMappingURL=index.mjs.map