react-native-laminar 1.1.0 → 1.4.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 (151) hide show
  1. package/README.md +47 -3
  2. package/lib/commonjs/hooks/use-display-units.js +1 -0
  3. package/lib/commonjs/hooks/use-display-units.js.map +1 -1
  4. package/lib/commonjs/hooks/use-inline-auto-width.js +43 -10
  5. package/lib/commonjs/hooks/use-inline-auto-width.js.map +1 -1
  6. package/lib/commonjs/hooks/use-morph-motion.js +2 -1
  7. package/lib/commonjs/hooks/use-morph-motion.js.map +1 -1
  8. package/lib/commonjs/hooks/use-morph-text-style.js +4 -0
  9. package/lib/commonjs/hooks/use-morph-text-style.js.map +1 -1
  10. package/lib/commonjs/hooks/use-numeric-lanes.js +1 -0
  11. package/lib/commonjs/hooks/use-numeric-lanes.js.map +1 -1
  12. package/lib/commonjs/hooks/use-text-glyphs.js +28 -7
  13. package/lib/commonjs/hooks/use-text-glyphs.js.map +1 -1
  14. package/lib/commonjs/index.js +58 -11
  15. package/lib/commonjs/index.js.map +1 -1
  16. package/lib/commonjs/model/display-units.js +7 -1
  17. package/lib/commonjs/model/display-units.js.map +1 -1
  18. package/lib/commonjs/model/numeric-lanes.js +4 -0
  19. package/lib/commonjs/model/numeric-lanes.js.map +1 -1
  20. package/lib/commonjs/model/text-keys.js +4 -0
  21. package/lib/commonjs/model/text-keys.js.map +1 -1
  22. package/lib/commonjs/motion/entry-exit-builders.js +78 -1
  23. package/lib/commonjs/motion/entry-exit-builders.js.map +1 -1
  24. package/lib/commonjs/motion/preset-map.js +7 -0
  25. package/lib/commonjs/motion/preset-map.js.map +1 -1
  26. package/lib/commonjs/view/glyph-run.js +34 -3
  27. package/lib/commonjs/view/glyph-run.js.map +1 -1
  28. package/lib/commonjs/view/morph-viewport.js +33 -3
  29. package/lib/commonjs/view/morph-viewport.js.map +1 -1
  30. package/lib/commonjs/view/number-lane.js +5 -1
  31. package/lib/commonjs/view/number-lane.js.map +1 -1
  32. package/lib/commonjs/view/number-run.js +17 -1
  33. package/lib/commonjs/view/number-run.js.map +1 -1
  34. package/lib/commonjs/view/slots-run.js +258 -0
  35. package/lib/commonjs/view/slots-run.js.map +1 -0
  36. package/lib/commonjs/view/text-run.js +37 -3
  37. package/lib/commonjs/view/text-run.js.map +1 -1
  38. package/lib/module/hooks/use-display-units.js +2 -0
  39. package/lib/module/hooks/use-display-units.js.map +1 -1
  40. package/lib/module/hooks/use-inline-auto-width.js +44 -11
  41. package/lib/module/hooks/use-inline-auto-width.js.map +1 -1
  42. package/lib/module/hooks/use-morph-motion.js +2 -1
  43. package/lib/module/hooks/use-morph-motion.js.map +1 -1
  44. package/lib/module/hooks/use-morph-text-style.js +4 -0
  45. package/lib/module/hooks/use-morph-text-style.js.map +1 -1
  46. package/lib/module/hooks/use-numeric-lanes.js +1 -0
  47. package/lib/module/hooks/use-numeric-lanes.js.map +1 -1
  48. package/lib/module/hooks/use-text-glyphs.js +28 -7
  49. package/lib/module/hooks/use-text-glyphs.js.map +1 -1
  50. package/lib/module/index.js +60 -12
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/model/display-units.js +7 -1
  53. package/lib/module/model/display-units.js.map +1 -1
  54. package/lib/module/model/numeric-lanes.js +5 -0
  55. package/lib/module/model/numeric-lanes.js.map +1 -1
  56. package/lib/module/model/text-keys.js +4 -0
  57. package/lib/module/model/text-keys.js.map +1 -1
  58. package/lib/module/motion/entry-exit-builders.js +75 -0
  59. package/lib/module/motion/entry-exit-builders.js.map +1 -1
  60. package/lib/module/motion/preset-map.js +7 -0
  61. package/lib/module/motion/preset-map.js.map +1 -1
  62. package/lib/module/view/glyph-run.js +34 -3
  63. package/lib/module/view/glyph-run.js.map +1 -1
  64. package/lib/module/view/morph-viewport.js +33 -3
  65. package/lib/module/view/morph-viewport.js.map +1 -1
  66. package/lib/module/view/number-lane.js +5 -1
  67. package/lib/module/view/number-lane.js.map +1 -1
  68. package/lib/module/view/number-run.js +17 -1
  69. package/lib/module/view/number-run.js.map +1 -1
  70. package/lib/module/view/slots-run.js +253 -0
  71. package/lib/module/view/slots-run.js.map +1 -0
  72. package/lib/module/view/text-run.js +38 -4
  73. package/lib/module/view/text-run.js.map +1 -1
  74. package/lib/typescript/commonjs/hooks/use-display-units.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/hooks/use-inline-auto-width.d.ts +3 -1
  76. package/lib/typescript/commonjs/hooks/use-inline-auto-width.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/hooks/use-morph-motion.d.ts.map +1 -1
  78. package/lib/typescript/commonjs/hooks/use-morph-text-style.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/hooks/use-numeric-lanes.d.ts.map +1 -1
  80. package/lib/typescript/commonjs/hooks/use-text-glyphs.d.ts +2 -1
  81. package/lib/typescript/commonjs/hooks/use-text-glyphs.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/index.d.ts +1 -3
  83. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/model/display-units.d.ts.map +1 -1
  85. package/lib/typescript/commonjs/model/numeric-lanes.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/model/text-keys.d.ts.map +1 -1
  87. package/lib/typescript/commonjs/motion/entry-exit-builders.d.ts +13 -0
  88. package/lib/typescript/commonjs/motion/entry-exit-builders.d.ts.map +1 -1
  89. package/lib/typescript/commonjs/motion/preset-map.d.ts.map +1 -1
  90. package/lib/typescript/commonjs/types.d.ts +14 -2
  91. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  92. package/lib/typescript/commonjs/view/glyph-run.d.ts +7 -3
  93. package/lib/typescript/commonjs/view/glyph-run.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/view/morph-viewport.d.ts +3 -1
  95. package/lib/typescript/commonjs/view/morph-viewport.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/view/number-lane.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/view/number-run.d.ts +3 -2
  98. package/lib/typescript/commonjs/view/number-run.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/view/slots-run.d.ts +15 -0
  100. package/lib/typescript/commonjs/view/slots-run.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/view/text-run.d.ts +7 -2
  102. package/lib/typescript/commonjs/view/text-run.d.ts.map +1 -1
  103. package/lib/typescript/module/hooks/use-display-units.d.ts.map +1 -1
  104. package/lib/typescript/module/hooks/use-inline-auto-width.d.ts +3 -1
  105. package/lib/typescript/module/hooks/use-inline-auto-width.d.ts.map +1 -1
  106. package/lib/typescript/module/hooks/use-morph-motion.d.ts.map +1 -1
  107. package/lib/typescript/module/hooks/use-morph-text-style.d.ts.map +1 -1
  108. package/lib/typescript/module/hooks/use-numeric-lanes.d.ts.map +1 -1
  109. package/lib/typescript/module/hooks/use-text-glyphs.d.ts +2 -1
  110. package/lib/typescript/module/hooks/use-text-glyphs.d.ts.map +1 -1
  111. package/lib/typescript/module/index.d.ts +1 -3
  112. package/lib/typescript/module/index.d.ts.map +1 -1
  113. package/lib/typescript/module/model/display-units.d.ts.map +1 -1
  114. package/lib/typescript/module/model/numeric-lanes.d.ts.map +1 -1
  115. package/lib/typescript/module/model/text-keys.d.ts.map +1 -1
  116. package/lib/typescript/module/motion/entry-exit-builders.d.ts +13 -0
  117. package/lib/typescript/module/motion/entry-exit-builders.d.ts.map +1 -1
  118. package/lib/typescript/module/motion/preset-map.d.ts.map +1 -1
  119. package/lib/typescript/module/types.d.ts +14 -2
  120. package/lib/typescript/module/types.d.ts.map +1 -1
  121. package/lib/typescript/module/view/glyph-run.d.ts +7 -3
  122. package/lib/typescript/module/view/glyph-run.d.ts.map +1 -1
  123. package/lib/typescript/module/view/morph-viewport.d.ts +3 -1
  124. package/lib/typescript/module/view/morph-viewport.d.ts.map +1 -1
  125. package/lib/typescript/module/view/number-lane.d.ts.map +1 -1
  126. package/lib/typescript/module/view/number-run.d.ts +3 -2
  127. package/lib/typescript/module/view/number-run.d.ts.map +1 -1
  128. package/lib/typescript/module/view/slots-run.d.ts +15 -0
  129. package/lib/typescript/module/view/slots-run.d.ts.map +1 -0
  130. package/lib/typescript/module/view/text-run.d.ts +7 -2
  131. package/lib/typescript/module/view/text-run.d.ts.map +1 -1
  132. package/package.json +11 -2
  133. package/src/hooks/use-display-units.ts +1 -0
  134. package/src/hooks/use-inline-auto-width.ts +55 -12
  135. package/src/hooks/use-morph-motion.ts +2 -1
  136. package/src/hooks/use-morph-text-style.ts +3 -0
  137. package/src/hooks/use-numeric-lanes.ts +1 -0
  138. package/src/hooks/use-text-glyphs.ts +48 -10
  139. package/src/index.tsx +103 -17
  140. package/src/model/display-units.ts +4 -1
  141. package/src/model/numeric-lanes.ts +3 -0
  142. package/src/model/text-keys.ts +3 -0
  143. package/src/motion/entry-exit-builders.ts +73 -0
  144. package/src/motion/preset-map.ts +4 -0
  145. package/src/types.ts +16 -2
  146. package/src/view/glyph-run.tsx +48 -15
  147. package/src/view/morph-viewport.tsx +28 -3
  148. package/src/view/number-lane.tsx +7 -2
  149. package/src/view/number-run.tsx +13 -2
  150. package/src/view/slots-run.tsx +385 -0
  151. package/src/view/text-run.tsx +80 -7
