diff --git a/apps/color-buddy/src/App.svelte b/apps/color-buddy/src/App.svelte
index 775380e..26e4324 100644
--- a/apps/color-buddy/src/App.svelte
+++ b/apps/color-buddy/src/App.svelte
@@ -15,6 +15,50 @@
{},
$configStore.userName
);
+
+ // check if there's a palette specified in the url
+ const url = new URL(window.location.href);
+ // const colors = url.searchParams.get("colors");
+ // const background = url.searchParams.get("background") || "#ffffff";
+ // const palName = url.searchParams.get("palName");
+ // const space = url.searchParams.get("space");
+ const pal = deserializePaletteForUrl(window.location.href);
+ if (pal) {
+ colorStore.createNewPal(pal);
+ url.searchParams.delete("colors");
+ url.searchParams.delete("bg");
+ url.searchParams.delete("name");
+ url.searchParams.delete("space");
+ window.history.replaceState({}, "", url.toString());
+ }
+ // // } else
+ // if (colors) {
+ // console.log(colors, background, palName, space);
+ // let parsedColors = [];
+ // try {
+ // parsedColors = JSON.parse(colors || "[]");
+ // } catch (e) {
+ // console.error(e);
+ // }
+ // const newPal = makePalFromString(parsedColors, background);
+ // if (palName) {
+ // newPal.name = palName;
+ // }
+ // if (space) {
+ // newPal.colorSpace = space as any;
+ // }
+ // if (parsedColors.length > 0) {
+ // console.log("here", newPal);
+ // colorStore.createNewPal(newPal);
+ // }
+
+ // // remove the palette from the url
+ // url.searchParams.delete("colors");
+ // url.searchParams.delete("background");
+ // url.searchParams.delete("palName");
+ // url.searchParams.delete("space");
+ // window.history.replaceState({}, "", url.toString());
+ // }
});
// make sure no focused colors are out of bounds
@@ -43,11 +87,13 @@
import TourProvider from "./content-modules/TourProvider.svelte";
import Config from "./controls/Config.svelte";
import Title from "./controls/Title.svelte";
+ import SharePal from "./components/SharePal.svelte";
import { lint } from "./lib/api-calls";
import { debounce } from "vega";
import { buttonStyle } from "./lib/styles";
+ import { deserializePaletteForUrl } from "./lib/utils";
$: route = $configStore.route;
$: evalRoute = $configStore.evalDisplayMode;
@@ -114,6 +160,7 @@
Redo
+
diff --git a/apps/color-buddy/src/components/SharePal.svelte b/apps/color-buddy/src/components/SharePal.svelte
new file mode 100644
index 0000000..47ce966
--- /dev/null
+++ b/apps/color-buddy/src/components/SharePal.svelte
@@ -0,0 +1,44 @@
+
+
+
+
+
+
Share via url
+
+ {open && serializePaletteForUrl(palette)}
+
+
+
+ {#if copyState === "copied"}
+
Copied!
+ {/if}
+
+
+
+
+
+
diff --git a/apps/color-buddy/src/components/Tooltip.svelte b/apps/color-buddy/src/components/Tooltip.svelte
index 234102d..2c45718 100644
--- a/apps/color-buddy/src/components/Tooltip.svelte
+++ b/apps/color-buddy/src/components/Tooltip.svelte
@@ -129,7 +129,7 @@
}}
>
{/if}
-
+
diff --git a/apps/color-buddy/src/lib/utils.ts b/apps/color-buddy/src/lib/utils.ts
index 8723525..dd3e4ad 100644
--- a/apps/color-buddy/src/lib/utils.ts
+++ b/apps/color-buddy/src/lib/utils.ts
@@ -4,6 +4,7 @@ import {
makePalFromString,
} from "color-buddy-palette";
import type { Palette, StringPalette } from "color-buddy-palette";
+import queryString from "query-string";
import { Formatter, FracturedJsonOptions, EolStyle } from "fracturedjsonjs";
import fits from "../assets/outfits.json";
@@ -576,3 +577,36 @@ export function computeStroke(
}
return "none";
}
+
+export function serializePaletteForUrl(palette: Palette): string {
+ const colors = palette.colors.map((color) => color.toString());
+ const bg = palette.background.toString();
+ const name = palette.name;
+ const space = palette.colorSpace;
+ const params = { colors, bg, name, space };
+ console.log(params);
+ const str = queryString.stringify(params);
+ const prefix = window.location.origin + window.location.pathname;
+ return `${prefix}?&${str}`;
+}
+
+export function deserializePaletteForUrl(url: string): Palette | undefined {
+ const parsed = queryString.parse(url);
+ console.log(parsed);
+ const colorSpace = parsed.space as ColorSpace;
+ const colors = parsed.colors as string[];
+ const bg = parsed.bg as string;
+ const name = parsed.name as string;
+ console.log(name, bg, colors, colorSpace);
+ if (!colorSpace || !colors || !bg || !name) {
+ return undefined;
+ }
+ try {
+ const newPal = makePalFromString(colors, bg);
+ newPal.name = name;
+ return convertPalToSpace(newPal, colorSpace);
+ } catch (e) {
+ console.log(e);
+ return undefined;
+ }
+}
diff --git a/packages/color-namer/main.ts b/packages/color-namer/main.ts
index 0f5515c..9a907b8 100644
--- a/packages/color-namer/main.ts
+++ b/packages/color-namer/main.ts
@@ -33,7 +33,7 @@ export function nameColor(
const numResults = props?.numResults ?? 1;
const colors = props?.colors ?? heerStoneColors;
const listName = props?.colorListName ?? "heerStone";
- const str = `${color.toString().toUpperCase()}-${numResults}-${listName}`;
+ const str = `${color.toHex().toUpperCase()}-${numResults}-${listName}`;
if (nameCache.has(str)) {
return nameCache.get(str)!;
}
diff --git a/packages/palette-lint/package.json b/packages/palette-lint/package.json
index 2901136..a5c9daf 100644
--- a/packages/palette-lint/package.json
+++ b/packages/palette-lint/package.json
@@ -20,8 +20,8 @@
"rollup": "^4.18.0",
"ts-json-schema-generator": "^1.5.0",
"typescript": "^5.5.3",
- "vite-plugin-dts": "^4.0.0-beta.1",
"vite": "^5.2.0",
+ "vite-plugin-dts": "^4.0.0-beta.1",
"vitest": "^1.6.0"
},
"dependencies": {
@@ -29,7 +29,8 @@
"color-buddy-color-namer": "*",
"color-buddy-palette": "*",
"fracturedjsonjs": "^4.0.1",
- "ohm-js": "^17.1.0"
+ "ohm-js": "^17.1.0",
+ "query-string": "^9.1.1"
},
"license": "BSD-3-Clause",
"files": [
diff --git a/packages/palette/src/Color.ts b/packages/palette/src/Color.ts
index 6045e8e..e9bc3df 100644
--- a/packages/palette/src/Color.ts
+++ b/packages/palette/src/Color.ts
@@ -11,6 +11,7 @@ type DistAlgorithm = "76" | "CMC" | "2000" | "ITP" | "Jz" | "OK";
const ColorIOCaches = new Map();
const InGamutCache = new Map();
const colorStateCache = new Map();
+const distCache = new Map();
/**
* The base class for all color spaces
@@ -178,16 +179,28 @@ export class Color {
return val;
}
distance(color: Color, space: string): number {
+ const key = `distance-${this.toString()}-${color.toString()}-${space}`;
+ if (distCache.has(key)) {
+ return distCache.get(key)!;
+ }
const colorSpace = space || this.spaceName;
const targetSpace = space === "rgb" ? "srgb" : colorSpace;
const left = this.toColorIO().to(targetSpace);
const right = color.toColorIO().to(targetSpace);
- return left.distance(right);
+ const val = left.distance(right);
+ distCache.set(key, val);
+ return val;
}
symmetricDeltaE(color: Color, algorithm: DistAlgorithm = "2000"): number {
+ const key = `${this.toString()}-${color.toString()}-${algorithm}`;
+ if (distCache.has(key)) {
+ return distCache.get(key)!;
+ }
const left = this.deltaE(color, algorithm);
const right = color.deltaE(this, algorithm);
- return 0.5 * (left + right);
+ const val = 0.5 * (left + right);
+ distCache.set(key, val);
+ return val;
}
copy(): Color {
return this.fromChannels(this.toChannels());
diff --git a/yarn.lock b/yarn.lock
index b4d8eda..0b520f4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2314,11 +2314,6 @@
resolved "https://registry.npmjs.org/@types/color-namer/-/color-namer-1.3.3.tgz"
integrity sha512-DJ0MHHqazwb94dUBRhahK49nXhRGk2DIRNrVNVR3U3uQjYWY4uNhEjHXO+TbFQGpZcwli1pCj6xm3S3KsB/+3A==
-"@types/color-thief-node@^1.0.4":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@types/color-thief-node/-/color-thief-node-1.0.4.tgz#33b250895de87ed7090dce44bee2b19a419acbb6"
- integrity sha512-9mHoSyLAojvDQsZWxu3FHhiwUsQC7Lfuxrii6rnYc11uJ7GH2ODaM82gyDCXnR/5eXqlOymauUXU5eCEYAHS4A==
-
"@types/d3-array@*":
version "3.2.1"
resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz"
@@ -4653,6 +4648,11 @@ decimal.js@^10.4.3:
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz"
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
+decode-uri-component@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz#2ac4859663c704be22bf7db760a1494a49ab2cc5"
+ integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==
+
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz"
@@ -8754,6 +8754,15 @@ qs@^6.9.6:
dependencies:
side-channel "^1.0.6"
+query-string@^9.1.1:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-9.1.1.tgz#dbfebb4196aeb2919915f2b2b81b91b965cf03a0"
+ integrity sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==
+ dependencies:
+ decode-uri-component "^0.4.1"
+ filter-obj "^5.1.0"
+ split-on-first "^3.0.0"
+
querystringify@^2.1.1:
version "2.2.0"
resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz"
@@ -9536,6 +9545,11 @@ speakingurl@^14.0.1:
resolved "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz"
integrity sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==
+split-on-first@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-3.0.0.tgz#f04959c9ea8101b9b0bbf35a61b9ebea784a23e7"
+ integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==
+
split2@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/split2/-/split2-1.1.1.tgz"