Skip to content

Commit

Permalink
Fix #16
Browse files Browse the repository at this point in the history
  • Loading branch information
mgmeyers committed Aug 6, 2021
1 parent 2159392 commit ac68e68
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 36 deletions.
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,59 @@ settings:
*/
```

## `class-multi-toggle`

`class-multi-toggle` creates a dropdown of predefined options for a CSS variable. The `id` of the setting will be used as the variable name.

- When `allowEmpty` is `false`, a `default` option **must** be specified.
- When `allowEmpty` is `true`, the `default` attribute is optional, and may be set to `none`.

```css
/* @settings
name: Your Section Name Here
id: a-unique-id
settings:
-
id: theme-variant
title: Theme variant
description: Variations on a theme
type: class-multi-toggle
allowEmpty: false
default: my-class
options:
- my-class
- my-other-class
- and-yet-another
*/
```

Options may also be given a label:

```css
/* @settings
name: Your Section Name Here
id: a-unique-id
settings:
-
id: theme-variant
title: Theme variant
description: Variations on a theme
type: class-multi-toggle
allowEmpty: false
default: my-class
options:
-
label: My Class
value: my-class
-
label: My Other Class
value: my-other-class
*/
```

## `variable-text`

`variable-text` represents any text based CSS value. The `id` of the setting will be used as the variable name. `variable-text` settings require a `default` attribute.
Expand Down Expand Up @@ -207,6 +260,30 @@ settings:
*/
```

Options can optionally be given a label:

```css
/* @settings
name: Your Section Name Here
id: a-unique-id
settings:
-
id: text
title: UI font
description: Font used for the user interface
type: variable-select
default: Roboto
options:
-
label: The best font
value: Roboto
-
label: The next best font
value: Helvetica Neue
*/
```

This will output the variable:

```
Expand Down
18 changes: 17 additions & 1 deletion src/SettingsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
VariableText,
ColorFormat,
AltFormatList,
ClassMultiToggle,
} from "./settingHandlers";
import chroma from "chroma-js";
import {
Expand Down Expand Up @@ -269,6 +270,19 @@ export class CSSSettingsManager {
if (this.getSetting(section, settingId)) {
document.body.classList.add(setting.id);
}
} else if (setting.type === "class-multi-toggle") {
const multiToggle = setting as ClassMultiToggle;
let value = this.getSetting(section, settingId) as string | undefined;

if (value === undefined && !!multiToggle.default) {
value = multiToggle.default;
} else if (value === undefined) {
value = "none";
}

if (value !== "none") {
document.body.classList.add(value);
}
}
});
});
Expand Down Expand Up @@ -495,7 +509,9 @@ export class ImportModal extends Modal {

new Setting(contentEl)
.setName("Import style setting")
.setDesc("Import an entire or partial configuration. Warning: this may override existing settings");
.setDesc(
"Import an entire or partial configuration. Warning: this may override existing settings"
);

new Setting(contentEl).then((setting) => {
// Build an error message container
Expand Down
111 changes: 109 additions & 2 deletions src/settingHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,97 @@ export function createClassToggle(opts: {
});
}

interface SelectOption {
label: string;
value: string;
}

export interface ClassMultiToggle extends Meta {
default?: string;
allowEmpty: boolean;
options: Array<string | SelectOption>;
}

export function createClassMultiToggle(opts: {
sectionId: string;
config: ClassMultiToggle;
containerEl: HTMLElement;
settingsManager: CSSSettingsManager;
}): CleanupFunction {
const { sectionId, config, containerEl, settingsManager } = opts;

let dropdownComponent: DropdownComponent;

if (typeof config.default !== "string") {
return console.error(`Error: ${config.title} missing default value`);
}

let prevValue = settingsManager.getSetting(sectionId, config.id) as
| string
| undefined;

if (prevValue === undefined && !!config.default) {
prevValue = config.default;
} else if (prevValue === undefined) {
prevValue = "none";
}

new Setting(containerEl)
.setName(config.title)
.setDesc(createDescription(config.description, config.default))
.addDropdown((dropdown) => {
if (config.allowEmpty) {
dropdown.addOption("none", "");
}

config.options.forEach((o) => {
if (typeof o === "string") {
dropdown.addOption(o, o);
} else {
dropdown.addOption(o.value, o.label);
}
});

dropdown.setValue(prevValue).onChange((value) => {
settingsManager.setSetting(sectionId, config.id, value);

if (value !== "none") {
document.body.classList.add(value);
}

if (prevValue) {
document.body.classList.remove(prevValue);
}

prevValue = value;
});

dropdownComponent = dropdown;
})
.addExtraButton((b) => {
b.setIcon("reset");
b.onClick(() => {
const value = config.default || "none";

dropdownComponent.setValue(config.default || "none");

if (value !== "none") {
document.body.classList.add(value);
}

if (prevValue) {
document.body.classList.remove(prevValue);
}

settingsManager.clearSetting(sectionId, config.id);
});
b.setTooltip(resetTooltip);
})
.then((setting) => {
setting.settingEl.dataset.id = opts.config.id;
});
}

export interface VariableText extends Meta {
default: string;
}
Expand Down Expand Up @@ -312,7 +403,7 @@ export function createVariableNumberSlider(opts: {

export interface VariableSelect extends Meta {
default: string;
options: string[];
options: Array<string | SelectOption>;
}

export function createVariableSelect(opts: {
Expand All @@ -334,7 +425,13 @@ export function createVariableSelect(opts: {
.addDropdown((dropdown) => {
const value = settingsManager.getSetting(sectionId, config.id);

config.options.forEach((o) => dropdown.addOption(o, o));
config.options.forEach((o) => {
if (typeof o === "string") {
dropdown.addOption(o, o);
} else {
dropdown.addOption(o.value, o.label);
}
});

dropdown
.setValue(value !== undefined ? (value as string) : config.default)
Expand Down Expand Up @@ -796,6 +893,16 @@ export function createSettings(opts: {
});
break;
}
case "class-multi-toggle": {
pushId(setting.id);
createClassMultiToggle({
sectionId,
config: setting as ClassMultiToggle,
containerEl: getTargetContainer(containerStack),
settingsManager,
});
break;
}
case "variable-text": {
pushId(setting.id);
createVariableText({
Expand Down
66 changes: 33 additions & 33 deletions styles.css
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
.pcr-app .pcr-swatches > button {
padding: 0;
}

.pickr .pcr-button {
margin-right: 0;
}

.themed-color-wrapper > div {
background: var(--background-primary);
padding: 10px;
display: flex;
align-items: center;
border-radius: 4px;
}

.themed-color-wrapper > div + div {
margin-top: 6px;
}

.themed-color-wrapper button {
display: block;
}

.themed-color-wrapper .pickr-reset > button {
margin: 0 0 0 10px;
padding: 9px;
line-height: 1;
}

.themed-color-wrapper .pickr-reset > button > svg {
display: block;
}
.style-settings-heading {
cursor: pointer;
margin-bottom: 18px;
Expand Down Expand Up @@ -197,4 +164,37 @@
.style-settings-import-error.active {
display: block;
}
.pcr-app .pcr-swatches > button {
padding: 0;
}

.pickr .pcr-button {
margin-right: 0;
}

.themed-color-wrapper > div {
background: var(--background-primary);
padding: 10px;
display: flex;
align-items: center;
border-radius: 4px;
}

.themed-color-wrapper > div + div {
margin-top: 6px;
}

.themed-color-wrapper button {
display: block;
}

.themed-color-wrapper .pickr-reset > button {
margin: 0 0 0 10px;
padding: 9px;
line-height: 1;
}

.themed-color-wrapper .pickr-reset > button > svg {
display: block;
}
/*! Pickr 1.8.0 MIT | https://github.com/Simonwep/pickr */.pickr{position:relative;overflow:visible;transform:translateY(0)}.pickr *{box-sizing:border-box;outline:none;border:none;-webkit-appearance:none}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;cursor:pointer;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;border-radius:.15em;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" stroke="%2342445A" stroke-width="5px" stroke-linecap="round"><path d="M45,45L5,5"></path><path d="M45,5L5,45"></path></svg>') no-repeat 50%;background-size:0;transition:all .3s}.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;z-index:-1;z-index:auto}.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;border-radius:.15em}.pickr .pcr-button:after{transition:background .3s;background:currentColor}.pickr .pcr-button.clear{background-size:70%}.pickr .pcr-button.clear:before{opacity:0}.pickr .pcr-button.clear:focus{box-shadow:0 0 0 1px hsla(0,0%,100%,.85),0 0 0 3px currentColor}.pickr .pcr-button.disabled{cursor:not-allowed}.pcr-app *,.pickr *{box-sizing:border-box;outline:none;border:none;-webkit-appearance:none}.pcr-app button.pcr-active,.pcr-app button:focus,.pcr-app input.pcr-active,.pcr-app input:focus,.pickr button.pcr-active,.pickr button:focus,.pickr input.pcr-active,.pickr input:focus{box-shadow:0 0 0 1px hsla(0,0%,100%,.85),0 0 0 3px currentColor}.pcr-app .pcr-palette,.pcr-app .pcr-slider,.pickr .pcr-palette,.pickr .pcr-slider{transition:box-shadow .3s}.pcr-app .pcr-palette:focus,.pcr-app .pcr-slider:focus,.pickr .pcr-palette:focus,.pickr .pcr-slider:focus{box-shadow:0 0 0 1px hsla(0,0%,100%,.85),0 0 0 3px rgba(0,0,0,.25)}.pcr-app{position:fixed;display:flex;flex-direction:column;z-index:10000;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity .3s,visibility 0s .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-shadow:0 .15em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.03);left:0;top:0}.pcr-app.visible{transition:opacity .3s;visibility:visible;opacity:1}.pcr-app .pcr-swatches{display:flex;flex-wrap:wrap;margin-top:.75em}.pcr-app .pcr-swatches.pcr-last{margin:0}@supports (display:grid){.pcr-app .pcr-swatches{display:grid;align-items:center;grid-template-columns:repeat(auto-fit,1.75em)}}.pcr-app .pcr-swatches>button{font-size:1em;position:relative;width:calc(1.75em - 5px);height:calc(1.75em - 5px);border-radius:.15em;cursor:pointer;margin:2.5px;flex-shrink:0;justify-self:center;transition:all .15s;overflow:hidden;background:transparent;z-index:1}.pcr-app .pcr-swatches>button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:6px;border-radius:.15em;z-index:-1}.pcr-app .pcr-swatches>button:after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:currentColor;border:1px solid rgba(0,0,0,.05);border-radius:.15em;box-sizing:border-box}.pcr-app .pcr-swatches>button:hover{filter:brightness(1.05)}.pcr-app .pcr-swatches>button:not(.pcr-active){box-shadow:none}.pcr-app .pcr-interaction{display:flex;flex-wrap:wrap;align-items:center;margin:0 -.2em}.pcr-app .pcr-interaction>*{margin:0 .2em}.pcr-app .pcr-interaction input{letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#75797e;background:#f1f3f4;border-radius:.15em;transition:all .15s;padding:.45em .5em;margin-top:.75em}.pcr-app .pcr-interaction input:hover{filter:brightness(.975)}.pcr-app .pcr-interaction input:focus{box-shadow:0 0 0 1px hsla(0,0%,100%,.85),0 0 0 3px rgba(66,133,244,.75)}.pcr-app .pcr-interaction .pcr-result{color:#75797e;text-align:left;flex:1 1 8em;min-width:8em;transition:all .2s;border-radius:.15em;background:#f1f3f4;cursor:text}.pcr-app .pcr-interaction .pcr-result::-moz-selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{width:auto;color:#fff}.pcr-app .pcr-interaction .pcr-cancel:hover,.pcr-app .pcr-interaction .pcr-clear:hover,.pcr-app .pcr-interaction .pcr-save:hover{filter:brightness(.925)}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear{background:#f44250}.pcr-app .pcr-interaction .pcr-cancel:focus,.pcr-app .pcr-interaction .pcr-clear:focus{box-shadow:0 0 0 1px hsla(0,0%,100%,.85),0 0 0 3px rgba(244,66,80,.75)}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:column;cursor:grab;cursor:-webkit-grab}.pcr-app .pcr-selection .pcr-color-chooser:active,.pcr-app .pcr-selection .pcr-color-opacity:active,.pcr-app .pcr-selection .pcr-color-palette:active{cursor:grabbing;cursor:-webkit-grabbing}.pcr-app[data-theme=nano]{width:14.25em;max-width:95vw}.pcr-app[data-theme=nano] .pcr-swatches{margin-top:.6em;padding:0 .6em}.pcr-app[data-theme=nano] .pcr-interaction{padding:0 .6em .6em}.pcr-app[data-theme=nano] .pcr-selection{display:grid;grid-gap:.6em;grid-template-columns:1fr 4fr;grid-template-rows:5fr auto auto;align-items:center;height:10.5em;width:100%;align-self:flex-start}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview{grid-area:2/1/4/1;height:100%;width:100%;display:flex;flex-direction:row;justify-content:center;margin-left:.6em}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-last-color{display:none}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color{position:relative;background:currentColor;width:2em;height:2em;border-radius:50em;overflow:hidden}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-preview .pcr-current-color:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette{grid-area:1/1/2/3;width:100%;height:100%;z-index:1}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette{border-radius:.15em;width:100%;height:100%}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser{grid-area:2/2/2/2}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity{grid-area:3/2/3/2}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity{height:.5em;margin:0 .6em}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-picker{top:50%;transform:translateY(-50%)}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider{flex-grow:1;border-radius:50em}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(90deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.pcr-app[data-theme=nano] .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(90deg,transparent,#000),url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:100%,.25em}

0 comments on commit ac68e68

Please sign in to comment.