@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.
Files changed (327) hide show
  1. package/README.ko.md +146 -0
  2. package/README.md +146 -0
  3. package/dist/chunk-2REYWBQ6.js +32 -0
  4. package/dist/chunk-2REYWBQ6.js.map +1 -0
  5. package/dist/chunk-2SYUEQ6J.mjs +17 -0
  6. package/dist/chunk-2SYUEQ6J.mjs.map +1 -0
  7. package/dist/chunk-3ILEMZAL.mjs +32 -0
  8. package/dist/chunk-3ILEMZAL.mjs.map +1 -0
  9. package/dist/chunk-3Y2TQCHU.mjs +33 -0
  10. package/dist/chunk-3Y2TQCHU.mjs.map +1 -0
  11. package/dist/chunk-4LSFAAZW.js +1 -0
  12. package/dist/chunk-4LSFAAZW.js.map +1 -0
  13. package/dist/chunk-4W3X7OKF.js +100 -0
  14. package/dist/chunk-4W3X7OKF.js.map +1 -0
  15. package/dist/chunk-5JUIMXNF.js +108 -0
  16. package/dist/chunk-5JUIMXNF.js.map +1 -0
  17. package/dist/chunk-5RDMODGV.mjs +34 -0
  18. package/dist/chunk-5RDMODGV.mjs.map +1 -0
  19. package/dist/chunk-6ES4W2DL.mjs +1 -0
  20. package/dist/chunk-6ES4W2DL.mjs.map +1 -0
  21. package/dist/chunk-6EZ3QE5N.js +71 -0
  22. package/dist/chunk-6EZ3QE5N.js.map +1 -0
  23. package/dist/chunk-6JFERXNE.mjs +16 -0
  24. package/dist/chunk-6JFERXNE.mjs.map +1 -0
  25. package/dist/chunk-7SWW3ZIN.js +17 -0
  26. package/dist/chunk-7SWW3ZIN.js.map +1 -0
  27. package/dist/chunk-AXR56AUD.mjs +1 -0
  28. package/dist/chunk-AXR56AUD.mjs.map +1 -0
  29. package/dist/chunk-BE7JDL64.js +154 -0
  30. package/dist/chunk-BE7JDL64.js.map +1 -0
  31. package/dist/chunk-BHN2SRZC.js +51 -0
  32. package/dist/chunk-BHN2SRZC.js.map +1 -0
  33. package/dist/chunk-BJTO5JO5.mjs +11 -0
  34. package/dist/chunk-BJTO5JO5.mjs.map +1 -0
  35. package/dist/chunk-BWKKHCDG.mjs +164 -0
  36. package/dist/chunk-BWKKHCDG.mjs.map +1 -0
  37. package/dist/chunk-C5WFZJM4.js +218 -0
  38. package/dist/chunk-C5WFZJM4.js.map +1 -0
  39. package/dist/chunk-CGVFB23E.mjs +123 -0
  40. package/dist/chunk-CGVFB23E.mjs.map +1 -0
  41. package/dist/chunk-D2VDTRXO.js +1 -0
  42. package/dist/chunk-D2VDTRXO.js.map +1 -0
  43. package/dist/chunk-D75ADHVM.mjs +181 -0
  44. package/dist/chunk-D75ADHVM.mjs.map +1 -0
  45. package/dist/chunk-DCIF4XJL.js +309 -0
  46. package/dist/chunk-DCIF4XJL.js.map +1 -0
  47. package/dist/chunk-DGUM43GV.js +11 -0
  48. package/dist/chunk-DGUM43GV.js.map +1 -0
  49. package/dist/chunk-DSORCGJK.js +44 -0
  50. package/dist/chunk-DSORCGJK.js.map +1 -0
  51. package/dist/chunk-E5YUAOJI.js +27 -0
  52. package/dist/chunk-E5YUAOJI.js.map +1 -0
  53. package/dist/chunk-EG6NVPP2.js +164 -0
  54. package/dist/chunk-EG6NVPP2.js.map +1 -0
  55. package/dist/chunk-EL7YGOTY.js +1 -0
  56. package/dist/chunk-EL7YGOTY.js.map +1 -0
  57. package/dist/chunk-EM4MQEWV.mjs +100 -0
  58. package/dist/chunk-EM4MQEWV.mjs.map +1 -0
  59. package/dist/chunk-FCCCG5Z7.mjs +108 -0
  60. package/dist/chunk-FCCCG5Z7.mjs.map +1 -0
  61. package/dist/chunk-FEPGJ7WN.mjs +218 -0
  62. package/dist/chunk-FEPGJ7WN.mjs.map +1 -0
  63. package/dist/chunk-HXVWBFCN.js +16 -0
  64. package/dist/chunk-HXVWBFCN.js.map +1 -0
  65. package/dist/chunk-I5YMTJV6.mjs +51 -0
  66. package/dist/chunk-I5YMTJV6.mjs.map +1 -0
  67. package/dist/chunk-IMNWW7Q5.mjs +13 -0
  68. package/dist/chunk-IMNWW7Q5.mjs.map +1 -0
  69. package/dist/chunk-J5N76ASB.mjs +114 -0
  70. package/dist/chunk-J5N76ASB.mjs.map +1 -0
  71. package/dist/chunk-JBV26CUG.mjs +51 -0
  72. package/dist/chunk-JBV26CUG.mjs.map +1 -0
  73. package/dist/chunk-JMWXVXK5.js +53 -0
  74. package/dist/chunk-JMWXVXK5.js.map +1 -0
  75. package/dist/chunk-KWKV2GAH.js +60 -0
  76. package/dist/chunk-KWKV2GAH.js.map +1 -0
  77. package/dist/chunk-LDFE33ML.mjs +53 -0
  78. package/dist/chunk-LDFE33ML.mjs.map +1 -0
  79. package/dist/chunk-LF5LOI7K.mjs +174 -0
  80. package/dist/chunk-LF5LOI7K.mjs.map +1 -0
  81. package/dist/chunk-MMKAMH4U.mjs +16 -0
  82. package/dist/chunk-MMKAMH4U.mjs.map +1 -0
  83. package/dist/chunk-MUHFEEYW.js +33 -0
  84. package/dist/chunk-MUHFEEYW.js.map +1 -0
  85. package/dist/chunk-MUQYK5EO.js +1 -0
  86. package/dist/chunk-MUQYK5EO.js.map +1 -0
  87. package/dist/chunk-OBNALAMG.mjs +71 -0
  88. package/dist/chunk-OBNALAMG.mjs.map +1 -0
  89. package/dist/chunk-OLEYNPW6.js +25 -0
  90. package/dist/chunk-OLEYNPW6.js.map +1 -0
  91. package/dist/chunk-OYJRR3G2.js +123 -0
  92. package/dist/chunk-OYJRR3G2.js.map +1 -0
  93. package/dist/chunk-PLVG7AW3.js +16 -0
  94. package/dist/chunk-PLVG7AW3.js.map +1 -0
  95. package/dist/chunk-PYD4CES4.js +1 -0
  96. package/dist/chunk-PYD4CES4.js.map +1 -0
  97. package/dist/chunk-QACD2U6P.mjs +1 -0
  98. package/dist/chunk-QACD2U6P.mjs.map +1 -0
  99. package/dist/chunk-R5GGIVD4.js +10 -0
  100. package/dist/chunk-R5GGIVD4.js.map +1 -0
  101. package/dist/chunk-RCK5WCU5.mjs +25 -0
  102. package/dist/chunk-RCK5WCU5.mjs.map +1 -0
  103. package/dist/chunk-S6UUSM7S.js +13 -0
  104. package/dist/chunk-S6UUSM7S.js.map +1 -0
  105. package/dist/chunk-S7GOXCRM.js +114 -0
  106. package/dist/chunk-S7GOXCRM.js.map +1 -0
  107. package/dist/chunk-SMV5D5LO.mjs +28 -0
  108. package/dist/chunk-SMV5D5LO.mjs.map +1 -0
  109. package/dist/chunk-T7EVFD4G.mjs +60 -0
  110. package/dist/chunk-T7EVFD4G.mjs.map +1 -0
  111. package/dist/chunk-TLH3V4SY.mjs +1 -0
  112. package/dist/chunk-TLH3V4SY.mjs.map +1 -0
  113. package/dist/chunk-TUQ2CVAK.mjs +10 -0
  114. package/dist/chunk-TUQ2CVAK.mjs.map +1 -0
  115. package/dist/chunk-U6PVJKTB.js +51 -0
  116. package/dist/chunk-U6PVJKTB.js.map +1 -0
  117. package/dist/chunk-UXMMEEX4.mjs +27 -0
  118. package/dist/chunk-UXMMEEX4.mjs.map +1 -0
  119. package/dist/chunk-VVXNFFKI.mjs +44 -0
  120. package/dist/chunk-VVXNFFKI.mjs.map +1 -0
  121. package/dist/chunk-VZZ3RU3Q.js +28 -0
  122. package/dist/chunk-VZZ3RU3Q.js.map +1 -0
  123. package/dist/chunk-W4FWIZ2Y.js +34 -0
  124. package/dist/chunk-W4FWIZ2Y.js.map +1 -0
  125. package/dist/chunk-YEQFKOWD.mjs +154 -0
  126. package/dist/chunk-YEQFKOWD.mjs.map +1 -0
  127. package/dist/chunk-YPBKY4KY.mjs +1 -0
  128. package/dist/chunk-YPBKY4KY.mjs.map +1 -0
  129. package/dist/chunk-YY7K5CXX.js +174 -0
  130. package/dist/chunk-YY7K5CXX.js.map +1 -0
  131. package/dist/chunk-ZFORODOX.js +181 -0
  132. package/dist/chunk-ZFORODOX.js.map +1 -0
  133. package/dist/chunk-ZULSFSDG.mjs +309 -0
  134. package/dist/chunk-ZULSFSDG.mjs.map +1 -0
  135. package/dist/components/AdminManagerBase.d.mts +26 -0
  136. package/dist/components/AdminManagerBase.d.ts +26 -0
  137. package/dist/components/AdminManagerBase.js +13 -0
  138. package/dist/components/AdminManagerBase.js.map +1 -0
  139. package/dist/components/AdminManagerBase.mjs +12 -0
  140. package/dist/components/AdminManagerBase.mjs.map +1 -0
  141. package/dist/components/AdminManagerConfig.d.mts +83 -0
  142. package/dist/components/AdminManagerConfig.d.ts +83 -0
  143. package/dist/components/AdminManagerConfig.js +2 -0
  144. package/dist/components/AdminManagerConfig.js.map +1 -0
  145. package/dist/components/AdminManagerConfig.mjs +2 -0
  146. package/dist/components/AdminManagerConfig.mjs.map +1 -0
  147. package/dist/components/AdminShell.d.mts +30 -0
  148. package/dist/components/AdminShell.d.ts +30 -0
  149. package/dist/components/AdminShell.js +12 -0
  150. package/dist/components/AdminShell.js.map +1 -0
  151. package/dist/components/AdminShell.mjs +11 -0
  152. package/dist/components/AdminShell.mjs.map +1 -0
  153. package/dist/components/JsonLd.d.mts +32 -0
  154. package/dist/components/JsonLd.d.ts +32 -0
  155. package/dist/components/JsonLd.js +11 -0
  156. package/dist/components/JsonLd.js.map +1 -0
  157. package/dist/components/JsonLd.mjs +11 -0
  158. package/dist/components/JsonLd.mjs.map +1 -0
  159. package/dist/components/ResizableImage.d.mts +18 -0
  160. package/dist/components/ResizableImage.d.ts +18 -0
  161. package/dist/components/ResizableImage.js +10 -0
  162. package/dist/components/ResizableImage.js.map +1 -0
  163. package/dist/components/ResizableImage.mjs +9 -0
  164. package/dist/components/ResizableImage.mjs.map +1 -0
  165. package/dist/components/ToggleSwitch.d.mts +11 -0
  166. package/dist/components/ToggleSwitch.d.ts +11 -0
  167. package/dist/components/ToggleSwitch.js +10 -0
  168. package/dist/components/ToggleSwitch.js.map +1 -0
  169. package/dist/components/ToggleSwitch.mjs +9 -0
  170. package/dist/components/ToggleSwitch.mjs.map +1 -0
  171. package/dist/components/image-drop-zone.css +115 -0
  172. package/dist/components/index.d.mts +26 -0
  173. package/dist/components/index.d.ts +26 -0
  174. package/dist/components/index.js +35 -0
  175. package/dist/components/index.js.map +1 -0
  176. package/dist/components/index.mjs +35 -0
  177. package/dist/components/index.mjs.map +1 -0
  178. package/dist/components/toggle-switch.css +55 -0
  179. package/dist/hooks/index.d.mts +45 -0
  180. package/dist/hooks/index.d.ts +45 -0
  181. package/dist/hooks/index.js +25 -0
  182. package/dist/hooks/index.js.map +1 -0
  183. package/dist/hooks/index.mjs +25 -0
  184. package/dist/hooks/index.mjs.map +1 -0
  185. package/dist/hooks/useImageDropZone.d.mts +37 -0
  186. package/dist/hooks/useImageDropZone.d.ts +37 -0
  187. package/dist/hooks/useImageDropZone.js +13 -0
  188. package/dist/hooks/useImageDropZone.js.map +1 -0
  189. package/dist/hooks/useImageDropZone.mjs +12 -0
  190. package/dist/hooks/useImageDropZone.mjs.map +1 -0
  191. package/dist/hooks/useScrollReveal.d.mts +6 -0
  192. package/dist/hooks/useScrollReveal.d.ts +6 -0
  193. package/dist/hooks/useScrollReveal.js +12 -0
  194. package/dist/hooks/useScrollReveal.js.map +1 -0
  195. package/dist/hooks/useScrollReveal.mjs +11 -0
  196. package/dist/hooks/useScrollReveal.mjs.map +1 -0
  197. package/dist/image-drop-zone.css +115 -0
  198. package/dist/index-00a40-FQ.d.mts +136 -0
  199. package/dist/index-00a40-FQ.d.ts +136 -0
  200. package/dist/index.d.mts +35 -0
  201. package/dist/index.d.ts +35 -0
  202. package/dist/index.js +169 -0
  203. package/dist/index.js.map +1 -0
  204. package/dist/index.mjs +169 -0
  205. package/dist/index.mjs.map +1 -0
  206. package/dist/infrastructure/index.d.mts +4 -0
  207. package/dist/infrastructure/index.d.ts +4 -0
  208. package/dist/infrastructure/index.js +20 -0
  209. package/dist/infrastructure/index.js.map +1 -0
  210. package/dist/infrastructure/index.mjs +20 -0
  211. package/dist/infrastructure/index.mjs.map +1 -0
  212. package/dist/infrastructure/middleware/index.d.mts +3 -0
  213. package/dist/infrastructure/middleware/index.d.ts +3 -0
  214. package/dist/infrastructure/middleware/index.js +15 -0
  215. package/dist/infrastructure/middleware/index.js.map +1 -0
  216. package/dist/infrastructure/middleware/index.mjs +15 -0
  217. package/dist/infrastructure/middleware/index.mjs.map +1 -0
  218. package/dist/infrastructure/middleware/wrappers.d.mts +10 -0
  219. package/dist/infrastructure/middleware/wrappers.d.ts +10 -0
  220. package/dist/infrastructure/middleware/wrappers.js +15 -0
  221. package/dist/infrastructure/middleware/wrappers.js.map +1 -0
  222. package/dist/infrastructure/middleware/wrappers.mjs +15 -0
  223. package/dist/infrastructure/middleware/wrappers.mjs.map +1 -0
  224. package/dist/infrastructure/prisma.d.mts +5 -0
  225. package/dist/infrastructure/prisma.d.ts +5 -0
  226. package/dist/infrastructure/prisma.js +12 -0
  227. package/dist/infrastructure/prisma.js.map +1 -0
  228. package/dist/infrastructure/prisma.mjs +12 -0
  229. package/dist/infrastructure/prisma.mjs.map +1 -0
  230. package/dist/services/index.d.mts +22 -0
  231. package/dist/services/index.d.ts +22 -0
  232. package/dist/services/index.js +36 -0
  233. package/dist/services/index.js.map +1 -0
  234. package/dist/services/index.mjs +36 -0
  235. package/dist/services/index.mjs.map +1 -0
  236. package/dist/toggle-switch.css +55 -0
  237. package/dist/types/common.d.mts +14 -0
  238. package/dist/types/common.d.ts +14 -0
  239. package/dist/types/common.js +8 -0
  240. package/dist/types/common.js.map +1 -0
  241. package/dist/types/common.mjs +8 -0
  242. package/dist/types/common.mjs.map +1 -0
  243. package/dist/types/index.d.mts +1 -0
  244. package/dist/types/index.d.ts +1 -0
  245. package/dist/types/index.js +9 -0
  246. package/dist/types/index.js.map +1 -0
  247. package/dist/types/index.mjs +9 -0
  248. package/dist/types/index.mjs.map +1 -0
  249. package/dist/utils/admin-fetch.d.mts +11 -0
  250. package/dist/utils/admin-fetch.d.ts +11 -0
  251. package/dist/utils/admin-fetch.js +13 -0
  252. package/dist/utils/admin-fetch.js.map +1 -0
  253. package/dist/utils/admin-fetch.mjs +13 -0
  254. package/dist/utils/admin-fetch.mjs.map +1 -0
  255. package/dist/utils/api-helpers.d.mts +20 -0
  256. package/dist/utils/api-helpers.d.ts +20 -0
  257. package/dist/utils/api-helpers.js +12 -0
  258. package/dist/utils/api-helpers.js.map +1 -0
  259. package/dist/utils/api-helpers.mjs +12 -0
  260. package/dist/utils/api-helpers.mjs.map +1 -0
  261. package/dist/utils/date.d.mts +5 -0
  262. package/dist/utils/date.d.ts +5 -0
  263. package/dist/utils/date.js +12 -0
  264. package/dist/utils/date.js.map +1 -0
  265. package/dist/utils/date.mjs +12 -0
  266. package/dist/utils/date.mjs.map +1 -0
  267. package/dist/utils/html-sanitizer.d.mts +56 -0
  268. package/dist/utils/html-sanitizer.d.ts +56 -0
  269. package/dist/utils/html-sanitizer.js +11 -0
  270. package/dist/utils/html-sanitizer.js.map +1 -0
  271. package/dist/utils/html-sanitizer.mjs +11 -0
  272. package/dist/utils/html-sanitizer.mjs.map +1 -0
  273. package/dist/utils/image-variant-utils.d.mts +14 -0
  274. package/dist/utils/image-variant-utils.d.ts +14 -0
  275. package/dist/utils/image-variant-utils.js +10 -0
  276. package/dist/utils/image-variant-utils.js.map +1 -0
  277. package/dist/utils/image-variant-utils.mjs +10 -0
  278. package/dist/utils/image-variant-utils.mjs.map +1 -0
  279. package/dist/utils/image-variants.d.mts +13 -0
  280. package/dist/utils/image-variants.d.ts +13 -0
  281. package/dist/utils/image-variants.js +12 -0
  282. package/dist/utils/image-variants.js.map +1 -0
  283. package/dist/utils/image-variants.mjs +12 -0
  284. package/dist/utils/image-variants.mjs.map +1 -0
  285. package/dist/utils/index.d.mts +88 -0
  286. package/dist/utils/index.d.ts +88 -0
  287. package/dist/utils/index.js +92 -0
  288. package/dist/utils/index.js.map +1 -0
  289. package/dist/utils/index.mjs +92 -0
  290. package/dist/utils/index.mjs.map +1 -0
  291. package/dist/utils/jwt.d.mts +19 -0
  292. package/dist/utils/jwt.d.ts +19 -0
  293. package/dist/utils/jwt.js +9 -0
  294. package/dist/utils/jwt.js.map +1 -0
  295. package/dist/utils/jwt.mjs +9 -0
  296. package/dist/utils/jwt.mjs.map +1 -0
  297. package/dist/utils/r2-helpers.d.mts +9 -0
  298. package/dist/utils/r2-helpers.d.ts +9 -0
  299. package/dist/utils/r2-helpers.js +20 -0
  300. package/dist/utils/r2-helpers.js.map +1 -0
  301. package/dist/utils/r2-helpers.mjs +20 -0
  302. package/dist/utils/r2-helpers.mjs.map +1 -0
  303. package/dist/utils/r2-storage.d.mts +38 -0
  304. package/dist/utils/r2-storage.d.ts +38 -0
  305. package/dist/utils/r2-storage.js +17 -0
  306. package/dist/utils/r2-storage.js.map +1 -0
  307. package/dist/utils/r2-storage.mjs +17 -0
  308. package/dist/utils/r2-storage.mjs.map +1 -0
  309. package/dist/utils/route-params.d.mts +3 -0
  310. package/dist/utils/route-params.d.ts +3 -0
  311. package/dist/utils/route-params.js +8 -0
  312. package/dist/utils/route-params.js.map +1 -0
  313. package/dist/utils/route-params.mjs +8 -0
  314. package/dist/utils/route-params.mjs.map +1 -0
  315. package/dist/validators/index.d.mts +2 -0
  316. package/dist/validators/index.d.ts +2 -0
  317. package/dist/validators/index.js +11 -0
  318. package/dist/validators/index.js.map +1 -0
  319. package/dist/validators/index.mjs +11 -0
  320. package/dist/validators/index.mjs.map +1 -0
  321. package/dist/validators/shared.d.mts +6 -0
  322. package/dist/validators/shared.d.ts +6 -0
  323. package/dist/validators/shared.js +10 -0
  324. package/dist/validators/shared.js.map +1 -0
  325. package/dist/validators/shared.mjs +10 -0
  326. package/dist/validators/shared.mjs.map +1 -0
  327. 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"]}