@ohhwells/bridge 0.1.29-next.20 → 0.1.29-next.21

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.d.cts CHANGED
@@ -83,10 +83,10 @@ declare function ToggleGroupItem({ className, value, children, ...props }: {
83
83
  children: React.ReactNode;
84
84
  } & Omit<React.ComponentProps<typeof Toggle>, 'pressed' | 'onPressedChange'>): react_jsx_runtime.JSX.Element;
85
85
 
86
- declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter }: {
86
+ declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter: insertAfterProp }: {
87
87
  notifyOnConnect?: boolean;
88
88
  initialScheduleId?: string | null;
89
- insertAfter: string;
90
- }): react_jsx_runtime.JSX.Element;
89
+ insertAfter?: string;
90
+ }): react_jsx_runtime.JSX.Element | null;
91
91
 
92
92
  export { LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, Toggle, ToggleGroup, ToggleGroupItem, buildTarget, filterAvailablePages, getEditModeInitialState, isValidUrl, parseTarget, toggleVariants, validateUrlInput };
package/dist/index.d.ts CHANGED
@@ -83,10 +83,10 @@ declare function ToggleGroupItem({ className, value, children, ...props }: {
83
83
  children: React.ReactNode;
84
84
  } & Omit<React.ComponentProps<typeof Toggle>, 'pressed' | 'onPressedChange'>): react_jsx_runtime.JSX.Element;
85
85
 
86
- declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter }: {
86
+ declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter: insertAfterProp }: {
87
87
  notifyOnConnect?: boolean;
88
88
  initialScheduleId?: string | null;
89
- insertAfter: string;
90
- }): react_jsx_runtime.JSX.Element;
89
+ insertAfter?: string;
90
+ }): react_jsx_runtime.JSX.Element | null;
91
91
 
92
92
  export { LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, Toggle, ToggleGroup, ToggleGroupItem, buildTarget, filterAvailablePages, getEditModeInitialState, isValidUrl, parseTarget, toggleVariants, validateUrlInput };
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
8
8
  // src/ui/SchedulingWidget.tsx
9
- import { useEffect, useMemo, useRef, useState as useState2 } from "react";
9
+ import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
10
10
 
11
11
  // src/ui/EmailCaptureModal.tsx
12
12
  import { useState } from "react";
@@ -164,13 +164,6 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
164
164
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
165
165
  var API_URL = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
166
166
  var DAY_ABBR = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
