@duffcloudservices/cms 0.3.15 → 0.3.17

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 CHANGED
@@ -61,11 +61,15 @@ export default defineConfig({
61
61
 
62
62
  ```bash
63
63
  # .env
64
- VITE_SITE_SLUG=your-site-slug
65
-
66
- # Optional: for runtime overrides (premium tier)
64
+ # For runtime overrides (premium tier): the API base URL only.
67
65
  VITE_API_BASE_URL=https://portal.duffcloudservices.com
68
66
  VITE_TEXT_OVERRIDE_MODE=commit # 'commit' (default) or 'runtime'
67
+
68
+ # Deprecated: the site is now resolved server-side from the request Host
69
+ # (or the dedicated Container App's DCS_SITE_SLUG). VITE_SITE_SLUG is no
70
+ # longer placed in request URLs; it is optional and used only as a local
71
+ # cache-key hint. Safe to omit.
72
+ # VITE_SITE_SLUG=your-site-slug
69
73
  ```
70
74
 
71
75
  ### 3. Use Composables
@@ -310,6 +314,41 @@ For DCS-managed sites, `src/editor/editorBridge.ts` is the shared
310
314
  discovery/runtime layer that turns site DOM markers into portal editing
311
315
  entry points.
312
316
 
317
+ ### Managed background images
318
+
319
+ For customer-site hero, CTA, footer, card, staff, and gallery images that need editor image replacement, prefer the exported `ManagedImage` component over CSS-only `background-image` or hardcoded image arrays.
320
+
321
+ ```vue
322
+ <script setup lang="ts">
323
+ import ManagedImage from '@duffcloudservices/cms/managed-image'
324
+ </script>
325
+
326
+ <template>
327
+ <ManagedImage
328
+ page-slug="home"
329
+ image-key="hero.image.url"
330
+ alt-key="hero.image.alt"
331
+ fallback-src="/images/hero.jpg"
332
+ fallback-alt="Clinic hero"
333
+ context="hero"
334
+ class="h-full w-full object-cover"
335
+ />
336
+ </template>
337
+ ```
338
+
339
+ Add the URL and alt keys to `.dcs/content.yaml` using CDN URLs for committed content:
340
+
341
+ ```yaml
342
+ pages:
343
+ home:
344
+ hero.image.url: https://files.duffcloudservices.com/content/site-slug/assets/example.jpg
345
+ hero.image.alt: Clinic hero
346
+ ```
347
+
348
+ `ManagedImage` resolves build-time/runtime content with `useTextContent`, renders a real `<picture>/<img>` target, applies responsive CDN variants through `useResponsiveImage`, and emits `data-dcs-image-key`, `data-dcs-image-url`, and `data-dcs-image-alt` on the actual `<img>`. This lets the visual editor open image management for the asset and lets snapshot capture wait on an actual image before `full-page.png`.
349
+
350
+ For repeated galleries or cards, use indexed keys such as `gallery.item-0.image.url` and `gallery.item-0.image.alt`, then pass those keys through the rendered item. Do not make editable images CSS-only backgrounds; if a design needs background behavior, render a real managed image layer behind the content.
351
+
313
352
  Current first-party surfaces:
314
353
 
315
354
  - **Managed forms** — discovers `[data-form-key]`, reports
@@ -660,6 +660,9 @@ function createImageEditIcon(label) {
660
660
  });
661
661
  return icon;
662
662
  }
663
+ function getManagedImageKey(img) {
664
+ return img.dataset.dcsImageKey || img.closest("[data-dcs-image-key]")?.dataset.dcsImageKey || null;
665
+ }
663
666
  function showImageEditIcons(images) {
664
667
  if (!editingEnabled) return;
665
668
  if (imageEditIconTargets.length === images.length && images.every((img, i) => imageEditIconTargets[i] === img)) return;
@@ -685,6 +688,7 @@ function showImageEditIcons(images) {
685
688
  imageAlt: img.alt ?? null,
686
689
  imageWidth: img.naturalWidth,
687
690
  imageHeight: img.naturalHeight,
691
+ imageKey: getManagedImageKey(img),
688
692
  sectionId: sectionEl?.dataset.section ?? null,
689
693
  sectionLabel: sectionEl?.dataset.sectionLabel ?? null
690
694
  });
@@ -1130,12 +1134,14 @@ function initEditorBridge() {
1130
1134
  imageAlt: topImage?.alt ?? null,
1131
1135
  imageWidth: topImage?.naturalWidth ?? null,
1132
1136
  imageHeight: topImage?.naturalHeight ?? null,
1137
+ imageKey: topImage ? getManagedImageKey(topImage) : null,
1133
1138
  // All images at click point (for overlapping image scenarios like before/after sliders)
1134
1139
  images: allImages.length > 1 ? allImages.map((img) => ({
1135
1140
  imageUrl: img.currentSrc ?? img.src,
1136
1141
  imageAlt: img.alt ?? null,
1137
1142
  imageWidth: img.naturalWidth,
1138
- imageHeight: img.naturalHeight
1143
+ imageHeight: img.naturalHeight,
1144
+ imageKey: getManagedImageKey(img)
1139
1145
  })) : null
1140
1146
  });
1141
1147
  }, true);