diff --git a/docs/_layouts/palette.njk b/docs/_layouts/palette.njk index 5469caca9..2aa640849 100644 --- a/docs/_layouts/palette.njk +++ b/docs/_layouts/palette.njk @@ -23,7 +23,7 @@ 'tweaking-gray-chroma': tweaking.grayChroma, 'tweaked-chroma': tweaked?.chroma, 'tweaked-hue': tweaked?.hue, - 'tweaked-any': tweaksHumanReadable.length, + 'tweaked-any': Object.keys(tweaksHumanReadable).length, }" :style="{ '--chroma-scale': chromaScale, @@ -35,12 +35,19 @@
{% include 'breadcrumbs.njk' %} -

- {% raw %}{{ saved.title }}{% endraw %} - - +

+ {{ title }} + + + + + + + + Save{% raw %}{{ unsavedChanges ? '' : 'd' }}{% endraw %} +

-

{{ title }}

.wa-palette-{{ paletteId }} @@ -86,13 +93,6 @@ Reset - - - - - - Save - @@ -321,8 +321,21 @@ Add the following code at the top of your CSS file: - {% endmarkdown %} + +
+

Saved {{ 'custom palettes' if page.fileSlug == 'custom' else title + ' variations' }}

+ + +
+ {# {% include "svgs/palette.njk" %} #} +
+ +
+
+
+ +
{# end palette app #} {% endblock %} diff --git a/docs/assets/scripts/sidebar-tweaks.js b/docs/assets/scripts/sidebar-tweaks.js index 1c245717d..67929be70 100644 --- a/docs/assets/scripts/sidebar-tweaks.js +++ b/docs/assets/scripts/sidebar-tweaks.js @@ -13,23 +13,33 @@ sidebar.palettes = { sidebar.updateCurrent(); }, - updateSaved() { - this.saved = localStorage.savedPalettes ? JSON.parse(localStorage.savedPalettes) : []; + saved: [], + + /** + * Update saved palettes from local storage + */ + fromLocalStorage() { + // Replace contents of array without breaking references + let saved = localStorage.savedPalettes ? JSON.parse(localStorage.savedPalettes) : []; + this.saved.splice(0, this.saved.length, ...saved); }, - save(saved = this.saved) { - this.saved = saved ?? []; - - if (saved.length > 0) { - localStorage.savedPalettes = JSON.stringify(saved); + /** + * Write palettes to local storage + */ + toLocalStorage() { + if (this.saved.length > 0) { + localStorage.savedPalettes = JSON.stringify(this.saved); } else { delete localStorage.savedPalettes; } }, }; -sidebar.palettes.updateSaved(); -addEventListener('storage', event => sidebar.palettes.updateSaved()); +sidebar.palettes.fromLocalStorage(); + +// Palettes were updated in another tab +addEventListener('storage', () => sidebar.palettes.fromLocalStorage()); sidebar.palette = { getUid() { @@ -59,7 +69,9 @@ sidebar.palette = { delete(palette) { let savedPalettes = sidebar.palettes.saved; let count = savedPalettes.length; - if (count === 0) { + + if (count === 0 || !palette.uid) { + // No stored palettes or this palette has not been saved return; } @@ -68,7 +80,9 @@ sidebar.palette = { return; } - savedPalettes = savedPalettes.filter(p => !sidebar.palette.equals(palette, p)); + for (let index; index > -1; index = savedPalettes.findIndex(p => p.uid === palette.uid)) { + savedPalettes.splice(index, 1); + } if (savedPalettes.length === count) { // Nothing was removed @@ -96,17 +110,14 @@ sidebar.palette = { sidebar.updateCurrent(); - sidebar.palettes.save(savedPalettes); + sidebar.palettes.toLocalStorage(); - if (sidebar.palette.equals(globalThis.paletteApp?.saved, palette)) { + if (globalThis.paletteApp?.saved?.uid === palette.uid) { + // We deleted the currently active palette paletteApp.postDelete(); } }, - getSaved(palette, savedPalettes = sidebar.palettes.saved) { - return savedPalettes.find(p => sidebar.palette.equals(p, palette)); - }, - render(palette) { // Find existing let { title, id, search, uid } = palette; @@ -146,23 +157,27 @@ sidebar.palette = { } }, - save(palette, saved) { - let savedPalettes = sidebar.palettes.saved; - let existing = this.getSaved(saved ?? palette, savedPalettes); - let oldValues; - - if (existing) { - // Rename - oldValues = { ...existing }; - Object.assign(existing, palette); - } else { - savedPalettes.push(palette); + /** + * Save a palette, either by updating its existing entry or creating a new one + * @param {object} palette + */ + save(palette) { + if (!palette.uid) { + // First time saving + palette.uid = this.getUid(); } + let savedPalettes = sidebar.palettes.saved; + let existingIndex = palette.uid ? sidebar.palettes.saved.findIndex(p => p.uid === palette.uid) : -1; + let newIndex = existingIndex > -1 ? existingIndex : savedPalettes.length; + + let [oldValues] = sidebar.palettes.saved.splice(newIndex, 1, palette); + this.render(palette, oldValues); sidebar.updateCurrent(); + sidebar.palettes.toLocalStorage(); - sidebar.palettes.save(savedPalettes); + return palette; }, }; diff --git a/docs/docs/palettes/edit/tweak.css b/docs/docs/palettes/edit/tweak.css index c70d9ae01..e091b924a 100644 --- a/docs/docs/palettes/edit/tweak.css +++ b/docs/docs/palettes/edit/tweak.css @@ -286,3 +286,7 @@ wa-dropdown > .color.swatch { margin-right: 0.4em; } } + +.title wa-icon-button[name='pencil'] { + margin-inline-start: var(--wa-space-xs); +} diff --git a/docs/docs/palettes/edit/tweak.js b/docs/docs/palettes/edit/tweak.js index 2cdd63fee..a8e91d6b5 100644 --- a/docs/docs/palettes/edit/tweak.js +++ b/docs/docs/palettes/edit/tweak.js @@ -79,7 +79,8 @@ let paletteAppSpec = { grayColor: undefined, tweaking: {}, saved: null, - factor: 1.2, + unsavedChanges: false, + savedPalettes: sidebar.palettes.saved, }; }, @@ -118,9 +119,8 @@ let paletteAppSpec = { if (this.permalink.has('uid')) { this.uid = Number(this.permalink.get('uid')); + this.saved = sidebar.palettes.saved.find(p => p.uid === this.uid); } - - this.saved = sidebar.palette.getSaved(this.getPalette()); } }, @@ -128,9 +128,26 @@ let paletteAppSpec = { for (let ref in this.$refs) { this.$refs[ref].tooltipFormatter = percentFormatter; } + + nextTick().then(() => { + this.unsavedChanges = false; + }); }, computed: { + isCustom() { + return this.paletteId === 'custom'; + }, + + /** Default palette title for saving */ + defaultPaletteTitle() { + if (this.isCustom) { + return 'My Palette'; + } else { + return this.paletteTitle + ' (tweaked)'; + } + }, + seedColorObjects() { return this.seedColors .map(color => { @@ -401,6 +418,11 @@ let paletteAppSpec = { } return ret; }, + + /** Get other variants of the same base palette that are not this one */ + savedVariations() { + return this.savedPalettes.filter(palette => palette.id === this.paletteId && palette.uid !== this.uid); + }, }, watch: { @@ -430,6 +452,10 @@ let paletteAppSpec = { handler() { this.permalink.set('color', this.seedColors); this.permalink.updateLocation(); + + if (this.saved || this.isCustom) { + this.unsavedChanges = true; + } }, }, @@ -441,8 +467,8 @@ let paletteAppSpec = { // Update page URL this.permalink.updateLocation(); - if (this.saved) { - this.save({ silent: true }); + if (this.saved || this.isCustom) { + this.unsavedChanges = true; } }, }, @@ -467,50 +493,39 @@ let paletteAppSpec = { } }, - getPalette() { - return { id: this.paletteId, uid: this.uid, search: location.search }; - }, - - save({ silent } = {}) { - let title = silent - ? (this.saved?.title ?? this.paletteTitle) - : prompt('Palette title:', `${this.paletteTitle} (tweaked)`); - - if (!title) { - return; - } - + save({ title } = {}) { let uid = this.uid; - if (!uid) { - // First time saving - this.uid = uid = sidebar.palette.getUid(); + this.saved ??= { id: this.paletteId, uid: this.uid, search: location.search }; + if (title) { + // Renaming + this.saved.title = title; + } else { + this.saved.title ??= this.defaultPaletteTitle; + } + + sidebar.palette.save(this.saved); + + if (uid !== this.saved.uid) { + // UID changed (most likely from saving a new palette) + this.uid = this.saved.uid; this.permalink.set('uid', uid); this.permalink.updateLocation(); } - let palette = { ...this.getPalette(), uid, title }; - - sidebar.palette.save(palette, this.saved); - this.saved = palette; + this.unsavedChanges = false; }, rename() { - if (!this.saved) { - return; + let newTitle = prompt('Palette title:', this.saved?.title ?? this.defaultPaletteTitle); + + if (newTitle && newTitle !== this.saved?.title) { + this.save({ title: newTitle }); } - - let newTitle = prompt('New title:', this.saved.title); - - if (!newTitle) { - return; - } - - this.saved.title = newTitle; - sidebar.palette.save(this.saved); }, + // Cannot name this delete() because Vue complains deleteSaved() { sidebar.palette.delete(this.saved); },