167
- function getApiDomain() {
168
- const h = window.location.hostname;
169
- for (const base of ["ohhwells.site", "theflowops-staging.com", "theflowops.com"]) {
170
- if (h.endsWith(`.${base}`)) return h.slice(0, -(base.length + 1));
171
- }
172
- return h;
173
- }
174
167
  function classRunsOnDate(cls, date, type) {
175
168
  if (type === "FIXED") {
176
169
  const d = String(date.getDate()).padStart(2, "0");
@@ -216,10 +209,10 @@ function buildTimezoneLabel(tz) {
216
209
  return tz;
217
210
  }
218
211
  }
219
- function EmptyState({ inEditor }) {
212
+ function EmptyState({ inEditor, insertAfter }) {
220
213
  const handleAddSchedule = () => {
221
214
  if (inEditor) {
222
- window.parent.postMessage({ type: "ow:scheduling-not-connected" }, "*");
215
+ window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
223
216
  }
224
217
  };
225
218
  return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center gap-6 p-12 bg-[#FAFAF9] border-2 border-dashed border-[#E7E5E4] rounded-[10px] h-[264px] w-full box-border", children: [
@@ -444,18 +437,21 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
444
437
  const booked = getBookingsOnDate(cls, selectedDate);
445
438
  const available = cls.maxParticipants - booked;
446
439
  const isFull = available <= 0;
440
+ const isPrivate = cls.maxParticipants === 1;
447
441
  return /* @__PURE__ */ jsxs2("div", { children: [
448
442
  /* @__PURE__ */ jsxs2("div", { className: "flex gap-4 py-4 sm:items-center sm:gap-[60px] box-border", children: [
449
443
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2 shrink-0 sm:contents", children: [
450
- /* @__PURE__ */ jsx2("div", { className: "sm:w-[120px] sm:shrink-0", children: /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }) }),
451
- /* @__PURE__ */ jsx2(
452
- "span",
453
- {
454
- className: "inline-flex items-center px-2 py-0.5 rounded-full border text-xs font-medium sm:hidden",
455
- style: { borderColor: "#0885FE", color: "#0885FE" },
456
- children: "GROUP"
457
- }
458
- ),
444
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-2 sm:w-[120px] sm:shrink-0", children: [
445
+ /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block", children: formatClassTime(cls) }),
446
+ /* @__PURE__ */ jsx2(
447
+ "span",
448
+ {
449
+ className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium w-fit",
450
+ style: isPrivate ? { background: "#DDFBE3", color: "#199130", border: "1px solid #199130", fontWeight: 500 } : { background: "#EEEDFF", color: "#5953FF", border: "1px solid #5953FF", fontWeight: 500 },
451
+ children: isPrivate ? "PRIVATE" : "GROUP"
452
+ }
453
+ )
454
+ ] }),
459
455
  /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
460
456
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
461
457
  available,
@@ -528,7 +524,9 @@ function CalendarFoldIcon() {
528
524
  }
529
525
  );
530
526
  }
531
- function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter }) {
527
+ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter: insertAfterProp }) {
528
+ const autoId = useId();
529
+ const insertAfter = insertAfterProp ?? autoId;
532
530
  const [schedule, setSchedule] = useState2(null);
533
531
  const [loading, setLoading] = useState2(true);
534
532
  const [inEditor, setInEditor] = useState2(false);
@@ -558,88 +556,99 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
558
556
  if (typeof window === "undefined") return;
559
557
  const isInEditor = window.self !== window.top;
560
558
  setInEditor(isInEditor);
561
- if (isInEditor) {
562
- const startEmpty = initialScheduleId === null;
563
- if (startEmpty) setLoading(false);
564
- let initialized = startEmpty;
565
- const timer = !startEmpty ? setTimeout(() => {
566
- if (!initialized) {
559
+ function loadWithId(effectiveId) {
560
+ if (isInEditor) {
561
+ const startEmpty = effectiveId === null;
562
+ if (startEmpty) setLoading(false);
563
+ let initialized = startEmpty;
564
+ const timer = !startEmpty ? setTimeout(() => {
565
+ if (!initialized) {
566
+ initialized = true;
567
+ setLoading(false);
568
+ }
569
+ }, 5e3) : null;
570
+ const handler = (e) => {
571
+ if (e.data?.type === "ow:clear-scheduling-widget") {
572
+ if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
573
+ setSchedule(null);
574
+ setLoading(false);
575
+ return;
576
+ }
577
+ if (e.data?.type === "ow:switch-schedule") {
578
+ if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
579
+ switchScheduleIdRef.current = e.data.scheduleId ?? null;
580
+ initialized = false;
581
+ setLoading(true);
582
+ window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
583
+ return;
584
+ }
585
+ if (e.data?.type !== "ow:user-schedules-response") return;
586
+ if (e.data.insertAfter && e.data.insertAfter !== insertAfter) return;
587
+ if (initialized && switchScheduleIdRef.current === null) return;
567
588
  initialized = true;
589
+ if (timer) clearTimeout(timer);
590
+ const schedules = e.data.schedules ?? [];
591
+ const isSwitching = switchScheduleIdRef.current !== null;
592
+ const target = isSwitching ? schedules.find((s) => s.id === switchScheduleIdRef.current) ?? schedules[0] ?? null : effectiveId ? schedules.find((s) => s.id === effectiveId) ?? schedules[0] ?? null : schedules[0] ?? null;
593
+ switchScheduleIdRef.current = null;
594
+ setSchedule(target);
568
595
  setLoading(false);
596
+ if (notifyOnConnect && target && !isSwitching) {
597
+ window.parent.postMessage({
598
+ type: "ow:schedule-connected",
599
+ schedule: { id: target.id, name: target.name },
600
+ insertAfter
601
+ }, "*");
602
+ window.postMessage({ type: "ow:schedule-linked", scheduleId: target.id, insertAfter }, "*");
603
+ }
604
+ };
605
+ window.addEventListener("message", handler);
606
+ if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
607
+ return () => {
608
+ window.removeEventListener("message", handler);
609
+ if (timer) clearTimeout(timer);
610
+ };
611
+ }
612
+ if (!effectiveId) {
613
+ setLoading(false);
614
+ return;
615
+ }
616
+ ;
617
+ (async () => {
618
+ try {
619
+ const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
620
+ const data = await res.json();
621
+ setSchedule(data?.id ? data : null);
622
+ } catch {
569
623
  }
570
- }, 5e3) : null;
571
- const handler = (e) => {
572
- if (e.data?.type === "ow:clear-scheduling-widget") {
573
- if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
574
- setSchedule(null);
575
- setLoading(false);
576
- return;
577
- }
578
- if (e.data?.type === "ow:switch-schedule") {
579
- if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
580
- switchScheduleIdRef.current = e.data.scheduleId ?? null;
581
- initialized = false;
582
- setLoading(true);
583
- window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
584
- return;
585
- }
586
- if (e.data?.type !== "ow:user-schedules-response") return;
587
- if (e.data.insertAfter && e.data.insertAfter !== insertAfter) return;
588
- if (initialized && switchScheduleIdRef.current === null) return;
589
- initialized = true;
590
- if (timer) clearTimeout(timer);
591
- const schedules = e.data.schedules ?? [];
592
- const isSwitching = switchScheduleIdRef.current !== null;
593
- const target = isSwitching ? schedules.find((s) => s.id === switchScheduleIdRef.current) ?? schedules[0] ?? null : initialScheduleId ? schedules.find((s) => s.id === initialScheduleId) ?? schedules[0] ?? null : schedules[0] ?? null;
594
- switchScheduleIdRef.current = null;
595
- setSchedule(target);
596
624
  setLoading(false);
597
- if (notifyOnConnect && target && !isSwitching) {
598
- window.parent.postMessage({
599
- type: "ow:schedule-connected",
600
- schedule: { id: target.id, name: target.name },
601
- insertAfter
602
- }, "*");
603
- window.postMessage({ type: "ow:schedule-linked", scheduleId: target.id, insertAfter }, "*");
625
+ })();
626
+ }
627
+ if (initialScheduleId === void 0) {
628
+ let done = false;
629
+ let innerCleanup;
630
+ const timer = setTimeout(() => {
631
+ if (!done) {
632
+ done = true;
633
+ setLoading(false);
604
634
  }
635
+ }, 2e3);
636
+ const configHandler = (e) => {
637
+ if (e.data?.type !== "ow:schedule-config" || e.data.insertAfter !== insertAfter || done) return;
638
+ done = true;
639
+ clearTimeout(timer);
640
+ window.removeEventListener("message", configHandler);
641
+ innerCleanup = loadWithId(e.data.scheduleId ?? null);
605
642
  };
606
- window.addEventListener("message", handler);
607
- if (!startEmpty) window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
643
+ window.addEventListener("message", configHandler);
644
+ window.postMessage({ type: "ow:request-schedule-config", insertAfter }, "*");
608
645
  return () => {
609
- window.removeEventListener("message", handler);
610
- if (timer) clearTimeout(timer);
646
+ window.removeEventListener("message", configHandler);
647
+ clearTimeout(timer);
648
+ innerCleanup?.();
611
649
  };
612
650
  }
613
- if (initialScheduleId === null) {
614
- setLoading(false);
615
- return;
616
- }
617
- ;
618
- (async () => {
619
- try {
620
- if (initialScheduleId) {
621
- const res = await fetch(`${API_URL}/api/schedule/id/${initialScheduleId}`);
622
- const data = await res.json();
623
- setSchedule(data?.id ? data : null);
624
- } else {
625
- const domain = getApiDomain();
626
- const sitemapRes = await fetch(`${API_URL}/api/schedule/sitemap/${domain}`);
627
- const slugs = await sitemapRes.json();
628
- if (!Array.isArray(slugs) || !slugs.length) {
629
- setLoading(false);
630
- return;
631
- }
632
- const { slug } = [...slugs].sort(
633
- (a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
634
- )[0];
635
- const res = await fetch(`${API_URL}/api/schedule/${domain}/${slug}`);
636
- const data = await res.json();
637
- setSchedule(data?.id ? data : null);
638
- }
639
- } catch {
640
- }
641
- setLoading(false);
642
- })();
651
+ return loadWithId(initialScheduleId) ?? void 0;
643
652
  }, []);
644
653
  const timezoneLabel = schedule?.timezone ? (() => {
645
654
  try {
@@ -674,6 +683,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
674
683
  window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
675
684
  }
676
685
  };
686
+ if (!inEditor && !loading && !schedule) return null;
677
687
  const sectionId = `scheduling-${insertAfter}`;
678
688
  return /* @__PURE__ */ jsxs2(
679
689
  "section",
@@ -719,7 +729,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
719
729
  ] }),
720
730
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
721
731
  timezoneLabel && /* @__PURE__ */ jsx2("span", { className: "font-body text-sm font-normal text-(--color-accent,#A89B83)", children: timezoneLabel }),
722
- /* @__PURE__ */ jsx2("div", { className: "w-full p-0 sm:p-10 box-border", children: loading ? /* @__PURE__ */ jsx2(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ jsx2(EmptyState, { inEditor }) : /* @__PURE__ */ jsx2(
732
+ /* @__PURE__ */ jsx2("div", { className: "w-full p-0 sm:p-10 box-border", children: loading ? /* @__PURE__ */ jsx2(LoadingSkeleton, {}) : !schedule ? /* @__PURE__ */ jsx2(EmptyState, { inEditor, insertAfter }) : /* @__PURE__ */ jsx2(
723
733
  ScheduleView,
724
734
  {
725
735
  schedule,
@@ -4592,7 +4602,7 @@ function SectionPickerList({ sections, onSelect }) {
4592
4602
  }
4593
4603
 
4594
4604
  // src/ui/link-modal/UrlOrPageInput.tsx
4595
- import { useId, useRef as useRef2, useState as useState3 } from "react";
4605
+ import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
4596
4606
 
4597
4607
  // src/ui/input.tsx
4598
4608
  import * as React4 from "react";
@@ -4687,7 +4697,7 @@ function UrlOrPageInput({
4687
4697
  readOnly = false,
4688
4698
  urlError
4689
4699
  }) {
4690
- const inputId = useId();
4700
+ const inputId = useId2();
4691
4701
  const inputRef = useRef2(null);
4692
4702
  const [isFocused, setIsFocused] = useState3(false);
4693
4703
  const openDropdown = () => {
@@ -5277,9 +5287,14 @@ function initSectionsFromContent(content, removeExisting = false) {
5277
5287
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
5278
5288
  if (inEditor) getSectionsTracker().textContent = raw;
5279
5289
  const pageEntries = getPageSchedulingEntries(raw);
5280
- mountSchedulingEntries(pageEntries, false);
5281
- requestAnimationFrame(() => retryMissingSchedulingMounts(pageEntries, false));
5282
- setTimeout(() => retryMissingSchedulingMounts(pageEntries, false), 250);
5290
+ const preExisting = pageEntries.filter((e) => !isSchedulingWidgetMissing(e));
5291
+ const notifyForEntry = inEditor ? (e) => !e.scheduleId : false;
5292
+ mountSchedulingEntries(pageEntries, notifyForEntry);
5293
+ requestAnimationFrame(() => retryMissingSchedulingMounts(pageEntries, notifyForEntry));
5294
+ setTimeout(() => retryMissingSchedulingMounts(pageEntries, notifyForEntry), 250);
5295
+ for (const entry of preExisting) {
5296
+ window.postMessage({ type: "ow:schedule-config", insertAfter: entry.insertAfter, scheduleId: entry.scheduleId ?? null }, "*");
5297
+ }
5283
5298
  } catch {
5284
5299
  }
5285
5300
  }
@@ -5338,8 +5353,9 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
5338
5353
  const pending = entries.filter((e) => e.type === "scheduling").sort((a, b) => schedulingMountDepth(a.insertAfter) - schedulingMountDepth(b.insertAfter));
5339
5354
  for (let attempt = 0; attempt < pending.length + 1 && pending.length > 0; attempt++) {
5340
5355
  for (let i = pending.length - 1; i >= 0; i--) {
5341
- const { insertAfter, scheduleId } = pending[i];
5342
- if (mountSchedulingWidget(insertAfter, notifyOnConnect, scheduleId)) {
5356
+ const entry = pending[i];
5357
+ const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
5358
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
5343
5359
  pending.splice(i, 1);
5344
5360
  }
5345
5361
  }
@@ -5817,6 +5833,8 @@ function OhhwellsBridge() {
5817
5833
  });
5818
5834
  const postToParentRef = useRef3(postToParent);
5819
5835
  postToParentRef.current = postToParent;
5836
+ const sectionsLoadedRef = useRef3(false);
5837
+ const pendingScheduleConfigRequests = useRef3([]);
5820
5838
  const [toolbarRect, setToolbarRect] = useState5(null);
5821
5839
  const [toggleState, setToggleState] = useState5(null);
5822
5840
  const [maxBadge, setMaxBadge] = useState5(null);
@@ -5922,6 +5940,29 @@ function OhhwellsBridge() {
5922
5940
  const refreshStateRules = useCallback2(() => {
5923
5941
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
5924
5942
  }, []);
5943
+ const processConfigRequest = useCallback2((insertAfterVal) => {
5944
+ const tracker = getSectionsTracker();
5945
+ let entries = [];
5946
+ try {
5947
+ entries = JSON.parse(tracker.textContent || "[]");
5948
+ } catch {
5949
+ }
5950
+ const path = window.location.pathname;
5951
+ const entry = entries.find(
5952
+ (e) => e.type === "scheduling" && e.insertAfter === insertAfterVal && (!e.pagePath || e.pagePath === path)
5953
+ );
5954
+ if (entry) {
5955
+ window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: entry.scheduleId ?? null }, "*");
5956
+ return;
5957
+ }
5958
+ const newEntry = { type: "scheduling", insertAfter: insertAfterVal, pagePath: path };
5959
+ entries.push(newEntry);
5960
+ tracker.textContent = JSON.stringify(entries);
5961
+ if (isEditMode) {
5962
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
5963
+ }
5964
+ window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
5965
+ }, [isEditMode]);
5925
5966
  const deactivate = useCallback2(() => {
5926
5967
  const el = activeElRef.current;
5927
5968
  if (!el) return;
@@ -5998,6 +6039,8 @@ function OhhwellsBridge() {
5998
6039
  applyLinkByKey(key, val);
5999
6040
  }
6000
6041
  initSectionsFromContent(content, true);
6042
+ sectionsLoadedRef.current = true;
6043
+ pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
6001
6044
  return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
6002
6045
  }) : Promise.resolve();
6003
6046
  };
@@ -6694,6 +6737,8 @@ function OhhwellsBridge() {
6694
6737
  }
6695
6738
  if (sectionsJson) {
6696
6739
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
6740
+ sectionsLoadedRef.current = true;
6741
+ pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
6697
6742
  }
6698
6743
  postToParentRef.current({ type: "ow:hydrate-done" });
6699
6744
  };
@@ -6966,6 +7011,22 @@ function OhhwellsBridge() {
6966
7011
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
6967
7012
  };
6968
7013
  }, [isEditMode, refreshStateRules]);
7014
+ useEffect3(() => {
7015
+ const handler = (e) => {
7016
+ if (e.data?.type !== "ow:request-schedule-config") return;
7017
+ const insertAfterVal = e.data.insertAfter;
7018
+ if (!insertAfterVal) return;
7019
+ if (!sectionsLoadedRef.current) {
7020
+ if (!pendingScheduleConfigRequests.current.includes(insertAfterVal)) {
7021
+ pendingScheduleConfigRequests.current.push(insertAfterVal);
7022
+ }
7023
+ return;
7024
+ }
7025
+ processConfigRequest(insertAfterVal);
7026
+ };
7027
+ window.addEventListener("message", handler);
7028
+ return () => window.removeEventListener("message", handler);
7029
+ }, [processConfigRequest]);
6969
7030
  useEffect3(() => {
6970
7031
  if (!isEditMode) return;
6971
7032
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {