You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Plugins cannot register widget components. Two gaps, both in core:
Registration. getWidgetComponents() in packages/core/src/widgets/components.ts:103 returns only coreWidgetComponents. The comment on line 101 reads: "For now, only returns core components. Plugin widgets will be added later."
Render resolution. packages/core/src/components/WidgetRenderer.astro:19 uses a hardcoded componentMap with static imports. Even if a plugin registered a definition, there is no way to resolve a plugin-provided Astro component at render time.
Issue #343 documents this, with the same two-part framing and 3 thumbs-up.
Use case: a plugin that ships reusable widget components (donation button, social feed, newsletter signup) that admins can place in any widget area through the admin UI, without the theme author importing and mapping each plugin component.
Precedent
Portable Text already solves this problem. Plugins export blockComponents from a componentsEntry module, generateBlockComponentsModule in packages/core/src/astro/integration/virtual-modules.ts:339 concatenates them into a virtual module at build time, and <PortableText> consumes the merged map.
Widgets can use the same shape.
Proposed API
Plugins export a widgetComponents record from their existing componentsEntry module:
packages/core/src/astro/integration/virtual-modules.ts. Add generateWidgetComponentsModule(descriptors) next to generateBlockComponentsModule at line 339. Same filter on componentsEntry, same import { widgetComponents as wc0 } from ... shape, exports pluginWidgetComponents.
packages/core/src/astro/integration/index.ts. Register the new virtual module alongside the block components virtual module.
packages/core/src/widgets/components.ts. getWidgetComponents() merges coreWidgetComponents with plugin-contributed WidgetComponentDef[] pulled from active plugin descriptors.
packages/core/src/components/WidgetRenderer.astro. Replace the hardcoded componentMap with a merged map of core components plus virtual:emdash/plugin-widget-components. Resolve widget.componentId against the merged map.
packages/core/src/plugins/types.ts. Add widgetDefinitions?: WidgetComponentDef[] to the trusted plugin descriptor.
Rules
Plugin widget ids are namespaced with the plugin slug. core: is reserved.
Collision at build time throws. A plugin cannot shadow a core widget id, and two plugins cannot register the same id.
Empty plugin set still compiles (virtual module emits export const pluginWidgetComponents = {};).
Sandboxed plugins
Out of scope for this Discussion. The proposal covers trusted plugins only, which matches the current componentsEntry + blockComponents story. Sandboxed widget components would require serializing component modules across the sandbox boundary, which is a separate design question.
Open questions
Prop validation. Widget component props are defined as a PropDef map today, consumed by the admin editor dropdown. Should plugin-contributed PropDef maps go through a runtime zod-style check, or trust the trusted-plugin contract as is?
Collision policy. Throw at build, or log a warning and last-write-wins? Build-time throw is safer but harsher on DX when two dev plugins conflict.
Component ergonomics. Is there appetite for sugar that lets a plugin declare both the component and the definition in one place, e.g. a defineWidget() helper co-located with the Astro component?
Happy to open a PR once this is approved. Closes #343 if shipped.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Problem
Plugins cannot register widget components. Two gaps, both in core:
getWidgetComponents()inpackages/core/src/widgets/components.ts:103returns onlycoreWidgetComponents. The comment on line 101 reads: "For now, only returns core components. Plugin widgets will be added later."packages/core/src/components/WidgetRenderer.astro:19uses a hardcodedcomponentMapwith static imports. Even if a plugin registered a definition, there is no way to resolve a plugin-provided Astro component at render time.Issue #343 documents this, with the same two-part framing and 3 thumbs-up.
Use case: a plugin that ships reusable widget components (donation button, social feed, newsletter signup) that admins can place in any widget area through the admin UI, without the theme author importing and mapping each plugin component.
Precedent
Portable Text already solves this problem. Plugins export
blockComponentsfrom acomponentsEntrymodule,generateBlockComponentsModuleinpackages/core/src/astro/integration/virtual-modules.ts:339concatenates them into a virtual module at build time, and<PortableText>consumes the merged map.Widgets can use the same shape.
Proposed API
Plugins export a
widgetComponentsrecord from their existingcomponentsEntrymodule:Plugins also contribute widget definitions (id, label, props schema) via a new field on the plugin descriptor:
Integration sites
packages/core/src/astro/integration/virtual-modules.ts. AddgenerateWidgetComponentsModule(descriptors)next togenerateBlockComponentsModuleat line 339. Same filter oncomponentsEntry, sameimport { widgetComponents as wc0 } from ...shape, exportspluginWidgetComponents.packages/core/src/astro/integration/index.ts. Register the new virtual module alongside the block components virtual module.packages/core/src/widgets/components.ts.getWidgetComponents()mergescoreWidgetComponentswith plugin-contributedWidgetComponentDef[]pulled from active plugin descriptors.packages/core/src/components/WidgetRenderer.astro. Replace the hardcodedcomponentMapwith a merged map of core components plusvirtual:emdash/plugin-widget-components. Resolvewidget.componentIdagainst the merged map.packages/core/src/plugins/types.ts. AddwidgetDefinitions?: WidgetComponentDef[]to the trusted plugin descriptor.Rules
core:is reserved.export const pluginWidgetComponents = {};).Sandboxed plugins
Out of scope for this Discussion. The proposal covers trusted plugins only, which matches the current
componentsEntry+blockComponentsstory. Sandboxed widget components would require serializing component modules across the sandbox boundary, which is a separate design question.Open questions
PropDefmap today, consumed by the admin editor dropdown. Should plugin-contributedPropDefmaps go through a runtime zod-style check, or trust the trusted-plugin contract as is?defineWidget()helper co-located with the Astro component?Happy to open a PR once this is approved. Closes #343 if shipped.
Beta Was this translation helpful? Give feedback.
All reactions