@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.
Files changed (37) hide show
  1. package/dist/app/session/events.d.ts +9 -0
  2. package/dist/app/session/events.d.ts.map +1 -1
  3. package/dist/app/session/index.d.ts +8 -2
  4. package/dist/app/session/index.d.ts.map +1 -1
  5. package/dist/display-utils/helpers/DisplayHelpers.d.ts +165 -0
  6. package/dist/display-utils/helpers/DisplayHelpers.d.ts.map +1 -0
  7. package/dist/display-utils/helpers/ScrollView.d.ts +183 -0
  8. package/dist/display-utils/helpers/ScrollView.d.ts.map +1 -0
  9. package/dist/display-utils/helpers/index.d.ts +11 -0
  10. package/dist/display-utils/helpers/index.d.ts.map +1 -0
  11. package/dist/display-utils/index.d.ts +108 -0
  12. package/dist/display-utils/index.d.ts.map +1 -0
  13. package/dist/display-utils/measurer/TextMeasurer.d.ts +160 -0
  14. package/dist/display-utils/measurer/TextMeasurer.d.ts.map +1 -0
  15. package/dist/display-utils/measurer/index.d.ts +10 -0
  16. package/dist/display-utils/measurer/index.d.ts.map +1 -0
  17. package/dist/display-utils/measurer/script-detection.d.ts +53 -0
  18. package/dist/display-utils/measurer/script-detection.d.ts.map +1 -0
  19. package/dist/display-utils/profiles/g1.d.ts +33 -0
  20. package/dist/display-utils/profiles/g1.d.ts.map +1 -0
  21. package/dist/display-utils/profiles/index.d.ts +9 -0
  22. package/dist/display-utils/profiles/index.d.ts.map +1 -0
  23. package/dist/display-utils/profiles/types.d.ts +95 -0
  24. package/dist/display-utils/profiles/types.d.ts.map +1 -0
  25. package/dist/display-utils/wrapper/TextWrapper.d.ts +94 -0
  26. package/dist/display-utils/wrapper/TextWrapper.d.ts.map +1 -0
  27. package/dist/display-utils/wrapper/index.d.ts +12 -0
  28. package/dist/display-utils/wrapper/index.d.ts.map +1 -0
  29. package/dist/display-utils/wrapper/types.d.ts +71 -0
  30. package/dist/display-utils/wrapper/types.d.ts.map +1 -0
  31. package/dist/display-utils.d.ts +27 -986
  32. package/dist/display-utils.d.ts.map +1 -1
  33. package/dist/display-utils.js +9 -9
  34. package/dist/display-utils.js.map +2 -2
  35. package/dist/index.js +47 -30
  36. package/dist/index.js.map +4 -4
  37. package/package.json +4 -10
