@mentra/sdk 2.1.29-beta.1 → 2.1.30-beta.1
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/dist/app/session/events.d.ts +9 -0
- package/dist/app/session/events.d.ts.map +1 -1
- package/dist/app/session/index.d.ts +8 -2
- package/dist/app/session/index.d.ts.map +1 -1
- package/dist/display-utils/helpers/DisplayHelpers.d.ts +165 -0
- package/dist/display-utils/helpers/DisplayHelpers.d.ts.map +1 -0
- package/dist/display-utils/helpers/ScrollView.d.ts +183 -0
- package/dist/display-utils/helpers/ScrollView.d.ts.map +1 -0
- package/dist/display-utils/helpers/index.d.ts +11 -0
- package/dist/display-utils/helpers/index.d.ts.map +1 -0
- package/dist/display-utils/index.d.ts +108 -0
- package/dist/display-utils/index.d.ts.map +1 -0
- package/dist/display-utils/measurer/TextMeasurer.d.ts +160 -0
- package/dist/display-utils/measurer/TextMeasurer.d.ts.map +1 -0
- package/dist/display-utils/measurer/index.d.ts +10 -0
- package/dist/display-utils/measurer/index.d.ts.map +1 -0
- package/dist/display-utils/measurer/script-detection.d.ts +53 -0
- package/dist/display-utils/measurer/script-detection.d.ts.map +1 -0
- package/dist/display-utils/profiles/g1.d.ts +33 -0
- package/dist/display-utils/profiles/g1.d.ts.map +1 -0
- package/dist/display-utils/profiles/index.d.ts +9 -0
- package/dist/display-utils/profiles/index.d.ts.map +1 -0
- package/dist/display-utils/profiles/types.d.ts +95 -0
- package/dist/display-utils/profiles/types.d.ts.map +1 -0
- package/dist/display-utils/wrapper/TextWrapper.d.ts +94 -0
- package/dist/display-utils/wrapper/TextWrapper.d.ts.map +1 -0
- package/dist/display-utils/wrapper/index.d.ts +12 -0
- package/dist/display-utils/wrapper/index.d.ts.map +1 -0
- package/dist/display-utils/wrapper/types.d.ts +71 -0
- package/dist/display-utils/wrapper/types.d.ts.map +1 -0
- package/dist/display-utils.d.ts +27 -986
- package/dist/display-utils.d.ts.map +1 -1
- package/dist/display-utils.js +9 -9
- package/dist/display-utils.js.map +2 -2
- package/dist/index.js +47 -30
- package/dist/index.js.map +4 -4
- package/package.json +4 -10
package/dist/display-utils.d.ts
CHANGED
|
@@ -1,989 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Display Utils
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Glasses-agnostic, pixel-accurate text measurement and wrapping library
|
|
5
|
+
* for smart glasses displays.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import {
|
|
10
|
+
* TextMeasurer,
|
|
11
|
+
* TextWrapper,
|
|
12
|
+
* DisplayHelpers,
|
|
13
|
+
* ScrollView,
|
|
14
|
+
* G1_PROFILE,
|
|
15
|
+
* createG1Toolkit
|
|
16
|
+
* } from '@mentra/sdk/display-utils'
|
|
17
|
+
*
|
|
18
|
+
* // Quick start
|
|
19
|
+
* const { wrapper } = createG1Toolkit()
|
|
20
|
+
* const result = wrapper.wrap("Your text here")
|
|
21
|
+
*
|
|
22
|
+
* // Scrollable content
|
|
23
|
+
* const scrollView = new ScrollView(measurer, wrapper)
|
|
24
|
+
* scrollView.setContent("Very long text...")
|
|
25
|
+
* scrollView.scrollDown()
|
|
26
|
+
* const viewport = scrollView.getViewport()
|
|
27
|
+
* ```
|
|
6
28
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// Profile Types
|
|
11
|
-
// ============================================================================
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Display profile for a specific glasses model.
|
|
15
|
-
* All text measurement and wrapping derives from this configuration.
|
|
16
|
-
*/
|
|
17
|
-
export interface DisplayProfile {
|
|
18
|
-
/** Unique identifier for this glasses model */
|
|
19
|
-
id: string;
|
|
20
|
-
/** Human-readable name */
|
|
21
|
-
name: string;
|
|
22
|
-
/** Display width in pixels */
|
|
23
|
-
displayWidthPx: number;
|
|
24
|
-
/** Display height in pixels (if applicable) */
|
|
25
|
-
displayHeightPx?: number;
|
|
26
|
-
/** Maximum number of lines that can be displayed */
|
|
27
|
-
maxLines: number;
|
|
28
|
-
/** Maximum safe payload size in bytes (for BLE transmission) */
|
|
29
|
-
maxPayloadBytes: number;
|
|
30
|
-
/** BLE chunk size for transmission */
|
|
31
|
-
bleChunkSize: number;
|
|
32
|
-
/** Font metrics for text measurement */
|
|
33
|
-
fontMetrics: FontMetrics;
|
|
34
|
-
/** Optional constraints */
|
|
35
|
-
constraints?: DisplayConstraints;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Font metrics for pixel-accurate text measurement.
|
|
39
|
-
*/
|
|
40
|
-
export interface FontMetrics {
|
|
41
|
-
/**
|
|
42
|
-
* Map of character to glyph width in pixels.
|
|
43
|
-
* Keys are single characters.
|
|
44
|
-
*/
|
|
45
|
-
glyphWidths: Map<string, number>;
|
|
46
|
-
/** Default glyph width for unmapped characters */
|
|
47
|
-
defaultGlyphWidth: number;
|
|
48
|
-
/**
|
|
49
|
-
* Formula to convert glyph width to rendered pixel width.
|
|
50
|
-
* G1 example: (glyphWidth + 1) * 2
|
|
51
|
-
*/
|
|
52
|
-
renderFormula: (glyphWidth: number) => number;
|
|
53
|
-
/**
|
|
54
|
-
* Uniform-width scripts - verified to render all characters at same width.
|
|
55
|
-
* These are NOT averages - they are the actual uniform width in RENDERED pixels.
|
|
56
|
-
*/
|
|
57
|
-
uniformScripts: UniformScriptWidths;
|
|
58
|
-
/**
|
|
59
|
-
* Fallback configuration for unmapped characters.
|
|
60
|
-
*/
|
|
61
|
-
fallback: FallbackConfig;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Uniform width scripts - these scripts render all characters at the same width.
|
|
65
|
-
* Values are in RENDERED pixels (after applying renderFormula if applicable).
|
|
66
|
-
* Verified through hardware testing.
|
|
67
|
-
*/
|
|
68
|
-
export interface UniformScriptWidths {
|
|
69
|
-
/** Chinese, Japanese Kanji - all chars same width */
|
|
70
|
-
cjk: number;
|
|
71
|
-
/** Japanese Hiragana - all chars same width */
|
|
72
|
-
hiragana: number;
|
|
73
|
-
/** Japanese Katakana - all chars same width */
|
|
74
|
-
katakana: number;
|
|
75
|
-
/** Korean Hangul - all chars same width */
|
|
76
|
-
korean: number;
|
|
77
|
-
/** Russian, etc. - all chars same width */
|
|
78
|
-
cyrillic: number;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Fallback strategy for unmapped characters.
|
|
82
|
-
*/
|
|
83
|
-
export interface FallbackConfig {
|
|
84
|
-
/**
|
|
85
|
-
* Max known Latin width for safe fallback (in rendered pixels).
|
|
86
|
-
* Using max ensures we never overflow (worst case: slight under-utilization).
|
|
87
|
-
*/
|
|
88
|
-
latinMaxWidth: number;
|
|
89
|
-
/** What to do with completely unknown characters */
|
|
90
|
-
unknownBehavior: "useLatinMax" | "throw" | "filter";
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Optional display constraints.
|
|
94
|
-
*/
|
|
95
|
-
export interface DisplayConstraints {
|
|
96
|
-
/** Minimum characters before allowing hyphen break */
|
|
97
|
-
minCharsBeforeHyphen?: number;
|
|
98
|
-
/** Characters that should not appear at start of line (kinsoku) */
|
|
99
|
-
noStartChars?: string[];
|
|
100
|
-
/** Characters that should not appear at end of line (kinsoku) */
|
|
101
|
-
noEndChars?: string[];
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Script type for character classification.
|
|
105
|
-
*/
|
|
106
|
-
export type ScriptType = "latin" | "cjk" | "hiragana" | "katakana" | "korean" | "cyrillic" | "numbers" | "punctuation" | "unsupported";
|
|
107
|
-
|
|
108
|
-
// ============================================================================
|
|
109
|
-
// G1 Profiles
|
|
110
|
-
// ============================================================================
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Even Realities G1 Smart Glasses Display Profile
|
|
114
|
-
*
|
|
115
|
-
* Verified through empirical testing with actual hardware.
|
|
116
|
-
* See: line-width-debug-tool/line-width-spec.md
|
|
117
|
-
*/
|
|
118
|
-
export declare const G1_PROFILE: DisplayProfile;
|
|
119
|
-
/**
|
|
120
|
-
* G1 Profile for LEGACY mobile clients that have their own wrapping logic.
|
|
121
|
-
*
|
|
122
|
-
* Old mobile clients re-wrap text received from the cloud, causing double-wrapping.
|
|
123
|
-
* This profile uses a reduced display width (~522px instead of 576px) so that
|
|
124
|
-
* when the mobile client re-wraps, the result still fits within 5 lines.
|
|
125
|
-
*
|
|
126
|
-
* Use this profile when:
|
|
127
|
-
* - Mobile client version < X.X.X (has old wrapping logic)
|
|
128
|
-
* - You see text getting cut off or exceeding 5 lines
|
|
129
|
-
*
|
|
130
|
-
* Once all clients are updated, this can be deprecated.
|
|
131
|
-
*/
|
|
132
|
-
export declare const G1_PROFILE_LEGACY: DisplayProfile;
|
|
133
|
-
/**
|
|
134
|
-
* Get the hyphen width for G1 in rendered pixels.
|
|
135
|
-
* Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
|
|
136
|
-
*/
|
|
137
|
-
export declare const G1_HYPHEN_WIDTH_PX = 10;
|
|
138
|
-
/**
|
|
139
|
-
* Get the space width for G1 in rendered pixels.
|
|
140
|
-
* Space glyph = 2px → rendered = (2+1)*2 = 6px
|
|
141
|
-
*/
|
|
142
|
-
export declare const G1_SPACE_WIDTH_PX = 6;
|
|
143
|
-
|
|
144
|
-
// ============================================================================
|
|
145
|
-
// Script Detection
|
|
146
|
-
// ============================================================================
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Unicode ranges for script detection.
|
|
150
|
-
* Used to classify characters for proper width measurement.
|
|
151
|
-
*/
|
|
152
|
-
export declare const SCRIPT_RANGES: {
|
|
153
|
-
readonly cjk: readonly [readonly [19968, 40959], readonly [13312, 19903], readonly [131072, 173791], readonly [173824, 177983], readonly [177984, 178207], readonly [63744, 64255]];
|
|
154
|
-
readonly hiragana: readonly [readonly [12352, 12447]];
|
|
155
|
-
readonly katakana: readonly [readonly [12448, 12543], readonly [12784, 12799]];
|
|
156
|
-
readonly korean: readonly [readonly [44032, 55215], readonly [4352, 4607], readonly [12592, 12687], readonly [43360, 43391], readonly [55216, 55295]];
|
|
157
|
-
readonly cyrillic: readonly [readonly [1024, 1279], readonly [1280, 1327]];
|
|
158
|
-
readonly numbers: readonly [readonly [48, 57]];
|
|
159
|
-
readonly punctuation: readonly [readonly [32, 47], readonly [58, 64], readonly [91, 96], readonly [123, 126]];
|
|
160
|
-
readonly arabic: readonly [readonly [1536, 1791]];
|
|
161
|
-
readonly hebrew: readonly [readonly [1424, 1535]];
|
|
162
|
-
readonly thai: readonly [readonly [3584, 3711]];
|
|
163
|
-
readonly emoji: readonly [readonly [128512, 128591], readonly [127744, 128511], readonly [128640, 128767], readonly [127456, 127487], readonly [9728, 9983], readonly [9984, 10175], readonly [65024, 65039], readonly [129280, 129535]];
|
|
164
|
-
};
|
|
165
|
-
/**
|
|
166
|
-
* Detect the script type of a single character.
|
|
167
|
-
*
|
|
168
|
-
* @param char - Single character to classify
|
|
169
|
-
* @returns The script type of the character
|
|
170
|
-
*/
|
|
171
|
-
export declare function detectScript(char: string): ScriptType;
|
|
172
|
-
/**
|
|
173
|
-
* Check if a character is a CJK character (Chinese, Japanese Kanji).
|
|
174
|
-
* CJK characters can break anywhere without needing a hyphen.
|
|
175
|
-
*/
|
|
176
|
-
export declare function isCJKCharacter(char: string): boolean;
|
|
177
|
-
/**
|
|
178
|
-
* Check if a character is Korean Hangul.
|
|
179
|
-
*/
|
|
180
|
-
export declare function isKoreanCharacter(char: string): boolean;
|
|
181
|
-
/**
|
|
182
|
-
* Check if a character is from a uniform-width script.
|
|
183
|
-
* These scripts render all characters at the same width.
|
|
184
|
-
*/
|
|
185
|
-
export declare function isUniformWidthScript(char: string): boolean;
|
|
186
|
-
/**
|
|
187
|
-
* Check if a character is from an unsupported script.
|
|
188
|
-
* These characters may not render correctly on the glasses.
|
|
189
|
-
*/
|
|
190
|
-
export declare function isUnsupportedScript(char: string): boolean;
|
|
191
|
-
/**
|
|
192
|
-
* Check if breaking between two characters requires a hyphen.
|
|
193
|
-
* Returns false for:
|
|
194
|
-
* - Breaking after CJK characters (can break anywhere)
|
|
195
|
-
* - Breaking before or after spaces
|
|
196
|
-
* - Breaking after punctuation
|
|
197
|
-
*/
|
|
198
|
-
export declare function needsHyphenForBreak(charBefore: string, charAfter: string): boolean;
|
|
199
|
-
|
|
200
|
-
// ============================================================================
|
|
201
|
-
// Text Measurer
|
|
202
|
-
// ============================================================================
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Character measurement result with detailed breakdown.
|
|
206
|
-
*/
|
|
207
|
-
export interface CharMeasurement {
|
|
208
|
-
/** The character measured */
|
|
209
|
-
char: string;
|
|
210
|
-
/** Width in rendered pixels */
|
|
211
|
-
widthPx: number;
|
|
212
|
-
/** The script type of the character */
|
|
213
|
-
script: ScriptType;
|
|
214
|
-
/** Whether width came from glyph map (true) or fallback (false) */
|
|
215
|
-
fromGlyphMap: boolean;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Text measurement result with detailed breakdown.
|
|
219
|
-
*/
|
|
220
|
-
export interface TextMeasurement {
|
|
221
|
-
/** The text measured */
|
|
222
|
-
text: string;
|
|
223
|
-
/** Total width in rendered pixels */
|
|
224
|
-
totalWidthPx: number;
|
|
225
|
-
/** Number of characters */
|
|
226
|
-
charCount: number;
|
|
227
|
-
/** Per-character measurements (optional, for debugging) */
|
|
228
|
-
chars?: CharMeasurement[];
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Measures text width in pixels based on a DisplayProfile.
|
|
232
|
-
* All measurements are in actual rendered pixels, not abstract units.
|
|
233
|
-
*
|
|
234
|
-
* Key features:
|
|
235
|
-
* - Pixel-perfect measurement for mapped characters
|
|
236
|
-
* - Uniform-width handling for CJK, Korean, Cyrillic
|
|
237
|
-
* - Safe fallback for unmapped Latin characters
|
|
238
|
-
* - Caching for performance
|
|
239
|
-
*/
|
|
240
|
-
export declare class TextMeasurer {
|
|
241
|
-
private readonly profile;
|
|
242
|
-
private readonly charCache;
|
|
243
|
-
constructor(profile: DisplayProfile);
|
|
244
|
-
/**
|
|
245
|
-
* Pre-compute rendered widths for all known glyphs.
|
|
246
|
-
*/
|
|
247
|
-
private buildCharCache;
|
|
248
|
-
/**
|
|
249
|
-
* Measure the total pixel width of a text string.
|
|
250
|
-
*
|
|
251
|
-
* @param text - The text to measure
|
|
252
|
-
* @returns Width in rendered pixels
|
|
253
|
-
*/
|
|
254
|
-
measureText(text: string): number;
|
|
255
|
-
/**
|
|
256
|
-
* Measure text with detailed breakdown of each character.
|
|
257
|
-
*
|
|
258
|
-
* @param text - The text to measure
|
|
259
|
-
* @returns Detailed measurement result
|
|
260
|
-
*/
|
|
261
|
-
measureTextDetailed(text: string): TextMeasurement;
|
|
262
|
-
/**
|
|
263
|
-
* Measure a single character's pixel width.
|
|
264
|
-
*
|
|
265
|
-
* IMPORTANT: This is PIXEL-PERFECT measurement, not averaging!
|
|
266
|
-
* - Mapped characters: exact width from glyph map
|
|
267
|
-
* - Uniform scripts (CJK, Korean, Cyrillic): verified uniform width
|
|
268
|
-
* - Unmapped Latin: MAX width fallback (safe, never overflow)
|
|
269
|
-
*
|
|
270
|
-
* @param char - Single character to measure
|
|
271
|
-
* @returns Width in rendered pixels
|
|
272
|
-
*/
|
|
273
|
-
measureChar(char: string): number;
|
|
274
|
-
/**
|
|
275
|
-
* Calculate character width (called when not in cache).
|
|
276
|
-
*/
|
|
277
|
-
private calculateCharWidth;
|
|
278
|
-
/**
|
|
279
|
-
* Get the raw glyph width (before render formula).
|
|
280
|
-
* Returns undefined for unmapped characters.
|
|
281
|
-
*
|
|
282
|
-
* @param char - Single character
|
|
283
|
-
* @returns Glyph width in pixels, or undefined if not in glyph map
|
|
284
|
-
*/
|
|
285
|
-
getGlyphWidth(char: string): number | undefined;
|
|
286
|
-
/**
|
|
287
|
-
* Check if text fits within a pixel width.
|
|
288
|
-
*
|
|
289
|
-
* @param text - Text to check
|
|
290
|
-
* @param maxWidthPx - Maximum width in pixels
|
|
291
|
-
* @returns true if text fits
|
|
292
|
-
*/
|
|
293
|
-
fitsInWidth(text: string, maxWidthPx: number): boolean;
|
|
294
|
-
/**
|
|
295
|
-
* Find how many characters fit within a pixel width.
|
|
296
|
-
*
|
|
297
|
-
* @param text - Text to measure
|
|
298
|
-
* @param maxWidthPx - Maximum width in pixels
|
|
299
|
-
* @param startIndex - Starting index (default: 0)
|
|
300
|
-
* @returns Number of characters that fit
|
|
301
|
-
*/
|
|
302
|
-
charsThatFit(text: string, maxWidthPx: number, startIndex?: number): number;
|
|
303
|
-
/**
|
|
304
|
-
* Find the pixel position of a character index in text.
|
|
305
|
-
*
|
|
306
|
-
* @param text - Text to measure
|
|
307
|
-
* @param index - Character index
|
|
308
|
-
* @returns Pixel offset from start of text
|
|
309
|
-
*/
|
|
310
|
-
getPixelOffset(text: string, index: number): number;
|
|
311
|
-
/**
|
|
312
|
-
* Detect the script type of a character.
|
|
313
|
-
*
|
|
314
|
-
* @param char - Single character
|
|
315
|
-
* @returns Script type
|
|
316
|
-
*/
|
|
317
|
-
detectScript(char: string): ScriptType;
|
|
318
|
-
/**
|
|
319
|
-
* Check if a character is from a uniform-width script.
|
|
320
|
-
*
|
|
321
|
-
* @param char - Single character
|
|
322
|
-
* @returns true if character is from CJK, Korean, or Cyrillic
|
|
323
|
-
*/
|
|
324
|
-
isUniformWidth(char: string): boolean;
|
|
325
|
-
/**
|
|
326
|
-
* Get the display profile.
|
|
327
|
-
*/
|
|
328
|
-
getProfile(): DisplayProfile;
|
|
329
|
-
/**
|
|
330
|
-
* Get the display width in pixels.
|
|
331
|
-
*/
|
|
332
|
-
getDisplayWidthPx(): number;
|
|
333
|
-
/**
|
|
334
|
-
* Get the maximum number of lines.
|
|
335
|
-
*/
|
|
336
|
-
getMaxLines(): number;
|
|
337
|
-
/**
|
|
338
|
-
* Get the maximum payload size in bytes.
|
|
339
|
-
*/
|
|
340
|
-
getMaxPayloadBytes(): number;
|
|
341
|
-
/**
|
|
342
|
-
* Calculate the UTF-8 byte size of text.
|
|
343
|
-
*
|
|
344
|
-
* @param text - Text to measure
|
|
345
|
-
* @returns Byte size
|
|
346
|
-
*/
|
|
347
|
-
getByteSize(text: string): number;
|
|
348
|
-
/**
|
|
349
|
-
* Get the width of a hyphen character in rendered pixels.
|
|
350
|
-
*/
|
|
351
|
-
getHyphenWidth(): number;
|
|
352
|
-
/**
|
|
353
|
-
* Get the width of a space character in rendered pixels.
|
|
354
|
-
*/
|
|
355
|
-
getSpaceWidth(): number;
|
|
356
|
-
/**
|
|
357
|
-
* Clear the character cache.
|
|
358
|
-
* Useful if profile metrics change at runtime.
|
|
359
|
-
*/
|
|
360
|
-
clearCache(): void;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// ============================================================================
|
|
364
|
-
// Wrapper Types
|
|
365
|
-
// ============================================================================
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Options for text wrapping.
|
|
369
|
-
*/
|
|
370
|
-
export interface WrapOptions {
|
|
371
|
-
/** Maximum width in pixels (defaults to profile's displayWidthPx) */
|
|
372
|
-
maxWidthPx?: number;
|
|
373
|
-
/** Maximum number of lines (defaults to profile's maxLines) */
|
|
374
|
-
maxLines?: number;
|
|
375
|
-
/** Maximum total bytes (defaults to profile's maxPayloadBytes) */
|
|
376
|
-
maxBytes?: number;
|
|
377
|
-
/**
|
|
378
|
-
* Break mode:
|
|
379
|
-
* - 'character': Break mid-word with hyphen for 100% utilization
|
|
380
|
-
* - 'word': Break at word boundaries, hyphenate only if word > line
|
|
381
|
-
* - 'strict-word': Break at word boundaries only, truncate long words
|
|
382
|
-
*/
|
|
383
|
-
breakMode?: BreakMode;
|
|
384
|
-
/** Character to use for hyphenation (default: '-') */
|
|
385
|
-
hyphenChar?: string;
|
|
386
|
-
/** Minimum characters before allowing hyphen break (default: 3) */
|
|
387
|
-
minCharsBeforeHyphen?: number;
|
|
388
|
-
/** Whether to trim whitespace from line ends (default: true) */
|
|
389
|
-
trimLines?: boolean;
|
|
390
|
-
/** Whether to preserve explicit newlines in input (default: true) */
|
|
391
|
-
preserveNewlines?: boolean;
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Break mode for text wrapping.
|
|
395
|
-
*/
|
|
396
|
-
export type BreakMode = "character" | "word" | "strict-word";
|
|
397
|
-
/**
|
|
398
|
-
* Result of wrapping operation.
|
|
399
|
-
*/
|
|
400
|
-
export interface WrapResult {
|
|
401
|
-
/** Wrapped lines */
|
|
402
|
-
lines: string[];
|
|
403
|
-
/** Whether content was truncated to fit constraints */
|
|
404
|
-
truncated: boolean;
|
|
405
|
-
/** Total pixel width of widest line */
|
|
406
|
-
maxLineWidthPx: number;
|
|
407
|
-
/** Total byte size of all lines */
|
|
408
|
-
totalBytes: number;
|
|
409
|
-
/** Per-line metadata */
|
|
410
|
-
lineMetrics: LineMetrics[];
|
|
411
|
-
/** Original input text */
|
|
412
|
-
originalText: string;
|
|
413
|
-
/** Break mode used */
|
|
414
|
-
breakMode: BreakMode;
|
|
415
|
-
}
|
|
416
|
-
/**
|
|
417
|
-
* Per-line metrics from wrapping.
|
|
418
|
-
*/
|
|
419
|
-
export interface LineMetrics {
|
|
420
|
-
/** The line text */
|
|
421
|
-
text: string;
|
|
422
|
-
/** Width in pixels */
|
|
423
|
-
widthPx: number;
|
|
424
|
-
/** Byte size of this line */
|
|
425
|
-
bytes: number;
|
|
426
|
-
/** Utilization percentage (widthPx / maxWidthPx * 100) */
|
|
427
|
-
utilizationPercent: number;
|
|
428
|
-
/** Whether this line ends with a hyphen from breaking */
|
|
429
|
-
endsWithHyphen: boolean;
|
|
430
|
-
/** Whether this line was created from an explicit newline */
|
|
431
|
-
fromExplicitNewline: boolean;
|
|
432
|
-
}
|
|
433
|
-
/**
|
|
434
|
-
* Default wrap options.
|
|
435
|
-
*/
|
|
436
|
-
export declare const DEFAULT_WRAP_OPTIONS: Required<Omit<WrapOptions, "maxWidthPx" | "maxLines" | "maxBytes">>;
|
|
437
|
-
|
|
438
|
-
// ============================================================================
|
|
439
|
-
// Text Wrapper
|
|
440
|
-
// ============================================================================
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* Wraps text to fit display constraints.
|
|
444
|
-
*
|
|
445
|
-
* Supports multiple break modes:
|
|
446
|
-
* - 'character': Break mid-word with hyphen for 100% line utilization
|
|
447
|
-
* - 'word': Break at word boundaries, hyphenate only if word > line width
|
|
448
|
-
* - 'strict-word': Break at word boundaries only, no hyphenation
|
|
449
|
-
*
|
|
450
|
-
* Key features:
|
|
451
|
-
* - Pixel-accurate wrapping (no abstract units)
|
|
452
|
-
* - Hyphen-aware breaking (accounts for hyphen width)
|
|
453
|
-
* - CJK support (breaks anywhere without hyphen)
|
|
454
|
-
* - Preserves explicit newlines
|
|
455
|
-
* - Respects byte limits for BLE transmission
|
|
456
|
-
*/
|
|
457
|
-
export declare class TextWrapper {
|
|
458
|
-
private readonly measurer;
|
|
459
|
-
private readonly defaultOptions;
|
|
460
|
-
constructor(measurer: TextMeasurer, defaultOptions?: WrapOptions);
|
|
461
|
-
/**
|
|
462
|
-
* Wrap text to fit within constraints.
|
|
463
|
-
*
|
|
464
|
-
* @param text - Text to wrap (may contain \n for explicit breaks)
|
|
465
|
-
* @param options - Override default options
|
|
466
|
-
* @returns Wrap result with lines and metadata
|
|
467
|
-
*/
|
|
468
|
-
wrap(text: string, options?: WrapOptions): WrapResult;
|
|
469
|
-
/**
|
|
470
|
-
* Simple wrap returning just lines (convenience method).
|
|
471
|
-
*
|
|
472
|
-
* @param text - Text to wrap
|
|
473
|
-
* @param options - Override default options
|
|
474
|
-
* @returns Array of wrapped lines
|
|
475
|
-
*/
|
|
476
|
-
wrapToLines(text: string, options?: WrapOptions): string[];
|
|
477
|
-
/**
|
|
478
|
-
* Check if text needs wrapping.
|
|
479
|
-
*
|
|
480
|
-
* @param text - Text to check
|
|
481
|
-
* @param maxWidthPx - Optional width override
|
|
482
|
-
* @returns true if text exceeds single line
|
|
483
|
-
*/
|
|
484
|
-
needsWrap(text: string, maxWidthPx?: number): boolean;
|
|
485
|
-
/**
|
|
486
|
-
* Get current default options.
|
|
487
|
-
*/
|
|
488
|
-
getOptions(): Required<WrapOptions>;
|
|
489
|
-
/**
|
|
490
|
-
* Get the measurer instance.
|
|
491
|
-
*/
|
|
492
|
-
getMeasurer(): TextMeasurer;
|
|
493
|
-
/**
|
|
494
|
-
* Wrap a single paragraph (no newlines) according to break mode.
|
|
495
|
-
*/
|
|
496
|
-
private wrapParagraph;
|
|
497
|
-
/**
|
|
498
|
-
* Character break mode: Break mid-word with hyphen for 100% line utilization.
|
|
499
|
-
*/
|
|
500
|
-
private wrapCharacterMode;
|
|
501
|
-
/**
|
|
502
|
-
* Word break mode: Break at word boundaries, hyphenate only if word > line width.
|
|
503
|
-
*/
|
|
504
|
-
private wrapWordMode;
|
|
505
|
-
/**
|
|
506
|
-
* Strict word break mode: Break at word boundaries only, no hyphenation.
|
|
507
|
-
* Long words will overflow the line.
|
|
508
|
-
*/
|
|
509
|
-
private wrapStrictWordMode;
|
|
510
|
-
/**
|
|
511
|
-
* Split text into words, handling CJK characters specially.
|
|
512
|
-
* CJK characters are treated as individual "words" since they can break anywhere.
|
|
513
|
-
*/
|
|
514
|
-
private splitIntoWords;
|
|
515
|
-
/**
|
|
516
|
-
* Hyphenate a word that's too long to fit on a single line.
|
|
517
|
-
*/
|
|
518
|
-
private hyphenateLongWord;
|
|
519
|
-
/**
|
|
520
|
-
* Back off characters from line end until hyphen fits.
|
|
521
|
-
* Returns null if we back off to a space (natural break point - no hyphen needed).
|
|
522
|
-
*/
|
|
523
|
-
private backoffForHyphen;
|
|
524
|
-
/**
|
|
525
|
-
* Merge user options with defaults.
|
|
526
|
-
*/
|
|
527
|
-
private mergeOptions;
|
|
528
|
-
/**
|
|
529
|
-
* Create an empty result for empty input.
|
|
530
|
-
*/
|
|
531
|
-
private createEmptyResult;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// ============================================================================
|
|
535
|
-
// Display Helpers
|
|
536
|
-
// ============================================================================
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Truncation result with metadata.
|
|
540
|
-
*/
|
|
541
|
-
export interface TruncateResult {
|
|
542
|
-
/** The truncated text */
|
|
543
|
-
text: string;
|
|
544
|
-
/** Whether text was truncated */
|
|
545
|
-
wasTruncated: boolean;
|
|
546
|
-
/** Width in pixels of truncated text */
|
|
547
|
-
widthPx: number;
|
|
548
|
-
/** Original text length */
|
|
549
|
-
originalLength: number;
|
|
550
|
-
/** Truncated text length */
|
|
551
|
-
truncatedLength: number;
|
|
552
|
-
}
|
|
553
|
-
/**
|
|
554
|
-
* Page result for pagination.
|
|
555
|
-
*/
|
|
556
|
-
export interface Page {
|
|
557
|
-
/** Lines on this page */
|
|
558
|
-
lines: string[];
|
|
559
|
-
/** Page number (1-indexed) */
|
|
560
|
-
pageNumber: number;
|
|
561
|
-
/** Total number of pages */
|
|
562
|
-
totalPages: number;
|
|
563
|
-
/** Whether this is the first page */
|
|
564
|
-
isFirst: boolean;
|
|
565
|
-
/** Whether this is the last page */
|
|
566
|
-
isLast: boolean;
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Chunk result for BLE transmission.
|
|
570
|
-
*/
|
|
571
|
-
export interface Chunk {
|
|
572
|
-
/** The chunk text */
|
|
573
|
-
text: string;
|
|
574
|
-
/** Chunk index (0-indexed) */
|
|
575
|
-
index: number;
|
|
576
|
-
/** Total number of chunks */
|
|
577
|
-
totalChunks: number;
|
|
578
|
-
/** Byte size of this chunk */
|
|
579
|
-
bytes: number;
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Optional helper utilities for common display operations.
|
|
583
|
-
* Built on top of TextMeasurer and TextWrapper for convenience.
|
|
584
|
-
*/
|
|
585
|
-
export declare class DisplayHelpers {
|
|
586
|
-
private readonly measurer;
|
|
587
|
-
private readonly wrapper;
|
|
588
|
-
private readonly profile;
|
|
589
|
-
constructor(measurer: TextMeasurer, wrapper: TextWrapper);
|
|
590
|
-
/**
|
|
591
|
-
* Truncate lines array to max count.
|
|
592
|
-
*
|
|
593
|
-
* @param lines - Array of lines
|
|
594
|
-
* @param maxLines - Maximum lines to keep
|
|
595
|
-
* @param fromEnd - If true, keep last N lines; if false, keep first N (default: false)
|
|
596
|
-
* @returns Truncated lines array
|
|
597
|
-
*/
|
|
598
|
-
truncateToLines(lines: string[], maxLines: number, fromEnd?: boolean): string[];
|
|
599
|
-
/**
|
|
600
|
-
* Truncate text to fit within pixel width, adding ellipsis if needed.
|
|
601
|
-
*
|
|
602
|
-
* @param text - Text to truncate
|
|
603
|
-
* @param maxWidthPx - Maximum width in pixels
|
|
604
|
-
* @param ellipsis - Ellipsis string (default: '...')
|
|
605
|
-
* @returns Truncation result
|
|
606
|
-
*/
|
|
607
|
-
truncateWithEllipsis(text: string, maxWidthPx?: number, ellipsis?: string): TruncateResult;
|
|
608
|
-
/**
|
|
609
|
-
* Estimate how many lines text will need without fully wrapping.
|
|
610
|
-
* This is a quick estimate based on average character width.
|
|
611
|
-
*
|
|
612
|
-
* @param text - Text to estimate
|
|
613
|
-
* @param maxWidthPx - Optional width override
|
|
614
|
-
* @returns Estimated line count
|
|
615
|
-
*/
|
|
616
|
-
estimateLineCount(text: string, maxWidthPx?: number): number;
|
|
617
|
-
/**
|
|
618
|
-
* Wrap and truncate text to fit screen in one call.
|
|
619
|
-
*
|
|
620
|
-
* @param text - Text to fit
|
|
621
|
-
* @param options - Wrap options
|
|
622
|
-
* @returns Lines that fit on screen
|
|
623
|
-
*/
|
|
624
|
-
fitToScreen(text: string, options?: WrapOptions): string[];
|
|
625
|
-
/**
|
|
626
|
-
* Wrap text and paginate into screen-sized pages.
|
|
627
|
-
*
|
|
628
|
-
* @param text - Text to paginate
|
|
629
|
-
* @param options - Wrap options (maxLines will be used as page size)
|
|
630
|
-
* @returns Array of pages
|
|
631
|
-
*/
|
|
632
|
-
paginate(text: string, options?: WrapOptions): Page[];
|
|
633
|
-
/**
|
|
634
|
-
* Calculate UTF-8 byte size of text.
|
|
635
|
-
*
|
|
636
|
-
* @param text - Text to measure
|
|
637
|
-
* @returns Byte size
|
|
638
|
-
*/
|
|
639
|
-
calculateByteSize(text: string): number;
|
|
640
|
-
/**
|
|
641
|
-
* Check if text exceeds byte limit.
|
|
642
|
-
*
|
|
643
|
-
* @param text - Text to check
|
|
644
|
-
* @param maxBytes - Optional override (defaults to profile)
|
|
645
|
-
* @returns true if exceeds limit
|
|
646
|
-
*/
|
|
647
|
-
exceedsByteLimit(text: string, maxBytes?: number): boolean;
|
|
648
|
-
/**
|
|
649
|
-
* Split text into BLE-safe chunks.
|
|
650
|
-
* Tries to split at word/line boundaries when possible.
|
|
651
|
-
*
|
|
652
|
-
* @param text - Text to chunk
|
|
653
|
-
* @param chunkSize - Optional override (defaults to profile)
|
|
654
|
-
* @returns Array of chunks
|
|
655
|
-
*/
|
|
656
|
-
splitIntoChunks(text: string, chunkSize?: number): Chunk[];
|
|
657
|
-
/**
|
|
658
|
-
* Calculate line utilization statistics.
|
|
659
|
-
*
|
|
660
|
-
* @param result - Wrap result to analyze
|
|
661
|
-
* @returns Utilization statistics
|
|
662
|
-
*/
|
|
663
|
-
calculateUtilization(result: WrapResult): {
|
|
664
|
-
averageUtilization: number;
|
|
665
|
-
minUtilization: number;
|
|
666
|
-
maxUtilization: number;
|
|
667
|
-
totalWastedPx: number;
|
|
668
|
-
};
|
|
669
|
-
/**
|
|
670
|
-
* Pad lines array to exact count with empty strings.
|
|
671
|
-
*
|
|
672
|
-
* @param lines - Lines to pad
|
|
673
|
-
* @param targetCount - Target number of lines
|
|
674
|
-
* @param padAtEnd - If true, pad at end; if false, pad at start (default: true)
|
|
675
|
-
* @returns Padded lines array
|
|
676
|
-
*/
|
|
677
|
-
padToLineCount(lines: string[], targetCount: number, padAtEnd?: boolean): string[];
|
|
678
|
-
/**
|
|
679
|
-
* Join lines with newlines for display.
|
|
680
|
-
*
|
|
681
|
-
* @param lines - Lines to join
|
|
682
|
-
* @returns Joined string
|
|
683
|
-
*/
|
|
684
|
-
joinLines(lines: string[]): string;
|
|
685
|
-
/**
|
|
686
|
-
* Get the measurer instance.
|
|
687
|
-
*/
|
|
688
|
-
getMeasurer(): TextMeasurer;
|
|
689
|
-
/**
|
|
690
|
-
* Get the wrapper instance.
|
|
691
|
-
*/
|
|
692
|
-
getWrapper(): TextWrapper;
|
|
693
|
-
/**
|
|
694
|
-
* Get the display profile.
|
|
695
|
-
*/
|
|
696
|
-
getProfile(): DisplayProfile;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// ============================================================================
|
|
700
|
-
// Scroll View
|
|
701
|
-
// ============================================================================
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Scroll position information.
|
|
705
|
-
*/
|
|
706
|
-
export interface ScrollPosition {
|
|
707
|
-
/** Current scroll offset (0 = top) */
|
|
708
|
-
offset: number;
|
|
709
|
-
/** Total number of lines in content */
|
|
710
|
-
totalLines: number;
|
|
711
|
-
/** Number of visible lines (viewport size) */
|
|
712
|
-
visibleLines: number;
|
|
713
|
-
/** Maximum scroll offset */
|
|
714
|
-
maxOffset: number;
|
|
715
|
-
/** Whether we're at the top */
|
|
716
|
-
atTop: boolean;
|
|
717
|
-
/** Whether we're at the bottom */
|
|
718
|
-
atBottom: boolean;
|
|
719
|
-
/** Scroll percentage (0-100) */
|
|
720
|
-
scrollPercent: number;
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* Visible content from the scroll view.
|
|
724
|
-
*/
|
|
725
|
-
export interface ScrollViewport {
|
|
726
|
-
/** Lines currently visible */
|
|
727
|
-
lines: string[];
|
|
728
|
-
/** Scroll position info */
|
|
729
|
-
position: ScrollPosition;
|
|
730
|
-
/** Whether content was truncated during wrapping */
|
|
731
|
-
contentTruncated: boolean;
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* ScrollView provides a scrollable viewport into long wrapped text.
|
|
735
|
-
*
|
|
736
|
-
* Unlike pagination (discrete pages), scrolling allows continuous
|
|
737
|
-
* movement through content line by line.
|
|
738
|
-
*
|
|
739
|
-
* @example
|
|
740
|
-
* ```typescript
|
|
741
|
-
* const scrollView = new ScrollView(measurer, wrapper)
|
|
742
|
-
* scrollView.setContent("Very long text that wraps to many lines...")
|
|
743
|
-
*
|
|
744
|
-
* // Get initial view (top)
|
|
745
|
-
* let view = scrollView.getViewport()
|
|
746
|
-
* console.log(view.lines) // First 5 lines
|
|
747
|
-
*
|
|
748
|
-
* // Scroll down
|
|
749
|
-
* scrollView.scrollDown(2) // Move down 2 lines
|
|
750
|
-
* view = scrollView.getViewport()
|
|
751
|
-
*
|
|
752
|
-
* // Scroll to bottom
|
|
753
|
-
* scrollView.scrollToBottom()
|
|
754
|
-
*
|
|
755
|
-
* // Scroll to specific position
|
|
756
|
-
* scrollView.scrollTo(10) // Line 10 at top of viewport
|
|
757
|
-
* ```
|
|
758
|
-
*/
|
|
759
|
-
export declare class ScrollView {
|
|
760
|
-
private readonly measurer;
|
|
761
|
-
private readonly wrapper;
|
|
762
|
-
private readonly profile;
|
|
763
|
-
private readonly viewportSize;
|
|
764
|
-
private allLines;
|
|
765
|
-
private wrapResult;
|
|
766
|
-
private scrollOffset;
|
|
767
|
-
constructor(measurer: TextMeasurer, wrapper: TextWrapper, viewportSize?: number);
|
|
768
|
-
/**
|
|
769
|
-
* Set the content to display in the scroll view.
|
|
770
|
-
* Wraps the text and resets scroll position to top.
|
|
771
|
-
*
|
|
772
|
-
* @param text - Text content to display
|
|
773
|
-
* @param options - Optional wrap options
|
|
774
|
-
*/
|
|
775
|
-
setContent(text: string, options?: Omit<WrapOptions, "maxLines">): void;
|
|
776
|
-
/**
|
|
777
|
-
* Append content to the existing scroll view.
|
|
778
|
-
* Useful for streaming/live content like captions.
|
|
779
|
-
*
|
|
780
|
-
* @param text - Text to append
|
|
781
|
-
* @param options - Optional wrap options
|
|
782
|
-
* @param autoScroll - If true, scroll to show new content (default: true)
|
|
783
|
-
*/
|
|
784
|
-
appendContent(text: string, options?: Omit<WrapOptions, "maxLines">, autoScroll?: boolean): void;
|
|
785
|
-
/**
|
|
786
|
-
* Get the current viewport (visible lines).
|
|
787
|
-
*/
|
|
788
|
-
getViewport(): ScrollViewport;
|
|
789
|
-
/**
|
|
790
|
-
* Get current scroll position information.
|
|
791
|
-
*/
|
|
792
|
-
getPosition(): ScrollPosition;
|
|
793
|
-
/**
|
|
794
|
-
* Scroll to a specific line offset.
|
|
795
|
-
*
|
|
796
|
-
* @param offset - Line offset (0 = top)
|
|
797
|
-
*/
|
|
798
|
-
scrollTo(offset: number): void;
|
|
799
|
-
/**
|
|
800
|
-
* Scroll down by a number of lines.
|
|
801
|
-
*
|
|
802
|
-
* @param lines - Number of lines to scroll (default: 1)
|
|
803
|
-
*/
|
|
804
|
-
scrollDown(lines?: number): void;
|
|
805
|
-
/**
|
|
806
|
-
* Scroll up by a number of lines.
|
|
807
|
-
*
|
|
808
|
-
* @param lines - Number of lines to scroll (default: 1)
|
|
809
|
-
*/
|
|
810
|
-
scrollUp(lines?: number): void;
|
|
811
|
-
/**
|
|
812
|
-
* Scroll down by one viewport (page down).
|
|
813
|
-
*/
|
|
814
|
-
pageDown(): void;
|
|
815
|
-
/**
|
|
816
|
-
* Scroll up by one viewport (page up).
|
|
817
|
-
*/
|
|
818
|
-
pageUp(): void;
|
|
819
|
-
/**
|
|
820
|
-
* Scroll to the top.
|
|
821
|
-
*/
|
|
822
|
-
scrollToTop(): void;
|
|
823
|
-
/**
|
|
824
|
-
* Scroll to the bottom.
|
|
825
|
-
*/
|
|
826
|
-
scrollToBottom(): void;
|
|
827
|
-
/**
|
|
828
|
-
* Scroll to show a specific line in the viewport.
|
|
829
|
-
*
|
|
830
|
-
* @param lineIndex - The line index to show
|
|
831
|
-
* @param position - Where in viewport: 'top', 'center', 'bottom' (default: 'top')
|
|
832
|
-
*/
|
|
833
|
-
scrollToLine(lineIndex: number, position?: "top" | "center" | "bottom"): void;
|
|
834
|
-
/**
|
|
835
|
-
* Scroll by a percentage of total content.
|
|
836
|
-
*
|
|
837
|
-
* @param percent - Percentage (0-100)
|
|
838
|
-
*/
|
|
839
|
-
scrollToPercent(percent: number): void;
|
|
840
|
-
/**
|
|
841
|
-
* Check if currently at the top.
|
|
842
|
-
*/
|
|
843
|
-
isAtTop(): boolean;
|
|
844
|
-
/**
|
|
845
|
-
* Check if currently at the bottom.
|
|
846
|
-
*/
|
|
847
|
-
isAtBottom(): boolean;
|
|
848
|
-
/**
|
|
849
|
-
* Check if content is scrollable (more lines than viewport).
|
|
850
|
-
*/
|
|
851
|
-
isScrollable(): boolean;
|
|
852
|
-
/**
|
|
853
|
-
* Get all lines (not just visible).
|
|
854
|
-
*/
|
|
855
|
-
getAllLines(): string[];
|
|
856
|
-
/**
|
|
857
|
-
* Get total line count.
|
|
858
|
-
*/
|
|
859
|
-
getTotalLines(): number;
|
|
860
|
-
/**
|
|
861
|
-
* Get the viewport size.
|
|
862
|
-
*/
|
|
863
|
-
getViewportSize(): number;
|
|
864
|
-
/**
|
|
865
|
-
* Clear all content and reset scroll position.
|
|
866
|
-
*/
|
|
867
|
-
clear(): void;
|
|
868
|
-
/**
|
|
869
|
-
* Get the measurer instance.
|
|
870
|
-
*/
|
|
871
|
-
getMeasurer(): TextMeasurer;
|
|
872
|
-
/**
|
|
873
|
-
* Get the wrapper instance.
|
|
874
|
-
*/
|
|
875
|
-
getWrapper(): TextWrapper;
|
|
876
|
-
/**
|
|
877
|
-
* Get the display profile.
|
|
878
|
-
*/
|
|
879
|
-
getProfile(): DisplayProfile;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// ============================================================================
|
|
883
|
-
// Factory Functions
|
|
884
|
-
// ============================================================================
|
|
885
|
-
|
|
886
|
-
/**
|
|
887
|
-
* @mentra/display-utils
|
|
888
|
-
*
|
|
889
|
-
* Glasses-agnostic, pixel-accurate text measurement and wrapping library
|
|
890
|
-
* for smart glasses displays.
|
|
891
|
-
*
|
|
892
|
-
* Key features:
|
|
893
|
-
* - Pixel-perfect measurement (no abstract units or averages)
|
|
894
|
-
* - Multiple break modes (character, word, strict-word)
|
|
895
|
-
* - Full script support (Latin, CJK, Korean, Cyrillic)
|
|
896
|
-
* - Configurable display profiles for different glasses hardware
|
|
897
|
-
*
|
|
898
|
-
* @example
|
|
899
|
-
* ```typescript
|
|
900
|
-
* import {
|
|
901
|
-
* TextMeasurer,
|
|
902
|
-
* TextWrapper,
|
|
903
|
-
* DisplayHelpers,
|
|
904
|
-
* G1_PROFILE
|
|
905
|
-
* } from '@mentra/display-utils'
|
|
906
|
-
*
|
|
907
|
-
* // Create measurer and wrapper for G1 glasses
|
|
908
|
-
* const measurer = new TextMeasurer(G1_PROFILE)
|
|
909
|
-
* const wrapper = new TextWrapper(measurer, { breakMode: 'character' })
|
|
910
|
-
* const helpers = new DisplayHelpers(measurer, wrapper)
|
|
911
|
-
*
|
|
912
|
-
* // Wrap text for display
|
|
913
|
-
* const result = wrapper.wrap("Hello, world! This is a long text.")
|
|
914
|
-
* console.log(result.lines)
|
|
915
|
-
* // ["Hello, world! This is a long text th-", "at needs wrapping."]
|
|
916
|
-
* ```
|
|
917
|
-
*/
|
|
918
|
-
export type { DisplayProfile, FontMetrics, UniformScriptWidths, FallbackConfig, DisplayConstraints, ScriptType, } from "./profiles";
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
export type { CharMeasurement, TextMeasurement } from "./measurer";
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
export type { WrapOptions, WrapResult, LineMetrics, BreakMode } from "./wrapper";
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
export type { TruncateResult, Page, Chunk, ScrollPosition, ScrollViewport } from "./helpers";
|
|
928
|
-
|
|
929
|
-
/**
|
|
930
|
-
* Create a complete display toolkit for a given profile.
|
|
931
|
-
*
|
|
932
|
-
* @param profile - Display profile (defaults to G1)
|
|
933
|
-
* @param wrapOptions - Default wrap options
|
|
934
|
-
* @returns Object with measurer, wrapper, and helpers
|
|
935
|
-
*
|
|
936
|
-
* @example
|
|
937
|
-
* ```typescript
|
|
938
|
-
* const { measurer, wrapper, helpers } = createDisplayToolkit()
|
|
939
|
-
* const lines = wrapper.wrapToLines("Hello, world!")
|
|
940
|
-
* ```
|
|
941
|
-
*/
|
|
942
|
-
export declare function createDisplayToolkit(profile?: DisplayProfile, wrapOptions?: WrapOptions): {
|
|
943
|
-
measurer: TextMeasurer;
|
|
944
|
-
wrapper: TextWrapper;
|
|
945
|
-
helpers: DisplayHelpers;
|
|
946
|
-
profile: DisplayProfile;
|
|
947
|
-
};
|
|
948
|
-
/**
|
|
949
|
-
* Create a G1-configured display toolkit with character breaking.
|
|
950
|
-
* This is the recommended setup for captions and similar high-utilization use cases.
|
|
951
|
-
*
|
|
952
|
-
* @returns Object with measurer, wrapper, and helpers configured for G1
|
|
953
|
-
*
|
|
954
|
-
* @example
|
|
955
|
-
* ```typescript
|
|
956
|
-
* const { wrapper } = createG1Toolkit()
|
|
957
|
-
* const result = wrapper.wrap("Your text here")
|
|
958
|
-
* ```
|
|
959
|
-
*/
|
|
960
|
-
export declare function createG1Toolkit(): {
|
|
961
|
-
measurer: TextMeasurer;
|
|
962
|
-
wrapper: TextWrapper;
|
|
963
|
-
helpers: DisplayHelpers;
|
|
964
|
-
profile: DisplayProfile;
|
|
965
|
-
};
|
|
966
|
-
/**
|
|
967
|
-
* Create a G1-configured display toolkit for LEGACY mobile clients.
|
|
968
|
-
*
|
|
969
|
-
* Use this when the mobile client has old wrapping logic that re-wraps
|
|
970
|
-
* text received from the cloud. This profile uses a reduced display width
|
|
971
|
-
* (~522px instead of 576px) to prevent double-wrapping overflow.
|
|
972
|
-
*
|
|
973
|
-
* @returns Object with measurer, wrapper, and helpers configured for legacy G1 clients
|
|
974
|
-
*
|
|
975
|
-
* @example
|
|
976
|
-
* ```typescript
|
|
977
|
-
* // For old mobile clients that double-wrap
|
|
978
|
-
* const { wrapper } = createG1LegacyToolkit()
|
|
979
|
-
* const result = wrapper.wrap("Your text here")
|
|
980
|
-
* // Lines will be shorter to account for mobile re-wrapping
|
|
981
|
-
* ```
|
|
982
|
-
*/
|
|
983
|
-
export declare function createG1LegacyToolkit(): {
|
|
984
|
-
measurer: TextMeasurer;
|
|
985
|
-
wrapper: TextWrapper;
|
|
986
|
-
helpers: DisplayHelpers;
|
|
987
|
-
profile: DisplayProfile;
|
|
988
|
-
};
|
|
989
|
-
}
|
|
29
|
+
export { type DisplayProfile, type FontMetrics, type UniformScriptWidths, type FallbackConfig, type DisplayConstraints, type ScriptType, G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX, TextMeasurer, type CharMeasurement, type TextMeasurement, detectScript, isCJKCharacter, isKoreanCharacter, isUniformWidthScript, isUnsupportedScript, needsHyphenForBreak, SCRIPT_RANGES, TextWrapper, type WrapOptions, type WrapResult, type LineMetrics, type BreakMode, DEFAULT_WRAP_OPTIONS, DisplayHelpers, type TruncateResult, type Page, type Chunk, ScrollView, type ScrollPosition, type ScrollViewport, createDisplayToolkit, createG1Toolkit, createG1LegacyToolkit, } from "./display-utils/index";
|
|
30
|
+
//# sourceMappingURL=display-utils.d.ts.map
|