sa2kit 1.6.69 → 1.6.72

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 (43) hide show
  1. package/dist/festivalCard/core/index.d.mts +1 -1
  2. package/dist/festivalCard/core/index.d.ts +1 -1
  3. package/dist/festivalCard/core/index.js +4 -2
  4. package/dist/festivalCard/core/index.js.map +1 -1
  5. package/dist/festivalCard/core/index.mjs +4 -2
  6. package/dist/festivalCard/core/index.mjs.map +1 -1
  7. package/dist/festivalCard/index.d.mts +3 -3
  8. package/dist/festivalCard/index.d.ts +3 -3
  9. package/dist/festivalCard/index.js +220 -119
  10. package/dist/festivalCard/index.js.map +1 -1
  11. package/dist/festivalCard/index.mjs +219 -120
  12. package/dist/festivalCard/index.mjs.map +1 -1
  13. package/dist/festivalCard/miniapp/index.d.mts +3 -3
  14. package/dist/festivalCard/miniapp/index.d.ts +3 -3
  15. package/dist/festivalCard/miniapp/index.js +51 -15
  16. package/dist/festivalCard/miniapp/index.js.map +1 -1
  17. package/dist/festivalCard/miniapp/index.mjs +51 -15
  18. package/dist/festivalCard/miniapp/index.mjs.map +1 -1
  19. package/dist/festivalCard/routes/index.d.mts +44 -0
  20. package/dist/festivalCard/routes/index.d.ts +44 -0
  21. package/dist/festivalCard/routes/index.js +268 -0
  22. package/dist/festivalCard/routes/index.js.map +1 -0
  23. package/dist/festivalCard/routes/index.mjs +263 -0
  24. package/dist/festivalCard/routes/index.mjs.map +1 -0
  25. package/dist/festivalCard/server/index.d.mts +1 -1
  26. package/dist/festivalCard/server/index.d.ts +1 -1
  27. package/dist/festivalCard/web/index.d.mts +18 -4
  28. package/dist/festivalCard/web/index.d.ts +18 -4
  29. package/dist/festivalCard/web/index.js +220 -119
  30. package/dist/festivalCard/web/index.js.map +1 -1
  31. package/dist/festivalCard/web/index.mjs +219 -120
  32. package/dist/festivalCard/web/index.mjs.map +1 -1
  33. package/dist/{festivalCardService-uSg0oNuD.d.mts → festivalCardService-CqBTVC6x.d.mts} +3 -1
  34. package/dist/{festivalCardService-C0fhTezx.d.ts → festivalCardService-iFKu0k9q.d.ts} +3 -1
  35. package/dist/index.d.mts +3 -3
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.js +220 -119
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.mjs +219 -120
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/{types-B-tjQTGi.d.mts → types-D2WetAPc.d.mts} +8 -1
  42. package/dist/{types-B-tjQTGi.d.ts → types-D2WetAPc.d.ts} +8 -1
  43. package/package.json +6 -1
@@ -55,7 +55,8 @@ var DEFAULT_FESTIVAL_CARD_CONFIG = {
55
55
  src: "https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80",
56
56
  fit: "cover",
57
57
  borderRadius: 16,
58
- alt: "holiday"
58
+ alt: "holiday",
59
+ isBackground: false
59
60
  }
60
61
  ]
61
62
  },
@@ -114,7 +115,8 @@ var DEFAULT_FESTIVAL_CARD_CONFIG = {
114
115
  src: "https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80",
115
116
  fit: "cover",
116
117
  borderRadius: 14,
117
- alt: "gift"
118
+ alt: "gift",
119
+ isBackground: false
118
120
  },
