@ohhwells/bridge 0.1.36-next.46 → 0.1.36-next.48

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.js CHANGED
@@ -4405,7 +4405,7 @@ function ItemActionToolbar({
4405
4405
  /* @__PURE__ */ jsx8(
4406
4406
  ToolbarActionTooltip,
4407
4407
  {
4408
- label: "Add link",
4408
+ label: "Edit link",
4409
4409
  side: tooltipSide,
4410
4410
  buttonProps: {
4411
4411
  onMouseDown: (e) => {
@@ -5951,6 +5951,87 @@ function clearHrefKeyHover(anchor) {
5951
5951
  function isInsideNavigationItem(el) {
5952
5952
  return getNavigationItemAnchor(el) !== null;
5953
5953
  }
5954
+ function getNavigationRoot(el) {
5955
+ const explicit = el.closest("[data-ohw-nav-root]");
5956
+ if (explicit) return explicit;
5957
+ return el.closest("nav, footer, aside");
5958
+ }
5959
+ function findFooterItemGroup(item) {
5960
+ const footer = item.closest("footer");
5961
+ if (!footer) return null;
5962
+ let node = item.parentElement;
5963
+ while (node && node !== footer) {
5964
+ const hasDirectNavItems = Array.from(
5965
+ node.querySelectorAll(":scope > [data-ohw-href-key]")
5966
+ ).some(isNavigationItem);
5967
+ if (hasDirectNavItems) return node;
5968
+ node = node.parentElement;
5969
+ }
5970
+ return null;
5971
+ }
5972
+ function isNavigationRoot(el) {
5973
+ return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
5974
+ }
5975
+ function isInferredFooterGroup(el) {
5976
+ const footer = el.closest("footer");
5977
+ if (!footer || el === footer) return false;
5978
+ return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
5979
+ }
5980
+ function isNavigationContainer(el) {
5981
+ return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
5982
+ }
5983
+ function getNavigationSelectionParent(el) {
5984
+ if (isNavigationItem(el)) {
5985
+ const explicit = el.closest("[data-ohw-nav-container]");
5986
+ if (explicit) return explicit;
5987
+ const footerGroup = findFooterItemGroup(el);
5988
+ if (footerGroup) return footerGroup;
5989
+ return getNavigationRoot(el);
5990
+ }
5991
+ if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
5992
+ return getNavigationRoot(el);
5993
+ }
5994
+ return null;
5995
+ }
5996
+ function placeCaretAtPoint(el, x, y) {
5997
+ const selection = window.getSelection();
5998
+ if (!selection) return;
5999
+ if (typeof document.caretRangeFromPoint === "function") {
6000
+ const range = document.caretRangeFromPoint(x, y);
6001
+ if (range && el.contains(range.startContainer)) {
6002
+ selection.removeAllRanges();
6003
+ selection.addRange(range);
6004
+ return;
6005
+ }
6006
+ }
6007
+ const caretPositionFromPoint = document.caretPositionFromPoint;
6008
+ if (typeof caretPositionFromPoint === "function") {
6009
+ const position = caretPositionFromPoint(x, y);
6010
+ if (position && el.contains(position.offsetNode)) {
6011
+ const range = document.createRange();
6012
+ range.setStart(position.offsetNode, position.offset);
6013
+ range.collapse(true);
6014
+ selection.removeAllRanges();
6015
+ selection.addRange(range);
6016
+ }
6017
+ }
6018
+ }
6019
+ function selectAllTextInEditable(el) {
6020
+ const selection = window.getSelection();
6021
+ if (!selection) return;
6022
+ const range = document.createRange();
6023
+ range.selectNodeContents(el);
6024
+ selection.removeAllRanges();
6025
+ selection.addRange(range);
6026
+ }
6027
+ function getNavigationLabelEditable(target) {
6028
+ const editable = target.closest('[data-ohw-editable="text"]');
6029
+ if (!editable) return null;
6030
+ const hrefCtx = getHrefKeyFromElement(editable);
6031
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
6032
+ if (!navAnchor) return null;
6033
+ return { editable, navAnchor };
6034
+ }
5954
6035
  function collectSections() {
5955
6036
  return collectSectionsFromDom();
5956
6037
  }
@@ -6431,6 +6512,8 @@ function OhhwellsBridge() {
6431
6512
  });
6432
6513
  const selectRef = useRef3(() => {
6433
6514
  });
6515
+ const selectFrameRef = useRef3(() => {
6516
+ });
6434
6517
  const deselectRef = useRef3(() => {
6435
6518
  });
6436
6519
  const reselectNavigationItemRef = useRef3(() => {
@@ -6721,7 +6804,24 @@ function OhhwellsBridge() {
6721
6804
  setToolbarShowEditLink(false);
6722
6805
  setActiveCommands(/* @__PURE__ */ new Set());
6723
6806
  }, [deactivate]);
6724
- const activate = useCallback3((el) => {
6807
+ const selectFrame = useCallback3((el) => {
6808
+ if (!isNavigationContainer(el)) return;
6809
+ if (activeElRef.current) deactivate();
6810
+ selectedElRef.current = el;
6811
+ clearHrefKeyHover(el);
6812
+ setHoveredItemRect(null);
6813
+ hoveredItemElRef.current = null;
6814
+ siblingHintElRef.current = null;
6815
+ setSiblingHintRect(null);
6816
+ setIsItemDragging(false);
6817
+ setReorderHrefKey(null);
6818
+ setReorderDragDisabled(false);
6819
+ setToolbarVariant("select-frame");
6820
+ setToolbarRect(el.getBoundingClientRect());
6821
+ setToolbarShowEditLink(false);
6822
+ setActiveCommands(/* @__PURE__ */ new Set());
6823
+ }, [deactivate]);
6824
+ const activate = useCallback3((el, options) => {
6725
6825
  if (activeElRef.current === el) return;
6726
6826
  selectedElRef.current = null;
6727
6827
  deactivate();
@@ -6739,6 +6839,9 @@ function OhhwellsBridge() {
6739
6839
  activeElRef.current = el;
6740
6840
  originalContentRef.current = el.innerHTML;
6741
6841
  el.focus();
6842
+ if (options?.caretX !== void 0 && options?.caretY !== void 0) {
6843
+ placeCaretAtPoint(el, options.caretX, options.caretY);
6844
+ }
6742
6845
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6743
6846
  const navAnchor = getNavigationItemAnchor(el);
6744
6847
  if (navAnchor) {
@@ -6756,6 +6859,7 @@ function OhhwellsBridge() {
6756
6859
  activateRef.current = activate;
6757
6860
  deactivateRef.current = deactivate;
6758
6861
  selectRef.current = select;
6862
+ selectFrameRef.current = selectFrame;
6759
6863
  deselectRef.current = deselect;
6760
6864
  useLayoutEffect2(() => {
6761
6865
  if (!subdomain || isEditMode) {
@@ -7017,7 +7121,8 @@ function OhhwellsBridge() {
7017
7121
  e.preventDefault();
7018
7122
  e.stopPropagation();
7019
7123
  if (selectedElRef.current === navAnchor) {
7020
- activateRef.current(editable);
7124
+ if (e.detail >= 2) return;
7125
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
7021
7126
  return;
7022
7127
  }
7023
7128
  selectRef.current(navAnchor);
@@ -7036,6 +7141,15 @@ function OhhwellsBridge() {
7036
7141
  selectRef.current(hrefAnchor);
7037
7142
  return;
7038
7143
  }
7144
+ const selectedContainer = selectedElRef.current;
7145
+ if (selectedContainer && isNavigationContainer(selectedContainer)) {
7146
+ const navItem = getNavigationItemAnchor(target);
7147
+ if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
7148
+ e.preventDefault();
7149
+ e.stopPropagation();
7150
+ return;
7151
+ }
7152
+ }
7039
7153
  if (activeElRef.current) {
7040
7154
  const sel = window.getSelection();
7041
7155
  if (sel && !sel.isCollapsed) {
@@ -7061,6 +7175,28 @@ function OhhwellsBridge() {
7061
7175
  deselectRef.current();
7062
7176
  deactivateRef.current();
7063
7177
  };
7178
+ const handleDblClick = (e) => {
7179
+ const target = e.target;
7180
+ if (target.closest("[data-ohw-toolbar]")) return;
7181
+ if (target.closest("[data-ohw-state-toggle]")) return;
7182
+ if (target.closest("[data-ohw-max-badge]")) return;
7183
+ if (isInsideLinkEditor(target)) return;
7184
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
7185
+ return;
7186
+ }
7187
+ const navLabel = getNavigationLabelEditable(target);
7188
+ if (!navLabel) return;
7189
+ const { editable } = navLabel;
7190
+ e.preventDefault();
7191
+ e.stopPropagation();
7192
+ if (activeElRef.current !== editable) {
7193
+ activateRef.current(editable);
7194
+ }
7195
+ requestAnimationFrame(() => {
7196
+ selectAllTextInEditable(editable);
7197
+ refreshActiveCommandsRef.current();
7198
+ });
7199
+ };
7064
7200
  const handleMouseOver = (e) => {
7065
7201
  const target = e.target;
7066
7202
  const navAnchor = getNavigationItemAnchor(target);
@@ -7634,12 +7770,26 @@ function OhhwellsBridge() {
7634
7770
  };
7635
7771
  window.addEventListener("message", handleDeactivate);
7636
7772
  const handleKeyDown = (e) => {
7773
+ if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
7774
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
7775
+ if (navAnchor) {
7776
+ e.preventDefault();
7777
+ selectAllTextInEditable(activeElRef.current);
7778
+ refreshActiveCommandsRef.current();
7779
+ return;
7780
+ }
7781
+ }
7637
7782
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
7638
7783
  setLinkPopoverRef.current(null);
7639
7784
  return;
7640
7785
  }
7641
7786
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
7642
- deselectRef.current();
7787
+ const parent = getNavigationSelectionParent(selectedElRef.current);
7788
+ if (parent) {
7789
+ selectFrameRef.current(parent);
7790
+ } else {
7791
+ deselectRef.current();
7792
+ }
7643
7793
  return;
7644
7794
  }
7645
7795
  if (e.key === "Escape" && activeElRef.current) {
@@ -7878,7 +8028,17 @@ function OhhwellsBridge() {
7878
8028
  return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
7879
8029
  });
7880
8030
  if (textEditable) {
7881
- activateRef.current(textEditable);
8031
+ const hrefCtx = getHrefKeyFromElement(textEditable);
8032
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
8033
+ if (navAnchor) {
8034
+ if (selectedElRef.current === navAnchor) {
8035
+ activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
8036
+ } else {
8037
+ selectRef.current(navAnchor);
8038
+ }
8039
+ return;
8040
+ }
8041
+ activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
7882
8042
  return;
7883
8043
  }
7884
8044
  deactivateRef.current();
@@ -7902,6 +8062,7 @@ function OhhwellsBridge() {
7902
8062
  };
7903
8063
  window.addEventListener("resize", handleViewportResize, { passive: true });
7904
8064
  document.addEventListener("click", handleClick, true);
8065
+ document.addEventListener("dblclick", handleDblClick, true);
7905
8066
  document.addEventListener("paste", handlePaste, true);
7906
8067
  document.addEventListener("input", handleInput, true);
7907
8068
  document.addEventListener("mouseover", handleMouseOver, true);
@@ -7916,6 +8077,7 @@ function OhhwellsBridge() {
7916
8077
  window.addEventListener("scroll", handleScroll, true);
7917
8078
  return () => {
7918
8079
  document.removeEventListener("click", handleClick, true);
8080
+ document.removeEventListener("dblclick", handleDblClick, true);
7919
8081
  document.removeEventListener("paste", handlePaste, true);
7920
8082
  document.removeEventListener("input", handleInput, true);
7921
8083
  document.removeEventListener("mouseover", handleMouseOver, true);
@@ -8060,25 +8222,25 @@ function OhhwellsBridge() {
8060
8222
  /* @__PURE__ */ jsx21("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
8061
8223
  siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
8062
8224
  hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
8063
- toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ jsx21(
8225
+ toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx21(
8064
8226
  ItemInteractionLayer,
8065
8227
  {
8066
8228
  rect: toolbarRect,
8067
8229
  elRef: glowElRef,
8068
8230
  state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
8069
- showHandle: Boolean(reorderHrefKey),
8231
+ showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
8070
8232
  dragDisabled: reorderDragDisabled,
8071
8233
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
8072
8234
  onDragHandleDragStart: handleItemDragStart,
8073
8235
  onDragHandleDragEnd: handleItemDragEnd,
8074
- toolbar: isItemDragging ? void 0 : /* @__PURE__ */ jsx21(
8236
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx21(
8075
8237
  ItemActionToolbar,
8076
8238
  {
8077
8239
  onEditLink: openLinkPopoverForSelected,
8078
8240
  onAddItem: handleAddNavigationItem,
8079
8241
  addItemDisabled: false
8080
8242
  }
8081
- )
8243
+ ) : void 0
8082
8244
  }
8083
8245
  ),
8084
8246
  toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs11(Fragment3, { children: [