package/README.md CHANGED
@@ -86,6 +86,31 @@ export default function Counter() {
86
86
  </Pressable>
87
87
  ```
88
88
 
89
+ ### Centered text in a fixed-width container
90
+
91
+ Use `align` when the parent owns the width and Laminar should place the animated row inside that space.
92
+
93
+ ```tsx
94
+ <Pressable
95
+ style={{
96
+ width: "100%",
97
+ height: 50,
98
+ alignItems: "center",
99
+ justifyContent: "center",
100
+ borderRadius: 25,
101
+ backgroundColor: "#000000",
102
+ }}
103
+ >
104
+ <Laminar
105
+ text={isFinished ? "Continue and Finish" : "Continue"}
106
+ align="center"
107
+ autoSize={false}
108
+ containerStyle={{ width: "100%" }}
109
+ style={{ color: "#ffffff", fontSize: 24, fontWeight: "700" }}
110
+ />
111
+ </Pressable>
112
+ ```
113
+
89
114
  `autoSize` (default `true`) animates the outer container width toward the measured final text width. The button grows and shrinks without layout feedback loops.
90
115
 
91
116
  ### Standalone word without auto-sizing
@@ -93,6 +118,7 @@ export default function Counter() {
93
118
  ```tsx
94
119
  <Laminar
95
120
  text={word}
121
+ align="center"
96
122
  autoSize={false}
97
123
  fontSize={40}
98
124
  style={{ color: "#000000" }}
@@ -108,9 +134,13 @@ Use `autoSize={false}` when the parent already defines the space and you only wa
108
134
  ```ts
109
135
  type LaminarProps = {
110
136
  text: string | number;
111
- variant?: "text" | "number";
137
+ variant?: "text" | "number" | "slots";
112
138
  fontSize?: number;
113
139
  color?: string;
140
+ align?: "left" | "center" | "right";
141
+ leading?: ReactNode | Readonly<Record<string, ReactNode>>;
142
+ leadingKey?: string | number;
143
+ leadingGap?: number;
114
144
  style?: StyleProp<TextStyle>;
115
145
  containerStyle?: StyleProp<ViewStyle>;
116
146
  fontStyle?: StyleProp<TextStyle>;
@@ -125,11 +155,15 @@ type LaminarProps = {
125
155
  | Prop | Default | Description |
126
156
  | ------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------- |
127
157
  | `text` | Required | The value to display. Numbers are converted to strings internally. |
128
- | `variant` | `"text"` | `"text"` uses LCS glyph reconciliation. `"number"` uses right-aligned digit lanes. |
158
+ | `variant` | `"text"` | `"text"` uses LCS glyph reconciliation. `"number"` uses right-aligned digit lanes. `"slots"` rolls digits through slot columns using the same lanes. |
129
159
  | `fontSize` | Undefined | Convenience prop merged into the text style. |
130
160
  | `color` | Undefined | Convenience prop merged into the text style. |
161
+ | `align` | `"left"` | Visual alignment for Laminar's viewport and animated glyph row. |
162
+ | `leading` | Undefined | Optional inline element, or text-keyed leading content, rendered in text mode. |
163
+ | `leadingKey` | Undefined | Advanced identity override for a direct leading element. |
164
+ | `leadingGap` | `0` | Spacing between the leading element and the first text glyph. |
131
165
  | `style` | Undefined | Text style applied after `fontSize` and `color`. |
132
- | `containerStyle` | Undefined | Style for the outer viewport shell. Use for placement and alignment. |
166
+ | `containerStyle` | Undefined | Advanced style override for the outer viewport shell. |
133
167
  | `fontStyle` | Undefined | Additional text style merged before `style`. |
134
168
  | `animationDuration` | Preset default | Duration override in milliseconds. |
135
169
  | `animationPreset` | `"default"` for text, `"snappy"` for number | Named motion recipe. |
@@ -151,6 +185,7 @@ type LaminarProps = {
151
185
  ```tsx
152
186
  <Laminar text={word} animationPreset="smooth" />
153
187
  <Laminar text={count} variant="number" animationPreset="snappy" />
188
+ <Laminar text={count} variant="slots" animationPreset="snappy" />
154
189
 
155
190
  // Override duration
156
191
  <Laminar text={word} animationPreset="default" animationDuration={520} />
@@ -176,6 +211,15 @@ type LaminarProps = {
176
211
  - Standalone centered words → `autoSize={false}`
177
212
  - Fixed-width counters → `autoSize={false}`
178
213
 
214
+ **Use `align` for visual alignment.**
215
+
216
+ ```tsx
217
+ <Laminar text={word} align="center" autoSize={false} />
218
+ <Laminar text={price} variant="number" align="right" autoSize={false} />
219
+ ```
220
+
221
+ Use `containerStyle` only when you need lower-level control over the outer viewport.
222
+
179
223
  **Match formatting across renders for numbers.**
180
224
 
181
225
  Switching between `$1,234` and `1234` mid-session breaks lane alignment. Keep the format consistent.
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.useDisplayUnits = void 0;
7
7
  var _react = require("react");
8
8
  var _displayUnits = require("../model/display-units");
9
+ // normalize the same units used by rendering before measurement reads them
9
10
  const useDisplayUnits = (value, enabled = true) => (0, _react.useMemo)(() =>
10
11
  // skip unit work when auto size is off
11
12
  enabled ? (0, _displayUnits.splitDisplayUnits)(value).map(_displayUnits.normalizeDisplayUnit) : [], [enabled, value]);
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_displayUnits","useDisplayUnits","value","enabled","useMemo","splitDisplayUnits","map","normalizeDisplayUnit","exports"],"sourceRoot":"../../../src","sources":["hooks/use-display-units.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AAKO,MAAME,eAAe,GAAGA,CAC7BC,KAAa,EACbC,OAAO,GAAG,IAAI,KAEd,IAAAC,cAAO,EACL;AACE;AACAD,OAAO,GACH,IAAAE,+BAAiB,EAACH,KAAK,CAAC,CAACI,GAAG,CAACC,kCAAoB,CAAC,GAClD,EAAE,EACR,CAACJ,OAAO,EAAED,KAAK,CACjB,CAAC;AAACM,OAAA,CAAAP,eAAA,GAAAA,eAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_displayUnits","useDisplayUnits","value","enabled","useMemo","splitDisplayUnits","map","normalizeDisplayUnit","exports"],"sourceRoot":"../../../src","sources":["hooks/use-display-units.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AAKA;AACO,MAAME,eAAe,GAAGA,CAC7BC,KAAa,EACbC,OAAO,GAAG,IAAI,KAEd,IAAAC,cAAO,EACL;AACE;AACAD,OAAO,GACH,IAAAE,+BAAiB,EAACH,KAAK,CAAC,CAACI,GAAG,CAACC,kCAAoB,CAAC,GAClD,EAAE,EACR,CAACJ,OAAO,EAAED,KAAK,CACjB,CAAC;AAACM,OAAA,CAAAP,eAAA,GAAAA,eAAA","ignoreList":[]}
@@ -6,25 +6,26 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.useInlineAutoWidth = void 0;
7
7
  var _react = require("react");
8
8
  var _reactNativeReanimated = require("react-native-reanimated");
9
+ const WIDTH_CACHE_LIMIT = 64;
10
+
11
+ // measure each content signature once and drive later changes through one width value
9
12
  const useInlineAutoWidth = ({
10
13
  enabled,
11
- driveToWidth
14
+ driveToWidth,
15
+ measurementKey
12
16
  }) => {
13
17
  const widthValue = (0, _reactNativeReanimated.useSharedValue)(0);
14
18
  const measuredWidthRef = (0, _react.useRef)(null);
15
19
  const bootstrappedRef = (0, _react.useRef)(false);
20
+ const widthCacheRef = (0, _react.useRef)(new Map());
16
21
  const [hasBootstrappedWidth, setHasBootstrappedWidth] = (0, _react.useState)(false);
17
- const captureLayout = (0, _react.useCallback)(event => {
18
- if (!enabled) {
19
- return;
20
- }
21
- const nextWidth = Math.max(0, Math.ceil(event.nativeEvent.layout.width));
22
+
23
+ // the first measurement establishes the shell without animating from zero
24
+ const applyWidth = (0, _react.useCallback)(nextWidth => {
22
25
  if (measuredWidthRef.current === nextWidth) {
23
26
  return;
24
27
  }
25
28
  measuredWidthRef.current = nextWidth;
26
-
27
- // snap the first width so mount does not animate from zero
28
29
  if (!bootstrappedRef.current) {
29
30
  bootstrappedRef.current = true;
30
31
  widthValue.value = nextWidth;
@@ -32,13 +33,45 @@ const useInlineAutoWidth = ({
32
33
  return;
33
34
  }
34
35
  widthValue.value = driveToWidth(nextWidth);
35
- }, [driveToWidth, enabled, widthValue]);
36
+ }, [driveToWidth, widthValue]);
37
+ const captureLayout = (0, _react.useCallback)(event => {
38
+ if (!enabled) {
39
+ return;
40
+ }
41
+
42
+ // round up so fractional native measurements cannot clip the final glyph
43
+ const nextWidth = Math.max(0, Math.ceil(event.nativeEvent.layout.width));
44
+
45
+ // delete before setting so a repeated key moves to the most recent position
46
+ widthCacheRef.current.delete(measurementKey);
47
+ if (widthCacheRef.current.size >= WIDTH_CACHE_LIMIT) {
48
+ // map insertion order gives the lru entry at the front
49
+ const oldestKey = widthCacheRef.current.keys().next().value;
50
+ if (oldestKey !== undefined) {
51
+ widthCacheRef.current.delete(oldestKey);
52
+ }
53
+ }
54
+ widthCacheRef.current.set(measurementKey, nextWidth);
55
+ applyWidth(nextWidth);
56
+ }, [applyWidth, enabled, measurementKey]);
57
+ const cachedWidth = widthCacheRef.current.get(measurementKey);
58
+
59
+ // a cached width can restore the shell before the hidden probe renders again
60
+ (0, _react.useEffect)(() => {
61
+ if (enabled && cachedWidth !== undefined) {
62
+ // promote cache hits so active states stay available longer
63
+ widthCacheRef.current.delete(measurementKey);
64
+ widthCacheRef.current.set(measurementKey, cachedWidth);
65
+ applyWidth(cachedWidth);
66
+ }
67
+ }, [applyWidth, cachedWidth, enabled, measurementKey]);
36
68
  const animatedWidthStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => enabled && hasBootstrappedWidth ? {
37
69
  width: widthValue.value
38
70
  } : {}, [enabled, hasBootstrappedWidth]);
39
71
  return {
40
72
  captureLayout,
41
- animatedWidthStyle
73
+ animatedWidthStyle,
74
+ shouldMeasure: enabled && cachedWidth === undefined
42
75
  };
43
76
  };
44
77
  exports.useInlineAutoWidth = useInlineAutoWidth;
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNativeReanimated","useInlineAutoWidth","enabled","driveToWidth","widthValue","useSharedValue","measuredWidthRef","useRef","bootstrappedRef","hasBootstrappedWidth","setHasBootstrappedWidth","useState","captureLayout","useCallback","event","nextWidth","Math","max","ceil","nativeEvent","layout","width","current","value","animatedWidthStyle","useAnimatedStyle","exports"],"sourceRoot":"../../../src","sources":["hooks/use-inline-auto-width.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,sBAAA,GAAAD,OAAA;AAOO,MAAME,kBAAkB,GAAGA,CAAC;EAAEC,OAAO;EAAEC;AAAqB,CAAC,KAAK;EACvE,MAAMC,UAAU,GAAG,IAAAC,qCAAc,EAAC,CAAC,CAAC;EACpC,MAAMC,gBAAgB,GAAG,IAAAC,aAAM,EAAgB,IAAI,CAAC;EACpD,MAAMC,eAAe,GAAG,IAAAD,aAAM,EAAC,KAAK,CAAC;EACrC,MAAM,CAACE,oBAAoB,EAAEC,uBAAuB,CAAC,GAAG,IAAAC,eAAQ,EAAC,KAAK,CAAC;EAEvE,MAAMC,aAAa,GAAG,IAAAC,kBAAW,EAC9BC,KAAwB,IAAK;IAC5B,IAAI,CAACZ,OAAO,EAAE;MACZ;IACF;IAEA,MAAMa,SAAS,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,IAAI,CAACJ,KAAK,CAACK,WAAW,CAACC,MAAM,CAACC,KAAK,CAAC,CAAC;IAExE,IAAIf,gBAAgB,CAACgB,OAAO,KAAKP,SAAS,EAAE;MAC1C;IACF;IAEAT,gBAAgB,CAACgB,OAAO,GAAGP,SAAS;;IAEpC;IACA,IAAI,CAACP,eAAe,CAACc,OAAO,EAAE;MAC5Bd,eAAe,CAACc,OAAO,GAAG,IAAI;MAC9BlB,UAAU,CAACmB,KAAK,GAAGR,SAAS;MAC5BL,uBAAuB,CAAC,IAAI,CAAC;MAC7B;IACF;IAEAN,UAAU,CAACmB,KAAK,GAAGpB,YAAY,CAACY,SAAS,CAAC;EAC5C,CAAC,EACD,CAACZ,YAAY,EAAED,OAAO,EAAEE,UAAU,CACpC,CAAC;EAED,MAAMoB,kBAAkB,GAAG,IAAAC,uCAAgB,EACzC,MACEvB,OAAO,IAAIO,oBAAoB,GAC3B;IACEY,KAAK,EAAEjB,UAAU,CAACmB;EACpB,CAAC,GACD,CAAC,CAAC,EACR,CAACrB,OAAO,EAAEO,oBAAoB,CAChC,CAAC;EAED,OAAO;IACLG,aAAa;IACbY;EACF,CAAC;AACH,CAAC;AAACE,OAAA,CAAAzB,kBAAA,GAAAA,kBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNativeReanimated","WIDTH_CACHE_LIMIT","useInlineAutoWidth","enabled","driveToWidth","measurementKey","widthValue","useSharedValue","measuredWidthRef","useRef","bootstrappedRef","widthCacheRef","Map","hasBootstrappedWidth","setHasBootstrappedWidth","useState","applyWidth","useCallback","nextWidth","current","value","captureLayout","event","Math","max","ceil","nativeEvent","layout","width","delete","size","oldestKey","keys","next","undefined","set","cachedWidth","get","useEffect","animatedWidthStyle","useAnimatedStyle","shouldMeasure","exports"],"sourceRoot":"../../../src","sources":["hooks/use-inline-auto-width.ts"],"mappings":"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","ignoreList":[]}
@@ -6,13 +6,14 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.useMorphMotion = void 0;
7
7
  var _react = require("react");
8
8
  var _presetMap = require("../motion/preset-map");
9
+ // resolve one motion recipe and one shared stagger unit for a render tree
9
10
  const useMorphMotion = ({
10
11
  variant,
11
12
  animationPreset,
12
13
  animationDuration,
13
14
  stagger
14
15
  }) => {
15
- // numbers feel better with snappy unless you pick something else
16
+ // numeric variants need a quicker default because their lanes update often
16
17
  const resolvedPreset = animationPreset ?? (variant === "text" ? "default" : "snappy");
17
18
  const motionRecipe = (0, _react.useMemo)(() => (0, _presetMap.resolveMotionRecipe)(resolvedPreset, animationDuration), [animationDuration, resolvedPreset]);
18
19
  return {
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_presetMap","useMorphMotion","variant","animationPreset","animationDuration","stagger","resolvedPreset","motionRecipe","useMemo","resolveMotionRecipe","staggerMs","Math","round","exports"],"sourceRoot":"../../../src","sources":["hooks/use-morph-motion.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AAmBO,MAAME,cAAc,GAAGA,CAAC;EAC7BC,OAAO;EACPC,eAAe;EACfC,iBAAiB;EACjBC;AACM,CAAC,KAAkB;EACzB;EACA,MAAMC,cAAc,GAClBH,eAAe,KAAKD,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;EAEhE,MAAMK,YAAY,GAAG,IAAAC,cAAO,EAC1B,MAAM,IAAAC,8BAAmB,EAACH,cAAc,EAAEF,iBAAiB,CAAC,EAC5D,CAACA,iBAAiB,EAAEE,cAAc,CACpC,CAAC;EAED,OAAO;IACLC,YAAY;IACZG,SAAS,EAAEC,IAAI,CAACC,KAAK,CAACP,OAAO,GAAG,IAAI;EACtC,CAAC;AACH,CAAC;AAACQ,OAAA,CAAAZ,cAAA,GAAAA,cAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_presetMap","useMorphMotion","variant","animationPreset","animationDuration","stagger","resolvedPreset","motionRecipe","useMemo","resolveMotionRecipe","staggerMs","Math","round","exports"],"sourceRoot":"../../../src","sources":["hooks/use-morph-motion.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,UAAA,GAAAD,OAAA;AAmBA;AACO,MAAME,cAAc,GAAGA,CAAC;EAC7BC,OAAO;EACPC,eAAe;EACfC,iBAAiB;EACjBC;AACM,CAAC,KAAkB;EACzB;EACA,MAAMC,cAAc,GAClBH,eAAe,KAAKD,OAAO,KAAK,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;EAEhE,MAAMK,YAAY,GAAG,IAAAC,cAAO,EAC1B,MAAM,IAAAC,8BAAmB,EAACH,cAAc,EAAEF,iBAAiB,CAAC,EAC5D,CAACA,iBAAiB,EAAEE,cAAc,CACpC,CAAC;EAED,OAAO;IACLC,YAAY;IACZG,SAAS,EAAEC,IAAI,CAACC,KAAK,CAACP,OAAO,GAAG,IAAI;EACtC,CAAC;AACH,CAAC;AAACQ,OAAA,CAAAZ,cAAA,GAAAA,cAAA","ignoreList":[]}
@@ -5,12 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.useMorphTextStyle = void 0;
7
7
  var _react = require("react");
8
+ // compose the public style layers into the style passed to every glyph
8
9
  const useMorphTextStyle = ({
9
10
  fontSize,
10
11
  color,
11
12
  fontStyle,
12
13
  style
13
14
  }) => {
15
+ // keep the base layer small so caller styles can override it predictably
14
16
  const baseTextStyle = (0, _react.useMemo)(() => {
15
17
  const nextStyle = {
16
18
  includeFontPadding: false
@@ -23,6 +25,8 @@ const useMorphTextStyle = ({
23
25
  }
24
26
  return nextStyle;
25
27
  }, [color, fontSize]);
28
+
29
+ // preserve the merge order used by the public style contract
26
30
  const textStyle = (0, _react.useMemo)(() => [baseTextStyle, fontStyle, style], [baseTextStyle, fontStyle, style]);
27
31
  return {
28
32
  textStyle
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","useMorphTextStyle","fontSize","color","fontStyle","style","baseTextStyle","useMemo","nextStyle","includeFontPadding","undefined","textStyle","exports"],"sourceRoot":"../../../src","sources":["hooks/use-morph-text-style.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAcO,MAAMC,iBAAiB,GAAGA,CAAC;EAChCC,QAAQ;EACRC,KAAK;EACLC,SAAS;EACTC;AACM,CAAC,KAAqB;EAC5B,MAAMC,aAAa,GAAG,IAAAC,cAAO,EAAC,MAAM;IAClC,MAAMC,SAAoB,GAAG;MAC3BC,kBAAkB,EAAE;IACtB,CAAC;IAED,IAAIP,QAAQ,KAAKQ,SAAS,EAAE;MAC1BF,SAAS,CAACN,QAAQ,GAAGA,QAAQ;IAC/B;IAEA,IAAIC,KAAK,KAAKO,SAAS,EAAE;MACvBF,SAAS,CAACL,KAAK,GAAGA,KAAK;IACzB;IAEA,OAAOK,SAAS;EAClB,CAAC,EAAE,CAACL,KAAK,EAAED,QAAQ,CAAC,CAAC;EAErB,MAAMS,SAAS,GAAG,IAAAJ,cAAO,EACvB,MAAM,CAACD,aAAa,EAAEF,SAAS,EAAEC,KAAK,CAAC,EACvC,CAACC,aAAa,EAAEF,SAAS,EAAEC,KAAK,CAClC,CAAC;EAED,OAAO;IACLM;EACF,CAAC;AACH,CAAC;AAACC,OAAA,CAAAX,iBAAA,GAAAA,iBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","useMorphTextStyle","fontSize","color","fontStyle","style","baseTextStyle","useMemo","nextStyle","includeFontPadding","undefined","textStyle","exports"],"sourceRoot":"../../../src","sources":["hooks/use-morph-text-style.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAcA;AACO,MAAMC,iBAAiB,GAAGA,CAAC;EAChCC,QAAQ;EACRC,KAAK;EACLC,SAAS;EACTC;AACM,CAAC,KAAqB;EAC5B;EACA,MAAMC,aAAa,GAAG,IAAAC,cAAO,EAAC,MAAM;IAClC,MAAMC,SAAoB,GAAG;MAC3BC,kBAAkB,EAAE;IACtB,CAAC;IAED,IAAIP,QAAQ,KAAKQ,SAAS,EAAE;MAC1BF,SAAS,CAACN,QAAQ,GAAGA,QAAQ;IAC/B;IAEA,IAAIC,KAAK,KAAKO,SAAS,EAAE;MACvBF,SAAS,CAACL,KAAK,GAAGA,KAAK;IACzB;IAEA,OAAOK,SAAS;EAClB,CAAC,EAAE,CAACL,KAAK,EAAED,QAAQ,CAAC,CAAC;;EAErB;EACA,MAAMS,SAAS,GAAG,IAAAJ,cAAO,EACvB,MAAM,CAACD,aAAa,EAAEF,SAAS,EAAEC,KAAK,CAAC,EACvC,CAACC,aAAa,EAAEF,SAAS,EAAEC,KAAK,CAClC,CAAC;EAED,OAAO;IACLM;EACF,CAAC;AACH,CAAC;AAACC,OAAA,CAAAX,iBAAA,GAAAA,iBAAA","ignoreList":[]}
@@ -7,6 +7,7 @@ exports.useNumericLanes = void 0;
7
7
  var _react = require("react");
8
8
  var _displayUnits = require("../model/display-units");
9
9
  var _numericLanes = require("../model/numeric-lanes");
10
+ // retain numeric lane identity across value changes without storing it in state
10
11
  const useNumericLanes = value => {
11
12
  const units = (0, _react.useMemo)(() => (0, _displayUnits.splitDisplayUnits)(value), [value]);
12
13
  const ledgerRef = (0, _react.useRef)({
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_displayUnits","_numericLanes","useNumericLanes","value","units","useMemo","splitDisplayUnits","ledgerRef","useRef","previousValue","laneKeys","map","_","index","nextSeed","length","direction","current","nextLedger","reconcileNumericLanes","leadLength","findNumericLeadLength","exports"],"sourceRoot":"../../../src","sources":["hooks/use-numeric-lanes.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,aAAA,GAAAD,OAAA;AAIA,IAAAE,aAAA,GAAAF,OAAA;AAgBO,MAAMG,eAAe,GAAIC,KAAa,IAA0B;EACrE,MAAMC,KAAK,GAAG,IAAAC,cAAO,EAAC,MAAM,IAAAC,+BAAiB,EAACH,KAAK,CAAC,EAAE,CAACA,KAAK,CAAC,CAAC;EAC9D,MAAMI,SAAS,GAAG,IAAAC,aAAM,EAAgB;IACtCC,aAAa,EAAEN,KAAK;IACpBO,QAAQ,EAAEN,KAAK,CAACO,GAAG,CAAC,CAACC,CAAC,EAAEC,KAAK,KAAKA,KAAK,CAAC;IACxCC,QAAQ,EAAEV,KAAK,CAACW,MAAM;IACtBC,SAAS,EAAE;EACb,CAAC,CAAC;;EAEF;EACA,IAAIb,KAAK,KAAKI,SAAS,CAACU,OAAO,CAACR,aAAa,EAAE;IAC7C,MAAMS,UAAU,GAAG,IAAAC,mCAAqB,EACtCZ,SAAS,CAACU,OAAO,CAACR,aAAa,EAC/BN,KAAK,EACLI,SAAS,CAACU,OAAO,CAACP,QAAQ,EAC1BH,SAAS,CAACU,OAAO,CAACH,QACpB,CAAC;IAEDP,SAAS,CAACU,OAAO,GAAG;MAClBR,aAAa,EAAEN,KAAK;MACpBO,QAAQ,EAAEQ,UAAU,CAACR,QAAQ;MAC7BI,QAAQ,EAAEI,UAAU,CAACJ,QAAQ;MAC7BE,SAAS,EAAEE,UAAU,CAACF;IACxB,CAAC;EACH;EAEA,OAAO;IACLZ,KAAK;IACLM,QAAQ,EAAEH,SAAS,CAACU,OAAO,CAACP,QAAQ;IACpCM,SAAS,EAAET,SAAS,CAACU,OAAO,CAACD,SAAS;IACtCI,UAAU,EAAE,IAAAC,mCAAqB,EAACjB,KAAK;EACzC,CAAC;AACH,CAAC;AAACkB,OAAA,CAAApB,eAAA,GAAAA,eAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_displayUnits","_numericLanes","useNumericLanes","value","units","useMemo","splitDisplayUnits","ledgerRef","useRef","previousValue","laneKeys","map","_","index","nextSeed","length","direction","current","nextLedger","reconcileNumericLanes","leadLength","findNumericLeadLength","exports"],"sourceRoot":"../../../src","sources":["hooks/use-numeric-lanes.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,aAAA,GAAAD,OAAA;AAIA,IAAAE,aAAA,GAAAF,OAAA;AAgBA;AACO,MAAMG,eAAe,GAAIC,KAAa,IAA0B;EACrE,MAAMC,KAAK,GAAG,IAAAC,cAAO,EAAC,MAAM,IAAAC,+BAAiB,EAACH,KAAK,CAAC,EAAE,CAACA,KAAK,CAAC,CAAC;EAC9D,MAAMI,SAAS,GAAG,IAAAC,aAAM,EAAgB;IACtCC,aAAa,EAAEN,KAAK;IACpBO,QAAQ,EAAEN,KAAK,CAACO,GAAG,CAAC,CAACC,CAAC,EAAEC,KAAK,KAAKA,KAAK,CAAC;IACxCC,QAAQ,EAAEV,KAAK,CAACW,MAAM;IACtBC,SAAS,EAAE;EACb,CAAC,CAAC;;EAEF;EACA,IAAIb,KAAK,KAAKI,SAAS,CAACU,OAAO,CAACR,aAAa,EAAE;IAC7C,MAAMS,UAAU,GAAG,IAAAC,mCAAqB,EACtCZ,SAAS,CAACU,OAAO,CAACR,aAAa,EAC/BN,KAAK,EACLI,SAAS,CAACU,OAAO,CAACP,QAAQ,EAC1BH,SAAS,CAACU,OAAO,CAACH,QACpB,CAAC;IAEDP,SAAS,CAACU,OAAO,GAAG;MAClBR,aAAa,EAAEN,KAAK;MACpBO,QAAQ,EAAEQ,UAAU,CAACR,QAAQ;MAC7BI,QAAQ,EAAEI,UAAU,CAACJ,QAAQ;MAC7BE,SAAS,EAAEE,UAAU,CAACF;IACxB,CAAC;EACH;EAEA,OAAO;IACLZ,KAAK;IACLM,QAAQ,EAAEH,SAAS,CAACU,OAAO,CAACP,QAAQ;IACpCM,SAAS,EAAET,SAAS,CAACU,OAAO,CAACD,SAAS;IACtCI,UAAU,EAAE,IAAAC,mCAAqB,EAACjB,KAAK;EACzC,CAAC;AACH,CAAC;AAACkB,OAAA,CAAApB,eAAA,GAAAA,eAAA","ignoreList":[]}
@@ -7,28 +7,49 @@ exports.useTextGlyphs = void 0;
7
7
  var _react = require("react");
8
8
  var _displayUnits = require("../model/display-units");
9
9
  var _textKeys = require("../model/text-keys");
10
- const useTextGlyphs = (value, namespace) => {
11
- const units = (0, _react.useMemo)(() => (0, _displayUnits.splitDisplayUnits)(value), [value]);
10
+ // build the inline token stream that lets text and leading content share one ledger
11
+ const useTextGlyphs = (value, namespace, leading, leadingKey) => {
12
+ const units = (0, _react.useMemo)(() => [
13
+ // the map key becomes the identity when leading content is state keyed
14
+ ...(leading ? [{
15
+ kind: "element",
16
+ signature: `leading:${String(leadingKey ?? "default")}`,
17
+ element: leading
18
+ }] : []), ...(0, _displayUnits.splitDisplayUnits)(value).map(unit => ({
19
+ kind: "text",
20
+ signature: `text:${unit}`,
21
+ value: unit
22
+ }))], [leading, leadingKey, value]);
23
+ const signatures = units.map(unit => unit.signature);
12
24
  const ledgerRef = (0, _react.useRef)({
13
25
  previousValue: value,
14
- previousUnits: units,
26
+ previousSignatures: signatures,
15
27
  glyphKeys: units.map((_, index) => `${namespace}:c${index}`),
16
28
  nextSeed: units.length
17
29
  });
18
- if (value !== ledgerRef.current.previousValue) {
30
+
31
+ // reconcile only when a token signature changes so stable glyphs keep their views
32
+ if (value !== ledgerRef.current.previousValue || signatures.length !== ledgerRef.current.previousSignatures.length || signatures.some((signature, index) => signature !== ledgerRef.current.previousSignatures[index])) {
19
33
  // keep ids stable so unchanged glyphs stay mounted between updates
20
- const nextLedger = (0, _textKeys.reconcileTextGlyphKeys)(ledgerRef.current.previousUnits, units, ledgerRef.current.glyphKeys, ledgerRef.current.nextSeed, namespace);
34
+ const nextLedger = (0, _textKeys.reconcileTextGlyphKeys)(ledgerRef.current.previousSignatures, signatures, ledgerRef.current.glyphKeys, ledgerRef.current.nextSeed, namespace);
21
35
  ledgerRef.current = {
22
36
  previousValue: value,
23
- previousUnits: units,
37
+ previousSignatures: signatures,
24
38
  glyphKeys: nextLedger.glyphKeys,
25
39
  nextSeed: nextLedger.nextSeed
26
40
  };
27
41
  }
28
42
  const glyphKeys = ledgerRef.current.glyphKeys;
43
+
44
+ // normalize spaces at the edge where tokens become renderable glyphs
29
45
  return (0, _react.useMemo)(() => units.map((unit, index) => ({
30
46
  id: glyphKeys[index],
31
- value: (0, _displayUnits.normalizeDisplayUnit)(unit)
47
+ kind: unit.kind,
48
+ ...(unit.kind === "text" ? {
49
+ value: (0, _displayUnits.normalizeDisplayUnit)(unit.value)
50
+ } : {
51
+ element: unit.element
52
+ })
32
53
  })), [glyphKeys, units]);
33
54
  };
34
55
  exports.useTextGlyphs = useTextGlyphs;
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_displayUnits","_textKeys","useTextGlyphs","value","namespace","units","useMemo","splitDisplayUnits","ledgerRef","useRef","previousValue","previousUnits","glyphKeys","map","_","index","nextSeed","length","current","nextLedger","reconcileTextGlyphKeys","unit","id","normalizeDisplayUnit","exports"],"sourceRoot":"../../../src","sources":["hooks/use-text-glyphs.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AAIA,IAAAE,SAAA,GAAAF,OAAA;AAUO,MAAMG,aAAa,GAAGA,CAC3BC,KAAa,EACbC,SAAiB,KACS;EAC1B,MAAMC,KAAK,GAAG,IAAAC,cAAO,EAAC,MAAM,IAAAC,+BAAiB,EAACJ,KAAK,CAAC,EAAE,CAACA,KAAK,CAAC,CAAC;EAC9D,MAAMK,SAAS,GAAG,IAAAC,aAAM,EAAkB;IACxCC,aAAa,EAAEP,KAAK;IACpBQ,aAAa,EAAEN,KAAK;IACpBO,SAAS,EAAEP,KAAK,CAACQ,GAAG,CAAC,CAACC,CAAC,EAAEC,KAAK,KAAK,GAAGX,SAAS,KAAKW,KAAK,EAAE,CAAC;IAC5DC,QAAQ,EAAEX,KAAK,CAACY;EAClB,CAAC,CAAC;EAEF,IAAId,KAAK,KAAKK,SAAS,CAACU,OAAO,CAACR,aAAa,EAAE;IAC7C;IACA,MAAMS,UAAU,GAAG,IAAAC,gCAAsB,EACvCZ,SAAS,CAACU,OAAO,CAACP,aAAa,EAC/BN,KAAK,EACLG,SAAS,CAACU,OAAO,CAACN,SAAS,EAC3BJ,SAAS,CAACU,OAAO,CAACF,QAAQ,EAC1BZ,SACF,CAAC;IAEDI,SAAS,CAACU,OAAO,GAAG;MAClBR,aAAa,EAAEP,KAAK;MACpBQ,aAAa,EAAEN,KAAK;MACpBO,SAAS,EAAEO,UAAU,CAACP,SAAS;MAC/BI,QAAQ,EAAEG,UAAU,CAACH;IACvB,CAAC;EACH;EAEA,MAAMJ,SAAS,GAAGJ,SAAS,CAACU,OAAO,CAACN,SAAS;EAE7C,OAAO,IAAAN,cAAO,EACZ,MACED,KAAK,CAACQ,GAAG,CAAC,CAACQ,IAAI,EAAEN,KAAK,MAAM;IAC1BO,EAAE,EAAEV,SAAS,CAACG,KAAK,CAAC;IACpBZ,KAAK,EAAE,IAAAoB,kCAAoB,EAACF,IAAI;EAClC,CAAC,CAAC,CAAC,EACL,CAACT,SAAS,EAAEP,KAAK,CACnB,CAAC;AACH,CAAC;AAACmB,OAAA,CAAAtB,aAAA,GAAAA,aAAA","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_displayUnits","_textKeys","useTextGlyphs","value","namespace","leading","leadingKey","units","useMemo","kind","signature","String","element","splitDisplayUnits","map","unit","signatures","ledgerRef","useRef","previousValue","previousSignatures","glyphKeys","_","index","nextSeed","length","current","some","nextLedger","reconcileTextGlyphKeys","id","normalizeDisplayUnit","exports"],"sourceRoot":"../../../src","sources":["hooks/use-text-glyphs.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AAIA,IAAAE,SAAA,GAAAF,OAAA;AAcA;AACO,MAAMG,aAAa,GAAGA,CAC3BC,KAAa,EACbC,SAAiB,EACjBC,OAAmB,EACnBC,UAA4B,KACF;EAC1B,MAAMC,KAAK,GAAG,IAAAC,cAAO,EACnB,MAAM;EACJ;EACA,IAAIH,OAAO,GACP,CACE;IACEI,IAAI,EAAE,SAAS;IACfC,SAAS,EAAE,WAAWC,MAAM,CAACL,UAAU,IAAI,SAAS,CAAC,EAAE;IACvDM,OAAO,EAAEP;EACX,CAAC,CACF,GACD,EAAE,CAAC,EACP,GAAG,IAAAQ,+BAAiB,EAACV,KAAK,CAAC,CAACW,GAAG,CAAEC,IAAI,KAAM;IACzCN,IAAI,EAAE,MAAe;IACrBC,SAAS,EAAE,QAAQK,IAAI,EAAE;IACzBZ,KAAK,EAAEY;EACT,CAAC,CAAC,CAAC,CACJ,EACD,CAACV,OAAO,EAAEC,UAAU,EAAEH,KAAK,CAC7B,CAAC;EACD,MAAMa,UAAU,GAAGT,KAAK,CAACO,GAAG,CAAEC,IAAI,IAAKA,IAAI,CAACL,SAAS,CAAC;EACtD,MAAMO,SAAS,GAAG,IAAAC,aAAM,EAAkB;IACxCC,aAAa,EAAEhB,KAAK;IACpBiB,kBAAkB,EAAEJ,UAAU;IAC9BK,SAAS,EAAEd,KAAK,CAACO,GAAG,CAAC,CAACQ,CAAC,EAAEC,KAAK,KAAK,GAAGnB,SAAS,KAAKmB,KAAK,EAAE,CAAC;IAC5DC,QAAQ,EAAEjB,KAAK,CAACkB;EAClB,CAAC,CAAC;;EAEF;EACA,IACEtB,KAAK,KAAKc,SAAS,CAACS,OAAO,CAACP,aAAa,IACzCH,UAAU,CAACS,MAAM,KAAKR,SAAS,CAACS,OAAO,CAACN,kBAAkB,CAACK,MAAM,IACjET,UAAU,CAACW,IAAI,CACb,CAACjB,SAAS,EAAEa,KAAK,KAAKb,SAAS,KAAKO,SAAS,CAACS,OAAO,CAACN,kBAAkB,CAACG,KAAK,CAChF,CAAC,EACD;IACA;IACA,MAAMK,UAAU,GAAG,IAAAC,gCAAsB,EACvCZ,SAAS,CAACS,OAAO,CAACN,kBAAkB,EACpCJ,UAAU,EACVC,SAAS,CAACS,OAAO,CAACL,SAAS,EAC3BJ,SAAS,CAACS,OAAO,CAACF,QAAQ,EAC1BpB,SACF,CAAC;IAEDa,SAAS,CAACS,OAAO,GAAG;MAClBP,aAAa,EAAEhB,KAAK;MACpBiB,kBAAkB,EAAEJ,UAAU;MAC9BK,SAAS,EAAEO,UAAU,CAACP,SAAS;MAC/BG,QAAQ,EAAEI,UAAU,CAACJ;IACvB,CAAC;EACH;EAEA,MAAMH,SAAS,GAAGJ,SAAS,CAACS,OAAO,CAACL,SAAS;;EAE7C;EACA,OAAO,IAAAb,cAAO,EACZ,MACED,KAAK,CAACO,GAAG,CAAC,CAACC,IAAI,EAAEQ,KAAK,MAAM;IAC1BO,EAAE,EAAET,SAAS,CAACE,KAAK,CAAC;IACpBd,IAAI,EAAEM,IAAI,CAACN,IAAI;IACf,IAAIM,IAAI,CAACN,IAAI,KAAK,MAAM,GACpB;MAAEN,KAAK,EAAE,IAAA4B,kCAAoB,EAAChB,IAAI,CAACZ,KAAK;IAAE,CAAC,GAC3C;MAAES,OAAO,EAAEG,IAAI,CAACH;IAAQ,CAAC;EAC/B,CAAC,CAAC,CAAC,EACL,CAACS,SAAS,EAAEd,KAAK,CACnB,CAAC;AACH,CAAC;AAACyB,OAAA,CAAA9B,aAAA,GAAAA,aAAA","ignoreList":[]}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.MorphingText = exports.Laminar = void 0;
6
+ exports.Laminar = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _useInlineAutoWidth = require("./hooks/use-inline-auto-width");
@@ -12,15 +12,21 @@ var _useMorphTextStyle = require("./hooks/use-morph-text-style");
12
12
  var _displayUnits = require("./model/display-units");
13
13
  var _morphViewport = require("./view/morph-viewport");
14
14
  var _numberRun = require("./view/number-run");
15
+ var _slotsRun = require("./view/slots-run");
15
16
  var _textRun = require("./view/text-run");
16
17
  var _jsxRuntime = require("react/jsx-runtime");
17
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
+ // choose the content variant and connect it to the shared viewport and measurement flow
18
20
  const Laminar = exports.Laminar = /*#__PURE__*/_react.default.memo(function Laminar({
19
21
  text,
20
22
  variant = "text",
21
23
  fontSize,
22
24
  color,
25
+ align = "left",
23
26
  className,
27
+ leading,
28
+ leadingKey,
29
+ leadingGap = 0,
24
30
  style,
25
31
  containerStyle,
26
32
  fontStyle,
@@ -31,6 +37,10 @@ const Laminar = exports.Laminar = /*#__PURE__*/_react.default.memo(function Lami
31
37
  clipToBounds = false
32
38
  }) {
33
39
  const resolvedValue = String(text ?? "");
40
+ // resolve state keyed leading content before measurement and token reconciliation
41
+ const leadingMap = isLeadingMap(leading) ? leading : undefined;
42
+ const resolvedLeading = leadingMap ? leadingMap[resolvedValue] : leading;
43
+ const resolvedLeadingKey = leadingMap ? resolvedValue : leadingKey;
34
44
  const {
35
45
  motionRecipe,
36
46
  staggerMs
@@ -48,13 +58,22 @@ const Laminar = exports.Laminar = /*#__PURE__*/_react.default.memo(function Lami
48
58
  fontStyle,
49
59
  style
50
60
  });
61
+
62
+ // invalidate the probe when text style, leading content, or leading spacing changes
63
+ const measurementKey = _react.default.useMemo(() => {
64
+ const flattenedStyle = _reactNative.StyleSheet.flatten(textStyle);
65
+ return JSON.stringify([resolvedValue, flattenedStyle?.fontFamily, flattenedStyle?.fontSize, flattenedStyle?.fontStyle, flattenedStyle?.fontWeight, flattenedStyle?.fontVariant, flattenedStyle?.letterSpacing, flattenedStyle?.lineHeight, flattenedStyle?.textTransform, variant === "text" && Boolean(resolvedLeading), variant === "text" ? resolvedLeadingKey : undefined, variant === "text" ? leadingGap : 0]);
66
+ }, [leadingGap, resolvedLeading, resolvedLeadingKey, resolvedValue, textStyle, variant]);
51
67
  const {
52
68
  captureLayout,
53
- animatedWidthStyle
69
+ animatedWidthStyle,
70
+ shouldMeasure
54
71
  } = (0, _useInlineAutoWidth.useInlineAutoWidth)({
55
72
  enabled: autoSize,
56
- driveToWidth: motionRecipe.driveNumber
73
+ driveToWidth: motionRecipe.driveNumber,
74
+ measurementKey
57
75
  });
76
+ // measurement uses the same normalized units as the visible text row
58
77
  const measuredValue = _react.default.useMemo(() => {
59
78
  if (!autoSize) {
60
79
  return "";
@@ -64,17 +83,39 @@ const Laminar = exports.Laminar = /*#__PURE__*/_react.default.memo(function Lami
64
83
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_morphViewport.MorphViewport, {
65
84
  autoSize: autoSize,
66
85
  clipToBounds: clipToBounds,
86
+ align: align,
67
87
  containerStyle: containerStyle,
68
88
  animatedWidthStyle: animatedWidthStyle,
69
- measurement: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
70
- numberOfLines: 1,
89
+ measurement: shouldMeasure ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
71
90
  onLayout: captureLayout,
72
- style: textStyle,
73
- children: measuredValue
74
- }),
75
- children: variant === "number" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_numberRun.NumberRun, {
91
+ style: {
92
+ flexDirection: "row",
93
+ alignSelf: "flex-start"
94
+ },
95
+ children: [variant === "text" && resolvedLeading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
96
+ style: {
97
+ alignItems: "center",
98
+ justifyContent: "center",
99
+ marginRight: leadingGap
100
+ },
101
+ children: resolvedLeading
102
+ }) : null, (0, _displayUnits.splitDisplayUnits)(measuredValue).map((unit, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
103
+ style: textStyle,
104
+ children: (0, _displayUnits.normalizeDisplayUnit)(unit)
105
+ }, `${unit}-${index}`))]
106
+ }) : undefined,
107
+ children: variant === "slots" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_slotsRun.SlotsRun, {
108
+ value: resolvedValue,
109
+ motionRecipe: motionRecipe,
110
+ align: align,
111
+ fontSize: fontSize,
112
+ textStyle: textStyle,
113
+ staggerMs: staggerMs,
114
+ className: className
115
+ }) : variant === "number" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_numberRun.NumberRun, {
76
116
  value: resolvedValue,
77
117
  motionRecipe: motionRecipe,
118
+ align: align,
78
119
  fontSize: fontSize,
79
120
  textStyle: textStyle,
80
121
  staggerMs: staggerMs,
@@ -82,11 +123,17 @@ const Laminar = exports.Laminar = /*#__PURE__*/_react.default.memo(function Lami
82
123
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_textRun.TextRun, {
83
124
  value: resolvedValue,
84
125
  motionRecipe: motionRecipe,
126
+ align: align,
127
+ leading: resolvedLeading,
128
+ leadingKey: resolvedLeadingKey,
129
+ leadingGap: leadingGap,
85
130
  textStyle: textStyle,
86
131
  className: className
87
132
  })
88
133
  });
89
134
  });
90
- const MorphingText = exports.MorphingText = Laminar;
91
- var _default = exports.default = Laminar;
135
+ function isLeadingMap(value) {
136
+ // react elements are objects too, so exclude them before treating a value as a map
137
+ return typeof value === "object" && value !== null && ! /*#__PURE__*/_react.default.isValidElement(value) && !Array.isArray(value);
138
+ }
92
139
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_useInlineAutoWidth","_useMorphMotion","_useMorphTextStyle","_displayUnits","_morphViewport","_numberRun","_textRun","_jsxRuntime","e","__esModule","default","Laminar","exports","React","memo","text","variant","fontSize","color","className","style","containerStyle","fontStyle","animationDuration","animationPreset","stagger","autoSize","clipToBounds","resolvedValue","String","motionRecipe","staggerMs","useMorphMotion","textStyle","useMorphTextStyle","captureLayout","animatedWidthStyle","useInlineAutoWidth","enabled","driveToWidth","driveNumber","measuredValue","useMemo","splitDisplayUnits","map","normalizeDisplayUnit","join","jsx","MorphViewport","measurement","Text","numberOfLines","onLayout","children","NumberRun","value","TextRun","MorphingText","_default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_useInlineAutoWidth","_useMorphMotion","_useMorphTextStyle","_displayUnits","_morphViewport","_numberRun","_slotsRun","_textRun","_jsxRuntime","e","__esModule","default","Laminar","exports","React","memo","text","variant","fontSize","color","align","className","leading","leadingKey","leadingGap","style","containerStyle","fontStyle","animationDuration","animationPreset","stagger","autoSize","clipToBounds","resolvedValue","String","leadingMap","isLeadingMap","undefined","resolvedLeading","resolvedLeadingKey","motionRecipe","staggerMs","useMorphMotion","textStyle","useMorphTextStyle","measurementKey","useMemo","flattenedStyle","StyleSheet","flatten","JSON","stringify","fontFamily","fontWeight","fontVariant","letterSpacing","lineHeight","textTransform","Boolean","captureLayout","animatedWidthStyle","shouldMeasure","useInlineAutoWidth","enabled","driveToWidth","driveNumber","measuredValue","splitDisplayUnits","map","normalizeDisplayUnit","join","jsx","MorphViewport","measurement","jsxs","View","onLayout","flexDirection","alignSelf","children","alignItems","justifyContent","marginRight","unit","index","Text","SlotsRun","value","NumberRun","TextRun","isValidElement","Array","isArray"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -8,6 +8,8 @@ const NBSP = "\u00A0";
8
8
  const graphemeSegmenter = typeof Intl !== "undefined" && typeof Intl.Segmenter === "function" ? new Intl.Segmenter(undefined, {
9
9
  granularity: "grapheme"
10
10
  }) : null;
11
+
12
+ // segment graphemes when the runtime supports them so emoji and combining marks stay whole
11
13
  const splitDisplayUnits = input => {
12
14
  if (graphemeSegmenter) {
13
15
  return Array.from(graphemeSegmenter.segment(input), part => part.segment);
@@ -15,11 +17,15 @@ const splitDisplayUnits = input => {
15
17
  return Array.from(input);
16
18
  };
17
19
 
18
- // swap plain spaces so measured text keeps its width
20
+ // replace plain spaces because native text measurement can collapse them
19
21
  exports.splitDisplayUnits = splitDisplayUnits;
20
22
  const normalizeDisplayUnit = unit => unit === " " ? NBSP : unit;
23
+
24
+ // numeric lanes only treat ascii digits as place-value columns
21
25
  exports.normalizeDisplayUnit = normalizeDisplayUnit;
22
26
  const isAsciiDigit = unit => unit >= "0" && unit <= "9";
27
+
28
+ // leading symbols and punctuation stay attached to the left side of a number
23
29
  exports.isAsciiDigit = isAsciiDigit;
24
30
  const findNumericLeadLength = units => {
25
31
  const firstDigitIndex = units.findIndex(isAsciiDigit);
@@ -1 +1 @@
1
- {"version":3,"names":["NBSP","graphemeSegmenter","Intl","Segmenter","undefined","granularity","splitDisplayUnits","input","Array","from","segment","part","exports","normalizeDisplayUnit","unit","isAsciiDigit","findNumericLeadLength","units","firstDigitIndex","findIndex","length"],"sourceRoot":"../../../src","sources":["model/display-units.ts"],"mappings":";;;;;;AAAA,MAAMA,IAAI,GAAG,QAAQ;AACrB,MAAMC,iBAAiB,GACrB,OAAOC,IAAI,KAAK,WAAW,IAAI,OAAOA,IAAI,CAACC,SAAS,KAAK,UAAU,GAC/D,IAAID,IAAI,CAACC,SAAS,CAACC,SAAS,EAAE;EAAEC,WAAW,EAAE;AAAW,CAAC,CAAC,GAC1D,IAAI;AAEH,MAAMC,iBAAiB,GAAIC,KAAa,IAAe;EAC5D,IAAIN,iBAAiB,EAAE;IACrB,OAAOO,KAAK,CAACC,IAAI,CACfR,iBAAiB,CAACS,OAAO,CAACH,KAAK,CAAC,EAC/BI,IAAI,IAAKA,IAAI,CAACD,OACjB,CAAC;EACH;EAEA,OAAOF,KAAK,CAACC,IAAI,CAACF,KAAK,CAAC;AAC1B,CAAC;;AAED;AAAAK,OAAA,CAAAN,iBAAA,GAAAA,iBAAA;AACO,MAAMO,oBAAoB,GAAIC,IAAY,IAC/CA,IAAI,KAAK,GAAG,GAAGd,IAAI,GAAGc,IAAI;AAACF,OAAA,CAAAC,oBAAA,GAAAA,oBAAA;AAEtB,MAAME,YAAY,GAAID,IAAY,IAAKA,IAAI,IAAI,GAAG,IAAIA,IAAI,IAAI,GAAG;AAACF,OAAA,CAAAG,YAAA,GAAAA,YAAA;AAElE,MAAMC,qBAAqB,GAAIC,KAAwB,IAAK;EACjE,MAAMC,eAAe,GAAGD,KAAK,CAACE,SAAS,CAACJ,YAAY,CAAC;EAErD,OAAOG,eAAe,KAAK,CAAC,CAAC,GAAGD,KAAK,CAACG,MAAM,GAAGF,eAAe;AAChE,CAAC;AAACN,OAAA,CAAAI,qBAAA,GAAAA,qBAAA","ignoreList":[]}
1
+ {"version":3,"names":["NBSP","graphemeSegmenter","Intl","Segmenter","undefined","granularity","splitDisplayUnits","input","Array","from","segment","part","exports","normalizeDisplayUnit","unit","isAsciiDigit","findNumericLeadLength","units","firstDigitIndex","findIndex","length"],"sourceRoot":"../../../src","sources":["model/display-units.ts"],"mappings":";;;;;;AAAA,MAAMA,IAAI,GAAG,QAAQ;AACrB,MAAMC,iBAAiB,GACrB,OAAOC,IAAI,KAAK,WAAW,IAAI,OAAOA,IAAI,CAACC,SAAS,KAAK,UAAU,GAC/D,IAAID,IAAI,CAACC,SAAS,CAACC,SAAS,EAAE;EAAEC,WAAW,EAAE;AAAW,CAAC,CAAC,GAC1D,IAAI;;AAEV;AACO,MAAMC,iBAAiB,GAAIC,KAAa,IAAe;EAC5D,IAAIN,iBAAiB,EAAE;IACrB,OAAOO,KAAK,CAACC,IAAI,CACfR,iBAAiB,CAACS,OAAO,CAACH,KAAK,CAAC,EAC/BI,IAAI,IAAKA,IAAI,CAACD,OACjB,CAAC;EACH;EAEA,OAAOF,KAAK,CAACC,IAAI,CAACF,KAAK,CAAC;AAC1B,CAAC;;AAED;AAAAK,OAAA,CAAAN,iBAAA,GAAAA,iBAAA;AACO,MAAMO,oBAAoB,GAAIC,IAAY,IAC/CA,IAAI,KAAK,GAAG,GAAGd,IAAI,GAAGc,IAAI;;AAE5B;AAAAF,OAAA,CAAAC,oBAAA,GAAAA,oBAAA;AACO,MAAME,YAAY,GAAID,IAAY,IAAKA,IAAI,IAAI,GAAG,IAAIA,IAAI,IAAI,GAAG;;AAExE;AAAAF,OAAA,CAAAG,YAAA,GAAAA,YAAA;AACO,MAAMC,qBAAqB,GAAIC,KAAwB,IAAK;EACjE,MAAMC,eAAe,GAAGD,KAAK,CAACE,SAAS,CAACJ,YAAY,CAAC;EAErD,OAAOG,eAAe,KAAK,CAAC,CAAC,GAAGD,KAAK,CAACG,MAAM,GAAGF,eAAe;AAChE,CAAC;AAACN,OAAA,CAAAI,qBAAA,GAAAA,qBAAA","ignoreList":[]}
@@ -5,8 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.reconcileNumericLanes = void 0;
7
7
  var _displayUnits = require("./display-units");
8
+ // strip formatting before comparing values so direction follows the displayed number
8
9
  const readNumericMagnitude = input => parseFloat(input.replace(/[^0-9.-]/g, "")) || 0;
10
+
11
+ // the sign controls which side of each digit lane enters and exits
9
12
  const deriveFlowDirection = (previousValue, nextValue) => Math.sign(readNumericMagnitude(nextValue) - readNumericMagnitude(previousValue));
13
+ // preserve right-aligned place values while allowing prefixes to grow or shrink
10
14
  const reconcileNumericLanes = (previousValue, nextValue, previousKeys, seed) => {
11
15
  const previousUnits = (0, _displayUnits.splitDisplayUnits)(previousValue);
12
16
  const nextUnits = (0, _displayUnits.splitDisplayUnits)(nextValue);
@@ -1 +1 @@
1
- {"version":3,"names":["_displayUnits","require","readNumericMagnitude","input","parseFloat","replace","deriveFlowDirection","previousValue","nextValue","Math","sign","reconcileNumericLanes","previousKeys","seed","previousUnits","splitDisplayUnits","nextUnits","nextLaneKeys","Array","length","nextSeed","nextLeadLength","findNumericLeadLength","previousLeadLength","sharedLeadLength","min","index","previousTailUnits","slice","nextTailUnits","previousTailKeys","laneCount","max","leftPaddedPreviousUnits","fill","leftPaddedNextUnits","leftPaddedPreviousKeys","nextTailOffset","paddedIndex","nextUnit","previousUnit","previousKey","laneKeys","direction","exports"],"sourceRoot":"../../../src","sources":["model/numeric-lanes.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_displayUnits","require","readNumericMagnitude","input","parseFloat","replace","deriveFlowDirection","previousValue","nextValue","Math","sign","reconcileNumericLanes","previousKeys","seed","previousUnits","splitDisplayUnits","nextUnits","nextLaneKeys","Array","length","nextSeed","nextLeadLength","findNumericLeadLength","previousLeadLength","sharedLeadLength","min","index","previousTailUnits","slice","nextTailUnits","previousTailKeys","laneCount","max","leftPaddedPreviousUnits","fill","leftPaddedNextUnits","leftPaddedPreviousKeys","nextTailOffset","paddedIndex","nextUnit","previousUnit","previousKey","laneKeys","direction","exports"],"sourceRoot":"../../../src","sources":["model/numeric-lanes.ts"],"mappings":"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","ignoreList":[]}
@@ -4,12 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.reconcileTextGlyphKeys = void 0;
7
+ // find the longest ordered set of shared units so edits keep nearby glyph identity
7
8
  const computeLcsPairs = (previousUnits, nextUnits) => {
8
9
  const previousLength = previousUnits.length;
9
10
  const nextLength = nextUnits.length;
10
11
  if (previousLength === 0 || nextLength === 0) {
11
12
  return [];
12
13
  }
14
+
15
+ // dynamic programming makes the middle edit deterministic when prefix and suffix match
13
16
  const dp = Array.from({
14
17
  length: previousLength + 1
15
18
  }, () => new Array(nextLength + 1).fill(0));
@@ -37,6 +40,7 @@ const computeLcsPairs = (previousUnits, nextUnits) => {
37
40
  pairs.reverse();
38
41
  return pairs;
39
42
  };
43
+ // reuse prefix, suffix, and lcs matches before allocating keys for new glyphs
40
44
  const reconcileTextGlyphKeys = (previousUnits, nextUnits, previousKeys, seed, namespace) => {
41
45
  const previousLength = previousUnits.length;
42
46
  const nextLength = nextUnits.length;