119
121
  {
120
122
  id: "p3-text-1",
@@ -180,9 +182,10 @@ var useFestivalCardConfig = (options) => {
180
182
  const [loading, setLoading] = useState(Boolean(options?.fetchConfig));
181
183
  const [saving, setSaving] = useState(false);
182
184
  useEffect(() => {
183
- if (!options?.fetchConfig) return;
185
+ const fetchConfig = options?.fetchConfig;
186
+ if (!fetchConfig) return;
184
187
  let active = true;
185
- void options.fetchConfig().then((value) => {
188
+ void fetchConfig().then((value) => {
186
189
  if (!active) return;
187
190
  setConfig(normalizeFestivalCardConfig(value));
188
191
  }).finally(() => {
@@ -191,16 +194,17 @@ var useFestivalCardConfig = (options) => {
191
194
  return () => {
192
195
  active = false;
193
196
  };
194
- }, [options]);
197
+ }, [options?.fetchConfig]);
195
198
  const save = useCallback(async () => {
196
- if (!options?.onSave) return;
199
+ const onSave = options?.onSave;
200
+ if (!onSave) return;
197
201
  setSaving(true);
198
202
  try {
199
- await options.onSave(config);
203
+ await onSave(config);
200
204
  } finally {
201
205
  setSaving(false);
202
206
  }
203
- }, [config, options]);
207
+ }, [config, options?.onSave]);
204
208
  return useMemo(
205
209
  () => ({
206
210
  config,
@@ -214,6 +218,7 @@ var useFestivalCardConfig = (options) => {
214
218
  };
215
219
  var elementStyle = (element) => ({
216
220
  position: "absolute",
221
+ zIndex: 2,
217
222
  left: `${element.x}%`,
218
223
  top: `${element.y}%`,
219
224
  width: `${element.width ?? 70}%`,
@@ -256,22 +261,23 @@ var renderElement = (element) => {
256
261
  );
257
262
  };
258
263
  var FestivalCardPageRenderer = ({ page }) => {
264
+ const backgroundElement = page.elements.find(
265
+ (element) => element.type === "image" && Boolean(element.isBackground)
266
+ );
267
+ const foregroundElements = page.elements.filter((element) => !(element.type === "image" && element.isBackground));
259
268
  return /* @__PURE__ */ React2.createElement(
260
269
  "div",
261
270
  {
271
+ className: "relative h-full w-full overflow-hidden rounded-2xl",
262
272
  style: {
263
- position: "relative",
264
- width: "100%",
265
- height: "100%",
266
- overflow: "hidden",
267
- borderRadius: 16,
268
273
  backgroundColor: page.background?.color || "#0f172a",
269
- backgroundImage: page.background?.image ? `url(${page.background.image})` : void 0,
274
+ backgroundImage: backgroundElement ? `url(${backgroundElement.src})` : page.background?.image ? `url(${page.background.image})` : void 0,
270
275
  backgroundSize: "cover",
271
276
  backgroundPosition: "center"
272
277
  }
273
278
  },
274
- page.elements.map(renderElement)
279
+ /* @__PURE__ */ React2.createElement("div", { className: "absolute inset-0 bg-slate-950/20" }),
280
+ foregroundElements.map(renderElement)
275
281
  );
276
282
  };
277
283
 
@@ -301,6 +307,16 @@ var FestivalCardService = class {
301
307
  constructor(options) {
302
308
  this.db = options?.db || getFestivalCardDb();
303
309
  }
310
+ async listConfigs() {
311
+ if (!this.db) {
312
+ return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
313
+ }
314
+ if (this.db.listConfigs) {
315
+ const list = await this.db.listConfigs();
316
+ return list.length > 0 ? list : [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
317
+ }
318
+ return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
319
+ }
304
320
  async getConfig(cardId = "default-festival-card") {
305
321
  if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;
306
322
  const config = await this.db.getConfig(cardId);
@@ -312,15 +328,35 @@ var FestivalCardService = class {
312
328
  await this.db.saveConfig(cardId, normalized);
313
329
  return normalized;
314
330
  }
331
+ async deleteConfig(cardId) {
332
+ if (!this.db?.deleteConfig) return;
333
+ await this.db.deleteConfig(cardId);
334
+ }
315
335
  };
316
336
  var memoryStore = /* @__PURE__ */ new Map();
337
+ var defaultId = DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card";
338
+ if (!memoryStore.has(defaultId)) {
339
+ memoryStore.set(defaultId, DEFAULT_FESTIVAL_CARD_CONFIG);
340
+ }
317
341
  var createInMemoryFestivalCardDb = () => ({
342
+ listConfigs() {
343
+ return Promise.resolve(
344
+ Array.from(memoryStore.entries()).map(([id, config]) => ({
345
+ id,
346
+ name: config.name || id
347
+ }))
348
+ );
349
+ },
318
350
  getConfig(id) {
319
351
  return Promise.resolve(memoryStore.get(id) || null);
320
352
  },
321
353
  saveConfig(id, config) {
322
354
  memoryStore.set(id, config);
323
355
  return Promise.resolve();
356
+ },
357
+ deleteConfig(id) {
358
+ memoryStore.delete(id);
359
+ return Promise.resolve();
324
360
  }
325
361
  });
326
362
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/festivalCard/core/defaults.ts","../../../src/festivalCard/core/normalize.ts","../../../src/festivalCard/hooks/useFestivalCardConfig.ts","../../../src/festivalCard/components/FestivalCardPageRenderer.tsx","../../../src/festivalCard/components/FestivalCardMiniapp.tsx","../../../src/festivalCard/server/db.ts","../../../src/festivalCard/services/festivalCardService.ts"],"names":["React","useMemo","useState"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { FestivalCardConfig } from '../types';\n\nexport const DEFAULT_FESTIVAL_CARD_CONFIG: FestivalCardConfig = {\n id: 'default-festival-card',\n name: 'Holiday Card',\n theme: 'winter',\n coverTitle: 'Happy Holidays',\n coverSubtitle: 'Warm wishes for you',\n background: {\n colorA: '#0c1a34',\n colorB: '#1f4f8a',\n },\n backgroundMusic: {\n src: '',\n loop: true,\n autoPlay: false,\n volume: 0.5,\n },\n pages: [\n {\n id: 'page-1',\n title: '封面',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p1-text-1',\n type: 'text',\n x: 50,\n y: 20,\n content: '新年快乐',\n fontSize: 34,\n fontWeight: 700,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p1-text-2',\n type: 'text',\n x: 50,\n y: 36,\n content: '愿这一年平安喜乐',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#dbeafe',\n },\n {\n id: 'p1-image-1',\n type: 'image',\n x: 50,\n y: 68,\n width: 72,\n height: 42,\n src: 'https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 16,\n alt: 'holiday',\n },\n ],\n },\n {\n id: 'page-2',\n title: '祝福',\n background: { color: '#1a3766' },\n elements: [\n {\n id: 'p2-text-1',\n type: 'text',\n x: 50,\n y: 28,\n content: '愿你新岁:',\n fontSize: 28,\n fontWeight: 700,\n align: 'center',\n color: '#fef3c7',\n },\n {\n id: 'p2-text-2',\n type: 'text',\n x: 50,\n y: 42,\n content: '所得皆所期,所失亦无碍',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p2-text-3',\n type: 'text',\n x: 50,\n y: 55,\n content: '愿你的每一步都走向光亮',\n fontSize: 16,\n fontWeight: 400,\n align: 'center',\n color: '#dbeafe',\n },\n ],\n },\n {\n id: 'page-3',\n title: '落款',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p3-image-1',\n type: 'image',\n x: 50,\n y: 34,\n width: 60,\n height: 42,\n src: 'https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 14,\n alt: 'gift',\n },\n {\n id: 'p3-text-1',\n type: 'text',\n x: 50,\n y: 72,\n content: 'Best wishes, from SA2Kit',\n fontSize: 18,\n fontWeight: 600,\n align: 'center',\n color: '#f8fafc',\n },\n ],\n },\n ],\n};\n","import { DEFAULT_FESTIVAL_CARD_CONFIG } from './defaults';\nimport type { FestivalCardConfig, FestivalCardPage } from '../types';\n\nconst ensurePage = (page: FestivalCardPage, index: number): FestivalCardPage => ({\n id: page.id || `page-${index + 1}`,\n title: page.title || `第 ${index + 1} 页`,\n elements: Array.isArray(page.elements) ? page.elements : [],\n background: page.background || {},\n});\n\nexport const normalizeFestivalCardConfig = (\n config?: Partial<FestivalCardConfig> | null\n): FestivalCardConfig => {\n const pages = config?.pages && config.pages.length > 0 ? config.pages : DEFAULT_FESTIVAL_CARD_CONFIG.pages;\n\n return {\n ...DEFAULT_FESTIVAL_CARD_CONFIG,\n ...config,\n background: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.background,\n ...(config?.background || {}),\n },\n backgroundMusic: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic,\n ...(config?.backgroundMusic || {}),\n src: config?.backgroundMusic?.src ?? DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic?.src ?? '',\n },\n pages: pages.map(ensurePage),\n };\n};\n\nexport const resizeFestivalCardPages = (config: FestivalCardConfig, pageCount: number): FestivalCardConfig => {\n const safeCount = Math.max(1, Math.min(12, Math.floor(pageCount || 1)));\n const nextPages = [...config.pages];\n\n while (nextPages.length < safeCount) {\n const idx = nextPages.length;\n nextPages.push({\n id: `page-${idx + 1}`,\n title: `第 ${idx + 1} 页`,\n elements: [],\n background: {},\n });\n }\n\n return {\n ...config,\n pages: nextPages.slice(0, safeCount),\n };\n};\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { DEFAULT_FESTIVAL_CARD_CONFIG, normalizeFestivalCardConfig } from '../core';\nimport type { FestivalCardConfig } from '../types';\n\ninterface UseFestivalCardConfigOptions {\n initialConfig?: FestivalCardConfig;\n fetchConfig?: () => Promise<FestivalCardConfig>;\n onSave?: (config: FestivalCardConfig) => Promise<void> | void;\n}\n\nexport const useFestivalCardConfig = (options?: UseFestivalCardConfigOptions) => {\n const [config, setConfig] = useState<FestivalCardConfig>(() =>\n normalizeFestivalCardConfig(options?.initialConfig || DEFAULT_FESTIVAL_CARD_CONFIG)\n );\n const [loading, setLoading] = useState(Boolean(options?.fetchConfig));\n const [saving, setSaving] = useState(false);\n\n useEffect(() => {\n if (!options?.fetchConfig) return;\n\n let active = true;\n void options\n .fetchConfig()\n .then((value) => {\n if (!active) return;\n setConfig(normalizeFestivalCardConfig(value));\n })\n .finally(() => {\n if (active) setLoading(false);\n });\n\n return () => {\n active = false;\n };\n }, [options]);\n\n const save = useCallback(async () => {\n if (!options?.onSave) return;\n setSaving(true);\n try {\n await options.onSave(config);\n } finally {\n setSaving(false);\n }\n }, [config, options]);\n\n return useMemo(\n () => ({\n config,\n setConfig,\n loading,\n saving,\n save,\n }),\n [config, loading, save, saving]\n );\n};\n","'use client';\n\nimport React from 'react';\nimport type { FestivalCardElement, FestivalCardPage } from '../types';\n\nconst elementStyle = (element: FestivalCardElement): React.CSSProperties => ({\n position: 'absolute',\n left: `${element.x}%`,\n top: `${element.y}%`,\n width: `${element.width ?? 70}%`,\n height: element.height ? `${element.height}%` : undefined,\n transform: 'translate(-50%, -50%)',\n});\n\nconst renderElement = (element: FestivalCardElement) => {\n if (element.type === 'text') {\n return (\n <div\n key={element.id}\n style={{\n ...elementStyle(element),\n color: element.color || '#f8fafc',\n fontSize: element.fontSize || 18,\n fontWeight: element.fontWeight || 500,\n textAlign: element.align || 'left',\n lineHeight: 1.45,\n whiteSpace: 'pre-wrap',\n }}\n >\n {element.content}\n </div>\n );\n }\n\n return (\n <img\n key={element.id}\n src={element.src}\n alt={element.alt || 'festival-card-image'}\n style={{\n ...elementStyle(element),\n objectFit: element.fit || 'cover',\n borderRadius: element.borderRadius || 0,\n overflow: 'hidden',\n boxShadow: '0 12px 30px rgba(2, 6, 23, 0.32)',\n }}\n />\n );\n};\n\ninterface FestivalCardPageRendererProps {\n page: FestivalCardPage;\n}\n\nexport const FestivalCardPageRenderer: React.FC<FestivalCardPageRendererProps> = ({ page }) => {\n return (\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: 16,\n backgroundColor: page.background?.color || '#0f172a',\n backgroundImage: page.background?.image ? `url(${page.background.image})` : undefined,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }}\n >\n {page.elements.map(renderElement)}\n </div>\n );\n};\n","'use client';\n\nimport React, { useMemo, useState } from 'react';\nimport { normalizeFestivalCardConfig } from '../core';\nimport type { FestivalCardConfig } from '../types';\nimport { FestivalCardPageRenderer } from './FestivalCardPageRenderer';\n\ninterface FestivalCardMiniappProps {\n config: FestivalCardConfig;\n}\n\nexport const FestivalCardMiniapp: React.FC<FestivalCardMiniappProps> = ({ config }) => {\n const normalized = useMemo(() => normalizeFestivalCardConfig(config), [config]);\n const [index, setIndex] = useState(0);\n const page = normalized.pages[index];\n\n if (!page) return null;\n\n return (\n <div>\n <div style={{ height: 420 }}>\n <FestivalCardPageRenderer page={page} />\n </div>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 12 }}>\n <button type=\"button\" disabled={index <= 0} onClick={() => setIndex((v) => Math.max(0, v - 1))}>\n 上一页\n </button>\n <div>\n {index + 1}/{normalized.pages.length}\n </div>\n <button\n type=\"button\"\n disabled={index >= normalized.pages.length - 1}\n onClick={() => setIndex((v) => Math.min(normalized.pages.length - 1, v + 1))}\n >\n 下一页\n </button>\n </div>\n </div>\n );\n};\n","import type { FestivalCardDbAdapter } from '../types';\n\nlet dbAdapter: FestivalCardDbAdapter | null = null;\n\nexport const initializeFestivalCardDb = (adapter: FestivalCardDbAdapter): void => {\n dbAdapter = adapter;\n};\n\nexport const getFestivalCardDb = (): FestivalCardDbAdapter | null => dbAdapter;\n","import { DEFAULT_FESTIVAL_CARD_CONFIG, normalizeFestivalCardConfig } from '../core';\nimport { getFestivalCardDb } from '../server/db';\nimport type { FestivalCardConfig, FestivalCardDbAdapter, FestivalCardServiceOptions } from '../types';\n\nexport class FestivalCardService {\n private db: FestivalCardDbAdapter | null;\n\n constructor(options?: FestivalCardServiceOptions) {\n this.db = options?.db || getFestivalCardDb();\n }\n\n async getConfig(cardId = 'default-festival-card'): Promise<FestivalCardConfig> {\n if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;\n const config = await this.db.getConfig(cardId);\n return normalizeFestivalCardConfig(config);\n }\n\n async saveConfig(cardId: string, config: FestivalCardConfig): Promise<FestivalCardConfig> {\n const normalized = normalizeFestivalCardConfig(config);\n if (!this.db) return normalized;\n await this.db.saveConfig(cardId, normalized);\n return normalized;\n }\n}\n\nconst memoryStore = new Map<string, FestivalCardConfig>();\n\nexport const createInMemoryFestivalCardDb = (): FestivalCardDbAdapter => ({\n getConfig(id: string) {\n return Promise.resolve(memoryStore.get(id) || null);\n },\n saveConfig(id: string, config: FestivalCardConfig) {\n memoryStore.set(id, config);\n return Promise.resolve();\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/festivalCard/core/defaults.ts","../../../src/festivalCard/core/normalize.ts","../../../src/festivalCard/hooks/useFestivalCardConfig.ts","../../../src/festivalCard/components/FestivalCardPageRenderer.tsx","../../../src/festivalCard/components/FestivalCardMiniapp.tsx","../../../src/festivalCard/server/db.ts","../../../src/festivalCard/services/festivalCardService.ts"],"names":["React","useMemo","useState"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { FestivalCardConfig } from '../types';\n\nexport const DEFAULT_FESTIVAL_CARD_CONFIG: FestivalCardConfig = {\n id: 'default-festival-card',\n name: 'Holiday Card',\n theme: 'winter',\n coverTitle: 'Happy Holidays',\n coverSubtitle: 'Warm wishes for you',\n background: {\n colorA: '#0c1a34',\n colorB: '#1f4f8a',\n },\n backgroundMusic: {\n src: '',\n loop: true,\n autoPlay: false,\n volume: 0.5,\n },\n pages: [\n {\n id: 'page-1',\n title: '封面',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p1-text-1',\n type: 'text',\n x: 50,\n y: 20,\n content: '新年快乐',\n fontSize: 34,\n fontWeight: 700,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p1-text-2',\n type: 'text',\n x: 50,\n y: 36,\n content: '愿这一年平安喜乐',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#dbeafe',\n },\n {\n id: 'p1-image-1',\n type: 'image',\n x: 50,\n y: 68,\n width: 72,\n height: 42,\n src: 'https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 16,\n alt: 'holiday',\n isBackground: false,\n },\n ],\n },\n {\n id: 'page-2',\n title: '祝福',\n background: { color: '#1a3766' },\n elements: [\n {\n id: 'p2-text-1',\n type: 'text',\n x: 50,\n y: 28,\n content: '愿你新岁:',\n fontSize: 28,\n fontWeight: 700,\n align: 'center',\n color: '#fef3c7',\n },\n {\n id: 'p2-text-2',\n type: 'text',\n x: 50,\n y: 42,\n content: '所得皆所期,所失亦无碍',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p2-text-3',\n type: 'text',\n x: 50,\n y: 55,\n content: '愿你的每一步都走向光亮',\n fontSize: 16,\n fontWeight: 400,\n align: 'center',\n color: '#dbeafe',\n },\n ],\n },\n {\n id: 'page-3',\n title: '落款',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p3-image-1',\n type: 'image',\n x: 50,\n y: 34,\n width: 60,\n height: 42,\n src: 'https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 14,\n alt: 'gift',\n isBackground: false,\n },\n {\n id: 'p3-text-1',\n type: 'text',\n x: 50,\n y: 72,\n content: 'Best wishes, from SA2Kit',\n fontSize: 18,\n fontWeight: 600,\n align: 'center',\n color: '#f8fafc',\n },\n ],\n },\n ],\n};\n","import { DEFAULT_FESTIVAL_CARD_CONFIG } from './defaults';\nimport type { FestivalCardConfig, FestivalCardPage } from '../types';\n\nconst ensurePage = (page: FestivalCardPage, index: number): FestivalCardPage => ({\n id: page.id || `page-${index + 1}`,\n title: page.title || `第 ${index + 1} 页`,\n elements: Array.isArray(page.elements) ? page.elements : [],\n background: page.background || {},\n});\n\nexport const normalizeFestivalCardConfig = (\n config?: Partial<FestivalCardConfig> | null\n): FestivalCardConfig => {\n const pages = config?.pages && config.pages.length > 0 ? config.pages : DEFAULT_FESTIVAL_CARD_CONFIG.pages;\n\n return {\n ...DEFAULT_FESTIVAL_CARD_CONFIG,\n ...config,\n background: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.background,\n ...(config?.background || {}),\n },\n backgroundMusic: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic,\n ...(config?.backgroundMusic || {}),\n src: config?.backgroundMusic?.src ?? DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic?.src ?? '',\n },\n pages: pages.map(ensurePage),\n };\n};\n\nexport const resizeFestivalCardPages = (config: FestivalCardConfig, pageCount: number): FestivalCardConfig => {\n const safeCount = Math.max(1, Math.min(12, Math.floor(pageCount || 1)));\n const nextPages = [...config.pages];\n\n while (nextPages.length < safeCount) {\n const idx = nextPages.length;\n nextPages.push({\n id: `page-${idx + 1}`,\n title: `第 ${idx + 1} 页`,\n elements: [],\n background: {},\n });\n }\n\n return {\n ...config,\n pages: nextPages.slice(0, safeCount),\n };\n};\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { DEFAULT_FESTIVAL_CARD_CONFIG, normalizeFestivalCardConfig } from '../core';\nimport type { FestivalCardConfig } from '../types';\n\ninterface UseFestivalCardConfigOptions {\n initialConfig?: FestivalCardConfig;\n fetchConfig?: () => Promise<FestivalCardConfig>;\n onSave?: (config: FestivalCardConfig) => Promise<void> | void;\n}\n\nexport const useFestivalCardConfig = (options?: UseFestivalCardConfigOptions) => {\n const [config, setConfig] = useState<FestivalCardConfig>(() =>\n normalizeFestivalCardConfig(options?.initialConfig || DEFAULT_FESTIVAL_CARD_CONFIG)\n );\n const [loading, setLoading] = useState(Boolean(options?.fetchConfig));\n const [saving, setSaving] = useState(false);\n\n useEffect(() => {\n const fetchConfig = options?.fetchConfig;\n if (!fetchConfig) return;\n\n let active = true;\n void fetchConfig()\n .then((value) => {\n if (!active) return;\n setConfig(normalizeFestivalCardConfig(value));\n })\n .finally(() => {\n if (active) setLoading(false);\n });\n\n return () => {\n active = false;\n };\n }, [options?.fetchConfig]);\n\n const save = useCallback(async () => {\n const onSave = options?.onSave;\n if (!onSave) return;\n setSaving(true);\n try {\n await onSave(config);\n } finally {\n setSaving(false);\n }\n }, [config, options?.onSave]);\n\n return useMemo(\n () => ({\n config,\n setConfig,\n loading,\n saving,\n save,\n }),\n [config, loading, save, saving]\n );\n};\n","'use client';\n\nimport React from 'react';\nimport type { FestivalCardElement, FestivalCardPage } from '../types';\n\nconst elementStyle = (element: FestivalCardElement): React.CSSProperties => ({\n position: 'absolute',\n zIndex: 2,\n left: `${element.x}%`,\n top: `${element.y}%`,\n width: `${element.width ?? 70}%`,\n height: element.height ? `${element.height}%` : undefined,\n transform: 'translate(-50%, -50%)',\n});\n\nconst renderElement = (element: FestivalCardElement) => {\n if (element.type === 'text') {\n return (\n <div\n key={element.id}\n style={{\n ...elementStyle(element),\n color: element.color || '#f8fafc',\n fontSize: element.fontSize || 18,\n fontWeight: element.fontWeight || 500,\n textAlign: element.align || 'left',\n lineHeight: 1.45,\n whiteSpace: 'pre-wrap',\n }}\n >\n {element.content}\n </div>\n );\n }\n\n return (\n <img\n key={element.id}\n src={element.src}\n alt={element.alt || 'festival-card-image'}\n style={{\n ...elementStyle(element),\n objectFit: element.fit || 'cover',\n borderRadius: element.borderRadius || 0,\n overflow: 'hidden',\n boxShadow: '0 12px 30px rgba(2, 6, 23, 0.32)',\n }}\n />\n );\n};\n\ninterface FestivalCardPageRendererProps {\n page: FestivalCardPage;\n}\n\nexport const FestivalCardPageRenderer: React.FC<FestivalCardPageRendererProps> = ({ page }) => {\n const backgroundElement = page.elements.find(\n (element): element is Extract<FestivalCardElement, { type: 'image' }> => element.type === 'image' && Boolean(element.isBackground)\n );\n const foregroundElements = page.elements.filter((element) => !(element.type === 'image' && element.isBackground));\n\n return (\n <div\n className=\"relative h-full w-full overflow-hidden rounded-2xl\"\n style={{\n backgroundColor: page.background?.color || '#0f172a',\n backgroundImage: backgroundElement\n ? `url(${backgroundElement.src})`\n : page.background?.image\n ? `url(${page.background.image})`\n : undefined,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }}\n >\n <div className=\"absolute inset-0 bg-slate-950/20\" />\n {foregroundElements.map(renderElement)}\n </div>\n );\n};\n","'use client';\n\nimport React, { useMemo, useState } from 'react';\nimport { normalizeFestivalCardConfig } from '../core';\nimport type { FestivalCardConfig } from '../types';\nimport { FestivalCardPageRenderer } from './FestivalCardPageRenderer';\n\ninterface FestivalCardMiniappProps {\n config: FestivalCardConfig;\n}\n\nexport const FestivalCardMiniapp: React.FC<FestivalCardMiniappProps> = ({ config }) => {\n const normalized = useMemo(() => normalizeFestivalCardConfig(config), [config]);\n const [index, setIndex] = useState(0);\n const page = normalized.pages[index];\n\n if (!page) return null;\n\n return (\n <div>\n <div style={{ height: 420 }}>\n <FestivalCardPageRenderer page={page} />\n </div>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 12 }}>\n <button type=\"button\" disabled={index <= 0} onClick={() => setIndex((v) => Math.max(0, v - 1))}>\n 上一页\n </button>\n <div>\n {index + 1}/{normalized.pages.length}\n </div>\n <button\n type=\"button\"\n disabled={index >= normalized.pages.length - 1}\n onClick={() => setIndex((v) => Math.min(normalized.pages.length - 1, v + 1))}\n >\n 下一页\n </button>\n </div>\n </div>\n );\n};\n","import type { FestivalCardDbAdapter } from '../types';\n\nlet dbAdapter: FestivalCardDbAdapter | null = null;\n\nexport const initializeFestivalCardDb = (adapter: FestivalCardDbAdapter): void => {\n dbAdapter = adapter;\n};\n\nexport const getFestivalCardDb = (): FestivalCardDbAdapter | null => dbAdapter;\n","import { DEFAULT_FESTIVAL_CARD_CONFIG, normalizeFestivalCardConfig } from '../core';\nimport { getFestivalCardDb } from '../server/db';\nimport type {\n FestivalCardConfig,\n FestivalCardConfigSummary,\n FestivalCardDbAdapter,\n FestivalCardServiceOptions,\n} from '../types';\n\nexport class FestivalCardService {\n private db: FestivalCardDbAdapter | null;\n\n constructor(options?: FestivalCardServiceOptions) {\n this.db = options?.db || getFestivalCardDb();\n }\n\n async listConfigs(): Promise<FestivalCardConfigSummary[]> {\n if (!this.db) {\n return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n if (this.db.listConfigs) {\n const list = await this.db.listConfigs();\n return list.length > 0\n ? list\n : [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n async getConfig(cardId = 'default-festival-card'): Promise<FestivalCardConfig> {\n if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;\n const config = await this.db.getConfig(cardId);\n return normalizeFestivalCardConfig(config);\n }\n\n async saveConfig(cardId: string, config: FestivalCardConfig): Promise<FestivalCardConfig> {\n const normalized = normalizeFestivalCardConfig(config);\n if (!this.db) return normalized;\n await this.db.saveConfig(cardId, normalized);\n return normalized;\n }\n\n async deleteConfig(cardId: string): Promise<void> {\n if (!this.db?.deleteConfig) return;\n await this.db.deleteConfig(cardId);\n }\n}\n\nconst memoryStore = new Map<string, FestivalCardConfig>();\nconst defaultId = DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card';\nif (!memoryStore.has(defaultId)) {\n memoryStore.set(defaultId, DEFAULT_FESTIVAL_CARD_CONFIG);\n}\n\nexport const createInMemoryFestivalCardDb = (): FestivalCardDbAdapter => ({\n listConfigs() {\n return Promise.resolve(\n Array.from(memoryStore.entries()).map(([id, config]) => ({\n id,\n name: config.name || id,\n }))\n );\n },\n getConfig(id: string) {\n return Promise.resolve(memoryStore.get(id) || null);\n },\n saveConfig(id: string, config: FestivalCardConfig) {\n memoryStore.set(id, config);\n return Promise.resolve();\n },\n deleteConfig(id: string) {\n memoryStore.delete(id);\n return Promise.resolve();\n },\n});\n"]}
@@ -0,0 +1,44 @@
1
+ import { i as FestivalCardDbAdapter, h as FestivalCardConfigSummary, F as FestivalCardConfig } from '../../types-D2WetAPc.mjs';
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+
4
+ interface FestivalCardRouteConfig {
5
+ db?: FestivalCardDbAdapter;
6
+ }
7
+ declare const createListFestivalCardsHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest) => Promise<NextResponse<{
8
+ success: boolean;
9
+ data: FestivalCardConfigSummary[];
10
+ }> | NextResponse<{
11
+ success: boolean;
12
+ error: string;
13
+ }>>;
14
+ declare const createGetFestivalCardHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest, context: {
15
+ params: {
16
+ id: string;
17
+ };
18
+ }) => Promise<NextResponse<{
19
+ success: boolean;
20
+ data: FestivalCardConfig;
21
+ }> | NextResponse<{
22
+ success: boolean;
23
+ error: string;
24
+ }>>;
25
+ declare const createUpsertFestivalCardHandler: (config?: FestivalCardRouteConfig) => (request: NextRequest, context: {
26
+ params: {
27
+ id: string;
28
+ };
29
+ }) => Promise<NextResponse<{
30
+ success: boolean;
31
+ data: FestivalCardConfig;
32
+ }> | NextResponse<{
33
+ success: boolean;
34
+ error: string;
35
+ }>>;
36
+ declare const createDeleteFestivalCardHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest, context: {
37
+ params: {
38
+ id: string;
39
+ };
40
+ }) => Promise<NextResponse<{
41
+ success: boolean;
42
+ }>>;
43
+
44
+ export { type FestivalCardRouteConfig, createDeleteFestivalCardHandler, createGetFestivalCardHandler, createListFestivalCardsHandler, createUpsertFestivalCardHandler };
@@ -0,0 +1,44 @@
1
+ import { i as FestivalCardDbAdapter, h as FestivalCardConfigSummary, F as FestivalCardConfig } from '../../types-D2WetAPc.js';
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+
4
+ interface FestivalCardRouteConfig {
5
+ db?: FestivalCardDbAdapter;
6
+ }
7
+ declare const createListFestivalCardsHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest) => Promise<NextResponse<{
8
+ success: boolean;
9
+ data: FestivalCardConfigSummary[];
10
+ }> | NextResponse<{
11
+ success: boolean;
12
+ error: string;
13
+ }>>;
14
+ declare const createGetFestivalCardHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest, context: {
15
+ params: {
16
+ id: string;
17
+ };
18
+ }) => Promise<NextResponse<{
19
+ success: boolean;
20
+ data: FestivalCardConfig;
21
+ }> | NextResponse<{
22
+ success: boolean;
23
+ error: string;
24
+ }>>;
25
+ declare const createUpsertFestivalCardHandler: (config?: FestivalCardRouteConfig) => (request: NextRequest, context: {
26
+ params: {
27
+ id: string;
28
+ };
29
+ }) => Promise<NextResponse<{
30
+ success: boolean;
31
+ data: FestivalCardConfig;
32
+ }> | NextResponse<{
33
+ success: boolean;
34
+ error: string;
35
+ }>>;
36
+ declare const createDeleteFestivalCardHandler: (config?: FestivalCardRouteConfig) => (_request: NextRequest, context: {
37
+ params: {
38
+ id: string;
39
+ };
40
+ }) => Promise<NextResponse<{
41
+ success: boolean;
42
+ }>>;
43
+
44
+ export { type FestivalCardRouteConfig, createDeleteFestivalCardHandler, createGetFestivalCardHandler, createListFestivalCardsHandler, createUpsertFestivalCardHandler };
@@ -0,0 +1,268 @@
1
+ 'use strict';
2
+
3
+ var server = require('next/server');
4
+
5
+ // src/festivalCard/routes/index.ts
6
+
7
+ // src/festivalCard/server/db.ts
8
+ var dbAdapter = null;
9
+ var initializeFestivalCardDb = (adapter) => {
10
+ dbAdapter = adapter;
11
+ };
12
+ var getFestivalCardDb = () => dbAdapter;
13
+
14
+ // src/festivalCard/core/defaults.ts
15
+ var DEFAULT_FESTIVAL_CARD_CONFIG = {
16
+ id: "default-festival-card",
17
+ name: "Holiday Card",
18
+ theme: "winter",
19
+ coverTitle: "Happy Holidays",
20
+ coverSubtitle: "Warm wishes for you",
21
+ background: {
22
+ colorA: "#0c1a34",
23
+ colorB: "#1f4f8a"
24
+ },
25
+ backgroundMusic: {
26
+ src: "",
27
+ loop: true,
28
+ autoPlay: false,
29
+ volume: 0.5
30
+ },
31
+ pages: [
32
+ {
33
+ id: "page-1",
34
+ title: "\u5C01\u9762",
35
+ background: { color: "#11284d" },
36
+ elements: [
37
+ {
38
+ id: "p1-text-1",
39
+ type: "text",
40
+ x: 50,
41
+ y: 20,
42
+ content: "\u65B0\u5E74\u5FEB\u4E50",
43
+ fontSize: 34,
44
+ fontWeight: 700,
45
+ align: "center",
46
+ color: "#f8fafc"
47
+ },
48
+ {
49
+ id: "p1-text-2",
50
+ type: "text",
51
+ x: 50,
52
+ y: 36,
53
+ content: "\u613F\u8FD9\u4E00\u5E74\u5E73\u5B89\u559C\u4E50",
54
+ fontSize: 18,
55
+ fontWeight: 500,
56
+ align: "center",
57
+ color: "#dbeafe"
58
+ },
59
+ {
60
+ id: "p1-image-1",
61
+ type: "image",
62
+ x: 50,
63
+ y: 68,
64
+ width: 72,
65
+ height: 42,
66
+ src: "https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80",
67
+ fit: "cover",
68
+ borderRadius: 16,
69
+ alt: "holiday",
70
+ isBackground: false
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ id: "page-2",
76
+ title: "\u795D\u798F",
77
+ background: { color: "#1a3766" },
78
+ elements: [
79
+ {
80
+ id: "p2-text-1",
81
+ type: "text",
82
+ x: 50,
83
+ y: 28,
84
+ content: "\u613F\u4F60\u65B0\u5C81\uFF1A",
85
+ fontSize: 28,
86
+ fontWeight: 700,
87
+ align: "center",
88
+ color: "#fef3c7"
89
+ },
90
+ {
91
+ id: "p2-text-2",
92
+ type: "text",
93
+ x: 50,
94
+ y: 42,
95
+ content: "\u6240\u5F97\u7686\u6240\u671F\uFF0C\u6240\u5931\u4EA6\u65E0\u788D",
96
+ fontSize: 18,
97
+ fontWeight: 500,
98
+ align: "center",
99
+ color: "#f8fafc"
100
+ },
101
+ {
102
+ id: "p2-text-3",
103
+ type: "text",
104
+ x: 50,
105
+ y: 55,
106
+ content: "\u613F\u4F60\u7684\u6BCF\u4E00\u6B65\u90FD\u8D70\u5411\u5149\u4EAE",
107
+ fontSize: 16,
108
+ fontWeight: 400,
109
+ align: "center",
110
+ color: "#dbeafe"
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ id: "page-3",
116
+ title: "\u843D\u6B3E",
117
+ background: { color: "#11284d" },
118
+ elements: [
119
+ {
120
+ id: "p3-image-1",
121
+ type: "image",
122
+ x: 50,
123
+ y: 34,
124
+ width: 60,
125
+ height: 42,
126
+ src: "https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80",
127
+ fit: "cover",
128
+ borderRadius: 14,
129
+ alt: "gift",
130
+ isBackground: false
131
+ },
132
+ {
133
+ id: "p3-text-1",
134
+ type: "text",
135
+ x: 50,
136
+ y: 72,
137
+ content: "Best wishes, from SA2Kit",
138
+ fontSize: 18,
139
+ fontWeight: 600,
140
+ align: "center",
141
+ color: "#f8fafc"
142
+ }
143
+ ]
144
+ }
145
+ ]
146
+ };
147
+
148
+ // src/festivalCard/core/normalize.ts
149
+ var ensurePage = (page, index) => ({
150
+ id: page.id || `page-${index + 1}`,
151
+ title: page.title || `\u7B2C ${index + 1} \u9875`,
152
+ elements: Array.isArray(page.elements) ? page.elements : [],
153
+ background: page.background || {}
154
+ });
155
+ var normalizeFestivalCardConfig = (config) => {
156
+ const pages = config?.pages && config.pages.length > 0 ? config.pages : DEFAULT_FESTIVAL_CARD_CONFIG.pages;
157
+ return {
158
+ ...DEFAULT_FESTIVAL_CARD_CONFIG,
159
+ ...config,
160
+ background: {
161
+ ...DEFAULT_FESTIVAL_CARD_CONFIG.background,
162
+ ...config?.background || {}
163
+ },
164
+ backgroundMusic: {
165
+ ...DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic,
166
+ ...config?.backgroundMusic || {},
167
+ src: config?.backgroundMusic?.src ?? DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic?.src ?? ""
168
+ },
169
+ pages: pages.map(ensurePage)
170
+ };
171
+ };
172
+
173
+ // src/festivalCard/services/festivalCardService.ts
174
+ var FestivalCardService = class {
175
+ constructor(options) {
176
+ this.db = options?.db || getFestivalCardDb();
177
+ }
178
+ async listConfigs() {
179
+ if (!this.db) {
180
+ return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
181
+ }
182
+ if (this.db.listConfigs) {
183
+ const list = await this.db.listConfigs();
184
+ return list.length > 0 ? list : [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
185
+ }
186
+ return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card", name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];
187
+ }
188
+ async getConfig(cardId = "default-festival-card") {
189
+ if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;
190
+ const config = await this.db.getConfig(cardId);
191
+ return normalizeFestivalCardConfig(config);
192
+ }
193
+ async saveConfig(cardId, config) {
194
+ const normalized = normalizeFestivalCardConfig(config);
195
+ if (!this.db) return normalized;
196
+ await this.db.saveConfig(cardId, normalized);
197
+ return normalized;
198
+ }
199
+ async deleteConfig(cardId) {
200
+ if (!this.db?.deleteConfig) return;
201
+ await this.db.deleteConfig(cardId);
202
+ }
203
+ };
204
+ var memoryStore = /* @__PURE__ */ new Map();
205
+ var defaultId = DEFAULT_FESTIVAL_CARD_CONFIG.id || "default-festival-card";
206
+ if (!memoryStore.has(defaultId)) {
207
+ memoryStore.set(defaultId, DEFAULT_FESTIVAL_CARD_CONFIG);
208
+ }
209
+
210
+ // src/festivalCard/routes/index.ts
211
+ var createService = (config) => {
212
+ if (config.db) initializeFestivalCardDb(config.db);
213
+ return new FestivalCardService({ db: config.db });
214
+ };
215
+ var createListFestivalCardsHandler = (config = {}) => {
216
+ const service = createService(config);
217
+ return async (_request) => {
218
+ try {
219
+ const data = await service.listConfigs();
220
+ return server.NextResponse.json({ success: true, data });
221
+ } catch (error) {
222
+ return server.NextResponse.json({ success: false, error: error.message }, { status: 500 });
223
+ }
224
+ };
225
+ };
226
+ var createGetFestivalCardHandler = (config = {}) => {
227
+ const service = createService(config);
228
+ return async (_request, context) => {
229
+ try {
230
+ const card = await service.getConfig(context.params.id);
231
+ return server.NextResponse.json({ success: true, data: card });
232
+ } catch (error) {
233
+ return server.NextResponse.json({ success: false, error: error.message }, { status: 500 });
234
+ }
235
+ };
236
+ };
237
+ var createUpsertFestivalCardHandler = (config = {}) => {
238
+ const service = createService(config);
239
+ return async (request, context) => {
240
+ try {
241
+ const body = await request.json();
242
+ const payload = body && typeof body === "object" && "config" in body ? body.config : void 0;
243
+ const normalized = normalizeFestivalCardConfig(payload || {});
244
+ const data = await service.saveConfig(context.params.id, normalized);
245
+ return server.NextResponse.json({ success: true, data });
246
+ } catch (error) {
247
+ return server.NextResponse.json({ success: false, error: error.message }, { status: 500 });
248
+ }
249
+ };
250
+ };
251
+ var createDeleteFestivalCardHandler = (config = {}) => {
252
+ const service = createService(config);
253
+ return async (_request, context) => {
254
+ try {
255
+ await service.deleteConfig(context.params.id);
256
+ return server.NextResponse.json({ success: true });
257
+ } catch (error) {
258
+ return server.NextResponse.json({ success: false, error: error.message }, { status: 500 });
259
+ }
260
+ };
261
+ };
262
+
263
+ exports.createDeleteFestivalCardHandler = createDeleteFestivalCardHandler;
264
+ exports.createGetFestivalCardHandler = createGetFestivalCardHandler;
265
+ exports.createListFestivalCardsHandler = createListFestivalCardsHandler;
266
+ exports.createUpsertFestivalCardHandler = createUpsertFestivalCardHandler;
267
+ //# sourceMappingURL=index.js.map
268
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/festivalCard/server/db.ts","../../../src/festivalCard/core/defaults.ts","../../../src/festivalCard/core/normalize.ts","../../../src/festivalCard/services/festivalCardService.ts","../../../src/festivalCard/routes/index.ts"],"names":["NextResponse"],"mappings":"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","file":"index.js","sourcesContent":["import type { FestivalCardDbAdapter } from '../types';\n\nlet dbAdapter: FestivalCardDbAdapter | null = null;\n\nexport const initializeFestivalCardDb = (adapter: FestivalCardDbAdapter): void => {\n dbAdapter = adapter;\n};\n\nexport const getFestivalCardDb = (): FestivalCardDbAdapter | null => dbAdapter;\n","import type { FestivalCardConfig } from '../types';\n\nexport const DEFAULT_FESTIVAL_CARD_CONFIG: FestivalCardConfig = {\n id: 'default-festival-card',\n name: 'Holiday Card',\n theme: 'winter',\n coverTitle: 'Happy Holidays',\n coverSubtitle: 'Warm wishes for you',\n background: {\n colorA: '#0c1a34',\n colorB: '#1f4f8a',\n },\n backgroundMusic: {\n src: '',\n loop: true,\n autoPlay: false,\n volume: 0.5,\n },\n pages: [\n {\n id: 'page-1',\n title: '封面',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p1-text-1',\n type: 'text',\n x: 50,\n y: 20,\n content: '新年快乐',\n fontSize: 34,\n fontWeight: 700,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p1-text-2',\n type: 'text',\n x: 50,\n y: 36,\n content: '愿这一年平安喜乐',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#dbeafe',\n },\n {\n id: 'p1-image-1',\n type: 'image',\n x: 50,\n y: 68,\n width: 72,\n height: 42,\n src: 'https://images.unsplash.com/photo-1512389142860-9c449e58a543?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 16,\n alt: 'holiday',\n isBackground: false,\n },\n ],\n },\n {\n id: 'page-2',\n title: '祝福',\n background: { color: '#1a3766' },\n elements: [\n {\n id: 'p2-text-1',\n type: 'text',\n x: 50,\n y: 28,\n content: '愿你新岁:',\n fontSize: 28,\n fontWeight: 700,\n align: 'center',\n color: '#fef3c7',\n },\n {\n id: 'p2-text-2',\n type: 'text',\n x: 50,\n y: 42,\n content: '所得皆所期,所失亦无碍',\n fontSize: 18,\n fontWeight: 500,\n align: 'center',\n color: '#f8fafc',\n },\n {\n id: 'p2-text-3',\n type: 'text',\n x: 50,\n y: 55,\n content: '愿你的每一步都走向光亮',\n fontSize: 16,\n fontWeight: 400,\n align: 'center',\n color: '#dbeafe',\n },\n ],\n },\n {\n id: 'page-3',\n title: '落款',\n background: { color: '#11284d' },\n elements: [\n {\n id: 'p3-image-1',\n type: 'image',\n x: 50,\n y: 34,\n width: 60,\n height: 42,\n src: 'https://images.unsplash.com/photo-1456324504439-367cee3b3c32?auto=format&fit=crop&w=1200&q=80',\n fit: 'cover',\n borderRadius: 14,\n alt: 'gift',\n isBackground: false,\n },\n {\n id: 'p3-text-1',\n type: 'text',\n x: 50,\n y: 72,\n content: 'Best wishes, from SA2Kit',\n fontSize: 18,\n fontWeight: 600,\n align: 'center',\n color: '#f8fafc',\n },\n ],\n },\n ],\n};\n","import { DEFAULT_FESTIVAL_CARD_CONFIG } from './defaults';\nimport type { FestivalCardConfig, FestivalCardPage } from '../types';\n\nconst ensurePage = (page: FestivalCardPage, index: number): FestivalCardPage => ({\n id: page.id || `page-${index + 1}`,\n title: page.title || `第 ${index + 1} 页`,\n elements: Array.isArray(page.elements) ? page.elements : [],\n background: page.background || {},\n});\n\nexport const normalizeFestivalCardConfig = (\n config?: Partial<FestivalCardConfig> | null\n): FestivalCardConfig => {\n const pages = config?.pages && config.pages.length > 0 ? config.pages : DEFAULT_FESTIVAL_CARD_CONFIG.pages;\n\n return {\n ...DEFAULT_FESTIVAL_CARD_CONFIG,\n ...config,\n background: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.background,\n ...(config?.background || {}),\n },\n backgroundMusic: {\n ...DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic,\n ...(config?.backgroundMusic || {}),\n src: config?.backgroundMusic?.src ?? DEFAULT_FESTIVAL_CARD_CONFIG.backgroundMusic?.src ?? '',\n },\n pages: pages.map(ensurePage),\n };\n};\n\nexport const resizeFestivalCardPages = (config: FestivalCardConfig, pageCount: number): FestivalCardConfig => {\n const safeCount = Math.max(1, Math.min(12, Math.floor(pageCount || 1)));\n const nextPages = [...config.pages];\n\n while (nextPages.length < safeCount) {\n const idx = nextPages.length;\n nextPages.push({\n id: `page-${idx + 1}`,\n title: `第 ${idx + 1} 页`,\n elements: [],\n background: {},\n });\n }\n\n return {\n ...config,\n pages: nextPages.slice(0, safeCount),\n };\n};\n","import { DEFAULT_FESTIVAL_CARD_CONFIG, normalizeFestivalCardConfig } from '../core';\nimport { getFestivalCardDb } from '../server/db';\nimport type {\n FestivalCardConfig,\n FestivalCardConfigSummary,\n FestivalCardDbAdapter,\n FestivalCardServiceOptions,\n} from '../types';\n\nexport class FestivalCardService {\n private db: FestivalCardDbAdapter | null;\n\n constructor(options?: FestivalCardServiceOptions) {\n this.db = options?.db || getFestivalCardDb();\n }\n\n async listConfigs(): Promise<FestivalCardConfigSummary[]> {\n if (!this.db) {\n return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n if (this.db.listConfigs) {\n const list = await this.db.listConfigs();\n return list.length > 0\n ? list\n : [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n return [{ id: DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card', name: DEFAULT_FESTIVAL_CARD_CONFIG.name }];\n }\n\n async getConfig(cardId = 'default-festival-card'): Promise<FestivalCardConfig> {\n if (!this.db) return DEFAULT_FESTIVAL_CARD_CONFIG;\n const config = await this.db.getConfig(cardId);\n return normalizeFestivalCardConfig(config);\n }\n\n async saveConfig(cardId: string, config: FestivalCardConfig): Promise<FestivalCardConfig> {\n const normalized = normalizeFestivalCardConfig(config);\n if (!this.db) return normalized;\n await this.db.saveConfig(cardId, normalized);\n return normalized;\n }\n\n async deleteConfig(cardId: string): Promise<void> {\n if (!this.db?.deleteConfig) return;\n await this.db.deleteConfig(cardId);\n }\n}\n\nconst memoryStore = new Map<string, FestivalCardConfig>();\nconst defaultId = DEFAULT_FESTIVAL_CARD_CONFIG.id || 'default-festival-card';\nif (!memoryStore.has(defaultId)) {\n memoryStore.set(defaultId, DEFAULT_FESTIVAL_CARD_CONFIG);\n}\n\nexport const createInMemoryFestivalCardDb = (): FestivalCardDbAdapter => ({\n listConfigs() {\n return Promise.resolve(\n Array.from(memoryStore.entries()).map(([id, config]) => ({\n id,\n name: config.name || id,\n }))\n );\n },\n getConfig(id: string) {\n return Promise.resolve(memoryStore.get(id) || null);\n },\n saveConfig(id: string, config: FestivalCardConfig) {\n memoryStore.set(id, config);\n return Promise.resolve();\n },\n deleteConfig(id: string) {\n memoryStore.delete(id);\n return Promise.resolve();\n },\n});\n","import { NextResponse } from 'next/server';\nimport { initializeFestivalCardDb } from '../server/db';\nimport { FestivalCardService } from '../services';\nimport { normalizeFestivalCardConfig } from '../core';\nimport type { FestivalCardConfig, FestivalCardDbAdapter } from '../types';\nimport type { NextRequest } from 'next/server';\n\nexport interface FestivalCardRouteConfig {\n db?: FestivalCardDbAdapter;\n}\n\nconst createService = (config: FestivalCardRouteConfig) => {\n if (config.db) initializeFestivalCardDb(config.db);\n return new FestivalCardService({ db: config.db });\n};\n\nexport const createListFestivalCardsHandler = (config: FestivalCardRouteConfig = {}) => {\n const service = createService(config);\n return async (_request: NextRequest) => {\n try {\n const data = await service.listConfigs();\n return NextResponse.json({ success: true, data });\n } catch (error) {\n return NextResponse.json({ success: false, error: (error as Error).message }, { status: 500 });\n }\n };\n};\n\nexport const createGetFestivalCardHandler = (config: FestivalCardRouteConfig = {}) => {\n const service = createService(config);\n return async (_request: NextRequest, context: { params: { id: string } }) => {\n try {\n const card = await service.getConfig(context.params.id);\n return NextResponse.json({ success: true, data: card });\n } catch (error) {\n return NextResponse.json({ success: false, error: (error as Error).message }, { status: 500 });\n }\n };\n};\n\nexport const createUpsertFestivalCardHandler = (config: FestivalCardRouteConfig = {}) => {\n const service = createService(config);\n return async (request: NextRequest, context: { params: { id: string } }) => {\n try {\n const body: unknown = await request.json();\n const payload =\n body && typeof body === 'object' && 'config' in body\n ? (body as { config?: unknown }).config\n : undefined;\n const normalized = normalizeFestivalCardConfig((payload || {}) as Partial<FestivalCardConfig>);\n const data = await service.saveConfig(context.params.id, normalized);\n return NextResponse.json({ success: true, data });\n } catch (error) {\n return NextResponse.json({ success: false, error: (error as Error).message }, { status: 500 });\n }\n };\n};\n\nexport const createDeleteFestivalCardHandler = (config: FestivalCardRouteConfig = {}) => {\n const service = createService(config);\n return async (_request: NextRequest, context: { params: { id: string } }) => {\n try {\n await service.deleteConfig(context.params.id);\n return NextResponse.json({ success: true });\n } catch (error) {\n return NextResponse.json({ success: false, error: (error as Error).message }, { status: 500 });\n }\n };\n};\n"]}