diff --git a/src/display/data-schema/data.d.ts b/src/display/data-schema/data.d.ts index 7a2ca728..baf502c5 100644 --- a/src/display/data-schema/data.d.ts +++ b/src/display/data-schema/data.d.ts @@ -457,19 +457,50 @@ export type RelationsStyle = Record; /** * Defines the text style for a Text component. - * You can pass an object similar to PIXI.TextStyle options. + * You can pass an object with properties similar to PIXI.TextStyleOptions, + * along with custom properties for this library. * * @see {@link https://pixijs.download/release/docs/text.TextStyleOptions.html} * * @example - * const textStyleExample: TextStyle = { - * fontFamily: 'Arial', - * fontSize: 24, - * fill: 'white', - * stroke: { color: 'black', width: 2 } + * // Fixed font size + * const fixedSizeStyle: TextStyle = { fontSize: 24, fill: 'red' }; + * + * @example + * // Font size as a string (delegated to PixiJS) + * const stringSizeStyle: TextStyle = { fontSize: '2px', fill: '#00FF00' }; + * + * @example + * // Auto font size with custom range + * const autoSizeStyle: TextStyle = { + * fontSize: 'auto', + * autoFont: { min: 10, max: 50 }, + * fill: 'blue' * }; */ -export type TextStyle = Record; +export interface TextStyle { + /** + * The font size. Can be a number (in pixels), a string parsable by PixiJS (e.g., '16px'), + * or the keyword 'auto' to enable dynamic sizing based on the `autoFont` options. + */ + fontSize?: number | 'auto' | string; + + /** + * Configuration for the 'auto' font size mode. + * This is only active when `fontSize` is 'auto'. + */ + autoFont?: { + min?: number; + max?: number; + }; + + /** + * Allows any other properties, similar to PIXI.TextStyleOptions. + * This provides flexibility for standard text styling. + * e.g., fill, fontFamily, fontWeight, etc. + */ + [key: string]: unknown; +} /** * Defines a tint color to be applied to a component. diff --git a/src/display/data-schema/primitive-schema.js b/src/display/data-schema/primitive-schema.js index 81cfb39c..cf1b971b 100644 --- a/src/display/data-schema/primitive-schema.js +++ b/src/display/data-schema/primitive-schema.js @@ -186,10 +186,24 @@ export const TextureStyle = z */ export const RelationsStyle = z.record(z.string(), z.unknown()); +export const DEFAULT_AUTO_FONT_RANGE = { min: 1, max: 100 }; /** * @see {@link https://pixijs.download/release/docs/text.TextStyleOptions.html} */ -export const TextStyle = z.record(z.string(), z.unknown()); +export const TextStyle = z + .object({ + fontSize: z.union([z.number(), z.literal('auto'), z.string()]).optional(), + autoFont: z + .object({ + min: z.number().positive().default(DEFAULT_AUTO_FONT_RANGE.min), + max: z.number().positive().default(DEFAULT_AUTO_FONT_RANGE.max), + }) + .refine((data) => data.min <= data.max, { + message: 'autoFont.min must not be greater than autoFont.max', + }) + .optional(), + }) + .passthrough(); /** * @see {@link https://pixijs.download/release/docs/color.ColorSource.html} diff --git a/src/display/mixins/Textstyleable.js b/src/display/mixins/Textstyleable.js index d47bac0f..c3db5ce8 100644 --- a/src/display/mixins/Textstyleable.js +++ b/src/display/mixins/Textstyleable.js @@ -1,4 +1,5 @@ import { getColor } from '../../utils/get'; +import { DEFAULT_AUTO_FONT_RANGE } from '../data-schema/primitive-schema'; import { FONT_WEIGHT, UPDATE_STAGES } from './constants'; const KEYS = ['text', 'split', 'style', 'margin']; @@ -15,7 +16,8 @@ export const Textstyleable = (superClass) => { } else if (key === 'fill') { this.style[key] = getColor(theme, style.fill); } else if (key === 'fontSize' && style[key] === 'auto') { - setAutoFontSize(this, margin); + const range = style.autoFont ?? DEFAULT_AUTO_FONT_RANGE; + setAutoFontSize(this, margin, range); } else { this.style[key] = style[key]; } @@ -30,7 +32,7 @@ export const Textstyleable = (superClass) => { return MixedClass; }; -const setAutoFontSize = (object, margin) => { +const setAutoFontSize = (object, margin, range) => { object.visible = false; const { width, height } = object.parent.props.size; const parentSize = { @@ -39,9 +41,7 @@ const setAutoFontSize = (object, margin) => { }; object.visible = true; - let minSize = 1; - let maxSize = 100; - + let { min: minSize, max: maxSize } = range; while (minSize <= maxSize) { const fontSize = Math.floor((minSize + maxSize) / 2); object.style.fontSize = fontSize;