@ohhwells/bridge 0.1.23 → 0.1.24
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/README.md +58 -0
- package/dist/index.cjs +136 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +137 -82
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -23,10 +23,10 @@ declare function ToggleGroupItem({ className, value, children, ...props }: {
|
|
|
23
23
|
children: React.ReactNode;
|
|
24
24
|
} & Omit<React.ComponentProps<typeof Toggle>, 'pressed' | 'onPressedChange'>): react_jsx_runtime.JSX.Element;
|
|
25
25
|
|
|
26
|
-
declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter }: {
|
|
26
|
+
declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter: insertAfterProp }: {
|
|
27
27
|
notifyOnConnect?: boolean;
|
|
28
28
|
initialScheduleId?: string | null;
|
|
29
|
-
insertAfter
|
|
29
|
+
insertAfter?: string;
|
|
30
30
|
}): react_jsx_runtime.JSX.Element | null;
|
|
31
31
|
|
|
32
32
|
export { OhhwellsBridge, SchedulingWidget, Toggle, ToggleGroup, ToggleGroupItem, toggleVariants };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,10 +23,10 @@ declare function ToggleGroupItem({ className, value, children, ...props }: {
|
|
|
23
23
|
children: React.ReactNode;
|
|
24
24
|
} & Omit<React.ComponentProps<typeof Toggle>, 'pressed' | 'onPressedChange'>): react_jsx_runtime.JSX.Element;
|
|
25
25
|
|
|
26
|
-
declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter }: {
|
|
26
|
+
declare function SchedulingWidget({ notifyOnConnect, initialScheduleId, insertAfter: insertAfterProp }: {
|
|
27
27
|
notifyOnConnect?: boolean;
|
|
28
28
|
initialScheduleId?: string | null;
|
|
29
|
-
insertAfter
|
|
29
|
+
insertAfter?: string;
|
|
30
30
|
}): react_jsx_runtime.JSX.Element | null;
|
|
31
31
|
|
|
32
32
|
export { OhhwellsBridge, SchedulingWidget, Toggle, ToggleGroup, ToggleGroupItem, toggleVariants };
|
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");
|
|
@@ -531,7 +524,9 @@ function CalendarFoldIcon() {
|
|
|
531
524
|
}
|
|
532
525
|
);
|
|
533
526
|
}
|
|
534
|
-
function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter }) {
|
|
527
|
+
function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAfter: insertAfterProp }) {
|
|
528
|
+
const autoId = useId();
|
|
529
|
+
const insertAfter = insertAfterProp ?? autoId;
|
|
535
530
|
const [schedule, setSchedule] = useState2(null);
|
|
536
531
|
const [loading, setLoading] = useState2(true);
|
|
537
532
|
const [inEditor, setInEditor] = useState2(false);
|
|
@@ -561,88 +556,99 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
561
556
|
if (typeof window === "undefined") return;
|
|
562
557
|
const isInEditor = window.self !== window.top;
|
|
563
558
|
setInEditor(isInEditor);
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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;
|
|
570
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);
|
|
571
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 {
|
|
572
623
|
}
|
|
573
|
-
}, 5e3) : null;
|
|
574
|
-
const handler = (e) => {
|
|
575
|
-
if (e.data?.type === "ow:clear-scheduling-widget") {
|
|
576
|
-
if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
|
|
577
|
-
setSchedule(null);
|
|
578
|
-
setLoading(false);
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
if (e.data?.type === "ow:switch-schedule") {
|
|
582
|
-
if (!e.data.insertAfter || e.data.insertAfter !== insertAfter) return;
|
|
583
|
-
switchScheduleIdRef.current = e.data.scheduleId ?? null;
|
|
584
|
-
initialized = false;
|
|
585
|
-
setLoading(true);
|
|
586
|
-
window.parent.postMessage({ type: "ow:request-user-schedules", insertAfter }, "*");
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
if (e.data?.type !== "ow:user-schedules-response") return;
|
|
590
|
-
if (e.data.insertAfter && e.data.insertAfter !== insertAfter) return;
|
|
591
|
-
if (initialized && switchScheduleIdRef.current === null) return;
|
|
592
|
-
initialized = true;
|
|
593
|
-
if (timer) clearTimeout(timer);
|
|
594
|
-
const schedules = e.data.schedules ?? [];
|
|
595
|
-
const isSwitching = switchScheduleIdRef.current !== null;
|
|
596
|
-
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;
|
|
597
|
-
switchScheduleIdRef.current = null;
|
|
598
|
-
setSchedule(target);
|
|
599
624
|
setLoading(false);
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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);
|
|
607
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);
|
|
608
642
|
};
|
|
609
|
-
window.addEventListener("message",
|
|
610
|
-
|
|
643
|
+
window.addEventListener("message", configHandler);
|
|
644
|
+
window.postMessage({ type: "ow:request-schedule-config", insertAfter }, "*");
|
|
611
645
|
return () => {
|
|
612
|
-
window.removeEventListener("message",
|
|
613
|
-
|
|
646
|
+
window.removeEventListener("message", configHandler);
|
|
647
|
+
clearTimeout(timer);
|
|
648
|
+
innerCleanup?.();
|
|
614
649
|
};
|
|
615
650
|
}
|
|
616
|
-
|
|
617
|
-
setLoading(false);
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
;
|
|
621
|
-
(async () => {
|
|
622
|
-
try {
|
|
623
|
-
if (initialScheduleId) {
|
|
624
|
-
const res = await fetch(`${API_URL}/api/schedule/id/${initialScheduleId}`);
|
|
625
|
-
const data = await res.json();
|
|
626
|
-
setSchedule(data?.id ? data : null);
|
|
627
|
-
} else {
|
|
628
|
-
const domain = getApiDomain();
|
|
629
|
-
const sitemapRes = await fetch(`${API_URL}/api/schedule/sitemap/${domain}`);
|
|
630
|
-
const slugs = await sitemapRes.json();
|
|
631
|
-
if (!Array.isArray(slugs) || !slugs.length) {
|
|
632
|
-
setLoading(false);
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
const { slug } = [...slugs].sort(
|
|
636
|
-
(a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()
|
|
637
|
-
)[0];
|
|
638
|
-
const res = await fetch(`${API_URL}/api/schedule/${domain}/${slug}`);
|
|
639
|
-
const data = await res.json();
|
|
640
|
-
setSchedule(data?.id ? data : null);
|
|
641
|
-
}
|
|
642
|
-
} catch {
|
|
643
|
-
}
|
|
644
|
-
setLoading(false);
|
|
645
|
-
})();
|
|
651
|
+
return loadWithId(initialScheduleId) ?? void 0;
|
|
646
652
|
}, []);
|
|
647
653
|
const timezoneLabel = schedule?.timezone ? (() => {
|
|
648
654
|
try {
|
|
@@ -4342,10 +4348,14 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
4342
4348
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
4343
4349
|
if (inEditor) getSectionsTracker().textContent = raw;
|
|
4344
4350
|
const pageEntries = getPageSchedulingEntries(raw);
|
|
4351
|
+
const preExisting = pageEntries.filter((e) => !isSchedulingWidgetMissing(e));
|
|
4345
4352
|
const notifyForEntry = inEditor ? (e) => !e.scheduleId : false;
|
|
4346
4353
|
mountSchedulingEntries(pageEntries, notifyForEntry);
|
|
4347
4354
|
requestAnimationFrame(() => retryMissingSchedulingMounts(pageEntries, notifyForEntry));
|
|
4348
4355
|
setTimeout(() => retryMissingSchedulingMounts(pageEntries, notifyForEntry), 250);
|
|
4356
|
+
for (const entry of preExisting) {
|
|
4357
|
+
window.postMessage({ type: "ow:schedule-config", insertAfter: entry.insertAfter, scheduleId: entry.scheduleId ?? null }, "*");
|
|
4358
|
+
}
|
|
4349
4359
|
} catch {
|
|
4350
4360
|
}
|
|
4351
4361
|
}
|
|
@@ -4799,6 +4809,8 @@ function OhhwellsBridge() {
|
|
|
4799
4809
|
});
|
|
4800
4810
|
const postToParentRef = useRef2(postToParent);
|
|
4801
4811
|
postToParentRef.current = postToParent;
|
|
4812
|
+
const sectionsLoadedRef = useRef2(false);
|
|
4813
|
+
const pendingScheduleConfigRequests = useRef2([]);
|
|
4802
4814
|
const [toolbarRect, setToolbarRect] = useState3(null);
|
|
4803
4815
|
const [toggleState, setToggleState] = useState3(null);
|
|
4804
4816
|
const [maxBadge, setMaxBadge] = useState3(null);
|
|
@@ -4831,6 +4843,29 @@ function OhhwellsBridge() {
|
|
|
4831
4843
|
const refreshStateRules = useCallback(() => {
|
|
4832
4844
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
4833
4845
|
}, []);
|
|
4846
|
+
const processConfigRequest = useCallback((insertAfterVal) => {
|
|
4847
|
+
const tracker = getSectionsTracker();
|
|
4848
|
+
let entries = [];
|
|
4849
|
+
try {
|
|
4850
|
+
entries = JSON.parse(tracker.textContent || "[]");
|
|
4851
|
+
} catch {
|
|
4852
|
+
}
|
|
4853
|
+
const path = window.location.pathname;
|
|
4854
|
+
const entry = entries.find(
|
|
4855
|
+
(e) => e.type === "scheduling" && e.insertAfter === insertAfterVal && (!e.pagePath || e.pagePath === path)
|
|
4856
|
+
);
|
|
4857
|
+
if (entry) {
|
|
4858
|
+
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: entry.scheduleId ?? null }, "*");
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
const newEntry = { type: "scheduling", insertAfter: insertAfterVal, pagePath: path };
|
|
4862
|
+
entries.push(newEntry);
|
|
4863
|
+
tracker.textContent = JSON.stringify(entries);
|
|
4864
|
+
if (isEditMode) {
|
|
4865
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
|
|
4866
|
+
}
|
|
4867
|
+
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
4868
|
+
}, [isEditMode]);
|
|
4834
4869
|
const deactivate = useCallback(() => {
|
|
4835
4870
|
const el = activeElRef.current;
|
|
4836
4871
|
if (!el) return;
|
|
@@ -4902,6 +4937,8 @@ function OhhwellsBridge() {
|
|
|
4902
4937
|
});
|
|
4903
4938
|
}
|
|
4904
4939
|
initSectionsFromContent(content, true);
|
|
4940
|
+
sectionsLoadedRef.current = true;
|
|
4941
|
+
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
4905
4942
|
return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
|
|
4906
4943
|
}) : Promise.resolve();
|
|
4907
4944
|
};
|
|
@@ -5551,6 +5588,8 @@ function OhhwellsBridge() {
|
|
|
5551
5588
|
}
|
|
5552
5589
|
if (sectionsJson) {
|
|
5553
5590
|
initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
|
|
5591
|
+
sectionsLoadedRef.current = true;
|
|
5592
|
+
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
5554
5593
|
}
|
|
5555
5594
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
5556
5595
|
};
|
|
@@ -5814,6 +5853,22 @@ function OhhwellsBridge() {
|
|
|
5814
5853
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
5815
5854
|
};
|
|
5816
5855
|
}, [isEditMode, refreshStateRules]);
|
|
5856
|
+
useEffect2(() => {
|
|
5857
|
+
const handler = (e) => {
|
|
5858
|
+
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
5859
|
+
const insertAfterVal = e.data.insertAfter;
|
|
5860
|
+
if (!insertAfterVal) return;
|
|
5861
|
+
if (!sectionsLoadedRef.current) {
|
|
5862
|
+
if (!pendingScheduleConfigRequests.current.includes(insertAfterVal)) {
|
|
5863
|
+
pendingScheduleConfigRequests.current.push(insertAfterVal);
|
|
5864
|
+
}
|
|
5865
|
+
return;
|
|
5866
|
+
}
|
|
5867
|
+
processConfigRequest(insertAfterVal);
|
|
5868
|
+
};
|
|
5869
|
+
window.addEventListener("message", handler);
|
|
5870
|
+
return () => window.removeEventListener("message", handler);
|
|
5871
|
+
}, [processConfigRequest]);
|
|
5817
5872
|
useEffect2(() => {
|
|
5818
5873
|
if (!isEditMode) return;
|
|
5819
5874
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|