-import {EditorUiContext, EditorUiElement, EditorContainerUiElement} from "./core";
+import {
+ EditorUiContext,
+ EditorUiElement,
+ EditorContainerUiElement,
+ EditorUiBuilderDefinition,
+ isUiBuilderDefinition
+} from "./core";
import {el} from "../../helpers";
+import {uniqueId} from "../../../services/util";
export interface EditorFormFieldDefinition {
label: string;
valuesByLabel: Record<string, string>
}
+interface EditorFormTabDefinition {
+ label: string;
+ contents: EditorFormFieldDefinition[];
+}
+
export interface EditorFormDefinition {
submitText: string;
action: (formData: FormData, context: EditorUiContext) => Promise<boolean>;
- fields: EditorFormFieldDefinition[];
+ fields: (EditorFormFieldDefinition|EditorUiBuilderDefinition)[];
}
export class EditorFormField extends EditorUiElement {
protected onCancel: null|(() => void) = null;
constructor(definition: EditorFormDefinition) {
- super(definition.fields.map(fieldDefinition => new EditorFormField(fieldDefinition)));
+ let children: (EditorFormField|EditorUiElement)[] = definition.fields.map(fieldDefinition => {
+ if (isUiBuilderDefinition(fieldDefinition)) {
+ return fieldDefinition.build();
+ }
+ return new EditorFormField(fieldDefinition)
+ });
+
+ super(children);
this.definition = definition;
}
}
protected getFieldByName(name: string): EditorFormField|null {
- for (const child of this.children as EditorFormField[]) {
- if (child.getName() === name) {
- return child;
+
+ const search = (children: EditorUiElement[]): EditorFormField|null => {
+ for (const child of children) {
+ if (child instanceof EditorFormField && child.getName() === name) {
+ return child;
+ } else if (child instanceof EditorContainerUiElement) {
+ const matchingChild = search(child.getChildren());
+ if (matchingChild) {
+ return matchingChild;
+ }
+ }
}
- }
- return null;
+ return null;
+ };
+
+ return search(this.getChildren());
}
protected buildDOM(): HTMLElement {
return form;
}
+}
+
+export class EditorFormTab extends EditorContainerUiElement {
+
+ protected definition: EditorFormTabDefinition;
+ protected fields: EditorFormField[];
+ protected id: string;
+
+ constructor(definition: EditorFormTabDefinition) {
+ const fields = definition.contents.map(fieldDef => new EditorFormField(fieldDef));
+ super(fields);
+
+ this.definition = definition;
+ this.fields = fields;
+ this.id = uniqueId();
+ }
+
+ public getLabel(): string {
+ return this.getContext().translate(this.definition.label);
+ }
+
+ public getId(): string {
+ return this.id;
+ }
+
+ protected buildDOM(): HTMLElement {
+ return el(
+ 'div',
+ {
+ class: 'editor-form-tab-content',
+ role: 'tabpanel',
+ id: `editor-tabpanel-${this.id}`,
+ 'aria-labelledby': `editor-tab-${this.id}`,
+ },
+ this.fields.map(f => f.getDOMElement())
+ );
+ }
+}
+export class EditorFormTabs extends EditorContainerUiElement {
+
+ protected definitions: EditorFormTabDefinition[] = [];
+ protected tabs: EditorFormTab[] = [];
+
+ constructor(definitions: EditorFormTabDefinition[]) {
+ const tabs: EditorFormTab[] = definitions.map(d => new EditorFormTab(d));
+ super(tabs);
+
+ this.definitions = definitions;
+ this.tabs = tabs;
+ }
+
+ protected buildDOM(): HTMLElement {
+ const controls: HTMLElement[] = [];
+ const contents: HTMLElement[] = [];
+
+ const selectTab = (tabIndex: number) => {
+ for (let i = 0; i < controls.length; i++) {
+ controls[i].setAttribute('aria-selected', (i === tabIndex) ? 'true' : 'false');
+ }
+ for (let i = 0; i < contents.length; i++) {
+ contents[i].hidden = !(i === tabIndex);
+ }
+ };
+
+ for (const tab of this.tabs) {
+ const button = el('button', {
+ class: 'editor-form-tab-control',
+ type: 'button',
+ role: 'tab',
+ id: `editor-tab-${tab.getId()}`,
+ 'aria-controls': `editor-tabpanel-${tab.getId()}`
+ }, [tab.getLabel()]);
+ contents.push(tab.getDOMElement());
+ controls.push(button);
+
+ button.addEventListener('click', event => {
+ selectTab(controls.indexOf(button));
+ });
+ }
+
+ selectTab(0);
+
+ return el('div', {class: 'editor-form-tab-container'}, [
+ el('div', {class: 'editor-form-tab-controls'}, controls),
+ el('div', {class: 'editor-form-tab-contents'}, contents),
+ ]);
+ }
}
\ No newline at end of file