@foxpixel/react 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -40,6 +40,7 @@ __export(index_exports, {
40
40
  ProtectedRoute: () => ProtectedRoute,
41
41
  SITE_CONTENT_QUERY_KEY: () => SITE_CONTENT_QUERY_KEY,
42
42
  getBlogPostSchemaLd: () => getBlogPostSchemaLd,
43
+ prefetchSiteContent: () => prefetchSiteContent,
43
44
  useAdminBlogAnalytics: () => useAdminBlogAnalytics,
44
45
  useAdminBlogCategories: () => useAdminBlogCategories,
45
46
  useAdminBlogComments: () => useAdminBlogComments,
@@ -76,7 +77,7 @@ __export(index_exports, {
76
77
  module.exports = __toCommonJS(index_exports);
77
78
 
78
79
  // src/context/FoxPixelContext.tsx
79
- var import_react = require("react");
80
+ var import_react = __toESM(require("react"));
80
81
 
81
82
  // src/client/http.ts
82
83
  var import_axios = __toESM(require("axios"));
@@ -188,15 +189,21 @@ var FoxPixelHttpClient = class {
188
189
 
189
190
  // src/context/FoxPixelContext.tsx
190
191
  var import_jsx_runtime = require("react/jsx-runtime");
192
+ if (!import_react.default || typeof import_react.default.useMemo !== "function") {
193
+ throw new Error(
194
+ '@foxpixel/react: React is not available. Ensure your app uses a single React instance and the SDK is not bundled with a different React. In Next.js use transpilePackages: ["@foxpixel/react"] and ensure react/react-dom resolve to one module (see next.config.js).'
195
+ );
196
+ }
191
197
  var FoxPixelContext = (0, import_react.createContext)(null);
192
- function FoxPixelProvider({ children, config = {} }) {
198
+ function FoxPixelProvider({ children, config = {}, queryClient }) {
193
199
  const client = (0, import_react.useMemo)(() => {
194
200
  return new FoxPixelHttpClient(config);
195
201
  }, [config.apiUrl, config.apiKey, config.tenantId]);
196
202
  const value = (0, import_react.useMemo)(() => ({
197
203
  client,
198
- config
199
- }), [client, config]);
204
+ config,
205
+ queryClient: queryClient ?? null
206
+ }), [client, config, queryClient]);
200
207
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FoxPixelContext.Provider, { value, children });
201
208
  }
202
209
  function useFoxPixelContext() {
@@ -423,11 +430,10 @@ function withAuth(Component, options = {}) {
423
430
  }
424
431
 
425
432
  // src/components/Editable.tsx
426
- var import_react7 = require("react");
433
+ var import_react8 = require("react");
427
434
 
428
435
  // src/hooks/useEditMode.ts
429
436
  var import_react6 = require("react");
430
- var import_react_query = require("@tanstack/react-query");
431
437
  var SITE_CONTENT_QUERY_KEY = "siteContent";
432
438
  function useEditMode() {
433
439
  const [isEditMode, setIsEditMode] = (0, import_react6.useState)(false);
@@ -439,18 +445,29 @@ function useEditMode() {
439
445
  return isEditMode;
440
446
  }
441
447
  function useEditModeMessaging() {
442
- const queryClient = (0, import_react_query.useQueryClient)();
448
+ const ctx = useFoxPixelContext();
449
+ const queryClient = ctx?.queryClient ?? null;
443
450
  const isEditMode = useEditMode();
444
451
  (0, import_react6.useEffect)(() => {
445
452
  if (!isEditMode || typeof window === "undefined") return;
446
453
  window.parent.postMessage({ type: "FOXPIXEL_READY" }, "*");
447
454
  const handleMessage = (event) => {
455
+ if (!queryClient) return;
448
456
  const { type, payload } = event.data || {};
449
- if (type === "FOXPIXEL_CONTENT_UPDATED" && payload?.contentKey) {
450
- queryClient.invalidateQueries({
451
- queryKey: [SITE_CONTENT_QUERY_KEY, payload.contentKey]
452
- });
457
+ if (type !== "FOXPIXEL_CONTENT_UPDATED" || !payload?.contentKey) return;
458
+ const { contentKey, newValue } = payload;
459
+ if (typeof newValue === "string") {
460
+ queryClient.setQueryData(
461
+ [SITE_CONTENT_QUERY_KEY, contentKey],
462
+ (prev) => ({
463
+ value: newValue,
464
+ contentType: prev?.contentType ?? "TEXT"
465
+ })
466
+ );
453
467
  }
468
+ queryClient.invalidateQueries({
469
+ queryKey: [SITE_CONTENT_QUERY_KEY, contentKey]
470
+ });
454
471
  };
455
472
  window.addEventListener("message", handleMessage);
456
473
  return () => window.removeEventListener("message", handleMessage);
@@ -483,16 +500,40 @@ function useSendEditRequest() {
483
500
  }
484
501
 
485
502
  // src/hooks/useSiteContentQuery.ts
486
- var import_react_query2 = require("@tanstack/react-query");
503
+ var import_react7 = require("react");
504
+ function getCached(queryClient, contentKey) {
505
+ const data = queryClient.getQueryData([
506
+ SITE_CONTENT_QUERY_KEY,
507
+ contentKey
508
+ ]);
509
+ if (data == null) return void 0;
510
+ return { value: data.value ?? "", contentType: data.contentType ?? "TEXT" };
511
+ }
487
512
  function useSiteContentQuery(contentKey, options) {
488
513
  const { defaultValue } = options;
489
- const { client } = useFoxPixelContext();
490
- const { data, isLoading } = (0, import_react_query2.useQuery)({
491
- queryKey: [SITE_CONTENT_QUERY_KEY, contentKey],
492
- queryFn: async () => {
514
+ const { client, queryClient } = useFoxPixelContext();
515
+ const [state, setState] = (0, import_react7.useState)(() => {
516
+ if (queryClient) {
517
+ const cached = getCached(queryClient, contentKey);
518
+ if (cached) {
519
+ return { value: cached.value, isLoading: false, contentType: cached.contentType };
520
+ }
521
+ }
522
+ return { value: defaultValue, isLoading: true, contentType: "TEXT" };
523
+ });
524
+ const contentKeyRef = (0, import_react7.useRef)(contentKey);
525
+ contentKeyRef.current = contentKey;
526
+ (0, import_react7.useEffect)(() => {
527
+ if (!queryClient) {
528
+ setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
529
+ return;
530
+ }
531
+ const key = contentKeyRef.current;
532
+ const queryKey = [SITE_CONTENT_QUERY_KEY, key];
533
+ const queryFn = async () => {
493
534
  try {
494
535
  const content = await client.get(
495
- `/api/site/content/${encodeURIComponent(contentKey)}`
536
+ `/api/site/content/${encodeURIComponent(key)}`
496
537
  );
497
538
  if (!content) return null;
498
539
  return {
@@ -500,23 +541,50 @@ function useSiteContentQuery(contentKey, options) {
500
541
  contentType: content.contentType ?? "TEXT"
501
542
  };
502
543
  } catch (err) {
503
- const status = err?.status;
544
+ const status = err?.response?.status;
504
545
  if (status === 404) return null;
505
546
  throw err;
506
547
  }
507
- },
508
- staleTime: 1e3 * 60 * 5,
509
- retry: 1
510
- });
511
- return {
512
- value: data?.value ?? defaultValue,
513
- isLoading,
514
- contentType: data?.contentType ?? "TEXT"
515
- };
548
+ };
549
+ let cancelled = false;
550
+ queryClient.fetchQuery({
551
+ queryKey,
552
+ queryFn,
553
+ staleTime: 1e3 * 60 * 5,
554
+ retry: 1
555
+ }).then((data) => {
556
+ if (cancelled) return;
557
+ setState({
558
+ value: data?.value ?? defaultValue,
559
+ isLoading: false,
560
+ contentType: data?.contentType ?? "TEXT"
561
+ });
562
+ }).catch(() => {
563
+ if (cancelled) return;
564
+ setState((s) => ({ ...s, value: defaultValue, isLoading: false }));
565
+ });
566
+ const unsub = queryClient.getQueryCache().subscribe((event) => {
567
+ if (event?.type === "updated" && event?.query?.queryKey[1] === key) {
568
+ const cached = getCached(queryClient, key);
569
+ if (cached && !cancelled) {
570
+ setState({
571
+ value: cached.value,
572
+ isLoading: false,
573
+ contentType: cached.contentType
574
+ });
575
+ }
576
+ }
577
+ });
578
+ return () => {
579
+ cancelled = true;
580
+ unsub();
581
+ };
582
+ }, [queryClient, contentKey, defaultValue, client]);
583
+ return state;
516
584
  }
517
585
 
518
586
  // src/utils/sanitize.ts
519
- var import_isomorphic_dompurify = __toESM(require("isomorphic-dompurify"));
587
+ var import_sanitize_html = __toESM(require("sanitize-html"));
520
588
  var DEFAULT_ALLOWED_TAGS = [
521
589
  "p",
522
590
  "br",
@@ -547,13 +615,16 @@ var DEFAULT_ALLOWED_TAGS = [
547
615
  "th",
548
616
  "td"
549
617
  ];
550
- var DEFAULT_ALLOWED_ATTR = ["href", "target", "rel", "src", "alt", "title", "class"];
618
+ var DEFAULT_ALLOWED_ATTR = {
619
+ a: ["href", "target", "rel", "title"],
620
+ img: ["src", "alt", "title", "width", "height"],
621
+ "*": ["class"]
622
+ };
551
623
  function sanitizeHtml(html) {
552
624
  if (typeof html !== "string") return "";
553
- return import_isomorphic_dompurify.default.sanitize(html, {
554
- ALLOWED_TAGS: DEFAULT_ALLOWED_TAGS,
555
- ALLOWED_ATTR: DEFAULT_ALLOWED_ATTR,
556
- ADD_ATTR: ["target"]
625
+ return (0, import_sanitize_html.default)(html, {
626
+ allowedTags: DEFAULT_ALLOWED_TAGS,
627
+ allowedAttributes: DEFAULT_ALLOWED_ATTR
557
628
  });
558
629
  }
559
630
 
@@ -564,6 +635,23 @@ function cn(...args) {
564
635
 
565
636
  // src/components/Editable.tsx
566
637
  var import_jsx_runtime6 = require("react/jsx-runtime");
638
+ var EDIT_MODE_TOOLTIP_STYLE = {
639
+ position: "absolute",
640
+ top: "-28px",
641
+ left: "50%",
642
+ transform: "translateX(-50%)",
643
+ fontSize: "10px",
644
+ fontFamily: "system-ui, sans-serif",
645
+ padding: "4px 8px",
646
+ backgroundColor: "rgb(37 99 235)",
647
+ color: "white",
648
+ borderRadius: "4px",
649
+ whiteSpace: "nowrap",
650
+ pointerEvents: "none",
651
+ zIndex: 100,
652
+ boxShadow: "0 1px 3px rgba(0,0,0,0.2)",
653
+ transition: "opacity 0.15s ease"
654
+ };
567
655
  function Editable({
568
656
  contentKey,
569
657
  defaultValue,
@@ -571,13 +659,14 @@ function Editable({
571
659
  multiline = false,
572
660
  className
573
661
  }) {
662
+ const [isHovered, setIsHovered] = (0, import_react8.useState)(false);
574
663
  const isEditMode = useEditModeMessaging();
575
664
  const sendEditRequest = useSendEditRequest();
576
665
  const { value, isLoading, contentType } = useSiteContentQuery(contentKey, {
577
666
  defaultValue
578
667
  });
579
668
  const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
580
- const handleClick = (0, import_react7.useCallback)(
669
+ const handleClick = (0, import_react8.useCallback)(
581
670
  (e) => {
582
671
  if (isEditMode) {
583
672
  e.preventDefault();
@@ -593,7 +682,7 @@ function Editable({
593
682
  [isEditMode, contentKey, value, contentType, section, sendEditRequest]
594
683
  );
595
684
  if (isLoading) {
596
- return (0, import_react7.createElement)(as, {
685
+ return (0, import_react8.createElement)(as, {
597
686
  className: cn(
598
687
  "animate-pulse bg-muted rounded",
599
688
  multiline ? "h-20" : "h-6",
@@ -604,36 +693,59 @@ function Editable({
604
693
  "aria-label": "Loading content..."
605
694
  });
606
695
  }
607
- const editModeStyles = isEditMode ? cn(
608
- "cursor-pointer transition-all duration-200",
609
- "hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
610
- "hover:bg-blue-50/50 dark:hover:bg-blue-950/30",
611
- "relative group"
612
- ) : "";
696
+ const editModeWrapperStyle = isEditMode ? {
697
+ position: "relative",
698
+ display: "inline",
699
+ cursor: "pointer",
700
+ borderRadius: "2px",
701
+ outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
702
+ outlineOffset: "2px",
703
+ backgroundColor: isHovered ? "rgba(59 130 246 / 0.08)" : void 0
704
+ } : {};
705
+ const tooltipSpan = isEditMode ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
706
+ "span",
707
+ {
708
+ style: {
709
+ ...EDIT_MODE_TOOLTIP_STYLE,
710
+ opacity: isHovered ? 1 : 0
711
+ },
712
+ "aria-hidden": true,
713
+ children: "Click to edit"
714
+ }
715
+ ) : null;
716
+ const hoverHandlers = isEditMode ? {
717
+ onMouseEnter: () => setIsHovered(true),
718
+ onMouseLeave: () => setIsHovered(false)
719
+ } : {};
613
720
  if (multiline && value.includes("\n")) {
614
721
  const safeBr = sanitizeHtml(value.replace(/\n/g, "<br />"));
615
- return (0, import_react7.createElement)(as, {
616
- className: cn(className, editModeStyles),
617
- "data-content-key": contentKey,
618
- "data-editable": isEditMode ? "true" : void 0,
619
- onClick: isEditMode ? handleClick : void 0,
620
- dangerouslySetInnerHTML: { __html: safeBr },
621
- title: isEditMode ? "Click to edit" : void 0
622
- });
722
+ return (0, import_react8.createElement)(
723
+ "span",
724
+ { style: editModeWrapperStyle, ...hoverHandlers },
725
+ (0, import_react8.createElement)(as, {
726
+ className,
727
+ "data-content-key": contentKey,
728
+ "data-editable": isEditMode ? "true" : void 0,
729
+ onClick: isEditMode ? handleClick : void 0,
730
+ dangerouslySetInnerHTML: { __html: safeBr }
731
+ }),
732
+ tooltipSpan
733
+ );
623
734
  }
624
- return (0, import_react7.createElement)(
625
- as,
626
- {
627
- className: cn(className, editModeStyles),
628
- "data-content-key": contentKey,
629
- "data-editable": isEditMode ? "true" : void 0,
630
- onClick: isEditMode ? handleClick : void 0,
631
- title: isEditMode ? "Click to edit" : void 0
632
- },
633
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
634
- value,
635
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute -top-6 left-1/2 -translate-x-1/2 px-2 py-0.5 bg-blue-600 text-white text-[10px] rounded opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-50", children: "Click to edit" })
636
- ] })
735
+ return (0, import_react8.createElement)(
736
+ "span",
737
+ { style: editModeWrapperStyle, ...hoverHandlers },
738
+ (0, import_react8.createElement)(
739
+ as,
740
+ {
741
+ className,
742
+ "data-content-key": contentKey,
743
+ "data-editable": isEditMode ? "true" : void 0,
744
+ onClick: isEditMode ? handleClick : void 0
745
+ },
746
+ value
747
+ ),
748
+ tooltipSpan
637
749
  );
638
750
  }
639
751
  function EditableHTML({
@@ -642,13 +754,14 @@ function EditableHTML({
642
754
  as = "div",
643
755
  className
644
756
  }) {
757
+ const [isHovered, setIsHovered] = (0, import_react8.useState)(false);
645
758
  const isEditMode = useEditModeMessaging();
646
759
  const sendEditRequest = useSendEditRequest();
647
760
  const { value, isLoading } = useSiteContentQuery(contentKey, {
648
761
  defaultValue
649
762
  });
650
763
  const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
651
- const handleClick = (0, import_react7.useCallback)(
764
+ const handleClick = (0, import_react8.useCallback)(
652
765
  (e) => {
653
766
  if (isEditMode) {
654
767
  e.preventDefault();
@@ -659,26 +772,44 @@ function EditableHTML({
659
772
  [isEditMode, contentKey, value, section, sendEditRequest]
660
773
  );
661
774
  if (isLoading) {
662
- return (0, import_react7.createElement)(as, {
775
+ return (0, import_react8.createElement)(as, {
663
776
  className: cn("animate-pulse bg-muted rounded h-32", className),
664
777
  "aria-busy": true
665
778
  });
666
779
  }
667
- const editModeStyles = isEditMode ? cn(
668
- "cursor-pointer transition-all duration-200",
669
- "hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
670
- "hover:bg-blue-50/50 dark:hover:bg-blue-950/30",
671
- "relative group"
672
- ) : "";
780
+ const wrapperStyle = isEditMode ? {
781
+ position: "relative",
782
+ cursor: "pointer",
783
+ borderRadius: "2px",
784
+ outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
785
+ outlineOffset: "2px",
786
+ backgroundColor: isHovered ? "rgba(59 130 246 / 0.08)" : void 0
787
+ } : {};
673
788
  const safeHtml = sanitizeHtml(value);
674
- return (0, import_react7.createElement)(as, {
675
- className: cn("prose prose-slate dark:prose-invert", className, editModeStyles),
676
- "data-content-key": contentKey,
677
- "data-editable": isEditMode ? "true" : void 0,
678
- onClick: isEditMode ? handleClick : void 0,
679
- title: isEditMode ? "Click to edit" : void 0,
680
- dangerouslySetInnerHTML: { __html: safeHtml }
681
- });
789
+ const hoverHandlers = isEditMode ? { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) } : {};
790
+ return (0, import_react8.createElement)(
791
+ "div",
792
+ { style: wrapperStyle, ...hoverHandlers },
793
+ (0, import_react8.createElement)(as, {
794
+ className: cn("prose prose-slate dark:prose-invert", className),
795
+ "data-content-key": contentKey,
796
+ "data-editable": isEditMode ? "true" : void 0,
797
+ onClick: isEditMode ? handleClick : void 0,
798
+ dangerouslySetInnerHTML: { __html: safeHtml }
799
+ }),
800
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
801
+ "span",
802
+ {
803
+ style: {
804
+ ...EDIT_MODE_TOOLTIP_STYLE,
805
+ top: "-24px",
806
+ opacity: isHovered ? 1 : 0
807
+ },
808
+ "aria-hidden": true,
809
+ children: "Click to edit"
810
+ }
811
+ )
812
+ );
682
813
  }
683
814
  function EditableImage({
684
815
  contentKey,
@@ -689,13 +820,14 @@ function EditableImage({
689
820
  height,
690
821
  priority = false
691
822
  }) {
823
+ const [isHovered, setIsHovered] = (0, import_react8.useState)(false);
692
824
  const isEditMode = useEditModeMessaging();
693
825
  const sendEditRequest = useSendEditRequest();
694
826
  const { value: src, isLoading } = useSiteContentQuery(contentKey, {
695
827
  defaultValue
696
828
  });
697
829
  const section = contentKey.includes(".") ? contentKey.split(".")[0] : void 0;
698
- const handleClick = (0, import_react7.useCallback)(
830
+ const handleClick = (0, import_react8.useCallback)(
699
831
  (e) => {
700
832
  if (isEditMode) {
701
833
  e.preventDefault();
@@ -715,39 +847,55 @@ function EditableImage({
715
847
  }
716
848
  );
717
849
  }
718
- const editModeStyles = isEditMode ? cn(
719
- "cursor-pointer transition-all duration-200",
720
- "hover:ring-2 hover:ring-blue-500 hover:ring-offset-2",
721
- "hover:opacity-90",
722
- "relative group"
723
- ) : "";
724
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: cn("relative", isEditMode && "group"), children: [
850
+ const wrapperStyle = isEditMode ? {
851
+ position: "relative",
852
+ display: "inline-block",
853
+ cursor: "pointer",
854
+ borderRadius: "2px",
855
+ outline: isHovered ? "2px solid rgb(59 130 246)" : "none",
856
+ outlineOffset: "2px"
857
+ } : {};
858
+ const hoverHandlers = isEditMode ? { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) } : {};
859
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: wrapperStyle, ...hoverHandlers, children: [
725
860
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
726
861
  "img",
727
862
  {
728
863
  src,
729
864
  alt,
730
- className: cn(className, editModeStyles),
865
+ className,
866
+ style: isEditMode && isHovered ? { opacity: 0.95 } : void 0,
731
867
  width,
732
868
  height,
733
869
  loading: priority ? "eager" : "lazy",
734
870
  "data-content-key": contentKey,
735
871
  "data-editable": isEditMode ? "true" : void 0,
736
- onClick: isEditMode ? handleClick : void 0,
737
- title: isEditMode ? "Click to edit image" : void 0
872
+ onClick: isEditMode ? handleClick : void 0
738
873
  }
739
874
  ),
740
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute top-2 left-2 px-2 py-0.5 bg-blue-600 text-white text-[10px] rounded opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none", children: "Click to edit image" })
875
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
876
+ "span",
877
+ {
878
+ style: {
879
+ ...EDIT_MODE_TOOLTIP_STYLE,
880
+ top: "8px",
881
+ left: "8px",
882
+ transform: "none",
883
+ opacity: isHovered ? 1 : 0
884
+ },
885
+ "aria-hidden": true,
886
+ children: "Click to edit image"
887
+ }
888
+ )
741
889
  ] });
742
890
  }
743
891
 
744
892
  // src/hooks/useServices.ts
745
- var import_react8 = require("react");
893
+ var import_react9 = require("react");
746
894
  function useServices(options = {}) {
747
895
  const { client } = useFoxPixelContext();
748
- const [services, setServices] = (0, import_react8.useState)(null);
749
- const [isLoading, setIsLoading] = (0, import_react8.useState)(true);
750
- const [error, setError] = (0, import_react8.useState)(null);
896
+ const [services, setServices] = (0, import_react9.useState)(null);
897
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(true);
898
+ const [error, setError] = (0, import_react9.useState)(null);
751
899
  const fetchServices = async () => {
752
900
  try {
753
901
  setIsLoading(true);
@@ -765,7 +913,7 @@ function useServices(options = {}) {
765
913
  setIsLoading(false);
766
914
  }
767
915
  };
768
- (0, import_react8.useEffect)(() => {
916
+ (0, import_react9.useEffect)(() => {
769
917
  fetchServices();
770
918
  }, [options.category, options.active]);
771
919
  return {
@@ -777,11 +925,11 @@ function useServices(options = {}) {
777
925
  }
778
926
 
779
927
  // src/hooks/useLeadCapture.ts
780
- var import_react9 = require("react");
928
+ var import_react10 = require("react");
781
929
  function useLeadCapture() {
782
930
  const { client } = useFoxPixelContext();
783
- const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
784
- const [error, setError] = (0, import_react9.useState)(null);
931
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
932
+ const [error, setError] = (0, import_react10.useState)(null);
785
933
  const captureLead = async (data) => {
786
934
  try {
787
935
  setIsLoading(true);
@@ -804,11 +952,11 @@ function useLeadCapture() {
804
952
  }
805
953
 
806
954
  // src/hooks/useContactCapture.ts
807
- var import_react10 = require("react");
955
+ var import_react11 = require("react");
808
956
  function useContactCapture() {
809
957
  const { client } = useFoxPixelContext();
810
- const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
811
- const [error, setError] = (0, import_react10.useState)(null);
958
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
959
+ const [error, setError] = (0, import_react11.useState)(null);
812
960
  const captureContact = async (data) => {
813
961
  try {
814
962
  setIsLoading(true);
@@ -831,16 +979,16 @@ function useContactCapture() {
831
979
  }
832
980
 
833
981
  // src/hooks/useSiteContent.ts
834
- var import_react11 = require("react");
982
+ var import_react12 = require("react");
835
983
  function useSiteContent(contentKey, options = {}) {
836
984
  const { defaultValue = "", fetchOnMount = true } = options;
837
985
  const { client } = useFoxPixelContext();
838
986
  const { user, hasPermission } = useAuth();
839
- const [data, setData] = (0, import_react11.useState)(null);
840
- const [isLoading, setIsLoading] = (0, import_react11.useState)(fetchOnMount);
841
- const [error, setError] = (0, import_react11.useState)(null);
987
+ const [data, setData] = (0, import_react12.useState)(null);
988
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(fetchOnMount);
989
+ const [error, setError] = (0, import_react12.useState)(null);
842
990
  const canEdit = user !== null && hasPermission("site:content:update");
843
- const fetchContent = (0, import_react11.useCallback)(async () => {
991
+ const fetchContent = (0, import_react12.useCallback)(async () => {
844
992
  try {
845
993
  setIsLoading(true);
846
994
  setError(null);
@@ -858,7 +1006,7 @@ function useSiteContent(contentKey, options = {}) {
858
1006
  setIsLoading(false);
859
1007
  }
860
1008
  }, [client, contentKey]);
861
- const updateContent = (0, import_react11.useCallback)(async (newValue) => {
1009
+ const updateContent = (0, import_react12.useCallback)(async (newValue) => {
862
1010
  try {
863
1011
  setError(null);
864
1012
  const updated = await client.put(
@@ -871,7 +1019,7 @@ function useSiteContent(contentKey, options = {}) {
871
1019
  throw err;
872
1020
  }
873
1021
  }, [client, contentKey]);
874
- (0, import_react11.useEffect)(() => {
1022
+ (0, import_react12.useEffect)(() => {
875
1023
  if (fetchOnMount) {
876
1024
  fetchContent();
877
1025
  }
@@ -890,10 +1038,10 @@ function useSiteContent(contentKey, options = {}) {
890
1038
  function useSiteContents(contentKeys, options = {}) {
891
1039
  const { defaults = {} } = options;
892
1040
  const { client } = useFoxPixelContext();
893
- const [data, setData] = (0, import_react11.useState)({});
894
- const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
895
- const [error, setError] = (0, import_react11.useState)(null);
896
- const fetchContents = (0, import_react11.useCallback)(async () => {
1041
+ const [data, setData] = (0, import_react12.useState)({});
1042
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
1043
+ const [error, setError] = (0, import_react12.useState)(null);
1044
+ const fetchContents = (0, import_react12.useCallback)(async () => {
897
1045
  if (contentKeys.length === 0) {
898
1046
  setData({});
899
1047
  setIsLoading(false);
@@ -913,10 +1061,10 @@ function useSiteContents(contentKeys, options = {}) {
913
1061
  setIsLoading(false);
914
1062
  }
915
1063
  }, [client, contentKeys.join(",")]);
916
- (0, import_react11.useEffect)(() => {
1064
+ (0, import_react12.useEffect)(() => {
917
1065
  fetchContents();
918
1066
  }, [fetchContents]);
919
- const getValue = (0, import_react11.useCallback)((key, defaultValue) => {
1067
+ const getValue = (0, import_react12.useCallback)((key, defaultValue) => {
920
1068
  const content = data[key];
921
1069
  if (content?.value) {
922
1070
  return content.value;
@@ -933,10 +1081,10 @@ function useSiteContents(contentKeys, options = {}) {
933
1081
  }
934
1082
  function useSiteContentSection(section) {
935
1083
  const { client } = useFoxPixelContext();
936
- const [contents, setContents] = (0, import_react11.useState)([]);
937
- const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
938
- const [error, setError] = (0, import_react11.useState)(null);
939
- const fetchContents = (0, import_react11.useCallback)(async () => {
1084
+ const [contents, setContents] = (0, import_react12.useState)([]);
1085
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
1086
+ const [error, setError] = (0, import_react12.useState)(null);
1087
+ const fetchContents = (0, import_react12.useCallback)(async () => {
940
1088
  try {
941
1089
  setIsLoading(true);
942
1090
  setError(null);
@@ -950,7 +1098,7 @@ function useSiteContentSection(section) {
950
1098
  setIsLoading(false);
951
1099
  }
952
1100
  }, [client, section]);
953
- (0, import_react11.useEffect)(() => {
1101
+ (0, import_react12.useEffect)(() => {
954
1102
  fetchContents();
955
1103
  }, [fetchContents]);
956
1104
  return {
@@ -961,13 +1109,43 @@ function useSiteContentSection(section) {
961
1109
  };
962
1110
  }
963
1111
 
1112
+ // src/prefetchSiteContent.ts
1113
+ async function prefetchSiteContent(queryClient, options) {
1114
+ const { apiUrl, apiKey, tenantId, contentKeys } = options;
1115
+ const client = new FoxPixelHttpClient({ apiUrl, apiKey, tenantId });
1116
+ await Promise.all(
1117
+ contentKeys.map(async (contentKey) => {
1118
+ try {
1119
+ const content = await client.get(
1120
+ `/api/site/content/${encodeURIComponent(contentKey)}`
1121
+ );
1122
+ queryClient.setQueryData(
1123
+ [SITE_CONTENT_QUERY_KEY, contentKey],
1124
+ {
1125
+ value: content?.value ?? "",
1126
+ contentType: content?.contentType ?? "TEXT"
1127
+ }
1128
+ );
1129
+ } catch (err) {
1130
+ const status = err?.response?.status;
1131
+ if (status === 404) {
1132
+ queryClient.setQueryData([SITE_CONTENT_QUERY_KEY, contentKey], {
1133
+ value: "",
1134
+ contentType: "TEXT"
1135
+ });
1136
+ }
1137
+ }
1138
+ })
1139
+ );
1140
+ }
1141
+
964
1142
  // src/blog/hooks.ts
965
- var import_react12 = require("react");
1143
+ var import_react13 = require("react");
966
1144
  function useBlogPosts(options = {}) {
967
1145
  const { client } = useFoxPixelContext();
968
- const [data, setData] = (0, import_react12.useState)(null);
969
- const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
970
- const [error, setError] = (0, import_react12.useState)(null);
1146
+ const [data, setData] = (0, import_react13.useState)(null);
1147
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1148
+ const [error, setError] = (0, import_react13.useState)(null);
971
1149
  const page = options.page ?? 0;
972
1150
  const limit = options.limit ?? 10;
973
1151
  const fetchPosts = async () => {
@@ -987,7 +1165,7 @@ function useBlogPosts(options = {}) {
987
1165
  setIsLoading(false);
988
1166
  }
989
1167
  };
990
- (0, import_react12.useEffect)(() => {
1168
+ (0, import_react13.useEffect)(() => {
991
1169
  fetchPosts();
992
1170
  }, [page, limit]);
993
1171
  return {
@@ -999,9 +1177,9 @@ function useBlogPosts(options = {}) {
999
1177
  }
1000
1178
  function useBlogPost(slug) {
1001
1179
  const { client } = useFoxPixelContext();
1002
- const [data, setData] = (0, import_react12.useState)(null);
1003
- const [isLoading, setIsLoading] = (0, import_react12.useState)(!!slug);
1004
- const [error, setError] = (0, import_react12.useState)(null);
1180
+ const [data, setData] = (0, import_react13.useState)(null);
1181
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(!!slug);
1182
+ const [error, setError] = (0, import_react13.useState)(null);
1005
1183
  const fetchPost = async () => {
1006
1184
  if (!slug) {
1007
1185
  setData(null);
@@ -1020,7 +1198,7 @@ function useBlogPost(slug) {
1020
1198
  setIsLoading(false);
1021
1199
  }
1022
1200
  };
1023
- (0, import_react12.useEffect)(() => {
1201
+ (0, import_react13.useEffect)(() => {
1024
1202
  fetchPost();
1025
1203
  }, [slug]);
1026
1204
  return {
@@ -1032,9 +1210,9 @@ function useBlogPost(slug) {
1032
1210
  }
1033
1211
  function useBlogCategories() {
1034
1212
  const { client } = useFoxPixelContext();
1035
- const [data, setData] = (0, import_react12.useState)(null);
1036
- const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
1037
- const [error, setError] = (0, import_react12.useState)(null);
1213
+ const [data, setData] = (0, import_react13.useState)(null);
1214
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1215
+ const [error, setError] = (0, import_react13.useState)(null);
1038
1216
  const fetchCategories = async () => {
1039
1217
  try {
1040
1218
  setIsLoading(true);
@@ -1048,7 +1226,7 @@ function useBlogCategories() {
1048
1226
  setIsLoading(false);
1049
1227
  }
1050
1228
  };
1051
- (0, import_react12.useEffect)(() => {
1229
+ (0, import_react13.useEffect)(() => {
1052
1230
  fetchCategories();
1053
1231
  }, []);
1054
1232
  return {
@@ -1060,9 +1238,9 @@ function useBlogCategories() {
1060
1238
  }
1061
1239
  function useBlogTags() {
1062
1240
  const { client } = useFoxPixelContext();
1063
- const [data, setData] = (0, import_react12.useState)(null);
1064
- const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
1065
- const [error, setError] = (0, import_react12.useState)(null);
1241
+ const [data, setData] = (0, import_react13.useState)(null);
1242
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1243
+ const [error, setError] = (0, import_react13.useState)(null);
1066
1244
  const fetchTags = async () => {
1067
1245
  try {
1068
1246
  setIsLoading(true);
@@ -1076,7 +1254,7 @@ function useBlogTags() {
1076
1254
  setIsLoading(false);
1077
1255
  }
1078
1256
  };
1079
- (0, import_react12.useEffect)(() => {
1257
+ (0, import_react13.useEffect)(() => {
1080
1258
  fetchTags();
1081
1259
  }, []);
1082
1260
  return {
@@ -1088,9 +1266,9 @@ function useBlogTags() {
1088
1266
  }
1089
1267
  function useBlogComments(slug) {
1090
1268
  const { client } = useFoxPixelContext();
1091
- const [data, setData] = (0, import_react12.useState)(null);
1092
- const [isLoading, setIsLoading] = (0, import_react12.useState)(!!slug);
1093
- const [error, setError] = (0, import_react12.useState)(null);
1269
+ const [data, setData] = (0, import_react13.useState)(null);
1270
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(!!slug);
1271
+ const [error, setError] = (0, import_react13.useState)(null);
1094
1272
  const fetchComments = async () => {
1095
1273
  if (!slug) {
1096
1274
  setData(null);
@@ -1111,7 +1289,7 @@ function useBlogComments(slug) {
1111
1289
  setIsLoading(false);
1112
1290
  }
1113
1291
  };
1114
- (0, import_react12.useEffect)(() => {
1292
+ (0, import_react13.useEffect)(() => {
1115
1293
  fetchComments();
1116
1294
  }, [slug]);
1117
1295
  return {
@@ -1123,8 +1301,8 @@ function useBlogComments(slug) {
1123
1301
  }
1124
1302
  function useBlogCommentSubmit(slug) {
1125
1303
  const { client } = useFoxPixelContext();
1126
- const [isSubmitting, setIsSubmitting] = (0, import_react12.useState)(false);
1127
- const [error, setError] = (0, import_react12.useState)(null);
1304
+ const [isSubmitting, setIsSubmitting] = (0, import_react13.useState)(false);
1305
+ const [error, setError] = (0, import_react13.useState)(null);
1128
1306
  const submit = async (payload) => {
1129
1307
  if (!slug) return null;
1130
1308
  try {
@@ -1152,9 +1330,9 @@ function useBlogCommentSubmit(slug) {
1152
1330
  }
1153
1331
  function useBlogFeaturedPosts(limit = 6) {
1154
1332
  const { client } = useFoxPixelContext();
1155
- const [data, setData] = (0, import_react12.useState)(null);
1156
- const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
1157
- const [error, setError] = (0, import_react12.useState)(null);
1333
+ const [data, setData] = (0, import_react13.useState)(null);
1334
+ const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1335
+ const [error, setError] = (0, import_react13.useState)(null);
1158
1336
  const fetchFeatured = async () => {
1159
1337
  try {
1160
1338
  setIsLoading(true);
@@ -1172,7 +1350,7 @@ function useBlogFeaturedPosts(limit = 6) {
1172
1350
  setIsLoading(false);
1173
1351
  }
1174
1352
  };
1175
- (0, import_react12.useEffect)(() => {
1353
+ (0, import_react13.useEffect)(() => {
1176
1354
  fetchFeatured();
1177
1355
  }, [limit]);
1178
1356
  return {
@@ -1184,9 +1362,9 @@ function useBlogFeaturedPosts(limit = 6) {
1184
1362
  }
1185
1363
  function useNewsletterSubscribe() {
1186
1364
  const { client } = useFoxPixelContext();
1187
- const [isSubmitting, setIsSubmitting] = (0, import_react12.useState)(false);
1188
- const [error, setError] = (0, import_react12.useState)(null);
1189
- const [success, setSuccess] = (0, import_react12.useState)(false);
1365
+ const [isSubmitting, setIsSubmitting] = (0, import_react13.useState)(false);
1366
+ const [error, setError] = (0, import_react13.useState)(null);
1367
+ const [success, setSuccess] = (0, import_react13.useState)(false);
1190
1368
  const subscribe = async (payload) => {
1191
1369
  try {
1192
1370
  setIsSubmitting(true);
@@ -1219,9 +1397,9 @@ function useNewsletterSubscribe() {
1219
1397
  }
1220
1398
  function useNewsletterUnsubscribe() {
1221
1399
  const { client } = useFoxPixelContext();
1222
- const [isSubmitting, setIsSubmitting] = (0, import_react12.useState)(false);
1223
- const [error, setError] = (0, import_react12.useState)(null);
1224
- const [success, setSuccess] = (0, import_react12.useState)(false);
1400
+ const [isSubmitting, setIsSubmitting] = (0, import_react13.useState)(false);
1401
+ const [error, setError] = (0, import_react13.useState)(null);
1402
+ const [success, setSuccess] = (0, import_react13.useState)(false);
1225
1403
  const unsubscribe = async (email) => {
1226
1404
  try {
1227
1405
  setIsSubmitting(true);
@@ -1266,15 +1444,15 @@ function useNewsletterUnsubscribe() {
1266
1444
  }
1267
1445
 
1268
1446
  // src/blog/admin-hooks.ts
1269
- var import_react13 = require("react");
1447
+ var import_react14 = require("react");
1270
1448
  function useAdminBlogPosts(options = {}) {
1271
1449
  const { client } = useFoxPixelContext();
1272
- const [data, setData] = (0, import_react13.useState)(null);
1273
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1274
- const [error, setError] = (0, import_react13.useState)(null);
1450
+ const [data, setData] = (0, import_react14.useState)(null);
1451
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1452
+ const [error, setError] = (0, import_react14.useState)(null);
1275
1453
  const page = options.page ?? 0;
1276
1454
  const size = options.size ?? 20;
1277
- const fetchPosts = (0, import_react13.useCallback)(async () => {
1455
+ const fetchPosts = (0, import_react14.useCallback)(async () => {
1278
1456
  try {
1279
1457
  setIsLoading(true);
1280
1458
  setError(null);
@@ -1289,17 +1467,17 @@ function useAdminBlogPosts(options = {}) {
1289
1467
  setIsLoading(false);
1290
1468
  }
1291
1469
  }, [client, page, size]);
1292
- (0, import_react13.useEffect)(() => {
1470
+ (0, import_react14.useEffect)(() => {
1293
1471
  fetchPosts();
1294
1472
  }, [fetchPosts]);
1295
1473
  return { data, isLoading, error, refetch: fetchPosts };
1296
1474
  }
1297
1475
  function useAdminBlogPost(id) {
1298
1476
  const { client } = useFoxPixelContext();
1299
- const [data, setData] = (0, import_react13.useState)(null);
1300
- const [isLoading, setIsLoading] = (0, import_react13.useState)(!!id);
1301
- const [error, setError] = (0, import_react13.useState)(null);
1302
- const fetchPost = (0, import_react13.useCallback)(async () => {
1477
+ const [data, setData] = (0, import_react14.useState)(null);
1478
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(!!id);
1479
+ const [error, setError] = (0, import_react14.useState)(null);
1480
+ const fetchPost = (0, import_react14.useCallback)(async () => {
1303
1481
  if (!id) {
1304
1482
  setData(null);
1305
1483
  setIsLoading(false);
@@ -1316,15 +1494,15 @@ function useAdminBlogPost(id) {
1316
1494
  setIsLoading(false);
1317
1495
  }
1318
1496
  }, [client, id]);
1319
- (0, import_react13.useEffect)(() => {
1497
+ (0, import_react14.useEffect)(() => {
1320
1498
  fetchPost();
1321
1499
  }, [fetchPost]);
1322
1500
  return { data, isLoading, error, refetch: fetchPost };
1323
1501
  }
1324
1502
  function useAdminBlogPostMutations() {
1325
1503
  const { client } = useFoxPixelContext();
1326
- const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
1327
- const [error, setError] = (0, import_react13.useState)(null);
1504
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
1505
+ const [error, setError] = (0, import_react14.useState)(null);
1328
1506
  const create = async (payload) => {
1329
1507
  try {
1330
1508
  setIsLoading(true);
@@ -1368,10 +1546,10 @@ function useAdminBlogPostMutations() {
1368
1546
  }
1369
1547
  function useAdminBlogCategories() {
1370
1548
  const { client } = useFoxPixelContext();
1371
- const [data, setData] = (0, import_react13.useState)(null);
1372
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1373
- const [error, setError] = (0, import_react13.useState)(null);
1374
- const fetchCategories = (0, import_react13.useCallback)(async () => {
1549
+ const [data, setData] = (0, import_react14.useState)(null);
1550
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1551
+ const [error, setError] = (0, import_react14.useState)(null);
1552
+ const fetchCategories = (0, import_react14.useCallback)(async () => {
1375
1553
  try {
1376
1554
  setIsLoading(true);
1377
1555
  setError(null);
@@ -1383,7 +1561,7 @@ function useAdminBlogCategories() {
1383
1561
  setIsLoading(false);
1384
1562
  }
1385
1563
  }, [client]);
1386
- (0, import_react13.useEffect)(() => {
1564
+ (0, import_react14.useEffect)(() => {
1387
1565
  fetchCategories();
1388
1566
  }, [fetchCategories]);
1389
1567
  const create = async (payload) => {
@@ -1420,10 +1598,10 @@ function useAdminBlogCategories() {
1420
1598
  }
1421
1599
  function useAdminBlogTags() {
1422
1600
  const { client } = useFoxPixelContext();
1423
- const [data, setData] = (0, import_react13.useState)(null);
1424
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1425
- const [error, setError] = (0, import_react13.useState)(null);
1426
- const fetchTags = (0, import_react13.useCallback)(async () => {
1601
+ const [data, setData] = (0, import_react14.useState)(null);
1602
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1603
+ const [error, setError] = (0, import_react14.useState)(null);
1604
+ const fetchTags = (0, import_react14.useCallback)(async () => {
1427
1605
  try {
1428
1606
  setIsLoading(true);
1429
1607
  setError(null);
@@ -1435,7 +1613,7 @@ function useAdminBlogTags() {
1435
1613
  setIsLoading(false);
1436
1614
  }
1437
1615
  }, [client]);
1438
- (0, import_react13.useEffect)(() => {
1616
+ (0, import_react14.useEffect)(() => {
1439
1617
  fetchTags();
1440
1618
  }, [fetchTags]);
1441
1619
  const create = async (payload) => {
@@ -1472,11 +1650,11 @@ function useAdminBlogTags() {
1472
1650
  }
1473
1651
  function useAdminBlogComments(options = {}) {
1474
1652
  const { client } = useFoxPixelContext();
1475
- const [data, setData] = (0, import_react13.useState)(null);
1476
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1477
- const [error, setError] = (0, import_react13.useState)(null);
1653
+ const [data, setData] = (0, import_react14.useState)(null);
1654
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1655
+ const [error, setError] = (0, import_react14.useState)(null);
1478
1656
  const { status, postId, page = 0, size = 20 } = options;
1479
- const fetchComments = (0, import_react13.useCallback)(async () => {
1657
+ const fetchComments = (0, import_react14.useCallback)(async () => {
1480
1658
  try {
1481
1659
  setIsLoading(true);
1482
1660
  setError(null);
@@ -1493,7 +1671,7 @@ function useAdminBlogComments(options = {}) {
1493
1671
  setIsLoading(false);
1494
1672
  }
1495
1673
  }, [client, status, postId, page, size]);
1496
- (0, import_react13.useEffect)(() => {
1674
+ (0, import_react14.useEffect)(() => {
1497
1675
  fetchComments();
1498
1676
  }, [fetchComments]);
1499
1677
  const updateStatus = async (id, newStatus) => {
@@ -1520,11 +1698,11 @@ function useAdminBlogComments(options = {}) {
1520
1698
  }
1521
1699
  function useAdminNewsletterSubscribers(options = {}) {
1522
1700
  const { client } = useFoxPixelContext();
1523
- const [data, setData] = (0, import_react13.useState)(null);
1524
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1525
- const [error, setError] = (0, import_react13.useState)(null);
1701
+ const [data, setData] = (0, import_react14.useState)(null);
1702
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1703
+ const [error, setError] = (0, import_react14.useState)(null);
1526
1704
  const { status, page = 0, size = 20 } = options;
1527
- const fetchSubscribers = (0, import_react13.useCallback)(async () => {
1705
+ const fetchSubscribers = (0, import_react14.useCallback)(async () => {
1528
1706
  try {
1529
1707
  setIsLoading(true);
1530
1708
  setError(null);
@@ -1540,7 +1718,7 @@ function useAdminNewsletterSubscribers(options = {}) {
1540
1718
  setIsLoading(false);
1541
1719
  }
1542
1720
  }, [client, status, page, size]);
1543
- (0, import_react13.useEffect)(() => {
1721
+ (0, import_react14.useEffect)(() => {
1544
1722
  fetchSubscribers();
1545
1723
  }, [fetchSubscribers]);
1546
1724
  const remove = async (id) => {
@@ -1557,10 +1735,10 @@ function useAdminNewsletterSubscribers(options = {}) {
1557
1735
  }
1558
1736
  function useAdminNewsletterStats() {
1559
1737
  const { client } = useFoxPixelContext();
1560
- const [data, setData] = (0, import_react13.useState)(null);
1561
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1562
- const [error, setError] = (0, import_react13.useState)(null);
1563
- const fetchStats = (0, import_react13.useCallback)(async () => {
1738
+ const [data, setData] = (0, import_react14.useState)(null);
1739
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1740
+ const [error, setError] = (0, import_react14.useState)(null);
1741
+ const fetchStats = (0, import_react14.useCallback)(async () => {
1564
1742
  try {
1565
1743
  setIsLoading(true);
1566
1744
  setError(null);
@@ -1572,17 +1750,17 @@ function useAdminNewsletterStats() {
1572
1750
  setIsLoading(false);
1573
1751
  }
1574
1752
  }, [client]);
1575
- (0, import_react13.useEffect)(() => {
1753
+ (0, import_react14.useEffect)(() => {
1576
1754
  fetchStats();
1577
1755
  }, [fetchStats]);
1578
1756
  return { data, isLoading, error, refetch: fetchStats };
1579
1757
  }
1580
1758
  function useAdminBlogSettings() {
1581
1759
  const { client } = useFoxPixelContext();
1582
- const [data, setData] = (0, import_react13.useState)(null);
1583
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1584
- const [error, setError] = (0, import_react13.useState)(null);
1585
- const fetchSettings = (0, import_react13.useCallback)(async () => {
1760
+ const [data, setData] = (0, import_react14.useState)(null);
1761
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1762
+ const [error, setError] = (0, import_react14.useState)(null);
1763
+ const fetchSettings = (0, import_react14.useCallback)(async () => {
1586
1764
  try {
1587
1765
  setIsLoading(true);
1588
1766
  setError(null);
@@ -1594,7 +1772,7 @@ function useAdminBlogSettings() {
1594
1772
  setIsLoading(false);
1595
1773
  }
1596
1774
  }, [client]);
1597
- (0, import_react13.useEffect)(() => {
1775
+ (0, import_react14.useEffect)(() => {
1598
1776
  fetchSettings();
1599
1777
  }, [fetchSettings]);
1600
1778
  const update = async (settings) => {
@@ -1611,10 +1789,10 @@ function useAdminBlogSettings() {
1611
1789
  }
1612
1790
  function useAdminBlogAnalytics() {
1613
1791
  const { client } = useFoxPixelContext();
1614
- const [data, setData] = (0, import_react13.useState)(null);
1615
- const [isLoading, setIsLoading] = (0, import_react13.useState)(true);
1616
- const [error, setError] = (0, import_react13.useState)(null);
1617
- const fetchAnalytics = (0, import_react13.useCallback)(async () => {
1792
+ const [data, setData] = (0, import_react14.useState)(null);
1793
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
1794
+ const [error, setError] = (0, import_react14.useState)(null);
1795
+ const fetchAnalytics = (0, import_react14.useCallback)(async () => {
1618
1796
  try {
1619
1797
  setIsLoading(true);
1620
1798
  setError(null);
@@ -1626,7 +1804,7 @@ function useAdminBlogAnalytics() {
1626
1804
  setIsLoading(false);
1627
1805
  }
1628
1806
  }, [client]);
1629
- (0, import_react13.useEffect)(() => {
1807
+ (0, import_react14.useEffect)(() => {
1630
1808
  fetchAnalytics();
1631
1809
  }, [fetchAnalytics]);
1632
1810
  return { data, isLoading, error, refetch: fetchAnalytics };
@@ -1675,6 +1853,7 @@ function getBlogPostSchemaLd(post, options) {
1675
1853
  ProtectedRoute,
1676
1854
  SITE_CONTENT_QUERY_KEY,
1677
1855
  getBlogPostSchemaLd,
1856
+ prefetchSiteContent,
1678
1857
  useAdminBlogAnalytics,
1679
1858
  useAdminBlogCategories,
1680
1859
  useAdminBlogComments,