@xiwebdesign/xicms-core 7.23.0 → 7.25.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 (105) hide show
  1. package/dist/admin/AdminApp.js +2 -1
  2. package/dist/admin/AdminApp.js.map +1 -1
  3. package/dist/admin/CoreVersion.d.ts +6 -0
  4. package/dist/admin/CoreVersion.js +42 -1
  5. package/dist/admin/CoreVersion.js.map +1 -1
  6. package/dist/admin/SuperadminPanel.js +19 -3
  7. package/dist/admin/SuperadminPanel.js.map +1 -1
  8. package/dist/admin/dashboard/DashboardPanel.js +46 -9
  9. package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
  10. package/dist/admin/forms/FormsPanel.d.ts +9 -0
  11. package/dist/admin/forms/FormsPanel.js +102 -16
  12. package/dist/admin/forms/FormsPanel.js.map +1 -1
  13. package/dist/admin/forms/gezien.d.ts +3 -0
  14. package/dist/admin/forms/gezien.js +22 -0
  15. package/dist/admin/forms/gezien.js.map +1 -0
  16. package/dist/admin/lib/kleur.d.ts +32 -0
  17. package/dist/admin/lib/kleur.js +60 -0
  18. package/dist/admin/lib/kleur.js.map +1 -0
  19. package/dist/admin/lib/pagesClient.d.ts +32 -0
  20. package/dist/admin/lib/pagesClient.js +60 -1
  21. package/dist/admin/lib/pagesClient.js.map +1 -1
  22. package/dist/admin/lib/seoHulp.d.ts +28 -0
  23. package/dist/admin/lib/seoHulp.js +33 -0
  24. package/dist/admin/lib/seoHulp.js.map +1 -0
  25. package/dist/admin/media/MediaManager.js +133 -51
  26. package/dist/admin/media/MediaManager.js.map +1 -1
  27. package/dist/admin/pages/PageEditor.d.ts +14 -0
  28. package/dist/admin/pages/PageEditor.js +192 -123
  29. package/dist/admin/pages/PageEditor.js.map +1 -1
  30. package/dist/admin/pages/PagesPanel.js +88 -40
  31. package/dist/admin/pages/PagesPanel.js.map +1 -1
  32. package/dist/admin/settings/SettingsPanel.js +100 -19
  33. package/dist/admin/settings/SettingsPanel.js.map +1 -1
  34. package/dist/admin/shop/OrdersTab.js +171 -3
  35. package/dist/admin/shop/OrdersTab.js.map +1 -1
  36. package/dist/admin/shop/ProductsTab.js +1 -1
  37. package/dist/admin/shop/ProductsTab.js.map +1 -1
  38. package/dist/admin/shop/ShopPanel.js +5 -2
  39. package/dist/admin/shop/ShopPanel.js.map +1 -1
  40. package/dist/admin/stats/StatsPanel.js +30 -2
  41. package/dist/admin/stats/StatsPanel.js.map +1 -1
  42. package/dist/admin/stats/lib.d.ts +14 -1
  43. package/dist/admin/stats/lib.js +46 -2
  44. package/dist/admin/stats/lib.js.map +1 -1
  45. package/dist/admin/visual/VisualEditor.js +80 -4
  46. package/dist/admin/visual/VisualEditor.js.map +1 -1
  47. package/dist/admin.css +1 -1
  48. package/dist/blocks/builtins/FormBlockRender.js +8 -2
  49. package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
  50. package/dist/blocks/builtins/lib/submitForm.d.ts +3 -1
  51. package/dist/blocks/builtins/lib/submitForm.js +2 -2
  52. package/dist/blocks/builtins/lib/submitForm.js.map +1 -1
  53. package/dist/components/EditBar.d.ts +3 -1
  54. package/dist/components/EditBar.js +30 -4
  55. package/dist/components/EditBar.js.map +1 -1
  56. package/dist/components/News.js +8 -4
  57. package/dist/components/News.js.map +1 -1
  58. package/dist/components/PageView.d.ts +5 -0
  59. package/dist/components/PageView.js +24 -2
  60. package/dist/components/PageView.js.map +1 -1
  61. package/dist/components/ResponsiveImage.d.ts +1 -1
  62. package/dist/components/ResponsiveImage.js +3 -1
  63. package/dist/components/ResponsiveImage.js.map +1 -1
  64. package/dist/components/site/SiteNav.d.ts +29 -0
  65. package/dist/components/site/SiteNav.js +82 -0
  66. package/dist/components/site/SiteNav.js.map +1 -0
  67. package/dist/content/types.d.ts +8 -0
  68. package/dist/index.d.ts +3 -1
  69. package/dist/index.js +8 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/media/ImageContext.d.ts +1 -6
  72. package/dist/media/ImageContext.js +6 -1
  73. package/dist/media/ImageContext.js.map +1 -1
  74. package/dist/releaseNotes.d.ts +15 -0
  75. package/dist/releaseNotes.js +28 -0
  76. package/dist/releaseNotes.js.map +1 -0
  77. package/dist/schema/mail.d.ts +20 -0
  78. package/dist/schema/mail.js +14 -0
  79. package/dist/schema/mail.js.map +1 -1
  80. package/dist/schema/settings.d.ts +105 -0
  81. package/dist/schema/settings.js +45 -5
  82. package/dist/schema/settings.js.map +1 -1
  83. package/dist/schema/shop.d.ts +2 -0
  84. package/dist/schema/shop.js +12 -2
  85. package/dist/schema/shop.js.map +1 -1
  86. package/dist/schema/siteConfig.d.ts +9 -0
  87. package/dist/server/blockData.js +6 -2
  88. package/dist/server/blockData.js.map +1 -1
  89. package/dist/server/draft.d.ts +11 -0
  90. package/dist/server/draft.js +20 -1
  91. package/dist/server/draft.js.map +1 -1
  92. package/dist/server/index.d.ts +3 -1
  93. package/dist/server/index.js +7 -1
  94. package/dist/server/index.js.map +1 -1
  95. package/dist/server/pages.js +4 -1
  96. package/dist/server/pages.js.map +1 -1
  97. package/dist/server/previewToken.d.ts +34 -0
  98. package/dist/server/previewToken.js +44 -0
  99. package/dist/server/previewToken.js.map +1 -0
  100. package/dist/server/redirects.d.ts +15 -0
  101. package/dist/server/redirects.js +15 -0
  102. package/dist/server/redirects.js.map +1 -0
  103. package/dist/styles.css +110 -0
  104. package/dist/version.js +1 -1
  105. package/package.json +1 -1
