@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,181 @@
|
|
|
1
|
+
// src/components/ResizableImage.tsx
|
|
2
|
+
import { Node, mergeAttributes } from "@tiptap/core";
|
|
3
|
+
import {
|
|
4
|
+
ReactNodeViewRenderer,
|
|
5
|
+
NodeViewWrapper
|
|
6
|
+
} from "@tiptap/react";
|
|
7
|
+
import { useCallback, useRef, useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function AlignIcon({ type }) {
|
|
10
|
+
const w = 12;
|
|
11
|
+
const lines = [
|
|
12
|
+
{ y: 0, lw: w },
|
|
13
|
+
{ y: 3.5, lw: 7 },
|
|
14
|
+
{ y: 7, lw: 10 }
|
|
15
|
+
];
|
|
16
|
+
return /* @__PURE__ */ jsx("svg", { width: w, height: "10", viewBox: `0 0 ${w} 10`, fill: "currentColor", children: lines.map((l, i) => {
|
|
17
|
+
const x = type === "center" ? (w - l.lw) / 2 : type === "right" ? w - l.lw : 0;
|
|
18
|
+
return /* @__PURE__ */ jsx("rect", { x, y: l.y, width: l.lw, height: "1.5", rx: ".5" }, i);
|
|
19
|
+
}) });
|
|
20
|
+
}
|
|
21
|
+
function ResizableImageComponent(props) {
|
|
22
|
+
const { node, updateAttributes, selected } = props;
|
|
23
|
+
const imgRef = useRef(null);
|
|
24
|
+
const [resizing, setResizing] = useState(false);
|
|
25
|
+
const src = node.attrs.src;
|
|
26
|
+
const alt = node.attrs.alt || "";
|
|
27
|
+
const title = node.attrs.title || void 0;
|
|
28
|
+
const width = node.attrs.width;
|
|
29
|
+
const align = node.attrs.align || "center";
|
|
30
|
+
const startResize = useCallback(
|
|
31
|
+
(e, handle) => {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
e.stopPropagation();
|
|
34
|
+
const startX = e.clientX;
|
|
35
|
+
const startY = e.clientY;
|
|
36
|
+
const startWidth = imgRef.current?.offsetWidth || 300;
|
|
37
|
+
const startHeight = imgRef.current?.offsetHeight || 200;
|
|
38
|
+
const aspectRatio = startWidth / startHeight;
|
|
39
|
+
const isEdge = handle.length === 1;
|
|
40
|
+
const isHorizontal = handle === "e" || handle === "w";
|
|
41
|
+
const signX = handle.includes("e") ? 1 : -1;
|
|
42
|
+
const signY = handle.includes("s") ? 1 : -1;
|
|
43
|
+
const calcNewWidth = (ev) => {
|
|
44
|
+
const dx = (ev.clientX - startX) * signX;
|
|
45
|
+
const dy = (ev.clientY - startY) * signY;
|
|
46
|
+
let delta;
|
|
47
|
+
if (isEdge) {
|
|
48
|
+
delta = isHorizontal ? dx : dy * aspectRatio;
|
|
49
|
+
} else {
|
|
50
|
+
delta = Math.abs(dx) > Math.abs(dy) ? dx : dy * aspectRatio;
|
|
51
|
+
}
|
|
52
|
+
return Math.max(80, startWidth + delta);
|
|
53
|
+
};
|
|
54
|
+
const onMouseMove = (ev) => {
|
|
55
|
+
const newWidth = calcNewWidth(ev);
|
|
56
|
+
if (imgRef.current) {
|
|
57
|
+
imgRef.current.style.width = `${newWidth}px`;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const onMouseUp = (ev) => {
|
|
61
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
62
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
63
|
+
setResizing(false);
|
|
64
|
+
updateAttributes({ width: Math.round(calcNewWidth(ev)) });
|
|
65
|
+
};
|
|
66
|
+
setResizing(true);
|
|
67
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
68
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
69
|
+
},
|
|
70
|
+
[updateAttributes]
|
|
71
|
+
);
|
|
72
|
+
const handles = ["nw", "n", "ne", "w", "e", "sw", "s", "se"];
|
|
73
|
+
return /* @__PURE__ */ jsxs(
|
|
74
|
+
NodeViewWrapper,
|
|
75
|
+
{
|
|
76
|
+
className: `resizable-image-wrapper resizable-image-align-${align} ${selected ? "selected" : ""} ${resizing ? "resizing" : ""}`,
|
|
77
|
+
children: [
|
|
78
|
+
selected && !resizing && /* @__PURE__ */ jsx("div", { className: "resizable-image-align-toolbar", children: ["left", "center", "right"].map((a) => /* @__PURE__ */ jsx(
|
|
79
|
+
"button",
|
|
80
|
+
{
|
|
81
|
+
type: "button",
|
|
82
|
+
className: `resizable-image-align-btn ${align === a ? "active" : ""}`,
|
|
83
|
+
onMouseDown: (e) => {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
updateAttributes({ align: a });
|
|
86
|
+
},
|
|
87
|
+
title: a === "left" ? "\uC67C\uCABD \uC815\uB82C" : a === "center" ? "\uAC00\uC6B4\uB370 \uC815\uB82C" : "\uC624\uB978\uCABD \uC815\uB82C",
|
|
88
|
+
children: /* @__PURE__ */ jsx(AlignIcon, { type: a })
|
|
89
|
+
},
|
|
90
|
+
a
|
|
91
|
+
)) }),
|
|
92
|
+
/* @__PURE__ */ jsxs(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
className: "resizable-image-container",
|
|
96
|
+
style: { width: width ? `${width}px` : void 0 },
|
|
97
|
+
children: [
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
"img",
|
|
100
|
+
{
|
|
101
|
+
ref: imgRef,
|
|
102
|
+
src,
|
|
103
|
+
alt,
|
|
104
|
+
title,
|
|
105
|
+
style: { width: width ? `${width}px` : void 0 },
|
|
106
|
+
draggable: false
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
(selected || resizing) && handles.map((h) => /* @__PURE__ */ jsx(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
className: `resizable-image-handle resizable-image-handle-${h}`,
|
|
113
|
+
onMouseDown: (e) => startResize(e, h)
|
|
114
|
+
},
|
|
115
|
+
h
|
|
116
|
+
))
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
var ResizableImage = Node.create({
|
|
125
|
+
name: "image",
|
|
126
|
+
group: "block",
|
|
127
|
+
atom: true,
|
|
128
|
+
draggable: true,
|
|
129
|
+
addAttributes() {
|
|
130
|
+
return {
|
|
131
|
+
src: { default: null },
|
|
132
|
+
alt: { default: null },
|
|
133
|
+
title: { default: null },
|
|
134
|
+
width: { default: null },
|
|
135
|
+
align: {
|
|
136
|
+
default: "center",
|
|
137
|
+
parseHTML: (element) => element.getAttribute("data-align") || "center",
|
|
138
|
+
renderHTML: (attributes) => ({
|
|
139
|
+
"data-align": attributes.align
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
},
|
|
144
|
+
parseHTML() {
|
|
145
|
+
return [{ tag: "img[src]" }];
|
|
146
|
+
},
|
|
147
|
+
renderHTML({ HTMLAttributes }) {
|
|
148
|
+
const attrs = { ...HTMLAttributes };
|
|
149
|
+
const styles = [];
|
|
150
|
+
if (attrs.width) {
|
|
151
|
+
styles.push(`width: ${attrs.width}px`);
|
|
152
|
+
}
|
|
153
|
+
const align = attrs["data-align"] || "center";
|
|
154
|
+
styles.push("display: block");
|
|
155
|
+
if (align === "center") {
|
|
156
|
+
styles.push("margin-left: auto", "margin-right: auto");
|
|
157
|
+
} else if (align === "right") {
|
|
158
|
+
styles.push("margin-left: auto");
|
|
159
|
+
}
|
|
160
|
+
if (styles.length) attrs.style = styles.join("; ");
|
|
161
|
+
return ["img", mergeAttributes(attrs)];
|
|
162
|
+
},
|
|
163
|
+
addNodeView() {
|
|
164
|
+
return ReactNodeViewRenderer(ResizableImageComponent);
|
|
165
|
+
},
|
|
166
|
+
addCommands() {
|
|
167
|
+
return {
|
|
168
|
+
setImage: (options) => ({ commands }) => {
|
|
169
|
+
return commands.insertContent({
|
|
170
|
+
type: this.name,
|
|
171
|
+
attrs: options
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export {
|
|
179
|
+
ResizableImage
|
|
180
|
+
};
|
|
181
|
+
//# sourceMappingURL=chunk-D75ADHVM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ResizableImage.tsx"],"sourcesContent":["\"use client\";\n\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport {\n ReactNodeViewRenderer,\n NodeViewWrapper,\n type NodeViewProps,\n} from \"@tiptap/react\";\nimport { useCallback, useRef, useState } from \"react\";\n\ntype Handle = \"nw\" | \"ne\" | \"sw\" | \"se\" | \"n\" | \"s\" | \"e\" | \"w\";\n\nfunction AlignIcon({ type }: { type: \"left\" | \"center\" | \"right\" }) {\n const w = 12;\n const lines = [\n { y: 0, lw: w },\n { y: 3.5, lw: 7 },\n { y: 7, lw: 10 },\n ];\n return (\n <svg width={w} height=\"10\" viewBox={`0 0 ${w} 10`} fill=\"currentColor\">\n {lines.map((l, i) => {\n const x =\n type === \"center\"\n ? (w - l.lw) / 2\n : type === \"right\"\n ? w - l.lw\n : 0;\n return <rect key={i} x={x} y={l.y} width={l.lw} height=\"1.5\" rx=\".5\" />;\n })}\n </svg>\n );\n}\n\nfunction ResizableImageComponent(props: NodeViewProps) {\n const { node, updateAttributes, selected } = props;\n const imgRef = useRef<HTMLImageElement>(null);\n const [resizing, setResizing] = useState(false);\n\n const src = node.attrs.src as string;\n const alt = (node.attrs.alt as string) || \"\";\n const title = (node.attrs.title as string) || undefined;\n const width = node.attrs.width as number | null;\n const align = (node.attrs.align as string) || \"center\";\n\n const startResize = useCallback(\n (e: React.MouseEvent, handle: Handle) => {\n e.preventDefault();\n e.stopPropagation();\n\n const startX = e.clientX;\n const startY = e.clientY;\n const startWidth = imgRef.current?.offsetWidth || 300;\n const startHeight = imgRef.current?.offsetHeight || 200;\n const aspectRatio = startWidth / startHeight;\n\n const isEdge = handle.length === 1; // \"n\", \"s\", \"e\", \"w\"\n const isHorizontal = handle === \"e\" || handle === \"w\";\n\n // x 방향 부호: 오른쪽 핸들이면 +1, 왼쪽이면 -1\n const signX = handle.includes(\"e\") ? 1 : -1;\n // y 방향 부호: 아래쪽 핸들이면 +1, 위쪽이면 -1\n const signY = handle.includes(\"s\") ? 1 : -1;\n\n const calcNewWidth = (ev: MouseEvent) => {\n const dx = (ev.clientX - startX) * signX;\n const dy = (ev.clientY - startY) * signY;\n\n let delta: number;\n if (isEdge) {\n // 변 중간 핸들: 해당 축 방향만 사용하되 비율 유지\n delta = isHorizontal ? dx : dy * aspectRatio;\n } else {\n // 모서리 핸들: 더 큰 변화량 기준으로 비율 유지\n delta = Math.abs(dx) > Math.abs(dy) ? dx : dy * aspectRatio;\n }\n return Math.max(80, startWidth + delta);\n };\n\n const onMouseMove = (ev: MouseEvent) => {\n const newWidth = calcNewWidth(ev);\n if (imgRef.current) {\n imgRef.current.style.width = `${newWidth}px`;\n }\n };\n\n const onMouseUp = (ev: MouseEvent) => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"mouseup\", onMouseUp);\n setResizing(false);\n updateAttributes({ width: Math.round(calcNewWidth(ev)) });\n };\n\n setResizing(true);\n document.addEventListener(\"mousemove\", onMouseMove);\n document.addEventListener(\"mouseup\", onMouseUp);\n },\n [updateAttributes]\n );\n\n const handles: Handle[] = [\"nw\", \"n\", \"ne\", \"w\", \"e\", \"sw\", \"s\", \"se\"];\n\n return (\n <NodeViewWrapper\n className={`resizable-image-wrapper resizable-image-align-${align} ${selected ? \"selected\" : \"\"} ${resizing ? \"resizing\" : \"\"}`}\n >\n {selected && !resizing && (\n <div className=\"resizable-image-align-toolbar\">\n {([\"left\", \"center\", \"right\"] as const).map((a) => (\n <button\n key={a}\n type=\"button\"\n className={`resizable-image-align-btn ${align === a ? \"active\" : \"\"}`}\n onMouseDown={(e) => {\n e.preventDefault();\n updateAttributes({ align: a });\n }}\n title={a === \"left\" ? \"왼쪽 정렬\" : a === \"center\" ? \"가운데 정렬\" : \"오른쪽 정렬\"}\n >\n <AlignIcon type={a} />\n </button>\n ))}\n </div>\n )}\n <div\n className=\"resizable-image-container\"\n style={{ width: width ? `${width}px` : undefined }}\n >\n <img\n ref={imgRef}\n src={src}\n alt={alt}\n title={title}\n style={{ width: width ? `${width}px` : undefined }}\n draggable={false}\n />\n {(selected || resizing) &&\n handles.map((h) => (\n <div\n key={h}\n className={`resizable-image-handle resizable-image-handle-${h}`}\n onMouseDown={(e) => startResize(e, h)}\n />\n ))}\n </div>\n </NodeViewWrapper>\n );\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n resizableImage: {\n setImage: (options: {\n src: string;\n alt?: string;\n title?: string;\n width?: number;\n align?: string;\n }) => ReturnType;\n };\n }\n}\n\nexport const ResizableImage = Node.create({\n name: \"image\",\n group: \"block\",\n atom: true,\n draggable: true,\n\n addAttributes() {\n return {\n src: { default: null },\n alt: { default: null },\n title: { default: null },\n width: { default: null },\n align: {\n default: \"center\",\n parseHTML: (element: HTMLElement) =>\n element.getAttribute(\"data-align\") || \"center\",\n renderHTML: (attributes: Record<string, unknown>) => ({\n \"data-align\": attributes.align,\n }),\n },\n };\n },\n\n parseHTML() {\n return [{ tag: \"img[src]\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n const attrs = { ...HTMLAttributes };\n const styles: string[] = [];\n if (attrs.width) {\n styles.push(`width: ${attrs.width}px`);\n }\n const align = attrs[\"data-align\"] || \"center\";\n styles.push(\"display: block\");\n if (align === \"center\") {\n styles.push(\"margin-left: auto\", \"margin-right: auto\");\n } else if (align === \"right\") {\n styles.push(\"margin-left: auto\");\n }\n if (styles.length) attrs.style = styles.join(\"; \");\n return [\"img\", mergeAttributes(attrs)];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(ResizableImageComponent);\n },\n\n addCommands() {\n return {\n setImage:\n (options: {\n src: string;\n alt?: string;\n title?: string;\n width?: number;\n align?: string;\n }) =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n attrs: options,\n });\n },\n } satisfies Partial<import(\"@tiptap/core\").RawCommands>;\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunk5JUIMXNFjs = require('./chunk-5JUIMXNF.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkKWKV2GAHjs = require('./chunk-KWKV2GAH.js');
|
|
9
|
+
|
|
10
|
+
// src/components/AdminManagerBase.tsx
|
|
11
|
+
var _react = require('react');
|
|
12
|
+
var _reactvirtual = require('@tanstack/react-virtual');
|
|
13
|
+
var _sonner = require('sonner');
|
|
14
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
15
|
+
function AdminManagerBaseInner({
|
|
16
|
+
initialItems,
|
|
17
|
+
config,
|
|
18
|
+
initialSelectedId,
|
|
19
|
+
startWithNew,
|
|
20
|
+
defaultFilterValue,
|
|
21
|
+
innerRef
|
|
22
|
+
}) {
|
|
23
|
+
const list = _chunk5JUIMXNFjs.useAdminList.call(void 0, {
|
|
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 = _chunk5JUIMXNFjs.useAdminForm.call(void 0, 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
|
+
_react.useEffect.call(void 0, () => {
|
|
61
|
+
if (startWithNew) {
|
|
62
|
+
handleAdd();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (initialSelectedId) {
|
|
66
|
+
selectItem(initialSelectedId);
|
|
67
|
+
}
|
|
68
|
+
}, []);
|
|
69
|
+
const filteredItems = _react.useMemo.call(void 0,
|
|
70
|
+
() => config.filterItems(items, filterValue, searchQuery),
|
|
71
|
+
[items, filterValue, searchQuery, config]
|
|
72
|
+
);
|
|
73
|
+
const publishedItems = _react.useMemo.call(void 0,
|
|
74
|
+
() => items.filter(config.meta.getItemPublished),
|
|
75
|
+
[items, config]
|
|
76
|
+
);
|
|
77
|
+
const selectItem = _react.useCallback.call(void 0, async (id) => {
|
|
78
|
+
startEdit(id, config.emptyForm);
|
|
79
|
+
try {
|
|
80
|
+
const res = await _chunkKWKV2GAHjs.adminFetch.call(void 0, `${config.apiPath}/${id}`);
|
|
81
|
+
const json = await res.json();
|
|
82
|
+
if (json.success) {
|
|
83
|
+
setForm(config.loadItem(json.data));
|
|
84
|
+
} else {
|
|
85
|
+
_sonner.toast.error(_optionalChain([json, 'access', _ => _.error, 'optionalAccess', _2 => _2.message]) || "\uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328");
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {
|
|
88
|
+
_sonner.toast.error("\uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328");
|
|
89
|
+
} finally {
|
|
90
|
+
setLoading(false);
|
|
91
|
+
}
|
|
92
|
+
}, [config.apiPath, config.loadItem, config.emptyForm]);
|
|
93
|
+
_react.useImperativeHandle.call(void 0, innerRef, () => ({ selectItem }), [selectItem]);
|
|
94
|
+
const handleAdd = _react.useCallback.call(void 0, () => {
|
|
95
|
+
addNew(config.emptyForm);
|
|
96
|
+
}, [config.emptyForm]);
|
|
97
|
+
async function handleSave() {
|
|
98
|
+
const err = config.validate(form);
|
|
99
|
+
if (err) {
|
|
100
|
+
_sonner.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 _chunkKWKV2GAHjs.adminFetch.call(void 0, url, {
|
|
109
|
+
method,
|
|
110
|
+
headers: { ..._chunkKWKV2GAHjs.getAuthHeaders.call(void 0, ), "Content-Type": "application/json" },
|
|
111
|
+
body: JSON.stringify(payload)
|
|
112
|
+
});
|
|
113
|
+
const json = await res.json();
|
|
114
|
+
if (json.success) {
|
|
115
|
+
const listRes = await _chunkKWKV2GAHjs.adminFetch.call(void 0, `${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
|
+
_sonner.toast.success("\uC800\uC7A5 \uC644\uB8CC");
|
|
123
|
+
_optionalChain([config, 'access', _3 => _3.onAfterSave, 'optionalCall', _4 => _4()]);
|
|
124
|
+
_optionalChain([config, 'access', _5 => _5.onNavigateToList, 'optionalCall', _6 => _6()]);
|
|
125
|
+
} else {
|
|
126
|
+
_sonner.toast.error(_optionalChain([json, 'access', _7 => _7.error, 'optionalAccess', _8 => _8.message]) || "\uC800\uC7A5 \uC2E4\uD328");
|
|
127
|
+
}
|
|
128
|
+
} catch (e2) {
|
|
129
|
+
_sonner.toast.error("\uC800\uC7A5 \uC911 \uC624\uB958 \uBC1C\uC0DD");
|
|
130
|
+
} finally {
|
|
131
|
+
setSaving(false);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const handleDelete = _react.useCallback.call(void 0, 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 _chunkKWKV2GAHjs.adminFetch.call(void 0, `${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
|
+
_sonner.toast.error("\uC0AD\uC81C\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
|
|
150
|
+
}
|
|
151
|
+
} catch (e3) {
|
|
152
|
+
_sonner.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 = _react.useRef.call(void 0, null);
|
|
156
|
+
const virtualizer = _reactvirtual.useVirtualizer.call(void 0, {
|
|
157
|
+
count: filteredItems.length,
|
|
158
|
+
getScrollElement: () => listScrollRef.current,
|
|
159
|
+
estimateSize: () => 58,
|
|
160
|
+
overscan: 5
|
|
161
|
+
});
|
|
162
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: `pm${mobilePv ? " mobile-pv-on" : ""}`, children: [
|
|
163
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-topbar", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-tb-l", children: [
|
|
164
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "pm-tb-logo", children: config.meta.appTitle }),
|
|
165
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "pm-tb-sep" }),
|
|
166
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "pm-tb-pg", children: config.meta.pageTitle })
|
|
167
|
+
] }) }),
|
|
168
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-tabs", children: [
|
|
169
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
className: `pm-tab ${tab === "list" ? "on" : ""}`,
|
|
173
|
+
onClick: () => {
|
|
174
|
+
setTab("list");
|
|
175
|
+
_optionalChain([config, 'access', _9 => _9.onNavigateToList, 'optionalCall', _10 => _10()]);
|
|
176
|
+
},
|
|
177
|
+
children: config.meta.listTabLabel
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mobile-pv-bar", children: [
|
|
190
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-body", children: [
|
|
210
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: `pm-panel pm-panel-list ${tab === "list" ? "on" : ""}`, children: [
|
|
211
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-list-left", children: [
|
|
212
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pm-perf-list", ref: listScrollRef, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsx.call(void 0,
|
|
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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-list-right", children: [
|
|
261
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0,
|
|
269
|
+
"div",
|
|
270
|
+
{
|
|
271
|
+
className: `pm-panel pm-panel-edit ${tab === "edit" ? "on" : ""}`,
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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
|
+
_optionalChain([config, 'access', _11 => _11.onNavigateToList, 'optionalCall', _12 => _12()]);
|
|
285
|
+
},
|
|
286
|
+
onDelete: () => {
|
|
287
|
+
if (selectedId) handleDelete(selectedId);
|
|
288
|
+
}
|
|
289
|
+
}) }),
|
|
290
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "pm-edit-right", children: [
|
|
291
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "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
|
+
_optionalChain([config, 'access', _13 => _13.renderModal, 'optionalCall', _14 => _14()])
|
|
299
|
+
] });
|
|
300
|
+
}
|
|
301
|
+
function AdminManagerBase(props) {
|
|
302
|
+
const { ref, ...rest } = props;
|
|
303
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AdminManagerBaseInner, { ...rest, innerRef: ref });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
exports.AdminManagerBase = AdminManagerBase;
|
|
309
|
+
//# sourceMappingURL=chunk-DCIF4XJL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DCIF4XJL.js","../src/components/AdminManagerBase.tsx"],"names":[],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DCIF4XJL.js","sourcesContent":[null,"\"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"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.__require = __require;
|
|
11
|
+
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DGUM43GV.js"],"names":[],"mappings":"AAAA,6EAAI,UAAU,kBAAkB,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,QAAQ,IAAI,YAAY,EAAE,QAAQ,EAAE,OAAO,MAAM,IAAI,YAAY,EAAE,IAAI,KAAK,CAAC,CAAC,EAAE;AAC/H,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,QAAQ,IAAI,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE;AACpB,EAAE,GAAG,CAAC,OAAO,QAAQ,IAAI,WAAW,EAAE,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;AAC3E,EAAE,MAAM,KAAK,CAAC,uBAAuB,EAAE,EAAE,EAAE,oBAAoB,CAAC;AAChE,CAAC,CAAC;AACF;AACA;AACE;AACF,8BAAC","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DGUM43GV.js"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/utils/api-helpers.ts
|
|
2
|
+
var _server = require('next/server');
|
|
3
|
+
function validateIds(ids) {
|
|
4
|
+
if (!Array.isArray(ids) || ids.length === 0) {
|
|
5
|
+
return {
|
|
6
|
+
valid: false,
|
|
7
|
+
response: _server.NextResponse.json(
|
|
8
|
+
{ success: false, error: { message: "No ids provided" } },
|
|
9
|
+
{ status: 400 }
|
|
10
|
+
)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
return { valid: true, ids };
|
|
14
|
+
}
|
|
15
|
+
function validateAndParse(schema, data) {
|
|
16
|
+
const result = schema.safeParse(data);
|
|
17
|
+
if (!result.success) {
|
|
18
|
+
return {
|
|
19
|
+
success: false,
|
|
20
|
+
response: _server.NextResponse.json(
|
|
21
|
+
{
|
|
22
|
+
success: false,
|
|
23
|
+
error: {
|
|
24
|
+
message: _optionalChain([result, 'access', _ => _.error, 'access', _2 => _2.issues, 'access', _3 => _3[0], 'optionalAccess', _4 => _4.message]) || "Validation error",
|
|
25
|
+
details: { issues: result.error.issues }
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{ status: 400 }
|
|
29
|
+
)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return { success: true, data: result.data };
|
|
33
|
+
}
|
|
34
|
+
function parseSortKey(searchParams, validKeys, defaultKey) {
|
|
35
|
+
const param = searchParams.get("sortBy");
|
|
36
|
+
return validKeys.includes(_nullishCoalesce(param, () => ( ""))) ? param : defaultKey;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
exports.validateIds = validateIds; exports.validateAndParse = validateAndParse; exports.parseSortKey = parseSortKey;
|
|
44
|
+
//# sourceMappingURL=chunk-DSORCGJK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DSORCGJK.js","../src/utils/api-helpers.ts"],"names":[],"mappings":"AAAA;ACAA,qCAA6B;AAGtB,SAAS,WAAA,CAAY,GAAA,EAAyF;AACnH,EAAA,GAAA,CAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,EAAA,GAAK,GAAA,CAAI,OAAA,IAAW,CAAA,EAAG;AAC3C,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA;AAAA,MACP,QAAA,EAAU,oBAAA,CAAa,IAAA;AAAA,QACrB,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,EAAE,OAAA,EAAS,kBAAkB,EAAE,CAAA;AAAA,QACxD,EAAE,MAAA,EAAQ,IAAI;AAAA,MAChB;AAAA,IACF,CAAA;AAAA,EACF;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,IAAI,CAAA;AAC5B;AAEO,SAAS,gBAAA,CACd,MAAA,EACA,IAAA,EACyE;AACzE,EAAA,MAAM,OAAA,EAAS,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA;AACpC,EAAA,GAAA,CAAI,CAAC,MAAA,CAAO,OAAA,EAAS;AACnB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,QAAA,EAAU,oBAAA,CAAa,IAAA;AAAA,QACrB;AAAA,UACE,OAAA,EAAS,KAAA;AAAA,UACT,KAAA,EAAO;AAAA,YACL,OAAA,kBAAS,MAAA,mBAAO,KAAA,qBAAM,MAAA,qBAAO,CAAC,CAAA,6BAAG,UAAA,GAAW,kBAAA;AAAA,YAC5C,OAAA,EAAS,EAAE,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,OAAO;AAAA,UACzC;AAAA,QACF,CAAA;AAAA,QACA,EAAE,MAAA,EAAQ,IAAI;AAAA,MAChB;AAAA,IACF,CAAA;AAAA,EACF;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,KAAK,CAAA;AAC5C;AAEO,SAAS,YAAA,CACd,YAAA,EACA,SAAA,EACA,UAAA,EACG;AACH,EAAA,MAAM,MAAA,EAAQ,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA;AACvC,EAAA,OAAQ,SAAA,CAAgC,QAAA,kBAAS,KAAA,UAAS,IAAE,EAAA,EAAK,MAAA,EAAc,UAAA;AACjF;ADTA;AACA;AACE;AACA;AACA;AACF,oHAAC","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-DSORCGJK.js","sourcesContent":[null,"import { NextResponse } from 'next/server';\nimport type { ZodSchema } from 'zod';\n\nexport function validateIds(ids: unknown): { valid: true; ids: string[] } | { valid: false; response: NextResponse } {\n if (!Array.isArray(ids) || ids.length === 0) {\n return {\n valid: false,\n response: NextResponse.json(\n { success: false, error: { message: 'No ids provided' } },\n { status: 400 },\n ),\n };\n }\n return { valid: true, ids };\n}\n\nexport function validateAndParse<T>(\n schema: ZodSchema<T>,\n data: unknown,\n): { success: true; data: T } | { success: false; response: NextResponse } {\n const result = schema.safeParse(data);\n if (!result.success) {\n return {\n success: false,\n response: NextResponse.json(\n {\n success: false,\n error: {\n message: result.error.issues[0]?.message || 'Validation error',\n details: { issues: result.error.issues },\n },\n },\n { status: 400 },\n ),\n };\n }\n return { success: true, data: result.data };\n}\n\nexport function parseSortKey<T extends string>(\n searchParams: URLSearchParams,\n validKeys: readonly T[],\n defaultKey: T,\n): T {\n const param = searchParams.get('sortBy');\n return (validKeys as readonly string[]).includes(param ?? '') ? (param as T) : defaultKey;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/utils/date.ts
|
|
2
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
3
|
+
function toLocalDatetime(iso) {
|
|
4
|
+
if (!iso) return "";
|
|
5
|
+
const d = new Date(iso);
|
|
6
|
+
if (isNaN(d.getTime())) return "";
|
|
7
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
8
|
+
}
|
|
9
|
+
function formatDateTime(date) {
|
|
10
|
+
if (!date) return "-";
|
|
11
|
+
const d = new Date(date);
|
|
12
|
+
if (isNaN(d.getTime())) return "-";
|
|
13
|
+
return `${d.getFullYear()}.${pad(d.getMonth() + 1)}.${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
14
|
+
}
|
|
15
|
+
function formatDate(date) {
|
|
16
|
+
if (!date) return "-";
|
|
17
|
+
const d = new Date(date);
|
|
18
|
+
if (isNaN(d.getTime())) return "-";
|
|
19
|
+
return `${d.getFullYear()}.${pad(d.getMonth() + 1)}.${pad(d.getDate())}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
exports.toLocalDatetime = toLocalDatetime; exports.formatDateTime = formatDateTime; exports.formatDate = formatDate;
|
|
27
|
+
//# sourceMappingURL=chunk-E5YUAOJI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-E5YUAOJI.js","../src/utils/date.ts"],"names":[],"mappings":"AAAA;ACAA,IAAM,IAAA,EAAM,CAAC,CAAA,EAAA,GAAc,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AAE7C,SAAS,eAAA,CAAgB,GAAA,EAA4B;AAC1D,EAAA,GAAA,CAAI,CAAC,GAAA,EAAK,OAAO,EAAA;AACjB,EAAA,MAAM,EAAA,EAAI,IAAI,IAAA,CAAK,GAAG,CAAA;AACtB,EAAA,GAAA,CAAI,KAAA,CAAM,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA,EAAG,OAAO,EAAA;AAC/B,EAAA,OAAO,CAAA,EAAA;AACT;AAEgB;AACT,EAAA;AACC,EAAA;AACF,EAAA;AACG,EAAA;AACT;AAEgB;AACT,EAAA;AACC,EAAA;AACF,EAAA;AACG,EAAA;AACT;ADDU;AACA;AACA;AACA;AACA;AACA","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-cms-kit/dist/chunk-E5YUAOJI.js","sourcesContent":[null,"const pad = (n: number) => String(n).padStart(2, '0');\n\nexport function toLocalDatetime(iso: string | null): string {\n if (!iso) return '';\n const d = new Date(iso);\n if (isNaN(d.getTime())) return '';\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\nexport function formatDateTime(date: string | null): string {\n if (!date) return '-';\n const d = new Date(date);\n if (isNaN(d.getTime())) return '-';\n return `${d.getFullYear()}.${pad(d.getMonth() + 1)}.${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\nexport function formatDate(date: string | null): string {\n if (!date) return '-';\n const d = new Date(date);\n if (isNaN(d.getTime())) return '-';\n return `${d.getFullYear()}.${pad(d.getMonth() + 1)}.${pad(d.getDate())}`;\n}\n"]}
|