type-tester-tdf 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/dom.ts","../src/core/fit.ts","../src/core/opentype.ts","../src/core/typeTester.ts","../src/react/index.tsx"],"names":["useRef","useEffect","jsx"],"mappings":"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","file":"react.cjs","sourcesContent":["// Minimal, safe DOM construction helpers. All text is set via textContent and\n// all attributes via setAttribute, so untrusted values can never be interpreted\n// as HTML or script (no innerHTML, no eval).\n\n/** Properties accepted by {@link el}. */\nexport interface ElProps {\n\t/** Space-separated class names. */\n\tclass?: string;\n\t/** Text content (set via textContent — never parsed as HTML). */\n\ttext?: string;\n\t/** Attributes to set via setAttribute. Nullish values are skipped. */\n\tattrs?: Record<string, string | number | boolean | null | undefined>;\n\t/** Child nodes to append. */\n\tchildren?: Node[];\n}\n\n/**\n * Creates an element of the given tag with safe text/attribute/children\n * assignment. Returns the typed element.\n */\nexport function el<K extends keyof HTMLElementTagNameMap>(\n\ttag: K,\n\tprops: ElProps = {},\n): HTMLElementTagNameMap[K] {\n\tconst node = document.createElement(tag);\n\tif (props.class) node.className = props.class;\n\tif (props.text != null) node.textContent = props.text;\n\tif (props.attrs) {\n\t\tfor (const [name, value] of Object.entries(props.attrs)) {\n\t\t\tif (value == null || value === false) continue;\n\t\t\tnode.setAttribute(name, value === true ? \"\" : String(value));\n\t\t}\n\t}\n\tif (props.children) {\n\t\tfor (const child of props.children) node.appendChild(child);\n\t}\n\treturn node;\n}\n\n/** Clamps a number into the inclusive [min, max] range. */\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Parses a numeric attribute/string, returning the fallback when the value is\n * missing or not a finite number. Prevents NaN leaking into the UI.\n */\nexport function toNumber(value: unknown, fallback: number): number {\n\tif (value == null || value === \"\") return fallback;\n\tconst n = typeof value === \"number\" ? value : Number(value);\n\treturn Number.isFinite(n) ? n : fallback;\n}\n","// Auto-fit engine. Replaces the legacy `bigtext` dependency.\n//\n// Sizing is computed by measuring the text once at a reference size in an\n// offscreen mirror, then scaling linearly: glyph advances and em-based\n// letter-spacing both scale linearly with font-size, so\n// fittedSize = referenceSize * containerWidth / measuredWidth\n// is exact and needs a single read + write per fit (no read/write thrashing,\n// no binary-search loop). Re-fitting is driven by ResizeObserver (so it tracks\n// container resizes) and rAF-debounced (so typing does not thrash layout).\n\nimport { clamp } from \"./dom.js\";\n\nconst REFERENCE_SIZE = 100;\n\n/** Font properties copied to the mirror so measurement matches the real text. */\nconst MIRROR_PROPS = [\n\t\"fontFamily\",\n\t\"fontWeight\",\n\t\"fontStyle\",\n\t\"fontStretch\",\n\t\"letterSpacing\",\n\t\"fontFeatureSettings\",\n\t\"fontVariationSettings\",\n\t\"textTransform\",\n] as const;\n\n/** Drives auto-fit sizing for a single text element. */\nexport class Fitter {\n\tprivate readonly target: HTMLElement;\n\tprivate readonly min: number;\n\tprivate readonly max: number;\n\tprivate mirror: HTMLSpanElement | null = null;\n\tprivate observer: ResizeObserver | null = null;\n\tprivate frame = 0;\n\tprivate onFit: ((size: number) => void) | null = null;\n\tprivate destroyed = false;\n\t// Last container width fitted against. Used to ignore ResizeObserver\n\t// notifications caused purely by height changes (a fit grows the line\n\t// height, which would otherwise re-trigger the observer in a loop).\n\tprivate lastWidth = -1;\n\n\t/**\n\t * @param target Element whose text is being fitted.\n\t * @param min Minimum font-size in px.\n\t * @param max Maximum font-size in px.\n\t */\n\tconstructor(target: HTMLElement, min: number, max: number) {\n\t\tthis.target = target;\n\t\tthis.min = min;\n\t\tthis.max = max;\n\t}\n\n\t/**\n\t * Starts observing the target's container and reports the fitted size via\n\t * `onFit` whenever it should change. Re-fits once fonts have loaded.\n\t */\n\tstart(onFit: (size: number) => void): void {\n\t\tthis.onFit = onFit;\n\t\tif (typeof ResizeObserver !== \"undefined\") {\n\t\t\tconst container = this.target.parentElement ?? this.target;\n\t\t\tthis.observer = new ResizeObserver(() => {\n\t\t\t\t// Only re-fit when the available width changes; height-only changes\n\t\t\t\t// are a consequence of fitting and must not feed back.\n\t\t\t\tif (container.clientWidth !== this.lastWidth) this.schedule();\n\t\t\t});\n\t\t\tthis.observer.observe(container);\n\t\t}\n\t\t// Re-fit after web fonts load so we never measure fallback metrics.\n\t\tconst fonts = (document as Document & { fonts?: FontFaceSet }).fonts;\n\t\tif (fonts?.ready) {\n\t\t\tfonts.ready.then(() => this.schedule()).catch(() => {});\n\t\t}\n\t\tthis.schedule();\n\t}\n\n\t/** Requests a fit on the next animation frame, coalescing rapid calls. */\n\tschedule(): void {\n\t\tif (this.destroyed) return;\n\t\tif (typeof requestAnimationFrame === \"undefined\") {\n\t\t\tthis.fit();\n\t\t\treturn;\n\t\t}\n\t\tif (this.frame) return;\n\t\tthis.frame = requestAnimationFrame(() => {\n\t\t\tthis.frame = 0;\n\t\t\tthis.fit();\n\t\t});\n\t}\n\n\t/** Measures the text and reports the fitted size. */\n\tprivate fit(): void {\n\t\tif (this.destroyed || !this.onFit) return;\n\t\tconst container = this.target.parentElement ?? this.target;\n\t\tconst width = container.clientWidth;\n\t\tif (width <= 0) return;\n\n\t\tconst mirror = this.ensureMirror();\n\t\tconst computed = getComputedStyle(this.target);\n\t\tfor (const prop of MIRROR_PROPS) {\n\t\t\tmirror.style[prop] = computed[prop];\n\t\t}\n\t\tmirror.style.fontSize = `${REFERENCE_SIZE}px`;\n\t\tmirror.textContent = this.target.textContent ?? \"\";\n\n\t\tconst measured = mirror.getBoundingClientRect().width;\n\t\tif (measured <= 0) return;\n\n\t\tthis.lastWidth = width;\n\t\tconst size = clamp((REFERENCE_SIZE * width) / measured, this.min, this.max);\n\t\tthis.onFit(Math.round(size * 100) / 100);\n\t}\n\n\t/** Lazily creates the shared offscreen measurement mirror. */\n\tprivate ensureMirror(): HTMLSpanElement {\n\t\tif (this.mirror) return this.mirror;\n\t\tconst mirror = document.createElement(\"span\");\n\t\tmirror.setAttribute(\"aria-hidden\", \"true\");\n\t\tObject.assign(mirror.style, {\n\t\t\tposition: \"absolute\",\n\t\t\tleft: \"-9999px\",\n\t\t\ttop: \"0\",\n\t\t\tvisibility: \"hidden\",\n\t\t\twhiteSpace: \"nowrap\",\n\t\t\tpointerEvents: \"none\",\n\t\t});\n\t\tdocument.body.appendChild(mirror);\n\t\tthis.mirror = mirror;\n\t\treturn mirror;\n\t}\n\n\t/** Stops observing and removes the mirror. */\n\tdestroy(): void {\n\t\tthis.destroyed = true;\n\t\tif (this.frame) cancelAnimationFrame(this.frame);\n\t\tthis.observer?.disconnect();\n\t\tthis.observer = null;\n\t\tthis.mirror?.remove();\n\t\tthis.mirror = null;\n\t\tthis.onFit = null;\n\t}\n}\n","// OpenType feature registry: correct, spec-accurate tags, labels and grouping.\n// Replaces the legacy optValues table which had duplicate/ambiguous labels\n// (\"Contextual\" for both calt and clig, \"Historical\" for both hlig and hist)\n// and a mislabelled `nalt`.\n\n/** A four-character OpenType GSUB/GPOS feature tag. */\nexport type FeatureTag = string;\n\n/** Logical grouping used to organise features in a control UI. */\nexport type FeatureGroup =\n\t| \"Ligatures\"\n\t| \"Letter Case\"\n\t| \"Figures\"\n\t| \"Fractions\"\n\t| \"Alternates\"\n\t| \"Position\"\n\t| \"Stylistic Sets\";\n\n/** Definition of a single OpenType feature exposed by the tester. */\nexport interface FeatureDef {\n\t/** The OpenType feature tag, e.g. \"smcp\". */\n\ttag: FeatureTag;\n\t/** Human-readable, unambiguous label. */\n\tlabel: string;\n\t/** Group the feature belongs to. */\n\tgroup: FeatureGroup;\n}\n\n/**\n * The default, ordered list of supported OpenType features. Labels are unique\n * and follow the Microsoft OpenType feature registry naming.\n */\nexport const FEATURES: readonly FeatureDef[] = [\n\t// Ligatures\n\t{ tag: \"liga\", label: \"Standard Ligatures\", group: \"Ligatures\" },\n\t{ tag: \"dlig\", label: \"Discretionary Ligatures\", group: \"Ligatures\" },\n\t{ tag: \"hlig\", label: \"Historical Ligatures\", group: \"Ligatures\" },\n\t{ tag: \"clig\", label: \"Contextual Ligatures\", group: \"Ligatures\" },\n\n\t// Letter Case\n\t{ tag: \"smcp\", label: \"Small Capitals\", group: \"Letter Case\" },\n\t{ tag: \"c2sc\", label: \"Capitals to Small Capitals\", group: \"Letter Case\" },\n\t{ tag: \"case\", label: \"Case-Sensitive Forms\", group: \"Letter Case\" },\n\t{ tag: \"cpsp\", label: \"Capital Spacing\", group: \"Letter Case\" },\n\n\t// Figures\n\t{ tag: \"lnum\", label: \"Lining Figures\", group: \"Figures\" },\n\t{ tag: \"onum\", label: \"Oldstyle Figures\", group: \"Figures\" },\n\t{ tag: \"pnum\", label: \"Proportional Figures\", group: \"Figures\" },\n\t{ tag: \"tnum\", label: \"Tabular Figures\", group: \"Figures\" },\n\t{ tag: \"zero\", label: \"Slashed Zero\", group: \"Figures\" },\n\t{ tag: \"ordn\", label: \"Ordinals\", group: \"Figures\" },\n\n\t// Fractions\n\t{ tag: \"frac\", label: \"Fractions\", group: \"Fractions\" },\n\t{ tag: \"afrc\", label: \"Alternative Fractions\", group: \"Fractions\" },\n\n\t// Alternates\n\t{ tag: \"swsh\", label: \"Swash\", group: \"Alternates\" },\n\t{ tag: \"calt\", label: \"Contextual Alternates\", group: \"Alternates\" },\n\t{ tag: \"salt\", label: \"Stylistic Alternates\", group: \"Alternates\" },\n\t{ tag: \"hist\", label: \"Historical Forms\", group: \"Alternates\" },\n\t{ tag: \"nalt\", label: \"Alternate Annotation Forms\", group: \"Alternates\" },\n\n\t// Position\n\t{ tag: \"sups\", label: \"Superscript\", group: \"Position\" },\n\t{ tag: \"subs\", label: \"Subscript\", group: \"Position\" },\n\n\t// Stylistic Sets ss01–ss20\n\t...Array.from({ length: 20 }, (_, i): FeatureDef => {\n\t\tconst n = i + 1;\n\t\tconst tag = `ss${String(n).padStart(2, \"0\")}`;\n\t\treturn { tag, label: `Stylistic Set ${n}`, group: \"Stylistic Sets\" };\n\t}),\n];\n\n/** Lookup map from tag to its definition. */\nexport const FEATURE_BY_TAG: ReadonlyMap<FeatureTag, FeatureDef> = new Map(\n\tFEATURES.map((f) => [f.tag, f]),\n);\n\n/** Returns the label for a tag, falling back to the upper-cased tag itself. */\nexport function featureLabel(tag: FeatureTag): string {\n\treturn FEATURE_BY_TAG.get(tag)?.label ?? tag.toUpperCase();\n}\n\n/** True if the tag is a known, supported OpenType feature. */\nexport function isKnownFeature(tag: string): boolean {\n\treturn FEATURE_BY_TAG.has(tag);\n}\n\n/**\n * Builds a CSS `font-feature-settings` value from a set of active tags so that\n * multiple features compose (e.g. small caps + oldstyle figures) instead of\n * each selection overwriting the others. Returns \"normal\" when none are active.\n */\nexport function featureSettings(active: Iterable<FeatureTag>): string {\n\tconst tags = Array.from(active).filter(isKnownFeature);\n\tif (tags.length === 0) return \"normal\";\n\treturn tags.map((tag) => `\"${tag}\" 1`).join(\", \");\n}\n","// Framework-agnostic, dependency-free type tester.\n//\n// Replaces the legacy jQuery/jQuery-UI/bigtext widget. Key differences:\n// - No eval, no innerHTML with user data — DOM is built with createElement and\n// textContent, styles via element.style (no string injection).\n// - Native, accessible controls: <input type=range>, <button aria-pressed>,\n// <select>, and checkbox-based feature toggles with a focus-managed panel.\n// - OpenType features compose (multiple active at once).\n// - Auto-fit via ResizeObserver (tracks container resizes) instead of bigtext.\n// - No global state; each instance owns its DOM, listeners and observers and is\n// fully torn down by destroy().\n\nimport { Fitter } from \"./fit.js\";\nimport { clamp, el, toNumber } from \"./dom.js\";\nimport {\n\tFEATURES,\n\tFEATURE_BY_TAG,\n\ttype FeatureDef,\n\ttype FeatureTag,\n\tfeatureLabel,\n\tfeatureSettings,\n\tisKnownFeature,\n} from \"./opentype.js\";\nimport type {\n\tAlign,\n\tControlsConfig,\n\tRange,\n\tTypeTesterOptions,\n\tTypeTesterState,\n} from \"./types.js\";\n\n/** Default slider ranges, overridable per control. */\nconst DEFAULT_RANGES = {\n\tsize: { min: 8, max: 300, step: 1 },\n\ttracking: { min: -0.1, max: 0.5, step: 0.005 },\n\tweight: { min: 100, max: 900, step: 100 },\n} as const;\n\nconst ALIGNS: readonly Align[] = [\"left\", \"center\", \"right\"];\n\n// Monotonic counter for unique element ids (deterministic, collision-free even\n// for instances created within the same millisecond).\nlet idCounter = 0;\nfunction nextId(): number {\n\treturn ++idCounter;\n}\n\n/** Resolves a boolean|Range control config against a default range. */\nfunction resolveRange(value: boolean | Range | undefined, fallback: Range): Range | null {\n\tif (!value) return null;\n\tif (value === true) return { ...fallback };\n\treturn { min: value.min, max: value.max, step: value.step ?? fallback.step };\n}\n\n/** A type tester instance bound to a host element. */\nexport class TypeTester {\n\tprivate readonly host: HTMLElement;\n\tprivate readonly options: TypeTesterOptions;\n\tprivate readonly controls: ControlsConfig;\n\tprivate readonly state: TypeTesterState;\n\tprivate readonly activeFeatures = new Set<FeatureTag>();\n\tprivate readonly cleanups: Array<() => void> = [];\n\n\tprivate typeEl!: HTMLElement;\n\tprivate textEl!: HTMLElement;\n\tprivate liveEl!: HTMLElement;\n\tprivate sizeOutput: HTMLOutputElement | null = null;\n\tprivate fitter: Fitter | null = null;\n\n\t/**\n\t * @param host Element to render the tester into.\n\t * @param options Configuration; all fields optional.\n\t */\n\tconstructor(host: HTMLElement, options: TypeTesterOptions = {}) {\n\t\tthis.host = host;\n\t\tthis.options = options;\n\t\tthis.controls = options.controls ?? {};\n\n\t\tconst fit = options.size === \"fit\";\n\t\tfor (const tag of options.features ?? []) {\n\t\t\tif (isKnownFeature(tag)) this.activeFeatures.add(tag);\n\t\t}\n\t\tthis.state = {\n\t\t\ttext: options.text ?? \"\",\n\t\t\tsize: fit ? 0 : toNumber(options.size, 80),\n\t\t\tfit,\n\t\t\ttracking: toNumber(options.tracking, 0),\n\t\t\tweight: toNumber(options.weight, 400),\n\t\t\titalic: options.italic ?? false,\n\t\t\talign: options.align ?? \"left\",\n\t\t\twrap: options.wrap ?? true,\n\t\t\tfeatures: Array.from(this.activeFeatures),\n\t\t};\n\n\t\tthis.render();\n\t}\n\n\t/** Returns a snapshot of the current state. */\n\tgetState(): TypeTesterState {\n\t\treturn { ...this.state, features: Array.from(this.activeFeatures) };\n\t}\n\n\t/** Removes all DOM, listeners and observers created by this instance. */\n\tdestroy(): void {\n\t\tthis.fitter?.destroy();\n\t\tthis.fitter = null;\n\t\tfor (const off of this.cleanups.splice(0)) off();\n\t\tthis.host.replaceChildren();\n\t}\n\n\t// ---- rendering -------------------------------------------------------\n\n\tprivate render(): void {\n\t\tthis.host.classList.add(\"tt\");\n\n\t\tthis.textEl = el(\"div\", {\n\t\t\tclass: \"tt__text\",\n\t\t\ttext: this.state.text,\n\t\t\tattrs: {\n\t\t\t\trole: \"textbox\",\n\t\t\t\t\"aria-label\": this.options.ariaLabel ?? \"Sample text\",\n\t\t\t\t\"aria-multiline\": String(this.state.wrap),\n\t\t\t\tcontenteditable: this.options.editable !== false ? \"true\" : null,\n\t\t\t\tspellcheck: \"true\",\n\t\t\t\t\"data-placeholder\": this.options.placeholder ?? \"Type to test…\",\n\t\t\t},\n\t\t});\n\t\tthis.typeEl = el(\"div\", { class: \"tt__type\", children: [this.textEl] });\n\t\tconst stage = el(\"div\", { class: \"tt__stage\", children: [this.typeEl] });\n\n\t\tthis.liveEl = el(\"div\", {\n\t\t\tclass: \"tt__sr-only\",\n\t\t\tattrs: { \"aria-live\": \"polite\", \"aria-atomic\": \"true\" },\n\t\t});\n\n\t\tconst controls = this.buildControls();\n\t\tconst children: Node[] = [stage];\n\t\tif (controls) children.push(controls);\n\t\tchildren.push(this.liveEl);\n\t\tthis.host.replaceChildren(...children);\n\n\t\tif (this.options.editable !== false) this.wireEditable();\n\t\tthis.applyStyles();\n\t\tthis.setupFit();\n\t}\n\n\tprivate buildControls(): HTMLElement | null {\n\t\tconst items: Node[] = [];\n\t\tconst sizeRange = resolveRange(this.controls.size, DEFAULT_RANGES.size);\n\t\tif (sizeRange && !this.state.fit) items.push(this.buildSize(sizeRange));\n\t\tconst trackingRange = resolveRange(this.controls.tracking, DEFAULT_RANGES.tracking);\n\t\tif (trackingRange) items.push(this.buildTracking(trackingRange));\n\t\tconst weightRange = resolveRange(\n\t\t\tthis.controls.weight,\n\t\t\tthis.options.variable?.wght ?? DEFAULT_RANGES.weight,\n\t\t);\n\t\tif (weightRange) items.push(this.buildWeight(weightRange));\n\t\tif (this.controls.italic) items.push(this.buildItalic());\n\t\tif (this.controls.align) items.push(this.buildAlign());\n\t\tif (this.controls.wrap) items.push(this.buildWrap());\n\t\tif (this.controls.features) items.push(this.buildFeatures());\n\n\t\tif (items.length === 0) return null;\n\t\treturn el(\"div\", {\n\t\t\tclass: \"tt__controls\",\n\t\t\tattrs: { role: \"group\", \"aria-label\": \"Typography controls\" },\n\t\t\tchildren: items,\n\t\t});\n\t}\n\n\t// ---- generic control builders (no per-control copy-paste) -------------\n\n\tprivate buildSlider(\n\t\tkey: \"size\" | \"tracking\" | \"weight\",\n\t\tlabel: string,\n\t\trange: Range,\n\t\tvalue: number,\n\t\tunit: string,\n\t\tonInput: (value: number) => void,\n\t): HTMLElement {\n\t\tconst output = el(\"output\", { class: \"tt__value\", text: `${value}${unit}` });\n\t\tconst input = el(\"input\", {\n\t\t\tclass: `tt__slider tt__slider--${key}`,\n\t\t\tattrs: {\n\t\t\t\ttype: \"range\",\n\t\t\t\tmin: range.min,\n\t\t\t\tmax: range.max,\n\t\t\t\tstep: range.step ?? 1,\n\t\t\t\tvalue,\n\t\t\t\t\"aria-label\": label,\n\t\t\t},\n\t\t});\n\t\tconst handler = () => {\n\t\t\tconst v = Number(input.value);\n\t\t\toutput.textContent = `${v}${unit}`;\n\t\t\tonInput(v);\n\t\t\tthis.announce(`${label} ${v}${unit}`);\n\t\t};\n\t\tinput.addEventListener(\"input\", handler);\n\t\tthis.cleanups.push(() => input.removeEventListener(\"input\", handler));\n\t\tif (key === \"size\") this.sizeOutput = output;\n\t\treturn el(\"label\", {\n\t\t\tclass: `tt__control tt__control--${key}`,\n\t\t\tchildren: [el(\"span\", { class: \"tt__label\", text: label }), input, output],\n\t\t});\n\t}\n\n\tprivate buildSize(range: Range): HTMLElement {\n\t\tthis.state.size = clamp(this.state.size, range.min, range.max);\n\t\treturn this.buildSlider(\"size\", \"Size\", range, this.state.size, \"px\", (v) => {\n\t\t\tthis.state.size = v;\n\t\t\tthis.applyStyles();\n\t\t\tthis.emitChange();\n\t\t});\n\t}\n\n\tprivate buildTracking(range: Range): HTMLElement {\n\t\tthis.state.tracking = clamp(this.state.tracking, range.min, range.max);\n\t\treturn this.buildSlider(\n\t\t\t\"tracking\",\n\t\t\t\"Tracking\",\n\t\t\trange,\n\t\t\tthis.state.tracking,\n\t\t\t\"em\",\n\t\t\t(v) => {\n\t\t\t\tthis.state.tracking = v;\n\t\t\t\tthis.applyStyles();\n\t\t\t\tthis.emitChange();\n\t\t\t},\n\t\t);\n\t}\n\n\tprivate buildWeight(range: Range): HTMLElement {\n\t\tthis.state.weight = clamp(this.state.weight, range.min, range.max);\n\t\treturn this.buildSlider(\"weight\", \"Weight\", range, this.state.weight, \"\", (v) => {\n\t\t\tthis.state.weight = v;\n\t\t\tthis.applyStyles();\n\t\t\tthis.emitChange();\n\t\t});\n\t}\n\n\tprivate buildToggle(\n\t\tkey: string,\n\t\tlabel: string,\n\t\tpressed: boolean,\n\t\tonToggle: (pressed: boolean) => void,\n\t): HTMLButtonElement {\n\t\tconst button = el(\"button\", {\n\t\t\tclass: `tt__toggle tt__toggle--${key}`,\n\t\t\ttext: label,\n\t\t\t// aria-pressed is a string-valued ARIA state and must always be present\n\t\t\t// (\"false\"), unlike boolean HTML attributes which are omitted when off.\n\t\t\tattrs: { type: \"button\", \"aria-pressed\": String(pressed) },\n\t\t});\n\t\tconst handler = () => {\n\t\t\tconst next = button.getAttribute(\"aria-pressed\") !== \"true\";\n\t\t\tbutton.setAttribute(\"aria-pressed\", String(next));\n\t\t\tonToggle(next);\n\t\t\tthis.announce(`${label} ${next ? \"on\" : \"off\"}`);\n\t\t};\n\t\tbutton.addEventListener(\"click\", handler);\n\t\tthis.cleanups.push(() => button.removeEventListener(\"click\", handler));\n\t\treturn button;\n\t}\n\n\tprivate buildItalic(): HTMLElement {\n\t\tconst button = this.buildToggle(\"italic\", \"Italic\", this.state.italic, (on) => {\n\t\t\tthis.state.italic = on;\n\t\t\tthis.applyStyles();\n\t\t\tthis.emitChange();\n\t\t});\n\t\treturn el(\"div\", { class: \"tt__control\", children: [button] });\n\t}\n\n\tprivate buildWrap(): HTMLElement {\n\t\tconst button = this.buildToggle(\"wrap\", \"Wrap\", this.state.wrap, (on) => {\n\t\t\tthis.state.wrap = on;\n\t\t\tthis.textEl.setAttribute(\"aria-multiline\", String(on));\n\t\t\tthis.applyStyles();\n\t\t\tthis.emitChange();\n\t\t});\n\t\treturn el(\"div\", { class: \"tt__control\", children: [button] });\n\t}\n\n\tprivate buildAlign(): HTMLElement {\n\t\tconst select = el(\"select\", {\n\t\t\tclass: \"tt__select tt__select--align\",\n\t\t\tattrs: { \"aria-label\": \"Alignment\" },\n\t\t\tchildren: ALIGNS.map((a) =>\n\t\t\t\tel(\"option\", {\n\t\t\t\t\ttext: a.charAt(0).toUpperCase() + a.slice(1),\n\t\t\t\t\tattrs: { value: a, selected: a === this.state.align },\n\t\t\t\t}),\n\t\t\t),\n\t\t});\n\t\tconst handler = () => {\n\t\t\tconst value = select.value as Align;\n\t\t\tif (ALIGNS.includes(value)) {\n\t\t\t\tthis.state.align = value;\n\t\t\t\tthis.applyStyles();\n\t\t\t\tthis.emitChange();\n\t\t\t\tthis.announce(`Alignment ${value}`);\n\t\t\t}\n\t\t};\n\t\tselect.addEventListener(\"change\", handler);\n\t\tthis.cleanups.push(() => select.removeEventListener(\"change\", handler));\n\t\treturn el(\"label\", {\n\t\t\tclass: \"tt__control tt__control--align\",\n\t\t\tchildren: [el(\"span\", { class: \"tt__label\", text: \"Align\" }), select],\n\t\t});\n\t}\n\n\tprivate buildFeatures(): HTMLElement {\n\t\tconst offered: readonly FeatureDef[] = Array.isArray(this.controls.features)\n\t\t\t? this.controls.features\n\t\t\t\t\t.filter(isKnownFeature)\n\t\t\t\t\t// Preserve each feature's real group/label from the registry rather\n\t\t\t\t\t// than flattening everything into \"Alternates\".\n\t\t\t\t\t.map((tag) => FEATURE_BY_TAG.get(tag) ?? { tag, label: featureLabel(tag), group: \"Alternates\" })\n\t\t\t: FEATURES;\n\n\t\tconst panelId = `tt-feat-${nextId()}`;\n\t\tconst toggle = el(\"button\", {\n\t\t\tclass: \"tt__toggle tt__toggle--features\",\n\t\t\ttext: \"Features\",\n\t\t\tattrs: {\n\t\t\t\ttype: \"button\",\n\t\t\t\t\"aria-haspopup\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\"aria-controls\": panelId,\n\t\t\t},\n\t\t});\n\n\t\tconst checks = offered.map((f) => {\n\t\t\tconst input = el(\"input\", {\n\t\t\t\tattrs: { type: \"checkbox\", value: f.tag, checked: this.activeFeatures.has(f.tag) },\n\t\t\t});\n\t\t\tconst onChange = () => this.toggleFeature(f.tag, input.checked);\n\t\t\tinput.addEventListener(\"change\", onChange);\n\t\t\tthis.cleanups.push(() => input.removeEventListener(\"change\", onChange));\n\t\t\treturn el(\"label\", {\n\t\t\t\tclass: \"tt__feature\",\n\t\t\t\tchildren: [input, el(\"span\", { text: f.label })],\n\t\t\t});\n\t\t});\n\n\t\tconst panel = el(\"div\", {\n\t\t\tclass: \"tt__panel\",\n\t\t\tattrs: { id: panelId, role: \"group\", \"aria-label\": \"OpenType features\", hidden: true },\n\t\t\tchildren: checks,\n\t\t});\n\n\t\tconst wrapper = el(\"div\", {\n\t\t\tclass: \"tt__control tt__control--features\",\n\t\t\tchildren: [toggle, panel],\n\t\t});\n\n\t\tconst setOpen = (open: boolean) => {\n\t\t\ttoggle.setAttribute(\"aria-expanded\", String(open));\n\t\t\tpanel.toggleAttribute(\"hidden\", !open);\n\t\t\tif (open) {\n\t\t\t\tconst first = panel.querySelector<HTMLInputElement>(\"input\");\n\t\t\t\tfirst?.focus();\n\t\t\t}\n\t\t};\n\t\tconst onToggleClick = () => setOpen(toggle.getAttribute(\"aria-expanded\") !== \"true\");\n\t\tconst onKeydown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === \"Escape\" && toggle.getAttribute(\"aria-expanded\") === \"true\") {\n\t\t\t\tsetOpen(false);\n\t\t\t\ttoggle.focus();\n\t\t\t}\n\t\t};\n\t\tconst onOutside = (e: MouseEvent) => {\n\t\t\tif (toggle.getAttribute(\"aria-expanded\") !== \"true\") return;\n\t\t\tif (!wrapper.contains(e.target as Node)) setOpen(false);\n\t\t};\n\t\ttoggle.addEventListener(\"click\", onToggleClick);\n\t\t// Escape is handled at the document level so it closes the panel no matter\n\t\t// where focus currently is, then restores focus to the toggle.\n\t\tdocument.addEventListener(\"keydown\", onKeydown);\n\t\tdocument.addEventListener(\"click\", onOutside);\n\t\tthis.cleanups.push(() => {\n\t\t\ttoggle.removeEventListener(\"click\", onToggleClick);\n\t\t\tdocument.removeEventListener(\"keydown\", onKeydown);\n\t\t\tdocument.removeEventListener(\"click\", onOutside);\n\t\t});\n\n\t\treturn wrapper;\n\t}\n\n\tprivate toggleFeature(tag: FeatureTag, on: boolean): void {\n\t\tif (on) this.activeFeatures.add(tag);\n\t\telse this.activeFeatures.delete(tag);\n\t\tthis.state.features = Array.from(this.activeFeatures);\n\t\tthis.applyStyles();\n\t\tthis.emitChange();\n\t\tthis.announce(`${featureLabel(tag)} ${on ? \"on\" : \"off\"}`);\n\t}\n\n\t// ---- behaviour -------------------------------------------------------\n\n\tprivate wireEditable(): void {\n\t\tconst handler = () => {\n\t\t\tthis.state.text = this.textEl.textContent ?? \"\";\n\t\t\tif (this.state.fit) this.fitter?.schedule();\n\t\t\tthis.emitChange();\n\t\t};\n\t\tthis.textEl.addEventListener(\"input\", handler);\n\t\tthis.cleanups.push(() => this.textEl.removeEventListener(\"input\", handler));\n\t}\n\n\tprivate setupFit(): void {\n\t\tif (!this.state.fit) return;\n\t\tconst range = resolveRange(this.controls.size, DEFAULT_RANGES.size) ?? DEFAULT_RANGES.size;\n\t\tthis.fitter = new Fitter(this.textEl, range.min, range.max);\n\t\tthis.fitter.start((size) => {\n\t\t\tthis.state.size = size;\n\t\t\tthis.typeEl.style.fontSize = `${size}px`;\n\t\t\tif (this.sizeOutput) this.sizeOutput.textContent = `${size}px`;\n\t\t});\n\t}\n\n\t/** Applies the full typographic state to the type element via element.style. */\n\tprivate applyStyles(): void {\n\t\tconst s = this.typeEl.style;\n\t\tconst family = this.options.fontFamily\n\t\t\t? `\"${this.options.fontFamily}\"${this.options.fallback ? `, ${this.options.fallback}` : \", sans-serif\"}`\n\t\t\t: (this.options.fallback ?? \"sans-serif\");\n\t\ts.fontFamily = family;\n\t\tif (!this.state.fit) s.fontSize = `${this.state.size}px`;\n\t\ts.letterSpacing = `${this.state.tracking}em`;\n\t\ts.fontStyle = this.state.italic ? \"italic\" : \"normal\";\n\t\ts.textAlign = this.state.align;\n\t\tthis.textEl.style.whiteSpace = this.state.wrap ? \"normal\" : \"nowrap\";\n\n\t\tif (this.options.variable?.wght) {\n\t\t\ts.fontVariationSettings = `\"wght\" ${this.state.weight}`;\n\t\t}\n\t\ts.fontWeight = String(this.state.weight);\n\n\t\tconst settings = featureSettings(this.activeFeatures);\n\t\ts.fontFeatureSettings = settings;\n\t\t// Older Safari needs the prefixed property; modern engines ignore it.\n\t\ts.setProperty(\"-webkit-font-feature-settings\", settings);\n\t}\n\n\tprivate announce(message: string): void {\n\t\tthis.liveEl.textContent = message;\n\t}\n\n\tprivate emitChange(): void {\n\t\tthis.options.onChange?.(this.getState());\n\t}\n}\n","// React wrapper around the framework-agnostic TypeTester core. React is a peer\n// dependency, externalised at build time, so the core stays dependency-free.\n\nimport { useEffect, useRef } from \"react\";\nimport { TypeTester } from \"../core/typeTester.js\";\nimport type { TypeTesterOptions, TypeTesterState } from \"../core/types.js\";\n\n/** Props for {@link TypeTesterComponent}. Mirrors {@link TypeTesterOptions}. */\nexport interface TypeTesterProps extends TypeTesterOptions {\n\t/** Class applied to the host element. */\n\tclassName?: string;\n}\n\n/**\n * Renders a {@link TypeTester} into a host div. The instance is recreated when\n * any structural option changes and is always torn down on unmount.\n */\nexport function TypeTesterComponent(props: TypeTesterProps): JSX.Element {\n\tconst { className, onChange, ...options } = props;\n\tconst hostRef = useRef<HTMLDivElement>(null);\n\t// Keep the latest onChange without forcing a tester rebuild on each render.\n\tconst onChangeRef = useRef<((state: TypeTesterState) => void) | undefined>(onChange);\n\tonChangeRef.current = onChange;\n\n\t// Serialise structural options so the effect only re-runs on real changes.\n\tconst key = JSON.stringify(options);\n\n\tuseEffect(() => {\n\t\tconst host = hostRef.current;\n\t\tif (!host) return;\n\t\tconst instance = new TypeTester(host, {\n\t\t\t...options,\n\t\t\tonChange: (state) => onChangeRef.current?.(state),\n\t\t});\n\t\treturn () => instance.destroy();\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [key]);\n\n\treturn <div ref={hostRef} className={className} />;\n}\n\nexport { TypeTester } from \"../core/typeTester.js\";\nexport type {\n\tAlign,\n\tControlsConfig,\n\tRange,\n\tSize,\n\tTypeTesterOptions,\n\tTypeTesterState,\n\tVariableConfig,\n} from \"../core/types.js\";\nexport type { FeatureTag } from \"../core/opentype.js\";\n"]}
@@ -0,0 +1,15 @@
1
+ import { e as TypeTesterOptions } from './typeTester-CtFcaLf7.cjs';
2
+ export { A as Align, C as ControlsConfig, d as FeatureTag, R as Range, S as Size, T as TypeTester, f as TypeTesterState, V as VariableConfig } from './typeTester-CtFcaLf7.cjs';
3
+
4
+ /** Props for {@link TypeTesterComponent}. Mirrors {@link TypeTesterOptions}. */
5
+ interface TypeTesterProps extends TypeTesterOptions {
6
+ /** Class applied to the host element. */
7
+ className?: string;
8
+ }
9
+ /**
10
+ * Renders a {@link TypeTester} into a host div. The instance is recreated when
11
+ * any structural option changes and is always torn down on unmount.
12
+ */
13
+ declare function TypeTesterComponent(props: TypeTesterProps): JSX.Element;
14
+
15
+ export { TypeTesterComponent, TypeTesterOptions, type TypeTesterProps };
@@ -0,0 +1,15 @@
1
+ import { e as TypeTesterOptions } from './typeTester-CtFcaLf7.js';
2
+ export { A as Align, C as ControlsConfig, d as FeatureTag, R as Range, S as Size, T as TypeTester, f as TypeTesterState, V as VariableConfig } from './typeTester-CtFcaLf7.js';
3
+
4
+ /** Props for {@link TypeTesterComponent}. Mirrors {@link TypeTesterOptions}. */
5
+ interface TypeTesterProps extends TypeTesterOptions {
6
+ /** Class applied to the host element. */
7
+ className?: string;
8
+ }
9
+ /**
10
+ * Renders a {@link TypeTester} into a host div. The instance is recreated when
11
+ * any structural option changes and is always torn down on unmount.
12
+ */
13
+ declare function TypeTesterComponent(props: TypeTesterProps): JSX.Element;
14
+
15
+ export { TypeTesterComponent, TypeTesterOptions, type TypeTesterProps };
package/dist/react.js ADDED
@@ -0,0 +1,26 @@
1
+ import { TypeTester } from './chunk-TSLTIRBT.js';
2
+ export { TypeTester } from './chunk-TSLTIRBT.js';
3
+ import { useRef, useEffect } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function TypeTesterComponent(props) {
7
+ const { className, onChange, ...options } = props;
8
+ const hostRef = useRef(null);
9
+ const onChangeRef = useRef(onChange);
10
+ onChangeRef.current = onChange;
11
+ const key = JSON.stringify(options);
12
+ useEffect(() => {
13
+ const host = hostRef.current;
14
+ if (!host) return;
15
+ const instance = new TypeTester(host, {
16
+ ...options,
17
+ onChange: (state) => onChangeRef.current?.(state)
18
+ });
19
+ return () => instance.destroy();
20
+ }, [key]);
21
+ return /* @__PURE__ */ jsx("div", { ref: hostRef, className });
22
+ }
23
+
24
+ export { TypeTesterComponent };
25
+ //# sourceMappingURL=react.js.map
26
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/index.tsx"],"names":[],"mappings":";;;;;AAiBO,SAAS,oBAAoB,KAAA,EAAqC;AACxE,EAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,GAAG,SAAQ,GAAI,KAAA;AAC5C,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAE3C,EAAA,MAAM,WAAA,GAAc,OAAuD,QAAQ,CAAA;AACnF,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAGtB,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAElC,EAAA,SAAA,CAAU,MAAM;AACf,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,QAAA,GAAW,IAAI,UAAA,CAAW,IAAA,EAAM;AAAA,MACrC,GAAG,OAAA;AAAA,MACH,QAAA,EAAU,CAAC,KAAA,KAAU,WAAA,CAAY,UAAU,KAAK;AAAA,KAChD,CAAA;AACD,IAAA,OAAO,MAAM,SAAS,OAAA,EAAQ;AAAA,EAE/B,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,OAAA,EAAS,SAAA,EAAsB,CAAA;AACjD","file":"react.js","sourcesContent":["// React wrapper around the framework-agnostic TypeTester core. React is a peer\n// dependency, externalised at build time, so the core stays dependency-free.\n\nimport { useEffect, useRef } from \"react\";\nimport { TypeTester } from \"../core/typeTester.js\";\nimport type { TypeTesterOptions, TypeTesterState } from \"../core/types.js\";\n\n/** Props for {@link TypeTesterComponent}. Mirrors {@link TypeTesterOptions}. */\nexport interface TypeTesterProps extends TypeTesterOptions {\n\t/** Class applied to the host element. */\n\tclassName?: string;\n}\n\n/**\n * Renders a {@link TypeTester} into a host div. The instance is recreated when\n * any structural option changes and is always torn down on unmount.\n */\nexport function TypeTesterComponent(props: TypeTesterProps): JSX.Element {\n\tconst { className, onChange, ...options } = props;\n\tconst hostRef = useRef<HTMLDivElement>(null);\n\t// Keep the latest onChange without forcing a tester rebuild on each render.\n\tconst onChangeRef = useRef<((state: TypeTesterState) => void) | undefined>(onChange);\n\tonChangeRef.current = onChange;\n\n\t// Serialise structural options so the effect only re-runs on real changes.\n\tconst key = JSON.stringify(options);\n\n\tuseEffect(() => {\n\t\tconst host = hostRef.current;\n\t\tif (!host) return;\n\t\tconst instance = new TypeTester(host, {\n\t\t\t...options,\n\t\t\tonChange: (state) => onChangeRef.current?.(state),\n\t\t});\n\t\treturn () => instance.destroy();\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [key]);\n\n\treturn <div ref={hostRef} className={className} />;\n}\n\nexport { TypeTester } from \"../core/typeTester.js\";\nexport type {\n\tAlign,\n\tControlsConfig,\n\tRange,\n\tSize,\n\tTypeTesterOptions,\n\tTypeTesterState,\n\tVariableConfig,\n} from \"../core/types.js\";\nexport type { FeatureTag } from \"../core/opentype.js\";\n"]}
@@ -0,0 +1,147 @@
1
+ /* Type Tester TDF — base styles. Import once: `import "type-tester-tdf/styles.css"`.
2
+ All visual styling is optional; the component is functional without it. */
3
+
4
+ .tt {
5
+ --tt-fg: #111;
6
+ --tt-bg: #fff;
7
+ --tt-accent: #2563eb;
8
+ --tt-border: #d4d4d4;
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 0.75rem;
12
+ color: var(--tt-fg);
13
+ background: var(--tt-bg);
14
+ }
15
+
16
+ .tt__stage {
17
+ min-width: 0;
18
+ }
19
+
20
+ .tt__type {
21
+ margin: 0;
22
+ line-height: 1.1;
23
+ }
24
+
25
+ /* Editable sample text. Placeholder is rendered via CSS so it is never real
26
+ content the user must delete and is never read as stale text. */
27
+ .tt__text {
28
+ outline: none;
29
+ min-height: 1em;
30
+ }
31
+
32
+ .tt__text:empty::before {
33
+ content: attr(data-placeholder);
34
+ color: #9ca3af;
35
+ pointer-events: none;
36
+ }
37
+
38
+ .tt__text:focus-visible {
39
+ outline: 2px solid var(--tt-accent);
40
+ outline-offset: 2px;
41
+ }
42
+
43
+ .tt__controls {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ align-items: center;
47
+ gap: 0.75rem 1rem;
48
+ }
49
+
50
+ .tt__control {
51
+ display: inline-flex;
52
+ align-items: center;
53
+ gap: 0.4rem;
54
+ font: 500 0.8125rem/1.2 system-ui, sans-serif;
55
+ }
56
+
57
+ .tt__label {
58
+ color: #6b7280;
59
+ }
60
+
61
+ .tt__value {
62
+ min-width: 3.5ch;
63
+ color: var(--tt-fg);
64
+ font-variant-numeric: tabular-nums;
65
+ }
66
+
67
+ .tt__slider {
68
+ accent-color: var(--tt-accent);
69
+ }
70
+
71
+ .tt__toggle,
72
+ .tt__select {
73
+ font: inherit;
74
+ padding: 0.25rem 0.6rem;
75
+ color: var(--tt-fg);
76
+ background: var(--tt-bg);
77
+ border: 1px solid var(--tt-border);
78
+ border-radius: 0.375rem;
79
+ cursor: pointer;
80
+ }
81
+
82
+ /* Pressed state uses a text-weight + colour change in addition to background,
83
+ so it is not signalled by colour alone. */
84
+ .tt__toggle[aria-pressed="true"] {
85
+ font-weight: 700;
86
+ color: #fff;
87
+ background: var(--tt-accent);
88
+ border-color: var(--tt-accent);
89
+ }
90
+
91
+ .tt__toggle:focus-visible,
92
+ .tt__select:focus-visible,
93
+ .tt__slider:focus-visible {
94
+ outline: 2px solid var(--tt-accent);
95
+ outline-offset: 2px;
96
+ }
97
+
98
+ .tt__control--features {
99
+ position: relative;
100
+ }
101
+
102
+ .tt__panel {
103
+ position: absolute;
104
+ z-index: 10;
105
+ top: calc(100% + 0.25rem);
106
+ left: 0;
107
+ display: grid;
108
+ gap: 0.25rem;
109
+ max-height: 16rem;
110
+ overflow: auto;
111
+ padding: 0.5rem 0.75rem;
112
+ background: var(--tt-bg);
113
+ border: 1px solid var(--tt-border);
114
+ border-radius: 0.5rem;
115
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
116
+ }
117
+
118
+ .tt__panel[hidden] {
119
+ display: none;
120
+ }
121
+
122
+ .tt__feature {
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 0.5rem;
126
+ white-space: nowrap;
127
+ }
128
+
129
+ /* Visually hidden but available to assistive technology (live region). */
130
+ .tt__sr-only {
131
+ position: absolute;
132
+ width: 1px;
133
+ height: 1px;
134
+ margin: -1px;
135
+ padding: 0;
136
+ overflow: hidden;
137
+ clip: rect(0 0 0 0);
138
+ white-space: nowrap;
139
+ border: 0;
140
+ }
141
+
142
+ @media (prefers-reduced-motion: reduce) {
143
+ .tt * {
144
+ transition: none !important;
145
+ animation: none !important;
146
+ }
147
+ }
@@ -0,0 +1,173 @@
1
+ /** A four-character OpenType GSUB/GPOS feature tag. */
2
+ type FeatureTag = string;
3
+ /** Logical grouping used to organise features in a control UI. */
4
+ type FeatureGroup = "Ligatures" | "Letter Case" | "Figures" | "Fractions" | "Alternates" | "Position" | "Stylistic Sets";
5
+ /** Definition of a single OpenType feature exposed by the tester. */
6
+ interface FeatureDef {
7
+ /** The OpenType feature tag, e.g. "smcp". */
8
+ tag: FeatureTag;
9
+ /** Human-readable, unambiguous label. */
10
+ label: string;
11
+ /** Group the feature belongs to. */
12
+ group: FeatureGroup;
13
+ }
14
+ /**
15
+ * The default, ordered list of supported OpenType features. Labels are unique
16
+ * and follow the Microsoft OpenType feature registry naming.
17
+ */
18
+ declare const FEATURES: readonly FeatureDef[];
19
+ /** Lookup map from tag to its definition. */
20
+ declare const FEATURE_BY_TAG: ReadonlyMap<FeatureTag, FeatureDef>;
21
+ /** Returns the label for a tag, falling back to the upper-cased tag itself. */
22
+ declare function featureLabel(tag: FeatureTag): string;
23
+ /** True if the tag is a known, supported OpenType feature. */
24
+ declare function isKnownFeature(tag: string): boolean;
25
+ /**
26
+ * Builds a CSS `font-feature-settings` value from a set of active tags so that
27
+ * multiple features compose (e.g. small caps + oldstyle figures) instead of
28
+ * each selection overwriting the others. Returns "normal" when none are active.
29
+ */
30
+ declare function featureSettings(active: Iterable<FeatureTag>): string;
31
+
32
+ /** Text alignment values supported by the tester. */
33
+ type Align = "left" | "center" | "right";
34
+ /** Size can be a fixed pixel value or "fit" to auto-fit the container width. */
35
+ type Size = number | "fit";
36
+ /** Numeric range with optional step, used to configure slider controls. */
37
+ interface Range {
38
+ /** Minimum value (inclusive). */
39
+ min: number;
40
+ /** Maximum value (inclusive). */
41
+ max: number;
42
+ /** Step granularity. Defaults are control-specific. */
43
+ step?: number;
44
+ }
45
+ /**
46
+ * Which interactive controls to render, and optional range overrides. A boolean
47
+ * toggles a control on/off with default ranges; an object enables it with a
48
+ * custom range.
49
+ */
50
+ interface ControlsConfig {
51
+ /** Font-size slider (px). Default range 8–300. */
52
+ size?: boolean | Range;
53
+ /** Letter-spacing slider (em). Default range -0.1–0.5. */
54
+ tracking?: boolean | Range;
55
+ /** Font-weight slider. Default range 100–900 step 100 (or the variable axis). */
56
+ weight?: boolean | Range;
57
+ /** Italic toggle button. */
58
+ italic?: boolean;
59
+ /** Alignment control. */
60
+ align?: boolean;
61
+ /** Line-wrap toggle button. */
62
+ wrap?: boolean;
63
+ /**
64
+ * OpenType feature controls. `true` exposes the full default feature list;
65
+ * an array restricts the offered features to the given tags.
66
+ */
67
+ features?: boolean | FeatureTag[];
68
+ }
69
+ /** Optional variable-font axis configuration. */
70
+ interface VariableConfig {
71
+ /** `wght` axis range; when set, weight is driven via font-variation-settings. */
72
+ wght?: Range;
73
+ }
74
+ /** Options accepted by {@link TypeTester}. All fields are optional. */
75
+ interface TypeTesterOptions {
76
+ /** Initial sample text. */
77
+ text?: string;
78
+ /** Primary font-family name to test. */
79
+ fontFamily?: string;
80
+ /** Fallback font stack appended after the tested family. */
81
+ fallback?: string;
82
+ /** Initial size in px, or "fit" for auto-fit. */
83
+ size?: Size;
84
+ /** Initial letter-spacing in em. */
85
+ tracking?: number;
86
+ /** Initial font weight. */
87
+ weight?: number;
88
+ /** Initial italic state. */
89
+ italic?: boolean;
90
+ /** Initial alignment. */
91
+ align?: Align;
92
+ /** Whether text wraps (multi-line) or stays on a single line. */
93
+ wrap?: boolean;
94
+ /** Initially active OpenType feature tags. */
95
+ features?: FeatureTag[];
96
+ /** Whether the sample text is user-editable. */
97
+ editable?: boolean;
98
+ /** Placeholder shown when the editable area is empty. */
99
+ placeholder?: string;
100
+ /** Which controls to render. Omit to show none (display-only). */
101
+ controls?: ControlsConfig;
102
+ /** Variable-font axis configuration. */
103
+ variable?: VariableConfig;
104
+ /** Accessible label for the editable region. */
105
+ ariaLabel?: string;
106
+ /** Called whenever the typographic state changes. */
107
+ onChange?: (state: TypeTesterState) => void;
108
+ }
109
+ /** The live typographic state of a tester instance. */
110
+ interface TypeTesterState {
111
+ /** Current text content. */
112
+ text: string;
113
+ /** Resolved size in px (the fitted size when in "fit" mode). */
114
+ size: number;
115
+ /** Whether the tester is auto-fitting. */
116
+ fit: boolean;
117
+ /** Letter-spacing in em. */
118
+ tracking: number;
119
+ /** Font weight. */
120
+ weight: number;
121
+ /** Italic state. */
122
+ italic: boolean;
123
+ /** Alignment. */
124
+ align: Align;
125
+ /** Whether text wraps. */
126
+ wrap: boolean;
127
+ /** Active OpenType feature tags. */
128
+ features: FeatureTag[];
129
+ }
130
+
131
+ /** A type tester instance bound to a host element. */
132
+ declare class TypeTester {
133
+ private readonly host;
134
+ private readonly options;
135
+ private readonly controls;
136
+ private readonly state;
137
+ private readonly activeFeatures;
138
+ private readonly cleanups;
139
+ private typeEl;
140
+ private textEl;
141
+ private liveEl;
142
+ private sizeOutput;
143
+ private fitter;
144
+ /**
145
+ * @param host Element to render the tester into.
146
+ * @param options Configuration; all fields optional.
147
+ */
148
+ constructor(host: HTMLElement, options?: TypeTesterOptions);
149
+ /** Returns a snapshot of the current state. */
150
+ getState(): TypeTesterState;
151
+ /** Removes all DOM, listeners and observers created by this instance. */
152
+ destroy(): void;
153
+ private render;
154
+ private buildControls;
155
+ private buildSlider;
156
+ private buildSize;
157
+ private buildTracking;
158
+ private buildWeight;
159
+ private buildToggle;
160
+ private buildItalic;
161
+ private buildWrap;
162
+ private buildAlign;
163
+ private buildFeatures;
164
+ private toggleFeature;
165
+ private wireEditable;
166
+ private setupFit;
167
+ /** Applies the full typographic state to the type element via element.style. */
168
+ private applyStyles;
169
+ private announce;
170
+ private emitChange;
171
+ }
172
+
173
+ export { type Align as A, type ControlsConfig as C, FEATURES as F, type Range as R, type Size as S, TypeTester as T, type VariableConfig as V, FEATURE_BY_TAG as a, type FeatureDef as b, type FeatureGroup as c, type FeatureTag as d, type TypeTesterOptions as e, type TypeTesterState as f, featureLabel as g, featureSettings as h, isKnownFeature as i };