@duffcloudservices/cms 0.3.12 → 0.3.14

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.
@@ -18,9 +18,6 @@ function getTextKey(el) {
18
18
  function textKeySelector(key) {
19
19
  return `[data-text-key="${key}"], [data-dcs-text="${key}"]`;
20
20
  }
21
- function reviewSelector(key) {
22
- return `[data-dcs-reviews="${key}"]`;
23
- }
24
21
  var editorActive = false;
25
22
  var bridgeInitialized = false;
26
23
  var activeEditElement = null;
@@ -33,6 +30,8 @@ var imageEditIconElements = [];
33
30
  var imageEditIconTargets = [];
34
31
  var reviewEditIconElement = null;
35
32
  var reviewEditIconTarget = null;
33
+ var managedFormEditIconElement = null;
34
+ var managedFormEditIconTarget = null;
36
35
  var editingEnabled = true;
37
36
  var originalTextValues = /* @__PURE__ */ new Map();
38
37
  var sectionResizeObserver = null;
@@ -239,6 +238,33 @@ function applyEditorToElements() {
239
238
  removeReviewEditIcon();
240
239
  });
241
240
  });
241
+ const managedFormElements = document.querySelectorAll("[data-form-key]");
242
+ managedFormElements.forEach((formEl) => {
243
+ formEl.classList.add("dcs-managed-form");
244
+ if (!initializedManagedFormElements.has(formEl)) {
245
+ initializedManagedFormElements.add(formEl);
246
+ const openManagedForm = (e) => {
247
+ if (!editingEnabled) return;
248
+ e.preventDefault();
249
+ e.stopPropagation();
250
+ e.stopImmediatePropagation();
251
+ postToParent("dcs:managed-form-click", {
252
+ formId: formEl.dataset.formKey ?? null
253
+ });
254
+ };
255
+ formEl.addEventListener("click", openManagedForm, true);
256
+ formEl.addEventListener("dblclick", openManagedForm, true);
257
+ formEl.addEventListener("mouseenter", () => {
258
+ if (activeEditElement) return;
259
+ showManagedFormEditIcon(formEl);
260
+ });
261
+ formEl.addEventListener("mouseleave", (e) => {
262
+ const related = e.relatedTarget;
263
+ if (related && (related.classList?.contains("dcs-managed-form-edit-icon") || related.closest?.(".dcs-managed-form-edit-icon"))) return;
264
+ removeManagedFormEditIcon();
265
+ });
266
+ }
267
+ });
242
268
  const sections = document.querySelectorAll("[data-section]");
243
269
  sections.forEach((el) => {
244
270
  if (initializedSections.has(el)) return;
@@ -317,23 +343,6 @@ function applyEditorToElements() {
317
343
  summaryEl?.classList.add("dcs-blog-metadata");
318
344
  }
319
345
  }
320
- const managedFormElements = document.querySelectorAll("[data-form-key]");
321
- managedFormElements.forEach((formEl) => {
322
- formEl.classList.add("dcs-managed-form");
323
- if (initializedManagedFormElements.has(formEl)) return;
324
- initializedManagedFormElements.add(formEl);
325
- const openManagedForm = (e) => {
326
- if (!editingEnabled) return;
327
- e.preventDefault();
328
- e.stopPropagation();
329
- e.stopImmediatePropagation();
330
- postToParent("dcs:managed-form-click", {
331
- formId: formEl.dataset.formKey ?? null
332
- });
333
- };
334
- formEl.addEventListener("click", openManagedForm, true);
335
- formEl.addEventListener("dblclick", openManagedForm, true);
336
- });
337
346
  }
338
347
  function handleTextKeyDblClick(e) {
339
348
  if (!editingEnabled) return;
@@ -553,6 +562,53 @@ function removeReviewEditIcon() {
553
562
  }
554
563
  reviewEditIconTarget = null;
555
564
  }
