@brightcove/components-embed-code-modal

中文文档
1.3.0发布于 2026/11/07TypeScriptCommonJS近 30 天下载 3177

Embed Code Modal used for publishing videos

原始使用文档
文档目录6 节
  1. Usage
  2. To build
  3. Development
  4. Integrating with modules
  5. SPA entry ( @brightcove/components-embed-code-modal/spa )
  6. Peer dependency note

studio-components-embed-code-modal

Usage

To build

npm run build

Development

To run this module for development clone the repo and run

npm install
npm run demo

Sign in to Studio with a Studio UI (Marketing Studio) enabled account. If necessary, click the Profile icon and then the Switch to Studio link.

Navigate to https://studio.brightcove.com/products/videocloud/media/dev/sdk:remote.

The App runs at https://localhost.brightcove.com:12345/js/app.js as described in Creating a Module

The results of the API call to retrieve players will depend on sign in permissions.

Integrating with modules

This component was built for Marketing Studio modules, such as: studio-media-module-four.

Below you will find instructions on how to use the component inside of these modules.

Install the package

npm i @brightcove/components-embed-code-modal

Import the component and required types

import {
  EmbedCodeModal,
  VideoPayload,
} from '@brightcove/components-embed-code-modal';

VideoPayload is a TypeScript interface which describes an Object that will be accepted as a prop for your <EmbedCodeModal> component.

Here is an overview of the VideoPayload interface:

  videoId: string; // Video id, required
  videoName: string; // Video title, required
  accountId: string; // BC account id, required
  posterUrl?: string; // Video poster url, not required
  duration: number; // Video duration in seconds, required

Component Props

The component currently takes in two props:

  language?: 'en' | 'es' | 'fr' | 'ko' | 'ja' | 'zh';
  video: VideoPayload;
  • The VideoPayload interface is exported by the component.
  • The language prop is optional, if not passed, the component will get the language from StudioModule.config.lang. Currently, we use this for testing in our local sandbox.

Wiring Up Through the Module

The modal will only render once the video prop has been passed into the EmbedCodeModal component.

In order to keep our components fully decoupled, we look to our parent module's for wiring up our components together.

Here's an example of how the the Media Module's VideoLibrary is wiring up two separate components in order to open the EmbedCodeModal:

const [embedVideo, setEmbedVideo] = useState<VideoPayload>(null);

const handleAction = (event: DataGridAction) => {
  if (event.type === DataGridEvents.GetCode) {
    // build VideoPayload for EmbedCodeModal component here
    // this way we are completely de-coupling the EmbedCodeModal from the module
    const { payload: video } = event;
    setEmbedVideo({
      videoId: video.id,
      videoName: video.name,
      accountId: video.account_id,
      posterUrl: video?.images?.poster?.src,
      duration: video.duration,
    });
  }
};
  1. The Media Module imports both the DataGrid & EmbedCodeModal components. Neither component are coded to be aware of the other.
  2. The DataGrid component dispatches the GetCode action to tell its parent module: I would like to retrieve some code, go and do that, however your module handles this action.
  3. The Media Module handles this action by creating a new payload with the video information handed off by the DataGrid. It knows that it wants to open the EmbedCodeModal, so it will look to the VideoPayload interface to create what it needs.
  4. This video object is set to the module's local state.
  5. Within our JSX, our EmbedCodeModal should be passing this video object to the component: <EmbedCodeModal video={embedVideo} />
  6. Anytime that embedVideo updates in the module - it triggers the Embed Code Modal to open.

The reasons we have wired things up this way has been to achieve our goals of keeping micro-frontends decoupled. The EmbedCodeModal & the DataGrid are not interacting directly with each other. The DataGrid is providing video data that is being used, but when it triggers a Get Code event, it can just send an entire Video Object along with it. It doesn't need to know exactly what information the Embed Code Modal needs in order to successfully operate.

Likewise, the Embed Code Modal could be triggered by any other number of interfaces, and this abstraction helps us better prepare for the integrations coming in our future.

SPA entry (@brightcove/components-embed-code-modal/spa)

Studio SPA documents load no module-core, so window.StudioModule does not exist there. The ./spa entry exposes the LIVE and PROJECT surfaces, and takes every capability from the caller instead of a global:

import {
  SpaEmbedCodeModal,
  EmbedCodeModalTypes,
} from '@brightcove/components-embed-code-modal/spa';
import type {
  LivePayload,
  EmbedCodeModalRuntime,
} from '@brightcove/components-embed-code-modal/spa';

