@ohhwells/bridge 0.1.65-next.179 → 0.1.65-next.182

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 CHANGED
@@ -6907,7 +6907,7 @@ function showSuccess(form, message) {
6907
6907
  });
6908
6908
  return;
6909
6909
  }
6910
- const text = message ?? form.getAttribute("data-ohw-success-text") ?? DEFAULT_SUCCESS_TEXT;
6910
+ const text = message || form.getAttribute("data-ohw-success-text") || DEFAULT_SUCCESS_TEXT;
6911
6911
  const note = document.createElement("p");
6912
6912
  note.setAttribute("data-ohw-form-success", "");
6913
6913
  note.setAttribute("role", "status");
@@ -6949,6 +6949,9 @@ function ensureSuccessTextEl(form, formKey, initialText) {
6949
6949
  form.appendChild(el);
6950
6950
  return el;
6951
6951
  }
6952
+ function successInitialFor(form, formKey, content) {
6953
+ return content[formSuccessKey(formKey)] || form.getAttribute("data-ohw-success-text") || DEFAULT_SUCCESS_TEXT;
6954
+ }
6952
6955
  function setFormViewState(form, formKey, state, initialText) {
6953
6956
  const success = ensureSuccessTextEl(form, formKey, initialText);
6954
6957
  Array.from(form.children).forEach((child) => {
@@ -7301,6 +7304,7 @@ function reconcileFieldsFromContent(form, content) {
7301
7304
  setFieldPlaceholder(wrapper, spec.placeholder);
7302
7305
  const label = fieldLabelOf(wrapper);
7303
7306
  if (label && spec.label) label.textContent = spec.label;
7307
+ syncRequiredMark(wrapper);
7304
7308
  });
7305
7309
  const wanted = new Set(stored.map((spec) => spec.key));
7306
7310
  listFieldWrappers(form).forEach((wrapper) => {
@@ -7711,6 +7715,9 @@ var import_lucide_react7 = require("lucide-react");
7711
7715
 
7712
7716
  // src/lib/sections.ts
7713
7717
  var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
7718
+ function isChromeSection(el) {
7719
+ return el.matches("header, nav, footer, aside");
7720
+ }
7714
7721
  function titleCaseSectionId(id) {
7715
7722
  return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
7716
7723
  }
@@ -7783,7 +7790,7 @@ function useLiveSectionRect(sectionId) {
7783
7790
  }
7784
7791
  function computeSectionBoundaryFlags(instanceId) {
7785
7792
  const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7786
- (el) => !el.parentElement?.closest("[data-ohw-section]")
7793
+ (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7787
7794
  );
7788
7795
  const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7789
7796
  if (index === -1) return { isFirst: true, isLast: true };
@@ -7980,7 +7987,8 @@ function AiSectionOverlay({
7980
7987
  const reviewRect = useLiveSectionRect(reviewId);
7981
7988
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
7982
7989
  (0, import_react8.useEffect)(() => {
7983
- if (!activeSelectionId || !selectionRect) {
7990
+ const selectedEl = activeSelectionId ? findSectionElement(activeSelectionId) : null;
7991
+ if (!activeSelectionId || !selectionRect || selectedEl && isChromeSection(selectedEl)) {
7984
7992
  postToParent2({ type: "ow:section-rect", instanceId: null, rect: null });
7985
7993
  return;
7986
7994
  }
@@ -14125,6 +14133,10 @@ function isIconEditable(el) {
14125
14133
  return el.dataset.ohwEditable === "icon";
14126
14134
  }
14127
14135
  var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
14136
+ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data-ohw-field-toolbar], [data-ohw-item-toolbar], [data-ohw-more-menu], [data-ohw-state-toggle], [data-ohw-max-badge], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]';
14137
+ function isOverEditorChrome(x, y) {
14138
+ return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
14139
+ }
14128
14140
  var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"])';
14129
14141
  function getVideoEl2(el) {
14130
14142
  return el instanceof HTMLVideoElement ? el : el.querySelector("video");
@@ -15163,9 +15175,14 @@ function OhhwellsBridge() {
15163
15175
  const [fieldTypePickerOpen, setFieldTypePickerOpen] = (0, import_react16.useState)(false);
15164
15176
  const clearFormPick = (0, import_react16.useCallback)(() => {
15165
15177
  const form = formPickElRef.current;
15178
+ const editing = fieldPickElRef.current;
15179
+ if (commitPlaceholderEdit(editing) && editing) {
15180
+ const owner = editing.closest('[data-ohw-editable="form"]');
15181
+ if (owner) persistFieldsRef.current(owner);
15182
+ }
15166
15183
  if (form) {
15167
15184
  const key = formKeyOf(form);
15168
- if (key) setFormViewState(form, key, "default", DEFAULT_SUCCESS_TEXT);
15185
+ if (key) setFormViewState(form, key, "default", successInitialFor(form, key, editContentRef.current));
15169
15186
  }
15170
15187
  setFormViewStateUi("default");
15171
15188
  setFormPickCount(null);
@@ -15559,7 +15576,9 @@ function OhhwellsBridge() {
15559
15576
  const deactivate = (0, import_react16.useCallback)(() => {
15560
15577
  const el = activeElRef.current;
15561
15578
  if (!el) return;
15562
- const key = el.dataset.ohwKey;
15579
+ const isFormBlock = el.dataset.ohwEditable === "form";
15580
+ const isFormControl = el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement;
15581
+ const key = isFormBlock || isFormControl ? void 0 : el.dataset.ohwKey;
15563
15582
  if (key) {
15564
15583
  const timer = autoSaveTimers.current.get(key);
15565
15584
  if (timer !== void 0) {
@@ -16668,6 +16687,7 @@ function OhhwellsBridge() {
16668
16687
  applyLinkHref(el, val);
16669
16688
  } else if (el.dataset.ohwEditable === "icon") {
16670
16689
  applyIconMarkup(el, val);
16690
+ } else if (el.dataset.ohwEditable === "form") {
16671
16691
  } else if (el.innerHTML !== val) {
16672
16692
  el.innerHTML = val;
16673
16693
  }
@@ -16770,8 +16790,9 @@ function OhhwellsBridge() {
16770
16790
  const wrapper = getFieldWrapper(input);
16771
16791
  if (!wrapper || wrapper !== fieldPickElRef.current) return;
16772
16792
  if (saveTimer) clearTimeout(saveTimer);
16793
+ const owner = wrapper.closest('[data-ohw-editable="form"]');
16773
16794
  saveTimer = setTimeout(() => {
16774
- const form = formPickElRef.current;
16795
+ const form = owner ?? formPickElRef.current;
16775
16796
  if (!form) return;
16776
16797
  const previous = input.getAttribute("placeholder");
16777
16798
  input.setAttribute("placeholder", input.value);
@@ -16843,6 +16864,7 @@ function OhhwellsBridge() {
16843
16864
  if (video && video.src !== val) applyVideoSrc(video, val);
16844
16865
  } else if (el.dataset.ohwEditable === "link") {
16845
16866
  applyLinkHref(el, val);
16867
+ } else if (el.dataset.ohwEditable === "form") {
16846
16868
  } else if (el.innerHTML !== val) {
16847
16869
  el.innerHTML = val;
16848
16870
  }
@@ -17485,6 +17507,19 @@ function OhhwellsBridge() {
17485
17507
  setHoveredNavContainerRect(null);
17486
17508
  return;
17487
17509
  }
17510
+ if (target.closest(EDITOR_CHROME_SELECTOR) || isOverEditorChrome(e.clientX, e.clientY) || isInsideLinkEditor(target)) {
17511
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
17512
+ hoveredItemElRef.current = null;
17513
+ setHoveredItemRect(null);
17514
+ hoveredNavContainerRef.current = null;
17515
+ setHoveredNavContainerRect(null);
17516
+ formHoverElRef.current = null;
17517
+ setFormHoverRect(null);
17518
+ siblingHintElRef.current = null;
17519
+ setSiblingHintRect(null);
17520
+ setSiblingHintRects([]);
17521
+ return;
17522
+ }
17488
17523
  if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
17489
17524
  hoveredItemElRef.current = null;
17490
17525
  setHoveredItemRect(null);
@@ -18226,7 +18261,10 @@ function OhhwellsBridge() {
18226
18261
  };
18227
18262
  const handleMouseMove = (e) => {
18228
18263
  const { clientX, clientY } = e;
18229
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
18264
+ if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
18265
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
18266
+ formHoverElRef.current = null;
18267
+ setFormHoverRect(null);
18230
18268
  hoveredItemElRef.current = null;
18231
18269
  setHoveredItemRect(null);
18232
18270
  hoveredNavContainerRef.current = null;
@@ -20101,28 +20139,6 @@ function OhhwellsBridge() {
20101
20139
  }
20102
20140
  ),
20103
20141
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20104
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
20105
- "button",
20106
- {
20107
- type: "button",
20108
- className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-semibold text-foreground transition-colors hover:bg-muted/80",
20109
- onClick: () => {
20110
- const form = formPickElRef.current;
20111
- if (!form) return;
20112
- postToParent2({
20113
- type: "ow:form-submissions",
20114
- formKey: formKeyOf(form),
20115
- hasLongText: formHasLongText(form)
20116
- });
20117
- },
20118
- "data-ohw-view-submissions": "",
20119
- children: [
20120
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react18.Table, { size: 14, "aria-hidden": true }),
20121
- "View submissions"
20122
- ]
20123
- }
20124
- ),
20125
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "mx-0.5 h-5 w-px bg-border" }),
20126
20142
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "flex items-center rounded-md bg-muted/70 p-0.5", children: ["default", "success"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20127
20143
  "button",
20128
20144
  {
@@ -20133,7 +20149,7 @@ function OhhwellsBridge() {
20133
20149
  const form = formPickElRef.current;
20134
20150
  const key = form ? formKeyOf(form) : null;
20135
20151
  if (!form || !key) return;
20136
- const initial = editContentRef.current[formSuccessKey(key)] ?? DEFAULT_SUCCESS_TEXT;
20152
+ const initial = successInitialFor(form, key, editContentRef.current);
20137
20153
  setFormViewState(form, key, state, initial);
20138
20154
  setFormViewStateUi(state);
20139
20155
  setFormPickRect(form.getBoundingClientRect());
@@ -20161,7 +20177,7 @@ function OhhwellsBridge() {
20161
20177
  chromeGap: formHoverElRef.current && getFieldWrapper(formHoverElRef.current) ? 8 : 24
20162
20178
  }
20163
20179
  ),
20164
- fieldPickRect && fieldPickState && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20180
+ fieldPickRect && fieldPickState && !isItemDragging && toolbarVariant !== "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
20165
20181
  ItemInteractionLayer,
20166
20182
  {
20167
20183
  rect: fieldPickRect,