625 lines
19 KiB
TypeScript
625 lines
19 KiB
TypeScript
/**
|
|
* ============================================================================
|
|
* MOCK FONT DATA
|
|
* ============================================================================
|
|
*
|
|
* Factory functions and preset mock data for fonts.
|
|
* Used in Storybook stories, tests, and development.
|
|
*
|
|
* ## Usage
|
|
*
|
|
* ```ts
|
|
* import {
|
|
* mockGoogleFont,
|
|
* mockFontshareFont,
|
|
* mockUnifiedFont,
|
|
* GOOGLE_FONTS,
|
|
* FONTHARE_FONTS,
|
|
* UNIFIED_FONTS,
|
|
* } from '$entities/Font/lib/mocks';
|
|
*
|
|
* // Create a mock Google Font
|
|
* const roboto = mockGoogleFont({ family: 'Roboto', category: 'sans-serif' });
|
|
*
|
|
* // Create a mock Fontshare font
|
|
* const satoshi = mockFontshareFont({ name: 'Satoshi', slug: 'satoshi' });
|
|
*
|
|
* // Create a mock UnifiedFont
|
|
* const font = mockUnifiedFont({ id: 'roboto', name: 'Roboto' });
|
|
*
|
|
* // Use preset fonts
|
|
* import { UNIFIED_FONTS } from '$entities/Font/lib/mocks';
|
|
* ```
|
|
*/
|
|
|
|
import type {
|
|
FontCategory,
|
|
FontProvider,
|
|
FontSubset,
|
|
FontVariant,
|
|
} from '$entities/Font/model/types';
|
|
import type {
|
|
FontItem,
|
|
FontshareFont,
|
|
GoogleFontItem,
|
|
} from '$entities/Font/model/types';
|
|
import type {
|
|
FontFeatures,
|
|
FontMetadata,
|
|
FontStyleUrls,
|
|
UnifiedFont,
|
|
} from '$entities/Font/model/types';
|
|
|
|
// GOOGLE FONTS MOCKS
|
|
|
|
/**
|
|
* Options for creating a mock Google Font
|
|
*/
|
|
export interface MockGoogleFontOptions {
|
|
/** Font family name (default: 'Mock Font') */
|
|
family?: string;
|
|
/** Font category (default: 'sans-serif') */
|
|
category?: 'sans-serif' | 'serif' | 'display' | 'handwriting' | 'monospace';
|
|
/** Font variants (default: ['regular', '700', 'italic', '700italic']) */
|
|
variants?: FontVariant[];
|
|
/** Font subsets (default: ['latin']) */
|
|
subsets?: string[];
|
|
/** Font version (default: 'v30') */
|
|
version?: string;
|
|
/** Last modified date (default: current ISO date) */
|
|
lastModified?: string;
|
|
/** Custom file URLs (if not provided, mock URLs are generated) */
|
|
files?: Partial<Record<FontVariant, string>>;
|
|
/** Popularity rank (1 = most popular) */
|
|
popularity?: number;
|
|
}
|
|
|
|
/**
|
|
* Default mock Google Font
|
|
*/
|
|
export function mockGoogleFont(options: MockGoogleFontOptions = {}): GoogleFontItem {
|
|
const {
|
|
family = 'Mock Font',
|
|
category = 'sans-serif',
|
|
variants = ['regular', '700', 'italic', '700italic'],
|
|
subsets = ['latin'],
|
|
version = 'v30',
|
|
lastModified = new Date().toISOString().split('T')[0],
|
|
files,
|
|
popularity = 1,
|
|
} = options;
|
|
|
|
const baseUrl = `https://fonts.gstatic.com/s/${family.toLowerCase().replace(/\s+/g, '')}/${version}`;
|
|
|
|
return {
|
|
family,
|
|
category,
|
|
variants: variants as FontVariant[],
|
|
subsets,
|
|
version,
|
|
lastModified,
|
|
files: files ?? {
|
|
regular: `${baseUrl}/KFOmCnqEu92Fr1Me4W.woff2`,
|
|
'700': `${baseUrl}/KFOlCnqEu92Fr1MmWUlfBBc9.woff2`,
|
|
italic: `${baseUrl}/KFOkCnqEu92Fr1Mu51xIIzI.woff2`,
|
|
'700italic': `${baseUrl}/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2`,
|
|
},
|
|
menu: `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family)}`,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Preset Google Font mocks
|
|
*/
|
|
export const GOOGLE_FONTS: Record<string, GoogleFontItem> = {
|
|
roboto: mockGoogleFont({
|
|
family: 'Roboto',
|
|
category: 'sans-serif',
|
|
variants: ['100', '300', '400', '500', '700', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'greek'],
|
|
popularity: 1,
|
|
}),
|
|
openSans: mockGoogleFont({
|
|
family: 'Open Sans',
|
|
category: 'sans-serif',
|
|
variants: ['300', '400', '500', '600', '700', '800', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'greek'],
|
|
popularity: 2,
|
|
}),
|
|
lato: mockGoogleFont({
|
|
family: 'Lato',
|
|
category: 'sans-serif',
|
|
variants: ['100', '300', '400', '700', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext'],
|
|
popularity: 3,
|
|
}),
|
|
playfairDisplay: mockGoogleFont({
|
|
family: 'Playfair Display',
|
|
category: 'serif',
|
|
variants: ['400', '500', '600', '700', '800', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic'],
|
|
popularity: 10,
|
|
}),
|
|
montserrat: mockGoogleFont({
|
|
family: 'Montserrat',
|
|
category: 'sans-serif',
|
|
variants: ['100', '200', '300', '400', '500', '600', '700', '800', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'vietnamese'],
|
|
popularity: 4,
|
|
}),
|
|
sourceSansPro: mockGoogleFont({
|
|
family: 'Source Sans Pro',
|
|
category: 'sans-serif',
|
|
variants: ['200', '300', '400', '600', '700', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'greek', 'vietnamese'],
|
|
popularity: 5,
|
|
}),
|
|
merriweather: mockGoogleFont({
|
|
family: 'Merriweather',
|
|
category: 'serif',
|
|
variants: ['300', '400', '700', '900', 'italic', '700italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'vietnamese'],
|
|
popularity: 15,
|
|
}),
|
|
robotoSlab: mockGoogleFont({
|
|
family: 'Roboto Slab',
|
|
category: 'serif',
|
|
variants: ['100', '300', '400', '500', '700', '900'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'greek', 'vietnamese'],
|
|
popularity: 8,
|
|
}),
|
|
oswald: mockGoogleFont({
|
|
family: 'Oswald',
|
|
category: 'sans-serif',
|
|
variants: ['200', '300', '400', '500', '600', '700'],
|
|
subsets: ['latin', 'latin-ext', 'vietnamese'],
|
|
popularity: 6,
|
|
}),
|
|
raleway: mockGoogleFont({
|
|
family: 'Raleway',
|
|
category: 'sans-serif',
|
|
variants: ['100', '200', '300', '400', '500', '600', '700', '800', '900', 'italic'],
|
|
subsets: ['latin', 'latin-ext', 'cyrillic', 'vietnamese'],
|
|
popularity: 7,
|
|
}),
|
|
};
|
|
|
|
// FONTHARE MOCKS
|
|
|
|
/**
|
|
* Options for creating a mock Fontshare font
|
|
*/
|
|
export interface MockFontshareFontOptions {
|
|
/** Font name (default: 'Mock Font') */
|
|
name?: string;
|
|
/** URL-friendly slug (default: derived from name) */
|
|
slug?: string;
|
|
/** Font category (default: 'sans') */
|
|
category?: 'sans' | 'serif' | 'slab' | 'display' | 'handwritten' | 'script' | 'mono';
|
|
/** Script (default: 'latin') */
|
|
script?: string;
|
|
/** Whether this is a variable font (default: false) */
|
|
isVariable?: boolean;
|
|
/** Font version (default: '1.0') */
|
|
version?: string;
|
|
/** Popularity/views count (default: 1000) */
|
|
views?: number;
|
|
/** Usage tags */
|
|
tags?: string[];
|
|
/** Font weights available */
|
|
weights?: number[];
|
|
/** Publisher name */
|
|
publisher?: string;
|
|
/** Designer name */
|
|
designer?: string;
|
|
}
|
|
|
|
/**
|
|
* Create a mock Fontshare style
|
|
*/
|
|
function mockFontshareStyle(
|
|
weight: number,
|
|
isItalic: boolean,
|
|
isVariable: boolean,
|
|
slug: string,
|
|
): FontshareFont['styles'][number] {
|
|
const weightLabel = weight === 400 ? 'Regular' : weight === 700 ? 'Bold' : weight.toString();
|
|
const suffix = isItalic ? 'italic' : '';
|
|
const variablePrefix = isVariable ? 'variable-' : '';
|
|
|
|
return {
|
|
id: `style-${weight}${isItalic ? '-italic' : ''}`,
|
|
default: weight === 400 && !isItalic,
|
|
file: `//cdn.fontshare.com/wf/${slug}-${variablePrefix}${weight}${suffix}.woff2`,
|
|
is_italic: isItalic,
|
|
is_variable: isVariable,
|
|
properties: {},
|
|
weight: {
|
|
label: isVariable ? 'Variable' + (isItalic ? ' Italic' : '') : weightLabel,
|
|
name: isVariable ? 'Variable' + (isItalic ? 'Italic' : '') : weightLabel,
|
|
native_name: null,
|
|
number: isVariable ? 0 : weight,
|
|
weight: isVariable ? 0 : weight,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Default mock Fontshare font
|
|
*/
|
|
export function mockFontshareFont(options: MockFontshareFontOptions = {}): FontshareFont {
|
|
const {
|
|
name = 'Mock Font',
|
|
slug = name.toLowerCase().replace(/\s+/g, '-'),
|
|
category = 'sans',
|
|
script = 'latin',
|
|
isVariable = false,
|
|
version = '1.0',
|
|
views = 1000,
|
|
tags = [],
|
|
weights = [400, 700],
|
|
publisher = 'Mock Foundry',
|
|
designer = 'Mock Designer',
|
|
} = options;
|
|
|
|
// Generate styles based on weights and variable setting
|
|
const styles: FontshareFont['styles'] = isVariable
|
|
? [
|
|
mockFontshareStyle(0, false, true, slug),
|
|
mockFontshareStyle(0, true, true, slug),
|
|
]
|
|
: weights.flatMap(weight => [
|
|
mockFontshareStyle(weight, false, false, slug),
|
|
mockFontshareStyle(weight, true, false, slug),
|
|
]);
|
|
|
|
return {
|
|
id: `mock-${slug}`,
|
|
name,
|
|
native_name: null,
|
|
slug,
|
|
category,
|
|
script,
|
|
publisher: {
|
|
bio: `Mock publisher bio for ${publisher}`,
|
|
email: null,
|
|
id: `pub-${slug}`,
|
|
links: [],
|
|
name: publisher,
|
|
},
|
|
designers: [
|
|
{
|
|
bio: `Mock designer bio for ${designer}`,
|
|
links: [],
|
|
name: designer,
|
|
},
|
|
],
|
|
related_families: null,
|
|
display_publisher_as_designer: false,
|
|
trials_enabled: true,
|
|
show_latin_metrics: false,
|
|
license_type: 'ofl',
|
|
languages: 'English, Spanish, French, German',
|
|
inserted_at: '2021-03-12T20:49:05Z',
|
|
story: `<p>A mock font story for ${name}.</p>`,
|
|
version,
|
|
views,
|
|
views_recent: Math.floor(views * 0.1),
|
|
is_hot: views > 5000,
|
|
is_new: views < 500,
|
|
is_shortlisted: null,
|
|
is_top: views > 10000,
|
|
axes: isVariable
|
|
? [
|
|
{
|
|
name: 'Weight',
|
|
property: 'wght',
|
|
range_default: 400,
|
|
range_left: 300,
|
|
range_right: 700,
|
|
},
|
|
]
|
|
: [],
|
|
font_tags: tags.map(name => ({ name })),
|
|
features: [],
|
|
styles,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Preset Fontshare font mocks
|
|
*/
|
|
export const FONTHARE_FONTS: Record<string, FontshareFont> = {
|
|
satoshi: mockFontshareFont({
|
|
name: 'Satoshi',
|
|
slug: 'satoshi',
|
|
category: 'sans',
|
|
isVariable: true,
|
|
views: 15000,
|
|
tags: ['Branding', 'Logos', 'Editorial'],
|
|
publisher: 'Indian Type Foundry',
|
|
designer: 'Denis Shelabovets',
|
|
}),
|
|
generalSans: mockFontshareFont({
|
|
name: 'General Sans',
|
|
slug: 'general-sans',
|
|
category: 'sans',
|
|
isVariable: true,
|
|
views: 12000,
|
|
tags: ['UI', 'Branding', 'Display'],
|
|
publisher: 'Indestructible Type',
|
|
designer: 'Eugene Tantsur',
|
|
}),
|
|
clashDisplay: mockFontshareFont({
|
|
name: 'Clash Display',
|
|
slug: 'clash-display',
|
|
category: 'display',
|
|
isVariable: false,
|
|
views: 8000,
|
|
tags: ['Headlines', 'Posters', 'Branding'],
|
|
weights: [400, 500, 600, 700],
|
|
publisher: 'Letterogika',
|
|
designer: 'Matěj Trnka',
|
|
}),
|
|
fonta: mockFontshareFont({
|
|
name: 'Fonta',
|
|
slug: 'fonta',
|
|
category: 'serif',
|
|
isVariable: false,
|
|
views: 5000,
|
|
tags: ['Editorial', 'Books', 'Magazines'],
|
|
weights: [300, 400, 500, 600, 700],
|
|
publisher: 'Fonta',
|
|
designer: 'Alexei Vanyashin',
|
|
}),
|
|
aileron: mockFontshareFont({
|
|
name: 'Aileron',
|
|
slug: 'aileron',
|
|
category: 'sans',
|
|
isVariable: false,
|
|
views: 3000,
|
|
tags: ['Display', 'Headlines'],
|
|
weights: [100, 200, 300, 400, 500, 600, 700, 800, 900],
|
|
publisher: 'Sorkin Type',
|
|
designer: 'Sorkin Type',
|
|
}),
|
|
beVietnamPro: mockFontshareFont({
|
|
name: 'Be Vietnam Pro',
|
|
slug: 'be-vietnam-pro',
|
|
category: 'sans',
|
|
isVariable: true,
|
|
views: 20000,
|
|
tags: ['UI', 'App', 'Web'],
|
|
publisher: 'ildefox',
|
|
designer: 'Manh Nguyen',
|
|
}),
|
|
};
|
|
|
|
// UNIFIED FONT MOCKS
|
|
|
|
/**
|
|
* Options for creating a mock UnifiedFont
|
|
*/
|
|
export interface MockUnifiedFontOptions {
|
|
/** Unique identifier (default: derived from name) */
|
|
id?: string;
|
|
/** Font display name (default: 'Mock Font') */
|
|
name?: string;
|
|
/** Font provider (default: 'google') */
|
|
provider?: FontProvider;
|
|
/** Font category (default: 'sans-serif') */
|
|
category?: FontCategory;
|
|
/** Font subsets (default: ['latin']) */
|
|
subsets?: FontSubset[];
|
|
/** Font variants (default: ['regular', '700', 'italic', '700italic']) */
|
|
variants?: FontVariant[];
|
|
/** Style URLs (if not provided, mock URLs are generated) */
|
|
styles?: FontStyleUrls;
|
|
/** Metadata overrides */
|
|
metadata?: Partial<FontMetadata>;
|
|
/** Features overrides */
|
|
features?: Partial<FontFeatures>;
|
|
}
|
|
|
|
/**
|
|
* Default mock UnifiedFont
|
|
*/
|
|
export function mockUnifiedFont(options: MockUnifiedFontOptions = {}): UnifiedFont {
|
|
const {
|
|
id,
|
|
name = 'Mock Font',
|
|
provider = 'google',
|
|
category = 'sans-serif',
|
|
subsets = ['latin'],
|
|
variants = ['regular', '700', 'italic', '700italic'],
|
|
styles,
|
|
metadata,
|
|
features,
|
|
} = options;
|
|
|
|
const fontId = id ?? name.toLowerCase().replace(/\s+/g, '');
|
|
const baseUrl = provider === 'google'
|
|
? `https://fonts.gstatic.com/s/${fontId}/v30`
|
|
: `//cdn.fontshare.com/wf/${fontId}`;
|
|
|
|
return {
|
|
id: fontId,
|
|
name,
|
|
provider,
|
|
category,
|
|
subsets,
|
|
variants: variants as FontVariant[],
|
|
styles: styles ?? {
|
|
regular: `${baseUrl}/regular.woff2`,
|
|
bold: `${baseUrl}/bold.woff2`,
|
|
italic: `${baseUrl}/italic.woff2`,
|
|
boldItalic: `${baseUrl}/bolditalic.woff2`,
|
|
},
|
|
metadata: {
|
|
cachedAt: Date.now(),
|
|
version: '1.0',
|
|
lastModified: new Date().toISOString().split('T')[0],
|
|
popularity: 1,
|
|
...metadata,
|
|
},
|
|
features: {
|
|
isVariable: false,
|
|
...features,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Preset UnifiedFont mocks
|
|
*/
|
|
export const UNIFIED_FONTS: Record<string, UnifiedFont> = {
|
|
roboto: mockUnifiedFont({
|
|
id: 'roboto',
|
|
name: 'Roboto',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin', 'latin-ext'],
|
|
variants: ['100', '300', '400', '500', '700', '900'],
|
|
metadata: { popularity: 1 },
|
|
}),
|
|
openSans: mockUnifiedFont({
|
|
id: 'open-sans',
|
|
name: 'Open Sans',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin', 'latin-ext'],
|
|
variants: ['300', '400', '500', '600', '700', '800'],
|
|
metadata: { popularity: 2 },
|
|
}),
|
|
lato: mockUnifiedFont({
|
|
id: 'lato',
|
|
name: 'Lato',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin', 'latin-ext'],
|
|
variants: ['100', '300', '400', '700', '900'],
|
|
metadata: { popularity: 3 },
|
|
}),
|
|
playfairDisplay: mockUnifiedFont({
|
|
id: 'playfair-display',
|
|
name: 'Playfair Display',
|
|
provider: 'google',
|
|
category: 'serif',
|
|
subsets: ['latin'],
|
|
variants: ['400', '700', '900'],
|
|
metadata: { popularity: 10 },
|
|
}),
|
|
montserrat: mockUnifiedFont({
|
|
id: 'montserrat',
|
|
name: 'Montserrat',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin', 'latin-ext'],
|
|
variants: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
|
metadata: { popularity: 4 },
|
|
}),
|
|
satoshi: mockUnifiedFont({
|
|
id: 'satoshi',
|
|
name: 'Satoshi',
|
|
provider: 'fontshare',
|
|
category: 'sans-serif',
|
|
subsets: ['latin'],
|
|
variants: ['regular', 'bold', 'italic', 'bolditalic'] as FontVariant[],
|
|
features: { isVariable: true, axes: [{ name: 'wght', property: 'wght', default: 400, min: 300, max: 700 }] },
|
|
metadata: { popularity: 15000 },
|
|
}),
|
|
generalSans: mockUnifiedFont({
|
|
id: 'general-sans',
|
|
name: 'General Sans',
|
|
provider: 'fontshare',
|
|
category: 'sans-serif',
|
|
subsets: ['latin'],
|
|
variants: ['regular', 'bold', 'italic', 'bolditalic'] as FontVariant[],
|
|
features: { isVariable: true },
|
|
metadata: { popularity: 12000 },
|
|
}),
|
|
clashDisplay: mockUnifiedFont({
|
|
id: 'clash-display',
|
|
name: 'Clash Display',
|
|
provider: 'fontshare',
|
|
category: 'display',
|
|
subsets: ['latin'],
|
|
variants: ['regular', '500', '600', 'bold'] as FontVariant[],
|
|
features: { tags: ['Headlines', 'Posters', 'Branding'] },
|
|
metadata: { popularity: 8000 },
|
|
}),
|
|
oswald: mockUnifiedFont({
|
|
id: 'oswald',
|
|
name: 'Oswald',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin'],
|
|
variants: ['200', '300', '400', '500', '600', '700'],
|
|
metadata: { popularity: 6 },
|
|
}),
|
|
raleway: mockUnifiedFont({
|
|
id: 'raleway',
|
|
name: 'Raleway',
|
|
provider: 'google',
|
|
category: 'sans-serif',
|
|
subsets: ['latin'],
|
|
variants: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
|
|
metadata: { popularity: 7 },
|
|
}),
|
|
};
|
|
|
|
/**
|
|
* Get an array of all preset UnifiedFonts
|
|
*/
|
|
export function getAllMockFonts(): UnifiedFont[] {
|
|
return Object.values(UNIFIED_FONTS);
|
|
}
|
|
|
|
/**
|
|
* Get fonts by provider
|
|
*/
|
|
export function getFontsByProvider(provider: FontProvider): UnifiedFont[] {
|
|
return getAllMockFonts().filter(font => font.provider === provider);
|
|
}
|
|
|
|
/**
|
|
* Get fonts by category
|
|
*/
|
|
export function getFontsByCategory(category: FontCategory): UnifiedFont[] {
|
|
return getAllMockFonts().filter(font => font.category === category);
|
|
}
|
|
|
|
/**
|
|
* Generate an array of mock fonts with sequential naming
|
|
*/
|
|
export function generateMockFonts(count: number, options?: Omit<MockUnifiedFontOptions, 'id' | 'name'>): UnifiedFont[] {
|
|
return Array.from({ length: count }, (_, i) =>
|
|
mockUnifiedFont({
|
|
...options,
|
|
id: `mock-font-${i + 1}`,
|
|
name: `Mock Font ${i + 1}`,
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Generate an array of mock fonts with different categories
|
|
*/
|
|
export function generateMixedCategoryFonts(countPerCategory: number = 2): UnifiedFont[] {
|
|
const categories: FontCategory[] = ['sans-serif', 'serif', 'display', 'handwriting', 'monospace'];
|
|
const fonts: UnifiedFont[] = [];
|
|
|
|
categories.forEach(category => {
|
|
for (let i = 0; i < countPerCategory; i++) {
|
|
fonts.push(
|
|
mockUnifiedFont({
|
|
id: `${category}-${i + 1}`,
|
|
name: `${category.replace('-', ' ')} ${i + 1}`,
|
|
category,
|
|
}),
|
|
);
|
|
}
|
|
});
|
|
|
|
return fonts;
|
|
}
|