feat: each settings component handles state, + fix selects again lol
This commit is contained in:
parent
482caf0c5b
commit
74f9b1a022
|
@ -243,9 +243,11 @@ function ThemesTab() {
|
|||
switch (varInfo.type) {
|
||||
case "text":
|
||||
case "color":
|
||||
case "select":
|
||||
normalizedValue = varInfo.default;
|
||||
break;
|
||||
case "select":
|
||||
normalizedValue = varInfo.options.find(v => v.name === varInfo.default)!.value;
|
||||
break;
|
||||
case "checkbox":
|
||||
normalizedValue = varInfo.default ? "1" : "0";
|
||||
break;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { useSettings } from "@api/Settings";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot } from "@utils/modal";
|
||||
import { Text, useState } from "@webpack/common";
|
||||
import { Text } from "@webpack/common";
|
||||
import type { ReactNode } from "react";
|
||||
import { UserstyleHeader } from "usercss-meta";
|
||||
|
||||
|
@ -24,98 +24,79 @@ export function UserCSSSettingsModal({ modalProps, theme }: UserCSSSettingsModal
|
|||
|
||||
const controls: ReactNode[] = [];
|
||||
|
||||
function updateSetting(key: string, value: string, setValue: (value: string) => void) {
|
||||
function updateSetting(key: string, value: string) {
|
||||
themeSettings[key] = value;
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
for (const [name, varInfo] of Object.entries(theme.vars)) {
|
||||
switch (varInfo.type) {
|
||||
case "text": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingTextComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "checkbox": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingBooleanComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "color": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingColorComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "number": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingNumberComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "select": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingSelectComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
options={varInfo.options}
|
||||
value={value}
|
||||
default={varInfo.default}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case "range": {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
controls.push(
|
||||
<SettingRangeComponent
|
||||
label={varInfo.label}
|
||||
name={name}
|
||||
value={value}
|
||||
default={varInfo.default}
|
||||
min={varInfo.min}
|
||||
max={varInfo.max}
|
||||
step={varInfo.step}
|
||||
onChange={v => updateSetting(name, v, setValue)}
|
||||
themeSettings={themeSettings}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
|
|
|
@ -4,22 +4,31 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Forms, Switch } from "@webpack/common";
|
||||
import { Forms, Switch, useState } from "@webpack/common";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
name: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingBooleanComponent({ label, name, value, onChange }: Props) {
|
||||
export function SettingBooleanComponent({ label, name, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: boolean) {
|
||||
const corrected = value ? "1" : "0";
|
||||
|
||||
setValue(corrected);
|
||||
|
||||
themeSettings[name] = corrected;
|
||||
}
|
||||
|
||||
return (
|
||||
<Forms.FormSection>
|
||||
<Switch
|
||||
key={name}
|
||||
value={value === "1"}
|
||||
onChange={v => onChange(v ? "1" : "0")}
|
||||
onChange={handleChange}
|
||||
hideBorder
|
||||
style={{ marginBottom: "0.5em" }}
|
||||
>
|
||||
|
|
|
@ -55,11 +55,20 @@ function ColorPicker(props: ColorPickerProps) {
|
|||
interface Props {
|
||||
label: string;
|
||||
name: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingColorComponent({ label, name, value, onChange }: Props) {
|
||||
export function SettingColorComponent({ label, name, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: number) {
|
||||
const corrected = "#" + (value?.toString(16).padStart(6, "0") ?? "000000");
|
||||
|
||||
setValue(corrected);
|
||||
|
||||
themeSettings[name] = corrected;
|
||||
}
|
||||
|
||||
const normalizedValue = TinyColor(value).toHex();
|
||||
|
||||
return (
|
||||
|
@ -68,7 +77,7 @@ export function SettingColorComponent({ label, name, value, onChange }: Props) {
|
|||
<ColorPicker
|
||||
key={name}
|
||||
value={parseInt(normalizedValue, 16)}
|
||||
onChange={v => onChange("#" + (v?.toString(16).padStart(6, "0") ?? "000000"))}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Forms.FormSection>
|
||||
);
|
||||
|
|
|
@ -4,16 +4,23 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Forms, TextInput } from "@webpack/common";
|
||||
import { Forms, TextInput, useState } from "@webpack/common";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
name: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingNumberComponent({ label, name, value, onChange }: Props) {
|
||||
export function SettingNumberComponent({ label, name, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: string) {
|
||||
setValue(value);
|
||||
|
||||
themeSettings[name] = value;
|
||||
}
|
||||
|
||||
return (
|
||||
<Forms.FormSection>
|
||||
<Forms.FormTitle tag="h5">{label}</Forms.FormTitle>
|
||||
|
@ -22,7 +29,7 @@ export function SettingNumberComponent({ label, name, value, onChange }: Props)
|
|||
pattern="-?[0-9]+"
|
||||
key={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Forms.FormSection>
|
||||
);
|
||||
|
|
|
@ -4,20 +4,29 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Forms, Slider } from "@webpack/common";
|
||||
import { Forms, Slider, useState } from "@webpack/common";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
name: string;
|
||||
value: string;
|
||||
default: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingRangeComponent({ label, name, value, default: def, min, max, step, onChange }: Props) {
|
||||
export function SettingRangeComponent({ label, name, default: def, min, max, step, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: number) {
|
||||
const corrected = value.toString();
|
||||
|
||||
setValue(corrected);
|
||||
|
||||
themeSettings[name] = corrected;
|
||||
}
|
||||
|
||||
const markers: number[] = [];
|
||||
|
||||
// defaults taken from https://github.com/openstyles/stylus/wiki/Writing-UserCSS#default-value
|
||||
|
@ -31,7 +40,7 @@ export function SettingRangeComponent({ label, name, value, default: def, min, m
|
|||
<Slider
|
||||
initialValue={parseInt(value, 10)}
|
||||
defaultValue={def}
|
||||
onValueChange={v => onChange(v.toString())}
|
||||
onValueChange={handleChange}
|
||||
minValue={min}
|
||||
maxValue={max}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { identity } from "@utils/misc";
|
||||
import { ComponentTypes, Forms, Select } from "@webpack/common";
|
||||
import { ComponentTypes, Forms, Select, useState } from "@webpack/common";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
|
@ -15,12 +15,19 @@ interface Props {
|
|||
label: string;
|
||||
value: string;
|
||||
}[];
|
||||
value: string;
|
||||
default: string;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingSelectComponent({ label, name, options, value, default: def, onChange }: Props) {
|
||||
export function SettingSelectComponent({ label, name, options, default: def, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: string) {
|
||||
setValue(value);
|
||||
|
||||
themeSettings[name] = value;
|
||||
}
|
||||
|
||||
const opts = options.map(option => ({
|
||||
disabled: false,
|
||||
|
||||
|
@ -39,7 +46,7 @@ export function SettingSelectComponent({ label, name, options, value, default: d
|
|||
options={opts}
|
||||
closeOnSelect={true}
|
||||
|
||||
select={onChange}
|
||||
select={handleChange}
|
||||
isSelected={v => v === value}
|
||||
serialize={identity}
|
||||
/>
|
||||
|
|
|
@ -4,23 +4,30 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { Forms, TextInput } from "@webpack/common";
|
||||
import { Forms, TextInput, useState } from "@webpack/common";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
name: string;
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
themeSettings: Record<string, string>;
|
||||
}
|
||||
|
||||
export function SettingTextComponent({ label, name, value, onChange }: Props) {
|
||||
export function SettingTextComponent({ label, name, themeSettings }: Props) {
|
||||
const [value, setValue] = useState(themeSettings[name]);
|
||||
|
||||
function handleChange(value: string) {
|
||||
setValue(value);
|
||||
|
||||
themeSettings[name] = value;
|
||||
}
|
||||
|
||||
return (
|
||||
<Forms.FormSection>
|
||||
<Forms.FormTitle tag="h5">{label}</Forms.FormTitle>
|
||||
<TextInput
|
||||
key={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</Forms.FormSection>
|
||||
);
|
||||
|
|
|
@ -88,11 +88,6 @@ export async function compileUsercss(fileName: string) {
|
|||
varsToPass[k] = `${varsToPass[k]}${v.units ?? "px"}`;
|
||||
break;
|
||||
}
|
||||
|
||||
case "select": {
|
||||
varsToPass[k] = v.options.find(opt => opt.name === varsToPass[k])!.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue