From 9aabb3a21da6832ac3134bc2515b5d37e0aeae22 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 11:38:55 +0000 Subject: [PATCH 01/15] cms-api: Add createDamVideoBlock factory The DamVideoBlock always stores everything it has (autoplay, loop, show controls, preview image), even for sites that don't use any of it. The Admin already has a createDamVideoBlock factory that hides unsupported options from the editor, but they stay part of the block's data and of the generated types. Add the API counterpart: options left out of `supports` are part of neither the block's data nor its input, so they don't show up in blocks.generated.ts and aren't stored, even when the Admin still submits them. DamVideoBlock is now created from the factory with both options supported and still exported next to it, so this is non-breaking. Since it occupies the block name DamVideo, a block created with the factory needs a name of its own, which is why the Admin factory gains a `name` option. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TsAAGJBYo4museJ93voh6i --- .changeset/admin-dam-video-block-name.md | 15 + .changeset/api-dam-video-block-factory.md | 25 ++ .../2-core-concepts/2-blocks/4-factories.mdx | 54 +++- .../src/blocks/createDamVideoBlock.test.tsx | 4 + .../src/blocks/createDamVideoBlock.tsx | 8 +- .../blocks/video/createDamVideoBlock.test.ts | 53 ++++ .../dam/blocks/video/createDamVideoBlock.ts | 264 ++++++++++++++++++ .../src/dam/blocks/video/dam-video.block.ts | 153 +--------- packages/api/cms-api/src/index.ts | 1 + 9 files changed, 415 insertions(+), 162 deletions(-) create mode 100644 .changeset/admin-dam-video-block-name.md create mode 100644 .changeset/api-dam-video-block-factory.md create mode 100644 packages/api/cms-api/src/dam/blocks/video/createDamVideoBlock.test.ts create mode 100644 packages/api/cms-api/src/dam/blocks/video/createDamVideoBlock.ts diff --git a/.changeset/admin-dam-video-block-name.md b/.changeset/admin-dam-video-block-name.md new file mode 100644 index 00000000000..c5a4d237b30 --- /dev/null +++ b/.changeset/admin-dam-video-block-name.md @@ -0,0 +1,15 @@ +--- +"@dextinity/cms-admin": minor +--- + +Add `name` option to `createDamVideoBlock` + +A `DamVideoBlock` created with a custom `supports` needs a name of its own, because `DamVideo` is taken by the exported `DamVideoBlock`. The name must match the name of the block created with `createDamVideoBlock` in the API. + +**Example** + +```tsx +import { createDamVideoBlock } from "@dextinity/cms-admin"; + +export const TeaserVideoBlock = createDamVideoBlock({ name: "TeaserVideo", supports: [] }); +``` diff --git a/.changeset/api-dam-video-block-factory.md b/.changeset/api-dam-video-block-factory.md new file mode 100644 index 00000000000..0b1a224e7eb --- /dev/null +++ b/.changeset/api-dam-video-block-factory.md @@ -0,0 +1,25 @@ +--- +"@dextinity/cms-api": minor +--- + +Add `createDamVideoBlock` factory + +The `DamVideoBlock` always stores everything it has (autoplay, loop, show controls, preview image), even for sites that don't use any of it. `createDamVideoBlock` is the API counterpart of the Admin factory of the same name: pass what the site supports via `supports`, anything left out is part of neither the block's data nor its input, so it doesn't show up in `blocks.generated.ts` and isn't stored. + +`supports` takes: + +- `"controls"` — autoplay, loop and show controls, offered together +- `"previewImage"` — the poster image + +`DamVideoBlock` is now created from the factory with both supported and still exported next to it, so this is non-breaking. Since it occupies the block name `DamVideo`, a block created with the factory needs a name of its own. + +**Example** + +```ts +import { createDamVideoBlock } from "@dextinity/cms-api"; + +// For a site that only reads the video's URL +export const TeaserVideoBlock = createDamVideoBlock({ supports: [] }, "TeaserVideo"); +``` + +Use the same `supports` and the same name for the Admin block. diff --git a/docs/docs/2-core-concepts/2-blocks/4-factories.mdx b/docs/docs/2-core-concepts/2-blocks/4-factories.mdx index d4bdcefb037..5d4a7d55763 100644 --- a/docs/docs/2-core-concepts/2-blocks/4-factories.mdx +++ b/docs/docs/2-core-concepts/2-blocks/4-factories.mdx @@ -227,30 +227,62 @@ export const FullWidthImageBlock = createCompositeBlock({ }); ``` -## DamVideoBlock (Admin only) +## DamVideoBlock The DamVideoBlock factory creates a block for a video from the DAM. -Use `supports` to restrict what editors can set besides the video file itself: +Use `supports` to restrict what the block offers besides the video file itself: - `"controls"`: The playback options autoplay, loop and show controls. - `"previewImage"`: The poster image shown before playback. Both are supported by default. -`@dextinity/cms-admin` exports a ready-made `DamVideoBlock` created with those defaults, use the `createDamVideoBlock` factory to change them: +`@dextinity/cms-api` and `@dextinity/cms-admin` export a ready-made `DamVideoBlock` created with those defaults. +Use the `createDamVideoBlock` factory when a site doesn't need all of them, for instance an app integration that only reads the video's URL. -```tsx title="DamVideoBlock.tsx" +Give the block a name of its own — `DamVideo` is taken by the exported `DamVideoBlock` — and use that same name and the same `supports` in both the API and the Admin. + +### API + +Use the `createDamVideoBlock` factory: + +```ts title="teaser-video.block.ts" +import { createDamVideoBlock } from "@dextinity/cms-api"; + +// For a site that only reads the video's URL +export const TeaserVideoBlock = createDamVideoBlock({ supports: [] }, "TeaserVideo"); +``` + +Unsupported options are part of neither the block's data nor its input, so they don't show up in `blocks.generated.ts` and aren't stored. + +### Admin + +Use the `createDamVideoBlock` factory: + +```tsx title="TeaserVideoBlock.tsx" import { createDamVideoBlock } from "@dextinity/cms-admin"; -// For a site that renders no poster image -export const DamVideoBlock = createDamVideoBlock({ supports: ["controls"] }); +export const TeaserVideoBlock = createDamVideoBlock({ name: "TeaserVideo", supports: [] }); ``` -:::note +Unsupported options are hidden from the editor. +Their stored values are kept as long as the API block supports them, so widening `supports` later brings them back. -Leaving out an option only hides it from the editor. -Values that are already stored are kept as they are. -The preview image in particular stays part of the block's data either way, since the API's child block is non-nullable. -::: +### Site + +Render the video with the fields the block supports: + +```tsx title="TeaserVideoBlock.tsx" +import { PropsWithData } from "@dextinity/site-nextjs"; +import { TeaserVideoBlockData } from "@src/blocks.generated"; + +export function TeaserVideoBlock({ data: { damFile } }: PropsWithData) { + if (!damFile) { + return null; + } + + return