@withwiz/cms-kit 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.
- package/README.ko.md +146 -0
- package/README.md +146 -0
- package/dist/chunk-2REYWBQ6.js +32 -0
- package/dist/chunk-2REYWBQ6.js.map +1 -0
- package/dist/chunk-2SYUEQ6J.mjs +17 -0
- package/dist/chunk-2SYUEQ6J.mjs.map +1 -0
- package/dist/chunk-3ILEMZAL.mjs +32 -0
- package/dist/chunk-3ILEMZAL.mjs.map +1 -0
- package/dist/chunk-3Y2TQCHU.mjs +33 -0
- package/dist/chunk-3Y2TQCHU.mjs.map +1 -0
- package/dist/chunk-4LSFAAZW.js +1 -0
- package/dist/chunk-4LSFAAZW.js.map +1 -0
- package/dist/chunk-4W3X7OKF.js +100 -0
- package/dist/chunk-4W3X7OKF.js.map +1 -0
- package/dist/chunk-5JUIMXNF.js +108 -0
- package/dist/chunk-5JUIMXNF.js.map +1 -0
- package/dist/chunk-5RDMODGV.mjs +34 -0
- package/dist/chunk-5RDMODGV.mjs.map +1 -0
- package/dist/chunk-6ES4W2DL.mjs +1 -0
- package/dist/chunk-6ES4W2DL.mjs.map +1 -0
- package/dist/chunk-6EZ3QE5N.js +71 -0
- package/dist/chunk-6EZ3QE5N.js.map +1 -0
- package/dist/chunk-6JFERXNE.mjs +16 -0
- package/dist/chunk-6JFERXNE.mjs.map +1 -0
- package/dist/chunk-7SWW3ZIN.js +17 -0
- package/dist/chunk-7SWW3ZIN.js.map +1 -0
- package/dist/chunk-AXR56AUD.mjs +1 -0
- package/dist/chunk-AXR56AUD.mjs.map +1 -0
- package/dist/chunk-BE7JDL64.js +154 -0
- package/dist/chunk-BE7JDL64.js.map +1 -0
- package/dist/chunk-BHN2SRZC.js +51 -0
- package/dist/chunk-BHN2SRZC.js.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +11 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/chunk-BWKKHCDG.mjs +164 -0
- package/dist/chunk-BWKKHCDG.mjs.map +1 -0
- package/dist/chunk-C5WFZJM4.js +218 -0
- package/dist/chunk-C5WFZJM4.js.map +1 -0
- package/dist/chunk-CGVFB23E.mjs +123 -0
- package/dist/chunk-CGVFB23E.mjs.map +1 -0
- package/dist/chunk-D2VDTRXO.js +1 -0
- package/dist/chunk-D2VDTRXO.js.map +1 -0
- package/dist/chunk-D75ADHVM.mjs +181 -0
- package/dist/chunk-D75ADHVM.mjs.map +1 -0
- package/dist/chunk-DCIF4XJL.js +309 -0
- package/dist/chunk-DCIF4XJL.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-DSORCGJK.js +44 -0
- package/dist/chunk-DSORCGJK.js.map +1 -0
- package/dist/chunk-E5YUAOJI.js +27 -0
- package/dist/chunk-E5YUAOJI.js.map +1 -0
- package/dist/chunk-EG6NVPP2.js +164 -0
- package/dist/chunk-EG6NVPP2.js.map +1 -0
- package/dist/chunk-EL7YGOTY.js +1 -0
- package/dist/chunk-EL7YGOTY.js.map +1 -0
- package/dist/chunk-EM4MQEWV.mjs +100 -0
- package/dist/chunk-EM4MQEWV.mjs.map +1 -0
- package/dist/chunk-FCCCG5Z7.mjs +108 -0
- package/dist/chunk-FCCCG5Z7.mjs.map +1 -0
- package/dist/chunk-FEPGJ7WN.mjs +218 -0
- package/dist/chunk-FEPGJ7WN.mjs.map +1 -0
- package/dist/chunk-HXVWBFCN.js +16 -0
- package/dist/chunk-HXVWBFCN.js.map +1 -0
- package/dist/chunk-I5YMTJV6.mjs +51 -0
- package/dist/chunk-I5YMTJV6.mjs.map +1 -0
- package/dist/chunk-IMNWW7Q5.mjs +13 -0
- package/dist/chunk-IMNWW7Q5.mjs.map +1 -0
- package/dist/chunk-J5N76ASB.mjs +114 -0
- package/dist/chunk-J5N76ASB.mjs.map +1 -0
- package/dist/chunk-JBV26CUG.mjs +51 -0
- package/dist/chunk-JBV26CUG.mjs.map +1 -0
- package/dist/chunk-JMWXVXK5.js +53 -0
- package/dist/chunk-JMWXVXK5.js.map +1 -0
- package/dist/chunk-KWKV2GAH.js +60 -0
- package/dist/chunk-KWKV2GAH.js.map +1 -0
- package/dist/chunk-LDFE33ML.mjs +53 -0
- package/dist/chunk-LDFE33ML.mjs.map +1 -0
- package/dist/chunk-LF5LOI7K.mjs +174 -0
- package/dist/chunk-LF5LOI7K.mjs.map +1 -0
- package/dist/chunk-MMKAMH4U.mjs +16 -0
- package/dist/chunk-MMKAMH4U.mjs.map +1 -0
- package/dist/chunk-MUHFEEYW.js +33 -0
- package/dist/chunk-MUHFEEYW.js.map +1 -0
- package/dist/chunk-MUQYK5EO.js +1 -0
- package/dist/chunk-MUQYK5EO.js.map +1 -0
- package/dist/chunk-OBNALAMG.mjs +71 -0
- package/dist/chunk-OBNALAMG.mjs.map +1 -0
- package/dist/chunk-OLEYNPW6.js +25 -0
- package/dist/chunk-OLEYNPW6.js.map +1 -0
- package/dist/chunk-OYJRR3G2.js +123 -0
- package/dist/chunk-OYJRR3G2.js.map +1 -0
- package/dist/chunk-PLVG7AW3.js +16 -0
- package/dist/chunk-PLVG7AW3.js.map +1 -0
- package/dist/chunk-PYD4CES4.js +1 -0
- package/dist/chunk-PYD4CES4.js.map +1 -0
- package/dist/chunk-QACD2U6P.mjs +1 -0
- package/dist/chunk-QACD2U6P.mjs.map +1 -0
- package/dist/chunk-R5GGIVD4.js +10 -0
- package/dist/chunk-R5GGIVD4.js.map +1 -0
- package/dist/chunk-RCK5WCU5.mjs +25 -0
- package/dist/chunk-RCK5WCU5.mjs.map +1 -0
- package/dist/chunk-S6UUSM7S.js +13 -0
- package/dist/chunk-S6UUSM7S.js.map +1 -0
- package/dist/chunk-S7GOXCRM.js +114 -0
- package/dist/chunk-S7GOXCRM.js.map +1 -0
- package/dist/chunk-SMV5D5LO.mjs +28 -0
- package/dist/chunk-SMV5D5LO.mjs.map +1 -0
- package/dist/chunk-T7EVFD4G.mjs +60 -0
- package/dist/chunk-T7EVFD4G.mjs.map +1 -0
- package/dist/chunk-TLH3V4SY.mjs +1 -0
- package/dist/chunk-TLH3V4SY.mjs.map +1 -0
- package/dist/chunk-TUQ2CVAK.mjs +10 -0
- package/dist/chunk-TUQ2CVAK.mjs.map +1 -0
- package/dist/chunk-U6PVJKTB.js +51 -0
- package/dist/chunk-U6PVJKTB.js.map +1 -0
- package/dist/chunk-UXMMEEX4.mjs +27 -0
- package/dist/chunk-UXMMEEX4.mjs.map +1 -0
- package/dist/chunk-VVXNFFKI.mjs +44 -0
- package/dist/chunk-VVXNFFKI.mjs.map +1 -0
- package/dist/chunk-VZZ3RU3Q.js +28 -0
- package/dist/chunk-VZZ3RU3Q.js.map +1 -0
- package/dist/chunk-W4FWIZ2Y.js +34 -0
- package/dist/chunk-W4FWIZ2Y.js.map +1 -0
- package/dist/chunk-YEQFKOWD.mjs +154 -0
- package/dist/chunk-YEQFKOWD.mjs.map +1 -0
- package/dist/chunk-YPBKY4KY.mjs +1 -0
- package/dist/chunk-YPBKY4KY.mjs.map +1 -0
- package/dist/chunk-YY7K5CXX.js +174 -0
- package/dist/chunk-YY7K5CXX.js.map +1 -0
- package/dist/chunk-ZFORODOX.js +181 -0
- package/dist/chunk-ZFORODOX.js.map +1 -0
- package/dist/chunk-ZULSFSDG.mjs +309 -0
- package/dist/chunk-ZULSFSDG.mjs.map +1 -0
- package/dist/components/AdminManagerBase.d.mts +26 -0
- package/dist/components/AdminManagerBase.d.ts +26 -0
- package/dist/components/AdminManagerBase.js +13 -0
- package/dist/components/AdminManagerBase.js.map +1 -0
- package/dist/components/AdminManagerBase.mjs +12 -0
- package/dist/components/AdminManagerBase.mjs.map +1 -0
- package/dist/components/AdminManagerConfig.d.mts +83 -0
- package/dist/components/AdminManagerConfig.d.ts +83 -0
- package/dist/components/AdminManagerConfig.js +2 -0
- package/dist/components/AdminManagerConfig.js.map +1 -0
- package/dist/components/AdminManagerConfig.mjs +2 -0
- package/dist/components/AdminManagerConfig.mjs.map +1 -0
- package/dist/components/AdminShell.d.mts +30 -0
- package/dist/components/AdminShell.d.ts +30 -0
- package/dist/components/AdminShell.js +12 -0
- package/dist/components/AdminShell.js.map +1 -0
- package/dist/components/AdminShell.mjs +11 -0
- package/dist/components/AdminShell.mjs.map +1 -0
- package/dist/components/JsonLd.d.mts +32 -0
- package/dist/components/JsonLd.d.ts +32 -0
- package/dist/components/JsonLd.js +11 -0
- package/dist/components/JsonLd.js.map +1 -0
- package/dist/components/JsonLd.mjs +11 -0
- package/dist/components/JsonLd.mjs.map +1 -0
- package/dist/components/ResizableImage.d.mts +18 -0
- package/dist/components/ResizableImage.d.ts +18 -0
- package/dist/components/ResizableImage.js +10 -0
- package/dist/components/ResizableImage.js.map +1 -0
- package/dist/components/ResizableImage.mjs +9 -0
- package/dist/components/ResizableImage.mjs.map +1 -0
- package/dist/components/ToggleSwitch.d.mts +11 -0
- package/dist/components/ToggleSwitch.d.ts +11 -0
- package/dist/components/ToggleSwitch.js +10 -0
- package/dist/components/ToggleSwitch.js.map +1 -0
- package/dist/components/ToggleSwitch.mjs +9 -0
- package/dist/components/ToggleSwitch.mjs.map +1 -0
- package/dist/components/image-drop-zone.css +115 -0
- package/dist/components/index.d.mts +26 -0
- package/dist/components/index.d.ts +26 -0
- package/dist/components/index.js +35 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +35 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/components/toggle-switch.css +55 -0
- package/dist/hooks/index.d.mts +45 -0
- package/dist/hooks/index.d.ts +45 -0
- package/dist/hooks/index.js +25 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +25 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/hooks/useImageDropZone.d.mts +37 -0
- package/dist/hooks/useImageDropZone.d.ts +37 -0
- package/dist/hooks/useImageDropZone.js +13 -0
- package/dist/hooks/useImageDropZone.js.map +1 -0
- package/dist/hooks/useImageDropZone.mjs +12 -0
- package/dist/hooks/useImageDropZone.mjs.map +1 -0
- package/dist/hooks/useScrollReveal.d.mts +6 -0
- package/dist/hooks/useScrollReveal.d.ts +6 -0
- package/dist/hooks/useScrollReveal.js +12 -0
- package/dist/hooks/useScrollReveal.js.map +1 -0
- package/dist/hooks/useScrollReveal.mjs +11 -0
- package/dist/hooks/useScrollReveal.mjs.map +1 -0
- package/dist/image-drop-zone.css +115 -0
- package/dist/index-00a40-FQ.d.mts +136 -0
- package/dist/index-00a40-FQ.d.ts +136 -0
- package/dist/index.d.mts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +169 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +169 -0
- package/dist/index.mjs.map +1 -0
- package/dist/infrastructure/index.d.mts +4 -0
- package/dist/infrastructure/index.d.ts +4 -0
- package/dist/infrastructure/index.js +20 -0
- package/dist/infrastructure/index.js.map +1 -0
- package/dist/infrastructure/index.mjs +20 -0
- package/dist/infrastructure/index.mjs.map +1 -0
- package/dist/infrastructure/middleware/index.d.mts +3 -0
- package/dist/infrastructure/middleware/index.d.ts +3 -0
- package/dist/infrastructure/middleware/index.js +15 -0
- package/dist/infrastructure/middleware/index.js.map +1 -0
- package/dist/infrastructure/middleware/index.mjs +15 -0
- package/dist/infrastructure/middleware/index.mjs.map +1 -0
- package/dist/infrastructure/middleware/wrappers.d.mts +10 -0
- package/dist/infrastructure/middleware/wrappers.d.ts +10 -0
- package/dist/infrastructure/middleware/wrappers.js +15 -0
- package/dist/infrastructure/middleware/wrappers.js.map +1 -0
- package/dist/infrastructure/middleware/wrappers.mjs +15 -0
- package/dist/infrastructure/middleware/wrappers.mjs.map +1 -0
- package/dist/infrastructure/prisma.d.mts +5 -0
- package/dist/infrastructure/prisma.d.ts +5 -0
- package/dist/infrastructure/prisma.js +12 -0
- package/dist/infrastructure/prisma.js.map +1 -0
- package/dist/infrastructure/prisma.mjs +12 -0
- package/dist/infrastructure/prisma.mjs.map +1 -0
- package/dist/services/index.d.mts +22 -0
- package/dist/services/index.d.ts +22 -0
- package/dist/services/index.js +36 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/index.mjs +36 -0
- package/dist/services/index.mjs.map +1 -0
- package/dist/toggle-switch.css +55 -0
- package/dist/types/common.d.mts +14 -0
- package/dist/types/common.d.ts +14 -0
- package/dist/types/common.js +8 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/common.mjs +8 -0
- package/dist/types/common.mjs.map +1 -0
- package/dist/types/index.d.mts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +9 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/utils/admin-fetch.d.mts +11 -0
- package/dist/utils/admin-fetch.d.ts +11 -0
- package/dist/utils/admin-fetch.js +13 -0
- package/dist/utils/admin-fetch.js.map +1 -0
- package/dist/utils/admin-fetch.mjs +13 -0
- package/dist/utils/admin-fetch.mjs.map +1 -0
- package/dist/utils/api-helpers.d.mts +20 -0
- package/dist/utils/api-helpers.d.ts +20 -0
- package/dist/utils/api-helpers.js +12 -0
- package/dist/utils/api-helpers.js.map +1 -0
- package/dist/utils/api-helpers.mjs +12 -0
- package/dist/utils/api-helpers.mjs.map +1 -0
- package/dist/utils/date.d.mts +5 -0
- package/dist/utils/date.d.ts +5 -0
- package/dist/utils/date.js +12 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/date.mjs +12 -0
- package/dist/utils/date.mjs.map +1 -0
- package/dist/utils/html-sanitizer.d.mts +56 -0
- package/dist/utils/html-sanitizer.d.ts +56 -0
- package/dist/utils/html-sanitizer.js +11 -0
- package/dist/utils/html-sanitizer.js.map +1 -0
- package/dist/utils/html-sanitizer.mjs +11 -0
- package/dist/utils/html-sanitizer.mjs.map +1 -0
- package/dist/utils/image-variant-utils.d.mts +14 -0
- package/dist/utils/image-variant-utils.d.ts +14 -0
- package/dist/utils/image-variant-utils.js +10 -0
- package/dist/utils/image-variant-utils.js.map +1 -0
- package/dist/utils/image-variant-utils.mjs +10 -0
- package/dist/utils/image-variant-utils.mjs.map +1 -0
- package/dist/utils/image-variants.d.mts +13 -0
- package/dist/utils/image-variants.d.ts +13 -0
- package/dist/utils/image-variants.js +12 -0
- package/dist/utils/image-variants.js.map +1 -0
- package/dist/utils/image-variants.mjs +12 -0
- package/dist/utils/image-variants.mjs.map +1 -0
- package/dist/utils/index.d.mts +88 -0
- package/dist/utils/index.d.ts +88 -0
- package/dist/utils/index.js +92 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +92 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/jwt.d.mts +19 -0
- package/dist/utils/jwt.d.ts +19 -0
- package/dist/utils/jwt.js +9 -0
- package/dist/utils/jwt.js.map +1 -0
- package/dist/utils/jwt.mjs +9 -0
- package/dist/utils/jwt.mjs.map +1 -0
- package/dist/utils/r2-helpers.d.mts +9 -0
- package/dist/utils/r2-helpers.d.ts +9 -0
- package/dist/utils/r2-helpers.js +20 -0
- package/dist/utils/r2-helpers.js.map +1 -0
- package/dist/utils/r2-helpers.mjs +20 -0
- package/dist/utils/r2-helpers.mjs.map +1 -0
- package/dist/utils/r2-storage.d.mts +38 -0
- package/dist/utils/r2-storage.d.ts +38 -0
- package/dist/utils/r2-storage.js +17 -0
- package/dist/utils/r2-storage.js.map +1 -0
- package/dist/utils/r2-storage.mjs +17 -0
- package/dist/utils/r2-storage.mjs.map +1 -0
- package/dist/utils/route-params.d.mts +3 -0
- package/dist/utils/route-params.d.ts +3 -0
- package/dist/utils/route-params.js +8 -0
- package/dist/utils/route-params.js.map +1 -0
- package/dist/utils/route-params.mjs +8 -0
- package/dist/utils/route-params.mjs.map +1 -0
- package/dist/validators/index.d.mts +2 -0
- package/dist/validators/index.d.ts +2 -0
- package/dist/validators/index.js +11 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/validators/index.mjs +11 -0
- package/dist/validators/index.mjs.map +1 -0
- package/dist/validators/shared.d.mts +6 -0
- package/dist/validators/shared.d.ts +6 -0
- package/dist/validators/shared.js +10 -0
- package/dist/validators/shared.js.map +1 -0
- package/dist/validators/shared.mjs +10 -0
- package/dist/validators/shared.mjs.map +1 -0
- package/package.json +257 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useAdminForm,
|
|
3
|
+
useAdminList
|
|
4
|
+
} from "./chunk-FCCCG5Z7.mjs";
|
|
5
|
+
import {
|
|
6
|
+
adminFetch,
|
|
7
|
+
getAuthHeaders
|
|
8
|
+
} from "./chunk-T7EVFD4G.mjs";
|
|
9
|
+
|
|
10
|
+
// src/components/AdminManagerBase.tsx
|
|
11
|
+
import { useCallback, useEffect, useImperativeHandle, useMemo, useRef } from "react";
|
|
12
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
13
|
+
import { toast } from "sonner";
|
|
14
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
function AdminManagerBaseInner({
|
|
16
|
+
initialItems,
|
|
17
|
+
config,
|
|
18
|
+
initialSelectedId,
|
|
19
|
+
startWithNew,
|
|
20
|
+
defaultFilterValue,
|
|
21
|
+
innerRef
|
|
22
|
+
}) {
|
|
23
|
+
const list = useAdminList({
|
|
24
|
+
initialItems,
|
|
25
|
+
apiPath: config.apiPath,
|
|
26
|
+
defaultSortKey: config.defaultSortKey,
|
|
27
|
+
normalizeItem: config.normalizeListItem,
|
|
28
|
+
defaultFilterValue
|
|
29
|
+
});
|
|
30
|
+
const {
|
|
31
|
+
items,
|
|
32
|
+
setItems,
|
|
33
|
+
searchQuery,
|
|
34
|
+
setSearchQuery,
|
|
35
|
+
sortKey,
|
|
36
|
+
setSortKey,
|
|
37
|
+
filterValue,
|
|
38
|
+
setFilterValue
|
|
39
|
+
} = list;
|
|
40
|
+
const adminForm = useAdminForm(config.emptyForm);
|
|
41
|
+
const {
|
|
42
|
+
tab,
|
|
43
|
+
setTab,
|
|
44
|
+
form,
|
|
45
|
+
setForm,
|
|
46
|
+
updateField,
|
|
47
|
+
selectedId,
|
|
48
|
+
setSelectedId,
|
|
49
|
+
isNew,
|
|
50
|
+
setIsNew,
|
|
51
|
+
saving,
|
|
52
|
+
setSaving,
|
|
53
|
+
loading,
|
|
54
|
+
setLoading,
|
|
55
|
+
mobilePv,
|
|
56
|
+
setMobilePv,
|
|
57
|
+
addNew,
|
|
58
|
+
startEdit
|
|
59
|
+
} = adminForm;
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (startWithNew) {
|
|
62
|
+
handleAdd();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (initialSelectedId) {
|
|
66
|
+
selectItem(initialSelectedId);
|
|
67
|
+
}
|
|
68
|
+
}, []);
|
|
69
|
+
const filteredItems = useMemo(
|
|
70
|
+
() => config.filterItems(items, filterValue, searchQuery),
|
|
71
|
+
[items, filterValue, searchQuery, config]
|
|
72
|
+
);
|
|
73
|
+
const publishedItems = useMemo(
|
|
74
|
+
() => items.filter(config.meta.getItemPublished),
|
|
75
|
+
[items, config]
|
|
76
|
+
);
|
|
77
|
+
const selectItem = useCallback(async (id) => {
|
|
78
|
+
startEdit(id, config.emptyForm);
|
|
79
|
+
try {
|
|
80
|
+
const res = await adminFetch(`${config.apiPath}/${id}`);
|
|
81
|
+
const json = await res.json();
|
|
82
|
+
if (json.success) {
|
|
83
|
+
setForm(config.loadItem(json.data));
|
|
84
|
+
} else {
|
|
85
|
+
toast.error(json.error?.message || "\uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328");
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
toast.error("\uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328");
|
|
89
|
+
} finally {
|
|
90
|
+
setLoading(false);
|
|
91
|
+
}
|
|
92
|
+
}, [config.apiPath, config.loadItem, config.emptyForm]);
|
|
93
|
+
useImperativeHandle(innerRef, () => ({ selectItem }), [selectItem]);
|
|
94
|
+
const handleAdd = useCallback(() => {
|
|
95
|
+
addNew(config.emptyForm);
|
|
96
|
+
}, [config.emptyForm]);
|
|
97
|
+
async function handleSave() {
|
|
98
|
+
const err = config.validate(form);
|
|
99
|
+
if (err) {
|
|
100
|
+
toast.error(err);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const payload = config.buildSavePayload(form, { isNew, selectedId, items });
|
|
104
|
+
const url = isNew ? config.apiPath : `${config.apiPath}/${selectedId}`;
|
|
105
|
+
const method = isNew ? "POST" : "PUT";
|
|
106
|
+
setSaving(true);
|
|
107
|
+
try {
|
|
108
|
+
const res = await adminFetch(url, {
|
|
109
|
+
method,
|
|
110
|
+
headers: { ...getAuthHeaders(), "Content-Type": "application/json" },
|
|
111
|
+
body: JSON.stringify(payload)
|
|
112
|
+
});
|
|
113
|
+
const json = await res.json();
|
|
114
|
+
if (json.success) {
|
|
115
|
+
const listRes = await adminFetch(`${config.apiPath}?limit=100&sortBy=${sortKey}`);
|
|
116
|
+
const listJson = await listRes.json();
|
|
117
|
+
if (listJson.success) {
|
|
118
|
+
setItems(listJson.data.items.map(config.normalizeListItem));
|
|
119
|
+
}
|
|
120
|
+
setTab("list");
|
|
121
|
+
setSelectedId(null);
|
|
122
|
+
toast.success("\uC800\uC7A5 \uC644\uB8CC");
|
|
123
|
+
config.onAfterSave?.();
|
|
124
|
+
config.onNavigateToList?.();
|
|
125
|
+
} else {
|
|
126
|
+
toast.error(json.error?.message || "\uC800\uC7A5 \uC2E4\uD328");
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
toast.error("\uC800\uC7A5 \uC911 \uC624\uB958 \uBC1C\uC0DD");
|
|
130
|
+
} finally {
|
|
131
|
+
setSaving(false);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const handleDelete = useCallback(async (id) => {
|
|
135
|
+
const item = items.find((i) => i.id === id);
|
|
136
|
+
const label = item ? config.meta.getItemLabel(item) : id;
|
|
137
|
+
if (!confirm(`"${label}"\uC744(\uB97C) \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?`)) return;
|
|
138
|
+
try {
|
|
139
|
+
const res = await adminFetch(`${config.apiPath}/${id}`, {
|
|
140
|
+
method: "DELETE"
|
|
141
|
+
});
|
|
142
|
+
if (res.ok) {
|
|
143
|
+
setItems((prev) => prev.filter((i) => i.id !== id));
|
|
144
|
+
if (selectedId === id) {
|
|
145
|
+
setSelectedId(null);
|
|
146
|
+
setTab("list");
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
toast.error("\uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
150
|
+
}
|
|
151
|
+
} catch {
|
|
152
|
+
toast.error("\uC0AD\uC81C \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
|
|
153
|
+
}
|
|
154
|
+
}, [items, selectedId, config.apiPath, config.meta]);
|
|
155
|
+
const listScrollRef = useRef(null);
|
|
156
|
+
const virtualizer = useVirtualizer({
|
|
157
|
+
count: filteredItems.length,
|
|
158
|
+
getScrollElement: () => listScrollRef.current,
|
|
159
|
+
estimateSize: () => 58,
|
|
160
|
+
overscan: 5
|
|
161
|
+
});
|
|
162
|
+
return /* @__PURE__ */ jsxs("div", { className: `pm${mobilePv ? " mobile-pv-on" : ""}`, children: [
|
|
163
|
+
/* @__PURE__ */ jsx("div", { className: "pm-topbar", children: /* @__PURE__ */ jsxs("div", { className: "pm-tb-l", children: [
|
|
164
|
+
/* @__PURE__ */ jsx("span", { className: "pm-tb-logo", children: config.meta.appTitle }),
|
|
165
|
+
/* @__PURE__ */ jsx("span", { className: "pm-tb-sep" }),
|
|
166
|
+
/* @__PURE__ */ jsx("span", { className: "pm-tb-pg", children: config.meta.pageTitle })
|
|
167
|
+
] }) }),
|
|
168
|
+
/* @__PURE__ */ jsxs("div", { className: "pm-tabs", children: [
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
className: `pm-tab ${tab === "list" ? "on" : ""}`,
|
|
173
|
+
onClick: () => {
|
|
174
|
+
setTab("list");
|
|
175
|
+
config.onNavigateToList?.();
|
|
176
|
+
},
|
|
177
|
+
children: config.meta.listTabLabel
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
className: `pm-tab ${tab === "edit" ? "on" : ""}`,
|
|
184
|
+
onClick: () => setTab("edit"),
|
|
185
|
+
children: "\uD3B8\uC9D1 + \uBBF8\uB9AC\uBCF4\uAE30"
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
] }),
|
|
189
|
+
/* @__PURE__ */ jsxs("div", { className: "mobile-pv-bar", children: [
|
|
190
|
+
/* @__PURE__ */ jsx(
|
|
191
|
+
"button",
|
|
192
|
+
{
|
|
193
|
+
type: "button",
|
|
194
|
+
className: `mobile-pv-btn${!mobilePv ? " on" : ""}`,
|
|
195
|
+
onClick: () => setMobilePv(false),
|
|
196
|
+
children: "\uD3B8\uC9D1"
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
type: "button",
|
|
203
|
+
className: `mobile-pv-btn${mobilePv ? " on" : ""}`,
|
|
204
|
+
onClick: () => setMobilePv(true),
|
|
205
|
+
children: "\uBBF8\uB9AC\uBCF4\uAE30"
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
] }),
|
|
209
|
+
/* @__PURE__ */ jsxs("div", { className: "pm-body", children: [
|
|
210
|
+
/* @__PURE__ */ jsxs("div", { className: `pm-panel pm-panel-list ${tab === "list" ? "on" : ""}`, children: [
|
|
211
|
+
/* @__PURE__ */ jsxs("div", { className: "pm-list-left", children: [
|
|
212
|
+
/* @__PURE__ */ jsx("div", { className: "pm-list-header", children: config.renderFilterControls({
|
|
213
|
+
filterValue,
|
|
214
|
+
setFilterValue,
|
|
215
|
+
sortKey,
|
|
216
|
+
setSortKey,
|
|
217
|
+
sortOptions: config.sortOptions,
|
|
218
|
+
searchQuery,
|
|
219
|
+
setSearchQuery,
|
|
220
|
+
filteredCount: filteredItems.length,
|
|
221
|
+
filteredItems,
|
|
222
|
+
onAdd: handleAdd,
|
|
223
|
+
addButtonLabel: config.meta.addButtonLabel,
|
|
224
|
+
allItems: items
|
|
225
|
+
}) }),
|
|
226
|
+
/* @__PURE__ */ jsx("div", { className: "pm-perf-list", ref: listScrollRef, children: /* @__PURE__ */ jsx(
|
|
227
|
+
"div",
|
|
228
|
+
{
|
|
229
|
+
style: {
|
|
230
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
231
|
+
width: "100%",
|
|
232
|
+
position: "relative"
|
|
233
|
+
},
|
|
234
|
+
children: virtualizer.getVirtualItems().map((virtualRow) => {
|
|
235
|
+
const item = filteredItems[virtualRow.index];
|
|
236
|
+
return /* @__PURE__ */ jsx(
|
|
237
|
+
"div",
|
|
238
|
+
{
|
|
239
|
+
"data-index": virtualRow.index,
|
|
240
|
+
ref: virtualizer.measureElement,
|
|
241
|
+
style: {
|
|
242
|
+
position: "absolute",
|
|
243
|
+
top: 0,
|
|
244
|
+
left: 0,
|
|
245
|
+
width: "100%",
|
|
246
|
+
transform: `translateY(${virtualRow.start}px)`
|
|
247
|
+
},
|
|
248
|
+
children: config.renderListItem(item, {
|
|
249
|
+
isSelected: selectedId === item.id,
|
|
250
|
+
onSelect: selectItem,
|
|
251
|
+
onDelete: handleDelete
|
|
252
|
+
})
|
|
253
|
+
},
|
|
254
|
+
item.id
|
|
255
|
+
);
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
) })
|
|
259
|
+
] }),
|
|
260
|
+
/* @__PURE__ */ jsxs("div", { className: "pm-list-right", children: [
|
|
261
|
+
/* @__PURE__ */ jsx("div", { className: "pm-pv-label", children: "\uD648\uD398\uC774\uC9C0 \uBBF8\uB9AC\uBCF4\uAE30" }),
|
|
262
|
+
config.renderListPreview({
|
|
263
|
+
publishedItems,
|
|
264
|
+
onSelectItem: selectItem
|
|
265
|
+
})
|
|
266
|
+
] })
|
|
267
|
+
] }),
|
|
268
|
+
/* @__PURE__ */ jsxs(
|
|
269
|
+
"div",
|
|
270
|
+
{
|
|
271
|
+
className: `pm-panel pm-panel-edit ${tab === "edit" ? "on" : ""}`,
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ jsx("div", { className: "pm-edit-left", children: config.renderEditForm({
|
|
274
|
+
form,
|
|
275
|
+
setForm,
|
|
276
|
+
updateField,
|
|
277
|
+
isNew,
|
|
278
|
+
selectedId,
|
|
279
|
+
saving,
|
|
280
|
+
loading,
|
|
281
|
+
onSave: handleSave,
|
|
282
|
+
onCancel: () => {
|
|
283
|
+
setTab("list");
|
|
284
|
+
config.onNavigateToList?.();
|
|
285
|
+
},
|
|
286
|
+
onDelete: () => {
|
|
287
|
+
if (selectedId) handleDelete(selectedId);
|
|
288
|
+
}
|
|
289
|
+
}) }),
|
|
290
|
+
/* @__PURE__ */ jsxs("div", { className: "pm-edit-right", children: [
|
|
291
|
+
/* @__PURE__ */ jsx("div", { className: "pm-pv-label", children: "\uC2E4\uC2DC\uAC04 \uBBF8\uB9AC\uBCF4\uAE30" }),
|
|
292
|
+
config.renderDetailPreview({ form, isNew, selectedId })
|
|
293
|
+
] })
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
] }),
|
|
298
|
+
config.renderModal?.()
|
|
299
|
+
] });
|
|
300
|
+
}
|
|
301
|
+
function AdminManagerBase(props) {
|
|
302
|
+
const { ref, ...rest } = props;
|
|
303
|
+
return /* @__PURE__ */ jsx(AdminManagerBaseInner, { ...rest, innerRef: ref });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export {
|
|
307
|
+
AdminManagerBase
|
|
308
|
+
};
|
|
309
|
+
//# sourceMappingURL=chunk-ZULSFSDG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AdminManagerBase.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useImperativeHandle, useMemo, useRef, forwardRef } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { toast } from \"sonner\";\nimport { adminFetch, getAuthHeaders } from \"../utils/admin-fetch\";\nimport { useAdminList } from \"../hooks/useAdminList\";\nimport { useAdminForm } from \"../hooks/useAdminForm\";\nimport type { AdminManagerConfig } from \"./AdminManagerConfig\";\n\ninterface Props<TItem extends { id: string }, TForm extends object> {\n initialItems: TItem[];\n config: AdminManagerConfig<TItem, TForm>;\n /** 초기에 선택할 항목 ID (예: detail 라우트의 [id] 세그먼트) */\n initialSelectedId?: string | null;\n /** 최초 진입 시 새 항목 편집 모드로 시작할지 여부 (예: 새 항목 라우트) */\n startWithNew?: boolean;\n /** 초기 필터 값 (예: 카테고리 필터링) */\n defaultFilterValue?: string;\n}\n\nexport interface AdminManagerBaseHandle {\n selectItem: (id: string) => void;\n}\n\nfunction AdminManagerBaseInner<\n TItem extends { id: string },\n TForm extends object\n>({\n initialItems,\n config,\n initialSelectedId,\n startWithNew,\n defaultFilterValue,\n innerRef,\n}: Props<TItem, TForm> & { innerRef?: React.Ref<AdminManagerBaseHandle> }) {\n const list = useAdminList<TItem>({\n initialItems,\n apiPath: config.apiPath,\n defaultSortKey: config.defaultSortKey,\n normalizeItem: config.normalizeListItem,\n defaultFilterValue,\n });\n const {\n items,\n setItems,\n searchQuery,\n setSearchQuery,\n sortKey,\n setSortKey,\n filterValue,\n setFilterValue,\n } = list;\n\n const adminForm = useAdminForm<TForm>(config.emptyForm);\n const {\n tab,\n setTab,\n form,\n setForm,\n updateField,\n selectedId,\n setSelectedId,\n isNew,\n setIsNew,\n saving,\n setSaving,\n loading,\n setLoading,\n mobilePv,\n setMobilePv,\n addNew,\n startEdit,\n } = adminForm;\n\n useEffect(() => {\n if (startWithNew) {\n handleAdd();\n return;\n }\n if (initialSelectedId) {\n selectItem(initialSelectedId);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const filteredItems = useMemo(\n () => config.filterItems(items, filterValue, searchQuery),\n [items, filterValue, searchQuery, config]\n );\n\n const publishedItems = useMemo(\n () => items.filter(config.meta.getItemPublished),\n [items, config]\n );\n\n const selectItem = useCallback(async (id: string) => {\n startEdit(id, config.emptyForm);\n try {\n const res = await adminFetch(`${config.apiPath}/${id}`);\n const json = await res.json();\n if (json.success) {\n setForm(config.loadItem(json.data));\n } else {\n toast.error(json.error?.message || \"데이터 로드 실패\");\n }\n } catch {\n toast.error(\"데이터 로드 실패\");\n } finally {\n setLoading(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [config.apiPath, config.loadItem, config.emptyForm]);\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useImperativeHandle(innerRef, () => ({ selectItem }), [selectItem]);\n\n const handleAdd = useCallback(() => {\n addNew(config.emptyForm);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [config.emptyForm]);\n\n async function handleSave() {\n const err = config.validate(form);\n if (err) {\n toast.error(err);\n return;\n }\n const payload = config.buildSavePayload(form, { isNew, selectedId, items });\n const url = isNew ? config.apiPath : `${config.apiPath}/${selectedId}`;\n const method = isNew ? \"POST\" : \"PUT\";\n\n setSaving(true);\n try {\n const res = await adminFetch(url, {\n method,\n headers: { ...getAuthHeaders(), \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n const json = await res.json();\n if (json.success) {\n const listRes = await adminFetch(`${config.apiPath}?limit=100&sortBy=${sortKey}`);\n const listJson = await listRes.json();\n if (listJson.success) {\n setItems(listJson.data.items.map(config.normalizeListItem));\n }\n setTab(\"list\");\n setSelectedId(null);\n toast.success(\"저장 완료\");\n config.onAfterSave?.();\n config.onNavigateToList?.();\n } else {\n toast.error(json.error?.message || \"저장 실패\");\n }\n } catch {\n toast.error(\"저장 중 오류 발생\");\n } finally {\n setSaving(false);\n }\n }\n\n const handleDelete = useCallback(async (id: string) => {\n const item = items.find((i) => i.id === id);\n const label = item ? config.meta.getItemLabel(item) : id;\n if (!confirm(`\"${label}\"을(를) 삭제하시겠습니까?`)) return;\n try {\n const res = await adminFetch(`${config.apiPath}/${id}`, {\n method: \"DELETE\",\n });\n if (res.ok) {\n setItems((prev) => prev.filter((i) => i.id !== id));\n if (selectedId === id) {\n setSelectedId(null);\n setTab(\"list\");\n }\n } else {\n toast.error(\"삭제에 실패했습니다.\");\n }\n } catch {\n toast.error(\"삭제 중 오류가 발생했습니다.\");\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [items, selectedId, config.apiPath, config.meta]);\n\n const listScrollRef = useRef<HTMLDivElement>(null);\n\n const virtualizer = useVirtualizer({\n count: filteredItems.length,\n getScrollElement: () => listScrollRef.current,\n estimateSize: () => 58,\n overscan: 5,\n });\n\n return (\n <div className={`pm${mobilePv ? \" mobile-pv-on\" : \"\"}`}>\n {/* Topbar */}\n <div className=\"pm-topbar\">\n <div className=\"pm-tb-l\">\n <span className=\"pm-tb-logo\">{config.meta.appTitle}</span>\n <span className=\"pm-tb-sep\" />\n <span className=\"pm-tb-pg\">{config.meta.pageTitle}</span>\n </div>\n </div>\n\n {/* Tabs */}\n <div className=\"pm-tabs\">\n <div\n className={`pm-tab ${tab === \"list\" ? \"on\" : \"\"}`}\n onClick={() => { setTab(\"list\"); config.onNavigateToList?.(); }}\n >\n {config.meta.listTabLabel}\n </div>\n <div\n className={`pm-tab ${tab === \"edit\" ? \"on\" : \"\"}`}\n onClick={() => setTab(\"edit\")}\n >\n 편집 + 미리보기\n </div>\n </div>\n\n {/* Mobile Preview Toggle */}\n <div className=\"mobile-pv-bar\">\n <button\n type=\"button\"\n className={`mobile-pv-btn${!mobilePv ? \" on\" : \"\"}`}\n onClick={() => setMobilePv(false)}\n >\n 편집\n </button>\n <button\n type=\"button\"\n className={`mobile-pv-btn${mobilePv ? \" on\" : \"\"}`}\n onClick={() => setMobilePv(true)}\n >\n 미리보기\n </button>\n </div>\n\n {/* Body */}\n <div className=\"pm-body\">\n {/* List Panel */}\n <div className={`pm-panel pm-panel-list ${tab === \"list\" ? \"on\" : \"\"}`}>\n <div className=\"pm-list-left\">\n <div className=\"pm-list-header\">\n {config.renderFilterControls({\n filterValue,\n setFilterValue,\n sortKey,\n setSortKey,\n sortOptions: config.sortOptions,\n searchQuery,\n setSearchQuery,\n filteredCount: filteredItems.length,\n filteredItems,\n onAdd: handleAdd,\n addButtonLabel: config.meta.addButtonLabel,\n allItems: items,\n })}\n </div>\n <div className=\"pm-perf-list\" ref={listScrollRef}>\n <div\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n width: \"100%\",\n position: \"relative\",\n }}\n >\n {virtualizer.getVirtualItems().map((virtualRow) => {\n const item = filteredItems[virtualRow.index];\n return (\n <div\n key={item.id}\n data-index={virtualRow.index}\n ref={virtualizer.measureElement}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {config.renderListItem(item, {\n isSelected: selectedId === item.id,\n onSelect: selectItem,\n onDelete: handleDelete,\n })}\n </div>\n );\n })}\n </div>\n </div>\n </div>\n <div className=\"pm-list-right\">\n <div className=\"pm-pv-label\">홈페이지 미리보기</div>\n {config.renderListPreview({\n publishedItems,\n onSelectItem: selectItem,\n })}\n </div>\n </div>\n\n {/* Edit Panel */}\n <div\n className={`pm-panel pm-panel-edit ${tab === \"edit\" ? \"on\" : \"\"}`}\n >\n <div className=\"pm-edit-left\">\n {config.renderEditForm({\n form,\n setForm,\n updateField,\n isNew,\n selectedId,\n saving,\n loading,\n onSave: handleSave,\n onCancel: () => { setTab(\"list\"); config.onNavigateToList?.(); },\n onDelete: () => { if (selectedId) handleDelete(selectedId); },\n })}\n </div>\n <div className=\"pm-edit-right\">\n <div className=\"pm-pv-label\">실시간 미리보기</div>\n {config.renderDetailPreview({ form, isNew, selectedId })}\n </div>\n </div>\n </div>\n\n {/* Domain Modal */}\n {config.renderModal?.()}\n </div>\n );\n}\n\nexport default function AdminManagerBase<\n TItem extends { id: string },\n TForm extends object\n>(props: Props<TItem, TForm> & { ref?: React.Ref<AdminManagerBaseHandle> }) {\n const { ref, ...rest } = props;\n return <AdminManagerBaseInner {...rest} innerRef={ref} />;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { AdminManagerConfig } from './AdminManagerConfig.mjs';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface Props<TItem extends {
|
|
6
|
+
id: string;
|
|
7
|
+
}, TForm extends object> {
|
|
8
|
+
initialItems: TItem[];
|
|
9
|
+
config: AdminManagerConfig<TItem, TForm>;
|
|
10
|
+
/** 초기에 선택할 항목 ID (예: detail 라우트의 [id] 세그먼트) */
|
|
11
|
+
initialSelectedId?: string | null;
|
|
12
|
+
/** 최초 진입 시 새 항목 편집 모드로 시작할지 여부 (예: 새 항목 라우트) */
|
|
13
|
+
startWithNew?: boolean;
|
|
14
|
+
/** 초기 필터 값 (예: 카테고리 필터링) */
|
|
15
|
+
defaultFilterValue?: string;
|
|
16
|
+
}
|
|
17
|
+
interface AdminManagerBaseHandle {
|
|
18
|
+
selectItem: (id: string) => void;
|
|
19
|
+
}
|
|
20
|
+
declare function AdminManagerBase<TItem extends {
|
|
21
|
+
id: string;
|
|
22
|
+
}, TForm extends object>(props: Props<TItem, TForm> & {
|
|
23
|
+
ref?: React.Ref<AdminManagerBaseHandle>;
|
|
24
|
+
}): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
export { type AdminManagerBaseHandle, AdminManagerBase as default };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { AdminManagerConfig } from './AdminManagerConfig.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface Props<TItem extends {
|
|
6
|
+
id: string;
|
|
7
|
+
}, TForm extends object> {
|
|
8
|
+
initialItems: TItem[];
|
|
9
|
+
config: AdminManagerConfig<TItem, TForm>;
|
|
10
|
+
/** 초기에 선택할 항목 ID (예: detail 라우트의 [id] 세그먼트) */
|
|
11
|
+
initialSelectedId?: string | null;
|
|
12
|
+
/** 최초 진입 시 새 항목 편집 모드로 시작할지 여부 (예: 새 항목 라우트) */
|
|
13
|
+
startWithNew?: boolean;
|
|
14
|
+
/** 초기 필터 값 (예: 카테고리 필터링) */
|
|
15
|
+
defaultFilterValue?: string;
|
|
16
|
+
}
|
|
17
|
+
interface AdminManagerBaseHandle {
|
|
18
|
+
selectItem: (id: string) => void;
|
|
19
|
+
}
|
|
20
|
+
declare function AdminManagerBase<TItem extends {
|
|
21
|
+
id: string;
|
|
22
|
+
}, TForm extends object>(props: Props<TItem, TForm> & {
|
|
23
|
+
ref?: React.Ref<AdminManagerBaseHandle>;
|
|
24
|
+
}): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
export { type AdminManagerBaseHandle, AdminManagerBase as default };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkDCIF4XJLjs = require('../chunk-DCIF4XJL.js');
|
|
6
|
+
require('../chunk-5JUIMXNF.js');
|
|
7
|
+
require('../chunk-KWKV2GAH.js');
|
|
8
|
+
require('../chunk-EG6NVPP2.js');
|
|
9
|
+
require('../chunk-DGUM43GV.js');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.default = _chunkDCIF4XJLjs.AdminManagerBase;
|
|
13
|
+
//# sourceMappingURL=AdminManagerBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/components/AdminManagerBase.js"],"names":[],"mappings":"AAAA,qFAAY;AACZ;AACE;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACF,oDAAC","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/components/AdminManagerBase.js"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
AdminManagerBase
|
|
4
|
+
} from "../chunk-ZULSFSDG.mjs";
|
|
5
|
+
import "../chunk-FCCCG5Z7.mjs";
|
|
6
|
+
import "../chunk-T7EVFD4G.mjs";
|
|
7
|
+
import "../chunk-BWKKHCDG.mjs";
|
|
8
|
+
import "../chunk-BJTO5JO5.mjs";
|
|
9
|
+
export {
|
|
10
|
+
AdminManagerBase as default
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=AdminManagerBase.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ReactNode, Dispatch, SetStateAction } from 'react';
|
|
2
|
+
|
|
3
|
+
interface FilterSlotProps<TItem = unknown> {
|
|
4
|
+
filterValue: string;
|
|
5
|
+
setFilterValue: (v: string) => void;
|
|
6
|
+
sortKey: string;
|
|
7
|
+
setSortKey: (v: string) => void;
|
|
8
|
+
sortOptions: {
|
|
9
|
+
value: string;
|
|
10
|
+
label: string;
|
|
11
|
+
}[];
|
|
12
|
+
searchQuery: string;
|
|
13
|
+
setSearchQuery: (v: string) => void;
|
|
14
|
+
filteredCount: number;
|
|
15
|
+
filteredItems: TItem[];
|
|
16
|
+
onAdd: () => void;
|
|
17
|
+
addButtonLabel: string;
|
|
18
|
+
allItems: TItem[];
|
|
19
|
+
}
|
|
20
|
+
interface ListItemSlotProps<TItem> {
|
|
21
|
+
isSelected: boolean;
|
|
22
|
+
onSelect: (id: string) => void;
|
|
23
|
+
onDelete: (id: string) => void;
|
|
24
|
+
}
|
|
25
|
+
interface EditFormSlotProps<TForm> {
|
|
26
|
+
form: TForm;
|
|
27
|
+
setForm: Dispatch<SetStateAction<TForm>>;
|
|
28
|
+
updateField: <K extends keyof TForm>(key: K, value: TForm[K]) => void;
|
|
29
|
+
isNew: boolean;
|
|
30
|
+
selectedId: string | null;
|
|
31
|
+
saving: boolean;
|
|
32
|
+
loading: boolean;
|
|
33
|
+
onSave: () => void;
|
|
34
|
+
onCancel: () => void;
|
|
35
|
+
onDelete: () => void;
|
|
36
|
+
}
|
|
37
|
+
interface DetailPreviewSlotProps<TForm> {
|
|
38
|
+
form: TForm;
|
|
39
|
+
isNew: boolean;
|
|
40
|
+
selectedId: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface ListPreviewSlotProps<TItem> {
|
|
43
|
+
publishedItems: TItem[];
|
|
44
|
+
onSelectItem: (id: string) => void;
|
|
45
|
+
}
|
|
46
|
+
interface AdminManagerConfig<TItem extends {
|
|
47
|
+
id: string;
|
|
48
|
+
}, TForm extends object> {
|
|
49
|
+
meta: {
|
|
50
|
+
appTitle: string;
|
|
51
|
+
pageTitle: string;
|
|
52
|
+
listTabLabel: string;
|
|
53
|
+
addButtonLabel: string;
|
|
54
|
+
getItemLabel: (item: TItem) => string;
|
|
55
|
+
getItemPublished: (item: TItem) => boolean;
|
|
56
|
+
};
|
|
57
|
+
apiPath: string;
|
|
58
|
+
defaultSortKey: string;
|
|
59
|
+
sortOptions: {
|
|
60
|
+
value: string;
|
|
61
|
+
label: string;
|
|
62
|
+
}[];
|
|
63
|
+
emptyForm: TForm;
|
|
64
|
+
loadItem: (apiData: unknown) => TForm;
|
|
65
|
+
buildSavePayload: (form: TForm, ctx: {
|
|
66
|
+
isNew: boolean;
|
|
67
|
+
selectedId: string | null;
|
|
68
|
+
items: TItem[];
|
|
69
|
+
}) => Record<string, unknown>;
|
|
70
|
+
validate: (form: TForm) => string | null;
|
|
71
|
+
normalizeListItem: (raw: unknown) => TItem;
|
|
72
|
+
filterItems: (items: TItem[], filter: string, search: string) => TItem[];
|
|
73
|
+
renderFilterControls: (props: FilterSlotProps<TItem>) => ReactNode;
|
|
74
|
+
renderListItem: (item: TItem, props: ListItemSlotProps<TItem>) => ReactNode;
|
|
75
|
+
renderEditForm: (props: EditFormSlotProps<TForm>) => ReactNode;
|
|
76
|
+
renderDetailPreview: (props: DetailPreviewSlotProps<TForm>) => ReactNode;
|
|
77
|
+
renderListPreview: (props: ListPreviewSlotProps<TItem>) => ReactNode;
|
|
78
|
+
renderModal?: () => ReactNode;
|
|
79
|
+
onAfterSave?: () => void;
|
|
80
|
+
onNavigateToList?: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export type { AdminManagerConfig, DetailPreviewSlotProps, EditFormSlotProps, FilterSlotProps, ListItemSlotProps, ListPreviewSlotProps };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ReactNode, Dispatch, SetStateAction } from 'react';
|
|
2
|
+
|
|
3
|
+
interface FilterSlotProps<TItem = unknown> {
|
|
4
|
+
filterValue: string;
|
|
5
|
+
setFilterValue: (v: string) => void;
|
|
6
|
+
sortKey: string;
|
|
7
|
+
setSortKey: (v: string) => void;
|
|
8
|
+
sortOptions: {
|
|
9
|
+
value: string;
|
|
10
|
+
label: string;
|
|
11
|
+
}[];
|
|
12
|
+
searchQuery: string;
|
|
13
|
+
setSearchQuery: (v: string) => void;
|
|
14
|
+
filteredCount: number;
|
|
15
|
+
filteredItems: TItem[];
|
|
16
|
+
onAdd: () => void;
|
|
17
|
+
addButtonLabel: string;
|
|
18
|
+
allItems: TItem[];
|
|
19
|
+
}
|
|
20
|
+
interface ListItemSlotProps<TItem> {
|
|
21
|
+
isSelected: boolean;
|
|
22
|
+
onSelect: (id: string) => void;
|
|
23
|
+
onDelete: (id: string) => void;
|
|
24
|
+
}
|
|
25
|
+
interface EditFormSlotProps<TForm> {
|
|
26
|
+
form: TForm;
|
|
27
|
+
setForm: Dispatch<SetStateAction<TForm>>;
|
|
28
|
+
updateField: <K extends keyof TForm>(key: K, value: TForm[K]) => void;
|
|
29
|
+
isNew: boolean;
|
|
30
|
+
selectedId: string | null;
|
|
31
|
+
saving: boolean;
|
|
32
|
+
loading: boolean;
|
|
33
|
+
onSave: () => void;
|
|
34
|
+
onCancel: () => void;
|
|
35
|
+
onDelete: () => void;
|
|
36
|
+
}
|
|
37
|
+
interface DetailPreviewSlotProps<TForm> {
|
|
38
|
+
form: TForm;
|
|
39
|
+
isNew: boolean;
|
|
40
|
+
selectedId: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface ListPreviewSlotProps<TItem> {
|
|
43
|
+
publishedItems: TItem[];
|
|
44
|
+
onSelectItem: (id: string) => void;
|
|
45
|
+
}
|
|
46
|
+
interface AdminManagerConfig<TItem extends {
|
|
47
|
+
id: string;
|
|
48
|
+
}, TForm extends object> {
|
|
49
|
+
meta: {
|
|
50
|
+
appTitle: string;
|
|
51
|
+
pageTitle: string;
|
|
52
|
+
listTabLabel: string;
|
|
53
|
+
addButtonLabel: string;
|
|
54
|
+
getItemLabel: (item: TItem) => string;
|
|
55
|
+
getItemPublished: (item: TItem) => boolean;
|
|
56
|
+
};
|
|
57
|
+
apiPath: string;
|
|
58
|
+
defaultSortKey: string;
|
|
59
|
+
sortOptions: {
|
|
60
|
+
value: string;
|
|
61
|
+
label: string;
|
|
62
|
+
}[];
|
|
63
|
+
emptyForm: TForm;
|
|
64
|
+
loadItem: (apiData: unknown) => TForm;
|
|
65
|
+
buildSavePayload: (form: TForm, ctx: {
|
|
66
|
+
isNew: boolean;
|
|
67
|
+
selectedId: string | null;
|
|
68
|
+
items: TItem[];
|
|
69
|
+
}) => Record<string, unknown>;
|
|
70
|
+
validate: (form: TForm) => string | null;
|
|
71
|
+
normalizeListItem: (raw: unknown) => TItem;
|
|
72
|
+
filterItems: (items: TItem[], filter: string, search: string) => TItem[];
|
|
73
|
+
renderFilterControls: (props: FilterSlotProps<TItem>) => ReactNode;
|
|
74
|
+
renderListItem: (item: TItem, props: ListItemSlotProps<TItem>) => ReactNode;
|
|
75
|
+
renderEditForm: (props: EditFormSlotProps<TForm>) => ReactNode;
|
|
76
|
+
renderDetailPreview: (props: DetailPreviewSlotProps<TForm>) => ReactNode;
|
|
77
|
+
renderListPreview: (props: ListPreviewSlotProps<TItem>) => ReactNode;
|
|
78
|
+
renderModal?: () => ReactNode;
|
|
79
|
+
onAfterSave?: () => void;
|
|
80
|
+
onNavigateToList?: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export type { AdminManagerConfig, DetailPreviewSlotProps, EditFormSlotProps, FilterSlotProps, ListItemSlotProps, ListPreviewSlotProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/components/AdminManagerConfig.js"],"names":[],"mappings":"AAAA,6CAA6B","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/components/AdminManagerConfig.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { d as CmsNavItem } from '../index-00a40-FQ.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AdminShell props (spec.md §4.1 / Sprint 1 C1/C2).
|
|
6
|
+
*
|
|
7
|
+
* brand/nav/route 는 더 이상 하드코딩되지 않는다. 우선순위:
|
|
8
|
+
* props > §5 config boundary (`setCmsConfig`) > 안전 중립 기본값
|
|
9
|
+
* (빈 nav + 1회 `@withwiz/cms-kit:` warn, route 는 레거시 기본 경로).
|
|
10
|
+
*/
|
|
11
|
+
interface AdminShellProps {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
/** 브랜드 라벨 (사이드바 홈 링크 텍스트). 미지정 시 §5 config. */
|
|
14
|
+
brandLabel?: string;
|
|
15
|
+
/** 브랜드 홈 링크 href. */
|
|
16
|
+
brandHref?: string;
|
|
17
|
+
/** admin 링크 href. */
|
|
18
|
+
adminHref?: string;
|
|
19
|
+
/** 순서 있는 nav 항목 목록 (label/href/glyph). */
|
|
20
|
+
navItems?: CmsNavItem[];
|
|
21
|
+
/** 로그인 페이지 경로 (라우트 가드/리다이렉트). */
|
|
22
|
+
loginPath?: string;
|
|
23
|
+
/** "현재 사용자" 엔드포인트. */
|
|
24
|
+
meEndpoint?: string;
|
|
25
|
+
/** 로그아웃 엔드포인트. */
|
|
26
|
+
logoutEndpoint?: string;
|
|
27
|
+
}
|
|
28
|
+
declare function AdminShell({ children, brandLabel, brandHref, adminHref, navItems, loginPath, meEndpoint, logoutEndpoint, }: AdminShellProps): react_jsx_runtime.JSX.Element;
|
|
29
|
+
|
|
30
|
+
export { type AdminShellProps, AdminShell as default };
|