Detailed changes
@@ -18,7 +18,9 @@
"chroma-js": "^2.4.2",
"deepmerge": "^4.3.0",
"toml": "^3.0.0",
- "ts-node": "^10.9.1"
+ "ts-deepmerge": "^6.0.3",
+ "ts-node": "^10.9.1",
+ "utility-types": "^3.10.0"
}
},
"node_modules/@cspotcode/source-map-support": {
@@ -180,6 +182,14 @@
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
},
+ "node_modules/ts-deepmerge": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-6.0.3.tgz",
+ "integrity": "sha512-MBBJL0UK/mMnZRONMz4J1CRu5NsGtsh+gR1nkn8KLE9LXo/PCzeHhQduhNary8m5/m9ryOOyFwVKxq81cPlaow==",
+ "engines": {
+ "node": ">=14.13.1"
+ }
+ },
"node_modules/ts-node": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
@@ -235,6 +245,14 @@
"node": ">=4.2.0"
}
},
+ "node_modules/utility-types": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
+ "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@@ -382,6 +400,11 @@
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
},
+ "ts-deepmerge": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-6.0.3.tgz",
+ "integrity": "sha512-MBBJL0UK/mMnZRONMz4J1CRu5NsGtsh+gR1nkn8KLE9LXo/PCzeHhQduhNary8m5/m9ryOOyFwVKxq81cPlaow=="
+ },
"ts-node": {
"version": "10.9.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
@@ -408,6 +431,11 @@
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"peer": true
},
+ "utility-types": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
+ "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg=="
+ },
"v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
@@ -20,7 +20,9 @@
"chroma-js": "^2.4.2",
"deepmerge": "^4.3.0",
"toml": "^3.0.0",
- "ts-node": "^10.9.1"
+ "ts-deepmerge": "^6.0.3",
+ "ts-node": "^10.9.1",
+ "utility-types": "^3.10.0"
},
"prettier": {
"semi": false,
@@ -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),
+ }
+
+ })
+ ,
+
+ }
}
@@ -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;
@@ -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 };
}