Compare commits

..

No commits in common. "7948a27f39f161cb356f37854807ca93a80c15f7" and "b69bcacb7899c026346abf28a1f9f4f6ccf1b0f5" have entirely different histories.

12 changed files with 78 additions and 320 deletions

View File

@ -97,22 +97,5 @@
</footer> </footer>
</section> </section>
</div> </div>
<div class="dialog hidden" data-dialog="fileSave:nameDesign">
<section>
<header>Save your design</header>
<main class="list-choice">
<form id="fileSave:nameDesign:form" data-form="fileSave:nameDesign">
<label>
Name:
<input name="name" autofocus />
</label>
</form>
</main>
<footer>
<button data-dialog-action="cancel">Cancel</button>
<button form="fileSave:nameDesign:form">Save</button>
</footer>
</section>
</div>
</body> </body>
</html> </html>

View File

@ -1,50 +1,29 @@
import { DomList } from "./dom-list.js"; import { DomList } from "./dom-list.js";
import { addEventToElement, setText } from "./dom-utils.js"; import { addEventToElement, setText } from "./dom-utils.js";
import { awaitEvent, emitEvent, listenTo } from "./events.js"; import { emitEvent, listenTo } from "./events.js";
import { registerLoadCallback } from "./main.js";
registerLoadCallback(() => { export function initializeDialogs() {
listenTo("fileLoad:chooseDesign", designChoiceDialog); listenTo("fileLoad:chooseDesign", designChoiceDialog);
listenTo("fileSave:nameDesign", designNameDialog); }
});
function initializeDialog(dialogName, endEvent, { emptyValue, onDismiss } = {}) { function designChoiceDialog(e) {
const dialog = document.querySelector(`[data-dialog="${dialogName}"]`); const dialog = document.querySelector('[data-dialog="fileLoad:chooseDesign"]');
const dismiss = (data) => { const dismiss = (data) => {
dialog.classList.add("hidden"); dialog.classList.add("hidden");
console.log("dimiss > emit", data); emitEvent("fileLoad:chooseDesign:choice", data);
emitEvent(endEvent, data);
if (onDismiss) {
onDismiss();
}
} }
addEventToElement( addEventToElement(
"dialog-action", "cancel", "click", "dialog-action", "cancel", "click",
() => dismiss(emptyValue), () => dismiss(-1),
{ element: dialog }, { element: dialog },
); );
dialog.addEventListener("click", e => { dialog.addEventListener("click", e => {
if (e.target !== e.currentTarget) return; if (e.target !== e.currentTarget) return;
dismiss(emptyValue); dismiss(-1);
}); });
queueMicrotask(() => {
dialog.classList.remove("hidden");
});
return {
dialog,
dismiss,
};
}
function designChoiceDialog(e) {
const {
dialog, dismiss
} = initializeDialog("fileLoad:chooseDesign", "fileLoad:chooseDesign:choice", -1);
const list = new DomList(dialog.querySelector(":scope > section > main")); const list = new DomList(dialog.querySelector(":scope > section > main"));
list.clear(); list.clear();
@ -56,20 +35,6 @@ function designChoiceDialog(e) {
button.addEventListener("click", () => dismiss(designIndex)); button.addEventListener("click", () => dismiss(designIndex));
list.addItem(button); list.addItem(button);
} }
}
function designNameDialog() { dialog.classList.remove("hidden");
const {
dismiss
} = initializeDialog(
"fileSave:nameDesign",
"fileSave:nameDesign:named",
{
emptyValue: null
}
);
awaitEvent("fileSave:nameDesign:submit").then(e => {
dismiss(new FormData(e.detail.target).get("name"));
});
} }

View File

