@ohhwells/bridge 0.1.35 → 0.1.36-next.45

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
@@ -109,7 +109,7 @@ type ItemInteractionLayerProps = {
109
109
  rect: DOMRect;
110
110
  state: ItemInteractionState;
111
111
  elRef?: React.Ref<HTMLDivElement>;
112
- /** Slotted Custom/Toolbar instance (item-action or other fill). */
112
+ /** Slotted Custom/Toolbar instance (item-action or other fill). */
113
113
  toolbar?: React.ReactNode;
114
114
  showHandle?: boolean;
115
115
  dragDisabled?: boolean;
package/dist/index.d.ts CHANGED
@@ -109,7 +109,7 @@ type ItemInteractionLayerProps = {
109
109
  rect: DOMRect;
110
110
  state: ItemInteractionState;
111
111
  elRef?: React.Ref<HTMLDivElement>;
112
- /** Slotted Custom/Toolbar instance (item-action or other fill). */
112
+ /** Slotted Custom/Toolbar instance (item-action or other fill). */
113
113
  toolbar?: React.ReactNode;
114
114
  showHandle?: boolean;
115
115
  dragDisabled?: boolean;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React8, { useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
4
+ import React8, { useCallback as useCallback3, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -45,12 +45,13 @@ function useLinkHrefGuardian(...deps) {
45
45
  }
46
46
 
47
47
  // src/ui/SchedulingWidget.tsx
48
- import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
48
+ import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
49
49
 
50
50
  // src/ui/EmailCaptureModal.tsx
51
51
  import { useState } from "react";
52
52
  import { Dialog } from "radix-ui";
53
53
  import { jsx, jsxs } from "react/jsx-runtime";
54
+ var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
54
55
  function Spinner() {
55
56
  return /* @__PURE__ */ jsxs(
56
57
  "svg",
@@ -84,12 +85,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
84
85
  const [error, setError] = useState(null);
85
86
  const isBook = title === "Confirm your spot";
86
87
  const handleSubmit = async () => {
87
- if (!email.trim()) return;
88
+ const trimmed = email.trim();
89
+ if (!trimmed) return;
90
+ if (!isValidEmail(trimmed)) {
91
+ setError("Please enter a valid email address.");
92
+ return;
93
+ }
88
94
  setLoading(true);
89
95
  setError(null);
90
96
  try {
91
- await onSubmit(email.trim());
92
- setSubmittedEmail(email.trim());
97
+ await onSubmit(trimmed);
98
+ setSubmittedEmail(trimmed);
93
99
  setSuccess(true);
94
100
  } catch (e) {
95
101
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -164,7 +170,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
164
170
  {
165
171
  type: "email",
166
172
  value: email,
167
- onChange: (e) => setEmail(e.target.value),
173
+ onChange: (e) => {
174
+ setEmail(e.target.value);
175
+ if (error) setError(null);
176
+ },
168
177
  onKeyDown: handleKeyDown,
169
178
  placeholder: "hello@gmail.com",
170
179
  autoFocus: true,
@@ -221,12 +230,20 @@ function formatClassTime(cls) {
221
230
  const em = endTotal % 60;
222
231
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
223
232
  }
233
+ function formatBookingLabel(cls) {
234
+ const price = cls.price;
235
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
236
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
237
+ }
224
238
  function getBookingsOnDate(cls, date) {
225
239
  if (!cls.bookings?.length) return 0;
226
- const ds = date.toISOString().split("T")[0];
240
+ const target = new Date(date);
241
+ target.setHours(0, 0, 0, 0);
227
242
  return cls.bookings.filter((b) => {
228
243
  try {
229
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
244
+ const bookingDate = new Date(b.classDate);
245
+ bookingDate.setHours(0, 0, 0, 0);
246
+ return bookingDate.getTime() === target.getTime();
230
247
  } catch {
231
248
  return false;
232
249
  }
@@ -530,7 +547,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
530
547
  if (!cls.id) return;
531
548
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
532
549
  },
533
- children: isFull ? "Join Waitlist" : "Book Now"
550
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
534
551
  }
535
552
  )
536
553
  ] })
@@ -572,6 +589,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
572
589
  const [isHovered, setIsHovered] = useState2(false);
573
590
  const [modalState, setModalState] = useState2(null);
574
591
  const switchScheduleIdRef = useRef(null);
592
+ const liveScheduleIdRef = useRef(null);
593
+ const refetchLiveSchedule = useCallback(async () => {
594
+ const id = liveScheduleIdRef.current;
595
+ if (!id) return;
596
+ try {
597
+ const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
598
+ const data = await res.json();
599
+ if (data?.id) setSchedule(data);
600
+ } catch {
601
+ }
602
+ }, []);
575
603
  const dates = useMemo(() => {
576
604
  const today = /* @__PURE__ */ new Date();
577
605
  today.setHours(0, 0, 0, 0);
@@ -591,6 +619,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
591
619
  }
592
620
  }
593
621
  }, [schedule, dates]);
622
+ useEffect(() => {
623
+ if (typeof window === "undefined") return;
624
+ const onVisible = () => {
625
+ if (!document.hidden) void refetchLiveSchedule();
626
+ };
627
+ window.addEventListener("focus", refetchLiveSchedule);
628
+ document.addEventListener("visibilitychange", onVisible);
629
+ return () => {
630
+ window.removeEventListener("focus", refetchLiveSchedule);
631
+ document.removeEventListener("visibilitychange", onVisible);
632
+ };
633
+ }, [refetchLiveSchedule]);
594
634
  useEffect(() => {
595
635
  if (typeof window === "undefined") return;
596
636
  const isInEditor = window.self !== window.top;
@@ -652,7 +692,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
652
692
  setLoading(false);
653
693
  return;
654
694
  }
655
- ;
695
+ liveScheduleIdRef.current = effectiveId;
656
696
  (async () => {
657
697
  try {
658
698
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -709,18 +749,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
709
749
  const data = await res.json().catch(() => ({}));
710
750
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
711
751
  }
752
+ await refetchLiveSchedule();
712
753
  };
713
754
  const handleReplaceSchedule = () => {
714
755
  setIsHovered(false);
715
- if (schedule) {
716
- window.parent.postMessage({
717
- type: "ow:schedule-connected",
718
- schedule: { id: schedule.id, name: schedule.name },
719
- insertAfter
720
- }, "*");
721
- } else {
722
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
723
- }
756
+ window.parent.postMessage(
757
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
758
+ "*"
759
+ );
724
760
  };
725
761
  if (!inEditor && !loading && !schedule) return null;
726
762
  const sectionId = `scheduling-${insertAfter}`;
@@ -763,7 +799,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
763
799
  ),
764
800
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
765
801
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
766
- /* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
802
+ /* @__PURE__ */ jsx2(
803
+ "h2",
804
+ {
805
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
806
+ style: {
807
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
808
+ fontWeight: "var(--font-weight-heading, 400)",
809
+ lineHeight: 1.05,
810
+ letterSpacing: "-0.02em"
811
+ },
812
+ children: schedule?.name ?? "Book an appointment"
813
+ }
814
+ ),
767
815
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
768
816
  ] }),
769
817
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -5194,7 +5242,7 @@ function UrlOrPageInput({
5194
5242
  }
5195
5243
 
5196
5244
  // src/ui/link-modal/useLinkModalState.ts
5197
- import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
5245
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
5198
5246
  function useLinkModalState({
5199
5247
  open,
5200
5248
  mode,
@@ -5216,7 +5264,7 @@ function useLinkModalState({
5216
5264
  const [step, setStep] = useState4("input");
5217
5265
  const [dropdownOpen, setDropdownOpen] = useState4(false);
5218
5266
  const [urlError, setUrlError] = useState4("");
5219
- const reset = useCallback(() => {
5267
+ const reset = useCallback2(() => {
5220
5268
  setSearchValue("");
5221
5269
  setSelectedPage(null);
5222
5270
  setSelectedSection(null);
@@ -6026,6 +6074,8 @@ var ICONS = {
6026
6074
  insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
6027
6075
  insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
6028
6076
  };
6077
+ var TOOLBAR_PILL_PADDING = 2;
6078
+ var TOOLBAR_TOGGLE_GAP = 4;
6029
6079
  var TOOLBAR_GROUPS = [
6030
6080
  [
6031
6081
  { cmd: "bold", title: "Bold" },
@@ -6144,9 +6194,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
6144
6194
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
6145
6195
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
6146
6196
  }
6147
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
6197
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
6148
6198
  const GAP = 8;
6149
- const APPROX_H = 36;
6199
+ const APPROX_H = 32;
6150
6200
  const APPROX_W = approxW;
6151
6201
  const clip = getIframeVisibleClip(parentScroll);
6152
6202
  const clipTop = clip?.top ?? 0;
@@ -6204,6 +6254,15 @@ function FloatingToolbar({
6204
6254
  left,
6205
6255
  transform,
6206
6256
  zIndex: 2147483647,
6257
+ background: "#fff",
6258
+ border: "1px solid #E7E5E4",
6259
+ borderRadius: 6,
6260
+ boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
6261
+ display: "flex",
6262
+ alignItems: "center",
6263
+ padding: TOOLBAR_PILL_PADDING,
6264
+ gap: TOOLBAR_TOGGLE_GAP,
6265
+ fontFamily: "sans-serif",
6207
6266
  pointerEvents: "auto"
6208
6267
  },
6209
6268
  children: /* @__PURE__ */ jsxs11(CustomToolbar, { children: [
@@ -6339,7 +6398,7 @@ function OhhwellsBridge() {
6339
6398
  const subdomainFromQuery = searchParams.get("subdomain");
6340
6399
  const subdomain = resolveSubdomain(subdomainFromQuery);
6341
6400
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
6342
- const postToParent = useCallback2((data) => {
6401
+ const postToParent = useCallback3((data) => {
6343
6402
  if (typeof window !== "undefined" && window.parent !== window) {
6344
6403
  window.parent.postMessage(data, "*");
6345
6404
  }
@@ -6353,7 +6412,7 @@ function OhhwellsBridge() {
6353
6412
  const parentScrollRef = useRef3(null);
6354
6413
  const visibleViewportRef = useRef3(null);
6355
6414
  const [dialogPortalContainer, setDialogPortalContainer] = useState5(null);
6356
- const attachVisibleViewport = useCallback2((node) => {
6415
+ const attachVisibleViewport = useCallback3((node) => {
6357
6416
  visibleViewportRef.current = node;
6358
6417
  setDialogPortalContainer(node);
6359
6418
  if (node) applyVisibleViewport(node, parentScrollRef.current);
@@ -6412,7 +6471,7 @@ function OhhwellsBridge() {
6412
6471
  const bumpLinkPopoverGrace = () => {
6413
6472
  linkPopoverGraceUntilRef.current = Date.now() + 350;
6414
6473
  };
6415
- const runSectionsPrefetch = useCallback2((pages) => {
6474
+ const runSectionsPrefetch = useCallback3((pages) => {
6416
6475
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
6417
6476
  const gen = ++sectionsPrefetchGenRef.current;
6418
6477
  const paths = pages.map((p) => p.path);
@@ -6522,10 +6581,10 @@ function OhhwellsBridge() {
6522
6581
  vvp.removeEventListener("resize", update);
6523
6582
  };
6524
6583
  }, []);
6525
- const refreshStateRules = useCallback2(() => {
6584
+ const refreshStateRules = useCallback3(() => {
6526
6585
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
6527
6586
  }, []);
6528
- const processConfigRequest = useCallback2((insertAfterVal) => {
6587
+ const processConfigRequest = useCallback3((insertAfterVal) => {
6529
6588
  const tracker = getSectionsTracker();
6530
6589
  let entries = [];
6531
6590
  try {
@@ -6548,7 +6607,7 @@ function OhhwellsBridge() {
6548
6607
  }
6549
6608
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
6550
6609
  }, [isEditMode]);
6551
- const deactivate = useCallback2(() => {
6610
+ const deactivate = useCallback3(() => {
6552
6611
  const el = activeElRef.current;
6553
6612
  if (!el) return;
6554
6613
  const key = el.dataset.ohwKey;
@@ -6579,7 +6638,7 @@ function OhhwellsBridge() {
6579
6638
  setToolbarShowEditLink(false);
6580
6639
  postToParent({ type: "ow:exit-edit" });
6581
6640
  }, [postToParent]);
6582
- const deselect = useCallback2(() => {
6641
+ const deselect = useCallback3(() => {
6583
6642
  selectedElRef.current = null;
6584
6643
  setReorderHrefKey(null);
6585
6644
  setReorderDragDisabled(false);
@@ -6591,7 +6650,7 @@ function OhhwellsBridge() {
6591
6650
  setToolbarVariant("none");
6592
6651
  }
6593
6652
  }, []);
6594
- const reselectNavigationItem = useCallback2((navAnchor) => {
6653
+ const reselectNavigationItem = useCallback3((navAnchor) => {
6595
6654
  selectedElRef.current = navAnchor;
6596
6655
  const { key, disabled } = getNavigationItemReorderState(navAnchor);
6597
6656
  setReorderHrefKey(key);
@@ -6601,7 +6660,7 @@ function OhhwellsBridge() {
6601
6660
  setToolbarShowEditLink(false);
6602
6661
  setActiveCommands(/* @__PURE__ */ new Set());
6603
6662
  }, []);
6604
- const commitNavigationTextEdit = useCallback2((navAnchor) => {
6663
+ const commitNavigationTextEdit = useCallback3((navAnchor) => {
6605
6664
  const el = activeElRef.current;
6606
6665
  if (!el) return;
6607
6666
  const key = el.dataset.ohwKey;
@@ -6627,24 +6686,24 @@ function OhhwellsBridge() {
6627
6686
  postToParent({ type: "ow:exit-edit" });
6628
6687
  reselectNavigationItem(navAnchor);
6629
6688
  }, [postToParent, reselectNavigationItem]);
6630
- const handleAddNavigationItem = useCallback2(() => {
6689
+ const handleAddNavigationItem = useCallback3(() => {
6631
6690
  const selected = selectedElRef.current;
6632
6691
  if (!selected) return;
6633
6692
  const target = getNavigationItemAddHintTarget(selected);
6634
6693
  siblingHintElRef.current = target;
6635
6694
  setSiblingHintRect(target.getBoundingClientRect());
6636
6695
  }, []);
6637
- const handleItemDragStart = useCallback2(() => {
6696
+ const handleItemDragStart = useCallback3(() => {
6638
6697
  siblingHintElRef.current = null;
6639
6698
  setSiblingHintRect(null);
6640
6699
  setIsItemDragging(true);
6641
6700
  }, []);
6642
- const handleItemDragEnd = useCallback2(() => {
6701
+ const handleItemDragEnd = useCallback3(() => {
6643
6702
  setIsItemDragging(false);
6644
6703
  }, []);
6645
6704
  reselectNavigationItemRef.current = reselectNavigationItem;
6646
6705
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
6647
- const select = useCallback2((anchor) => {
6706
+ const select = useCallback3((anchor) => {
6648
6707
  if (!isNavigationItem(anchor)) return;
6649
6708
  if (activeElRef.current) deactivate();
6650
6709
  selectedElRef.current = anchor;
@@ -6662,7 +6721,7 @@ function OhhwellsBridge() {
6662
6721
  setToolbarShowEditLink(false);
6663
6722
  setActiveCommands(/* @__PURE__ */ new Set());
6664
6723
  }, [deactivate]);
6665
- const activate = useCallback2((el) => {
6724
+ const activate = useCallback3((el) => {
6666
6725
  if (activeElRef.current === el) return;
6667
6726
  selectedElRef.current = null;
6668
6727
  deactivate();
@@ -7941,13 +8000,13 @@ function OhhwellsBridge() {
7941
8000
  window.addEventListener("hashchange", onHashChange);
7942
8001
  return () => window.removeEventListener("hashchange", onHashChange);
7943
8002
  }, [pathname]);
7944
- const handleCommand = useCallback2((cmd) => {
8003
+ const handleCommand = useCallback3((cmd) => {
7945
8004
  document.execCommand(cmd, false);
7946
8005
  activeElRef.current?.focus();
7947
8006
  if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7948
8007
  refreshActiveCommandsRef.current();
7949
8008
  }, []);
7950
- const handleStateChange = useCallback2((state) => {
8009
+ const handleStateChange = useCallback3((state) => {
7951
8010
  if (!activeStateElRef.current) return;
7952
8011
  const el = activeStateElRef.current;
7953
8012
  if (state === "Default") {
@@ -7960,8 +8019,8 @@ function OhhwellsBridge() {
7960
8019
  }
7961
8020
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
7962
8021
  }, [deactivate]);
7963
- const closeLinkPopover = useCallback2(() => setLinkPopover(null), []);
7964
- const openLinkPopoverForActive = useCallback2(() => {
8022
+ const closeLinkPopover = useCallback3(() => setLinkPopover(null), []);
8023
+ const openLinkPopoverForActive = useCallback3(() => {
7965
8024
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7966
8025
  if (!hrefCtx) return;
7967
8026
  bumpLinkPopoverGrace();
@@ -7971,7 +8030,7 @@ function OhhwellsBridge() {
7971
8030
  });
7972
8031
  deactivate();
7973
8032
  }, [deactivate]);
7974
- const openLinkPopoverForSelected = useCallback2(() => {
8033
+ const openLinkPopoverForSelected = useCallback3(() => {
7975
8034
  const anchor = selectedElRef.current;
7976
8035
  if (!anchor) return;
7977
8036
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -7983,7 +8042,7 @@ function OhhwellsBridge() {
7983
8042
  });
7984
8043
  deselect();
7985
8044
  }, [deselect]);
7986
- const handleLinkPopoverSubmit = useCallback2(
8045
+ const handleLinkPopoverSubmit = useCallback3(
7987
8046
  (target) => {
7988
8047
  if (!linkPopover) return;
7989
8048
  const { key } = linkPopover;
@@ -8120,7 +8179,32 @@ function OhhwellsBridge() {
8120
8179
  onSubmit: handleLinkPopoverSubmit
8121
8180
  },
8122
8181
  `${linkPopover.key}-${pathname}`
8123
- ) : null
8182
+ ) : null,
8183
+ sectionGap && /* @__PURE__ */ jsxs11(
8184
+ "div",
8185
+ {
8186
+ "data-ohw-section-insert-line": "",
8187
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
8188
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
8189
+ children: [
8190
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8191
+ /* @__PURE__ */ jsx21(
8192
+ Badge,
8193
+ {
8194
+ className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
8195
+ onClick: () => {
8196
+ window.parent.postMessage(
8197
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
8198
+ "*"
8199
+ );
8200
+ },
8201
+ children: "Add Section"
8202
+ }
8203
+ ),
8204
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8205
+ ]
8206
+ }
8207
+ )
8124
8208
  ] }),
8125
8209
  bridgeRoot
8126
8210
  ) : null;