From 6ffc5a0cc59136d46a020aaf4fc67fbe20d78499 Mon Sep 17 00:00:00 2001 From: Oriolowsky Date: Sun, 1 Sep 2024 13:02:07 +0200 Subject: [PATCH 1/5] Added the option to set letter-spacing size to individual labels. (#1116) * Added the option to set letter-spacing size to individual labels. * Allowed to set letter-spacing for label groups from the Style tab. --- index.html | 22 ++++++++++++++++++++++ modules/ui/labels-editor.js | 22 ++++++++++++++++++++++ modules/ui/style.js | 7 +++++++ 3 files changed, 51 insertions(+) diff --git a/index.html b/index.html index 1e1f219b..09a428a3 100644 --- a/index.html +++ b/index.html @@ -1181,6 +1181,15 @@ + + + Letter spacing + + + + + + Stroke dash @@ -2678,6 +2687,19 @@ /> + + + @@ -8046,7 +8050,7 @@ - + @@ -8062,7 +8066,7 @@ - + diff --git a/versioning.js b/versioning.js index c8acea04..9e0951ae 100644 --- a/versioning.js +++ b/versioning.js @@ -12,7 +12,7 @@ * * Example: 1.102.0 -> Major version 1, Minor version 102, Patch version 0 */ -const VERSION = "1.100.00"; +const VERSION = "1.101.00"; { document.title += " v" + VERSION; @@ -20,7 +20,7 @@ const VERSION = "1.100.00"; if (loadingScreenVersion) loadingScreenVersion.innerText = `v${VERSION}`; const storedVersion = localStorage.getItem("version"); - if (compareVersions(storedVersion, VERSION).isOlder) setTimeout(showUpdateWindow, 6000); + if (compareVersions(storedVersion, VERSION, {patch: false}).isOlder) setTimeout(showUpdateWindow, 6000); function showUpdateWindow() { const changelog = "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog"; @@ -33,6 +33,7 @@ const VERSION = "1.100.00";

Join our Discord server and Reddit community to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.

@@ -57,16 +52,12 @@ const VERSION = "1.100.00"; const buttons = { Ok: function () { $(this).dialog("close"); - if (storedVersion) { - clearCache(); - localStorage.clear(); - } localStorage.setItem("version", VERSION); } }; if (storedVersion) { - buttons.Reload = () => { + buttons.Cleanup = () => { clearCache(); localStorage.clear(); localStorage.setItem("version", VERSION); @@ -95,11 +86,15 @@ function isValidVersion(versionString) { return !isNaN(major) && !isNaN(minor) && !isNaN(patch); } -function compareVersions(version1, version2) { +function compareVersions(version1, version2, options = {major: true, minor: true, patch: true}) { if (!isValidVersion(version1) || !isValidVersion(version2)) return {isEqual: false, isNewer: false, isOlder: false}; - const [major1, minor1, patch1] = version1.split(".").map(Number); - const [major2, minor2, patch2] = version2.split(".").map(Number); + let [major1, minor1, patch1] = version1.split(".").map(Number); + let [major2, minor2, patch2] = version2.split(".").map(Number); + + if (!options.major) major1 = major2 = 0; + if (!options.minor) minor1 = minor2 = 0; + if (!options.patch) patch1 = patch2 = 0; const isEqual = major1 === major2 && minor1 === minor2 && patch1 === patch2; const isNewer = major1 > major2 || (major1 === major2 && (minor1 > minor2 || (minor1 === minor2 && patch1 > patch2))); From 2fea87344bf95ba921115bcbac01e1964a20e37a Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 1 Sep 2024 14:07:18 +0200 Subject: [PATCH 3/5] feat: letter-spacing - update style files --- index.html | 4 ++-- modules/ui/style-presets.js | 22 ++++++++++++++++++++-- modules/ui/style.js | 3 +-- styles/ancient.json | 4 ++++ styles/atlas.json | 4 ++++ styles/clean.json | 18 +++++++++++------- styles/cyberpunk.json | 4 ++++ styles/darkSeas.json | 4 ++++ styles/default.json | 4 ++++ styles/gloom.json | 5 +++++ styles/light.json | 4 ++++ styles/monochrome.json | 6 +++++- styles/night.json | 6 +++++- styles/pale.json | 4 ++++ styles/watercolor.json | 4 ++++ 15 files changed, 81 insertions(+), 15 deletions(-) diff --git a/index.html b/index.html index dc208c62..b4b5284e 100644 --- a/index.html +++ b/index.html @@ -1182,10 +1182,10 @@ - + Letter spacing - + diff --git a/modules/ui/style-presets.js b/modules/ui/style-presets.js index ff3ae365..01626205 100644 --- a/modules/ui/style-presets.js +++ b/modules/ui/style-presets.js @@ -271,7 +271,15 @@ function addStylePreset() { "data-columns" ], "#legendBox": ["fill", "fill-opacity"], - "#burgLabels > #cities": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"], + "#burgLabels > #cities": [ + "opacity", + "fill", + "text-shadow", + "letter-spacing", + "data-size", + "font-size", + "font-family" + ], "#burgIcons > #cities": [ "opacity", "fill", @@ -283,7 +291,15 @@ function addStylePreset() { "stroke-linecap" ], "#anchors > #cities": ["opacity", "fill", "size", "stroke", "stroke-width"], - "#burgLabels > #towns": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"], + "#burgLabels > #towns": [ + "opacity", + "fill", + "text-shadow", + "letter-spacing", + "data-size", + "font-size", + "font-family" + ], "#burgIcons > #towns": [ "opacity", "fill", @@ -301,6 +317,7 @@ function addStylePreset() { "stroke", "stroke-width", "text-shadow", + "letter-spacing", "data-size", "font-size", "font-family", @@ -312,6 +329,7 @@ function addStylePreset() { "stroke", "stroke-width", "text-shadow", + "letter-spacing", "data-size", "font-size", "font-family", diff --git a/modules/ui/style.js b/modules/ui/style.js index 780f2b97..f742c01d 100644 --- a/modules/ui/style.js +++ b/modules/ui/style.js @@ -247,7 +247,7 @@ function selectStyleElement() { styleFillInput.value = styleFillOutput.value = el.attr("fill") || "#3e3e4b"; styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke") || "#3a3a3a"; styleStrokeWidthInput.value = el.attr("stroke-width") || 0; - styleLetterSpacingInput.value = el.attr("letter-spacing")+"px" || "0px"; + styleLetterSpacingInput.value = el.attr("letter-spacing") || 0; styleShadowInput.value = el.style("text-shadow") || "white 0 0 4px"; styleFont.style.display = "block"; @@ -436,7 +436,6 @@ styleStrokeWidthInput.addEventListener("input", e => { styleLetterSpacingInput.addEventListener("input", e => { getEl().attr("letter-spacing", e.target.value); - if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid(); }); styleStrokeDasharrayInput.addEventListener("input", function () { diff --git a/styles/ancient.json b/styles/ancient.json index 8bc05ec2..d57aa524 100644 --- a/styles/ancient.json +++ b/styles/ancient.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 12, "font-size": 12, "font-family": "Great Vibes" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 5, "font-size": 5, "font-family": "Great Vibes" @@ -384,6 +386,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 22, "font-size": 22, "font-family": "Great Vibes", @@ -395,6 +398,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Times New Roman", diff --git a/styles/atlas.json b/styles/atlas.json index d7990935..ef7d7f8a 100644 --- a/styles/atlas.json +++ b/styles/atlas.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 5, "font-size": 5, "font-family": "Amarante" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "Amarante" @@ -384,6 +386,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 21, "font-size": 21, "font-family": "Amarante", @@ -395,6 +398,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Amarante", diff --git a/styles/clean.json b/styles/clean.json index 82681e28..c5aad094 100644 --- a/styles/clean.json +++ b/styles/clean.json @@ -319,22 +319,22 @@ "mask": "url(#land)" }, "#legend": { - "data-size": 12.74, - "font-size": 12.74, + "data-size": 12, + "font-size": 12, "font-family": "Arial", "stroke": "#909090", - "stroke-width": 1.13, + "stroke-width": 1, "stroke-dasharray": 0, "stroke-linecap": "round", - "data-x": 98.39, - "data-y": 12.67, - "data-columns": null + "data-x": 99, + "data-y": 93, + "data-columns": 8 }, - "#legendBox": {}, "#burgLabels > #cities": { "opacity": 1, "fill": "#414141", "text-shadow": "white 0 0 4px", + "letter-spacing": 0, "data-size": 7, "font-size": 7, "font-family": "Arial" @@ -359,6 +359,8 @@ "#burgLabels > #towns": { "opacity": 1, "fill": "#414141", + "text-shadow": "none", + "letter-spacing": 0, "data-size": 3, "font-size": 3, "font-family": "Arial" @@ -386,6 +388,7 @@ "stroke": "#303030", "stroke-width": 0, "text-shadow": "white 0 0 2px", + "letter-spacing": 0, "data-size": 10, "font-size": 10, "font-family": "Arial", @@ -397,6 +400,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0 0 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Arial", diff --git a/styles/cyberpunk.json b/styles/cyberpunk.json index 2821eb7f..93f22284 100644 --- a/styles/cyberpunk.json +++ b/styles/cyberpunk.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#ffffff", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 8, "font-size": 8, "font-family": "Orbitron" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#ffffff", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 3, "font-size": 3, "font-family": "Orbitron" @@ -384,6 +386,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Orbitron", @@ -395,6 +398,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Almendra SC", diff --git a/styles/darkSeas.json b/styles/darkSeas.json index 9bed1ef2..2bc90fa6 100644 --- a/styles/darkSeas.json +++ b/styles/darkSeas.json @@ -321,6 +321,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 7, "font-size": 7, "font-family": "Lugrasimo" @@ -345,6 +346,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 5, "font-size": 5, "font-family": "Lugrasimo" @@ -371,6 +373,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 21, "font-size": 21, "font-family": "Eagle Lake", @@ -382,6 +385,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Eagle Lake", diff --git a/styles/default.json b/styles/default.json index 623e37f3..9168debc 100644 --- a/styles/default.json +++ b/styles/default.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 7, "font-size": 7, "font-family": "Almendra SC" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "Almendra SC" @@ -384,6 +386,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 22, "font-size": 22, "font-family": "Almendra SC", @@ -395,6 +398,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Almendra SC", diff --git a/styles/gloom.json b/styles/gloom.json index 858c807c..19318882 100644 --- a/styles/gloom.json +++ b/styles/gloom.json @@ -335,6 +335,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0 0 2px", + "letter-spacing": 0, "data-size": 8, "font-size": 8, "font-family": "Underdog" @@ -359,6 +360,8 @@ "#burgLabels > #towns": { "opacity": 1, "fill": "#3e3e4b", + "text-shadow": "none", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "Underdog" @@ -386,6 +389,7 @@ "stroke": "#b5b5b5", "stroke-width": 0, "text-shadow": "white 0 0 2px", + "letter-spacing": 0, "data-size": 20, "font-size": 20, "font-family": "Underdog", @@ -397,6 +401,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0 0 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Underdog", diff --git a/styles/light.json b/styles/light.json index cf846e1b..de539872 100644 --- a/styles/light.json +++ b/styles/light.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#3a3a3a", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 8, "font-size": 8, "font-family": "IM Fell English" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "IM Fell English" @@ -384,6 +386,7 @@ "stroke": "#000000", "stroke-width": 0.3, "text-shadow": "white 0px 0px 6px", + "letter-spacing": 0, "data-size": 14, "font-size": 14, "font-family": "IM Fell English", @@ -395,6 +398,7 @@ "stroke": "#701b05", "stroke-width": 0.1, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 6, "font-size": 6, "font-family": "IM Fell English", diff --git a/styles/monochrome.json b/styles/monochrome.json index 20d3e588..1ee17c43 100644 --- a/styles/monochrome.json +++ b/styles/monochrome.json @@ -328,6 +328,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 7, "font-size": 7, "font-family": "Courier New" @@ -353,6 +354,7 @@ "opacity": 1, "fill": "#000000", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "Courier New" @@ -380,6 +382,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Courier New", @@ -390,7 +393,8 @@ "fill": "#3e3e4b", "stroke": "#3a3a3a", "stroke-width": 0, - "text-shadow": "white 0 0 4px", + "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Courier New", diff --git a/styles/night.json b/styles/night.json index 90b40e75..67a5e799 100644 --- a/styles/night.json +++ b/styles/night.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#dbdbe1", "text-shadow": "black 0px 0px 4px", + "letter-spacing": 0, "data-size": 8, "font-size": 8, "font-family": "Courier New" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#ffffff", "text-shadow": "black 0px 0px 4px", + "letter-spacing": 0, "data-size": 4.28, "font-size": 4.28, "font-family": "Courier New" @@ -384,6 +386,7 @@ "stroke": "#7a83ae", "stroke-width": 0.3, "text-shadow": "black 0px 0px 0.1px", + "letter-spacing": 0, "data-size": 14, "font-size": 14, "font-family": "Courier New", @@ -394,7 +397,8 @@ "fill": "#3e3e4b", "stroke": "#3a3a3a", "stroke-width": 0, - "text-shadow": "white 0px 0px 4px", + "text-shadow": "black 0px 0px 4px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Almendra SC", diff --git a/styles/pale.json b/styles/pale.json index 312009b9..8e839600 100644 --- a/styles/pale.json +++ b/styles/pale.json @@ -332,6 +332,7 @@ "opacity": 0.8, "fill": "#3a3a3a", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 7, "font-size": 7, "font-family": "Arima Madurai" @@ -357,6 +358,7 @@ "opacity": 0.8, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 4, "font-size": 4, "font-family": "Arima Madurai" @@ -384,6 +386,7 @@ "stroke": "#000000", "stroke-width": 0, "text-shadow": "white 0px 0px 6px", + "letter-spacing": 0, "data-size": 14, "font-size": 14, "font-family": "Arima Madurai", @@ -395,6 +398,7 @@ "stroke": "#701b05", "stroke-width": 0.1, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 6, "font-size": 6, "font-family": "Arima Madurai", diff --git a/styles/watercolor.json b/styles/watercolor.json index 79cc9484..982c1b49 100644 --- a/styles/watercolor.json +++ b/styles/watercolor.json @@ -332,6 +332,7 @@ "opacity": 1, "fill": "#043449", "text-shadow": "white 0px 0px 2px", + "letter-spacing": 0, "data-size": 5, "font-size": 5, "font-family": "Comfortaa" @@ -357,6 +358,7 @@ "opacity": 1, "fill": "#3e3e4b", "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 3, "font-size": 3, "font-family": "Comfortaa" @@ -384,6 +386,7 @@ "stroke": "#000000", "stroke-width": 0.15, "text-shadow": "black 1px 1px 3px", + "letter-spacing": 0, "data-size": 18, "font-size": 18, "font-family": "Gloria Hallelujah", @@ -395,6 +398,7 @@ "stroke": "#3a3a3a", "stroke-width": 0, "text-shadow": "white 0px 0px 4px", + "letter-spacing": 0, "data-size": 16, "font-size": 16, "font-family": "Comfortaa", From 4f066c6dc1718d5b0884f506ec2b590a64da1e05 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 1 Sep 2024 14:14:06 +0200 Subject: [PATCH 4/5] feat: letter-spacing - improve UI, refactor --- index.html | 13 +-- modules/ui/labels-editor.js | 112 +++++++++++++------------ modules/ui/style.js | 158 ++++++++++++++++++------------------ 3 files changed, 141 insertions(+), 142 deletions(-) diff --git a/index.html b/index.html index b4b5284e..22d43a30 100644 --- a/index.html +++ b/index.html @@ -2694,14 +2694,15 @@ data-tip="Hide the letter spacing section" class="icon-text-width" > - + max="20" + step=".01" + value="0" + > diff --git a/modules/ui/labels-editor.js b/modules/ui/labels-editor.js index e707ec66..809be210 100644 --- a/modules/ui/labels-editor.js +++ b/modules/ui/labels-editor.js @@ -26,32 +26,32 @@ function editLabel() { modules.editLabel = true; // add listeners - document.getElementById("labelGroupShow").addEventListener("click", showGroupSection); - document.getElementById("labelGroupHide").addEventListener("click", hideGroupSection); - document.getElementById("labelGroupSelect").addEventListener("click", changeGroup); - document.getElementById("labelGroupInput").addEventListener("change", createNewGroup); - document.getElementById("labelGroupNew").addEventListener("click", toggleNewGroupInput); - document.getElementById("labelGroupRemove").addEventListener("click", removeLabelsGroup); + byId("labelGroupShow").on("click", showGroupSection); + byId("labelGroupHide").on("click", hideGroupSection); + byId("labelGroupSelect").on("click", changeGroup); + byId("labelGroupInput").on("change", createNewGroup); + byId("labelGroupNew").on("click", toggleNewGroupInput); + byId("labelGroupRemove").on("click", removeLabelsGroup); - document.getElementById("labelTextShow").addEventListener("click", showTextSection); - document.getElementById("labelTextHide").addEventListener("click", hideTextSection); - document.getElementById("labelText").addEventListener("input", changeText); - document.getElementById("labelTextRandom").addEventListener("click", generateRandomName); + byId("labelTextShow").on("click", showTextSection); + byId("labelTextHide").on("click", hideTextSection); + byId("labelText").on("input", changeText); + byId("labelTextRandom").on("click", generateRandomName); - document.getElementById("labelEditStyle").addEventListener("click", editGroupStyle); + byId("labelEditStyle").on("click", editGroupStyle); - document.getElementById("labelSizeShow").addEventListener("click", showSizeSection); - document.getElementById("labelSizeHide").addEventListener("click", hideSizeSection); - document.getElementById("labelStartOffset").addEventListener("input", changeStartOffset); - document.getElementById("labelRelativeSize").addEventListener("input", changeRelativeSize); + byId("labelSizeShow").on("click", showSizeSection); + byId("labelSizeHide").on("click", hideSizeSection); + byId("labelStartOffset").on("input", changeStartOffset); + byId("labelRelativeSize").on("input", changeRelativeSize); - document.getElementById("labelLetterSpacingShow").addEventListener("click", showLetterSpacingSection); - document.getElementById("labelLetterSpacingHide").addEventListener("click", hideLetterSpacingSection); - document.getElementById("labelLetterSpacingSize").addEventListener("input", changeLetterSpacingSize); + byId("labelLetterSpacingShow").on("click", showLetterSpacingSection); + byId("labelLetterSpacingHide").on("click", hideLetterSpacingSection); + byId("labelLetterSpacingSize").on("input", changeLetterSpacingSize); - document.getElementById("labelAlign").addEventListener("click", editLabelAlign); - document.getElementById("labelLegend").addEventListener("click", editLabelLegend); - document.getElementById("labelRemoveSingle").addEventListener("click", removeLabel); + byId("labelAlign").on("click", editLabelAlign); + byId("labelLegend").on("click", editLabelLegend); + byId("labelRemoveSingle").on("click", removeLabel); function showEditorTips() { showMainTip(); @@ -66,12 +66,12 @@ function editLabel() { const group = text.parentNode.id; if (group === "states" || group === "burgLabels") { - document.getElementById("labelGroupShow").style.display = "none"; + byId("labelGroupShow").style.display = "none"; return; } hideGroupSection(); - const select = document.getElementById("labelGroupSelect"); + const select = byId("labelGroupSelect"); select.options.length = 0; // remove all options labels.selectAll(":scope > g").each(function () { @@ -82,19 +82,17 @@ function editLabel() { } function updateValues(textPath) { - document.getElementById("labelText").value = [...textPath.querySelectorAll("tspan")] - .map(tspan => tspan.textContent) - .join("|"); - document.getElementById("labelStartOffset").value = parseFloat(textPath.getAttribute("startOffset")); - document.getElementById("labelRelativeSize").value = parseFloat(textPath.getAttribute("font-size")); - let letterSpacingSize = (textPath.getAttribute("letter-spacing")) ? textPath.getAttribute("letter-spacing") : 0; - document.getElementById("labelLetterSpacingSize").value = parseFloat(letterSpacingSize); + byId("labelText").value = [...textPath.querySelectorAll("tspan")].map(tspan => tspan.textContent).join("|"); + byId("labelStartOffset").value = parseFloat(textPath.getAttribute("startOffset")); + byId("labelRelativeSize").value = parseFloat(textPath.getAttribute("font-size")); + let letterSpacingSize = textPath.getAttribute("letter-spacing") ? textPath.getAttribute("letter-spacing") : 0; + byId("labelLetterSpacingSize").value = parseFloat(letterSpacingSize); } function drawControlPointsAndLine() { debug.select("#controlPoints").remove(); debug.append("g").attr("id", "controlPoints").attr("transform", elSelected.attr("transform")); - const path = document.getElementById("textPath_" + elSelected.attr("id")); + const path = byId("textPath_" + elSelected.attr("id")); debug.select("#controlPoints").append("path").attr("d", path.getAttribute("d")).on("click", addInterimControlPoint); const l = path.getTotalLength(); if (!l) return; @@ -123,7 +121,7 @@ function editLabel() { } function redrawLabelPath() { - const path = document.getElementById("textPath_" + elSelected.attr("id")); + const path = byId("textPath_" + elSelected.attr("id")); lineGen.curve(d3.curveBundle.beta(1)); const points = []; debug @@ -194,19 +192,19 @@ function editLabel() { function showGroupSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "none")); - document.getElementById("labelGroupSection").style.display = "inline-block"; + byId("labelGroupSection").style.display = "inline-block"; } function hideGroupSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "inline-block")); - document.getElementById("labelGroupSection").style.display = "none"; - document.getElementById("labelGroupInput").style.display = "none"; - document.getElementById("labelGroupInput").value = ""; - document.getElementById("labelGroupSelect").style.display = "inline-block"; + byId("labelGroupSection").style.display = "none"; + byId("labelGroupInput").style.display = "none"; + byId("labelGroupInput").value = ""; + byId("labelGroupSelect").style.display = "inline-block"; } function changeGroup() { - document.getElementById(this.value).appendChild(elSelected.node()); + byId(this.value).appendChild(elSelected.node()); } function toggleNewGroupInput() { @@ -230,7 +228,7 @@ function editLabel() { .replace(/ /g, "_") .replace(/[^\w\s]/gi, ""); - if (document.getElementById(group)) { + if (byId(group)) { tip("Element with this id already exists. Please provide a unique name", false, "error"); return; } @@ -243,22 +241,22 @@ function editLabel() { // just rename if only 1 element left const oldGroup = elSelected.node().parentNode; if (oldGroup !== "states" && oldGroup !== "addedLabels" && oldGroup.childElementCount === 1) { - document.getElementById("labelGroupSelect").selectedOptions[0].remove(); - document.getElementById("labelGroupSelect").options.add(new Option(group, group, false, true)); + byId("labelGroupSelect").selectedOptions[0].remove(); + byId("labelGroupSelect").options.add(new Option(group, group, false, true)); oldGroup.id = group; toggleNewGroupInput(); - document.getElementById("labelGroupInput").value = ""; + byId("labelGroupInput").value = ""; return; } const newGroup = elSelected.node().parentNode.cloneNode(false); - document.getElementById("labels").appendChild(newGroup); + byId("labels").appendChild(newGroup); newGroup.id = group; - document.getElementById("labelGroupSelect").options.add(new Option(group, group, false, true)); - document.getElementById(group).appendChild(elSelected.node()); + byId("labelGroupSelect").options.add(new Option(group, group, false, true)); + byId(group).appendChild(elSelected.node()); toggleNewGroupInput(); - document.getElementById("labelGroupInput").value = ""; + byId("labelGroupInput").value = ""; } function removeLabelsGroup() { @@ -281,7 +279,7 @@ function editLabel() { .select("#" + group) .selectAll("text") .each(function () { - document.getElementById("textPath_" + this.id).remove(); + byId("textPath_" + this.id).remove(); this.remove(); }); if (!basic) labels.select("#" + group).remove(); @@ -295,16 +293,16 @@ function editLabel() { function showTextSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "none")); - document.getElementById("labelTextSection").style.display = "inline-block"; + byId("labelTextSection").style.display = "inline-block"; } function hideTextSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "inline-block")); - document.getElementById("labelTextSection").style.display = "none"; + byId("labelTextSection").style.display = "none"; } function changeText() { - const input = document.getElementById("labelText").value; + const input = byId("labelText").value; const el = elSelected.select("textPath").node(); const lines = input.split("|"); @@ -329,7 +327,7 @@ function editLabel() { const culture = pack.cells.culture[cell]; name = Names.getCulture(culture); } - document.getElementById("labelText").value = name; + byId("labelText").value = name; changeText(); } @@ -340,22 +338,22 @@ function editLabel() { function showSizeSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "none")); - document.getElementById("labelSizeSection").style.display = "inline-block"; + byId("labelSizeSection").style.display = "inline-block"; } function hideSizeSection() { document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "inline-block")); - document.getElementById("labelSizeSection").style.display = "none"; + byId("labelSizeSection").style.display = "none"; } function showLetterSpacingSection() { - document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "none")); - document.getElementById("labelLetterSpacingSection").style.display = "inline-block"; + document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "none")); + byId("labelLetterSpacingSection").style.display = "inline-block"; } function hideLetterSpacingSection() { - document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "inline-block")); - document.getElementById("labelLetterSpacingSection").style.display = "none"; + document.querySelectorAll("#labelEditor > button").forEach(el => (el.style.display = "inline-block")); + byId("labelLetterSpacingSection").style.display = "none"; } function changeStartOffset() { diff --git a/modules/ui/style.js b/modules/ui/style.js index f742c01d..4f003bb1 100644 --- a/modules/ui/style.js +++ b/modules/ui/style.js @@ -18,7 +18,7 @@ } // store some style inputs as options -styleElements.addEventListener("change", function (ev) { +styleElements.on("change", function (ev) { if (ev.target.dataset.stored) lock(ev.target.dataset.stored); }); @@ -71,7 +71,7 @@ function getColorScheme(scheme = "bright") { } // Toggle style sections on element select -styleElementSelect.addEventListener("change", selectStyleElement); +styleElementSelect.on("change", selectStyleElement); function selectStyleElement() { const styleElement = styleElementSelect.value; @@ -409,7 +409,7 @@ function selectStyleElement() { } // Handle style inputs change -styleGroupSelect.addEventListener("change", selectStyleElement); +styleGroupSelect.on("change", selectStyleElement); function getEl() { const el = styleElementSelect.value; @@ -418,46 +418,46 @@ function getEl() { else return svg.select("#" + el).select("#" + g); } -styleFillInput.addEventListener("input", function () { +styleFillInput.on("input", function () { styleFillOutput.value = this.value; getEl().attr("fill", this.value); }); -styleStrokeInput.addEventListener("input", function () { +styleStrokeInput.on("input", function () { styleStrokeOutput.value = this.value; getEl().attr("stroke", this.value); if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid(); }); -styleStrokeWidthInput.addEventListener("input", e => { +styleStrokeWidthInput.on("input", e => { getEl().attr("stroke-width", e.target.value); if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid(); }); -styleLetterSpacingInput.addEventListener("input", e => { +styleLetterSpacingInput.on("input", e => { getEl().attr("letter-spacing", e.target.value); }); -styleStrokeDasharrayInput.addEventListener("input", function () { +styleStrokeDasharrayInput.on("input", function () { getEl().attr("stroke-dasharray", this.value); if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid(); }); -styleStrokeLinecapInput.addEventListener("change", function () { +styleStrokeLinecapInput.on("change", function () { getEl().attr("stroke-linecap", this.value); if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid(); }); -styleOpacityInput.addEventListener("input", e => { +styleOpacityInput.on("input", e => { getEl().attr("opacity", e.target.value); }); -styleFilterInput.addEventListener("change", function () { +styleFilterInput.on("change", function () { if (styleGroupSelect.value === "ocean") return oceanLayers.attr("filter", this.value); getEl().attr("filter", this.value); }); -styleTextureInput.addEventListener("change", function () { +styleTextureInput.on("change", function () { changeTexture(this.value); }); @@ -476,7 +476,7 @@ function updateTextureSelectValue(href) { } } -styleTextureShiftX.addEventListener("input", function () { +styleTextureShiftX.on("input", function () { texture.attr("data-x", this.value); texture .select("image") @@ -484,7 +484,7 @@ styleTextureShiftX.addEventListener("input", function () { .attr("width", graphWidth - this.valueAsNumber); }); -styleTextureShiftY.addEventListener("input", function () { +styleTextureShiftY.on("input", function () { texture.attr("data-y", this.value); texture .select("image") @@ -492,17 +492,17 @@ styleTextureShiftY.addEventListener("input", function () { .attr("height", graphHeight - this.valueAsNumber); }); -styleClippingInput.addEventListener("change", function () { +styleClippingInput.on("change", function () { getEl().attr("mask", this.value); }); -styleGridType.addEventListener("change", function () { +styleGridType.on("change", function () { getEl().attr("type", this.value); if (layerIsOn("toggleGrid")) drawGrid(); calculateFriendlyGridSize(); }); -styleGridScale.addEventListener("input", function () { +styleGridScale.on("input", function () { getEl().attr("scale", this.value); if (layerIsOn("toggleGrid")) drawGrid(); calculateFriendlyGridSize(); @@ -514,52 +514,52 @@ function calculateFriendlyGridSize() { styleGridSizeFriendly.value = friendly; } -styleGridShiftX.addEventListener("input", function () { +styleGridShiftX.on("input", function () { getEl().attr("dx", this.value); if (layerIsOn("toggleGrid")) drawGrid(); }); -styleGridShiftY.addEventListener("input", function () { +styleGridShiftY.on("input", function () { getEl().attr("dy", this.value); if (layerIsOn("toggleGrid")) drawGrid(); }); -styleRescaleMarkers.addEventListener("change", function () { +styleRescaleMarkers.on("change", function () { markers.attr("rescale", +this.checked); invokeActiveZooming(); }); -styleCoastlineAuto.addEventListener("change", function () { +styleCoastlineAuto.on("change", function () { coastline.select("#sea_island").attr("auto-filter", +this.checked); styleFilter.style.display = this.checked ? "none" : "block"; invokeActiveZooming(); }); -styleOceanFill.addEventListener("input", function () { +styleOceanFill.on("input", function () { oceanLayers.select("rect").attr("fill", this.value); styleOceanFillOutput.value = this.value; }); -styleOceanPattern.addEventListener("change", function () { +styleOceanPattern.on("change", function () { byId("oceanicPattern")?.setAttribute("href", this.value); }); -styleOceanPatternOpacity.addEventListener("input", e => { +styleOceanPatternOpacity.on("input", e => { byId("oceanicPattern").setAttribute("opacity", e.target.value); }); -outlineLayers.addEventListener("change", function () { +outlineLayers.on("change", function () { oceanLayers.selectAll("path").remove(); oceanLayers.attr("layers", this.value); OceanLayers(); }); -styleHeightmapScheme.addEventListener("change", function () { +styleHeightmapScheme.on("change", function () { getEl().attr("scheme", this.value); drawHeightmap(); }); -openCreateHeightmapSchemeButton.addEventListener("click", function () { +openCreateHeightmapSchemeButton.on("click", function () { // start with current scheme const scheme = getEl().attr("scheme"); this.dataset.stops = scheme.startsWith("#") @@ -678,97 +678,97 @@ openCreateHeightmapSchemeButton.addEventListener("click", function () { }); }); -styleHeightmapRenderOcean.addEventListener("change", e => { +styleHeightmapRenderOcean.on("change", e => { const checked = +e.target.checked; getEl().attr("data-render", checked); drawHeightmap(); }); -styleHeightmapTerracing.addEventListener("input", e => { +styleHeightmapTerracing.on("input", e => { getEl().attr("terracing", e.target.value); drawHeightmap(); }); -styleHeightmapSkip.addEventListener("input", e => { +styleHeightmapSkip.on("input", e => { getEl().attr("skip", e.target.value); drawHeightmap(); }); -styleHeightmapSimplification.addEventListener("input", e => { +styleHeightmapSimplification.on("input", e => { getEl().attr("relax", e.target.value); drawHeightmap(); }); -styleHeightmapCurve.addEventListener("change", e => { +styleHeightmapCurve.on("change", e => { getEl().attr("curve", e.target.value); drawHeightmap(); }); -styleReliefSet.addEventListener("change", e => { +styleReliefSet.on("change", e => { terrain.attr("set", e.target.value); ReliefIcons.draw(); if (!layerIsOn("toggleRelief")) toggleRelief(); }); -styleReliefSize.addEventListener("change", e => { +styleReliefSize.on("change", e => { terrain.attr("size", e.target.value); ReliefIcons.draw(); if (!layerIsOn("toggleRelief")) toggleRelief(); }); -styleReliefDensity.addEventListener("change", e => { +styleReliefDensity.on("change", e => { terrain.attr("density", e.target.value); ReliefIcons.draw(); if (!layerIsOn("toggleRelief")) toggleRelief(); }); -styleTemperatureFillOpacityInput.addEventListener("input", e => { +styleTemperatureFillOpacityInput.on("input", e => { temperature.attr("fill-opacity", e.target.value); }); -styleTemperatureFontSizeInput.addEventListener("input", e => { +styleTemperatureFontSizeInput.on("input", e => { temperature.attr("font-size", e.target.value + "px"); }); -styleTemperatureFillInput.addEventListener("input", e => { +styleTemperatureFillInput.on("input", e => { temperature.attr("fill", e.target.value); styleTemperatureFillOutput.value = e.target.value; }); -stylePopulationRuralStrokeInput.addEventListener("input", e => { +stylePopulationRuralStrokeInput.on("input", e => { population.select("#rural").attr("stroke", e.target.value); stylePopulationRuralStrokeOutput.value = e.target.value; }); -stylePopulationUrbanStrokeInput.addEventListener("input", e => { +stylePopulationUrbanStrokeInput.on("input", e => { population.select("#urban").attr("stroke", e.target.value); stylePopulationUrbanStrokeOutput.value = e.target.value; }); -styleCompassSizeInput.addEventListener("input", shiftCompass); -styleCompassShiftX.addEventListener("input", shiftCompass); -styleCompassShiftY.addEventListener("input", shiftCompass); +styleCompassSizeInput.on("input", shiftCompass); +styleCompassShiftX.on("input", shiftCompass); +styleCompassShiftY.on("input", shiftCompass); function shiftCompass() { const tr = `translate(${styleCompassShiftX.value} ${styleCompassShiftY.value}) scale(${styleCompassSizeInput.value})`; compass.select("use").attr("transform", tr); } -styleLegendColItems.addEventListener("input", e => { +styleLegendColItems.on("input", e => { legend.select("#legendBox").attr("data-columns", e.target.value); redrawLegend(); }); -styleLegendBack.addEventListener("input", e => { +styleLegendBack.on("input", e => { styleLegendBackOutput.value = e.target.value; legend.select("#legendBox").attr("fill", e.target.value); }); -styleLegendOpacity.addEventListener("input", e => { +styleLegendOpacity.on("input", e => { legend.select("#legendBox").attr("fill-opacity", e.target.value); }); -styleSelectFont.addEventListener("change", changeFont); +styleSelectFont.on("change", changeFont); function changeFont() { const family = styleSelectFont.value; getEl().attr("font-family", family); @@ -776,11 +776,11 @@ function changeFont() { if (styleElementSelect.value === "legend") redrawLegend(); } -styleShadowInput.addEventListener("input", function () { +styleShadowInput.on("input", function () { getEl().style("text-shadow", this.value); }); -styleFontAdd.addEventListener("click", function () { +styleFontAdd.on("click", function () { addFontNameInput.value = ""; addFontURLInput.value = ""; @@ -817,20 +817,20 @@ styleFontAdd.addEventListener("click", function () { }); }); -addFontMethod.addEventListener("change", function () { +addFontMethod.on("change", function () { addFontURLInput.style.display = this.value === "fontURL" ? "inline" : "none"; }); -styleFontSize.addEventListener("change", function () { +styleFontSize.on("change", function () { changeFontSize(getEl(), +this.value); }); -styleFontPlus.addEventListener("click", function () { +styleFontPlus.on("click", function () { const current = +styleFontSize.value || 12; changeFontSize(getEl(), Math.min(current + 1, 999)); }); -styleFontMinus.addEventListener("click", function () { +styleFontMinus.on("click", function () { const current = +styleFontSize.value || 12; changeFontSize(getEl(), Math.max(current - 1, 1)); }); @@ -853,16 +853,16 @@ function changeFontSize(el, size) { if (styleElementSelect.value === "legend") redrawLegend(); } -styleRadiusInput.addEventListener("change", function () { +styleRadiusInput.on("change", function () { changeRadius(+this.value); }); -styleRadiusPlus.addEventListener("click", function () { +styleRadiusPlus.on("click", function () { const size = Math.max(rn(getEl().attr("size") * 1.1, 2), 0.2); changeRadius(size); }); -styleRadiusMinus.addEventListener("click", function () { +styleRadiusMinus.on("click", function () { const size = Math.max(rn(getEl().attr("size") * 0.9, 2), 0.2); changeRadius(size); }); @@ -884,16 +884,16 @@ function changeRadius(size, group) { changeIconSize(size * 2, g); // change also anchor icons } -styleIconSizeInput.addEventListener("change", function () { +styleIconSizeInput.on("change", function () { changeIconSize(+this.value); }); -styleIconSizePlus.addEventListener("click", function () { +styleIconSizePlus.on("click", function () { const size = Math.max(rn(getEl().attr("size") * 1.1, 2), 0.2); changeIconSize(size); }); -styleIconSizeMinus.addEventListener("click", function () { +styleIconSizeMinus.on("click", function () { const size = Math.max(rn(getEl().attr("size") * 0.9, 2), 0.2); changeIconSize(size); }); @@ -918,34 +918,34 @@ function changeIconSize(size, group) { styleIconSizeInput.value = size; } -styleStatesBodyOpacity.addEventListener("input", e => { +styleStatesBodyOpacity.on("input", e => { statesBody.attr("opacity", e.target.value); }); -styleStatesBodyFilter.addEventListener("change", function () { +styleStatesBodyFilter.on("change", function () { statesBody.attr("filter", this.value); }); -styleStatesHaloWidth.addEventListener("input", e => { +styleStatesHaloWidth.on("input", e => { const value = e.target.value; statesHalo.attr("data-width", value).attr("stroke-width", value); }); -styleStatesHaloOpacity.addEventListener("input", e => { +styleStatesHaloOpacity.on("input", e => { statesHalo.attr("opacity", e.target.value); }); -styleStatesHaloBlur.addEventListener("input", e => { +styleStatesHaloBlur.on("input", e => { const value = Number(e.target.value); const blur = value > 0 ? `blur(${value}px)` : null; statesHalo.attr("filter", blur); }); -styleArmiesFillOpacity.addEventListener("input", e => { +styleArmiesFillOpacity.on("input", e => { armies.attr("fill-opacity", e.target.value); }); -styleArmiesSize.addEventListener("input", e => { +styleArmiesSize.on("input", e => { const value = Number(e.target.value); armies.attr("box-size", value).attr("font-size", value * 2); @@ -956,17 +956,17 @@ styleArmiesSize.addEventListener("input", e => { }); }); -emblemsStateSizeInput.addEventListener("change", e => { +emblemsStateSizeInput.on("change", e => { emblems.select("#stateEmblems").attr("data-size", e.target.value); drawEmblems(); }); -emblemsProvinceSizeInput.addEventListener("change", e => { +emblemsProvinceSizeInput.on("change", e => { emblems.select("#provinceEmblems").attr("data-size", e.target.value); drawEmblems(); }); -emblemsBurgSizeInput.addEventListener("change", e => { +emblemsBurgSizeInput.on("change", e => { emblems.select("#burgEmblems").attr("data-size", e.target.value); drawEmblems(); }); @@ -1021,7 +1021,7 @@ Object.keys(vignettePresets).forEach(preset => { styleVignettePreset.options.add(new Option(preset, preset, false, false)); }); -styleVignettePreset.addEventListener("change", function () { +styleVignettePreset.on("change", function () { const attributes = JSON.parse(vignettePresets[this.value]); for (const selector in attributes) { @@ -1053,35 +1053,35 @@ styleVignettePreset.addEventListener("change", function () { } }); -styleVignetteX.addEventListener("input", e => { +styleVignetteX.on("input", e => { byId("vignette-rect")?.setAttribute("x", `${e.target.value}%`); }); -styleVignetteWidth.addEventListener("input", e => { +styleVignetteWidth.on("input", e => { byId("vignette-rect")?.setAttribute("width", `${e.target.value}%`); }); -styleVignetteY.addEventListener("input", e => { +styleVignetteY.on("input", e => { byId("vignette-rect")?.setAttribute("y", `${e.target.value}%`); }); -styleVignetteHeight.addEventListener("input", e => { +styleVignetteHeight.on("input", e => { byId("vignette-rect")?.setAttribute("height", `${e.target.value}%`); }); -styleVignetteRx.addEventListener("input", e => { +styleVignetteRx.on("input", e => { byId("vignette-rect")?.setAttribute("rx", `${e.target.value}%`); }); -styleVignetteRy.addEventListener("input", e => { +styleVignetteRy.on("input", e => { byId("vignette-rect")?.setAttribute("ry", `${e.target.value}%`); }); -styleVignetteBlur.addEventListener("input", e => { +styleVignetteBlur.on("input", e => { byId("vignette-rect")?.setAttribute("filter", `blur(${e.target.value}px)`); }); -styleScaleBar.addEventListener("input", function (event) { +styleScaleBar.on("input", function (event) { const scaleBarBack = scaleBar.select("#scaleBarBack"); if (!scaleBarBack.size()) return; @@ -1161,7 +1161,7 @@ function updateElements() { } // GLOBAL FILTERS -mapFilters.addEventListener("click", applyMapFilter); +mapFilters.on("click", applyMapFilter); function applyMapFilter(event) { if (event.target.tagName !== "BUTTON") return; const button = event.target; From baf7a5c3b9830922411f0954cb7c6798e7c6caf2 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 1 Sep 2024 14:20:06 +0200 Subject: [PATCH 5/5] chore: update version --- versioning.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versioning.js b/versioning.js index 9e0951ae..8a5f9393 100644 --- a/versioning.js +++ b/versioning.js @@ -33,7 +33,7 @@ const VERSION = "1.101.00";
    Latest changes: -
  • Labels editor: ability to set letter spacing
  • +
  • Style: ability to set letter spacing
  • Zones update
  • Notes Editor: on-demand AI text generation
  • New style preset: Dark Seas