Fix components api and allow custom inputs

This commit is contained in:
Zerebos 2024-12-06 19:40:00 -05:00
parent e2d3049a97
commit 23aa6876d1
No known key found for this signature in database
6 changed files with 40 additions and 33 deletions

View File

@ -69,22 +69,6 @@ export default class BdApi {
get UI() {return UI;} get UI() {return UI;}
get ReactUtils() {return ReactUtils;} get ReactUtils() {return ReactUtils;}
get ContextMenu() {return ContextMenuAPI;} get ContextMenu() {return ContextMenuAPI;}
Components = {
get Tooltip() {return DiscordModules.Tooltip;},
get ColorInput() {return ColorInput;},
get DropdownInput() {return DropdownInput;},
get SettingItem() {return SettingItem;},
get KeybindInput() {return KeybindInput;},
get NumberInput() {return NumberInput;},
get RadioInput() {return RadioInput;},
get SearchInput() {return SearchInput;},
get SliderInput() {return SliderInput;},
get SwitchInput() {return SwitchInput;},
get TextInput() {return TextInput;},
get SettingGroup() {return SettingGroup;},
get ErrorBoundary() {return ErrorBoundary;},
};
Net = {fetch};
} }
// Add legacy functions // Add legacy functions
@ -150,10 +134,30 @@ BdApi.DOM = DOMAPI;
*/ */
BdApi.ContextMenu = ContextMenuAPI; BdApi.ContextMenu = ContextMenuAPI;
/**
* An set of react components plugins can make use of.
* @type Components
*/
BdApi.Components = { BdApi.Components = {
get Tooltip() {return DiscordModules.Tooltip;} get Tooltip() {return DiscordModules.Tooltip;},
get ColorInput() {return ColorInput;},
get DropdownInput() {return DropdownInput;},
get SettingItem() {return SettingItem;},
get KeybindInput() {return KeybindInput;},
get NumberInput() {return NumberInput;},
get RadioInput() {return RadioInput;},
get SearchInput() {return SearchInput;},
get SliderInput() {return SliderInput;},
get SwitchInput() {return SwitchInput;},
get TextInput() {return TextInput;},
get SettingGroup() {return SettingGroup;},
get ErrorBoundary() {return ErrorBoundary;},
}; };
/**
* An instance of {@link Net} for using network related tools.
* @type Net
*/
BdApi.Net = {fetch}; BdApi.Net = {fetch};
Object.freeze(BdApi); Object.freeze(BdApi);

View File

@ -146,13 +146,15 @@ const UI = {
* The shape of the object should match the props of the component you want to render, check the * 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. * `BdApi.Components` section for details. Shown below are ones common to all setting types.
* @param {object} setting * @param {object} setting
* @param {string} setting.type One of: dropdown, number, switch, text, slider, radio, keybind, color, custom
* @param {string} setting.id Identifier to used for callbacks * @param {string} setting.id Identifier to used for callbacks
* @param {string} setting.name Visual name to display * @param {string} setting.name Visual name to display
* @param {string} setting.note Visual description to display * @param {string} setting.note Visual description to display
* @param {any} setting.value Current value of the setting * @param {any} setting.value Current value of the setting
* @param {ReactElement} [setting.children] Only used for "custom" type
* @param {CallableFunction} [setting.onChange] Callback when the value changes (only argument is new value) * @param {CallableFunction} [setting.onChange] Callback when the value changes (only argument is new value)
* @param {boolean} [setting.disabled] Whether this setting is disabled * @param {boolean} [setting.disabled=false] Whether this setting is disabled
* @param {boolean} [setting.inline=true] Whether the input should render inline with the name (this is false by default only for radio type)
* @returns A SettingItem with a an input as the child * @returns A SettingItem with a an input as the child
*/ */
buildSetting(setting) { buildSetting(setting) {

View File

@ -24,7 +24,7 @@ function makeButton(button, value) {
function makeSwitch(control) { function makeSwitch(control) {
return <Flex align={Flex.Align.CENTER} style={{gap: "10px"}}> return <Flex align={Flex.Align.CENTER} style={{gap: "10px"}}>
<Text>{control.label}</Text> <Text>{control.label}</Text>
<Switch onChange={control.onChange} checked={control.checked} /> <Switch onChange={control.onChange} value={control.checked} />
</Flex>; </Flex>;
} }

View File

@ -170,7 +170,7 @@ export default function AddonCard({addon, prefix, type, disabled, enabled: initi
<div className="bd-addon-header"> <div className="bd-addon-header">
{type === "plugin" ? <ExtIcon size="18px" className="bd-icon" /> : <ThemeIcon size="18px" className="bd-icon" />} {type === "plugin" ? <ExtIcon size="18px" className="bd-icon" /> : <ThemeIcon size="18px" className="bd-icon" />}
<div className="bd-title">{title}</div> <div className="bd-title">{title}</div>
<Switch internalState={false} disabled={disabled} checked={isEnabled} onChange={onChange} /> <Switch internalState={false} disabled={disabled} value={isEnabled} onChange={onChange} />
</div> </div>
<div className="bd-description-wrap"> <div className="bd-description-wrap">
{disabled && <div className="banner banner-danger"><ErrorIcon className="bd-icon" />{`An error was encountered while trying to load this ${type}.`}</div>} {disabled && <div className="banner banner-danger"><ErrorIcon className="bd-icon" />{`An error was encountered while trying to load this ${type}.`}</div>}

View File

@ -3,7 +3,7 @@ import React from "@modules/react";
const {useState, useCallback} = React; const {useState, useCallback} = React;
export default function Switch({id, checked: initialValue, disabled, onChange, internalState = true}) { export default function Switch({id, value: initialValue, disabled, onChange, internalState = true}) {
const [checked, setChecked] = useState(initialValue); const [checked, setChecked] = useState(initialValue);
const change = useCallback(() => { const change = useCallback(() => {
onChange?.(!checked); onChange?.(!checked);

View File

@ -31,15 +31,16 @@ export default function Group({onChange, id, name, button, shown, onDrawerToggle
export function buildSetting(setting) { export function buildSetting(setting) {
let component = null; let children = 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 == "dropdown") children = <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 == "number") children = <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 == "switch") children = <Switch disabled={setting.disabled} id={setting.id} value={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 == "text") children = <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 == "slider") children = <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 == "radio") children = <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 == "keybind") children = <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 (setting.type == "color") children = <Color disabled={setting.disabled} id={setting.id} value={setting.value} defaultValue={setting.defaultValue} colors={setting.colors} onChange={setting.onChange} />;
if (!component) return null; if (setting.type == "custom") children = setting.children;
return <Item id={setting.id} inline={setting.type !== "radio"} key={setting.id} name={setting.name} note={setting.note}>{component}</Item>; if (!children) return null;
return <Item id={setting.id} inline={setting.hasOwnProperty("inline") ? setting.inline : setting.type !== "radio"} key={setting.id} name={setting.name} note={setting.note}>{children}</Item>;
} }