@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.
- package/README.md +332 -309
- package/dist/editor/editorBridge.js +127 -50
- package/dist/editor/editorBridge.js.map +1 -1
- package/dist/index.js +59 -13
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/package.json +90 -90
- package/src/components/DcsReviewShowcase.vue +321 -326
- package/src/components/PreviewRibbon.vue +612 -612
- package/src/components/ResponsiveImage.vue +55 -55
- package/src/composables/index.ts +10 -10
- package/src/composables/useMediaCarousel.ts +158 -158
- package/src/composables/useReleaseNotes.ts +153 -153
- package/src/composables/useResponsiveImage.ts +85 -85
- package/src/composables/useReviewContent.ts +150 -92
- package/src/composables/useSEO.ts +387 -387
- package/src/composables/useSiteVersion.ts +123 -123
- package/src/composables/useTextContent.ts +297 -297
|
@@ -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
|
|
857
|
-
outline-offset:
|
|
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
|
|
1035
|
+
if (data && typeof data === "object" && "key" in data) {
|
|
961
1036
|
const d = data;
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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
|
}
|