@ -1,5 +1,4 @@
import { deleteTooltip } from "./tooltip.js"; import { deleteTooltip } from "./tooltip.js";
import { deleteSolverMetadata } from "./solver.js";
export class DomList { export class DomList {
list; list;
@ -11,10 +10,7 @@ export class DomList {
} }
clear() { clear() {
this.list.querySelectorAll("[data-tooltip]") this.list.querySelectorAll("[data-tooltip]").forEach(e => deleteTooltip(Number(e.dataset.tooltip)))
.forEach(e => deleteTooltip(Number(e.dataset.tooltip)));
this.list.querySelectorAll("[data-solver-metadata]")
.forEach(e => deleteSolverMetadata(Number(e.dataset.solverMetadata)));
this.list.replaceChildren(...this.list.querySelectorAll(":scope > template, :scope > [data-keep]")); this.list.replaceChildren(...this.list.querySelectorAll(":scope > template, :scope > [data-keep]"));
} }

View File

@ -1,29 +1,20 @@
import { awaitEvent, emitEvent, listenTo } from "./events.js"; import { awaitEvent, emitEvent, listenTo } from "./events.js";
import { checkEquivalence, findFullEntry, stripEntryToMinimums } from "./ncpf-utils.js"; import { findFullEntry, stripEntryToMinimums } from "./ncpf-utils.js";
import { import { getPlannerMultiblockSize, getPlannerMultiblockType, loadPlanner, readPlannerTiles } from "./planner.js";
getPlannerDom,
getPlannerMultiblockSize,
getPlannerMultiblockType,
loadPlanner,
readPlannerCellData
} from "./planner.js";
import { getAtlasIndexFromMetadata, getAtlasMetadata } from "./atlas.js"; import { getAtlasIndexFromMetadata, getAtlasMetadata } from "./atlas.js";
import { getSolverMetadata, resetSolver } from "./solver.js"; import { resetSolver } from "./solver.js";
import { registerLoadCallback } from "./main.js";
registerLoadCallback(() => { export function initializeFileEvents() {
listenTo("file:load", () => showOpenFileDialog()); listenTo("file:load", () => showOpenFileDialog());
listenTo("file:new", () => {}); listenTo("file:new", () => {});
listenTo("file:save", () => saveFile()); listenTo("file:save", () => saveFile("test"));
}); }
export function showOpenFileDialog() { export function showOpenFileDialog() {
const input = document.createElement("input"); const input = document.createElement("input");
input.type = "file"; input.type = "file";
input.accept = ".ncpf.json"; input.accept = ".ncpf.json";
input.addEventListener("change", async () => { input.addEventListener("change", async () => {
const basename = input.files[0].name.split(/[/\\]/).pop();
const filename = basename.replace(/\.json$/, "").replace(/\.ncpf$/, "");
const data = await new Promise(resolve => { const data = await new Promise(resolve => {
const reader = new FileReader(); const reader = new FileReader();
reader.addEventListener("load", () => { reader.addEventListener("load", () => {
@ -31,7 +22,7 @@ export function showOpenFileDialog() {
}); });
reader.readAsText(input.files[0]); reader.readAsText(input.files[0]);
}); });
void loadFile(data, filename); void loadFile(data);
}); });
input.click(); input.click();
} }
@ -40,10 +31,10 @@ export async function loadExampleFile(filename) {
const data = await fetch(`./examples/${filename}.ncpf.json`) const data = await fetch(`./examples/${filename}.ncpf.json`)
.then(data => data.json()); .then(data => data.json());
return loadFile(data); return loadFile(data);
// return loadFile(data, filename);
} }
export async function loadFile(data, name) { export async function loadFile(data) {
console.log(data);
if (!data.designs) throw new Error("invalid file"); if (!data.designs) throw new Error("invalid file");
if (data.designs.length === 0) throw new Error("no designs"); if (data.designs.length === 0) throw new Error("no designs");
@ -63,36 +54,13 @@ export async function loadFile(data, name) {
const designWithAtlas = design.design.map(a => a.map(b => b.map(c => c === -1 ? -1 : blocks[c]))); const designWithAtlas = design.design.map(a => a.map(b => b.map(c => c === -1 ? -1 : blocks[c])));
loadPlanner(design.dimensions, design.type, designWithAtlas); loadPlanner(design.dimensions, design.type, designWithAtlas);
resetSolver(design, data.configuration[design.type]); resetSolver(design);
if (name) {
getPlannerDom().dataset.name = name;
}
console.log("load file", data);
} }
export async function saveFile(name = undefined) { export async function saveFile(name) {
if (!name) {
name = getPlannerDom().dataset.name;
}
if (!name) {
emitEvent("fileSave:nameDesign");
const nameEvent = await awaitEvent("fileSave:nameDesign:named");
name = nameEvent.detail;
console.log(nameEvent)
}
if (!name) {
name = "unnamed";
}
const multiblockType = getPlannerMultiblockType(); const multiblockType = getPlannerMultiblockType();
const designAsCellData = readPlannerCellData(); const designAsAtlas = readPlannerTiles();
const designAsAtlas = designAsCellData
.map(xPlane => xPlane.map(yRow => yRow.map(c => Number(c.tile))));
const designBlocksAtlasMap = Object.fromEntries( const designBlocksAtlasMap = Object.fromEntries(
[...new Set(designAsAtlas.flat(3))] [...new Set(designAsAtlas.flat(3))]
.filter(v => v !== -1) .filter(v => v !== -1)
@ -106,75 +74,36 @@ export async function saveFile(name = undefined) {
const designAsBlockIndices = designAsBlocks const designAsBlockIndices = designAsBlocks
.map(xPlane => xPlane.map(yRow => yRow.map(b => b?.designIndex ?? -1))); .map(xPlane => xPlane.map(yRow => yRow.map(b => b?.designIndex ?? -1)));
const minimizedBlocks = Object.entries(designBlocksAtlasMap) const designBlocksWithRecipes = designAsBlocks
.sort(([a], [b]) => a - b) .map(xPlane => xPlane
.map(([, m]) => stripEntryToMinimums(m)); .map(yRow => yRow
.map(block => {
const blockRecipes = designAsBlocks
.map((xPlane, x) => xPlane
.map((yRow, y) => yRow
.map((block, z) => {
if (!block) return; if (!block) return;
const fullBlock = findFullEntry( return findFullEntry("blocks", block, { configurationHint: multiblockType });
"blocks",
block,
{ configurationHint: multiblockType },
);
if (!fullBlock || !fullBlock.modules || !("ncpf:block_recipes" in fullBlock.modules)) return;
const designIndex = designBlocksAtlasMap[Number(designAsCellData[x][y][z].tile)].designIndex;
const solverMetadata = getSolverMetadata(designAsCellData[x][y][z].solverMetadata);
const minimizedBlock = minimizedBlocks[designIndex];
let recipeIndex = -1;
if (multiblockType === "nuclearcraft:overhaul_sfr") {
if (!minimizedBlock.modules) {
minimizedBlock.modules = {};
}
if (!minimizedBlock.modules["ncpf:block_recipes"]) {
minimizedBlock.modules["ncpf:block_recipes"] = {
recipes: [],
};
}
const recipes = minimizedBlock.modules["ncpf:block_recipes"].recipes;
const recipe = solverMetadata["block_recipe"];
recipeIndex = recipes.findIndex(r => checkEquivalence(r, recipe));
if (recipeIndex === -1) {
recipes.push(stripEntryToMinimums(recipe));
recipeIndex = recipes.length - 1;
}
}
return recipeIndex;
}) })
.filter(b => b != null) .filter(b => b && b.modules && "ncpf:block_recipes" in b.modules)
) )
.filter(r => r.length > 0) .filter(r => r.length > 0)
) )
.filter(p => p.length > 0); .filter(p => p.length > 0);
console.log("designBlocksWithRecipes", designBlocksWithRecipes)
let fileData = null; const minimizedBlocks = Object.entries(designBlocksAtlasMap)
.sort(([a], [b]) => a - b)
.map(([, m]) => stripEntryToMinimums(m));
if (multiblockType === "nuclearcraft:overhaul_sfr") { const data = {
const coolantRecipes = [];
let coolantRecipeIndex = -1;
const plannerMetadata = getSolverMetadata(getPlannerDom());
coolantRecipes.push(stripEntryToMinimums(plannerMetadata["coolant_recipe"]));
coolantRecipeIndex = 0;
fileData = {
addons: [], addons: [],
configuration: { configurations: {
[multiblockType]: { [multiblockType]: {
blocks: minimizedBlocks, blocks: minimizedBlocks,
coolant_recipes: coolantRecipes, coolant_recipes: [], // FIXME
}, },
}, },
designs: [ designs: [
{ {
block_recipes: blockRecipes, block_recipes: [], // FIXME
coolant_recipe: coolantRecipeIndex, coolant_recipe: 0, // FIXME
design: designAsBlockIndices, design: designAsBlockIndices,
dimensions: getPlannerMultiblockSize(), dimensions: getPlannerMultiblockSize(),
type: multiblockType, type: multiblockType,
@ -182,17 +111,7 @@ export async function saveFile(name = undefined) {
], ],
version: 1, version: 1,
}; };
}
console.log(`save file (${name})`, fileData); console.log(designBlocksAtlasMap);
console.log(data);
if (fileData) {
const blob = new Blob([ JSON.stringify(fileData) ], {
type: "application/json",
});
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = `${name}.ncpf.json`;
a.click();
}
} }

View File

@ -1,20 +1,13 @@
import { loadConfiguration } from "./configuration.js"; import { loadConfiguration } from "./configuration.js";
import { initializeDialogs } from "./dialogs.js";
import { addEventToButton, addEventToInput, debounce, getElements } from "./dom-utils.js"; import { addEventToButton, addEventToInput, debounce, getElements } from "./dom-utils.js";
import { awaitEvent, emitEvent, listenTo } from "./events.js"; import { awaitEvent, emitEvent, listenTo } from "./events.js";
import { loadExampleFile } from "./files.js"; import { initializeFileEvents, loadExampleFile, saveFile, showOpenFileDialog } from "./files.js";
import { initializePlanner } from "./planner.js";
import { initializeMenuResizing } from "./resize-menus.js";
import { getState, setState, STATE } from "./state.js"; import { getState, setState, STATE } from "./state.js";
import "./menu-bar.js"; import { initializeTooltips } from "./tooltip.js";
import "./dialogs.js"; import { initializeMenuBar } from "./menu-bar.js";
let loadCallbacks = [];
export function registerLoadCallback(cb) {
queueMicrotask(() => {
loadCallbacks.push(cb);
});
}
function runLoadCallbacks() {
loadCallbacks.forEach(cb => cb());
}
window.addEventListener("load", () => { window.addEventListener("load", () => {
emitEvent("setup-start"); emitEvent("setup-start");
@ -48,12 +41,6 @@ window.addEventListener("load", () => {
emitEvent(elem.dataset.input + ":change", e); emitEvent(elem.dataset.input + ":change", e);
}); });
}); });
getElements("form", "*").forEach(elem => {
elem.addEventListener("submit", e => {
e.preventDefault();
emitEvent(elem.dataset.form + ":submit", e);
});
});
addEventToInput("configuration", "input", loadConfiguration); addEventToInput("configuration", "input", loadConfiguration);
addEventToButton("load-configuration", "click", loadConfiguration); addEventToButton("load-configuration", "click", loadConfiguration);
@ -70,7 +57,12 @@ window.addEventListener("load", () => {
listenTo("config:end", () => setState(STATE.planning)); listenTo("config:end", () => setState(STATE.planning));
runLoadCallbacks(); initializeFileEvents();
initializePlanner();
initializeMenuResizing();
initializeTooltips();
initializeMenuBar();
initializeDialogs();
emitEvent("setup-end"); emitEvent("setup-end");
@ -78,4 +70,5 @@ window.addEventListener("load", () => {
awaitEvent("config:end").then(() => loadExampleFile("tiny reactor")); awaitEvent("config:end").then(() => loadExampleFile("tiny reactor"));
// awaitEvent("config:end").then(() => loadExampleFile("multi-reactor")); // awaitEvent("config:end").then(() => loadExampleFile("multi-reactor"));
awaitEvent("solver:reset:done").then(() => emitEvent("file:save"));
}); });

View File

@ -1,10 +1,8 @@
import { positionAsTooltip } from "./tooltip.js"; import { positionAsTooltip } from "./tooltip.js";
import { registerLoadCallback } from "./main.js";
let activeMenuBar = null; let activeMenuBar = null;
registerLoadCallback(() => { export function initializeMenuBar() {
console.log("menubar-load");
document.querySelectorAll(".menu-bar").forEach(menuBar => { document.querySelectorAll(".menu-bar").forEach(menuBar => {
menuBar.querySelectorAll("button").forEach(button => { menuBar.querySelectorAll("button").forEach(button => {
button.setAttribute("tabindex", "-1"); button.setAttribute("tabindex", "-1");
@ -68,7 +66,7 @@ registerLoadCallback(() => {
}); });
// TODO: keyboard navigation with alt and arrow keys // TODO: keyboard navigation with alt and arrow keys
}); }
function handleGlobalClick() { function handleGlobalClick() {

View File

@ -9,17 +9,9 @@ export function checkEquivalence(a, b) {
&& a.metadata === b.metadata && a.metadata === b.metadata
&& (a.blockstate === undefined && b.blockstate === undefined && (a.blockstate === undefined && b.blockstate === undefined
|| JSON.stringify(a.blockstate) === JSON.stringify(b.blockstate)); || JSON.stringify(a.blockstate) === JSON.stringify(b.blockstate));
case "legacy_fluid":
return a.name === b.name;
case "oredict": case "oredict":
return a.oredict === b.oredict; return a.oredict === b.oredict;
case "list":
return a.elements.length === b.elements.length &&
a.elements.every((aE, i) => checkEquivalence(aE, b.elements[i]));
default: default:
console.warn("unknown type", a.type, a, b); console.warn("unknown type", a.type, a, b);
} }
@ -32,17 +24,8 @@ export function stripEntryToMinimums(entry) {
case "legacy_block": case "legacy_block":
return objectKeepKeys(entry, "type", "name", "metadata", "blockstate"); return objectKeepKeys(entry, "type", "name", "metadata", "blockstate");
case "legacy_fluid":
return objectKeepKeys(entry, "type", "name");
case "oredict": case "oredict":
return objectKeepKeys(entry, "type", "oredict"); return objectKeepKeys(entry, "type", "oredict");
case "list":
return {
type: entry.type,
elements: entry.elements.map(stripEntryToMinimums),
};
} }
throw new Error(`unknown entry type ${entry.type}`); throw new Error(`unknown entry type ${entry.type}`);
} }

View File

@ -7,7 +7,6 @@ import { initialize3dArray } from "./js-utils.js";
import { recall, save } from "./storage.js"; import { recall, save } from "./storage.js";
import { createTooltip, tooltipDataToPlain } from "./tooltip.js"; import { createTooltip, tooltipDataToPlain } from "./tooltip.js";
import { lookupFromMetadata, resolveBlockName } from "./ncpf-utils.js"; import { lookupFromMetadata, resolveBlockName } from "./ncpf-utils.js";
import { registerLoadCallback } from "./main.js";
const zoomOptions = [ 0.5, 1, 2, 3, 4, 5 ]; const zoomOptions = [ 0.5, 1, 2, 3, 4, 5 ];
const zoomDefault = 2; const zoomDefault = 2;
@ -18,7 +17,7 @@ let multiblockSize = [9, 7, 9]; // width (screen x), height (xy grids), depth (s
let multiblockType = "nuclearcraft:overhaul_sfr"; let multiblockType = "nuclearcraft:overhaul_sfr";
let activeItem = -1; let activeItem = -1;
registerLoadCallback(() => { export function initializePlanner() {
listenTo("config:end", buildBlockPicker); listenTo("config:end", buildBlockPicker);
listenTo("config:end", buildPlanner); listenTo("config:end", buildPlanner);
@ -85,7 +84,7 @@ registerLoadCallback(() => {
console.log("Suppressing hover:", suppressHover); console.log("Suppressing hover:", suppressHover);
} }
}); });
}); }
function buildBlockPicker() { function buildBlockPicker() {
const filter = Filter.fromInput("block-picker:filter"); const filter = Filter.fromInput("block-picker:filter");
@ -307,7 +306,7 @@ export function loadPlanner(size, type, textures) {
buildPlanner(textures); buildPlanner(textures);
} }
export function readPlannerCellData() { export function readPlannerTiles() {
const planner = document.getElementById("planner"); const planner = document.getElementById("planner");
const tiles = initialize3dArray(...multiblockSize, -1); const tiles = initialize3dArray(...multiblockSize, -1);
const grids = [...planner.children].filter(e => e.dataset.y); const grids = [...planner.children].filter(e => e.dataset.y);
@ -316,21 +315,12 @@ export function readPlannerCellData() {
const gridTiles = [...grid.children].filter(e => e.dataset.tile); const gridTiles = [...grid.children].filter(e => e.dataset.tile);
for (let z = 0; z < multiblockSize[2]; z++) { for (let z = 0; z < multiblockSize[2]; z++) {
for (let x = 0; x < multiblockSize[0]; x++) { for (let x = 0; x < multiblockSize[0]; x++) {
tiles[x][y][z] = { ...gridTiles[x + z * multiblockSize[0]].dataset }; tiles[x][y][z] = Number(gridTiles[x + z * multiblockSize[0]].dataset.tile);
} }
} }
} }
return tiles; return tiles;
} }
export function getPlannerDom() {
return document.getElementById("planner");
}
export function getPlannerCellsDom() {
return document.querySelectorAll("#planner [data-tile]");
}
export function getPlannerCellDom(x, y, z) {
return document.querySelector(`#planner [data-x="${x}"][data-y="${y}"][data-z="${z}"]`);
}
export const getPlannerMultiblockType = () => multiblockType; export const getPlannerMultiblockType = () => multiblockType;
export const getPlannerMultiblockSize = () => multiblockSize; export const getPlannerMultiblockSize = () => multiblockSize;

View File

@ -1,7 +1,6 @@
import { recall, save } from "./storage.js"; import { recall, save } from "./storage.js";
import { registerLoadCallback } from "./main.js";
registerLoadCallback(() => { export function initializeMenuResizing() {
const handles = document.querySelectorAll('[data-resize]'); const handles = document.querySelectorAll('[data-resize]');
handles.forEach(handle => { handles.forEach(handle => {
handle.addEventListener("mousedown", startResize); handle.addEventListener("mousedown", startResize);
@ -10,7 +9,7 @@ registerLoadCallback(() => {
document.body.style.setProperty(`--${handle.dataset.resize}-size`, stored); document.body.style.setProperty(`--${handle.dataset.resize}-size`, stored);
} }
}); });
}); }
function startResize(e) { function startResize(e) {
window.addEventListener("mouseup", endResize); window.addEventListener("mouseup", endResize);

View File

@ -1,72 +1,7 @@
import { configuration } from "./configuration.js"; import { configuration } from "./configuration.js";
import { emitEvent } from "./events.js"; import { emitEvent } from "./events.js";
import { registerLoadCallback } from "./main.js";
import { getPlannerCellDom, getPlannerDom } from "./planner.js";
import { findFullEntry } from "./ncpf-utils.js";
registerLoadCallback(() => {
});
const solverMetadata = {};
let solverMetadataCounter = 0;
function createSolverMetadata(data) {
const id = solverMetadataCounter;
solverMetadata[id] = data;
solverMetadataCounter++;
return id;
}
export function setSolverMetadata(domNode, data) {
if (domNode.dataset.solverMetadata) {
solverMetadata[Number(domNode.dataset.solverMetadata)] = data;
return;
}
domNode.dataset.solverMetadata = createSolverMetadata(data).toString(10);
}
export function getSolverMetadata(id) {
if (typeof id === "object") {
// assume DOM element
if (id.dataset && id.dataset.solverMetadata) {
return getSolverMetadata(id.dataset.solverMetadata);
}
return null;
}
if (typeof id === "string") {
return getSolverMetadata(Number(id));
}
return solverMetadata[id];
}
export function deleteSolverMetadata(id) {
delete solverMetadata[id];
}
export function resetSolver(design = undefined, designConfiguration) {
const planner = getPlannerDom();
if (design && designConfiguration) {
planner.dataset.type = design.type;
if (design.type === "nuclearcraft:overhaul_sfr") {
// design has coolant_recipe and block_recipes
const designCoolantRecipe = designConfiguration.coolant_recipes[design.coolant_recipe];
const fullCoolantRecipe = findFullEntry(
"coolant_recipes",
designCoolantRecipe,
{ configurationHint: design.type },
);
setSolverMetadata(planner, { coolant_recipe: fullCoolantRecipe });
const designBlockRecipes = design.block_recipes.flat(3);
for (let x = 0; x < design.dimensions[0]; x++) {
for (let y = 0; y < design.dimensions[1]; y++) {
for (let z = 0; z < design.dimensions[2]; z++) {
const block = designConfiguration.blocks[design.design[x][y][z]];
if (!block || !block.modules || !block.modules["ncpf:block_recipes"]) continue;
const blockRecipeIndex = designBlockRecipes.shift();
const blockRecipe = block.modules["ncpf:block_recipes"].recipes[blockRecipeIndex];
setSolverMetadata(getPlannerCellDom(x, y, z), { block_recipe: blockRecipe });
}
}
}
}
}
export function resetSolver(design = undefined) {
console.log("solver", configuration, design);
emitEvent("solver:reset:done"); emitEvent("solver:reset:done");
} }

View File

@ -1,6 +1,5 @@
import { debounce } from "./dom-utils.js"; import { debounce } from "./dom-utils.js";
import { emitEvent, listenTo } from "./events.js"; import { emitEvent, listenTo } from "./events.js";
import { registerLoadCallback } from "./main.js";
const tooltips = {}; const tooltips = {};
let tooltipsCounter = 0; let tooltipsCounter = 0;
@ -8,7 +7,7 @@ let lastCoordinates = null;
let suppressTooltips = false; let suppressTooltips = false;
let activeTooltipTarget = null; let activeTooltipTarget = null;
registerLoadCallback(() => { export function initializeTooltips() {
document.querySelectorAll("[data-retain-tooltip-hover]").forEach(elem => document.querySelectorAll("[data-retain-tooltip-hover]").forEach(elem =>
elem.addEventListener("mousemove", e => { elem.addEventListener("mousemove", e => {
if (lastCoordinates !== null) { if (lastCoordinates !== null) {
@ -41,7 +40,7 @@ registerLoadCallback(() => {
suppressTooltips = !suppressTooltips; suppressTooltips = !suppressTooltips;
} }
}); });
}); }
export function createTooltip(data) { export function createTooltip(data) {
const id = tooltipsCounter; const id = tooltipsCounter;

View File

@ -352,9 +352,7 @@ input:not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
} }
.dialog > section > footer { .dialog > section > footer {
display: flex; display: flex;
gap: 0.5em; flex-direction: row-reverse;
flex-direction: row;
justify-content: end;
} }
.dialog > section > .list-choice { .dialog > section > .list-choice {
display: flex; display: flex;