@@ -0,0 +1,160 @@
1
+ import type { DisplayProfile, ScriptType } from "../profiles/types";
2
+ /**
3
+ * Character measurement result with detailed breakdown.
4
+ */
5
+ export interface CharMeasurement {
6
+ /** The character measured */
7
+ char: string;
8
+ /** Width in rendered pixels */
9
+ widthPx: number;
10
+ /** The script type of the character */
11
+ script: ScriptType;
12
+ /** Whether width came from glyph map (true) or fallback (false) */
13
+ fromGlyphMap: boolean;
14
+ }
15
+ /**
16
+ * Text measurement result with detailed breakdown.
17
+ */
18
+ export interface TextMeasurement {
19
+ /** The text measured */
20
+ text: string;
21
+ /** Total width in rendered pixels */
22
+ totalWidthPx: number;
23
+ /** Number of characters */
24
+ charCount: number;
25
+ /** Per-character measurements (optional, for debugging) */
26
+ chars?: CharMeasurement[];
27
+ }
28
+ /**
29
+ * Measures text width in pixels based on a DisplayProfile.
30
+ * All measurements are in actual rendered pixels, not abstract units.
31
+ *
32
+ * Key features:
33
+ * - Pixel-perfect measurement for mapped characters
34
+ * - Uniform-width handling for CJK, Korean, Cyrillic
35
+ * - Safe fallback for unmapped Latin characters
36
+ * - Caching for performance
37
+ */
38
+ export declare class TextMeasurer {
39
+ private readonly profile;
40
+ private readonly charCache;
41
+ constructor(profile: DisplayProfile);
42
+ /**
43
+ * Pre-compute rendered widths for all known glyphs.
44
+ */
45
+ private buildCharCache;
46
+ /**
47
+ * Measure the total pixel width of a text string.
48
+ *
49
+ * @param text - The text to measure
50
+ * @returns Width in rendered pixels
51
+ */
52
+ measureText(text: string): number;
53
+ /**
54
+ * Measure text with detailed breakdown of each character.
55
+ *
56
+ * @param text - The text to measure
57
+ * @returns Detailed measurement result
58
+ */
59
+ measureTextDetailed(text: string): TextMeasurement;
60
+ /**
61
+ * Measure a single character's pixel width.
62
+ *
63
+ * IMPORTANT: This is PIXEL-PERFECT measurement, not averaging!
64
+ * - Mapped characters: exact width from glyph map
65
+ * - Uniform scripts (CJK, Korean, Cyrillic): verified uniform width
66
+ * - Unmapped Latin: MAX width fallback (safe, never overflow)
67
+ *
68
+ * @param char - Single character to measure
69
+ * @returns Width in rendered pixels
70
+ */
71
+ measureChar(char: string): number;
72
+ /**
73
+ * Calculate character width (called when not in cache).
74
+ */
75
+ private calculateCharWidth;
76
+ /**
77
+ * Get the raw glyph width (before render formula).
78
+ * Returns undefined for unmapped characters.
79
+ *
80
+ * @param char - Single character
81
+ * @returns Glyph width in pixels, or undefined if not in glyph map
82
+ */
83
+ getGlyphWidth(char: string): number | undefined;
84
+ /**
85
+ * Check if text fits within a pixel width.
86
+ *
87
+ * @param text - Text to check
88
+ * @param maxWidthPx - Maximum width in pixels
89
+ * @returns true if text fits
90
+ */
91
+ fitsInWidth(text: string, maxWidthPx: number): boolean;
92
+ /**
93
+ * Find how many characters fit within a pixel width.
94
+ *
95
+ * @param text - Text to measure
96
+ * @param maxWidthPx - Maximum width in pixels
97
+ * @param startIndex - Starting index (default: 0)
98
+ * @returns Number of characters that fit
99
+ */
100
+ charsThatFit(text: string, maxWidthPx: number, startIndex?: number): number;
101
+ /**
102
+ * Find the pixel position of a character index in text.
103
+ *
104
+ * @param text - Text to measure
105
+ * @param index - Character index
106
+ * @returns Pixel offset from start of text
107
+ */
108
+ getPixelOffset(text: string, index: number): number;
109
+ /**
110
+ * Detect the script type of a character.
111
+ *
112
+ * @param char - Single character
113
+ * @returns Script type
114
+ */
115
+ detectScript(char: string): ScriptType;
116
+ /**
117
+ * Check if a character is from a uniform-width script.
118
+ *
119
+ * @param char - Single character
120
+ * @returns true if character is from CJK, Korean, or Cyrillic
121
+ */
122
+ isUniformWidth(char: string): boolean;
123
+ /**
124
+ * Get the display profile.
125
+ */
126
+ getProfile(): DisplayProfile;
127
+ /**
128
+ * Get the display width in pixels.
129
+ */
130
+ getDisplayWidthPx(): number;
131
+ /**
132
+ * Get the maximum number of lines.
133
+ */
134
+ getMaxLines(): number;
135
+ /**
136
+ * Get the maximum payload size in bytes.
137
+ */
138
+ getMaxPayloadBytes(): number;
139
+ /**
140
+ * Calculate the UTF-8 byte size of text.
141
+ *
142
+ * @param text - Text to measure
143
+ * @returns Byte size
144
+ */
145
+ getByteSize(text: string): number;
146
+ /**
147
+ * Get the width of a hyphen character in rendered pixels.
148
+ */
149
+ getHyphenWidth(): number;
150
+ /**
151
+ * Get the width of a space character in rendered pixels.
152
+ */
153
+ getSpaceWidth(): number;
154
+ /**
155
+ * Clear the character cache.
156
+ * Useful if profile metrics change at runtime.
157
+ */
158
+ clearCache(): void;
159
+ }
160
+ //# sourceMappingURL=TextMeasurer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextMeasurer.d.ts","sourceRoot":"","sources":["../../../src/display-utils/measurer/TextMeasurer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAGnE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,MAAM,EAAE,UAAU,CAAA;IAClB,mEAAmE;IACnE,YAAY,EAAE,OAAO,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAA;IACpB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;CAC1B;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;gBAE/C,OAAO,EAAE,cAAc;IAMnC;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAYjC;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAoClD;;;;;;;;;;OAUG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAoBjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;;;;;OAMG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAItD;;;;;;;OAOG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAU,GAAG,MAAM;IAyB9E;;;;;;OAMG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAenD;;;;;OAKG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAItC;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIrC;;OAEG;IACH,UAAU,IAAI,cAAc;IAI5B;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAI5B;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;;OAGG;IACH,UAAU,IAAI,IAAI;CAInB"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Text Measurer Module
3
+ *
4
+ * Provides pixel-accurate text measurement based on display profiles.
5
+ * All measurements are in actual rendered pixels, not abstract units.
6
+ */
7
+ export { TextMeasurer } from "./TextMeasurer";
8
+ export type { CharMeasurement, TextMeasurement } from "./TextMeasurer";
9
+ export { detectScript, isCJKCharacter, isKoreanCharacter, isUniformWidthScript, isUnsupportedScript, needsHyphenForBreak, SCRIPT_RANGES, } from "./script-detection";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/display-utils/measurer/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGtE,OAAO,EACL,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,GACd,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,53 @@
1
+ import type { ScriptType } from "../profiles/types";
2
+ /**
3
+ * Unicode ranges for script detection.
4
+ * Used to classify characters for proper width measurement.
5
+ */
6
+ export declare const SCRIPT_RANGES: {
7
+ readonly cjk: readonly [readonly [19968, 40959], readonly [13312, 19903], readonly [131072, 173791], readonly [173824, 177983], readonly [177984, 178207], readonly [63744, 64255]];
8
+ readonly hiragana: readonly [readonly [12352, 12447]];
9
+ readonly katakana: readonly [readonly [12448, 12543], readonly [12784, 12799]];
10
+ readonly korean: readonly [readonly [44032, 55215], readonly [4352, 4607], readonly [12592, 12687], readonly [43360, 43391], readonly [55216, 55295]];
11
+ readonly cyrillic: readonly [readonly [1024, 1279], readonly [1280, 1327]];
12
+ readonly numbers: readonly [readonly [48, 57]];
13
+ readonly punctuation: readonly [readonly [32, 47], readonly [58, 64], readonly [91, 96], readonly [123, 126]];
14
+ readonly arabic: readonly [readonly [1536, 1791]];
15
+ readonly hebrew: readonly [readonly [1424, 1535]];
16
+ readonly thai: readonly [readonly [3584, 3711]];
17
+ 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]];
18
+ };
19
+ /**
20
+ * Detect the script type of a single character.
21
+ *
22
+ * @param char - Single character to classify
23
+ * @returns The script type of the character
24
+ */
25
+ export declare function detectScript(char: string): ScriptType;
26
+ /**
27
+ * Check if a character is a CJK character (Chinese, Japanese Kanji).
28
+ * CJK characters can break anywhere without needing a hyphen.
29
+ */
30
+ export declare function isCJKCharacter(char: string): boolean;
31
+ /**
32
+ * Check if a character is Korean Hangul.
33
+ */
34
+ export declare function isKoreanCharacter(char: string): boolean;
35
+ /**
36
+ * Check if a character is from a uniform-width script.
37
+ * These scripts render all characters at the same width.
38
+ */
39
+ export declare function isUniformWidthScript(char: string): boolean;
40
+ /**
41
+ * Check if a character is from an unsupported script.
42
+ * These characters may not render correctly on the glasses.
43
+ */
44
+ export declare function isUnsupportedScript(char: string): boolean;
45
+ /**
46
+ * Check if breaking between two characters requires a hyphen.
47
+ * Returns false for:
48
+ * - Breaking after CJK characters (can break anywhere)
49
+ * - Breaking before or after spaces
50
+ * - Breaking after punctuation
51
+ */
52
+ export declare function needsHyphenForBreak(charBefore: string, charAfter: string): boolean;
53
+ //# sourceMappingURL=script-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script-detection.d.ts","sourceRoot":"","sources":["../../../src/display-utils/measurer/script-detection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAA;AAEjD;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;CA4DhB,CAAA;AAcV;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CA0DrD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CA6BlF"}
@@ -0,0 +1,33 @@
1
+ import { DisplayProfile } from "./types";
2
+ /**
3
+ * Even Realities G1 Smart Glasses Display Profile
4
+ *
5
+ * Verified through empirical testing with actual hardware.
6
+ * See: line-width-debug-tool/line-width-spec.md
7
+ */
8
+ export declare const G1_PROFILE: DisplayProfile;
9
+ /**
10
+ * G1 Profile for LEGACY mobile clients that have their own wrapping logic.
11
+ *
12
+ * Old mobile clients re-wrap text received from the cloud, causing double-wrapping.
13
+ * This profile uses a reduced display width (~522px instead of 576px) so that
14
+ * when the mobile client re-wraps, the result still fits within 5 lines.
15
+ *
16
+ * Use this profile when:
17
+ * - Mobile client version < X.X.X (has old wrapping logic)
18
+ * - You see text getting cut off or exceeding 5 lines
19
+ *
20
+ * Once all clients are updated, this can be deprecated.
21
+ */
22
+ export declare const G1_PROFILE_LEGACY: DisplayProfile;
23
+ /**
24
+ * Get the hyphen width for G1 in rendered pixels.
25
+ * Hyphen glyph = 4px → rendered = (4+1)*2 = 10px
26
+ */
27
+ export declare const G1_HYPHEN_WIDTH_PX = 10;
28
+ /**
29
+ * Get the space width for G1 in rendered pixels.
30
+ * Space glyph = 2px → rendered = (2+1)*2 = 6px
31
+ */
32
+ export declare const G1_SPACE_WIDTH_PX = 6;
33
+ //# sourceMappingURL=g1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g1.d.ts","sourceRoot":"","sources":["../../../src/display-utils/profiles/g1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAsHtC;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,cAgDxB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAoC/B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Display Profiles
3
+ *
4
+ * Hardware-specific configurations for smart glasses displays.
5
+ * Each profile defines display dimensions, font metrics, and constraints.
6
+ */
7
+ export type { DisplayProfile, FontMetrics, UniformScriptWidths, FallbackConfig, DisplayConstraints, ScriptType, } from "./types";
8
+ export { G1_PROFILE, G1_PROFILE_LEGACY, G1_HYPHEN_WIDTH_PX, G1_SPACE_WIDTH_PX } from "./g1";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/display-utils/profiles/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,UAAU,GACX,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAA"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Display profile for a specific glasses model.
3
+ * All text measurement and wrapping derives from this configuration.
4
+ */
5
+ export interface DisplayProfile {
6
+ /** Unique identifier for this glasses model */
7
+ id: string;
8
+ /** Human-readable name */
9
+ name: string;
10
+ /** Display width in pixels */
11
+ displayWidthPx: number;
12
+ /** Display height in pixels (if applicable) */
13
+ displayHeightPx?: number;
14
+ /** Maximum number of lines that can be displayed */
15
+ maxLines: number;
16
+ /** Maximum safe payload size in bytes (for BLE transmission) */
17
+ maxPayloadBytes: number;
18
+ /** BLE chunk size for transmission */
19
+ bleChunkSize: number;
20
+ /** Font metrics for text measurement */
21
+ fontMetrics: FontMetrics;
22
+ /** Optional constraints */
23
+ constraints?: DisplayConstraints;
24
+ }
25
+ /**
26
+ * Font metrics for pixel-accurate text measurement.
27
+ */
28
+ export interface FontMetrics {
29
+ /**
30
+ * Map of character to glyph width in pixels.
31
+ * Keys are single characters.
32
+ */
33
+ glyphWidths: Map<string, number>;
34
+ /** Default glyph width for unmapped characters */
35
+ defaultGlyphWidth: number;
36
+ /**
37
+ * Formula to convert glyph width to rendered pixel width.
38
+ * G1 example: (glyphWidth + 1) * 2
39
+ */
40
+ renderFormula: (glyphWidth: number) => number;
41
+ /**
42
+ * Uniform-width scripts - verified to render all characters at same width.
43
+ * These are NOT averages - they are the actual uniform width in RENDERED pixels.
44
+ */
45
+ uniformScripts: UniformScriptWidths;
46
+ /**
47
+ * Fallback configuration for unmapped characters.
48
+ */
49
+ fallback: FallbackConfig;
50
+ }
51
+ /**
52
+ * Uniform width scripts - these scripts render all characters at the same width.
53
+ * Values are in RENDERED pixels (after applying renderFormula if applicable).
54
+ * Verified through hardware testing.
55
+ */
56
+ export interface UniformScriptWidths {
57
+ /** Chinese, Japanese Kanji - all chars same width */
58
+ cjk: number;
59
+ /** Japanese Hiragana - all chars same width */
60
+ hiragana: number;
61
+ /** Japanese Katakana - all chars same width */
62
+ katakana: number;
63
+ /** Korean Hangul - all chars same width */
64
+ korean: number;
65
+ /** Russian, etc. - all chars same width */
66
+ cyrillic: number;
67
+ }
68
+ /**
69
+ * Fallback strategy for unmapped characters.
70
+ */
71
+ export interface FallbackConfig {
72
+ /**
73
+ * Max known Latin width for safe fallback (in rendered pixels).
74
+ * Using max ensures we never overflow (worst case: slight under-utilization).
75
+ */
76
+ latinMaxWidth: number;
77
+ /** What to do with completely unknown characters */
78
+ unknownBehavior: "useLatinMax" | "throw" | "filter";
79
+ }
80
+ /**
81
+ * Optional display constraints.
82
+ */
83
+ export interface DisplayConstraints {
84
+ /** Minimum characters before allowing hyphen break */
85
+ minCharsBeforeHyphen?: number;
86
+ /** Characters that should not appear at start of line (kinsoku) */
87
+ noStartChars?: string[];
88
+ /** Characters that should not appear at end of line (kinsoku) */
89
+ noEndChars?: string[];
90
+ }
91
+ /**
92
+ * Script type for character classification.
93
+ */
94
+ export type ScriptType = "latin" | "cjk" | "hiragana" | "katakana" | "korean" | "cyrillic" | "numbers" | "punctuation" | "unsupported";
95
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/display-utils/profiles/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAA;IAEV,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IAEZ,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAA;IAEtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAA;IAEhB,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAA;IAEvB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAA;IAEpB,wCAAwC;IACxC,WAAW,EAAE,WAAW,CAAA;IAExB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,kBAAkB,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,CAAA;IAEzB;;;OAGG;IACH,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAA;IAE7C;;;OAGG;IACH,cAAc,EAAE,mBAAmB,CAAA;IAEnC;;OAEG;IACH,QAAQ,EAAE,cAAc,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAA;IACX,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAA;IAErB,oDAAoD;IACpD,eAAe,EAAE,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAA;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAE7B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IAEvB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,KAAK,GACL,UAAU,GACV,UAAU,GACV,QAAQ,GACR,UAAU,GACV,SAAS,GACT,aAAa,GACb,aAAa,CAAA"}
@@ -0,0 +1,94 @@
1
+ import { TextMeasurer } from "../measurer/TextMeasurer";
2
+ import type { WrapOptions, WrapResult } from "./types";
3
+ /**
4
+ * Wraps text to fit display constraints.
5
+ *
6
+ * Supports multiple break modes:
7
+ * - 'character': Break mid-word with hyphen for 100% line utilization
8
+ * - 'word': Break at word boundaries, hyphenate only if word > line width
9
+ * - 'strict-word': Break at word boundaries only, no hyphenation
10
+ *
11
+ * Key features:
12
+ * - Pixel-accurate wrapping (no abstract units)
13
+ * - Hyphen-aware breaking (accounts for hyphen width)
14
+ * - CJK support (breaks anywhere without hyphen)
15
+ * - Preserves explicit newlines
16
+ * - Respects byte limits for BLE transmission
17
+ */
18
+ export declare class TextWrapper {
19
+ private readonly measurer;
20
+ private readonly defaultOptions;
21
+ constructor(measurer: TextMeasurer, defaultOptions?: WrapOptions);
22
+ /**
23
+ * Wrap text to fit within constraints.
24
+ *
25
+ * @param text - Text to wrap (may contain \n for explicit breaks)
26
+ * @param options - Override default options
27
+ * @returns Wrap result with lines and metadata
28
+ */
29
+ wrap(text: string, options?: WrapOptions): WrapResult;
30
+ /**
31
+ * Simple wrap returning just lines (convenience method).
32
+ *
33
+ * @param text - Text to wrap
34
+ * @param options - Override default options
35
+ * @returns Array of wrapped lines
36
+ */
37
+ wrapToLines(text: string, options?: WrapOptions): string[];
38
+ /**
39
+ * Check if text needs wrapping.
40
+ *
41
+ * @param text - Text to check
42
+ * @param maxWidthPx - Optional width override
43
+ * @returns true if text exceeds single line
44
+ */
45
+ needsWrap(text: string, maxWidthPx?: number): boolean;
46
+ /**
47
+ * Get current default options.
48
+ */
49
+ getOptions(): Required<WrapOptions>;
50
+ /**
51
+ * Get the measurer instance.
52
+ */
53
+ getMeasurer(): TextMeasurer;
54
+ /**
55
+ * Wrap a single paragraph (no newlines) according to break mode.
56
+ */
57
+ private wrapParagraph;
58
+ /**
59
+ * Character break mode: Break mid-word with hyphen for 100% line utilization.
60
+ */
61
+ private wrapCharacterMode;
62
+ /**
63
+ * Word break mode: Break at word boundaries, hyphenate only if word > line width.
64
+ */
65
+ private wrapWordMode;
66
+ /**
67
+ * Strict word break mode: Break at word boundaries only, no hyphenation.
68
+ * Long words will overflow the line.
69
+ */
70
+ private wrapStrictWordMode;
71
+ /**
72
+ * Split text into words, handling CJK characters specially.
73
+ * CJK characters are treated as individual "words" since they can break anywhere.
74
+ */
75
+ private splitIntoWords;
76
+ /**
77
+ * Hyphenate a word that's too long to fit on a single line.
78
+ */
79
+ private hyphenateLongWord;
80
+ /**
81
+ * Back off characters from line end until hyphen fits.
82
+ * Returns null if we back off to a space (natural break point - no hyphen needed).
83
+ */
84
+ private backoffForHyphen;
85
+ /**
86
+ * Merge user options with defaults.
87
+ */
88
+ private mergeOptions;
89
+ /**
90
+ * Create an empty result for empty input.
91
+ */
92
+ private createEmptyResult;
93
+ }
94
+ //# sourceMappingURL=TextWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextWrapper.d.ts","sourceRoot":"","sources":["../../../src/display-utils/wrapper/TextWrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAA;AAErD,OAAO,KAAK,EAAC,WAAW,EAAE,UAAU,EAAyB,MAAM,SAAS,CAAA;AAG5E;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;gBAE1C,QAAQ,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,WAAW;IAahE;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,UAAU;IA2ErD;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE;IAI1D;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO;IAKrD;;OAEG;IACH,UAAU,IAAI,QAAQ,CAAC,WAAW,CAAC;IAInC;;OAEG;IACH,WAAW,IAAI,YAAY;IAI3B;;OAEG;IACH,OAAO,CAAC,aAAa;IA6BrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6DzB;;OAEG;IACH,OAAO,CAAC,YAAY;IA2DpB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA4C1B;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6BtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgDzB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAgCxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAoB1B"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Text Wrapper Module
3
+ *
4
+ * Provides text wrapping with multiple break modes:
5
+ * - 'character': Break mid-word with hyphen for 100% line utilization
6
+ * - 'word': Break at word boundaries, hyphenate only if word > line width
7
+ * - 'strict-word': Break at word boundaries only, no hyphenation
8
+ */
9
+ export { TextWrapper } from "./TextWrapper";
10
+ export type { WrapOptions, WrapResult, LineMetrics, BreakMode } from "./types";
11
+ export { DEFAULT_WRAP_OPTIONS } from "./types";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/display-utils/wrapper/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Options for text wrapping.
3
+ */
4
+ export interface WrapOptions {
5
+ /** Maximum width in pixels (defaults to profile's displayWidthPx) */
6
+ maxWidthPx?: number;
7
+ /** Maximum number of lines (defaults to profile's maxLines) */
8
+ maxLines?: number;
9
+ /** Maximum total bytes (defaults to profile's maxPayloadBytes) */
10
+ maxBytes?: number;
11
+ /**
12
+ * Break mode:
13
+ * - 'character': Break mid-word with hyphen for 100% utilization
14
+ * - 'word': Break at word boundaries, hyphenate only if word > line
15
+ * - 'strict-word': Break at word boundaries only, truncate long words
16
+ */
17
+ breakMode?: BreakMode;
18
+ /** Character to use for hyphenation (default: '-') */
19
+ hyphenChar?: string;
20
+ /** Minimum characters before allowing hyphen break (default: 3) */
21
+ minCharsBeforeHyphen?: number;
22
+ /** Whether to trim whitespace from line ends (default: true) */
23
+ trimLines?: boolean;
24
+ /** Whether to preserve explicit newlines in input (default: true) */
25
+ preserveNewlines?: boolean;
26
+ }
27
+ /**
28
+ * Break mode for text wrapping.
29
+ */
30
+ export type BreakMode = "character" | "word" | "strict-word";
31
+ /**
32
+ * Result of wrapping operation.
33
+ */
34
+ export interface WrapResult {
35
+ /** Wrapped lines */
36
+ lines: string[];
37
+ /** Whether content was truncated to fit constraints */
38
+ truncated: boolean;
39
+ /** Total pixel width of widest line */
40
+ maxLineWidthPx: number;
41
+ /** Total byte size of all lines */
42
+ totalBytes: number;
43
+ /** Per-line metadata */
44
+ lineMetrics: LineMetrics[];
45
+ /** Original input text */
46
+ originalText: string;
47
+ /** Break mode used */
48
+ breakMode: BreakMode;
49
+ }
50
+ /**
51
+ * Per-line metrics from wrapping.
52
+ */
53
+ export interface LineMetrics {
54
+ /** The line text */
55
+ text: string;
56
+ /** Width in pixels */
57
+ widthPx: number;
58
+ /** Byte size of this line */
59
+ bytes: number;
60
+ /** Utilization percentage (widthPx / maxWidthPx * 100) */
61
+ utilizationPercent: number;
62
+ /** Whether this line ends with a hyphen from breaking */
63
+ endsWithHyphen: boolean;
64
+ /** Whether this line was created from an explicit newline */
65
+ fromExplicitNewline: boolean;
66
+ }
67
+ /**
68
+ * Default wrap options.
69
+ */
70
+ export declare const DEFAULT_WRAP_OPTIONS: Required<Omit<WrapOptions, "maxWidthPx" | "maxLines" | "maxBytes">>;
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/display-utils/wrapper/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IAErB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,mEAAmE;IACnE,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAE7B,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAA;AAE5D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,oBAAoB;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;IAEf,uDAAuD;IACvD,SAAS,EAAE,OAAO,CAAA;IAElB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAA;IAEtB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAA;IAElB,wBAAwB;IACxB,WAAW,EAAE,WAAW,EAAE,CAAA;IAE1B,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAA;IAEpB,sBAAsB;IACtB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAA;IAEZ,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAA;IAEf,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IAEb,0DAA0D;IAC1D,kBAAkB,EAAE,MAAM,CAAA;IAE1B,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAA;IAEvB,6DAA6D;IAC7D,mBAAmB,EAAE,OAAO,CAAA;CAC7B;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC,CAMpG,CAAA"}