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.
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # Type Tester TDF
2
+
3
+ [![npm](https://img.shields.io/npm/v/type-tester-tdf.svg)](https://www.npmjs.com/package/type-tester-tdf)
4
+
5
+ An accessible, **dependency-free** type tester for the web. Type a sample, then
6
+ adjust size, tracking, weight, italic, alignment, line-wrap, and **composable
7
+ OpenType features** live. Ships a framework-agnostic vanilla core and an optional
8
+ React component.
9
+
10
+ > **v2 is a ground-up rewrite.** The legacy jQuery + jQuery UI + BigText widget
11
+ > (v1) is preserved at the [`v1.0.0`](https://github.com/quitequinn/TypeTester_TDF/releases/tag/v1.0.0)
12
+ > git tag. v2 has **no runtime
13
+ > dependencies**, builds accessible native controls, escapes all input (no
14
+ > `eval`, no `innerHTML`), composes multiple OpenType features at once, and
15
+ > auto-fits with `ResizeObserver`. See [Migrating from v1](#migrating-from-v1).
16
+
17
+ - [Install](#install)
18
+ - [Vanilla JS](#vanilla-js) · full guide in [docs/vanilla.md](./docs/vanilla.md)
19
+ - [React](#react) · full guide in [docs/react.md](./docs/react.md)
20
+ - [Options](#options)
21
+ - [Controls](#controls)
22
+ - [OpenType features](#opentype-features)
23
+ - [Accessibility](#accessibility)
24
+ - [Migrating from v1](#migrating-from-v1)
25
+ - [Development](#development)
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ npm install type-tester-tdf
31
+ ```
32
+
33
+ Import the stylesheet once (optional — the component works without it):
34
+
35
+ ```js
36
+ import "type-tester-tdf/styles.css";
37
+ ```
38
+
39
+ ## Vanilla JS
40
+
41
+ ### Programmatic
42
+
43
+ ```js
44
+ import { TypeTester } from "type-tester-tdf";
45
+ import "type-tester-tdf/styles.css";
46
+
47
+ const tester = new TypeTester(document.querySelector("#demo"), {
48
+ text: "Typography",
49
+ fontFamily: "Inter",
50
+ size: 96,
51
+ controls: { size: true, tracking: true, weight: true, italic: true, features: true },
52
+ });
53
+
54
+ // later…
55
+ tester.destroy();
56
+ ```
57
+
58
+ ### Declarative (`data-*` auto-init)
59
+
60
+ ```html
61
+ <div
62
+ data-type-tester
63
+ data-font="Inter"
64
+ data-size="96"
65
+ data-text="Typography"
66
+ data-controls="size,tracking,weight,italic,align,features"
67
+ ></div>
68
+
69
+ <script type="module">
70
+ import { autoInit } from "type-tester-tdf";
71
+ import "type-tester-tdf/styles.css";
72
+ autoInit(); // initialises every [data-type-tester] element
73
+ </script>
74
+ ```
75
+
76
+ `autoInit()` is idempotent — already-initialised elements are skipped.
77
+
78
+ ## React
79
+
80
+ ```tsx
81
+ import { TypeTesterComponent } from "type-tester-tdf/react";
82
+ import "type-tester-tdf/styles.css";
83
+
84
+ export function Demo() {
85
+ return (
86
+ <TypeTesterComponent
87
+ text="Typography"
88
+ fontFamily="Inter"
89
+ size={96}
90
+ controls={{ size: true, weight: true, features: true }}
91
+ onChange={(state) => console.log(state)}
92
+ />
93
+ );
94
+ }
95
+ ```
96
+
97
+ React is a **peer dependency** (>=17); the core stays dependency-free.
98
+
99
+ ## Options
100
+
101
+ `new TypeTester(host, options)` / `<TypeTesterComponent {...options} />`:
102
+
103
+ | Option | Type | Default | Description |
104
+ | --- | --- | --- | --- |
105
+ | `text` | `string` | `""` | Initial sample text. |
106
+ | `fontFamily` | `string` | — | Primary family to test. |
107
+ | `fallback` | `string` | `"sans-serif"` | Fallback stack appended after the family. |
108
+ | `size` | `number \| "fit"` | `80` | Px size, or `"fit"` to auto-fit the container. |
109
+ | `tracking` | `number` | `0` | Letter-spacing in em. |
110
+ | `weight` | `number` | `400` | Font weight (or variable `wght` axis). |
111
+ | `italic` | `boolean` | `false` | Italic state. |
112
+ | `align` | `"left" \| "center" \| "right"` | `"left"` | Text alignment. |
113
+ | `wrap` | `boolean` | `true` | Multi-line wrap vs single line. |
114
+ | `features` | `string[]` | `[]` | Initially active OpenType feature tags. |
115
+ | `editable` | `boolean` | `true` | Whether the sample is user-editable. |
116
+ | `placeholder` | `string` | `"Type to test…"` | Empty-state placeholder (CSS, not real text). |
117
+ | `controls` | `ControlsConfig` | `{}` | Which controls to render (see below). |
118
+ | `variable` | `{ wght?: { min, max, step? } }` | — | Drive weight via `font-variation-settings`. |
119
+ | `ariaLabel` | `string` | `"Sample text"` | Accessible name for the editable region. |
120
+ | `onChange` | `(state) => void` | — | Called on every state change. |
121
+
122
+ ## Controls
123
+
124
+ `controls` selects which interactive controls appear. A `true` value uses the
125
+ default range; an object overrides it:
126
+
127
+ ```js
128
+ controls: {
129
+ size: { min: 12, max: 240, step: 1 }, // or `true`
130
+ tracking: true, // em slider
131
+ weight: true, // 100–900, or the variable axis
132
+ italic: true, // aria-pressed toggle button
133
+ align: true, // native <select>
134
+ wrap: true, // single-line toggle
135
+ features: true, // full OpenType list (or string[] subset)
136
+ }
137
+ ```
138
+
139
+ Default ranges: size `8–300px`, tracking `-0.1–0.5em`, weight `100–900` step 100.
140
+
141
+ ## OpenType features
142
+
143
+ Unlike v1 (one feature at a time), **features compose**: selecting Small Caps
144
+ and Oldstyle Figures yields `font-feature-settings: "smcp" 1, "onum" 1`.
145
+
146
+ ```js
147
+ import { FEATURES, featureSettings } from "type-tester-tdf";
148
+
149
+ featureSettings(["smcp", "onum"]); // => '"smcp" 1, "onum" 1'
150
+ ```
151
+
152
+ Supported tags include ligatures (`liga`, `dlig`, `hlig`, `clig`), case (`smcp`,
153
+ `c2sc`, `case`, `cpsp`), figures (`lnum`, `onum`, `pnum`, `tnum`, `zero`, `ordn`),
154
+ fractions (`frac`, `afrc`), alternates (`swsh`, `calt`, `salt`, `hist`, `nalt`),
155
+ position (`sups`, `subs`), and stylistic sets `ss01`–`ss20`. Restrict the offered
156
+ set with `controls: { features: ["smcp", "onum", "ss01"] }`.
157
+
158
+ ## Accessibility
159
+
160
+ - Native `<input type="range">`, `<button aria-pressed>`, `<select>`, and
161
+ checkbox feature toggles — full keyboard support out of the box.
162
+ - Editable region is a labelled `role="textbox"` with `aria-multiline`; the
163
+ placeholder is CSS-only, so screen readers never read stale text.
164
+ - The features panel manages focus, closes on `Escape` / outside click, and
165
+ exposes `aria-expanded` / `aria-haspopup`.
166
+ - State changes are announced via a polite live region.
167
+ - Toggle states use weight + colour (not colour alone); animations respect
168
+ `prefers-reduced-motion`.
169
+
170
+ ## Migrating from v1
171
+
172
+ | v1 (jQuery attributes) | v2 |
173
+ | --- | --- |
174
+ | `class="typeTester"` | `data-type-tester` (or `new TypeTester(el, …)`) |
175
+ | `font="Inter"` | `data-font="Inter"` / `fontFamily: "Inter"` |
176
+ | `size="90"` / `size=""` (fit) | `data-size="90"` / `data-size="fit"` |
177
+ | `weightoptions="true"` | `data-controls="weight"` / `controls: { weight: true }` |
178
+ | `optoptions="dlig,hlig"` | `data-features` / `controls: { features: [...] }` |
179
+ | magic words `"yup"`, `"nope"` | plain booleans / `"true"` / `"false"` |
180
+ | jQuery + jQuery UI + BigText | **no dependencies** |
181
+
182
+ The v1 source remains available at the [`v1.0.0`](https://github.com/quitequinn/TypeTester_TDF/releases/tag/v1.0.0) git tag.
183
+
184
+ ## Development
185
+
186
+ ```bash
187
+ npm install
188
+ npm run build # bundle ESM + CJS + types (tsup)
189
+ npm test # vitest + jsdom
190
+ npm run typecheck # tsc --noEmit
191
+ npm run dev # watch build
192
+ ```
193
+
194
+ ## License
195
+
196
+ ISC © Quinn Keaveney. Originally built for [The Designers Foundry](https://www.thedesignersfoundry.com/).