@ohhwells/bridge 0.1.65-next.182 → 0.1.65-next.184
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 +70 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +70 -23
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7018,6 +7018,7 @@ var FIELD_TYPES = [
|
|
|
7018
7018
|
];
|
|
7019
7019
|
var FIELD_ATTR = "data-ohw-form-field";
|
|
7020
7020
|
var FIELD_TYPE_ATTR = "data-ohw-field-type";
|
|
7021
|
+
var PLACEHOLDER_EDIT_ATTR = "data-ohw-placeholder-edit";
|
|
7021
7022
|
function fieldsKey(formKey) {
|
|
7022
7023
|
return `${formKey}-fields`;
|
|
7023
7024
|
}
|
|
@@ -7055,7 +7056,7 @@ function ensureFieldLabel(wrapper, key) {
|
|
|
7055
7056
|
label.style.lineHeight = "1.3";
|
|
7056
7057
|
const fromPlaceholder = input?.getAttribute("placeholder")?.trim();
|
|
7057
7058
|
const text = fromPlaceholder && fromPlaceholder.length < 40 ? fromPlaceholder : key.replace(/[-_]/g, " ");
|
|
7058
|
-
label.textContent =
|
|
7059
|
+
label.textContent = text;
|
|
7059
7060
|
if (input && input.parentElement === wrapper) wrapper.insertBefore(label, input);
|
|
7060
7061
|
else wrapper.insertBefore(label, wrapper.firstChild);
|
|
7061
7062
|
return label;
|
|
@@ -7111,8 +7112,11 @@ function readFieldsFromDom(form) {
|
|
|
7111
7112
|
return {
|
|
7112
7113
|
key: fieldKeyOf(wrapper),
|
|
7113
7114
|
type: fieldTypeOf(wrapper),
|
|
7114
|
-
label: fieldLabelOf(wrapper)
|
|
7115
|
-
|
|
7115
|
+
label: fieldLabelText(fieldLabelOf(wrapper)).trim(),
|
|
7116
|
+
// While a field is selected its placeholder text lives in the value (see
|
|
7117
|
+
// beginPlaceholderEdit), so reading the attribute would store an empty one — whoever
|
|
7118
|
+
// happens to save at that moment must still record what the owner typed.
|
|
7119
|
+
placeholder: input ? input.hasAttribute(PLACEHOLDER_EDIT_ATTR) ? input.value : input.getAttribute("placeholder") ?? "" : "",
|
|
7116
7120
|
required: Boolean(input?.hasAttribute("required"))
|
|
7117
7121
|
};
|
|
7118
7122
|
});
|
|
@@ -7140,7 +7144,7 @@ function applyFieldType(wrapper, type) {
|
|
|
7140
7144
|
const followsDefaults = {
|
|
7141
7145
|
// A label the owner wrote stays; one that still reads as a type name (or as the old
|
|
7142
7146
|
// placeholder the template shipped) follows the new type.
|
|
7143
|
-
label: isDefaultText(label?.textContent ?? "", (d) => d.label) || (label
|
|
7147
|
+
label: isDefaultText(label?.textContent ?? "", (d) => d.label) || fieldLabelText(label).trim() === placeholder.trim()
|
|
7144
7148
|
};
|
|
7145
7149
|
const { tag, inputType } = inputTagFor(type);
|
|
7146
7150
|
wrapper.setAttribute(FIELD_TYPE_ATTR, type);
|
|
@@ -7154,8 +7158,7 @@ function applyFieldType(wrapper, type) {
|
|
|
7154
7158
|
const applyDefaults = (el) => {
|
|
7155
7159
|
el.setAttribute("placeholder", defaults.placeholder);
|
|
7156
7160
|
if (label && followsDefaults.label) {
|
|
7157
|
-
|
|
7158
|
-
label.textContent = required ? `${defaults.label} *` : defaults.label;
|
|
7161
|
+
label.textContent = defaults.label;
|
|
7159
7162
|
}
|
|
7160
7163
|
};
|
|
7161
7164
|
if (input.tagName.toLowerCase() === tag) {
|
|
@@ -7175,13 +7178,19 @@ function applyFieldType(wrapper, type) {
|
|
|
7175
7178
|
input.replaceWith(next);
|
|
7176
7179
|
applyDefaults(next);
|
|
7177
7180
|
}
|
|
7181
|
+
var REQUIRED_MARK_ATTR = "data-ohw-field-required";
|
|
7182
|
+
function fieldLabelText(label) {
|
|
7183
|
+
if (!label) return "";
|
|
7184
|
+
return (label.textContent ?? "").replace(/\s*\*\s*$/, "").trimEnd();
|
|
7185
|
+
}
|
|
7178
7186
|
function syncRequiredMark(wrapper) {
|
|
7179
7187
|
const label = fieldLabelOf(wrapper);
|
|
7180
7188
|
if (!label) return;
|
|
7181
|
-
|
|
7182
|
-
const
|
|
7183
|
-
|
|
7184
|
-
if (
|
|
7189
|
+
label.querySelectorAll("[data-ohw-required-mark]").forEach((el) => el.remove());
|
|
7190
|
+
const words = fieldLabelText(label);
|
|
7191
|
+
if ((label.textContent ?? "") !== words) label.textContent = words;
|
|
7192
|
+
if (isFieldRequired(wrapper)) label.setAttribute(REQUIRED_MARK_ATTR, "");
|
|
7193
|
+
else label.removeAttribute(REQUIRED_MARK_ATTR);
|
|
7185
7194
|
}
|
|
7186
7195
|
function setFieldRequired(wrapper, required) {
|
|
7187
7196
|
const input = fieldInputOf(wrapper);
|
|
@@ -7191,7 +7200,6 @@ function setFieldRequired(wrapper, required) {
|
|
|
7191
7200
|
else input.removeAttribute("required");
|
|
7192
7201
|
if (label) syncRequiredMark(wrapper);
|
|
7193
7202
|
}
|
|
7194
|
-
var PLACEHOLDER_EDIT_ATTR = "data-ohw-placeholder-edit";
|
|
7195
7203
|
function beginPlaceholderEdit(wrapper) {
|
|
7196
7204
|
const input = fieldInputOf(wrapper);
|
|
7197
7205
|
if (!input || input.hasAttribute(PLACEHOLDER_EDIT_ATTR)) return;
|
|
@@ -7270,14 +7278,25 @@ function duplicateField(form, wrapper) {
|
|
|
7270
7278
|
function removeField(wrapper) {
|
|
7271
7279
|
wrapper.remove();
|
|
7272
7280
|
}
|
|
7273
|
-
function
|
|
7281
|
+
function applyFieldOrder(form, keys) {
|
|
7274
7282
|
const wrappers = listFieldWrappers(form);
|
|
7275
|
-
const
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
const
|
|
7279
|
-
|
|
7280
|
-
|
|
7283
|
+
const byKey = new Map(wrappers.map((wrapper) => [fieldKeyOf(wrapper), wrapper]));
|
|
7284
|
+
const ordered = keys.map((key) => byKey.get(key)).filter((w) => Boolean(w));
|
|
7285
|
+
if (ordered.length !== wrappers.length) return;
|
|
7286
|
+
const slots = wrappers.map((wrapper) => {
|
|
7287
|
+
const slot = document.createComment("ohw-field-slot");
|
|
7288
|
+
wrapper.replaceWith(slot);
|
|
7289
|
+
return slot;
|
|
7290
|
+
});
|
|
7291
|
+
ordered.forEach((wrapper, index) => slots[index].replaceWith(wrapper));
|
|
7292
|
+
}
|
|
7293
|
+
function moveField(form, key, toIndex) {
|
|
7294
|
+
const keys = listFieldWrappers(form).map(fieldKeyOf);
|
|
7295
|
+
const from = keys.indexOf(key);
|
|
7296
|
+
if (from === -1) return;
|
|
7297
|
+
const rest = keys.filter((k) => k !== key);
|
|
7298
|
+
rest.splice(Math.max(0, Math.min(rest.length, toIndex)), 0, key);
|
|
7299
|
+
applyFieldOrder(form, rest);
|
|
7281
7300
|
}
|
|
7282
7301
|
function reconcileFieldsFromContent(form, content) {
|
|
7283
7302
|
const formKey = form.getAttribute("data-ohw-key");
|
|
@@ -7303,14 +7322,18 @@ function reconcileFieldsFromContent(form, content) {
|
|
|
7303
7322
|
setFieldRequired(wrapper, spec.required);
|
|
7304
7323
|
setFieldPlaceholder(wrapper, spec.placeholder);
|
|
7305
7324
|
const label = fieldLabelOf(wrapper);
|
|
7306
|
-
if (label && spec.label) label.textContent = spec.label;
|
|
7325
|
+
if (label && spec.label) label.textContent = spec.label.replace(/\s*\*\s*$/, "").trimEnd();
|
|
7307
7326
|
syncRequiredMark(wrapper);
|
|
7308
7327
|
});
|
|
7309
7328
|
const wanted = new Set(stored.map((spec) => spec.key));
|
|
7310
7329
|
listFieldWrappers(form).forEach((wrapper) => {
|
|
7311
7330
|
if (!wanted.has(fieldKeyOf(wrapper))) wrapper.remove();
|
|
7312
7331
|
});
|
|
7313
|
-
|
|
7332
|
+
const currentOrder = listFieldWrappers(form).map(fieldKeyOf).join("\0");
|
|
7333
|
+
const storedOrder = stored.map((spec) => spec.key).join("\0");
|
|
7334
|
+
if (currentOrder !== storedOrder) {
|
|
7335
|
+
applyFieldOrder(form, stored.map((spec) => spec.key));
|
|
7336
|
+
}
|
|
7314
7337
|
}
|
|
7315
7338
|
|
|
7316
7339
|
// src/ui/form-field-toolbar.tsx
|
|
@@ -13387,8 +13410,10 @@ function getLinkHref3(el) {
|
|
|
13387
13410
|
}
|
|
13388
13411
|
function collectEditableNodes(extraContent, root = document) {
|
|
13389
13412
|
const isScoped = root !== document;
|
|
13390
|
-
const editableEls = Array.from(
|
|
13391
|
-
|
|
13413
|
+
const editableEls = Array.from(
|
|
13414
|
+
root.querySelectorAll('[data-ohw-editable]:not([data-ohw-editable="form"])')
|
|
13415
|
+
);
|
|
13416
|
+
if (isScoped && root instanceof HTMLElement && root.matches('[data-ohw-editable]:not([data-ohw-editable="form"])')) {
|
|
13392
13417
|
editableEls.unshift(root);
|
|
13393
13418
|
}
|
|
13394
13419
|
const nodes = editableEls.map((el) => {
|
|
@@ -15236,8 +15261,8 @@ function OhhwellsBridge() {
|
|
|
15236
15261
|
if (!wrapper || !form) return;
|
|
15237
15262
|
commitPlaceholderEdit(wrapper);
|
|
15238
15263
|
run(form, wrapper);
|
|
15239
|
-
beginPlaceholderEdit(wrapper);
|
|
15240
15264
|
persistFields(form);
|
|
15265
|
+
beginPlaceholderEdit(wrapper);
|
|
15241
15266
|
setFormPickRect(form.getBoundingClientRect());
|
|
15242
15267
|
},
|
|
15243
15268
|
[persistFields]
|
|
@@ -15595,6 +15620,12 @@ function OhhwellsBridge() {
|
|
|
15595
15620
|
}
|
|
15596
15621
|
el.removeAttribute("contenteditable");
|
|
15597
15622
|
el.removeAttribute("data-ohw-editing");
|
|
15623
|
+
const labelField = getFieldWrapper(el);
|
|
15624
|
+
if (labelField) {
|
|
15625
|
+
syncRequiredMark(labelField);
|
|
15626
|
+
const owner = labelField.closest('[data-ohw-editable="form"]');
|
|
15627
|
+
if (owner) persistFieldsRef.current(owner);
|
|
15628
|
+
}
|
|
15598
15629
|
activeElRef.current = null;
|
|
15599
15630
|
setNavGroupForceOpen(null, false);
|
|
15600
15631
|
setReorderHrefKey(null);
|
|
@@ -15750,6 +15781,12 @@ function OhhwellsBridge() {
|
|
|
15750
15781
|
}
|
|
15751
15782
|
el.removeAttribute("contenteditable");
|
|
15752
15783
|
el.removeAttribute("data-ohw-editing");
|
|
15784
|
+
const labelField = getFieldWrapper(el);
|
|
15785
|
+
if (labelField) {
|
|
15786
|
+
syncRequiredMark(labelField);
|
|
15787
|
+
const owner = labelField.closest('[data-ohw-editable="form"]');
|
|
15788
|
+
if (owner) persistFieldsRef.current(owner);
|
|
15789
|
+
}
|
|
15753
15790
|
activeElRef.current = null;
|
|
15754
15791
|
setMaxBadge(null);
|
|
15755
15792
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
@@ -16876,6 +16913,9 @@ function OhhwellsBridge() {
|
|
|
16876
16913
|
reconcileFooterOrderFromContent(content);
|
|
16877
16914
|
reconcileSocialsFromContent(content);
|
|
16878
16915
|
applySocialsDisplayFromContent(content);
|
|
16916
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
16917
|
+
listFieldWrappers(form).forEach(syncRequiredMark);
|
|
16918
|
+
});
|
|
16879
16919
|
} finally {
|
|
16880
16920
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
16881
16921
|
}
|
|
@@ -19003,6 +19043,13 @@ function OhhwellsBridge() {
|
|
|
19003
19043
|
if (brandKitRef.current) {
|
|
19004
19044
|
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
19005
19045
|
}
|
|
19046
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
19047
|
+
const formKey = formKeyOf(form);
|
|
19048
|
+
if (!formKey) return;
|
|
19049
|
+
const specs = readFieldsFromDom(form);
|
|
19050
|
+
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
19051
|
+
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
19052
|
+
});
|
|
19006
19053
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
19007
19054
|
};
|
|
19008
19055
|
const handleInsertSection = (e) => {
|