@dotcms/vue 1.5.5 → 1.7.0

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
@@ -14,12 +14,14 @@ The `@dotcms/vue` SDK is the dotCMS official Vue 3 library. It empowers Vue deve
14
14
  - [Quickstart: Render a Page with dotCMS](#quickstart-render-a-page-with-dotcms)
15
15
  - [Example Project](#example-project-)
16
16
  - [SDK Reference](#sdk-reference)
17
+ - [createDotCMSVue / useDotCMSClient](#createdotcmsvue--usedotcmsclient)
17
18
  - [DotCMSLayoutBody](#dotcmslayoutbody)
18
19
  - [DotCMSEditableText](#dotcmseditabletext)
19
20
  - [DotCMSBlockEditorRenderer](#dotcmsblockeditorrenderer)
20
21
  - [DotCMSShow](#dotcmsshow)
21
22
  - [useEditableDotCMSPage](#useeditabledotcmspage)
22
23
  - [useDotCMSShowWhen](#usedotcmsshowwhen)
24
+ - [createDotCMSImageLoader](#createdotcmsimageloader)
23
25
  - [toPlain](#toplain)
24
26
  - [Troubleshooting](#troubleshooting)
25
27
  - [Common Issues & Solutions](#common-issues--solutions)
@@ -95,17 +97,67 @@ Requires **Vue 3.4+** (declared as a peer dependency). The install also brings i
95
97
 
96
98
  ### dotCMS Client Configuration
97
99
 
100
+ Install the dotCMS Vue plugin once at startup. It builds the client and provides
101
+ it to the whole app, so components retrieve it with `useDotCMSClient()` instead
102
+ of importing a module-level singleton — the Vue analog of Angular's
103
+ `provideDotCMSClient`.
104
+
105
+ ```ts
106
+ // main.ts
107
+ import { createApp } from 'vue';
108
+ import { createDotCMSVue } from '@dotcms/vue';
109
+
110
+ import App from './App.vue';
111
+
112
+ const app = createApp(App);
113
+
114
+ app.use(
115
+ createDotCMSVue({
116
+ dotcmsUrl: import.meta.env.VITE_DOTCMS_HOST,
117
+ authToken: import.meta.env.VITE_DOTCMS_AUTH_TOKEN, // Optional for public content
118
+ siteId: import.meta.env.VITE_DOTCMS_SITE_ID, // Optional site identifier/name
119
+ requestOptions: {
120
+ // The UVE needs fresh data so in-context edits are reflected immediately.
121
+ cache: 'no-cache'
122
+ }
123
+ })
124
+ );
125
+
126
+ app.mount('#app');
127
+ ```
128
+
129
+ Then, in any component:
130
+
131
+ ```vue
132
+ <script setup lang="ts">
133
+ import { useDotCMSClient } from '@dotcms/vue';
134
+
135
+ const client = useDotCMSClient();
136
+ const { pageAsset } = await client.page.get('/');
137
+ </script>
138
+ ```
139
+
140
+ > **Using the client outside a component?** Code that runs before/outside a
141
+ > component `setup` — e.g. a Vue Router page loader — can't call
142
+ > `useDotCMSClient()`. Keep a reference to the plugin and read its `.client`:
143
+ >
144
+ > ```ts
145
+ > export const dotCMSVue = createDotCMSVue({ ...config });
146
+ > export const dotCMSClient = dotCMSVue.client; // same instance the plugin provides
147
+ > ```
148
+
149
+ If you prefer to manage the client yourself, `createDotCMSClient` from
150
+ `@dotcms/client` is still available and works with all of this SDK's components
151
+ and composables — the plugin is a convenience, not a requirement.
152
+
98
153
  ```typescript
99
154
  import { createDotCMSClient } from '@dotcms/client';
100
155
 
101
156
  export const dotCMSClient = createDotCMSClient({
102
157
  dotcmsUrl: import.meta.env.VITE_DOTCMS_HOST,
103
- authToken: import.meta.env.VITE_DOTCMS_AUTH_TOKEN, // Optional for public content
104
- siteId: import.meta.env.VITE_DOTCMS_SITE_ID, // Optional site identifier/name
105
- requestOptions: {
106
- // The UVE needs fresh data so in-context edits are reflected immediately.
107
- cache: 'no-cache'
108
- }
158
+ authToken: import.meta.env.VITE_DOTCMS_AUTH_TOKEN,
159
+ siteId: import.meta.env.VITE_DOTCMS_SITE_ID,
160
+ requestOptions: { cache: 'no-cache' }
109
161
  });
110
162
  ```
111
163
 
@@ -224,6 +276,26 @@ Looking to get started quickly? Our [Vue.js starter project](https://github.com/
224
276
 
225
277
  All components, composables and utilities are imported from `@dotcms/vue`.
226
278
 
279
+ ### createDotCMSVue / useDotCMSClient
280
+
281
+ `createDotCMSVue(config)` returns a Vue plugin that builds a dotCMS client and
282
+ provides it app-wide. `useDotCMSClient()` retrieves that client from any
283
+ component. See [dotCMS Client Configuration](#dotcms-client-configuration) for
284
+ the full setup.
285
+
286
+ ```ts
287
+ import { createDotCMSVue } from '@dotcms/vue';
288
+
289
+ const plugin = createDotCMSVue({ dotcmsUrl, authToken /* …DotCMSClientConfig */ });
290
+ app.use(plugin);
291
+ ```
292
+
293
+ | Export | Signature | Description |
294
+ | ------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
295
+ | `createDotCMSVue(config)` | `(config: DotCMSClientConfig) => DotCMSVuePlugin` | Vue plugin for `app.use()`. `config` is the same object accepted by `createDotCMSClient`. |
296
+ | `useDotCMSClient()` | `() => DotCMSClient` | Returns the provided client. Throws if the plugin was not installed. Call it inside `setup`. |
297
+ | `DotCMSVuePlugin.client` | `DotCMSClient` | The created client instance, for use outside components (e.g. router loaders). |
298
+
227
299
  ### DotCMSLayoutBody
228
300
 
229
301
  `DotCMSLayoutBody` renders the layout for a dotCMS page (rows → columns → containers → contentlets), dispatching each contentlet to the mapped component. It supports both production and development modes.
@@ -281,6 +353,28 @@ const components = {
281
353
  > [!TIP]
282
354
  > Always use the exact content type variable name from dotCMS as the key. You can find it in the Content Types section of your dotCMS admin panel.
283
355
 
356
+ #### Per-contentlet slots
357
+
358
+ Beyond mapping by content type, you can override a **specific** contentlet by
359
+ its `identifier` using a named slot: `#contentlet-<identifier>`. When present,
360
+ the slot renders instead of the mapped component — the Vue analog of the React
361
+ SDK's `slots` prop, useful for one-off custom markup or a pre-rendered node.
362
+
363
+ The contentlet is exposed as the slot's scope prop.
364
+
365
+ ```vue
366
+ <template>
367
+ <DotCMSLayoutBody :page="page" :components="components">
368
+ <!-- Renders instead of the Blog component for this one contentlet -->
369
+ <template #contentlet-a1b2c3d4="{ contentlet }">
370
+ <FeaturedBlog :blog="contentlet" />
371
+ </template>
372
+ </DotCMSLayoutBody>
373
+ </template>
374
+ ```
375
+
376
+ Contentlets without a matching slot fall back to the `components` mapping as usual.
377
+
284
378
  ### DotCMSEditableText
285
379
 
286
380
  `DotCMSEditableText` enables inline editing of a single text field in dotCMS. Inside the UVE in edit mode it mounts a TinyMCE editor; everywhere else it renders the field's current value.
@@ -330,6 +424,20 @@ const props = defineProps<{ contentlet: DotCMSBasicContentlet }>();
330
424
  | `style` | `CSSProperties` | ❌ | - | Inline styles for the container |
331
425
  | `isDevMode` | `boolean` | ❌ | `false` | When `true`, shows a visible message for invalid/unknown blocks |
332
426
 
427
+ > **`className`/`style` vs native `class`/`style`:** the `className` and `style`
428
+ > props mirror the React SDK so the same code shape works across frameworks. This
429
+ > component renders one of two root elements (an error box or the content
430
+ > container), so Vue's automatic attribute fallthrough does **not** apply — a
431
+ > native `class="prose"` on the tag will not reach the container. Use the
432
+ > `className` and `style` props to style the container:
433
+ >
434
+ > ```vue
435
+ > <DotCMSBlockEditorRenderer
436
+ > :blocks="contentlet.body"
437
+ > class-name="prose max-w-none"
438
+ > :style="{ marginTop: '1rem' }" />
439
+ > ```
440
+
333
441
  #### Usage
334
442
 
335
443
  A custom renderer is a Vue component that receives the block as a `node` prop and the rendered children in its default `<slot />`.
@@ -465,6 +573,46 @@ const isEditMode = useDotCMSShowWhen(UVE_MODE.EDIT); // Readonly<Ref<boolean>>
465
573
  </template>
466
574
  ```
467
575
 
576
+ ### createDotCMSImageLoader
577
+
578
+ `createDotCMSImageLoader(dotcmsUrl?)` returns a function that turns a dotCMS asset identifier (or path) into an optimized image URL via the dotCMS image API (the `/dA/` route, which handles resizing and optimization). It's the Vue analog of Angular's `provideDotCMSImageLoader` — Vue has no `IMAGE_LOADER` token, so you call the returned function directly.
579
+
580
+ Absolute `http(s)://…` URLs are returned unchanged, so mixing dotCMS assets with external/stock imagery just works.
581
+
582
+ | Argument | Type | Required | Default | Description |
583
+ | ----------- | -------- | -------- | ------- | ---------------------------------------------------------------------------------------- |
584
+ | `dotcmsUrl` | `string` | ❌ | `''` | Base URL of your dotCMS instance. Omit (empty) for site-relative `/dA/…` behind a proxy. |
585
+
586
+ The returned loader is `(src: string, options?) => string`, where `options` is `{ width?, quality?, languageId? }` (`quality` defaults to `50`, `languageId` to `'1'`).
587
+
588
+ ```ts
589
+ import { createDotCMSImageLoader } from '@dotcms/vue';
590
+
591
+ // Absolute (production)
592
+ const image = createDotCMSImageLoader(import.meta.env.VITE_DOTCMS_HOST);
593
+ image(contentlet.inode, { width: 800 });
594
+ // → https://demo.dotcms.com/dA/<inode>/800w/50q?language_id=1
595
+
596
+ // Site-relative (dev proxy) — omit the host so the Vite /dA proxy handles it
597
+ const proxied = createDotCMSImageLoader();
598
+ proxied(contentlet.inode, { width: 800 }); // → /dA/<inode>/800w/50q?language_id=1
599
+ ```
600
+
601
+ ```vue
602
+ <script setup lang="ts">
603
+ import { createDotCMSImageLoader } from '@dotcms/vue';
604
+ import type { DotCMSBasicContentlet } from '@dotcms/types';
605
+
606
+ const props = defineProps<{ contentlet: DotCMSBasicContentlet }>();
607
+
608
+ const image = createDotCMSImageLoader(import.meta.env.VITE_DOTCMS_HOST);
609
+ </script>
610
+
611
+ <template>
612
+ <img :src="image(contentlet.inode, { width: 800 })" :alt="contentlet.title" />
613
+ </template>
614
+ ```
615
+
468
616
  ### toPlain
469
617
 
470
618
  `toPlain` deep-unwraps a Vue reactive value (refs / reactive proxies) into a plain, structured-clone-safe object. Use it before passing reactive data to UVE editor actions (`editContentlet`, `enableBlockEditorInline`, …) from `@dotcms/uve`, which send their argument to the editor via `postMessage`.
package/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
+ export { createDotCMSVue, useDotCMSClient, DOTCMS_CLIENT } from './lib/client/dotcms-client.plugin';
2
+ export type { DotCMSClient, DotCMSVuePlugin } from './lib/client/dotcms-client.plugin';
1
3
  export { useEditableDotCMSPage } from './lib/composables/useEditableDotCMSPage';
2
4
  export { useDotCMSShowWhen } from './lib/composables/useDotCMSShowWhen';
3
5
  export { toPlain } from './lib/utils/toPlain';
6
+ export { createDotCMSImageLoader } from './lib/utils/imageLoader';
7
+ export type { DotCMSImageLoader, DotCMSImageLoaderOptions } from './lib/utils/imageLoader';
4
8
  export { default as DotCMSShow } from './lib/components/DotCMSShow/DotCMSShow.vue';
5
9
  export { default as DotCMSLayoutBody } from './lib/components/DotCMSLayoutBody/DotCMSLayoutBody.vue';
6
10
  export { default as DotCMSEditableText } from './lib/components/DotCMSEditableText/DotCMSEditableText.vue';