126 lines
3.9 KiB
JavaScript
126 lines
3.9 KiB
JavaScript
export function isNotEmpty(value) {
|
|
if (value === null || value === undefined) return false;
|
|
|
|
if (Array.isArray(value)) return value.length > 0;
|
|
|
|
if (typeof value === 'object') return Object.keys(value).length > 0;
|
|
|
|
if (typeof value === 'string') return value.trim() !== '';
|
|
|
|
return true; // для чисел, булевых и т.п.
|
|
}
|
|
|
|
export function formatPrice(raw) {
|
|
if (raw === null || raw === undefined) return '';
|
|
|
|
const str = String(raw).trim();
|
|
const match = str.match(/^([+-]?)(\d+(?:\.\d+)?)/);
|
|
if (!match) return '';
|
|
|
|
const sign = match[1] || '';
|
|
const num = parseFloat(match[2]);
|
|
|
|
if (isNaN(num) || num === 0) return '';
|
|
|
|
const formatted = Math.round(num)
|
|
.toString()
|
|
.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
|
|
|
|
return `${sign}${formatted}`;
|
|
}
|
|
|
|
/**
|
|
* Получить CSS-переменную DaisyUI OKLH/OKLCH и вернуть HEX для Telegram
|
|
* @param {string} cssVarName - например '--color-base-100'
|
|
* @returns {string} #RRGGBB
|
|
*/
|
|
export function getCssVarOklchRgb(cssVarName) {
|
|
// Получаем значение CSS-переменной
|
|
const cssVar = getComputedStyle(document.documentElement)
|
|
.getPropertyValue(cssVarName)
|
|
.trim();
|
|
|
|
// Проверяем, что это OKLCH
|
|
const match = cssVar.match(/^oklch\(\s*([\d.]+)%?\s+([\d.]+)\s+([\d.]+)\s*\)$/);
|
|
if (!match) {
|
|
console.warn(`CSS variable ${cssVarName} is not a valid OKLCH`);
|
|
return { r:0, g:0, b:0 };
|
|
}
|
|
|
|
// Парсим L, C, H
|
|
const L = parseFloat(match[1]) / 100; // L в daisyUI в процентах
|
|
const C = parseFloat(match[2]);
|
|
const H = parseFloat(match[3]);
|
|
|
|
// --- OKLCH -> OKLab ---
|
|
const hRad = (H * Math.PI) / 180;
|
|
const a = C * Math.cos(hRad);
|
|
const b = C * Math.sin(hRad);
|
|
const l = L;
|
|
|
|
// --- OKLab -> Linear RGB ---
|
|
const l_ = l + 0.3963377774 * a + 0.2158037573 * b;
|
|
const m_ = l - 0.1055613458 * a - 0.0638541728 * b;
|
|
const s_ = l - 0.0894841775 * a - 1.2914855480 * b;
|
|
|
|
const lCubed = l_ ** 3;
|
|
const mCubed = m_ ** 3;
|
|
const sCubed = s_ ** 3;
|
|
|
|
let r = 4.0767416621 * lCubed - 3.3077115913 * mCubed + 0.2309699292 * sCubed;
|
|
let g = -1.2684380046 * lCubed + 2.6097574011 * mCubed - 0.3413193965 * sCubed;
|
|
let b_ = -0.0041960863 * lCubed - 0.7034186147 * mCubed + 1.7076147010 * sCubed;
|
|
|
|
// --- Линейный RGB -> sRGB ---
|
|
const gammaCorrect = c => {
|
|
c = Math.min(Math.max(c, 0), 1); // обрезаем 0..1
|
|
return c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1/2.4) - 0.055;
|
|
};
|
|
|
|
r = Math.round(gammaCorrect(r) * 255);
|
|
g = Math.round(gammaCorrect(g) * 255);
|
|
b_ = Math.round(gammaCorrect(b_) * 255);
|
|
|
|
// --- Преобразуем в HEX ---
|
|
const toHex = n => n.toString(16).padStart(2, '0');
|
|
|
|
return `#${toHex(r)}${toHex(g)}${toHex(b_)}`;
|
|
}
|
|
|
|
export function deserializeStartParams(serialized) {
|
|
if (!serialized) {
|
|
return {};
|
|
}
|
|
|
|
// Восстанавливаем стандартные base64 символы
|
|
let encoded = serialized.replace(/-/g, '+').replace(/_/g, '/');
|
|
|
|
// Добавляем padding, если нужно
|
|
const padding = encoded.length % 4;
|
|
if (padding !== 0) {
|
|
encoded += '='.repeat(4 - padding);
|
|
}
|
|
|
|
// Декодируем из base64
|
|
let json;
|
|
try {
|
|
json = atob(encoded); // btoa / atob стандартные в браузере
|
|
} catch (e) {
|
|
throw new Error('Failed to decode base64 string');
|
|
}
|
|
|
|
// Парсим JSON
|
|
let parameters;
|
|
try {
|
|
parameters = JSON.parse(json);
|
|
} catch (e) {
|
|
throw new Error('Failed to decode JSON: ' + e.message);
|
|
}
|
|
|
|
if (typeof parameters !== 'object' || parameters === null || Array.isArray(parameters) && !Array.isArray(parameters)) {
|
|
throw new Error('Decoded value is not an object');
|
|
}
|
|
|
|
return parameters;
|
|
}
|