@@ -9,7 +9,9 @@ import { useSiteConfig } from "../../config.js";
9
9
  import { useRegistry } from "../../blocks/context.js";
10
10
  import { introspectToFields } from "../lib/zodFields.js";
11
11
  import { BlockErrorBoundary } from "../../blocks/BlockErrorBoundary.js";
12
- import { MediaPickerDialog } from "../media/MediaPicker.js";
12
+ import { MediaPickerDialog, MediaPickerButton } from "../media/MediaPicker.js";
13
+ import { Switch } from "../ui/switch.js";
14
+ import { titelMeter, omschrijvingMeter } from "../lib/seoHulp.js";
13
15
  import { useThemeVars } from "../../XiCMSProvider.js";
14
16
  import { buildBlockAddOptions } from "../../blocks/registry.js";
15
17
  import DOMPurify from "dompurify";
@@ -787,6 +789,10 @@ function VisualEditorInner({ onClose }) {
787
789
  if (e.key.toLowerCase() === "y" || e.shiftKey) redo();
788
790
  else undo();
789
791
  }
792
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "s") {
793
+ e.preventDefault();
794
+ void flushSave().catch(() => setStatus("error"));
795
+ }
790
796
  };
791
797
  window.addEventListener("beforeunload", beforeUnload);
792
798
  document.addEventListener("visibilitychange", onVisibility);