<SpaEmbedCodeModal
  data={livePayload}
  embedCodeModalType={EmbedCodeModalTypes.LIVE}
  runtime={{
    api: {
      config: { publisherId, api }, // the module API config
      execute: (descriptor, options) => studioApiCall(descriptor, options),
    },
    environment, // session.product.env — decides the player origins
    locale, // seeds the package-private i18next instance
    favoritePlayerId, // optional; absent falls back to 'default'
    onNotify, // optional; { variant, title?, message }
    shortenUrl, // cookie-authenticated /shortener/shorten adapter
  }}
/>;

The PROJECT surface renders the legacy project embed modal (Blue Steel presentation, not prism-core) and takes the same runtime plus three required capabilities:

<SpaEmbedCodeModal
  embedCodeModalType={EmbedCodeModalTypes.PROJECT}
  data={projectPayload}
  runtime={{
    api, // as above
    environment,
    locale,
    favoritePlayerId,
    shortenUrl,
    hasPublishingRole, // getCurrentUserAccount().roles includes PUBLISHING
    playersModuleUrl, // e.g. `${product.path}/players`
    onNotify, // required: creation failures and copy feedback
  }}
/>;

A PROJECT mount fetches the players itself and only offers the players whose master-branch configuration carries the interactivity plugin. When none does, it shows the create-player flow if hasPublishingRole is set, and the activation copy linking to playersModuleUrl otherwise. Creating posts the interactivity player and refetches the list, and it never publishes.

SpaEmbedCodeModal accepts SpaEmbedCodeModalEntryProps, the union of the LIVE and PROJECT props. SpaEmbedCodeModalProps remains the LIVE props, so an existing Omit<SpaEmbedCodeModalProps, 'runtime'> keeps every LIVE key: Omit over a union collapses to the keys its members share.

What the entry owns and what it does not:

  • Owns the players query (a per-mount react-query v3 client with the legacy retry: 3 / staleTime: 0 semantics), the i18next instance (six catalogues, registered under the embed-code-modal namespace only) and the CSS (scoped under .embed-code-modal at build time).
  • Never reads window.StudioModule, window.brightcove, the default i18next singleton, or the shell's query client. Two mounted instances with different runtimes cannot share configuration, players or callbacks.
  • The legacy EmbedCodeModal export is unchanged and still reads the Studio document. The two entries are separate webpack outputs (build/index.js and spa.js), so the legacy-only modules are absent from the SPA file rather than merely unused. npm run build fails if that isolation regresses. The PROJECT surface shares its presentation with the legacy root through ProjectModalView, and @brightcove/studio-components is required by the SPA bundle rather than banned: it is already an external peer, so it adds no bytes.

spa.js, spa.js.map and build/ are build outputs; they are produced by npm run build and shipped in the published package.

data must be a stable reference: a new object reopens the modal, so an inline object literal on every render makes a closed modal reopen immediately.

Peer dependency note

The SPA entry keeps react-query v3 at runtime (per-instance client), which is why react-query remains a peer dependency of this package, as it is for the legacy entry. A consumer of ./spa must have react-query@^3.38.0 installed.

版本与发布记录

@brightcove/components-embed-code-modal 共发布 70 个版本,首次发布于 2021/12/21;过去 12 个月发布了 14 个版本。

版本发布日期距今
1.3.0latest2026/11/072 天前
1.2.12026/11/035 天前
1.2.02026/11/035 天前
1.1.32026/09/261 个月前
1.1.22026/08/142 个月前
1.1.12026/07/283 个月前

关于 @brightcove/components-embed-code-modal 的常见问题

@brightcove/components-embed-code-modal 是什么?

Embed Code Modal used for publishing videos

如何安装 @brightcove/components-embed-code-modal?

在项目目录运行 npm install @brightcove/components-embed-code-modal,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^17.0.2 || ^18.0.0)、i18next(>=21)、react-dom(^17.0.2 || ^18.0.0)、react-query(^3.38.0)、react-i18next(>=11)、@brightcove/prism-core(^1.25.1)、@brightcove/studio-icons(*)、@brightcove/player-embed-code(^2.0.4)、@brightcove/studio-components(*)、@brightcove/react-player-loader(^1.4.2)、@brightcove/studio-api-services(^7.0.0 || ^8.0.0)、@brightcove/studio-design-tokens(*)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@brightcove/components-embed-code-modal 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@brightcove/components-embed-code-modal 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@brightcove/components-embed-code-modal 可以商用吗?

@brightcove/components-embed-code-modal 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@brightcove/components-embed-code-modal 的下载量有多少?

根据 npm 官方下载统计,@brightcove/components-embed-code-modal 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,177 次,日均约 106 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@brightcove/components-embed-code-modal 还在维护吗?

最新版本 1.3.0 发布于 2026/11/07(2 天前);至今共发布 70 个版本,其中过去 12 个月发布了 14 个;首次发布于 2021/12/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。