565
+ function createManagedFormEditIcon() {
566
+ const icon = document.createElement("button");
567
+ icon.className = "dcs-managed-form-edit-icon";
568
+ icon.setAttribute("type", "button");
569
+ icon.setAttribute("title", "Manage form");
570
+ icon.setAttribute("aria-label", "Manage form fields");
571
+ icon.innerHTML = `
572
+ <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
573
+ <path d="M3 6h18"/><path d="M7 12h10"/><path d="M10 18h4"/>
574
+ </svg>
575
+ <span class="dcs-managed-form-edit-label">Manage form</span>
576
+ `;
577
+ icon.addEventListener("click", (e) => {
578
+ e.preventDefault();
579
+ e.stopPropagation();
580
+ e.stopImmediatePropagation();
581
+ if (!managedFormEditIconTarget) return;
582
+ postToParent("dcs:managed-form-click", {
583
+ formId: managedFormEditIconTarget.dataset.formKey ?? null
584
+ });
585
+ removeManagedFormEditIcon();
586
+ }, true);
587
+ icon.addEventListener("mouseleave", (e) => {
588
+ const related = e.relatedTarget;
589
+ if (related && managedFormEditIconTarget && (related === managedFormEditIconTarget || managedFormEditIconTarget.contains(related))) return;
590
+ removeManagedFormEditIcon();
591
+ });
592
+ return icon;
593
+ }
594
+ function showManagedFormEditIcon(el) {
595
+ if (!editingEnabled) return;
596
+ if (!managedFormEditIconElement) {
597
+ managedFormEditIconElement = createManagedFormEditIcon();
598
+ document.body.appendChild(managedFormEditIconElement);
599
+ }
600
+ managedFormEditIconTarget = el;
601
+ const rect = el.getBoundingClientRect();
602
+ managedFormEditIconElement.style.top = `${rect.top + scrollY + 8}px`;
603
+ managedFormEditIconElement.style.left = `${rect.left + scrollX + 8}px`;
604
+ managedFormEditIconElement.style.display = "flex";
605
+ }
606
+ function removeManagedFormEditIcon() {
607
+ if (managedFormEditIconElement) {
608
+ managedFormEditIconElement.style.display = "none";
609
+ }
610
+ managedFormEditIconTarget = null;
611
+ }
556
612
  function createImageEditIcon(label) {
557
613
  const icon = document.createElement("button");
558
614
  icon.className = "dcs-image-edit-icon";
@@ -766,6 +822,46 @@ function injectEditorStyles() {
766
822
  transform: scale(1.1);
767
823
  }
768
824
 
825
+ .dcs-managed-form-edit-icon {
826
+ position: absolute;
827
+ z-index: 99999;
828
+ display: none;
829
+ align-items: center;
830
+ justify-content: center;
831
+ gap: 4px;
832
+ min-width: 24px;
833
+ height: 24px;
834
+ padding: 0 8px;
835
+ margin: 0;
836
+ border: 1.5px solid hsl(271 91% 65%);
837
+ border-radius: 4px;
838
+ background: hsl(271 91% 65% / 0.12);
839
+ backdrop-filter: blur(4px);
840
+ color: hsl(271 91% 65%);
841
+ cursor: pointer;
842
+ pointer-events: auto;
843
+ transition: background 0.15s, transform 0.1s;
844
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12);
845
+ font-size: 11px;
846
+ font-weight: 600;
847
+ line-height: 1;
848
+ white-space: nowrap;
849
+ }
850
+
851
+ .dcs-managed-form-edit-icon:hover {
852
+ background: hsl(271 91% 65% / 0.24);
853
+ transform: scale(1.03);
854
+ }
855
+
856
+ .dcs-managed-form-edit-icon svg {
857
+ display: block;
858
+ flex-shrink: 0;
859
+ }
860
+
861
+ .dcs-managed-form-edit-label {
862
+ white-space: nowrap;
863
+ }
864
+
769
865
  /* Floating image edit icon button \u2014 green to distinguish from text (blue) and array (violet) */
770
866
  .dcs-image-edit-icon {
771
867
  position: absolute;
@@ -853,33 +949,11 @@ function injectEditorStyles() {
853
949
  }
854
950
 
855
951
  [data-form-key].dcs-managed-form:hover {
856
- outline: 2px solid hsl(271 91% 65% / 0.65) !important;
857
- outline-offset: 10px;
952
+ outline: 2px dashed hsl(271 91% 65% / 0.65) !important;
953
+ outline-offset: 4px;
858
954
  background-color: hsl(271 91% 65% / 0.04);
859
955
  }
860
956
 
861
- [data-form-key].dcs-managed-form::after {
862
- content: 'Click to manage form';
863
- position: absolute;
864
- top: -28px;
865
- left: 8px;
866
- font-size: 11px;
867
- font-weight: 600;
868
- color: hsl(271 91% 65%);
869
- background: hsl(271 91% 65% / 0.12);
870
- border: 1px solid hsl(271 91% 65% / 0.3);
871
- padding: 2px 8px;
872
- border-radius: 4px;
873
- opacity: 0;
874
- transition: opacity 0.2s;
875
- pointer-events: none;
876
- white-space: nowrap;
877
- }
878
-
879
- [data-form-key].dcs-managed-form:hover::after {
880
- opacity: 1;
881
- }
882
-
883
957
  /* Blog metadata (title / summary) \u2014 click to edit */
884
958
  .dcs-blog-metadata {
885
959
  cursor: pointer;
@@ -940,6 +1014,7 @@ function handleMessage(event) {
940
1014
  removeEditIcon();
941
1015
  removeArrayEditIcon();
942
1016
  removeReviewEditIcon();
1017
+ removeManagedFormEditIcon();
943
1018
  removeAllImageEditIcons();
944
1019
  document.querySelectorAll(".dcs-editable").forEach((el) => {
945
1020
  el.classList.remove("dcs-editable");
@@ -957,13 +1032,15 @@ function handleMessage(event) {
957
1032
  }
958
1033
  break;
959
1034
  case "dcs:update-reviews":
960
- if (data && typeof data === "object" && "key" in data && "html" in data) {
1035
+ if (data && typeof data === "object" && "key" in data) {
961
1036
  const d = data;
962
- const reviewEl = document.querySelector(reviewSelector(d.key));
963
- if (reviewEl) {
964
- reviewEl.innerHTML = d.html;
965
- scheduleRediscovery();
966
- }
1037
+ globalThis.dispatchEvent(new CustomEvent("dcs:reviews-updated", {
1038
+ detail: {
1039
+ key: d.key,
1040
+ reviews: Array.isArray(d.reviews) ? d.reviews : null
1041
+ }
1042
+ }));
1043
+ scheduleRediscovery();
967
1044
  }
968
1045
  break;
969
1046
  }