Implement Toggleable<T> and Interactive<T> properly

This commit is contained in:
Piotr Osiewicz
2023-06-20 16:05:23 -07:00
committed by Mikayla Maki
parent c47d1e9f51
commit 198a446b03
5 changed files with 104 additions and 42 deletions
+30 -23
View File
@@ -1,30 +1,37 @@
import { ColorScheme } from "../theme/colorScheme"
import { withOpacity } from "../theme/color"
import { text, background } from "./components"
import { toggleable } from "./toggle"
import { interactive } from "./interactive"
export default function commandPalette(colorScheme: ColorScheme) {
let layer = colorScheme.highest
return {
keystrokeSpacing: 8,
key: {
text: text(layer, "mono", "variant", "default", { size: "xs" }),
cornerRadius: 2,
background: background(layer, "on"),
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
},
margin: {
top: 1,
bottom: 1,
left: 2,
},
active: {
text: text(layer, "mono", "on", "default", { size: "xs" }),
background: withOpacity(background(layer, "on"), 0.2),
},
let layer = colorScheme.highest
return {
keystrokeSpacing: 8,
key:
toggleable(interactive({
text: text(layer, "mono", "variant", "default", { size: "xs" }),
cornerRadius: 2,
background: background(layer, "on"),
padding: {
top: 1,
bottom: 1,
left: 6,
right: 6,
},
}
margin: {
top: 1,
bottom: 1,
left: 2,
},
}, { hover: { cornerRadius: 4, padding: { top: 17 } } }), {
default: {
text: text(layer, "mono", "on", "default", { size: "xs" }),
background: withOpacity(background(layer, "on"), 0.2),
}
})
,
}
}
+13 -6
View File
@@ -1,3 +1,5 @@
import { DeepPartial } from "utility-types";
import merge from "ts-deepmerge"
interface Interactive<T> {
default: T,
hover?: T,
@@ -5,21 +7,26 @@ interface Interactive<T> {
disabled?: T,
}
export function interactive<T>(base: T, modifications: Partial<Interactive<T>>): Interactive<T> {
const interactiveObj: Interactive<T> = {
// Helper function for creating Interactive<T> objects that works pretty much like Toggle<T>.
// It takes a object to be used as a value for `default` field and then fills out other fields
// with fields from either `base` or `modifications`. Notably, it does not touch `hover`, `clicked` and `disabled` if there are no modifications for it.
export function interactive<T extends Object>(base: T, modifications: DeepPartial<Interactive<T>>): Interactive<T> {
let interactiveObj: Interactive<T> = {
default: base,
};
if (modifications.default !== undefined) {
interactiveObj.default = merge(interactiveObj.default, modifications.default) as T;
}
if (modifications.hover !== undefined) {
interactiveObj.hover = { ...base, ...modifications.hover };
interactiveObj.hover = merge(interactiveObj.default, modifications.hover) as T;
}
if (modifications.clicked !== undefined) {
interactiveObj.clicked = { ...base, ...modifications.clicked };
interactiveObj.clicked = merge(interactiveObj.default, modifications.clicked) as T;
}
if (modifications.disabled !== undefined) {
interactiveObj.disabled = { ...base, ...modifications.disabled };
interactiveObj.disabled = merge(interactiveObj.default, modifications.disabled) as T;
}
return interactiveObj;
+29 -11
View File
@@ -1,17 +1,35 @@
import { DeepPartial } from 'utility-types';
import merge from 'ts-deepmerge';
interface Toggleable<T> {
inactive: T
active: T,
}
export function toggleable<T>(inactive: T, modifications: Partial<Toggleable<T>>): Toggleable<T> {
let active: T = inactive;
if (modifications.active !== undefined) {
active = { ...inactive, ...modifications.active };
}
return {
inactive: inactive,
active: active
};
d
/// Helper function for creating Toggleable objects; it takes a object of type T that is used as
/// `inactive` member of result Toggleable<T>. `active` member is created by applying `modifications` on top of `inactive` argument.
// Thus, the following call:
// ```
// toggleable({day: 1, month: "January"}, {day: 3})
// ```
// To return the following object:
// ```
// Toggleable<_>{
// inactive: { day: 1, month: "January" },
// active: { day: 3, month: "January" }
// }
// ```
// Remarkably, it also works for nested structures:
// ```
// toggleable({first_level: "foo", second_level: {nested_member: "nested"}}, {second_level: {nested_member: "another nested thing"}})
// ```
// ```
// Toggleable<_> {
// inactive: {first_level: "foo", second_level: {nested_member: "nested"}},
// active: { first_level: "foo", second_level: {nested_member: "another nested thing"}}
// }
// ```
export function toggleable<T extends Object>(inactive: T, modifications: DeepPartial<T>): Toggleable<T> {
let active: T = merge(inactive, modifications) as T;
return { active: active, inactive: inactive };
}