@@ -1093,7 +1099,7 @@ function VisualEditorInner({ onClose }) {
1093
1099
  /* @__PURE__ */ jsx(PageTranslationSettings, { draft, locale, onTranslate: setTranslation })
1094
1100
  ] }) : draft ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4", children: [
1095
1101
  /* @__PURE__ */ jsx("p", { className: "xicms-ve__hint", children: "Klik op een blok om het te bewerken." }),
1096
- /* @__PURE__ */ jsx(PageSettings, { draft, onChange: (part) => mutateDraft((d) => ({ ...d, ...part }), { coalesce: true }) }),
1102
+ /* @__PURE__ */ jsx(PageSettings, { draft, siteId, onChange: (part) => mutateDraft((d) => ({ ...d, ...part }), { coalesce: true }) }),
1097
1103
  !isDemoActive() && /* @__PURE__ */ jsx(
1098
1104
  VersionsPanel,
1099
1105
  {
@@ -1199,6 +1205,22 @@ function VisualEditorInner({ onClose }) {
1199
1205
  children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "13", height: "13", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M19 12l-7 7-7-7" }) })
1200
1206
  }
1201
1207
  ),
1208
+ /* @__PURE__ */ jsx(
1209
+ "button",
1210
+ {
1211
+ type: "button",
1212
+ className: "xicms-ve-blokknop",
1213
+ title: "Blok invoegen na dit blok",
1214
+ "aria-label": `Blok invoegen na ${b.label}`,
1215
+ onMouseDown: (e) => e.preventDefault(),
1216
+ onClick: () => {
1217
+ setSelectedProduct(null);
1218
+ setSelectedKey(b.key);
1219
+ setPanelOpen(true);
1220
+ },
1221
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "13", height: "13", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 5v14M5 12h14" }) })
1222
+ }
1223
+ ),
1202
1224
  /* @__PURE__ */ jsx(
1203
1225
  "button",
1204
1226
  {
@@ -1403,17 +1425,71 @@ function FmtBtn({ label, title, onRun }) {
1403
1425
  }
1404
1426
  );
1405
1427
  }
1428
+ function MeterRegel({ m }) {
1429
+ const kleur = m.toon === "goed" ? "text-emerald-700" : m.toon === "lang" || m.toon === "leeg" ? "text-amber-700" : "text-slate-500";
1430
+ return /* @__PURE__ */ jsx("p", { className: `mt-1 text-xs ${kleur}`, children: m.tekst });
1431
+ }
1406
1432
  function PageSettings({
1407
1433
  draft,
1434
+ siteId,
1408
1435
  onChange
1409
1436
  }) {
1410
1437
  const seo = draft.seo ?? {};
1438
+ const { toast } = useToast();
1439
+ const [previewUrl, setPreviewUrl] = useState(null);
1440
+ const [bezig, setBezig] = useState(false);
1441
+ async function maakPreviewLink() {
1442
+ const { getFirebaseApp } = await import("../../firebase/client.js");
1443
+ const { callable } = await import("../../firebase/functionsClient.js");
1444
+ const app = getFirebaseApp();
1445
+ if (!app) return;
1446
+ setBezig(true);
1447
+ try {
1448
+ const res = await callable(app, "createPreviewLink")({ siteId, path: draft.path });
1449
+ setPreviewUrl(res.data.url);
1450
+ try {
1451
+ await navigator.clipboard?.writeText(res.data.url);
1452
+ toast({ title: "Preview-link gekopieerd", description: "Zeven dagen geldig; wie hem opent ziet de nieuwste stand, ook wat nog niet live is.", tone: "success" });
1453
+ } catch {
1454
+ toast({ title: "Preview-link gemaakt", tone: "success" });
1455
+ }
1456
+ } catch (e) {
1457
+ toast({ title: "Preview-link mislukt", description: e.message, tone: "error" });
1458
+ } finally {
1459
+ setBezig(false);
1460
+ }
1461
+ }
1411
1462
  return /* @__PURE__ */ jsxs("details", { className: "xicms-ve__section", open: true, children: [
1412
1463
  /* @__PURE__ */ jsx("summary", { className: "text-sm font-semibold", children: "Pagina-instellingen" }),
1413
1464
  /* @__PURE__ */ jsxs("div", { className: "mt-2 grid gap-3", children: [
1414
1465
  /* @__PURE__ */ jsx(Field, { label: "Paginatitel", children: /* @__PURE__ */ jsx(Input, { value: draft.title ?? "", onChange: (e) => onChange({ title: e.target.value }) }) }),
1415
- /* @__PURE__ */ jsx(Field, { label: "SEO-titel", hint: "Leeg = paginatitel", children: /* @__PURE__ */ jsx(Input, { value: seo.title ?? "", onChange: (e) => onChange({ seo: { ...seo, title: e.target.value } }) }) }),
1416
- /* @__PURE__ */ jsx(Field, { label: "SEO-omschrijving", hint: "Wordt getoond in zoekresultaten", children: /* @__PURE__ */ jsx(Textarea, { rows: 3, value: seo.description ?? "", onChange: (e) => onChange({ seo: { ...seo, description: e.target.value } }) }) })
1466
+ /* @__PURE__ */ jsxs(Field, { label: "Titel in zoekresultaten", hint: "Leeg = paginatitel", children: [
1467
+ /* @__PURE__ */ jsx(Input, { value: seo.title ?? "", onChange: (e) => onChange({ seo: { ...seo, title: e.target.value } }) }),
1468
+ /* @__PURE__ */ jsx(MeterRegel, { m: titelMeter(seo.title, draft.title) })
1469
+ ] }),
1470
+ /* @__PURE__ */ jsxs(Field, { label: "Omschrijving voor Google", hint: "E\xE9n of twee zinnen die uitnodigen om te klikken", children: [
1471
+ /* @__PURE__ */ jsx(Textarea, { rows: 3, value: seo.description ?? "", onChange: (e) => onChange({ seo: { ...seo, description: e.target.value } }) }),
1472
+ /* @__PURE__ */ jsx(MeterRegel, { m: omschrijvingMeter(seo.description) })
1473
+ ] }),
1474
+ /* @__PURE__ */ jsx(Field, { label: "Afbeelding bij het delen", hint: "Voorbeeld op social media/WhatsApp. Leeg = standaardafbeelding van de site.", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
1475
+ seo.ogImage && // eslint-disable-next-line @next/next/no-img-element
1476
+ /* @__PURE__ */ jsx("img", { src: seo.ogImage, alt: "", className: "h-12 w-20 rounded-md border border-slate-200 object-cover" }),
1477
+ /* @__PURE__ */ jsx(MediaPickerButton, { siteId, label: seo.ogImage ? "Andere kiezen" : "Kies / upload", onSelect: (m) => onChange({ seo: { ...seo, ogImage: m.url } }) }),
1478
+ seo.ogImage && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => onChange({ seo: { ...seo, ogImage: void 0 } }), children: "Weghalen" })
1479
+ ] }) }),
1480
+ /* @__PURE__ */ jsx(
1481
+ Switch,
1482
+ {
1483
+ checked: Boolean(seo.noindex),
1484
+ onCheckedChange: (v) => onChange({ seo: { ...seo, noindex: v || void 0 } }),
1485
+ label: "Niet opnemen in Google"
1486
+ }
1487
+ ),
1488
+ !isDemoActive() && /* @__PURE__ */ jsxs("div", { className: "grid gap-1 border-t border-slate-200 pt-3", children: [
1489
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", disabled: bezig, onClick: () => void maakPreviewLink(), children: bezig ? "Bezig\u2026" : "\u{1F517} Preview-link delen" }),
1490
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500", children: "Laat iemand zonder inlog meekijken naar de werkversie. Zeven dagen geldig, geen toegang tot het beheer." }),
1491
+ previewUrl && /* @__PURE__ */ jsx(Input, { readOnly: true, value: previewUrl, className: "text-xs", onFocus: (e) => e.currentTarget.select() })
1492
+ ] })
1417
1493
  ] })
1418
1494
  ] });
1419
1495
  }