updated DiscordColorways to v5.6.4.2
This commit is contained in:
parent
101e25329e
commit
cba15d56d3
16 changed files with 665 additions and 1274 deletions
|
@ -19,202 +19,73 @@ import {
|
|||
useState,
|
||||
} from "@webpack/common";
|
||||
|
||||
import { mainColors } from "../constants";
|
||||
import { colorVariables } from "../css";
|
||||
|
||||
interface ToolboxItem {
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
id?: string;
|
||||
iconClassName?: string;
|
||||
}
|
||||
|
||||
const ColorVarItems: ToolboxItem[] = colorVariables.map((colorVariable: string) => {
|
||||
return {
|
||||
title: "Copy " + colorVariable,
|
||||
onClick: () => {
|
||||
function getHex(str: string): string { return Object.assign(document.createElement("canvas").getContext("2d") as {}, { fillStyle: str }).fillStyle; }
|
||||
Clipboard.copy(getHex(getComputedStyle(document.body).getPropertyValue("--" + colorVariable)));
|
||||
Toasts.show({ message: "Color " + colorVariable + " copied to clipboard", id: "toolbox-color-var-copied", type: 1 });
|
||||
},
|
||||
id: colorVariable
|
||||
};
|
||||
});
|
||||
|
||||
const ToolboxItems: ToolboxItem[] = [
|
||||
{
|
||||
title: "Copy Accent Color",
|
||||
onClick: () => {
|
||||
function getHex(str: string): string {
|
||||
return Object.assign(
|
||||
document.createElement("canvas").getContext("2d") as {},
|
||||
{ fillStyle: str }
|
||||
).fillStyle;
|
||||
}
|
||||
Clipboard.copy(
|
||||
getHex(
|
||||
getComputedStyle(document.body).getPropertyValue(
|
||||
"--brand-experiment"
|
||||
)
|
||||
)
|
||||
);
|
||||
Toasts.show({
|
||||
message: "Accent color copied to clipboard",
|
||||
id: "toolbox-accent-color-copied",
|
||||
type: 1,
|
||||
});
|
||||
},
|
||||
id: "colorways-toolbox_copy-accent",
|
||||
iconClassName: "copy",
|
||||
},
|
||||
{
|
||||
title: "Copy Primary Color",
|
||||
onClick: () => {
|
||||
function getHex(str: string): string {
|
||||
return Object.assign(
|
||||
document.createElement("canvas").getContext("2d") as {},
|
||||
{ fillStyle: str }
|
||||
).fillStyle;
|
||||
}
|
||||
Clipboard.copy(
|
||||
getHex(
|
||||
getComputedStyle(document.body).getPropertyValue(
|
||||
"--background-primary"
|
||||
)
|
||||
)
|
||||
);
|
||||
Toasts.show({
|
||||
message: "Primary color copied to clipboard",
|
||||
id: "toolbox-primary-color-copied",
|
||||
type: 1,
|
||||
});
|
||||
},
|
||||
id: "colorways-toolbox_copy-primary",
|
||||
iconClassName: "copy",
|
||||
},
|
||||
{
|
||||
title: "Copy Secondary Color",
|
||||
onClick: () => {
|
||||
function getHex(str: string): string {
|
||||
return Object.assign(
|
||||
document.createElement("canvas").getContext("2d") as {},
|
||||
{ fillStyle: str }
|
||||
).fillStyle;
|
||||
}
|
||||
Clipboard.copy(
|
||||
getHex(
|
||||
getComputedStyle(document.body).getPropertyValue(
|
||||
"--background-secondary"
|
||||
)
|
||||
)
|
||||
);
|
||||
Toasts.show({
|
||||
message: "Secondary color copied to clipboard",
|
||||
id: "toolbox-secondary-color-copied",
|
||||
type: 1,
|
||||
});
|
||||
},
|
||||
id: "colorways-toolbox_copy-secondary",
|
||||
iconClassName: "copy",
|
||||
},
|
||||
{
|
||||
title: "Copy Tertiary Color",
|
||||
onClick: () => {
|
||||
function getHex(str: string): string {
|
||||
return Object.assign(
|
||||
document.createElement("canvas").getContext("2d") as {},
|
||||
{ fillStyle: str }
|
||||
).fillStyle;
|
||||
}
|
||||
Clipboard.copy(
|
||||
getHex(
|
||||
getComputedStyle(document.body).getPropertyValue(
|
||||
"--background-tertiary"
|
||||
)
|
||||
)
|
||||
);
|
||||
Toasts.show({
|
||||
message: "Tertiary color copied to clipboard",
|
||||
id: "toolbox-tertiary-color-copied",
|
||||
type: 1,
|
||||
});
|
||||
},
|
||||
id: "colorways-toolbox_copy-tertiary",
|
||||
iconClassName: "copy",
|
||||
}
|
||||
];
|
||||
import { getHex } from "../utils";
|
||||
|
||||
export default function ({ modalProps }: { modalProps: ModalProps; }) {
|
||||
const [colorVarItems, setColorVarItems] = useState<ToolboxItem[]>(ColorVarItems);
|
||||
const [ColorVars, setColorVars] = useState<string[]>(colorVariables);
|
||||
const [collapsedSettings, setCollapsedSettings] = useState<boolean>(true);
|
||||
let results: ToolboxItem[];
|
||||
let results: string[];
|
||||
function searchToolboxItems(e: string) {
|
||||
results = [];
|
||||
ColorVarItems.find((ToolboxItem: ToolboxItem) => {
|
||||
if (ToolboxItem.title.toLowerCase().includes(e.toLowerCase())) {
|
||||
results.push(ToolboxItem);
|
||||
colorVariables.find((colorVariable: string) => {
|
||||
if (colorVariable.toLowerCase().includes(e.toLowerCase())) {
|
||||
results.push(colorVariable);
|
||||
}
|
||||
});
|
||||
setColorVarItems(results);
|
||||
setColorVars(results);
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalRoot {...modalProps} className="colorwayColorpicker">
|
||||
<Flex style={{ gap: "8px", marginBottom: "8px" }}>
|
||||
<TextInput
|
||||
className="colorwaysColorpicker-search"
|
||||
placeholder="Search for a color:"
|
||||
onChange={e => {
|
||||
searchToolboxItems(e);
|
||||
if (e) {
|
||||
setCollapsedSettings(false);
|
||||
} else {
|
||||
setCollapsedSettings(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
onClick={() => setCollapsedSettings(!collapsedSettings)}
|
||||
>
|
||||
<svg width="32" height="24" viewBox="0 0 24 24" aria-hidden="true" role="img">
|
||||
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10" aria-hidden="true" />
|
||||
</svg>
|
||||
</Button>
|
||||
</Flex>
|
||||
<ScrollerThin style={{ color: "var(--text-normal)" }} orientation="vertical" className={collapsedSettings ? " colorwaysColorpicker-collapsed" : ""} paddingFix>
|
||||
{colorVarItems.map((toolboxItem: ToolboxItem) => {
|
||||
return (
|
||||
<div
|
||||
id={
|
||||
"colorways-colorstealer-item_" +
|
||||
toolboxItem.id
|
||||
}
|
||||
className="colorwaysCreator-settingItm colorwaysCreator-toolboxItm"
|
||||
onClick={toolboxItem.onClick}
|
||||
style={
|
||||
{
|
||||
"--brand-experiment":
|
||||
"var(--" + toolboxItem.id + ")",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
{toolboxItem.title}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</ScrollerThin>
|
||||
<Flex style={{ justifyContent: "space-between", marginTop: "8px" }} wrap="wrap" className={collapsedSettings ? "" : " colorwaysColorpicker-collapsed"}>
|
||||
{ToolboxItems.map((toolboxItem: ToolboxItem, i: number) => <div
|
||||
id={toolboxItem.id || `colorways-toolbox_item-${i}`}
|
||||
className="colorwayToolbox-listItem"
|
||||
>
|
||||
<CopyIcon onClick={toolboxItem.onClick} width={20} height={20} className="colorwayToolbox-listItemSVG" />
|
||||
<span className="colorwaysToolbox-label">{toolboxItem.title}</span>
|
||||
</div>
|
||||
)}
|
||||
</Flex>
|
||||
</ModalRoot>
|
||||
);
|
||||
return <ModalRoot {...modalProps} className="colorwayColorpicker">
|
||||
<Flex style={{ gap: "8px", marginBottom: "8px" }}>
|
||||
<TextInput
|
||||
className="colorwaysColorpicker-search"
|
||||
placeholder="Search for a color:"
|
||||
onChange={e => {
|
||||
searchToolboxItems(e);
|
||||
if (e) {
|
||||
setCollapsedSettings(false);
|
||||
} else {
|
||||
setCollapsedSettings(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => setCollapsedSettings(!collapsedSettings)}
|
||||
>
|
||||
<svg width="32" height="24" viewBox="0 0 24 24" aria-hidden="true" role="img">
|
||||
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10" aria-hidden="true" />
|
||||
</svg>
|
||||
</Button>
|
||||
</Flex>
|
||||
<ScrollerThin style={{ color: "var(--text-normal)" }} orientation="vertical" className={collapsedSettings ? " colorwaysColorpicker-collapsed" : ""} paddingFix>
|
||||
{ColorVars.map((colorVariable: string) => <div
|
||||
id={`colorways-colorstealer-item_${colorVariable}`}
|
||||
className="colorwaysCreator-settingItm colorwaysCreator-toolboxItm"
|
||||
onClick={() => {
|
||||
Clipboard.copy(getHex(getComputedStyle(document.body).getPropertyValue("--" + colorVariable)));
|
||||
Toasts.show({ message: "Color " + colorVariable + " copied to clipboard", id: "toolbox-color-var-copied", type: 1 });
|
||||
}} style={{ "--brand-experiment": `var(--${colorVariable})` } as React.CSSProperties}>
|
||||
{`Copy ${colorVariable}`}
|
||||
</div>)}
|
||||
</ScrollerThin>
|
||||
<Flex style={{ justifyContent: "space-between", marginTop: "8px" }} wrap="wrap" className={collapsedSettings ? "" : " colorwaysColorpicker-collapsed"}>
|
||||
{mainColors.map(mainColor => <div
|
||||
id={`colorways-toolbox_copy-${mainColor.name}`}
|
||||
className="colorwayToolbox-listItem"
|
||||
>
|
||||
<CopyIcon onClick={() => {
|
||||
Clipboard.copy(getHex(getComputedStyle(document.body).getPropertyValue(mainColor.var)));
|
||||
Toasts.show({ message: `${mainColor.title} color copied to clipboard`, id: `toolbox-${mainColor.name}-color-copied`, type: 1 });
|
||||
}} width={20} height={20} className="colorwayToolbox-listItemSVG" />
|
||||
<span className="colorwaysToolbox-label">{`Copy ${mainColor.title} Color`}</span>
|
||||
</div>
|
||||
)}
|
||||
</Flex>
|
||||
</ModalRoot>;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import { openModal } from "@utils/modal";
|
||||
import { FluxDispatcher, Text, Tooltip, useCallback, useEffect, useState } from "@webpack/common";
|
||||
import { FluxDispatcher, Text, Tooltip, useEffect, useState } from "@webpack/common";
|
||||
import { FluxEvents } from "@webpack/types";
|
||||
|
||||
import { PalleteIcon } from "./Icons";
|
||||
import SelectorModal from "./SelectorModal";
|
||||
import Selector from "./Selector";
|
||||
|
||||
export default function ({
|
||||
listItemClass = "ColorwaySelectorBtnContainer",
|
||||
|
@ -34,10 +34,8 @@ export default function ({
|
|||
setIsThin(useThinMenuButton);
|
||||
}
|
||||
|
||||
const cached_setButtonVisibility = useCallback(setButtonVisibility, []);
|
||||
|
||||
useEffect(() => {
|
||||
cached_setButtonVisibility();
|
||||
setButtonVisibility();
|
||||
});
|
||||
|
||||
FluxDispatcher.subscribe("COLORWAYS_UPDATE_BUTTON_HEIGHT" as FluxEvents, ({ isTall }) => {
|
||||
|
@ -48,61 +46,23 @@ export default function ({
|
|||
setVisibility(isVisible);
|
||||
});
|
||||
|
||||
if (!isThin) {
|
||||
return (<Tooltip text={<>
|
||||
<span>Colorways</span>
|
||||
<Text variant="text-xs/normal" style={{ color: "var(--text-muted)", fontWeight: 500 }}>{"Active Colorway: " + activeColorway}</Text>
|
||||
</>} position="right" tooltipContentClassName={listItemTooltipClass}
|
||||
>
|
||||
{({ onMouseEnter, onMouseLeave, onClick }) => {
|
||||
return (
|
||||
<>
|
||||
{visibility && <div className={listItemClass}>
|
||||
<div
|
||||
className={listItemWrapperClass + " ColorwaySelectorBtn"}
|
||||
onMouseEnter={async () => {
|
||||
onMouseEnter();
|
||||
setActiveColorway(await DataStore.get("actveColorwayID") || "None");
|
||||
}}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
openModal(props => <SelectorModal modalProps={props} />);
|
||||
}}
|
||||
><PalleteIcon /></div>
|
||||
</div>}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
} else {
|
||||
return (<Tooltip text={<>
|
||||
<span>Colorways</span>
|
||||
<Text variant="text-xs/normal" style={{ color: "var(--text-muted)", fontWeight: 500 }}>{"Active Colorway: " + activeColorway}</Text>
|
||||
</>} position="right" tooltipContentClassName={listItemTooltipClass}
|
||||
>
|
||||
{({ onMouseEnter, onMouseLeave, onClick }) => {
|
||||
return (
|
||||
<>
|
||||
{visibility && <div className={listItemClass}>
|
||||
<div
|
||||
className={listItemWrapperClass + " ColorwaySelectorBtn ColorwaySelectorBtn_thin"}
|
||||
onMouseEnter={async () => {
|
||||
onMouseEnter();
|
||||
setActiveColorway(await DataStore.get("actveColorwayID") || "None");
|
||||
}}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
openModal(props => <SelectorModal modalProps={props} />);
|
||||
}}
|
||||
><Text variant="text-xs/normal" style={{ color: "var(--header-primary)", fontWeight: 700, fontSize: 9 }}>Colorways</Text></div>
|
||||
</div>}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return <Tooltip text={
|
||||
!isThin ? <><span>Colorways</span><Text variant="text-xs/normal" style={{ color: "var(--text-muted)", fontWeight: 500 }}>{"Active Colorway: " + activeColorway}</Text></> : <span>{"Active Colorway: " + activeColorway}</span>
|
||||
} position="right" tooltipContentClassName="colorwaysBtn-tooltipContent"
|
||||
>
|
||||
{({ onMouseEnter, onMouseLeave, onClick }) => visibility ? <div className="ColorwaySelectorBtnContainer">
|
||||
<div
|
||||
className={"ColorwaySelectorBtn" + (isThin ? " ColorwaySelectorBtn_thin" : "")}
|
||||
onMouseEnter={async () => {
|
||||
onMouseEnter();
|
||||
setActiveColorway(await DataStore.get("actveColorwayID") || "None");
|
||||
}}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
openModal((props: any) => <Selector modalProps={props} />);
|
||||
}}
|
||||
>{isThin ? <Text variant="text-xs/normal" style={{ color: "var(--header-primary)", fontWeight: 700, fontSize: 9 }}>Colorways</Text> : <PalleteIcon />}</div>
|
||||
</div> : <></>}
|
||||
</Tooltip>;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import { generateCss, getPreset } from "../css";
|
|||
import { Colorway } from "../types";
|
||||
import { colorToHex, getHex, hexToString } from "../utils";
|
||||
import ConflictingColorsModal from "./ConflictingColorsModal";
|
||||
import InputColorwayIdModal from "./InputColorwayIdModal";
|
||||
import ThemePreviewCategory from "./ThemePreview";
|
||||
export default function ({
|
||||
modalProps,
|
||||
|
@ -51,26 +52,46 @@ export default function ({
|
|||
const [collapsedSettings, setCollapsedSettings] = useState<boolean>(true);
|
||||
const [collapsedPresets, setCollapsedPresets] = useState<boolean>(true);
|
||||
const [preset, setPreset] = useState<string>("default");
|
||||
const [presetColorArray, setPresetColorArray] = useState<string[]>(["accent", "primary", "secondary", "tertiary"]);
|
||||
const [presetColorArray, setPresetColorArray] = useState<string[]>(["primary", "secondary", "tertiary", "accent"]);
|
||||
|
||||
const colorProps = {
|
||||
accent: {
|
||||
get: accentColor,
|
||||
set: setAccentColor,
|
||||
name: "Accent"
|
||||
},
|
||||
primary: {
|
||||
get: primaryColor,
|
||||
set: setPrimaryColor,
|
||||
name: "Primary"
|
||||
},
|
||||
secondary: {
|
||||
get: secondaryColor,
|
||||
set: setSecondaryColor,
|
||||
name: "Secondary"
|
||||
},
|
||||
tertiary: {
|
||||
get: tertiaryColor,
|
||||
set: setTertiaryColor,
|
||||
name: "Tertiary"
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const parsedID = colorwayID?.split("colorway:")[1];
|
||||
if (parsedID) {
|
||||
const allEqual = (arr: any[]) => arr.every(v => v === arr[0]);
|
||||
if (!parsedID) {
|
||||
throw new Error("Please enter a Colorway ID");
|
||||
} else if (parsedID.length < 62) {
|
||||
throw new Error("Invalid Colorway ID");
|
||||
} else if (!hexToString(parsedID).includes(",")) {
|
||||
throw new Error("Invalid Colorway ID");
|
||||
} else if (!allEqual(hexToString(parsedID).split(",").map((e: string) => e.match("#")!.length)) && hexToString(parsedID).split(",").map((e: string) => e.match("#")!.length)[0] !== 1) {
|
||||
throw new Error("Invalid Colorway ID");
|
||||
} else {
|
||||
const colorArray: string[] = hexToString(parsedID).split(",");
|
||||
setAccentColor(colorArray[0].split("#")[1]);
|
||||
setPrimaryColor(colorArray[1].split("#")[1]);
|
||||
setSecondaryColor(colorArray[2].split("#")[1]);
|
||||
setTertiaryColor(colorArray[3].split("#")[1]);
|
||||
const setColor = [
|
||||
setAccentColor,
|
||||
setPrimaryColor,
|
||||
setSecondaryColor,
|
||||
setTertiaryColor
|
||||
];
|
||||
hexToString(parsedID).split(/,#/).forEach((color: string, i: number) => setColor[i](colorToHex(color)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -100,62 +121,26 @@ export default function ({
|
|||
value={colorwayName}
|
||||
onChange={setColorwayName}
|
||||
/>
|
||||
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||
Colors:
|
||||
</Forms.FormTitle>
|
||||
<div className="colorwayCreator-colorPreviews">
|
||||
{presetColorArray.includes("primary") &&
|
||||
<ColorPicker
|
||||
label={<Text className="colorwaysPicker-colorLabel">Primary</Text>}
|
||||
color={parseInt(primaryColor, 16)}
|
||||
onChange={(color: number) => {
|
||||
let hexColor = color.toString(16);
|
||||
while (hexColor.length < 6) {
|
||||
hexColor = "0" + hexColor;
|
||||
}
|
||||
setPrimaryColor(hexColor);
|
||||
}}
|
||||
{...colorPickerProps}
|
||||
/>}
|
||||
{presetColorArray.includes("secondary") &&
|
||||
<ColorPicker
|
||||
label={<Text className="colorwaysPicker-colorLabel">Secondary</Text>}
|
||||
color={parseInt(secondaryColor, 16)}
|
||||
onChange={(color: number) => {
|
||||
let hexColor = color.toString(16);
|
||||
while (hexColor.length < 6) {
|
||||
hexColor = "0" + hexColor;
|
||||
}
|
||||
setSecondaryColor(hexColor);
|
||||
}}
|
||||
{...colorPickerProps}
|
||||
/>}
|
||||
{presetColorArray.includes("tertiary") &&
|
||||
<ColorPicker
|
||||
label={<Text className="colorwaysPicker-colorLabel">Tertiary</Text>}
|
||||
color={parseInt(tertiaryColor, 16)}
|
||||
onChange={(color: number) => {
|
||||
let hexColor = color.toString(16);
|
||||
while (hexColor.length < 6) {
|
||||
hexColor = "0" + hexColor;
|
||||
}
|
||||
setTertiaryColor(hexColor);
|
||||
}}
|
||||
{...colorPickerProps}
|
||||
/>}
|
||||
{presetColorArray.includes("accent") &&
|
||||
<ColorPicker
|
||||
label={<Text className="colorwaysPicker-colorLabel">Accent</Text>}
|
||||
color={parseInt(accentColor, 16)}
|
||||
onChange={(color: number) => {
|
||||
let hexColor = color.toString(16);
|
||||
while (hexColor.length < 6) {
|
||||
hexColor = "0" + hexColor;
|
||||
}
|
||||
setAccentColor(hexColor);
|
||||
}}
|
||||
{...colorPickerProps}
|
||||
/>}
|
||||
<div className="colorwaysCreator-settingCat">
|
||||
<Forms.FormTitle style={{ marginBottom: 0 }}>
|
||||
Colors:
|
||||
</Forms.FormTitle>
|
||||
<div className="colorwayCreator-colorPreviews">
|
||||
{presetColorArray.map(presetColor => {
|
||||
return <ColorPicker
|
||||
label={<Text className="colorwaysPicker-colorLabel">{colorProps[presetColor].name}</Text>}
|
||||
color={parseInt(colorProps[presetColor].get, 16)}
|
||||
onChange={(color: number) => {
|
||||
let hexColor = color.toString(16);
|
||||
while (hexColor.length < 6) {
|
||||
hexColor = "0" + hexColor;
|
||||
}
|
||||
colorProps[presetColor].set(hexColor);
|
||||
}}
|
||||
{...colorPickerProps}
|
||||
/>;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`colorwaysCreator-settingCat${collapsedSettings ? " colorwaysCreator-settingCat-collapsed" : ""}`}>
|
||||
<div
|
||||
|
@ -231,12 +216,18 @@ export default function ({
|
|||
discordSaturation
|
||||
);
|
||||
} else {
|
||||
customColorwayCSS = getPreset(
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
tertiaryColor,
|
||||
accentColor
|
||||
)[preset].preset(discordSaturation);
|
||||
(getPreset()[preset].id === "gradientType1" || getPreset()[preset].id === "gradientType2") ?
|
||||
customColorwayCSS = getPreset(
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
tertiaryColor,
|
||||
accentColor
|
||||
)[preset].preset(discordSaturation).full : customColorwayCSS = getPreset(
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
tertiaryColor,
|
||||
accentColor
|
||||
)[preset].preset(discordSaturation);
|
||||
}
|
||||
const customColorway: Colorway = {
|
||||
name: (colorwayName || "Colorway") + (preset === "default" ? "" : ": Made for " + getPreset()[preset].name),
|
||||
|
@ -248,6 +239,13 @@ export default function ({
|
|||
colors: presetColorArray,
|
||||
author: UserStore.getCurrentUser().username,
|
||||
authorID: UserStore.getCurrentUser().id,
|
||||
isGradient: getPreset()[preset].id === "gradientType1" || getPreset()[preset].id === "gradientType2",
|
||||
linearGradient: (getPreset()[preset].id === "gradientType1" || getPreset()[preset].id === "gradientType2") ? getPreset(
|
||||
primaryColor,
|
||||
secondaryColor,
|
||||
tertiaryColor,
|
||||
accentColor
|
||||
)[preset].preset(discordSaturation).base : null
|
||||
};
|
||||
const customColorwaysArray: Colorway[] = [customColorway];
|
||||
DataStore.get("customColorways").then(
|
||||
|
@ -270,7 +268,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => {
|
||||
function setAllColors({ accent, primary, secondary, tertiary }: { accent: string, primary: string, secondary: string, tertiary: string; }) {
|
||||
setAccentColor(accent.split("#")[1]);
|
||||
|
@ -324,60 +322,16 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
onClick={() => {
|
||||
let colorwayID: string;
|
||||
function setColorwayID(e: string) {
|
||||
colorwayID = e;
|
||||
}
|
||||
openModal(props => {
|
||||
return (
|
||||
<ModalRoot {...props} className="colorwaysCreator-noMinHeight">
|
||||
<ModalContent className="colorwaysCreator-noHeader colorwaysCreator-noMinHeight">
|
||||
<Forms.FormTitle>Colorway ID:</Forms.FormTitle>
|
||||
<TextInput placeholder="Enter Colorway ID" onInput={e => setColorwayID(e.currentTarget.value)} />
|
||||
</ModalContent>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.BRAND}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
onClick={() => {
|
||||
if (!colorwayID) {
|
||||
throw new Error("Please enter a Colorway ID");
|
||||
} else if (!hexToString(colorwayID).includes(",")) {
|
||||
throw new Error("Invalid Colorway ID");
|
||||
} else {
|
||||
const setColor = [
|
||||
setAccentColor,
|
||||
setPrimaryColor,
|
||||
setSecondaryColor,
|
||||
setTertiaryColor
|
||||
];
|
||||
hexToString(colorwayID).split(/,#/).forEach((color: string, i: number) => setColor[i](colorToHex(color)));
|
||||
props.onClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
Finish
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
onClick={() => {
|
||||
props.onClose();
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalRoot>
|
||||
);
|
||||
});
|
||||
}}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => openModal((props: any) => <InputColorwayIdModal modalProps={props} onColorwayId={colorwayID => {
|
||||
const setColor = [
|
||||
setAccentColor,
|
||||
setPrimaryColor,
|
||||
setSecondaryColor,
|
||||
setTertiaryColor
|
||||
];
|
||||
hexToString(colorwayID).split(/,#/).forEach((color: string, i: number) => setColor[i](colorToHex(color)));
|
||||
}} />)}
|
||||
>
|
||||
Enter Colorway ID
|
||||
</Button>
|
||||
|
@ -385,7 +339,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => {
|
||||
modalProps.onClose();
|
||||
}}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
export default () => {
|
||||
return <div style={{
|
||||
width: "100%",
|
||||
height: 1,
|
||||
borderTop: "thin solid var(--background-modifier-accent)",
|
||||
marginTop: "var(--custom-margin-margin-medium)",
|
||||
marginBottom: 20
|
||||
}} />;
|
||||
};
|
|
@ -140,7 +140,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => {
|
||||
const stringToHex = (str: string) => {
|
||||
let hex = "";
|
||||
|
@ -169,7 +169,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => {
|
||||
Clipboard.copy(colorwayProps["dc-import"]);
|
||||
Toasts.show({
|
||||
|
@ -185,7 +185,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={async () => {
|
||||
const customColorways = await DataStore.get("customColorways");
|
||||
const customColorwaysArray: Colorway[] = [];
|
||||
|
@ -211,7 +211,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={async () => {
|
||||
const colorwaySourceFiles = await DataStore.get(
|
||||
"colorwaySourceFiles"
|
||||
|
@ -251,7 +251,7 @@ export default function ({
|
|||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => {
|
||||
modalProps.onClose();
|
||||
}}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2024 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { ModalContent, ModalFooter, ModalProps, ModalRoot } from "@utils/modal";
|
||||
import { Button, Forms, TextInput, useState } from "@webpack/common";
|
||||
|
||||
import { hexToString } from "../utils";
|
||||
|
||||
export default function ({ modalProps, onColorwayId }: { modalProps: ModalProps, onColorwayId: (colorwayID: string) => void; }) {
|
||||
const [colorwayID, setColorwayID] = useState<string>("");
|
||||
return <ModalRoot {...modalProps} className="colorwaysCreator-noMinHeight">
|
||||
<ModalContent className="colorwaysCreator-noHeader colorwaysCreator-noMinHeight">
|
||||
<Forms.FormTitle>Colorway ID:</Forms.FormTitle>
|
||||
<TextInput placeholder="Enter Colorway ID" onInput={e => setColorwayID(e.currentTarget.value)} />
|
||||
</ModalContent>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.BRAND}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
onClick={() => {
|
||||
if (!colorwayID) {
|
||||
throw new Error("Please enter a Colorway ID");
|
||||
} else if (!hexToString(colorwayID).includes(",")) {
|
||||
throw new Error("Invalid Colorway ID");
|
||||
} else {
|
||||
onColorwayId(colorwayID);
|
||||
modalProps.onClose();
|
||||
}
|
||||
}}
|
||||
>
|
||||
Finish
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginLeft: 8 }}
|
||||
color={Button.Colors.PRIMARY}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => modalProps.onClose()}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalRoot>;
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
/* eslint-disable arrow-parens */
|
||||
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||
import { ModalContent, ModalHeader, ModalProps, ModalRoot, openModal } from "@utils/modal";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import {
|
||||
|
@ -23,10 +25,11 @@ import {
|
|||
useEffect,
|
||||
useState,
|
||||
} from "@webpack/common";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { ColorwayCSS } from "..";
|
||||
import { defaultColorwaySource, fallbackColorways } from "../constants";
|
||||
import { generateCss } from "../css";
|
||||
import { generateCss, gradientBase } from "../css";
|
||||
import { Colorway } from "../types";
|
||||
import { colorToHex } from "../utils";
|
||||
import ColorPickerModal from "./ColorPicker";
|
||||
|
@ -36,10 +39,46 @@ import ColorwayInfoModal from "./InfoModal";
|
|||
|
||||
const { SelectionCircle } = findByPropsLazy("SelectionCircle");
|
||||
|
||||
function SelectorContainer({ children, isSettings, modalProps }: { children: ReactNode, isSettings?: boolean, modalProps: ModalProps; }) {
|
||||
if (!isSettings) {
|
||||
return <ModalRoot {...modalProps} className="colorwaySelectorModal">
|
||||
{children}
|
||||
</ModalRoot>;
|
||||
} else {
|
||||
return <SettingsTab title="Colors">
|
||||
<div className="colorwaysSettingsSelector-wrapper">
|
||||
{children}
|
||||
</div>
|
||||
</SettingsTab>;
|
||||
}
|
||||
}
|
||||
|
||||
function SelectorHeader({ children, isSettings }: { children: ReactNode, isSettings?: boolean; }) {
|
||||
if (!isSettings) {
|
||||
return <ModalHeader>
|
||||
{children}
|
||||
</ModalHeader>;
|
||||
} else {
|
||||
return <Flex style={{ gap: "0" }}>
|
||||
{children}
|
||||
</Flex>;
|
||||
}
|
||||
}
|
||||
|
||||
function SelectorContent({ children, isSettings }: { children: ReactNode, isSettings?: boolean; }) {
|
||||
if (!isSettings) {
|
||||
return <ModalContent className="colorwaySelectorModalContent">{children}</ModalContent>;
|
||||
} else {
|
||||
return <>{children}</>;
|
||||
}
|
||||
}
|
||||
|
||||
export default function ({
|
||||
modalProps,
|
||||
isSettings
|
||||
}: {
|
||||
modalProps: ModalProps;
|
||||
modalProps: ModalProps,
|
||||
isSettings?: boolean;
|
||||
}): JSX.Element | any {
|
||||
const [currentColorway, setCurrentColorway] = useState<string>("");
|
||||
const [colorways, setColorways] = useState<Colorway[]>([]);
|
||||
|
@ -179,8 +218,8 @@ export default function ({
|
|||
}
|
||||
|
||||
return (
|
||||
<ModalRoot {...modalProps} className="colorwaySelectorModal">
|
||||
<ModalHeader>
|
||||
<SelectorContainer modalProps={modalProps} isSettings={isSettings}>
|
||||
<SelectorHeader isSettings={isSettings}>
|
||||
<Select className="colorwaySelector-pill colorwaySelector-pill_select" options={[{
|
||||
value: "all",
|
||||
label: "All"
|
||||
|
@ -221,6 +260,7 @@ export default function ({
|
|||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
style={{ marginLeft: "8px" }}
|
||||
id="colorway-refreshcolorway"
|
||||
onMouseEnter={isShown ? () => { } : onMouseEnter}
|
||||
|
@ -237,7 +277,7 @@ export default function ({
|
|||
y="0px"
|
||||
width="20"
|
||||
height="20"
|
||||
style={{ padding: "6px" }}
|
||||
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
|
@ -255,11 +295,12 @@ export default function ({
|
|||
</Popout>;
|
||||
}}
|
||||
</Tooltip>
|
||||
<Tooltip text="Open Settings">
|
||||
{!isSettings ? <Tooltip text="Open Settings">
|
||||
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
style={{ marginLeft: "8px" }}
|
||||
id="colorway-opensettings"
|
||||
onMouseEnter={onMouseEnter}
|
||||
|
@ -274,18 +315,19 @@ export default function ({
|
|||
role="img"
|
||||
width="20"
|
||||
height="20"
|
||||
style={{ padding: "6px" }}
|
||||
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.738 10H22V14H19.739C19.498 14.931 19.1 15.798 18.565 16.564L20 18L18 20L16.565 18.564C15.797 19.099 14.932 19.498 14 19.738V22H10V19.738C9.069 19.498 8.203 19.099 7.436 18.564L6 20L4 18L5.436 16.564C4.901 15.799 4.502 14.932 4.262 14H2V10H4.262C4.502 9.068 4.9 8.202 5.436 7.436L4 6L6 4L7.436 5.436C8.202 4.9 9.068 4.502 10 4.262V2H14V4.261C14.932 4.502 15.797 4.9 16.565 5.435L18 3.999L20 5.999L18.564 7.436C19.099 8.202 19.498 9.069 19.738 10ZM12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16Z" />
|
||||
</svg>
|
||||
</Button>}
|
||||
</Tooltip>
|
||||
</Tooltip> : <></>}
|
||||
<Tooltip text="Create Colorway...">
|
||||
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
style={{ marginLeft: "8px" }}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
|
@ -300,7 +342,7 @@ export default function ({
|
|||
role="img"
|
||||
width="20"
|
||||
height="20"
|
||||
style={{ padding: "6px" }}
|
||||
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
|
@ -315,32 +357,34 @@ export default function ({
|
|||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
style={{ marginLeft: "8px" }}
|
||||
id="colorway-opencolorstealer"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => openModal((props) => <ColorPickerModal modalProps={props} />)}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" style={{ padding: "6px" }} fill="currentColor" viewBox="0 0 16 16">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" style={{ padding: "6px", boxSizing: "content-box" }} fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M12.433 10.07C14.133 10.585 16 11.15 16 8a8 8 0 1 0-8 8c1.996 0 1.826-1.504 1.649-3.08-.124-1.101-.252-2.237.351-2.92.465-.527 1.42-.237 2.433.07zM8 5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM5 6.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" />
|
||||
</svg>
|
||||
</Button>}
|
||||
</Tooltip>
|
||||
<Tooltip text="Close">
|
||||
{!isSettings ? <Tooltip text="Close">
|
||||
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
id="colorwaySelector-pill_closeSelector"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => modalProps.onClose()}
|
||||
>
|
||||
<CloseIcon style={{ padding: "6px" }} width={20} height={20} />
|
||||
<CloseIcon style={{ padding: "6px", boxSizing: "content-box" }} width={20} height={20} />
|
||||
</Button>}
|
||||
</Tooltip>
|
||||
</ModalHeader>
|
||||
<ModalContent className="colorwaySelectorModalContent">
|
||||
</Tooltip> : <></>}
|
||||
</SelectorHeader>
|
||||
<SelectorContent isSettings={isSettings}>
|
||||
<div className="colorwaysLoader-barContainer"><div className="colorwaysLoader-bar" style={{ height: loaderHeight }} /></div>
|
||||
<ScrollerThin style={{ maxHeight: "450px" }} className="ColorwaySelectorWrapper">
|
||||
{visibleColorwayArray.length === 0 &&
|
||||
|
@ -364,101 +408,105 @@ export default function ({
|
|||
];
|
||||
return (
|
||||
<Tooltip text={color.name}>
|
||||
{({ onMouseEnter, onMouseLeave }) => <div
|
||||
className={"discordColorway" + (currentColorway === color.name ? "" : "")}
|
||||
id={"colorway-" + color.name}
|
||||
data-last-official={ind + 1 === colorways.length}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<div
|
||||
className="colorwayInfoIconContainer"
|
||||
onClick={() => openModal((props) => <ColorwayInfoModal
|
||||
modalProps={props}
|
||||
colorwayProps={color}
|
||||
discrimProps={customColorways.includes(color)}
|
||||
loadUIProps={cached_loadUI}
|
||||
/>)}
|
||||
>
|
||||
<div className="colorwayInfoIcon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayCheckIconContainer">
|
||||
<div className="colorwayCheckIcon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle r="8" cx="12" cy="12" fill="var(--white-500)" />
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="var(--brand-500)" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="discordColorwayPreviewColorContainer"
|
||||
onClick={async () => {
|
||||
const [
|
||||
onDemandWays,
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
] = await DataStore.getMany([
|
||||
"onDemandWays",
|
||||
"onDemandWaysTintedText",
|
||||
"onDemandWaysDiscordSaturation"
|
||||
]);
|
||||
if (currentColorway === color.name) {
|
||||
DataStore.set("actveColorwayID", null);
|
||||
DataStore.set("actveColorway", null);
|
||||
ColorwayCSS.remove();
|
||||
} else {
|
||||
DataStore.set("activeColorwayColors", color.colors);
|
||||
DataStore.set("actveColorwayID", color.name);
|
||||
if (onDemandWays) {
|
||||
const demandedColorway = generateCss(
|
||||
colorToHex(color.primary),
|
||||
colorToHex(color.secondary),
|
||||
colorToHex(color.tertiary),
|
||||
colorToHex(color.accent),
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
);
|
||||
DataStore.set("actveColorway", demandedColorway);
|
||||
ColorwayCSS.set(demandedColorway);
|
||||
} else {
|
||||
DataStore.set("actveColorway", color["dc-import"]);
|
||||
ColorwayCSS.set(color["dc-import"]);
|
||||
}
|
||||
{({ onMouseEnter, onMouseLeave }) => {
|
||||
return (
|
||||
<div
|
||||
className="discordColorway"
|
||||
id={"colorway-" + color.name}
|
||||
data-last-official={
|
||||
ind + 1 === colorways.length
|
||||
}
|
||||
setCurrentColorway(await DataStore.get("actveColorwayID") as string);
|
||||
}}
|
||||
>
|
||||
{colors.map((colorItm) => <div
|
||||
className="discordColorwayPreviewColor"
|
||||
style={{ backgroundColor: color[colorItm] }}
|
||||
/>)}
|
||||
</div>
|
||||
{currentColorway === color.name && <SelectionCircle />}
|
||||
</div>}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={async () => {
|
||||
const [
|
||||
onDemandWays,
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
] = await DataStore.getMany([
|
||||
"onDemandWays",
|
||||
"onDemandWaysTintedText",
|
||||
"onDemandWaysDiscordSaturation"
|
||||
]);
|
||||
if (currentColorway === color.name) {
|
||||
DataStore.set("actveColorwayID", null);
|
||||
DataStore.set("actveColorway", null);
|
||||
ColorwayCSS.remove();
|
||||
} else {
|
||||
DataStore.set("activeColorwayColors", color.colors);
|
||||
DataStore.set("actveColorwayID", color.name);
|
||||
if (onDemandWays) {
|
||||
const demandedColorway = !color.isGradient ? generateCss(
|
||||
colorToHex(color.primary),
|
||||
colorToHex(color.secondary),
|
||||
colorToHex(color.tertiary),
|
||||
colorToHex(color.accent),
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
) : gradientBase(colorToHex(color.accent), onDemandWaysDiscordSaturation) + `:root:root {--custom-theme-background: linear-gradient(${color.linearGradient})}`;
|
||||
DataStore.set("actveColorway", demandedColorway);
|
||||
ColorwayCSS.set(demandedColorway);
|
||||
} else {
|
||||
DataStore.set("actveColorway", color["dc-import"]);
|
||||
ColorwayCSS.set(color["dc-import"]);
|
||||
}
|
||||
}
|
||||
setCurrentColorway(await DataStore.get("actveColorwayID") as string);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="colorwayInfoIconContainer"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openModal((props) => (
|
||||
<ColorwayInfoModal
|
||||
modalProps={
|
||||
props
|
||||
}
|
||||
colorwayProps={
|
||||
color
|
||||
}
|
||||
discrimProps={customColorways.includes(
|
||||
color
|
||||
)}
|
||||
loadUIProps={cached_loadUI}
|
||||
/>
|
||||
));
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="discordColorwayPreviewColorContainer">
|
||||
{!color.isGradient ? colors.map((colorItm) => <div
|
||||
className="discordColorwayPreviewColor"
|
||||
style={{
|
||||
backgroundColor: color[colorItm],
|
||||
}}
|
||||
/>) : <div
|
||||
className="discordColorwayPreviewColor"
|
||||
style={{
|
||||
background: `linear-gradient(${color.linearGradient})`,
|
||||
}}
|
||||
/>}
|
||||
</div>
|
||||
{currentColorway === color.name && <SelectionCircle />}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</ScrollerThin>
|
||||
</ModalContent >
|
||||
</ModalRoot >
|
||||
</SelectorContent>
|
||||
</SelectorContainer >
|
||||
);
|
||||
}
|
|
@ -125,35 +125,5 @@ export default function () {
|
|||
</Button>
|
||||
</Flex>
|
||||
</Forms.FormSection>
|
||||
<Forms.FormDivider className={Margins.top8 + " " + Margins.bottom8} />
|
||||
<Forms.FormSection title="Developer Options:">
|
||||
<Button
|
||||
size={Button.Sizes.SMALL}
|
||||
onClick={async () => {
|
||||
const colorwaySourceFiles = await DataStore.get(
|
||||
"colorwaySourceFiles"
|
||||
);
|
||||
const responses: Response[] = await Promise.all(
|
||||
colorwaySourceFiles.map((url: string) =>
|
||||
fetch(url)
|
||||
)
|
||||
);
|
||||
const data = await Promise.all(
|
||||
responses.map((res: Response) =>
|
||||
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||
));
|
||||
const colorwaysArr: Colorway[] = data.flatMap(json => json.url === defaultColorwaySource ? json.colorways : []);
|
||||
|
||||
colorwaysArr.forEach((color: Colorway) => {
|
||||
if (IS_DISCORD_DESKTOP) {
|
||||
DiscordNative.fileManager.saveWithDialog(generateCss(color.primary.split("#")[1] || "313338", color.secondary.split("#")[1] || "2b2d31", color.tertiary.split("#")[1] || "1e1f22", color.accent.split("#")[1] || "5865f2", true, true), `import_${color.name.replaceAll(" ", "-").replaceAll("'", "")}.css`);
|
||||
} else {
|
||||
saveFile(new File([generateCss(color.primary.split("#")[1] || "313338", color.secondary.split("#")[1] || "2b2d31", color.tertiary.split("#")[1] || "1e1f22", color.accent.split("#")[1] || "5865f2", true, true)], `import_${color.name.replaceAll(" ", "-").replaceAll("'", "")}.css`, { type: "text/plain;charset=utf-8" }));
|
||||
}
|
||||
});
|
||||
}}>
|
||||
Update all official Colorways and export
|
||||
</Button>
|
||||
</Forms.FormSection>
|
||||
</SettingsTab>;
|
||||
}
|
||||
|
|
|
@ -1,445 +0,0 @@
|
|||
/*
|
||||
* Vencord, a Discord client mod
|
||||
* Copyright (c) 2023 Vendicated and contributors
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/* eslint-disable arrow-parens */
|
||||
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import { Flex } from "@components/Flex";
|
||||
import { SettingsTab } from "@components/VencordSettings/shared";
|
||||
import { openModal } from "@utils/modal";
|
||||
import { findByPropsLazy } from "@webpack";
|
||||
import {
|
||||
Button,
|
||||
Forms,
|
||||
Menu,
|
||||
Popout,
|
||||
Select,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "@webpack/common";
|
||||
|
||||
import { ColorwayCSS } from "../..";
|
||||
import { defaultColorwaySource, fallbackColorways } from "../../constants";
|
||||
import { generateCss } from "../../css";
|
||||
import { Colorway } from "../../types";
|
||||
import { colorToHex } from "../../utils";
|
||||
import ColorPickerModal from "../ColorPicker";
|
||||
import CreatorModal from "../CreatorModal";
|
||||
import ColorwayInfoModal from "../InfoModal";
|
||||
|
||||
const { SelectionCircle } = findByPropsLazy("SelectionCircle");
|
||||
|
||||
export default function ({
|
||||
visibleTabProps = "all",
|
||||
}: {
|
||||
visibleTabProps?: string;
|
||||
}): JSX.Element | any {
|
||||
const [currentColorway, setCurrentColorway] = useState<string>("");
|
||||
const [colorways, setColorways] = useState<Colorway[]>([]);
|
||||
const [thirdPartyColorways, setThirdPartyColorways] = useState<Colorway[]>([]);
|
||||
const [customColorways, setCustomColorways] = useState<Colorway[]>([]);
|
||||
const [searchString, setSearchString] = useState<string>("");
|
||||
const [loaderHeight, setLoaderHeight] = useState<string>("2px");
|
||||
const [visibility, setVisibility] = useState<string>(visibleTabProps);
|
||||
const [showReloadMenu, setShowReloadMenu] = useState(false);
|
||||
let visibleColorwayArray: Colorway[];
|
||||
|
||||
switch (visibility) {
|
||||
case "all":
|
||||
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||
break;
|
||||
case "official":
|
||||
visibleColorwayArray = [...colorways];
|
||||
break;
|
||||
case "3rdparty":
|
||||
visibleColorwayArray = [...thirdPartyColorways];
|
||||
break;
|
||||
case "custom":
|
||||
visibleColorwayArray = [...customColorways];
|
||||
break;
|
||||
default:
|
||||
visibleColorwayArray = [...colorways, ...thirdPartyColorways, ...customColorways];
|
||||
break;
|
||||
}
|
||||
|
||||
async function loadUI() {
|
||||
const colorwaySourceFiles = await DataStore.get(
|
||||
"colorwaySourceFiles"
|
||||
);
|
||||
const responses: Response[] = await Promise.all(
|
||||
colorwaySourceFiles.map((url: string) =>
|
||||
fetch(url)
|
||||
)
|
||||
);
|
||||
const data = await Promise.all(
|
||||
responses.map((res: Response) =>
|
||||
res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; })
|
||||
));
|
||||
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||
const baseData = await DataStore.getMany([
|
||||
"customColorways",
|
||||
"actveColorwayID",
|
||||
]);
|
||||
setColorways(colorways || fallbackColorways);
|
||||
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||
setCustomColorways(baseData[0]);
|
||||
setCurrentColorway(baseData[1]);
|
||||
}
|
||||
|
||||
const cached_loadUI = useCallback(loadUI, [setColorways, setCustomColorways, setCurrentColorway]);
|
||||
|
||||
async function searchColorways(e: string) {
|
||||
if (!e) {
|
||||
cached_loadUI();
|
||||
return;
|
||||
}
|
||||
const colorwaySourceFiles = await DataStore.get("colorwaySourceFiles");
|
||||
const data = await Promise.all(
|
||||
colorwaySourceFiles.map((url: string) =>
|
||||
fetch(url).then((res) => res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; }))
|
||||
)
|
||||
);
|
||||
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||
const baseData = await DataStore.get("customColorways");
|
||||
var results: Colorway[] = [];
|
||||
(colorways || fallbackColorways).find((Colorway: Colorway) => {
|
||||
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||
results.push(Colorway);
|
||||
});
|
||||
var thirdPartyResults: Colorway[] = [];
|
||||
(thirdPartyColorwaysArr).find((Colorway: Colorway) => {
|
||||
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||
thirdPartyResults.push(Colorway);
|
||||
});
|
||||
var customResults: Colorway[] = [];
|
||||
baseData.find((Colorway: Colorway) => {
|
||||
if (Colorway.name.toLowerCase().includes(e.toLowerCase()))
|
||||
customResults.push(Colorway);
|
||||
});
|
||||
setColorways(results);
|
||||
setThirdPartyColorways(thirdPartyResults);
|
||||
setCustomColorways(customResults);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!searchString) {
|
||||
cached_loadUI();
|
||||
}
|
||||
setLoaderHeight("0px");
|
||||
}, [searchString]);
|
||||
|
||||
function ReloadPopout(onClose: () => void) {
|
||||
return (
|
||||
<Menu.Menu
|
||||
navId="dc-reload-menu"
|
||||
onClose={onClose}
|
||||
>
|
||||
<Menu.MenuItem
|
||||
id="dc-force-reload"
|
||||
label="Force Reload"
|
||||
action={async () => {
|
||||
setLoaderHeight("2px");
|
||||
const colorwaySourceFiles = await DataStore.get(
|
||||
"colorwaySourceFiles"
|
||||
);
|
||||
const responses: Response[] = await Promise.all(
|
||||
colorwaySourceFiles.map((url: string) =>
|
||||
fetch(url, { cache: "no-store" })
|
||||
)
|
||||
);
|
||||
const data = await Promise.all(
|
||||
responses.map((res: Response) => {
|
||||
setLoaderHeight("0px");
|
||||
return res.json().then(dt => { return { colorways: dt.colorways, url: res.url }; }).catch(() => { return { colorways: [], url: res.url }; });
|
||||
}
|
||||
));
|
||||
const colorways = data.flatMap((json) => json.url === defaultColorwaySource ? json.colorways : []);
|
||||
const thirdPartyColorwaysArr = data.flatMap((json) => json.url !== defaultColorwaySource ? json.colorways : []);
|
||||
const baseData = await DataStore.getMany([
|
||||
"customColorways",
|
||||
"actveColorwayID",
|
||||
]);
|
||||
setColorways(colorways || fallbackColorways);
|
||||
setThirdPartyColorways(thirdPartyColorwaysArr);
|
||||
setCustomColorways(baseData[0]);
|
||||
setCurrentColorway(baseData[1]);
|
||||
}}
|
||||
/>
|
||||
</Menu.Menu>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsTab title="Colors">
|
||||
<div className="colorwaysSettingsSelector-wrapper">
|
||||
<Flex style={{ gap: "0" }}>
|
||||
<Select className="colorwaySelector-pill colorwaySelector-pill_select" options={[{
|
||||
value: "all",
|
||||
label: "All"
|
||||
},
|
||||
{
|
||||
value: "official",
|
||||
label: "Official"
|
||||
},
|
||||
{
|
||||
value: "3rdparty",
|
||||
label: "3rd-Party"
|
||||
},
|
||||
{
|
||||
value: "custom",
|
||||
label: "Custom"
|
||||
}]} select={value => {
|
||||
setVisibility(value);
|
||||
}} isSelected={value => visibility === value} serialize={String} />
|
||||
<TextInput
|
||||
inputClassName="colorwaySelector-searchInput"
|
||||
className="colorwaySelector-search"
|
||||
placeholder="Search for Colorways..."
|
||||
value={searchString}
|
||||
onChange={(e: string) => [searchColorways, setSearchString].forEach(t => t(e))}
|
||||
/>
|
||||
<Tooltip text="Refresh Colorways...">
|
||||
{({ onMouseEnter, onMouseLeave }) => {
|
||||
return <Popout
|
||||
position="bottom"
|
||||
align="right"
|
||||
animation={Popout.Animation.NONE}
|
||||
shouldShow={showReloadMenu}
|
||||
onRequestClose={() => setShowReloadMenu(false)}
|
||||
renderPopout={() => ReloadPopout(() => setShowReloadMenu(false))}
|
||||
>
|
||||
{(_, { isShown }) => (
|
||||
<Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
style={{ marginLeft: "8px" }}
|
||||
id="colorway-refreshcolorway"
|
||||
onMouseEnter={isShown ? () => { } : onMouseEnter}
|
||||
onMouseLeave={isShown ? () => { } : onMouseLeave}
|
||||
onClick={() => {
|
||||
setLoaderHeight("2px");
|
||||
cached_loadUI().then(() => setLoaderHeight("0px"));
|
||||
}}
|
||||
onContextMenu={() => { onMouseLeave(); setShowReloadMenu(v => !v); }}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="20"
|
||||
height="20"
|
||||
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<rect
|
||||
y="0"
|
||||
fill="none"
|
||||
width="24"
|
||||
height="24"
|
||||
/>
|
||||
<path d="M6.351,6.351C7.824,4.871,9.828,4,12,4c4.411,0,8,3.589,8,8h2c0-5.515-4.486-10-10-10 C9.285,2,6.779,3.089,4.938,4.938L3,3v6h6L6.351,6.351z" />
|
||||
<path d="M17.649,17.649C16.176,19.129,14.173,20,12,20c-4.411,0-8-3.589-8-8H2c0,5.515,4.486,10,10,10 c2.716,0,5.221-1.089,7.062-2.938L21,21v-6h-6L17.649,17.649z" />
|
||||
</svg>
|
||||
</Button>
|
||||
)}
|
||||
</Popout>;
|
||||
}}
|
||||
</Tooltip>
|
||||
<Tooltip text="Create Colorway...">
|
||||
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
style={{ marginLeft: "8px" }}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => openModal((props) => <CreatorModal
|
||||
modalProps={props}
|
||||
loadUIProps={cached_loadUI}
|
||||
/>)}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
width="20"
|
||||
height="20"
|
||||
style={{ padding: "6px", boxSizing: "content-box" }}
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M20 11.1111H12.8889V4H11.1111V11.1111H4V12.8889H11.1111V20H12.8889V12.8889H20V11.1111Z"
|
||||
/>
|
||||
</svg>
|
||||
</Button>}
|
||||
</Tooltip>
|
||||
<Tooltip text="Open Color Stealer">
|
||||
{({ onMouseEnter, onMouseLeave }) => <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.PRIMARY}
|
||||
style={{ marginLeft: "8px" }}
|
||||
id="colorway-opencolorstealer"
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
onClick={() => openModal((props) => <ColorPickerModal modalProps={props} />)}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" style={{ padding: "6px", boxSizing: "content-box" }} fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M12.433 10.07C14.133 10.585 16 11.15 16 8a8 8 0 1 0-8 8c1.996 0 1.826-1.504 1.649-3.08-.124-1.101-.252-2.237.351-2.92.465-.527 1.42-.237 2.433.07zM8 5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zM5 6.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" />
|
||||
</svg>
|
||||
</Button>}
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
<div className="colorwaysLoader-barContainer"><div className="colorwaysLoader-bar" style={{ height: loaderHeight }} /></div>
|
||||
<div className="ColorwaySelectorWrapper">
|
||||
{visibleColorwayArray.length === 0 &&
|
||||
<Forms.FormTitle
|
||||
style={{
|
||||
marginBottom: 0,
|
||||
width: "100%",
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
No colorways...
|
||||
</Forms.FormTitle>
|
||||
}
|
||||
{visibleColorwayArray.map((color, ind) => {
|
||||
var colors: Array<string> = color.colors || [
|
||||
"accent",
|
||||
"primary",
|
||||
"secondary",
|
||||
"tertiary",
|
||||
];
|
||||
return (
|
||||
<Tooltip text={color.name}>
|
||||
{({ onMouseEnter, onMouseLeave }) => {
|
||||
return (
|
||||
<div
|
||||
className="discordColorway"
|
||||
id={"colorway-" + color.name}
|
||||
data-last-official={
|
||||
ind + 1 === colorways.length
|
||||
}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
<div
|
||||
className="colorwayInfoIconContainer"
|
||||
onClick={() => {
|
||||
openModal((props) => (
|
||||
<ColorwayInfoModal
|
||||
modalProps={
|
||||
props
|
||||
}
|
||||
colorwayProps={
|
||||
color
|
||||
}
|
||||
discrimProps={customColorways.includes(
|
||||
color
|
||||
)}
|
||||
loadUIProps={cached_loadUI}
|
||||
/>
|
||||
));
|
||||
}}
|
||||
>
|
||||
<div className="colorwayInfoIcon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayCheckIconContainer">
|
||||
<div className="colorwayCheckIcon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle r="8" cx="12" cy="12" fill="var(--white-500)" />
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="var(--brand-500)" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="discordColorwayPreviewColorContainer"
|
||||
onClick={async () => {
|
||||
const [
|
||||
onDemandWays,
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
] = await DataStore.getMany([
|
||||
"onDemandWays",
|
||||
"onDemandWaysTintedText",
|
||||
"onDemandWaysDiscordSaturation"
|
||||
]);
|
||||
if (currentColorway === color.name) {
|
||||
DataStore.set("actveColorwayID", null);
|
||||
DataStore.set("actveColorway", null);
|
||||
ColorwayCSS.remove();
|
||||
} else {
|
||||
DataStore.set("activeColorwayColors", color.colors);
|
||||
DataStore.set("actveColorwayID", color.name);
|
||||
if (onDemandWays) {
|
||||
const demandedColorway = generateCss(
|
||||
colorToHex(color.primary),
|
||||
colorToHex(color.secondary),
|
||||
colorToHex(color.tertiary),
|
||||
colorToHex(color.accent),
|
||||
onDemandWaysTintedText,
|
||||
onDemandWaysDiscordSaturation
|
||||
);
|
||||
DataStore.set("actveColorway", demandedColorway);
|
||||
ColorwayCSS.set(demandedColorway);
|
||||
} else {
|
||||
DataStore.set("actveColorway", color["dc-import"]);
|
||||
ColorwayCSS.set(color["dc-import"]);
|
||||
}
|
||||
}
|
||||
setCurrentColorway(await DataStore.get("actveColorwayID") as string);
|
||||
}}
|
||||
>
|
||||
{colors.map((colorItm) => {
|
||||
return (
|
||||
<div
|
||||
className="discordColorwayPreviewColor"
|
||||
style={{
|
||||
// prettier-ignore
|
||||
backgroundColor: color[colorItm],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{currentColorway === color.name && <SelectionCircle />}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</SettingsTab>
|
||||
);
|
||||
}
|
|
@ -27,7 +27,6 @@ import { versionData } from "userplugins/discordColorways";
|
|||
|
||||
import { defaultColorwaySource, fallbackColorways, knownColorwaySources } from "../../constants";
|
||||
import { Colorway } from "../../types";
|
||||
import Divider from "../Divider";
|
||||
import { CloseIcon } from "../Icons";
|
||||
|
||||
export default function () {
|
||||
|
@ -165,7 +164,8 @@ export default function () {
|
|||
&& <Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={async () => {
|
||||
var sourcesArr: string[] = [];
|
||||
const colorwaySourceFilesArr = await DataStore.get("colorwaySourceFiles");
|
||||
|
@ -183,7 +183,8 @@ export default function () {
|
|||
<Button
|
||||
innerClassName="colorwaysSettings-iconButtonInner"
|
||||
size={Button.Sizes.ICON}
|
||||
color={Button.Colors.TRANSPARENT}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
onClick={() => { Clipboard.copy(colorwaySourceFile); }}
|
||||
>
|
||||
<CopyIcon width={20} height={20} />
|
||||
|
@ -191,7 +192,7 @@ export default function () {
|
|||
</div>
|
||||
)}
|
||||
</Flex>
|
||||
<Divider />
|
||||
<Forms.FormDivider style={{ margin: "20px 0" }} />
|
||||
<Forms.FormTitle tag="h5">Quick Switch</Forms.FormTitle>
|
||||
<Switch
|
||||
value={colorsButtonVisibility}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { ModalProps, ModalRoot, openModal } from "@utils/modal";
|
||||
import {
|
||||
Forms,
|
||||
Text,
|
||||
|
@ -31,15 +32,137 @@ export default function ({
|
|||
previewCSS?: string;
|
||||
}) {
|
||||
const [collapsed, setCollapsed] = useState<boolean>(isCollapsed);
|
||||
function ThemePreview({
|
||||
accent,
|
||||
primary,
|
||||
secondary,
|
||||
tertiary,
|
||||
isModal,
|
||||
modalProps
|
||||
}: {
|
||||
accent: string,
|
||||
primary: string,
|
||||
secondary: string,
|
||||
tertiary: string,
|
||||
isModal?: boolean,
|
||||
modalProps?: ModalProps;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="colorwaysPreview-wrapper"
|
||||
style={{ background: `var(--bg-overlay-app-frame, ${tertiary})` }}
|
||||
>
|
||||
<div className="colorwaysPreview-titlebar" />
|
||||
<div className="colorwaysPreview-body">
|
||||
<div className="colorwayPreview-guilds">
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ background: `var(--bg-guild-button, ${primary})` }}
|
||||
onMouseEnter={e => e.currentTarget.style.background = accent}
|
||||
onMouseLeave={e => e.currentTarget.style.background = `var(--bg-guild-button, ${primary})`}
|
||||
onClick={() => {
|
||||
if (isModal) {
|
||||
modalProps?.onClose();
|
||||
} else {
|
||||
openModal((props: ModalProps) => <ModalRoot className="colorwaysPreview-modal" {...props}>
|
||||
<style>
|
||||
{previewCSS}
|
||||
</style>
|
||||
<ThemePreview accent={accent} primary={primary} secondary={secondary} tertiary={tertiary} isModal modalProps={props} />
|
||||
</ModalRoot>);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isModal ? <CloseIcon style={{ color: "var(--header-secondary)" }} /> : <svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19,3H14V5h5v5h2V5A2,2,0,0,0,19,3Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19,19H14v2h5a2,2,0,0,0,2-2V14H19Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M3,5v5H5V5h5V3H5A2,2,0,0,0,3,5Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M5,14H3v5a2,2,0,0,0,2,2h5V19H5Z"
|
||||
/>
|
||||
</svg>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div className="colorwayPreview-guildSeparator" style={{ backgroundColor: primary }} />
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ background: `var(--bg-guild-button, ${primary})` }}
|
||||
onMouseEnter={e => e.currentTarget.style.background = accent}
|
||||
onMouseLeave={e => e.currentTarget.style.background = `var(--bg-guild-button, ${primary})`}
|
||||
/>
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ background: `var(--bg-guild-button, ${primary})` }}
|
||||
onMouseEnter={e => e.currentTarget.style.background = accent}
|
||||
onMouseLeave={e => e.currentTarget.style.background = `var(--bg-guild-button, ${primary})`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-channels" style={{ background: `var(--bg-overlay-3, ${secondary})` }}>
|
||||
<div
|
||||
className="colorwayPreview-userArea"
|
||||
style={{
|
||||
background: `var(--bg-secondary-alt, hsl(${HexToHSL(secondary)[0]} ${HexToHSL(secondary)[1]}% ${Math.max(HexToHSL(secondary)[2] - 3.6, 0)}%))`
|
||||
}}
|
||||
/>
|
||||
<div className="colorwayPreview-filler" />
|
||||
<div
|
||||
className="colorwayPreview-topShadow"
|
||||
style={{
|
||||
"--primary-900-hsl": `${HexToHSL(tertiary)[0]} ${HexToHSL(tertiary)[1]}% ${Math.max(HexToHSL(tertiary)[2] - (3.6 * 6), 0)}%`,
|
||||
"--primary-500-hsl": `${HexToHSL(primary)[0]} ${HexToHSL(primary)[1]}% ${Math.min(HexToHSL(primary)[2] + (3.6 * 3), 100)}%`
|
||||
} as React.CSSProperties}
|
||||
>
|
||||
<Text
|
||||
tag="div"
|
||||
variant="text-md/semibold"
|
||||
lineClamp={1}
|
||||
selectable={false}
|
||||
>
|
||||
Preview
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-chat" style={{ background: `var(--bg-overlay-chat, ${primary})` }}>
|
||||
<div
|
||||
className="colorwayPreview-chatBox"
|
||||
style={{
|
||||
background: `var(--bg-overlay-3, hsl(${HexToHSL(primary)[0]} ${HexToHSL(primary)[1]}% ${Math.min(HexToHSL(primary)[2] + 3.6, 100)}%))`
|
||||
}}
|
||||
/>
|
||||
<div className="colorwayPreview-filler" />
|
||||
<div
|
||||
className="colorwayPreview-topShadow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
`${collapsed === true
|
||||
? "colorwaysPreview colorwaysPreview-collapsed"
|
||||
: "colorwaysPreview"
|
||||
} ${className}`
|
||||
}
|
||||
>
|
||||
<div className={`${collapsed ? "colorwaysPreview colorwaysPreview-collapsed" : "colorwaysPreview"} ${className || ""}`}>
|
||||
<div
|
||||
className="colorwaysCreator-settingItm colorwaysCreator-settingHeader"
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
|
@ -80,143 +203,3 @@ export default function ({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ThemePreview({
|
||||
accent,
|
||||
primary,
|
||||
secondary,
|
||||
tertiary,
|
||||
previewCSS
|
||||
}: {
|
||||
accent: string,
|
||||
primary: string,
|
||||
secondary: string,
|
||||
tertiary: string,
|
||||
previewCSS?: string;
|
||||
}) {
|
||||
const [isFullscreen, setIsFullscreen] = useState<boolean>(false);
|
||||
return (
|
||||
<div
|
||||
className="colorwaysPreview-container"
|
||||
>
|
||||
<style>
|
||||
{previewCSS}
|
||||
</style>
|
||||
<div
|
||||
className="colorwaysPreview-wrapper"
|
||||
style={{ backgroundColor: tertiary }}
|
||||
>
|
||||
<div className="colorwaysPreview-titlebar" />
|
||||
<div className="colorwaysPreview-body">
|
||||
<div className="colorwayPreview-guilds">
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ backgroundColor: primary }}
|
||||
onMouseEnter={e => e.currentTarget.style.backgroundColor = accent}
|
||||
onMouseLeave={e => e.currentTarget.style.backgroundColor = primary}
|
||||
onClick={e => {
|
||||
if (!document.fullscreenElement) {
|
||||
e.currentTarget
|
||||
.parentElement
|
||||
?.parentElement
|
||||
?.parentElement
|
||||
?.parentElement
|
||||
?.requestFullscreen();
|
||||
} else {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
setIsFullscreen(!isFullscreen);
|
||||
}}
|
||||
>
|
||||
{isFullscreen ? <CloseIcon /> : <svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19,3H14V5h5v5h2V5A2,2,0,0,0,19,3Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19,19H14v2h5a2,2,0,0,0,2-2V14H19Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M3,5v5H5V5h5V3H5A2,2,0,0,0,3,5Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M5,14H3v5a2,2,0,0,0,2,2h5V19H5Z"
|
||||
/>
|
||||
</svg>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div className="colorwayPreview-guildSeparator" style={{ backgroundColor: primary }} />
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ backgroundColor: primary }}
|
||||
onMouseEnter={e => { e.currentTarget.style.backgroundColor = accent; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.backgroundColor = primary; }}
|
||||
/>
|
||||
</div>
|
||||
<div className="colorwayPreview-guild">
|
||||
<div
|
||||
className="colorwayPreview-guildItem"
|
||||
style={{ backgroundColor: primary }}
|
||||
onMouseEnter={e => { e.currentTarget.style.backgroundColor = accent; }}
|
||||
onMouseLeave={e => { e.currentTarget.style.backgroundColor = primary; }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-channels" style={{ backgroundColor: secondary }}>
|
||||
<div
|
||||
className="colorwayPreview-userArea"
|
||||
style={{
|
||||
backgroundColor: "hsl(" + HexToHSL(secondary)[0] + " " + HexToHSL(secondary)[1] + "% " + Math.max(HexToHSL(secondary)[2] - 3.6, 0) + "%)"
|
||||
}}
|
||||
/>
|
||||
<div className="colorwayPreview-filler" />
|
||||
<div
|
||||
className="colorwayPreview-topShadow"
|
||||
style={{
|
||||
"--primary-900-hsl": `${HexToHSL(tertiary)[0]} ${HexToHSL(tertiary)[1]}% ${Math.max(HexToHSL(tertiary)[2] - (3.6 * 6), 0)}%`,
|
||||
"--primary-500-hsl": `${HexToHSL(primary)[0]} ${HexToHSL(primary)[1]}% ${Math.min(HexToHSL(primary)[2] + (3.6 * 3), 100)}%`
|
||||
} as React.CSSProperties}
|
||||
>
|
||||
<Text
|
||||
tag="div"
|
||||
variant="text-md/semibold"
|
||||
lineClamp={1}
|
||||
selectable={false}
|
||||
>
|
||||
Preview
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div className="colorwayPreview-chat" style={{ backgroundColor: primary }}>
|
||||
<div
|
||||
className="colorwayPreview-chatBox"
|
||||
style={{
|
||||
backgroundColor: "hsl(" + HexToHSL(primary)[0] + " " + HexToHSL(primary)[1] + "% " + Math.min(HexToHSL(primary)[2] + 3.6, 100) + "%)"
|
||||
}}
|
||||
/>
|
||||
<div className="colorwayPreview-filler" />
|
||||
<div
|
||||
className="colorwayPreview-topShadow"
|
||||
style={{
|
||||
"--primary-900-hsl": `${HexToHSL(tertiary)[0]} ${HexToHSL(tertiary)[1]}% ${Math.max(HexToHSL(tertiary)[2] - (3.6 * 6), 0)}%`
|
||||
} as React.CSSProperties}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -315,3 +315,10 @@ export const knownThemeVars = {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const mainColors = [
|
||||
{ name: "accent", title: "Accent", var: "--brand-experiment" },
|
||||
{ name: "primary", title: "Primary", var: "--background-primary" },
|
||||
{ name: "secondary", title: "Secondary", var: "--background-secondary" },
|
||||
{ name: "tertiary", title: "Tertiary", var: "--background-tertiary" }
|
||||
];
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { Plugins } from "Vencord";
|
||||
|
||||
import { colorToHex, HexToHSL } from "./utils";
|
||||
import { HexToHSL } from "./utils";
|
||||
|
||||
export const colorVariables: string[] = [
|
||||
"brand-100",
|
||||
|
@ -290,9 +290,73 @@ const BrandLightDiffs = {
|
|||
900: -61.6
|
||||
};
|
||||
|
||||
function gradientBase(accentColor?: string, discordSaturation = false) {
|
||||
return `@import url(//dablulite.github.io/css-snippets/NoLightInDark/import.css);
|
||||
@import url(//dablulite.github.io/css-snippets/NitroThemesFix/import.css);
|
||||
export const pureGradientBase = `
|
||||
.theme-dark :is(.colorwaysPreview-modal, .colorwaysPreview) {
|
||||
--bg-overlay-color: 0 0 0;
|
||||
--bg-overlay-color-inverse: 255 255 255;
|
||||
--bg-overlay-opacity-1: 0.85;
|
||||
--bg-overlay-opacity-2: 0.8;
|
||||
--bg-overlay-opacity-3: 0.7;
|
||||
--bg-overlay-opacity-4: 0.5;
|
||||
--bg-overlay-opacity-5: 0.4;
|
||||
--bg-overlay-opacity-6: 0.1;
|
||||
--bg-overlay-opacity-hover: 0.5;
|
||||
--bg-overlay-opacity-hover-inverse: 0.08;
|
||||
--bg-overlay-opacity-active: 0.45;
|
||||
--bg-overlay-opacity-active-inverse: 0.1;
|
||||
--bg-overlay-opacity-selected: 0.4;
|
||||
--bg-overlay-opacity-selected-inverse: 0.15;
|
||||
--bg-overlay-opacity-chat: 0.8;
|
||||
--bg-overlay-opacity-home: 0.85;
|
||||
--bg-overlay-opacity-home-card: 0.8;
|
||||
--bg-overlay-opacity-app-frame: var(--bg-overlay-opacity-4);
|
||||
--bg-guild-button: rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6));
|
||||
--bg-secondary-alt: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-chat-header: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
}
|
||||
.theme-light :is(.colorwaysPreview-modal, .colorwaysPreview) {
|
||||
--bg-overlay-color: 255 255 255;
|
||||
--bg-overlay-color-inverse: 0 0 0;
|
||||
--bg-overlay-opacity-1: 0.9;
|
||||
--bg-overlay-opacity-2: 0.8;
|
||||
--bg-overlay-opacity-3: 0.7;
|
||||
--bg-overlay-opacity-4: 0.6;
|
||||
--bg-overlay-opacity-5: 0.3;
|
||||
--bg-overlay-opacity-6: 0.15;
|
||||
--bg-overlay-opacity-hover: 0.7;
|
||||
--bg-overlay-opacity-hover-inverse: 0.02;
|
||||
--bg-overlay-opacity-active: 0.65;
|
||||
--bg-overlay-opacity-active-inverse: 0.03;
|
||||
--bg-overlay-opacity-selected: 0.6;
|
||||
--bg-overlay-opacity-selected-inverse: 0.04;
|
||||
--bg-overlay-opacity-chat: 0.9;
|
||||
--bg-overlay-opacity-home: 0.7;
|
||||
--bg-overlay-opacity-home-card: 0.9;
|
||||
--bg-overlay-opacity-app-frame: var(--bg-overlay-opacity-5);
|
||||
--bg-guild-button: rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3));
|
||||
--bg-secondary-alt: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-chat-header: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
}
|
||||
.colorwaysPreview-modal,
|
||||
.colorwaysPreview {
|
||||
--bg-overlay-1: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-1))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-2: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-2))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-3: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-3))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-4: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-4)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-4))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-5: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-5)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-5))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-6: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-6))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-hover: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-hover-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-hover-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-hover)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-hover))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-active: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-active-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-active-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-active)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-active))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-selected: linear-gradient(rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-selected-inverse)),rgb(var(--bg-overlay-color-inverse)/var(--bg-overlay-opacity-selected-inverse))) fixed 0 0/cover,linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-selected)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-selected))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-chat: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-home: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-home-card: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
--bg-overlay-app-frame: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame))) fixed 0 0/cover,var(--gradient-theme-bg) fixed 0 0/cover;
|
||||
}`;
|
||||
|
||||
|
||||
export function gradientBase(accentColor?: string, discordSaturation = false) {
|
||||
return `@import url(//dablulite.github.io/css-snippets/NitroThemesFix/import.css);
|
||||
.theme-dark {
|
||||
--bg-overlay-color: 0 0 0;
|
||||
--bg-overlay-color-inverse: 255 255 255;
|
||||
|
@ -401,14 +465,11 @@ function gradientBase(accentColor?: string, discordSaturation = false) {
|
|||
--bg-overlay-chat: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-chat))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||
--bg-overlay-home: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||
--bg-overlay-home-card: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-home-card))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||
--bg-overlay-app-frame: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;`;
|
||||
--bg-overlay-app-frame: linear-gradient(rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame)),rgb(var(--bg-overlay-color)/var(--bg-overlay-opacity-app-frame))) fixed 0 0/cover,var(--custom-theme-background) fixed 0 0/cover;
|
||||
}`;
|
||||
}
|
||||
|
||||
export function generateCss(primaryColor: string, secondaryColor: string, tertiaryColor: string, accentColor: string, tintedText: boolean, discordSaturation: boolean) {
|
||||
primaryColor = colorToHex(primaryColor);
|
||||
secondaryColor = colorToHex(secondaryColor);
|
||||
tertiaryColor = colorToHex(tertiaryColor);
|
||||
accentColor = colorToHex(accentColor);
|
||||
const colorwayCss = `/*Automatically Generated - Colorway Creator V${(Plugins.plugins.DiscordColorways as any).creatorVersion}*/
|
||||
:root:root {
|
||||
--brand-100-hsl: ${HexToHSL("#" + accentColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + accentColor)[1] / 100) * (100 + BrandSatDiffs[100])) * 10) / 10 : HexToHSL("#" + accentColor)[1]}%) ${Math.max(Math.round((HexToHSL("#" + accentColor)[2] + BrandLightDiffs[100]) * 10) / 10, 0)};
|
||||
|
@ -446,7 +507,9 @@ export function generateCss(primaryColor: string, secondaryColor: string, tertia
|
|||
--primary-600-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + primaryColor)[1]}%) ${HexToHSL("#" + primaryColor)[2]}%;
|
||||
--primary-560-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + 3.6, 100)}%;
|
||||
--primary-530-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[530])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 2), 100)}%;
|
||||
--primary-500-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[500])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 3), 100)}%;${tintedText ? `\n --primary-460-hsl: 0 calc(var(--saturation-factor, 1)*0%) 50%;
|
||||
--primary-500-hsl: ${HexToHSL("#" + primaryColor)[0]} calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[500])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%) ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 3), 100)}%;
|
||||
--interactive-muted: hsl(${HexToHSL("#" + primaryColor)[0]} 0% ${Math.min(HexToHSL("#" + primaryColor)[2] + (3.6 * 3), 100)}%);
|
||||
${tintedText ? `--primary-460-hsl: 0 calc(var(--saturation-factor, 1)*0%) 50%;
|
||||
--primary-430: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[430])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};
|
||||
--primary-400: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[400])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};
|
||||
--primary-360: ${HexToHSL("#" + secondaryColor)[0] === 0 ? "gray" : ((HexToHSL("#" + secondaryColor)[2] < 80) ? "hsl(" + HexToHSL("#" + secondaryColor)[0] + `, calc(var(--saturation-factor, 1)*${discordSaturation ? Math.round(((HexToHSL("#" + primaryColor)[1] / 100) * (100 + PrimarySatDiffs[360])) * 10) / 10 : HexToHSL("#" + primaryColor)[1]}%), 90%)` : "hsl(" + HexToHSL("#" + secondaryColor)[0] + ", calc(var(--saturation-factor, 1)*100%), 20%)")};` : ""}
|
||||
|
@ -635,15 +698,22 @@ export function getPreset(primaryColor?: string, secondaryColor?: string, tertia
|
|||
}
|
||||
|
||||
function gradientType1(discordSaturation = false) {
|
||||
return `${gradientBase(accentColor, discordSaturation)}
|
||||
--custom-theme-background: linear-gradient(239.16deg, #${primaryColor} 10.39%, #${secondaryColor} 26.87%, #${tertiaryColor} 48.31%, hsl(${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + secondaryColor)[1]}%) ${Math.min(HexToHSL("#" + secondaryColor)[2] + 3.6, 100)}%) 64.98%, #${primaryColor} 92.5%);
|
||||
}`;
|
||||
return {
|
||||
full: `${gradientBase(accentColor, discordSaturation)}
|
||||
:root:root {
|
||||
--custom-theme-background: linear-gradient(239.16deg, #${primaryColor} 10.39%, #${secondaryColor} 26.87%, #${tertiaryColor} 48.31%, hsl(${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + secondaryColor)[1]}%) ${Math.min(HexToHSL("#" + secondaryColor)[2] + 3.6, 100)}%) 64.98%, #${primaryColor} 92.5%);
|
||||
}`,
|
||||
base: `239.16deg, #${primaryColor} 10.39%, #${secondaryColor} 26.87%, #${tertiaryColor} 48.31%, hsl(${HexToHSL("#" + secondaryColor)[0]} calc(var(--saturation-factor, 1)*${HexToHSL("#" + secondaryColor)[1]}%) ${Math.min(HexToHSL("#" + secondaryColor)[2] + 3.6, 100)}%) 64.98%, #${primaryColor} 92.5%`
|
||||
};
|
||||
}
|
||||
|
||||
function gradientType2(discordSaturation = false) {
|
||||
return `${gradientBase(accentColor, discordSaturation)}
|
||||
--custom-theme-background: linear-gradient(48.17deg, #${primaryColor} 11.21%, #${secondaryColor} 61.92%);
|
||||
}`;
|
||||
return {
|
||||
full: `${gradientBase(accentColor, discordSaturation)}
|
||||
:root:root {
|
||||
--custom-theme-background: linear-gradient(48.17deg, #${primaryColor} 11.21%, #${secondaryColor} 61.92%);
|
||||
}`, base: `48.17deg, #${primaryColor} 11.21%, #${secondaryColor} 61.92%`
|
||||
};
|
||||
}
|
||||
|
||||
function hueRotation(discordSaturation = false) {
|
||||
|
|
|
@ -19,10 +19,9 @@ import {
|
|||
import ColorPickerModal from "./components/ColorPicker";
|
||||
import ColorwaysButton from "./components/ColorwaysButton";
|
||||
import CreatorModal from "./components/CreatorModal";
|
||||
import SelectorModal from "./components/SelectorModal";
|
||||
import Selector from "./components/Selector";
|
||||
import ManageColorwaysPage from "./components/SettingsTabs/ManageColorwaysPage";
|
||||
import OnDemandWaysPage from "./components/SettingsTabs/OnDemandPage";
|
||||
import SelectorPage from "./components/SettingsTabs/SelectorPage";
|
||||
import SettingsPage from "./components/SettingsTabs/SettingsPage";
|
||||
import Spinner from "./components/Spinner";
|
||||
import { defaultColorwaySource } from "./constants";
|
||||
|
@ -95,8 +94,8 @@ export const ColorwayCSS = {
|
|||
};
|
||||
|
||||
export const versionData = {
|
||||
pluginVersion: "5.6.2",
|
||||
creatorVersion: "1.18.1",
|
||||
pluginVersion: "5.6.4.2",
|
||||
creatorVersion: "1.18.3",
|
||||
};
|
||||
|
||||
export default definePlugin({
|
||||
|
@ -111,7 +110,7 @@ export default definePlugin({
|
|||
pluginVersion: versionData.pluginVersion,
|
||||
creatorVersion: versionData.creatorVersion,
|
||||
toolboxActions: {
|
||||
"Change Colorway": () => openModal(props => <SelectorModal modalProps={props} />),
|
||||
"Change Colorway": () => openModal(props => <Selector modalProps={props} />),
|
||||
"Open Colorway Creator": () => openModal(props => <CreatorModal modalProps={props} />),
|
||||
"Open Color Stealer": () => openModal(props => <ColorPickerModal modalProps={props} />),
|
||||
"Open Settings": () => SettingsRouter.open("ColorwaysSettings"),
|
||||
|
@ -152,12 +151,12 @@ export default definePlugin({
|
|||
}
|
||||
}
|
||||
],
|
||||
|
||||
set ColorPicker(e) {
|
||||
ColorPicker = e;
|
||||
},
|
||||
|
||||
makeSettingsCategories(SectionTypes: Record<string, unknown>) {
|
||||
console.log(SectionTypes);
|
||||
return [
|
||||
{
|
||||
section: SectionTypes.HEADER,
|
||||
|
@ -167,7 +166,7 @@ export default definePlugin({
|
|||
{
|
||||
section: "ColorwaysSelector",
|
||||
label: "Colorways",
|
||||
element: SelectorPage,
|
||||
element: () => <Selector isSettings modalProps={{ onClose: () => new Promise(() => true), transitionState: 1 }} />,
|
||||
className: "dc-colorway-selector"
|
||||
},
|
||||
{
|
||||
|
@ -202,22 +201,20 @@ export default definePlugin({
|
|||
enableStyle(style);
|
||||
ColorwayCSS.set((await DataStore.get("actveColorway")) || "");
|
||||
|
||||
addAccessory("colorways-btn", props => {
|
||||
if (String(props.message.content).match(/colorway:[0-9a-f]{0,71}/))
|
||||
return <Button onClick={() => {
|
||||
openModal(propss => (
|
||||
<CreatorModal
|
||||
modalProps={propss}
|
||||
colorwayID={String(props.message.content).match(/colorway:[0-9a-f]{0,71}/)![0]}
|
||||
/>
|
||||
));
|
||||
}} size={Button.Sizes.SMALL} color={Button.Colors.PRIMARY}>Add this Colorway...</Button>;
|
||||
return null;
|
||||
});
|
||||
addAccessory("colorways-btn", props => String(props.message.content).match(/colorway:[0-9a-f]{0,100}/) ? <Button
|
||||
onClick={() => openModal(modalProps => <CreatorModal
|
||||
modalProps={modalProps}
|
||||
colorwayID={String(props.message.content).match(/colorway:[0-9a-f]{0,100}/)![0]}
|
||||
/>)}
|
||||
size={Button.Sizes.SMALL}
|
||||
color={Button.Colors.PRIMARY}
|
||||
look={Button.Looks.OUTLINED}
|
||||
>
|
||||
Add this Colorway...
|
||||
</Button> : null);
|
||||
},
|
||||
stop() {
|
||||
removeServerListElement(ServerListRenderPosition.In, this.ColorwaysButton);
|
||||
|
||||
disableStyle(style);
|
||||
ColorwayCSS.remove();
|
||||
removeAccessory("colorways-btn");
|
||||
|
|
|
@ -47,85 +47,26 @@
|
|||
border-radius: 50%;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
box-shadow: 0 0 0 1px var(--interactive-normal);
|
||||
box-shadow: 0 0 0 1.5px var(--interactive-normal);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.discordColorway::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
border-radius: 50%;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
pointer-events: none;
|
||||
transition: .15s;
|
||||
}
|
||||
|
||||
.discordColorway.active::before {
|
||||
box-shadow: inset 0 0 0 2px var(--brand-500), inset 0 0 0 4px var(--background-primary);
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColor {
|
||||
width: calc(50% - 2px);
|
||||
height: calc(50% - 2px);
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColor:first-child {
|
||||
margin-top: 2px;
|
||||
margin-left: 2px;
|
||||
border-top-left-radius: 52px;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColor:nth-child(2) {
|
||||
margin-top: 2px;
|
||||
margin-right: 2px;
|
||||
border-top-right-radius: 52px;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColor:nth-child(3) {
|
||||
margin-bottom: 2px;
|
||||
margin-left: 2px;
|
||||
border-bottom-left-radius: 52px;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColor:nth-child(4) {
|
||||
margin-bottom: 2px;
|
||||
margin-right: 2px;
|
||||
border-bottom-right-radius: 52px;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColorContainer:not(:has(>.discordColorwayPreviewColor:nth-child(2)))>.discordColorwayPreviewColor {
|
||||
height: calc(100% - 4px);
|
||||
width: calc(100% - 4px);
|
||||
margin: 2px;
|
||||
border-radius: 52px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColorContainer:not(:has(>.discordColorwayPreviewColor:nth-child(3)))>.discordColorwayPreviewColor {
|
||||
height: calc(100% - 4px);
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColorContainer:not(:has(>.discordColorwayPreviewColor:nth-child(3)))>.discordColorwayPreviewColor:nth-child(1) {
|
||||
border-top-left-radius: 52px;
|
||||
border-bottom-left-radius: 52px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColorContainer:not(:has(>.discordColorwayPreviewColor:nth-child(3)))>.discordColorwayPreviewColor:nth-child(2) {
|
||||
border-top-right-radius: 52px;
|
||||
border-bottom-right-radius: 52px;
|
||||
margin-right: 2px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.discordColorwayPreviewColorContainer:not(:has(>.discordColorwayPreviewColor:nth-child(4)))>.discordColorwayPreviewColor:nth-child(3) {
|
||||
width: calc(100% - 4px);
|
||||
margin-right: 2px;
|
||||
border-bottom-right-radius: 52px;
|
||||
border-bottom-left-radius: 52px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ColorwaySelectorWrapper {
|
||||
|
@ -138,6 +79,10 @@
|
|||
scrollbar-width: none !important;
|
||||
}
|
||||
|
||||
.ColorwaySelectorWrapper::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.colorwaySelectorModal {
|
||||
width: 100% !important;
|
||||
min-width: 596px !important;
|
||||
|
@ -163,42 +108,23 @@
|
|||
width: 72px;
|
||||
}
|
||||
|
||||
.colorwayCheckIconContainer {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: var(--brand-500);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
z-index: +1;
|
||||
}
|
||||
|
||||
.discordColorway.active .colorwayCheckIconContainer {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.colorwayCheckIcon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
color: var(--white-500);
|
||||
}
|
||||
|
||||
.colorwayInfoIconContainer {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
background-color: var(--brand-500);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
z-index: +1;
|
||||
color: var(--white-500);
|
||||
padding: 1px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.colorwayInfoIconContainer:hover {
|
||||
background-color: var(--brand-700);
|
||||
background-color: var(--brand-experiment-560);
|
||||
}
|
||||
|
||||
.discordColorway:hover .colorwayInfoIconContainer {
|
||||
|
@ -206,13 +132,6 @@
|
|||
transition: .15s;
|
||||
}
|
||||
|
||||
.colorwayInfoIcon {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
color: var(--white-500);
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.colorwayCreator-swatch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -240,9 +159,7 @@
|
|||
gap: 8px;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
background-color: var(--background-secondary);
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.colorwayCreator-colorInput {
|
||||
|
@ -466,8 +383,8 @@
|
|||
.colorwaysPreview-modal {
|
||||
max-width: unset !important;
|
||||
max-height: unset !important;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
.colorwaysPreview-titlebar {
|
||||
|
@ -652,7 +569,6 @@
|
|||
width: 100%;
|
||||
height: 32px;
|
||||
flex: 1 0 auto;
|
||||
transition: background-color .1s linear;
|
||||
font-family: var(--font-display);
|
||||
font-weight: 500;
|
||||
padding: 12px 16px;
|
||||
|
@ -1001,13 +917,28 @@
|
|||
box-sizing: border-box;
|
||||
min-height: 44px;
|
||||
align-items: center;
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
|
||||
.theme-dark .colorwaysSettings-colorwaySource {
|
||||
background: var(--bg-overlay-3,var(--background-secondary));
|
||||
}
|
||||
|
||||
.theme-light .colorwaysSettings-colorwaySource {
|
||||
background: var(--bg-overlay-2,var(--background-secondary));
|
||||
}
|
||||
|
||||
.colorwaysSettings-colorwaySource:hover {
|
||||
background-color: var(--background-secondary-alt);
|
||||
}
|
||||
|
||||
.theme-dark .colorwaysSettings-colorwaySource:hover {
|
||||
background: var(--bg-overlay-1,var(--background-secondary-alt));
|
||||
}
|
||||
|
||||
.theme-light .colorwaysSettings-colorwaySource:hover {
|
||||
background: var(--bg-overlay-3,var(--background-secondary-alt));
|
||||
}
|
||||
|
||||
.colorwaysSettings-modalRoot {
|
||||
min-width: 520px;
|
||||
}
|
||||
|
@ -1204,3 +1135,11 @@
|
|||
opacity: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dc-warning-card {
|
||||
padding: 1em;
|
||||
margin-bottom: 1em;
|
||||
background-color: var(--info-warning-background);
|
||||
border-color: var(--info-warning-foreground);
|
||||
color: var(--info-warning-text);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
export interface Colorway {
|
||||
[key: string]: any,
|
||||
name: string,
|
||||
"dc-import": string,
|
||||
accent: string,
|
||||
|
@ -17,7 +18,8 @@ export interface Colorway {
|
|||
colors?: string[],
|
||||
isGradient?: boolean,
|
||||
sourceUrl?: string,
|
||||
sourceName?: string;
|
||||
sourceName?: string,
|
||||
linearGradient?: string;
|
||||
}
|
||||
|
||||
export interface ColorPickerProps {
|
||||
|
|
Loading…
Reference in a new issue