Files
xk-admin/apps/web-antd/src/components/canvas-spreadsheet/canvas/theme.ts
李琦 a38da5ce92
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
1. Excel交互组件封装优化
2026-06-26 12:52:26 +08:00

147 lines
4.1 KiB
TypeScript

export interface SpreadsheetTheme {
headerBg: string;
headerText: string;
cellBg: string;
border: string;
text: string;
textMuted: string;
selectionBg: string;
selectionBorder: string;
dirtyBg: string;
rowNumBg: string;
fillHandle: string;
fixedShadow: string;
imagePlaceholder: string;
findMatchBg: string;
findActiveMatchBg: string;
findActiveBorder: string;
}
export function getSpreadsheetTheme(isDark: boolean): SpreadsheetTheme {
if (isDark) {
return {
headerBg: '#1f1f1f',
headerText: 'rgba(255, 255, 255, 0.85)',
cellBg: '#141414',
border: '#424242',
text: 'rgba(255, 255, 255, 0.85)',
textMuted: 'rgba(255, 255, 255, 0.45)',
selectionBg: 'rgba(22, 93, 255, 0.25)',
selectionBorder: '#1668dc',
dirtyBg: 'rgba(255, 125, 0, 0.2)',
rowNumBg: '#1a1a1a',
fillHandle: '#1668dc',
fixedShadow: 'rgba(0, 0, 0, 0.45)',
imagePlaceholder: '#303030',
findMatchBg: 'rgba(255, 212, 0, 0.35)',
findActiveMatchBg: 'rgba(255, 212, 0, 0.55)',
findActiveBorder: '#faad14',
};
}
return {
headerBg: '#f5f7fa',
headerText: '#1d2129',
cellBg: '#ffffff',
border: '#e5e6eb',
text: '#1d2129',
textMuted: '#86909c',
selectionBg: 'rgba(22, 93, 255, 0.08)',
selectionBorder: '#165dff',
dirtyBg: 'rgba(255, 125, 0, 0.12)',
rowNumBg: '#fafafa',
fillHandle: '#165dff',
fixedShadow: 'rgba(0, 0, 0, 0.12)',
imagePlaceholder: '#f2f3f5',
findMatchBg: '#fff566',
findActiveMatchBg: '#ffe58f',
findActiveBorder: '#faad14',
};
}
export const HEADER_COLOR_PRESETS = [
'#f0f5ff',
'#fff7e6',
'#f6ffed',
'#fff1f0',
'#f9f0ff',
'#e6fffb',
];
function parseHexColor(hex: string): { r: number; g: number; b: number } | null {
const normalized = hex.trim().replace('#', '');
if (normalized.length === 3) {
return {
r: Number.parseInt(normalized[0]! + normalized[0], 16),
g: Number.parseInt(normalized[1]! + normalized[1], 16),
b: Number.parseInt(normalized[2]! + normalized[2], 16),
};
}
if (normalized.length === 6) {
return {
r: Number.parseInt(normalized.slice(0, 2), 16),
g: Number.parseInt(normalized.slice(2, 4), 16),
b: Number.parseInt(normalized.slice(4, 6), 16),
};
}
return null;
}
function rgbToHsl(r: number, g: number, b: number) {
const rn = r / 255;
const gn = g / 255;
const bn = b / 255;
const max = Math.max(rn, gn, bn);
const min = Math.min(rn, gn, bn);
const l = (max + min) / 2;
if (max === min) {
return { h: 0, s: 0, l };
}
const d = max - min;
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
let h = 0;
if (max === rn) h = ((gn - bn) / d + (gn < bn ? 6 : 0)) / 6;
else if (max === gn) h = ((bn - rn) / d + 2) / 6;
else h = ((rn - gn) / d + 4) / 6;
return { h, s, l };
}
function hslToHex(h: number, s: number, l: number): string {
if (s === 0) {
const v = Math.round(l * 255);
const hex = v.toString(16).padStart(2, '0');
return `#${hex}${hex}${hex}`;
}
const hue2rgb = (p: number, q: number, t: number) => {
let tt = t;
if (tt < 0) tt += 1;
if (tt > 1) tt -= 1;
if (tt < 1 / 6) return p + (q - p) * 6 * tt;
if (tt < 1 / 2) return q;
if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
const r = Math.round(hue2rgb(p, q, h + 1 / 3) * 255);
const g = Math.round(hue2rgb(p, q, h) * 255);
const b = Math.round(hue2rgb(p, q, h - 1 / 3) * 255);
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}
export function resolveHeaderColor(
color: string | undefined,
isDark: boolean,
fallback: string,
): string {
if (!color) return fallback;
if (!isDark) return color;
const rgb = parseHexColor(color);
if (!rgb) return fallback;
const { h, s, l } = rgbToHsl(rgb.r, rgb.g, rgb.b);
const darkL = Math.min(0.28, Math.max(0.16, l * 0.35 + 0.12));
const darkS = Math.min(0.55, s * 0.75 + 0.08);
return hslToHex(h, darkS, darkL);
}