@ohhwells/bridge 0.1.15 → 0.1.16-next.8
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 +198 -70
- package/dist/index.cjs +94 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +90 -12
- package/dist/index.js.map +1 -1
- package/dist/styles.css +112 -88
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -3433,8 +3433,30 @@ function isEditSessionActive() {
|
|
|
3433
3433
|
return new URLSearchParams(q).get("mode") === "edit";
|
|
3434
3434
|
}
|
|
3435
3435
|
|
|
3436
|
+
// src/ui/badge.tsx
|
|
3437
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
3438
|
+
var badgeVariants = cva(
|
|
3439
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
3440
|
+
{
|
|
3441
|
+
variants: {
|
|
3442
|
+
variant: {
|
|
3443
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
3444
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
3445
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
3446
|
+
outline: "text-foreground"
|
|
3447
|
+
}
|
|
3448
|
+
},
|
|
3449
|
+
defaultVariants: {
|
|
3450
|
+
variant: "default"
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
);
|
|
3454
|
+
function Badge({ className, variant, ...props }) {
|
|
3455
|
+
return /* @__PURE__ */ jsx3("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3436
3458
|
// src/OhhwellsBridge.tsx
|
|
3437
|
-
import { Fragment, jsx as
|
|
3459
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
3438
3460
|
var PRIMARY = "#0885FE";
|
|
3439
3461
|
var IMAGE_FADE_MS = 300;
|
|
3440
3462
|
function runOpacityFade(el, onDone) {
|
|
@@ -3642,7 +3664,7 @@ var TOOLBAR_GROUPS = [
|
|
|
3642
3664
|
];
|
|
3643
3665
|
function GlowFrame({ rect, elRef }) {
|
|
3644
3666
|
const GAP = 6;
|
|
3645
|
-
return /* @__PURE__ */
|
|
3667
|
+
return /* @__PURE__ */ jsx4(
|
|
3646
3668
|
"div",
|
|
3647
3669
|
{
|
|
3648
3670
|
ref: elRef,
|
|
@@ -3693,7 +3715,7 @@ function FloatingToolbar({
|
|
|
3693
3715
|
activeCommands
|
|
3694
3716
|
}) {
|
|
3695
3717
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll);
|
|
3696
|
-
return /* @__PURE__ */
|
|
3718
|
+
return /* @__PURE__ */ jsx4(
|
|
3697
3719
|
"div",
|
|
3698
3720
|
{
|
|
3699
3721
|
ref: elRef,
|
|
@@ -3717,10 +3739,10 @@ function FloatingToolbar({
|
|
|
3717
3739
|
whiteSpace: "nowrap"
|
|
3718
3740
|
},
|
|
3719
3741
|
children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
3720
|
-
gi > 0 && /* @__PURE__ */
|
|
3742
|
+
gi > 0 && /* @__PURE__ */ jsx4("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
|
|
3721
3743
|
btns.map((btn) => {
|
|
3722
3744
|
const isActive = activeCommands.has(btn.cmd);
|
|
3723
|
-
return /* @__PURE__ */
|
|
3745
|
+
return /* @__PURE__ */ jsx4(
|
|
3724
3746
|
"button",
|
|
3725
3747
|
{
|
|
3726
3748
|
title: btn.title,
|
|
@@ -3746,7 +3768,7 @@ function FloatingToolbar({
|
|
|
3746
3768
|
flexShrink: 0,
|
|
3747
3769
|
padding: 6
|
|
3748
3770
|
},
|
|
3749
|
-
children: /* @__PURE__ */
|
|
3771
|
+
children: /* @__PURE__ */ jsx4(
|
|
3750
3772
|
"svg",
|
|
3751
3773
|
{
|
|
3752
3774
|
width: "16",
|
|
@@ -3779,7 +3801,7 @@ function StateToggle({
|
|
|
3779
3801
|
states,
|
|
3780
3802
|
onStateChange
|
|
3781
3803
|
}) {
|
|
3782
|
-
return /* @__PURE__ */
|
|
3804
|
+
return /* @__PURE__ */ jsx4(
|
|
3783
3805
|
ToggleGroup,
|
|
3784
3806
|
{
|
|
3785
3807
|
"data-ohw-state-toggle": "",
|
|
@@ -3793,7 +3815,7 @@ function StateToggle({
|
|
|
3793
3815
|
left: rect.right - 8,
|
|
3794
3816
|
transform: "translateX(-100%)"
|
|
3795
3817
|
},
|
|
3796
|
-
children: states.map((state) => /* @__PURE__ */
|
|
3818
|
+
children: states.map((state) => /* @__PURE__ */ jsx4(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
3797
3819
|
}
|
|
3798
3820
|
);
|
|
3799
3821
|
}
|
|
@@ -3847,6 +3869,7 @@ function OhhwellsBridge() {
|
|
|
3847
3869
|
const glowElRef = useRef(null);
|
|
3848
3870
|
const hoveredImageRef = useRef(null);
|
|
3849
3871
|
const hoveredImageHasTextOverlapRef = useRef(false);
|
|
3872
|
+
const hoveredGapRef = useRef(null);
|
|
3850
3873
|
const imageUnhoverTimerRef = useRef(null);
|
|
3851
3874
|
const imageShowTimerRef = useRef(null);
|
|
3852
3875
|
const editStylesRef = useRef(null);
|
|
@@ -3862,6 +3885,7 @@ function OhhwellsBridge() {
|
|
|
3862
3885
|
const [toggleState, setToggleState] = useState(null);
|
|
3863
3886
|
const [maxBadge, setMaxBadge] = useState(null);
|
|
3864
3887
|
const [activeCommands, setActiveCommands] = useState(/* @__PURE__ */ new Set());
|
|
3888
|
+
const [sectionGap, setSectionGap] = useState(null);
|
|
3865
3889
|
useEffect(() => {
|
|
3866
3890
|
const update = () => {
|
|
3867
3891
|
const el = activeElRef.current;
|
|
@@ -3870,6 +3894,12 @@ function OhhwellsBridge() {
|
|
|
3870
3894
|
if (!prev || !activeStateElRef.current) return prev;
|
|
3871
3895
|
return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
|
|
3872
3896
|
});
|
|
3897
|
+
setSectionGap((prev) => {
|
|
3898
|
+
if (!prev) return prev;
|
|
3899
|
+
const anchor = document.querySelector(`[data-ohw-section="${prev.insertAfter}"]`);
|
|
3900
|
+
if (!anchor) return prev;
|
|
3901
|
+
return { ...prev, y: anchor.getBoundingClientRect().bottom };
|
|
3902
|
+
});
|
|
3873
3903
|
};
|
|
3874
3904
|
const vvp = window.visualViewport;
|
|
3875
3905
|
if (!vvp) return;
|
|
@@ -3962,7 +3992,7 @@ function OhhwellsBridge() {
|
|
|
3962
3992
|
}
|
|
3963
3993
|
let cancelled = false;
|
|
3964
3994
|
setFetchState("loading");
|
|
3965
|
-
const apiUrl =
|
|
3995
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
3966
3996
|
fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
3967
3997
|
if (cancelled) return;
|
|
3968
3998
|
const content = data?.content ?? {};
|
|
@@ -4374,10 +4404,32 @@ function OhhwellsBridge() {
|
|
|
4374
4404
|
}
|
|
4375
4405
|
}
|
|
4376
4406
|
};
|
|
4407
|
+
const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
|
|
4408
|
+
const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
4409
|
+
const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
|
|
4410
|
+
const ZONE = 20;
|
|
4411
|
+
for (let i = 0; i < sections.length; i++) {
|
|
4412
|
+
const a = sections[i];
|
|
4413
|
+
const b = sections[i + 1] ?? null;
|
|
4414
|
+
const boundaryY = a.getBoundingClientRect().bottom;
|
|
4415
|
+
if (Math.abs(y - boundaryY) <= ZONE) {
|
|
4416
|
+
const insertAfter = a.dataset.ohwSection ?? "";
|
|
4417
|
+
const insertBefore = b?.dataset.ohwSection ?? null;
|
|
4418
|
+
hoveredGapRef.current = { insertAfter, insertBefore };
|
|
4419
|
+
setSectionGap({ insertAfter, insertBefore, y: boundaryY });
|
|
4420
|
+
return;
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
if (hoveredGapRef.current) {
|
|
4424
|
+
hoveredGapRef.current = null;
|
|
4425
|
+
setSectionGap(null);
|
|
4426
|
+
}
|
|
4427
|
+
};
|
|
4377
4428
|
const handleMouseMove = (e) => {
|
|
4378
4429
|
const { clientX, clientY } = e;
|
|
4379
4430
|
probeImageAt(clientX, clientY);
|
|
4380
4431
|
probeHoverCardsAt(clientX, clientY);
|
|
4432
|
+
probeSectionGapAt(clientX, clientY);
|
|
4381
4433
|
};
|
|
4382
4434
|
const handlePointerSync = (e) => {
|
|
4383
4435
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
@@ -4385,6 +4437,7 @@ function OhhwellsBridge() {
|
|
|
4385
4437
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
4386
4438
|
probeImageAt(clientX, clientY);
|
|
4387
4439
|
probeHoverCardsAt(clientX, clientY);
|
|
4440
|
+
probeSectionGapAt(clientX, clientY);
|
|
4388
4441
|
};
|
|
4389
4442
|
const handleDragOver = (e) => {
|
|
4390
4443
|
e.preventDefault();
|
|
@@ -4792,8 +4845,8 @@ function OhhwellsBridge() {
|
|
|
4792
4845
|
return bridgeRoot ? createPortal(
|
|
4793
4846
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4794
4847
|
toolbarRect && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4795
|
-
/* @__PURE__ */
|
|
4796
|
-
/* @__PURE__ */
|
|
4848
|
+
/* @__PURE__ */ jsx4(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
|
|
4849
|
+
/* @__PURE__ */ jsx4(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
|
|
4797
4850
|
] }),
|
|
4798
4851
|
maxBadge && /* @__PURE__ */ jsxs(
|
|
4799
4852
|
"div",
|
|
@@ -4821,7 +4874,7 @@ function OhhwellsBridge() {
|
|
|
4821
4874
|
]
|
|
4822
4875
|
}
|
|
4823
4876
|
),
|
|
4824
|
-
toggleState && /* @__PURE__ */
|
|
4877
|
+
toggleState && /* @__PURE__ */ jsx4(
|
|
4825
4878
|
StateToggle,
|
|
4826
4879
|
{
|
|
4827
4880
|
rect: toggleState.rect,
|
|
@@ -4829,6 +4882,31 @@ function OhhwellsBridge() {
|
|
|
4829
4882
|
states: toggleState.states,
|
|
4830
4883
|
onStateChange: handleStateChange
|
|
4831
4884
|
}
|
|
4885
|
+
),
|
|
4886
|
+
sectionGap && /* @__PURE__ */ jsxs(
|
|
4887
|
+
"div",
|
|
4888
|
+
{
|
|
4889
|
+
"data-ohw-section-insert-line": "",
|
|
4890
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
4891
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
4892
|
+
children: [
|
|
4893
|
+
/* @__PURE__ */ jsx4("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
4894
|
+
/* @__PURE__ */ jsx4(
|
|
4895
|
+
Badge,
|
|
4896
|
+
{
|
|
4897
|
+
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",
|
|
4898
|
+
onClick: () => {
|
|
4899
|
+
window.parent.postMessage(
|
|
4900
|
+
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
4901
|
+
"*"
|
|
4902
|
+
);
|
|
4903
|
+
},
|
|
4904
|
+
children: "Add Section"
|
|
4905
|
+
}
|
|
4906
|
+
),
|
|
4907
|
+
/* @__PURE__ */ jsx4("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
4908
|
+
]
|
|
4909
|
+
}
|
|
4832
4910
|
)
|
|
4833
4911
|
] }),
|
|
4834
4912
|
bridgeRoot
|