Merge pull request #1465 from umbraco/feature/input-manifest
Feature: Manifest input
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# Manifest Picker Example
|
||||
|
||||
This example demonstrates the Manifest picker input UI.
|
||||
15
src/Umbraco.Web.UI.Client/examples/manifest-picker/index.ts
Normal file
15
src/Umbraco.Web.UI.Client/examples/manifest-picker/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { ManifestDashboard } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<ManifestDashboard> = [
|
||||
{
|
||||
type: 'dashboard',
|
||||
name: 'Example Manifest Picker Dashboard',
|
||||
alias: 'example.dashboard.manifestPicker',
|
||||
element: () => import('./manifest-picker-dashboard.js'),
|
||||
weight: 1000,
|
||||
meta: {
|
||||
label: 'Manifest Picker example',
|
||||
pathname: 'example-manifest-picker',
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,97 @@
|
||||
import { css, html, customElement, state, when, nothing } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbInputManifestElement } from '@umbraco-cms/backoffice/components';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
|
||||
@customElement('example-manifest-picker-dashboard')
|
||||
export class ExampleManifestPickerDashboard extends UmbLitElement {
|
||||
#options: Array<Option> = [];
|
||||
|
||||
@state()
|
||||
private _selectedExtensionType: string = 'collectionView';
|
||||
|
||||
@state()
|
||||
private _selectedManifest: string = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
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,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
#onSelect(event: UUISelectEvent) {
|
||||
this._selectedManifest = '';
|
||||
this._selectedExtensionType = event.target.value as string;
|
||||
}
|
||||
|
||||
#onChange(event: { target: UmbInputManifestElement }) {
|
||||
const selectedManifest = event.target.value;
|
||||
this._selectedManifest = selectedManifest?.value ?? '';
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
<umb-property-layout label="Select a extension type...">
|
||||
<uui-select
|
||||
slot="editor"
|
||||
label="Select type..."
|
||||
placeholder="Select type..."
|
||||
.options=${this.#options}
|
||||
@change=${this.#onSelect}></uui-select>
|
||||
</umb-property-layout>
|
||||
${when(
|
||||
this._selectedExtensionType,
|
||||
() => html`
|
||||
<umb-property-layout label="Selected extension type" description=${this._selectedExtensionType}>
|
||||
<div slot="editor">
|
||||
<umb-input-manifest
|
||||
.extensionType=${this._selectedExtensionType}
|
||||
@change=${this.#onChange}></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>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: var(--uui-size-layout-1);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default ExampleManifestPickerDashboard;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'example-manifest-picker-dashboard': ExampleManifestPickerDashboard;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ export * from './input-date/index.js';
|
||||
export * from './input-dropdown/index.js';
|
||||
export * from './input-eye-dropper/index.js';
|
||||
export * from './input-list-base/index.js';
|
||||
export * from './input-manifest/index.js';
|
||||
export * from './input-multi-url/index.js';
|
||||
export * from './input-number-range/index.js';
|
||||
export * from './input-radio-button-list/index.js';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './input-manifest.element.js';
|
||||
@@ -0,0 +1,85 @@
|
||||
import { html, customElement, property, css } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbChangeEvent } from '@umbraco-cms/backoffice/event';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { UMB_ITEM_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
@customElement('umb-input-manifest')
|
||||
export class UmbInputManifestElement extends UmbLitElement {
|
||||
#extensions: Array<typeof umbExtensionsRegistry.MANIFEST_TYPES> = [];
|
||||
|
||||
#extensionType?: string;
|
||||
@property({ type: String, attribute: 'extension-type' })
|
||||
public set extensionType(value: string | undefined) {
|
||||
this.#extensionType = value;
|
||||
this.#observeExtensions();
|
||||
}
|
||||
public get extensionType(): string | undefined {
|
||||
return this.#extensionType;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
value?: typeof UMB_ITEM_PICKER_MODAL.VALUE;
|
||||
|
||||
@property({ type: Number })
|
||||
max = Infinity;
|
||||
|
||||
#observeExtensions() {
|
||||
if (!this.#extensionType) return;
|
||||
this.observe(umbExtensionsRegistry.byType(this.#extensionType), (extensions) => {
|
||||
this.#extensions = extensions.sort((a, b) => a.type.localeCompare(b.type) || a.alias.localeCompare(b.alias));
|
||||
});
|
||||
}
|
||||
|
||||
async #onClick() {
|
||||
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
|
||||
const modalContext = modalManager.open(this, UMB_ITEM_PICKER_MODAL, {
|
||||
data: {
|
||||
headline: `${this.localize.term('general_choose')}...`,
|
||||
items: this.#extensions
|
||||
.filter((ext) => ext.type === this.extensionType)
|
||||
.map((ext) => ({
|
||||
label: ext.name,
|
||||
value: ext.alias,
|
||||
description: ext.alias,
|
||||
icon: (ext as any).meta?.icon, // HACK: Ugly way to get the icon. [LK]
|
||||
})),
|
||||
},
|
||||
});
|
||||
|
||||
const modalValue = await modalContext.onSubmit();
|
||||
|
||||
if (!modalValue) return;
|
||||
|
||||
this.value = modalValue;
|
||||
|
||||
this.dispatchEvent(new UmbChangeEvent());
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-button
|
||||
label=${this.localize.term('general_choose')}
|
||||
look="placeholder"
|
||||
color="default"
|
||||
@click=${this.#onClick}></uui-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbInputManifestElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-input-manifest': UmbInputManifestElement;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user