diff --git a/framework/core/js/src/admin/components/AdminPage.tsx b/framework/core/js/src/admin/components/AdminPage.tsx index 39f8fe2951..71517bd461 100644 --- a/framework/core/js/src/admin/components/AdminPage.tsx +++ b/framework/core/js/src/admin/components/AdminPage.tsx @@ -11,6 +11,7 @@ import saveSettings from '../utils/saveSettings'; import AdminHeader from './AdminHeader'; import generateElementId from '../utils/generateElementId'; import ColorPreviewInput from '../../common/components/ColorPreviewInput'; +import ItemList from '../../common/utils/ItemList'; export interface AdminHeaderOptions { title: Mithril.Children; @@ -57,7 +58,7 @@ export type HTMLInputTypes = | 'url' | 'week'; -interface CommonSettingsItemOptions extends Mithril.Attributes { +export interface CommonSettingsItemOptions extends Mithril.Attributes { setting: string; label: Mithril.Children; help?: Mithril.Children; @@ -112,6 +113,11 @@ export interface ColorPreviewSettingComponentOptions extends CommonSettingsItemO type: typeof ColorPreviewSettingType; } +export interface CustomSettingComponentOptions extends CommonSettingsItemOptions { + type: string; + [key: string]: unknown; +} + /** * All valid options for the setting component builder. */ @@ -120,7 +126,8 @@ export type SettingsComponentOptions = | SwitchSettingComponentOptions | SelectSettingComponentOptions | TextareaSettingComponentOptions - | ColorPreviewSettingComponentOptions; + | ColorPreviewSettingComponentOptions + | CustomSettingComponentOptions; /** * Valid attrs that can be returned by the `headerInfo` function @@ -185,6 +192,41 @@ export default abstract class AdminPage { + * return ( + *
+ * + * {attrs.help &&

{attrs.help}

} + * + * My setting component! + *
+ * ); + * }) + * }) + * ``` + */ + customSettingComponents(): ItemList<(attributes: CommonSettingsItemOptions) => Mithril.Children> { + const items = new ItemList<(attributes: CommonSettingsItemOptions) => Mithril.Children>(); + + return items; + } + /** * `buildSettingComponent` takes a settings object and turns it into a component. * Depending on the type of input, you can set the type to 'bool', 'select', or @@ -228,6 +270,8 @@ export default abstract class AdminPage ); + } else if (customSettingComponents.has(type)) { + return customSettingComponents.get(type)({ setting, help, label, ...componentAttrs }); } else { - componentAttrs.className = classList(['FormControl', componentAttrs.className]); + componentAttrs.className = classList('FormControl', componentAttrs.className); if ((TextareaSettingTypes as readonly string[]).includes(type)) { settingElement =