Create settings builder
This commit is contained in:
parent
53b4bed979
commit
00b5d800a0
|
@ -26,6 +26,7 @@ import SearchInput from "@ui/settings/components/search";
|
|||
import SliderInput from "@ui/settings/components/slider";
|
||||
import SwitchInput from "@ui/settings/components/switch";
|
||||
import TextInput from "@ui/settings/components/textbox";
|
||||
import SettingGroup from "@ui/settings/group";
|
||||
|
||||
const bounded = new Map();
|
||||
const PluginAPI = new AddonAPI(PluginManager);
|
||||
|
@ -79,6 +80,7 @@ export default class BdApi {
|
|||
get SliderInput() {return SliderInput;},
|
||||
get SwitchInput() {return SwitchInput;},
|
||||
get TextInput() {return TextInput;},
|
||||
get SettingGroup() {return SettingGroup;}
|
||||
};
|
||||
Net = {fetch};
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import Modals from "@ui/modals";
|
|||
import Toasts from "@ui/toasts";
|
||||
import Notices from "@ui/notices";
|
||||
import Tooltip from "@ui/tooltip";
|
||||
import Group, {buildSetting} from "@ui/settings/group";
|
||||
import React from "@modules/react";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -137,6 +139,64 @@ const UI = {
|
|||
if (data.error) throw new Error(data.error);
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a single setting wrapped in a setting item that has a name and note.
|
||||
* The shape of the object should match the props of the component you want to render, check the
|
||||
* `BdApi.Components` section for details. Shown below are ones common to all setting types.
|
||||
* @param {object} setting
|
||||
* @param {string} setting.id Identifier to used for callbacks
|
||||
* @param {string} setting.name Visual name to display
|
||||
* @param {string} setting.note Visual description to display
|
||||
* @param {any} setting.value Current value of the setting
|
||||
* @param {CallableFunction} [setting.onChange] Callback when the value changes (only argument is new value)
|
||||
* @param {boolean} [setting.disabled] Whether this setting is disabled
|
||||
|
||||
* @returns A SettingItem with a an input as the child
|
||||
*/
|
||||
buildSetting(setting) {
|
||||
return buildSetting(setting);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a settings panel (react element) based on json-like data.
|
||||
*
|
||||
* The `settings` array here is an array of the same settings types described in `buildSetting` above.
|
||||
* However, this API allows one additional setting "type" called `group`. This has the same properties
|
||||
* as the React Component found under the `Components` API.
|
||||
*
|
||||
* `onChange` will always be given 3 arguments: group id, setting id, and setting value. In the case
|
||||
* that you have settings on the "root" of the panel, the group id is `null`.
|
||||
*
|
||||
* `onDrawerToggle` is given 2 arguments: group id, and the current shown state. You can use this to
|
||||
* save drawer states.
|
||||
*
|
||||
* `getDrawerState` is given 2 arguments: group id, and the default shown state. You can use this to
|
||||
* recall a saved drawer state.
|
||||
*
|
||||
* @param {object} props
|
||||
* @param {Array<object>} props.settings Array of settings to show
|
||||
* @param {CallableFunction} props.onChange Function called on every change
|
||||
* @param {CallableFunction} [props.onDrawerToggle] Optionally used to save drawer states
|
||||
* @param {CallableFunction} [props.getDrawerState] Optionially used to recall drawer states
|
||||
* @returns React element usable for a settings panel
|
||||
*/
|
||||
buildSettingsPanel({settings, onChange, onDrawerToggle, getDrawerState}) {
|
||||
if (!settings?.length) throw new Error("No settings provided!");
|
||||
if (typeof(onChange) !== "function") throw new Error("No change listener provided!");
|
||||
return React.createElement(React.Fragment, null, settings.map(setting => {
|
||||
if (setting.type === "group") {
|
||||
const shownByDefault = setting.hasOwnProperty("shown") ? setting.shown : true;
|
||||
const groupProps = Object.assign({}, setting, {
|
||||
onChange,
|
||||
onDrawerToggle: state => onDrawerToggle?.(setting.id, state),
|
||||
shown: getDrawerState?.(setting.id, shownByDefault) ?? shownByDefault
|
||||
});
|
||||
return React.createElement(Group, groupProps);
|
||||
}
|
||||
return buildSetting(Object.assign({}, setting, {onChange: value => onChange(null, setting.id, value)}));
|
||||
}));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import DiscordModules from "./discordmodules";
|
||||
export default DiscordModules.React;
|
||||
/** @type {import("react")} */
|
||||
const React = DiscordModules.React;
|
||||
export default React;
|
||||
export const ReactDOM = DiscordModules.ReactDOM;
|
|
@ -14,26 +14,32 @@ import Color from "./components/color";
|
|||
const {useCallback} = React;
|
||||
|
||||
|
||||
export default function Group({onChange, id, name, button, shown, onDrawerToggle, showDivider, collapsible, settings}) {
|
||||
export default function Group({onChange, id, name, button, shown, onDrawerToggle, showDivider, collapsible, settings, children}) {
|
||||
const change = useCallback((settingId, value) => {
|
||||
if (id) onChange?.(id, settingId, value);
|
||||
else onChange?.(settingId, value);
|
||||
}, [id, onChange]);
|
||||
|
||||
return <Drawer collapsible={collapsible} name={name} button={button} shown={shown} onDrawerToggle={onDrawerToggle} showDivider={showDivider}>
|
||||
{settings.filter(s => !s.hidden).map((setting) => {
|
||||
let component = null;
|
||||
{settings.length && settings.filter(s => !s.hidden).map((setting) => {
|
||||
const callback = value => change(setting.id, value);
|
||||
if (setting.type == "dropdown") component = <Dropdown disabled={setting.disabled} id={setting.id} options={setting.options} value={setting.value} onChange={callback} />;
|
||||
if (setting.type == "number") component = <Number disabled={setting.disabled} id={setting.id} min={setting.min} max={setting.max} step={setting.step} value={setting.value} onChange={callback} />;
|
||||
if (setting.type == "switch") component = <Switch disabled={setting.disabled} id={setting.id} checked={setting.value} onChange={callback} />;
|
||||
if (setting.type == "text") component = <Textbox disabled={setting.disabled} id={setting.id} value={setting.value} onChange={callback} />;
|
||||
if (setting.type == "slider") component = <Slider disabled={setting.disabled} id={setting.id} min={setting.min} max={setting.max} step={setting.step} value={setting.value} onChange={callback} />;
|
||||
if (setting.type == "radio") component = <Radio disabled={setting.disabled} id={setting.id} name={setting.id} options={setting.options} value={setting.value} onChange={callback} />;
|
||||
if (setting.type == "keybind") component = <Keybind disabled={setting.disabled} id={setting.id} value={setting.value} max={setting.max} onChange={callback} />;
|
||||
if (setting.type == "color") component = <Color disabled={setting.disabled} id={setting.id} value={setting.value} defaultValue={setting.defaultValue} colors={setting.colors} onChange={callback} />;
|
||||
if (!component) return null;
|
||||
return <Item id={setting.id} inline={setting.type !== "radio"} key={setting.id} name={setting.name} note={setting.note}>{component}</Item>;
|
||||
return buildSetting({...setting, onChange: callback});
|
||||
})}
|
||||
{children}
|
||||
</Drawer>;
|
||||
}
|
||||
|
||||
|
||||
export function buildSetting(setting) {
|
||||
let component = null;
|
||||
if (setting.type == "dropdown") component = <Dropdown disabled={setting.disabled} id={setting.id} options={setting.options} value={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "number") component = <Number disabled={setting.disabled} id={setting.id} min={setting.min} max={setting.max} step={setting.step} value={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "switch") component = <Switch disabled={setting.disabled} id={setting.id} checked={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "text") component = <Textbox disabled={setting.disabled} id={setting.id} value={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "slider") component = <Slider disabled={setting.disabled} id={setting.id} min={setting.min} max={setting.max} step={setting.step} value={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "radio") component = <Radio disabled={setting.disabled} id={setting.id} name={setting.id} options={setting.options} value={setting.value} onChange={setting.onChange} />;
|
||||
if (setting.type == "keybind") component = <Keybind disabled={setting.disabled} id={setting.id} value={setting.value} max={setting.max} onChange={setting.onChange} />;
|
||||
if (setting.type == "color") component = <Color disabled={setting.disabled} id={setting.id} value={setting.value} defaultValue={setting.defaultValue} colors={setting.colors} onChange={setting.onChange} />;
|
||||
if (!component) return null;
|
||||
return <Item id={setting.id} inline={setting.type !== "radio"} key={setting.id} name={setting.name} note={setting.note}>{component}</Item>;
|
||||
}
|
Loading…
Reference in New Issue