@ohhwells/bridge 0.1.42-next.94 → 0.1.42-next.95
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.cjs +161 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +161 -31
- package/dist/index.js.map +1 -1
- package/dist/styles.css +12 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6717,6 +6717,8 @@ function applyNavOrderToContainer(container, order) {
|
|
|
6717
6717
|
if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
|
|
6718
6718
|
return;
|
|
6719
6719
|
}
|
|
6720
|
+
const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
|
|
6721
|
+
const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
|
|
6720
6722
|
const seen = /* @__PURE__ */ new Set();
|
|
6721
6723
|
for (const hrefKey of desired) {
|
|
6722
6724
|
if (seen.has(hrefKey)) continue;
|
|
@@ -6731,7 +6733,9 @@ function applyNavOrderToContainer(container, order) {
|
|
|
6731
6733
|
orderedEls.push(el);
|
|
6732
6734
|
}
|
|
6733
6735
|
for (const el of orderedEls) {
|
|
6734
|
-
if (
|
|
6736
|
+
if (anchor) {
|
|
6737
|
+
if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
|
|
6738
|
+
} else if (container.lastElementChild !== el) {
|
|
6735
6739
|
container.appendChild(el);
|
|
6736
6740
|
}
|
|
6737
6741
|
}
|
|
@@ -7073,6 +7077,11 @@ function reconcileFooterOrderFromContent(content) {
|
|
|
7073
7077
|
}
|
|
7074
7078
|
applyFooterOrder(order);
|
|
7075
7079
|
}
|
|
7080
|
+
function isRowLayoutColumn(links) {
|
|
7081
|
+
if (links.length < 2) return false;
|
|
7082
|
+
const firstTop = links[0].getBoundingClientRect().top;
|
|
7083
|
+
return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
|
|
7084
|
+
}
|
|
7076
7085
|
function buildLinkDropSlots(column, columnIndex) {
|
|
7077
7086
|
const links = listFooterLinksInColumn(column);
|
|
7078
7087
|
const colRect = column.getBoundingClientRect();
|
|
@@ -7090,6 +7099,32 @@ function buildLinkDropSlots(column, columnIndex) {
|
|
|
7090
7099
|
});
|
|
7091
7100
|
return slots;
|
|
7092
7101
|
}
|
|
7102
|
+
if (isRowLayoutColumn(links)) {
|
|
7103
|
+
for (let i = 0; i <= links.length; i++) {
|
|
7104
|
+
let left;
|
|
7105
|
+
if (i === 0) {
|
|
7106
|
+
left = links[0].getBoundingClientRect().left - barThickness / 2;
|
|
7107
|
+
} else if (i === links.length) {
|
|
7108
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
7109
|
+
left = last.right - barThickness / 2;
|
|
7110
|
+
} else {
|
|
7111
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
7112
|
+
const next = links[i].getBoundingClientRect();
|
|
7113
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7114
|
+
}
|
|
7115
|
+
const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7116
|
+
slots.push({
|
|
7117
|
+
insertIndex: i,
|
|
7118
|
+
columnIndex,
|
|
7119
|
+
left,
|
|
7120
|
+
top: heightRef.top,
|
|
7121
|
+
width: barThickness,
|
|
7122
|
+
height: Math.max(heightRef.height, colRect.height * 0.8),
|
|
7123
|
+
direction: "vertical"
|
|
7124
|
+
});
|
|
7125
|
+
}
|
|
7126
|
+
return slots;
|
|
7127
|
+
}
|
|
7093
7128
|
for (let i = 0; i <= links.length; i++) {
|
|
7094
7129
|
let top;
|
|
7095
7130
|
if (i === 0) {
|
|
@@ -7173,8 +7208,7 @@ function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
|
7173
7208
|
return true;
|
|
7174
7209
|
});
|
|
7175
7210
|
for (const slot of slots) {
|
|
7176
|
-
const
|
|
7177
|
-
const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
|
|
7211
|
+
const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
|
|
7178
7212
|
if (!best || dist < best.dist) best = { slot, dist };
|
|
7179
7213
|
}
|
|
7180
7214
|
}
|
|
@@ -7584,7 +7618,6 @@ function useNavItemDrag({
|
|
|
7584
7618
|
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
7585
7619
|
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
7586
7620
|
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
7587
|
-
armItemPressDrag();
|
|
7588
7621
|
navPointerDragRef.current = {
|
|
7589
7622
|
el: anchor,
|
|
7590
7623
|
startX: e.clientX,
|
|
@@ -7611,6 +7644,7 @@ function useNavItemDrag({
|
|
|
7611
7644
|
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
7612
7645
|
e.preventDefault();
|
|
7613
7646
|
pending.started = true;
|
|
7647
|
+
armItemPressDrag();
|
|
7614
7648
|
clearTextSelection();
|
|
7615
7649
|
try {
|
|
7616
7650
|
document.body.setPointerCapture(pending.pointerId);
|
|
@@ -7638,7 +7672,8 @@ function useNavItemDrag({
|
|
|
7638
7672
|
}
|
|
7639
7673
|
} catch {
|
|
7640
7674
|
}
|
|
7641
|
-
if (!pending
|
|
7675
|
+
if (!pending) return;
|
|
7676
|
+
if (!pending.started) {
|
|
7642
7677
|
unlockItemDragInteraction();
|
|
7643
7678
|
return;
|
|
7644
7679
|
}
|
|
@@ -7690,7 +7725,6 @@ function useNavItemDrag({
|
|
|
7690
7725
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
7691
7726
|
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7692
7727
|
if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
|
|
7693
|
-
armItemPressDrag();
|
|
7694
7728
|
navPointerDragRef.current = {
|
|
7695
7729
|
el: selected,
|
|
7696
7730
|
startX: clientX,
|
|
@@ -8917,6 +8951,7 @@ function OhhwellsBridge() {
|
|
|
8917
8951
|
const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
|
|
8918
8952
|
const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
8919
8953
|
const activeElRef = (0, import_react9.useRef)(null);
|
|
8954
|
+
const pointerHeldRef = (0, import_react9.useRef)(false);
|
|
8920
8955
|
const selectedElRef = (0, import_react9.useRef)(null);
|
|
8921
8956
|
const selectedHrefKeyRef = (0, import_react9.useRef)(null);
|
|
8922
8957
|
const selectedFooterColAttrRef = (0, import_react9.useRef)(null);
|
|
@@ -9614,7 +9649,6 @@ function OhhwellsBridge() {
|
|
|
9614
9649
|
if (e.button !== 0) return;
|
|
9615
9650
|
const selected = selectedElRef.current;
|
|
9616
9651
|
if (!selected) return;
|
|
9617
|
-
armFooterPressDrag();
|
|
9618
9652
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
9619
9653
|
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
9620
9654
|
footerPointerDragRef.current = {
|
|
@@ -9725,6 +9759,8 @@ function OhhwellsBridge() {
|
|
|
9725
9759
|
siblingHintElRef.current = null;
|
|
9726
9760
|
setSiblingHintRect(null);
|
|
9727
9761
|
setIsItemDragging(false);
|
|
9762
|
+
const preActivationSelection = window.getSelection();
|
|
9763
|
+
const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
|
|
9728
9764
|
el.setAttribute("contenteditable", "true");
|
|
9729
9765
|
el.setAttribute("data-ohw-editing", "");
|
|
9730
9766
|
el.removeAttribute("data-ohw-hovered");
|
|
@@ -9732,7 +9768,11 @@ function OhhwellsBridge() {
|
|
|
9732
9768
|
activeElRef.current = el;
|
|
9733
9769
|
originalContentRef.current = el.innerHTML;
|
|
9734
9770
|
el.focus({ preventScroll: true });
|
|
9735
|
-
if (
|
|
9771
|
+
if (preservedRange) {
|
|
9772
|
+
const selection = window.getSelection();
|
|
9773
|
+
selection?.removeAllRanges();
|
|
9774
|
+
selection?.addRange(preservedRange);
|
|
9775
|
+
} else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
9736
9776
|
const { caretX, caretY } = options;
|
|
9737
9777
|
placeCaretAtPoint(el, caretX, caretY);
|
|
9738
9778
|
requestAnimationFrame(() => {
|
|
@@ -10188,7 +10228,18 @@ function OhhwellsBridge() {
|
|
|
10188
10228
|
if (inActive || inActiveNav) {
|
|
10189
10229
|
e.preventDefault();
|
|
10190
10230
|
e.stopPropagation();
|
|
10191
|
-
|
|
10231
|
+
const selection = window.getSelection();
|
|
10232
|
+
const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
|
|
10233
|
+
console.log(
|
|
10234
|
+
"[OHW DEBUG handleClick] already-active branch",
|
|
10235
|
+
"detail=",
|
|
10236
|
+
e.detail,
|
|
10237
|
+
"hasRangeSelection=",
|
|
10238
|
+
hasRangeSelection,
|
|
10239
|
+
"willPlaceCaret=",
|
|
10240
|
+
e.detail < 2 && !hasRangeSelection
|
|
10241
|
+
);
|
|
10242
|
+
if (e.detail < 2 && !hasRangeSelection) {
|
|
10192
10243
|
placeCaretAtPoint(active, e.clientX, e.clientY);
|
|
10193
10244
|
refreshActiveCommandsRef.current();
|
|
10194
10245
|
}
|
|
@@ -10231,6 +10282,15 @@ function OhhwellsBridge() {
|
|
|
10231
10282
|
}
|
|
10232
10283
|
e.preventDefault();
|
|
10233
10284
|
e.stopPropagation();
|
|
10285
|
+
console.log(
|
|
10286
|
+
"[OHW DEBUG handleClick] first-activation branch",
|
|
10287
|
+
"detail=",
|
|
10288
|
+
e.detail,
|
|
10289
|
+
"selectionAtClick=",
|
|
10290
|
+
JSON.stringify(window.getSelection()?.toString() ?? ""),
|
|
10291
|
+
"collapsedAtClick=",
|
|
10292
|
+
window.getSelection()?.isCollapsed
|
|
10293
|
+
);
|
|
10234
10294
|
activateRef.current(editable);
|
|
10235
10295
|
return;
|
|
10236
10296
|
}
|
|
@@ -11341,30 +11401,83 @@ function OhhwellsBridge() {
|
|
|
11341
11401
|
const h = document.documentElement.scrollHeight;
|
|
11342
11402
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
11343
11403
|
};
|
|
11344
|
-
|
|
11345
|
-
|
|
11404
|
+
let selectionChangeRaf = null;
|
|
11405
|
+
const runSelectionChange = () => {
|
|
11406
|
+
selectionChangeRaf = null;
|
|
11407
|
+
const activeRoot = activeElRef.current;
|
|
11408
|
+
if (!activeRoot) return;
|
|
11346
11409
|
const next = /* @__PURE__ */ new Set();
|
|
11347
|
-
for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
|
|
11348
|
-
try {
|
|
11349
|
-
if (document.queryCommandState(cmd)) next.add(cmd);
|
|
11350
|
-
} catch {
|
|
11351
|
-
}
|
|
11352
|
-
}
|
|
11353
11410
|
const sel = window.getSelection();
|
|
11354
|
-
|
|
11355
|
-
if (
|
|
11356
|
-
const
|
|
11357
|
-
|
|
11358
|
-
if (
|
|
11359
|
-
const
|
|
11360
|
-
|
|
11361
|
-
else if (align === "right" || align === "end") next.add("justifyRight");
|
|
11362
|
-
else next.add("justifyLeft");
|
|
11411
|
+
let startNode = null;
|
|
11412
|
+
if (sel && sel.rangeCount > 0) {
|
|
11413
|
+
const range = sel.getRangeAt(0);
|
|
11414
|
+
startNode = range.startContainer;
|
|
11415
|
+
if (startNode.nodeType === Node.ELEMENT_NODE) {
|
|
11416
|
+
const el = startNode;
|
|
11417
|
+
startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
|
|
11363
11418
|
}
|
|
11364
11419
|
}
|
|
11365
|
-
|
|
11420
|
+
const startEl = startNode ? startNode.nodeType === Node.TEXT_NODE ? startNode.parentElement : startNode : null;
|
|
11421
|
+
if (startEl) {
|
|
11422
|
+
const cs = getComputedStyle(startEl);
|
|
11423
|
+
const weight = parseInt(cs.fontWeight, 10);
|
|
11424
|
+
let hasBold = cs.fontWeight === "bold" || !Number.isNaN(weight) && weight >= 600;
|
|
11425
|
+
let hasItalic = cs.fontStyle === "italic" || cs.fontStyle === "oblique";
|
|
11426
|
+
let hasUnderline = false;
|
|
11427
|
+
let hasStrike = false;
|
|
11428
|
+
let hasUl = false;
|
|
11429
|
+
let hasOl = false;
|
|
11430
|
+
for (let el = startEl; el; el = el.parentElement) {
|
|
11431
|
+
if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
|
|
11432
|
+
if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
|
|
11433
|
+
const decoration = getComputedStyle(el).textDecorationLine;
|
|
11434
|
+
if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
|
|
11435
|
+
if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
|
|
11436
|
+
if (el.tagName === "UL") hasUl = true;
|
|
11437
|
+
if (el.tagName === "OL") hasOl = true;
|
|
11438
|
+
if (el === activeRoot) break;
|
|
11439
|
+
}
|
|
11440
|
+
if (hasBold) next.add("bold");
|
|
11441
|
+
if (hasItalic) next.add("italic");
|
|
11442
|
+
if (hasUnderline) next.add("underline");
|
|
11443
|
+
if (hasStrike) next.add("strikeThrough");
|
|
11444
|
+
if (hasUl) next.add("insertUnorderedList");
|
|
11445
|
+
if (hasOl) next.add("insertOrderedList");
|
|
11446
|
+
const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
|
|
11447
|
+
const align = getComputedStyle(block).textAlign;
|
|
11448
|
+
if (align === "center") next.add("justifyCenter");
|
|
11449
|
+
else if (align === "right" || align === "end") next.add("justifyRight");
|
|
11450
|
+
else next.add("justifyLeft");
|
|
11451
|
+
}
|
|
11452
|
+
setActiveCommands((prev) => {
|
|
11453
|
+
if (prev.size === next.size) {
|
|
11454
|
+
let same = true;
|
|
11455
|
+
for (const cmd of prev) {
|
|
11456
|
+
if (!next.has(cmd)) {
|
|
11457
|
+
same = false;
|
|
11458
|
+
break;
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
if (same) return prev;
|
|
11462
|
+
}
|
|
11463
|
+
return next;
|
|
11464
|
+
});
|
|
11465
|
+
};
|
|
11466
|
+
const handleSelectionChange = () => {
|
|
11467
|
+
if (pointerHeldRef.current) return;
|
|
11468
|
+
if (selectionChangeRaf !== null) return;
|
|
11469
|
+
selectionChangeRaf = requestAnimationFrame(runSelectionChange);
|
|
11470
|
+
};
|
|
11471
|
+
const markPointerHeld = (e) => {
|
|
11472
|
+
if (e.button !== 0) return;
|
|
11473
|
+
pointerHeldRef.current = true;
|
|
11474
|
+
};
|
|
11475
|
+
const markPointerReleased = () => {
|
|
11476
|
+
if (!pointerHeldRef.current) return;
|
|
11477
|
+
pointerHeldRef.current = false;
|
|
11478
|
+
handleSelectionChange();
|
|
11366
11479
|
};
|
|
11367
|
-
refreshActiveCommandsRef.current =
|
|
11480
|
+
refreshActiveCommandsRef.current = runSelectionChange;
|
|
11368
11481
|
const handleDocMouseLeave = () => {
|
|
11369
11482
|
hoveredImageRef.current = null;
|
|
11370
11483
|
setMediaHover(null);
|
|
@@ -11604,7 +11717,6 @@ function OhhwellsBridge() {
|
|
|
11604
11717
|
const anchor = getNavigationItemAnchor(target);
|
|
11605
11718
|
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
11606
11719
|
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
11607
|
-
armFooterPressDrag();
|
|
11608
11720
|
footerPointerDragRef.current = {
|
|
11609
11721
|
el: anchor,
|
|
11610
11722
|
kind: "link",
|
|
@@ -11618,7 +11730,6 @@ function OhhwellsBridge() {
|
|
|
11618
11730
|
}
|
|
11619
11731
|
const col = target.closest("[data-ohw-footer-col]");
|
|
11620
11732
|
if (col && !getNavigationItemAnchor(target)) {
|
|
11621
|
-
armFooterPressDrag();
|
|
11622
11733
|
footerPointerDragRef.current = {
|
|
11623
11734
|
el: col,
|
|
11624
11735
|
kind: "column",
|
|
@@ -11647,6 +11758,7 @@ function OhhwellsBridge() {
|
|
|
11647
11758
|
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
11648
11759
|
e.preventDefault();
|
|
11649
11760
|
pending.started = true;
|
|
11761
|
+
armFooterPressDrag();
|
|
11650
11762
|
clearTextSelection();
|
|
11651
11763
|
try {
|
|
11652
11764
|
document.body.setPointerCapture(pending.pointerId);
|
|
@@ -11700,7 +11812,8 @@ function OhhwellsBridge() {
|
|
|
11700
11812
|
}
|
|
11701
11813
|
} catch {
|
|
11702
11814
|
}
|
|
11703
|
-
if (!pending
|
|
11815
|
+
if (!pending) return;
|
|
11816
|
+
if (!pending.started) {
|
|
11704
11817
|
unlockFooterDragInteraction();
|
|
11705
11818
|
return;
|
|
11706
11819
|
}
|
|
@@ -11735,6 +11848,22 @@ function OhhwellsBridge() {
|
|
|
11735
11848
|
unlockFooterDragInteraction();
|
|
11736
11849
|
};
|
|
11737
11850
|
}, [isEditMode]);
|
|
11851
|
+
(0, import_react9.useEffect)(() => {
|
|
11852
|
+
if (!isEditMode) return;
|
|
11853
|
+
const debugSelectionChange = () => {
|
|
11854
|
+
const sel = window.getSelection();
|
|
11855
|
+
console.log(
|
|
11856
|
+
"[OHW DEBUG selectionchange]",
|
|
11857
|
+
JSON.stringify(sel?.toString() ?? ""),
|
|
11858
|
+
"collapsed=",
|
|
11859
|
+
sel?.isCollapsed,
|
|
11860
|
+
"anchorNode=",
|
|
11861
|
+
sel?.anchorNode,
|
|
11862
|
+
"activeEl=",
|
|
11863
|
+
activeElRef.current
|
|
11864
|
+
);
|
|
11865
|
+
};
|
|
11866
|
+
}, [isEditMode]);
|
|
11738
11867
|
(0, import_react9.useEffect)(() => {
|
|
11739
11868
|
const handler = (e) => {
|
|
11740
11869
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
@@ -11793,6 +11922,7 @@ function OhhwellsBridge() {
|
|
|
11793
11922
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
11794
11923
|
}, [pathname]);
|
|
11795
11924
|
const handleCommand = (0, import_react9.useCallback)((cmd) => {
|
|
11925
|
+
document.execCommand("styleWithCSS", false, true);
|
|
11796
11926
|
document.execCommand(cmd, false);
|
|
11797
11927
|
activeElRef.current?.focus();
|
|
11798
11928
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|