mirror of
https://github.com/flarum/framework.git
synced 2025-04-25 14:14:03 +08:00
feat: support custom reusable setting components for buildSettingComponent
(#3494)
This commit is contained in:
parent
824fb2feff
commit
293e8ab8b6
@ -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<CustomAttrs extends IPageAttrs = IPageAt
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of extension-defined custom setting components to be available through
|
||||
* {@link AdminPage.buildSettingComponent}.
|
||||
*
|
||||
* The ItemList key represents the value for `type` to be provided when calling
|
||||
* {@link AdminPage.buildSettingComponent}. Other attributes passed are provided
|
||||
* as arguments to the function added to the ItemList.
|
||||
*
|
||||
* ItemList priority has no effect here.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* extend(AdminPage.prototype, 'customSettingComponents', function (items) {
|
||||
* // You can access the AdminPage instance with `this` to access its `settings` property.
|
||||
*
|
||||
* // Prefixing the key with your extension ID is recommended to avoid collisions.
|
||||
* items.add('my-ext.setting-component', (attrs) => {
|
||||
* return (
|
||||
* <div className={attrs.className}>
|
||||
* <label>{attrs.label}</label>
|
||||
* {attrs.help && <p class="helpText">{attrs.help}</p>}
|
||||
*
|
||||
* My setting component!
|
||||
* </div>
|
||||
* );
|
||||
* })
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
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<CustomAttrs extends IPageAttrs = IPageAt
|
||||
return entry.call(this);
|
||||
}
|
||||
|
||||
const customSettingComponents = this.customSettingComponents();
|
||||
|
||||
const { setting, help, type, label, ...componentAttrs } = entry;
|
||||
|
||||
const value = this.setting(setting)();
|
||||
@ -262,8 +306,10 @@ export default abstract class AdminPage<CustomAttrs extends IPageAttrs = IPageAt
|
||||
{...otherAttrs}
|
||||
/>
|
||||
);
|
||||
} 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 = <textarea id={inputId} aria-describedby={helpTextId} bidi={this.setting(setting)} {...componentAttrs} />;
|
||||
|
Loading…
x
Reference in New Issue
Block a user