umbraco-manifest-picker by umbraco/umbraco-cms-backoffice-skills
npx skills add https://github.com/umbraco/umbraco-cms-backoffice-skills --skill umbraco-manifest-picker<umb-input-manifest> 组件提供了一个选择器 UI,用于从 Umbraco 扩展注册表中选择已注册的扩展。它允许用户从任何扩展类型(工作区、仪表板、属性编辑器等)中进行选择,并返回选定的清单。这对于用户需要引用其他扩展的配置 UI 非常有用。
在实施前请务必获取最新文档:
Umbraco 源代码中包含一个工作示例:
位置 : /Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/manifest-picker/
此示例演示了一个允许用户按类型浏览和选择扩展的仪表板。
扩展注册表 : 用于理解扩展如何注册
umbraco-extension-registry广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Umbraco 元素 : 用于创建选择器 UI
umbraco-umbraco-elementimport { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
@customElement('my-manifest-picker-example')
export class MyManifestPickerExampleElement extends UmbLitElement {
@state()
private _selectedManifest = '';
#onChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Select a workspace">
<div slot="editor">
<umb-input-manifest
.extensionType=${'workspace'}
@change=${this.#onChange}
></umb-input-manifest>
</div>
</umb-property-layout>
${this._selectedManifest
? html`<p>Selected: <code>${this._selectedManifest}</code></p>`
: ''}
</uui-box>
`;
}
}
import { html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
interface Option {
name: string;
value: string;
selected: boolean;
}
@customElement('my-extension-browser')
export class MyExtensionBrowserElement extends UmbLitElement {
#options: Option[] = [];
@state()
private _selectedExtensionType = 'dashboard';
@state()
private _selectedManifest = '';
constructor() {
super();
// Build list of available extension types from registry
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
const types = [...new Set(extensions.map((x) => x.type))];
this.#options = types.sort().map((x) => ({
name: x,
value: x,
selected: x === this._selectedExtensionType,
}));
});
}
#onTypeSelect(event: UUISelectEvent) {
this._selectedManifest = '';
this._selectedExtensionType = event.target.value as string;
}
#onManifestChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Extension Type">
<uui-select
slot="editor"
label="Select type"
placeholder="Select type..."
.options=${this.#options}
@change=${this.#onTypeSelect}
></uui-select>
</umb-property-layout>
${when(
this._selectedExtensionType,
() => html`
<umb-property-layout
label="Select Extension"
description="Pick a ${this._selectedExtensionType}"
>
<div slot="editor">
<umb-input-manifest
.extensionType=${this._selectedExtensionType}
@change=${this.#onManifestChange}
></umb-input-manifest>
</div>
</umb-property-layout>
`,
() => nothing
)}
${when(
this._selectedManifest,
() => html`
<umb-property-layout label="Selected Manifest">
<div slot="editor">
<code>${this._selectedManifest}</code>
</div>
</umb-property-layout>
`,
() => nothing
)}
</uui-box>
`;
}
}
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// In your element constructor
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
// Get unique extension types
const types = [...new Set(extensions.map((x) => x.type))];
console.log('Available types:', types);
// Filter by type
const dashboards = extensions.filter((x) => x.type === 'dashboard');
console.log('Dashboards:', dashboards);
// Get extension by alias
const specific = extensions.find((x) => x.alias === 'Umb.Dashboard.Welcome');
console.log('Specific extension:', specific);
});
| 类型 | 描述 |
|---|---|
dashboard | 区域仪表板 |
workspace | 实体工作区 |
workspaceView | 工作区内的视图 |
workspaceAction | 工作区操作按钮 |
propertyEditorUi | 属性编辑器 UI |
propertyEditorSchema | 属性编辑器架构 |
entityAction | 上下文菜单操作 |
tree | 导航树 |
treeItem | 树项渲染器 |
section | 后台区域 |
sectionView | 区域视图 |
headerApp | 标题栏应用 |
modal | 模态对话框 |
condition | 扩展条件 |
| 属性 | 类型 | 描述 |
|---|---|---|
extensionType | string | 要从中选择的扩展类型 |
value | `ManifestBase | undefined` |
| 事件 | 详情 | 描述 |
|---|---|---|
change | { target: UmbInputManifestElement } | 当选择发生变化时触发 |
#onManifestChange(event: { target: UmbInputManifestElement }) {
const manifest = event.target.value;
if (manifest) {
console.log('Alias:', manifest.alias);
console.log('Name:', manifest.name);
console.log('Type:', manifest.type);
console.log('Full manifest:', manifest);
}
}
_selectedManifestvalue 是否存在<umb-property-layout> 中以获得一致的样式就是这样!始终获取最新文档,保持示例简洁,生成完整的工作代码。
每周安装量
75
仓库
GitHub 星标数
17
首次出现
2026年2月4日
安全审计
安装于
github-copilot55
cursor25
opencode23
codex23
gemini-cli21
amp21
The <umb-input-manifest> component provides a picker UI for selecting registered extensions from the Umbraco extension registry. It allows users to pick from any extension type (workspaces, dashboards, property editors, etc.) and returns the selected manifest. This is useful for configuration UIs where users need to reference other extensions.
Always fetch the latest docs before implementing:
The Umbraco source includes a working example:
Location : /Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/manifest-picker/
This example demonstrates a dashboard that lets users browse and select extensions by type.
Extension Registry : For understanding how extensions are registered
umbraco-extension-registryUmbraco Element : For creating picker UIs
umbraco-umbraco-elementimport { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
@customElement('my-manifest-picker-example')
export class MyManifestPickerExampleElement extends UmbLitElement {
@state()
private _selectedManifest = '';
#onChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Select a workspace">
<div slot="editor">
<umb-input-manifest
.extensionType=${'workspace'}
@change=${this.#onChange}
></umb-input-manifest>
</div>
</umb-property-layout>
${this._selectedManifest
? html`<p>Selected: <code>${this._selectedManifest}</code></p>`
: ''}
</uui-box>
`;
}
}
import { html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
interface Option {
name: string;
value: string;
selected: boolean;
}
@customElement('my-extension-browser')
export class MyExtensionBrowserElement extends UmbLitElement {
#options: Option[] = [];
@state()
private _selectedExtensionType = 'dashboard';
@state()
private _selectedManifest = '';
constructor() {
super();
// Build list of available extension types from registry
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
const types = [...new Set(extensions.map((x) => x.type))];
this.#options = types.sort().map((x) => ({
name: x,
value: x,
selected: x === this._selectedExtensionType,
}));
});
}
#onTypeSelect(event: UUISelectEvent) {
this._selectedManifest = '';
this._selectedExtensionType = event.target.value as string;
}
#onManifestChange(event: { target: UmbInputManifestElement }) {
const selectedManifest = event.target.value;
this._selectedManifest = selectedManifest?.value ?? '';
}
override render() {
return html`
<uui-box>
<umb-property-layout label="Extension Type">
<uui-select
slot="editor"
label="Select type"
placeholder="Select type..."
.options=${this.#options}
@change=${this.#onTypeSelect}
></uui-select>
</umb-property-layout>
${when(
this._selectedExtensionType,
() => html`
<umb-property-layout
label="Select Extension"
description="Pick a ${this._selectedExtensionType}"
>
<div slot="editor">
<umb-input-manifest
.extensionType=${this._selectedExtensionType}
@change=${this.#onManifestChange}
></umb-input-manifest>
</div>
</umb-property-layout>
`,
() => nothing
)}
${when(
this._selectedManifest,
() => html`
<umb-property-layout label="Selected Manifest">
<div slot="editor">
<code>${this._selectedManifest}</code>
</div>
</umb-property-layout>
`,
() => nothing
)}
</uui-box>
`;
}
}
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// In your element constructor
this.observe(umbExtensionsRegistry.extensions, (extensions) => {
// Get unique extension types
const types = [...new Set(extensions.map((x) => x.type))];
console.log('Available types:', types);
// Filter by type
const dashboards = extensions.filter((x) => x.type === 'dashboard');
console.log('Dashboards:', dashboards);
// Get extension by alias
const specific = extensions.find((x) => x.alias === 'Umb.Dashboard.Welcome');
console.log('Specific extension:', specific);
});
| Type | Description |
|---|---|
dashboard | Section dashboards |
workspace | Entity workspaces |
workspaceView | Views within workspaces |
workspaceAction | Workspace action buttons |
propertyEditorUi | Property editor UIs |
propertyEditorSchema | Property editor schemas |
| Property | Type | Description |
|---|---|---|
extensionType | string | The type of extension to pick from |
value | `ManifestBase | undefined` |
| Event | Detail | Description |
|---|---|---|
change | { target: UmbInputManifestElement } | Fired when selection changes |
#onManifestChange(event: { target: UmbInputManifestElement }) {
const manifest = event.target.value;
if (manifest) {
console.log('Alias:', manifest.alias);
console.log('Name:', manifest.name);
console.log('Type:', manifest.type);
console.log('Full manifest:', manifest);
}
}
_selectedManifest when type changesvalue exists before accessing properties<umb-property-layout> for consistent stylingThat's it! Always fetch fresh docs, keep examples minimal, generate complete working code.
Weekly Installs
75
Repository
GitHub Stars
17
First Seen
Feb 4, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot55
cursor25
opencode23
codex23
gemini-cli21
amp21
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
120,000 周安装
entityAction | Context menu actions |
tree | Navigation trees |
treeItem | Tree item renderers |
section | Backoffice sections |
sectionView | Section views |
headerApp | Header bar apps |
modal | Modal dialogs |
condition | Extension conditions |