import { layoutConfig } from './layout'; export type SearchProvider = { id: 'baidu' | 'bing' | 'google' | 'zhihu'; label: string; url: string; placeholder: string; }; export const searchProviders: SearchProvider[] = [ { id: 'baidu', label: '百度', url: 'https://www.baidu.com/s?wd=', placeholder: '百度一下', }, { id: 'bing', label: '必应', url: 'https://www.bing.com/search?q=', placeholder: '搜索必应', }, { id: 'google', label: '谷歌', url: 'https://www.google.com/search?q=', placeholder: '搜索谷歌', }, { id: 'zhihu', label: '知乎', url: 'https://www.zhihu.com/search?q=', placeholder: '知乎搜索', }, ]; export type SearchProviderId = SearchProvider['id']; export const getSearchProvider = (id?: string) => searchProviders.find(item => item.id === id) ?? searchProviders[0]; export type ThemePreset = { id: 'default' | 'warm' | 'sea' | 'forest'; label: string; overlay: string; image: string; }; export const themePresets: ThemePreset[] = [ { id: 'default', label: '默认', overlay: 'none', image: "url('/bg.png')", }, { id: 'warm', label: '暖阳', overlay: 'linear-gradient(135deg, rgba(255, 185, 110, 0.32), rgba(255, 221, 149, 0.14))', image: "url('/bg.png')", }, { id: 'sea', label: '海盐', overlay: 'linear-gradient(135deg, rgba(88, 200, 255, 0.3), rgba(183, 240, 255, 0.14))', image: "url('/bg.png')", }, { id: 'forest', label: '松林', overlay: 'linear-gradient(135deg, rgba(96, 198, 137, 0.28), rgba(217, 247, 201, 0.12))', image: "url('/bg.png')", }, ]; export type ThemePresetId = ThemePreset['id']; export const getThemePreset = (id?: string) => themePresets.find(item => item.id === id) ?? themePresets[0]; const clamp = (value: number, min: number) => (value < min ? min : value); const clampRange = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max); export type LayoutDensityPreset = { value: number; label: string; cellSize: number; gap: number; }; const baseGrid = layoutConfig.grid; const baseIcon = layoutConfig.icon; export const layoutDensityPresets: LayoutDensityPreset[] = [ { value: 1, label: '宽松', cellSize: baseGrid.cellSize + 16, gap: baseGrid.gap + 10, }, { value: 2, label: '标准', cellSize: baseGrid.cellSize, gap: baseGrid.gap, }, { value: 3, label: '紧凑', cellSize: clamp(baseGrid.cellSize - 18, 76), gap: clamp(baseGrid.gap - 6, 8), }, { value: 4, label: '更紧凑', cellSize: clamp(baseGrid.cellSize - 32, 64), gap: clamp(baseGrid.gap - 10, 4), }, ]; export const layoutDensityRange = { min: 1, max: 4, step: 0.1, default: 2, }; export const getLayoutDensityPreset = (value?: number) => { const normalized = clampRange( typeof value === 'number' ? value : layoutDensityRange.default, layoutDensityRange.min, layoutDensityRange.max ); const lower = Math.floor(normalized); const upper = Math.ceil(normalized); if (lower === upper) { return layoutDensityPresets[lower - 1] ?? layoutDensityPresets[1]; } const lowerPreset = layoutDensityPresets[lower - 1] ?? layoutDensityPresets[0]; const upperPreset = layoutDensityPresets[upper - 1] ?? layoutDensityPresets[layoutDensityPresets.length - 1]; const t = (normalized - lower) / (upper - lower); return { value: normalized, label: t < 0.5 ? lowerPreset.label : upperPreset.label, cellSize: Math.round(lowerPreset.cellSize + (upperPreset.cellSize - lowerPreset.cellSize) * t), gap: Math.round(lowerPreset.gap + (upperPreset.gap - lowerPreset.gap) * t), }; }; export const iconDensityRange = { min: 0, max: 50, step: 1, default: 25, }; const iconDensityScaleRange = { loose: 2, dense: 0, }; export const getIconDensityScale = (value?: number) => { const normalized = clampRange( typeof value === 'number' ? value : iconDensityRange.default, iconDensityRange.min, iconDensityRange.max ); const ease = (t: number) => Math.pow(t, 0.5); if (normalized === iconDensityRange.default) { return 1; } if (normalized < iconDensityRange.default) { // Smaller slider value = denser布局 const t = (iconDensityRange.default - normalized) / (iconDensityRange.default - iconDensityRange.min); return 1 - ease(t) * (1 - iconDensityScaleRange.dense); } const t = (normalized - iconDensityRange.default) / (iconDensityRange.max - iconDensityRange.default); return 1 + ease(t) * (iconDensityScaleRange.loose - 1); }; export const iconSizeRange = { min: 70, max: 100, step: 1, default: Math.round( ((baseGrid.cellSize - baseIcon.padding * 2) / baseGrid.cellSize) * 100 ), }; export const iconRadiusRange = { min: 0, max: 24, step: 1, default: baseIcon.radius, };