project migration to typescript

Project migration to typescript
This commit is contained in:
Dariusz L
2025-07-04 04:22:51 +02:00
parent 3e4cdf10bc
commit 5adc77471f
60 changed files with 12565 additions and 3021 deletions

View File

@@ -1,8 +1,3 @@
/**
* CommonUtils - Wspólne funkcje pomocnicze
* Eliminuje duplikację funkcji używanych w różnych modułach
*/
/**
* Generuje unikalny identyfikator UUID
* @returns {string} UUID w formacie xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
@@ -13,7 +8,6 @@ export function generateUUID() {
return v.toString(16);
});
}
/**
* Funkcja snap do siatki
* @param {number} value - Wartość do przyciągnięcia
@@ -23,58 +17,48 @@ export function generateUUID() {
export function snapToGrid(value, gridSize = 64) {
return Math.round(value / gridSize) * gridSize;
}
/**
* Oblicza dostosowanie snap dla warstwy
* @param {Object} layer - Obiekt warstwy
* @param {number} gridSize - Rozmiar siatki
* @param {number} snapThreshold - Próg przyciągania
* @returns {Object} Obiekt z dx i dy
* @returns {Point} Obiekt z dx i dy
*/
export function getSnapAdjustment(layer, gridSize = 64, snapThreshold = 10) {
if (!layer) {
return {dx: 0, dy: 0};
return { x: 0, y: 0 };
}
const layerEdges = {
left: layer.x,
right: layer.x + layer.width,
top: layer.y,
bottom: layer.y + layer.height
};
const x_adjustments = [
{type: 'x', delta: snapToGrid(layerEdges.left, gridSize) - layerEdges.left},
{type: 'x', delta: snapToGrid(layerEdges.right, gridSize) - layerEdges.right}
];
{ type: 'x', delta: snapToGrid(layerEdges.left, gridSize) - layerEdges.left },
{ type: 'x', delta: snapToGrid(layerEdges.right, gridSize) - layerEdges.right }
].map(adj => ({ ...adj, abs: Math.abs(adj.delta) }));
const y_adjustments = [
{type: 'y', delta: snapToGrid(layerEdges.top, gridSize) - layerEdges.top},
{type: 'y', delta: snapToGrid(layerEdges.bottom, gridSize) - layerEdges.bottom}
];
x_adjustments.forEach(adj => adj.abs = Math.abs(adj.delta));
y_adjustments.forEach(adj => adj.abs = Math.abs(adj.delta));
{ type: 'y', delta: snapToGrid(layerEdges.top, gridSize) - layerEdges.top },
{ type: 'y', delta: snapToGrid(layerEdges.bottom, gridSize) - layerEdges.bottom }
].map(adj => ({ ...adj, abs: Math.abs(adj.delta) }));
const bestXSnap = x_adjustments
.filter(adj => adj.abs < snapThreshold && adj.abs > 1e-9)
.sort((a, b) => a.abs - b.abs)[0];
const bestYSnap = y_adjustments
.filter(adj => adj.abs < snapThreshold && adj.abs > 1e-9)
.sort((a, b) => a.abs - b.abs)[0];
return {
dx: bestXSnap ? bestXSnap.delta : 0,
dy: bestYSnap ? bestYSnap.delta : 0
x: bestXSnap ? bestXSnap.delta : 0,
y: bestYSnap ? bestYSnap.delta : 0
};
}
/**
* Konwertuje współrzędne świata na lokalne
* @param {number} worldX - Współrzędna X w świecie
* @param {number} worldY - Współrzędna Y w świecie
* @param {Object} layerProps - Właściwości warstwy
* @returns {Object} Lokalne współrzędne {x, y}
* @param {any} layerProps - Właściwości warstwy
* @returns {Point} Lokalne współrzędne {x, y}
*/
export function worldToLocal(worldX, worldY, layerProps) {
const dx = worldX - layerProps.centerX;
@@ -82,46 +66,38 @@ export function worldToLocal(worldX, worldY, layerProps) {
const rad = -layerProps.rotation * Math.PI / 180;
const cos = Math.cos(rad);
const sin = Math.sin(rad);
return {
x: dx * cos - dy * sin,
y: dx * sin + dy * cos
};
}
/**
* Konwertuje współrzędne lokalne na świat
* @param {number} localX - Lokalna współrzędna X
* @param {number} localY - Lokalna współrzędna Y
* @param {Object} layerProps - Właściwości warstwy
* @returns {Object} Współrzędne świata {x, y}
* @param {any} layerProps - Właściwości warstwy
* @returns {Point} Współrzędne świata {x, y}
*/
export function localToWorld(localX, localY, layerProps) {
const rad = layerProps.rotation * Math.PI / 180;
const cos = Math.cos(rad);
const sin = Math.sin(rad);
return {
x: layerProps.centerX + localX * cos - localY * sin,
y: layerProps.centerY + localX * sin + localY * cos
};
}
/**
* Klonuje warstwy (bez klonowania obiektów Image dla oszczędności pamięci)
* @param {Array} layers - Tablica warstw do sklonowania
* @returns {Array} Sklonowane warstwy
* @param {Layer[]} layers - Tablica warstw do sklonowania
* @returns {Layer[]} Sklonowane warstwy
*/
export function cloneLayers(layers) {
return layers.map(layer => {
const newLayer = {...layer};
return newLayer;
});
return layers.map(layer => ({ ...layer }));
}
/**
* Tworzy sygnaturę stanu warstw (dla porównań)
* @param {Array} layers - Tablica warstw
* @param {Layer[]} layers - Tablica warstw
* @returns {string} Sygnatura JSON
*/
export function getStateSignature(layers) {
@@ -137,45 +113,43 @@ export function getStateSignature(layers) {
blendMode: layer.blendMode || 'normal',
opacity: layer.opacity !== undefined ? Math.round(layer.opacity * 100) / 100 : 1
};
if (layer.imageId) {
sig.imageId = layer.imageId;
}
if (layer.image && layer.image.src) {
sig.imageSrc = layer.image.src.substring(0, 100); // First 100 chars to avoid huge signatures
}
return sig;
}));
}
/**
* Debounce funkcja - opóźnia wykonanie funkcji
* @param {Function} func - Funkcja do wykonania
* @param {number} wait - Czas oczekiwania w ms
* @param {boolean} immediate - Czy wykonać natychmiast
* @returns {Function} Funkcja z debounce
* @returns {(...args: any[]) => void} Funkcja z debounce
*/
export function debounce(func, wait, immediate) {
let timeout;
return function executedFunction(...args) {
const later = () => {
timeout = null;
if (!immediate) func(...args);
if (!immediate)
func.apply(this, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func(...args);
if (timeout)
clearTimeout(timeout);
timeout = window.setTimeout(later, wait);
if (callNow)
func.apply(this, args);
};
}
/**
* Throttle funkcja - ogranicza częstotliwość wykonania
* @param {Function} func - Funkcja do wykonania
* @param {number} limit - Limit czasu w ms
* @returns {Function} Funkcja z throttle
* @returns {(...args: any[]) => void} Funkcja z throttle
*/
export function throttle(func, limit) {
let inThrottle;
@@ -187,7 +161,6 @@ export function throttle(func, limit) {
}
};
}
/**
* Ogranicza wartość do zakresu
* @param {number} value - Wartość do ograniczenia
@@ -198,7 +171,6 @@ export function throttle(func, limit) {
export function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
/**
* Interpolacja liniowa między dwoma wartościami
* @param {number} start - Wartość początkowa
@@ -209,7 +181,6 @@ export function clamp(value, min, max) {
export function lerp(start, end, factor) {
return start + (end - start) * factor;
}
/**
* Konwertuje stopnie na radiany
* @param {number} degrees - Stopnie
@@ -218,7 +189,6 @@ export function lerp(start, end, factor) {
export function degreesToRadians(degrees) {
return degrees * Math.PI / 180;
}
/**
* Konwertuje radiany na stopnie
* @param {number} radians - Radiany
@@ -227,23 +197,23 @@ export function degreesToRadians(degrees) {
export function radiansToDegrees(radians) {
return radians * 180 / Math.PI;
}
/**
* Tworzy canvas z kontekstem - eliminuje duplikaty w kodzie
* @param {number} width - Szerokość canvas
* @param {number} height - Wysokość canvas
* @param {string} contextType - Typ kontekstu (domyślnie '2d')
* @param {Object} contextOptions - Opcje kontekstu
* @returns {Object} Obiekt z canvas i ctx
* @param {object} contextOptions - Opcje kontekstu
* @returns {{canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D | null}} Obiekt z canvas i ctx
*/
export function createCanvas(width, height, contextType = '2d', contextOptions = {}) {
const canvas = document.createElement('canvas');
if (width) canvas.width = width;
if (height) canvas.height = height;
if (width)
canvas.width = width;
if (height)
canvas.height = height;
const ctx = canvas.getContext(contextType, contextOptions);
return {canvas, ctx};
return { canvas, ctx };
}
/**
* Normalizuje wartość do zakresu Uint8 (0-255)
* @param {number} value - Wartość do znormalizowania (0-1)
@@ -252,11 +222,10 @@ export function createCanvas(width, height, contextType = '2d', contextOptions =
export function normalizeToUint8(value) {
return Math.max(0, Math.min(255, Math.round(value * 255)));
}
/**
* Generuje unikalną nazwę pliku z identyfikatorem node-a
* @param {string} baseName - Podstawowa nazwa pliku
* @param {string|number} nodeId - Identyfikator node-a
* @param {string | number} nodeId - Identyfikator node-a
* @returns {string} Unikalna nazwa pliku
*/
export function generateUniqueFileName(baseName, nodeId) {
@@ -271,7 +240,6 @@ export function generateUniqueFileName(baseName, nodeId) {
const nameWithoutExt = baseName.replace(`.${extension}`, '');
return `${nameWithoutExt}_node_${nodeId}.${extension}`;
}
/**
* Sprawdza czy punkt jest w prostokącie
* @param {number} pointX - X punktu