react-native-laminar 1.4.2 → 1.4.4
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/lib/commonjs/hooks/use-inline-auto-width.js +105 -18
- package/lib/commonjs/hooks/use-inline-auto-width.js.map +1 -1
- package/lib/commonjs/hooks/use-text-glyphs.js +24 -21
- package/lib/commonjs/hooks/use-text-glyphs.js.map +1 -1
- package/lib/commonjs/index.js +6 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/view/glyph-run.js +38 -19
- package/lib/commonjs/view/glyph-run.js.map +1 -1
- package/lib/commonjs/view/morph-viewport.js +2 -0
- package/lib/commonjs/view/morph-viewport.js.map +1 -1
- package/lib/commonjs/view/text-run.js +34 -12
- package/lib/commonjs/view/text-run.js.map +1 -1
- package/lib/module/hooks/use-inline-auto-width.js +106 -19
- package/lib/module/hooks/use-inline-auto-width.js.map +1 -1
- package/lib/module/hooks/use-text-glyphs.js +24 -21
- package/lib/module/hooks/use-text-glyphs.js.map +1 -1
- package/lib/module/index.js +6 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/view/glyph-run.js +39 -20
- package/lib/module/view/glyph-run.js.map +1 -1
- package/lib/module/view/morph-viewport.js +2 -0
- package/lib/module/view/morph-viewport.js.map +1 -1
- package/lib/module/view/text-run.js +34 -12
- package/lib/module/view/text-run.js.map +1 -1
- package/lib/typescript/commonjs/hooks/use-inline-auto-width.d.ts +2 -0
- package/lib/typescript/commonjs/hooks/use-inline-auto-width.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/use-text-glyphs.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/view/glyph-run.d.ts +3 -1
- package/lib/typescript/commonjs/view/glyph-run.d.ts.map +1 -1
- package/lib/typescript/commonjs/view/morph-viewport.d.ts +3 -2
- package/lib/typescript/commonjs/view/morph-viewport.d.ts.map +1 -1
- package/lib/typescript/commonjs/view/text-run.d.ts +3 -1
- package/lib/typescript/commonjs/view/text-run.d.ts.map +1 -1
- package/lib/typescript/module/hooks/use-inline-auto-width.d.ts +2 -0
- package/lib/typescript/module/hooks/use-inline-auto-width.d.ts.map +1 -1
- package/lib/typescript/module/hooks/use-text-glyphs.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/view/glyph-run.d.ts +3 -1
- package/lib/typescript/module/view/glyph-run.d.ts.map +1 -1
- package/lib/typescript/module/view/morph-viewport.d.ts +3 -2
- package/lib/typescript/module/view/morph-viewport.d.ts.map +1 -1
- package/lib/typescript/module/view/text-run.d.ts +3 -1
- package/lib/typescript/module/view/text-run.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/hooks/use-inline-auto-width.ts +160 -18
- package/src/hooks/use-text-glyphs.ts +35 -28
- package/src/index.tsx +11 -1
- package/src/view/glyph-run.tsx +62 -33
- package/src/view/morph-viewport.tsx +7 -2
- package/src/view/text-run.tsx +59 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useId","useLayoutEffect","useMemo","useRef","useSharedValue","useTextGlyphs","createLeadingEnterTransition","createLeadingExitTransition","GlyphRun","jsx","_jsx","TextRun","memo","value","motionRecipe","align","leading","leadingKey","leadingGap","textStyle","className","scopeId","lastValueRef","lastLeadingPresenceRef","Boolean","lastLeadingKeyRef","hasAnimatedRef","isLeadingSwap","
|
|
1
|
+
{"version":3,"names":["React","useId","useLayoutEffect","useMemo","useRef","useSharedValue","useTextGlyphs","createLeadingEnterTransition","createLeadingExitTransition","GlyphRun","jsx","_jsx","TextRun","memo","value","motionRecipe","align","leading","leadingLayoutGroup","leadingKey","leadingGap","ready","textStyle","className","scopeId","hasDisplayedRef","displayedValueRef","displayedLeadingRef","displayedLeadingKeyRef","displayedLeadingGapRef","shouldDisplayTarget","current","visibleValue","visibleLeading","visibleLeadingKey","visibleLeadingGap","lastValueRef","lastLeadingPresenceRef","Boolean","lastLeadingKeyRef","hasAnimatedRef","isLeadingSwap","isLeadingChange","leadingSwapProgress","glyphs","elementEnterTransition","durationMs","easing","elementExitTransition","scale","hasAnimated","layoutTransition","undefined","leadingLayoutTransition","enterTransition","exitTransition","displayName"],"sourceRoot":"../../../src","sources":["view/text-run.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -6,11 +6,13 @@ type Params = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare const useInlineAutoWidth: ({ enabled, driveToWidth, measurementKey, }: Params) => {
|
|
8
8
|
captureLayout: (event: LayoutChangeEvent) => void;
|
|
9
|
+
captureVisibleLayout: (event: LayoutChangeEvent) => void;
|
|
9
10
|
animatedWidthStyle: {
|
|
10
11
|
width: number;
|
|
11
12
|
} | {
|
|
12
13
|
width?: undefined;
|
|
13
14
|
};
|
|
15
|
+
isReady: boolean;
|
|
14
16
|
shouldMeasure: boolean;
|
|
15
17
|
};
|
|
16
18
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-inline-auto-width.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-inline-auto-width.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-inline-auto-width.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-inline-auto-width.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,KAAK,MAAM,GAAG;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAUF,eAAO,MAAM,kBAAkB,GAAI,4CAIhC,MAAM;2BAyGG,iBAAiB;kCAlCjB,iBAAiB;;;;;;;;CA8I5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-text-glyphs.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-text-glyphs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"use-text-glyphs.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-text-glyphs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAgB3C,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,EACb,WAAW,MAAM,EACjB,UAAU,SAAS,EACnB,aAAa,MAAM,GAAG,MAAM,KAC3B,SAAS,UAAU,EAyErB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAOpE,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAOpE,eAAO,MAAM,OAAO,yDA+JhB,CAAC;AAcL,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
|
|
@@ -2,9 +2,11 @@ import React from "react";
|
|
|
2
2
|
import { type StyleProp, type TextStyle } from "react-native";
|
|
3
3
|
import type { ComplexAnimationBuilder, EntryExitAnimationFunction } from "react-native-reanimated";
|
|
4
4
|
import type { GlyphToken, LaminarAlign } from "../types";
|
|
5
|
-
export declare const GlyphRun: React.MemoExoticComponent<({ glyphs, layoutTransition, enterTransition, elementEnterTransition, exitTransition, elementExitTransition, leadingGap, align, textStyle, className, }: Readonly<{
|
|
5
|
+
export declare const GlyphRun: React.MemoExoticComponent<({ glyphs, layoutTransition, leadingLayoutTransition, leadingLayoutGroup, enterTransition, elementEnterTransition, exitTransition, elementExitTransition, leadingGap, align, textStyle, className, }: Readonly<{
|
|
6
6
|
glyphs: readonly GlyphToken[];
|
|
7
7
|
layoutTransition?: ComplexAnimationBuilder;
|
|
8
|
+
leadingLayoutTransition?: ComplexAnimationBuilder;
|
|
9
|
+
leadingLayoutGroup?: boolean;
|
|
8
10
|
enterTransition?: EntryExitAnimationFunction;
|
|
9
11
|
elementEnterTransition?: EntryExitAnimationFunction;
|
|
10
12
|
exitTransition?: EntryExitAnimationFunction;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glyph-run.d.ts","sourceRoot":"","sources":["../../../../src/view/glyph-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"glyph-run.d.ts","sourceRoot":"","sources":["../../../../src/view/glyph-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAqBzD,eAAO,MAAM,QAAQ,kOAchB,QAAQ,CAAC;IACV,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,0BAA0B,CAAC;IAC7C,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,cAAc,CAAC,EAAE,0BAA0B,CAAC;IAC5C,qBAAqB,CAAC,EAAE,0BAA0B,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,uBAsDH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { StyleProp, ViewStyle } from "react-native";
|
|
2
|
+
import type { LayoutChangeEvent, StyleProp, ViewStyle } from "react-native";
|
|
3
3
|
import Animated from "react-native-reanimated";
|
|
4
4
|
import type { LaminarAlign } from "../types";
|
|
5
5
|
type MorphViewportProps = {
|
|
@@ -8,9 +8,10 @@ type MorphViewportProps = {
|
|
|
8
8
|
readonly align: LaminarAlign;
|
|
9
9
|
readonly containerStyle?: StyleProp<ViewStyle>;
|
|
10
10
|
readonly animatedWidthStyle?: React.ComponentProps<typeof Animated.View>["style"];
|
|
11
|
+
readonly onVisibleLayout?: (event: LayoutChangeEvent) => void;
|
|
11
12
|
readonly measurement?: React.ReactNode;
|
|
12
13
|
readonly children: React.ReactNode;
|
|
13
14
|
};
|
|
14
|
-
export declare const MorphViewport: React.MemoExoticComponent<({ autoSize, clipToBounds, align, containerStyle, animatedWidthStyle, measurement, children, }: MorphViewportProps) => React.JSX.Element>;
|
|
15
|
+
export declare const MorphViewport: React.MemoExoticComponent<({ autoSize, clipToBounds, align, containerStyle, animatedWidthStyle, onVisibleLayout, measurement, children, }: MorphViewportProps) => React.JSX.Element>;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=morph-viewport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"morph-viewport.d.ts","sourceRoot":"","sources":["../../../../src/view/morph-viewport.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"morph-viewport.d.ts","sourceRoot":"","sources":["../../../../src/view/morph-viewport.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA4C7C,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IAClF,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC,CAAC;AAGF,eAAO,MAAM,aAAa,6IAUrB,kBAAkB,uBAwCtB,CAAC"}
|
|
@@ -7,11 +7,13 @@ type TextRunProps = {
|
|
|
7
7
|
readonly motionRecipe: MotionRecipe;
|
|
8
8
|
readonly align: LaminarAlign;
|
|
9
9
|
readonly leading?: ReactNode;
|
|
10
|
+
readonly leadingLayoutGroup?: boolean;
|
|
10
11
|
readonly leadingKey?: string | number;
|
|
11
12
|
readonly leadingGap?: number;
|
|
13
|
+
readonly ready?: boolean;
|
|
12
14
|
readonly textStyle?: StyleProp<TextStyle>;
|
|
13
15
|
readonly className?: string;
|
|
14
16
|
};
|
|
15
|
-
export declare const TextRun: React.MemoExoticComponent<({ value, motionRecipe, align, leading, leadingKey, leadingGap, textStyle, className, }: TextRunProps) => React.JSX.Element>;
|
|
17
|
+
export declare const TextRun: React.MemoExoticComponent<({ value, motionRecipe, align, leading, leadingLayoutGroup, leadingKey, leadingGap, ready, textStyle, className, }: TextRunProps) => React.JSX.Element>;
|
|
16
18
|
export {};
|
|
17
19
|
//# sourceMappingURL=text-run.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-run.d.ts","sourceRoot":"","sources":["../../../../src/view/text-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG3D,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAGF,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"text-run.d.ts","sourceRoot":"","sources":["../../../../src/view/text-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG3D,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAGF,eAAO,MAAM,OAAO,gJAYf,YAAY,uBAsHhB,CAAC"}
|
|
@@ -6,11 +6,13 @@ type Params = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare const useInlineAutoWidth: ({ enabled, driveToWidth, measurementKey, }: Params) => {
|
|
8
8
|
captureLayout: (event: LayoutChangeEvent) => void;
|
|
9
|
+
captureVisibleLayout: (event: LayoutChangeEvent) => void;
|
|
9
10
|
animatedWidthStyle: {
|
|
10
11
|
width: number;
|
|
11
12
|
} | {
|
|
12
13
|
width?: undefined;
|
|
13
14
|
};
|
|
15
|
+
isReady: boolean;
|
|
14
16
|
shouldMeasure: boolean;
|
|
15
17
|
};
|
|
16
18
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-inline-auto-width.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-inline-auto-width.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-inline-auto-width.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-inline-auto-width.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,KAAK,MAAM,GAAG;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAUF,eAAO,MAAM,kBAAkB,GAAI,4CAIhC,MAAM;2BAyGG,iBAAiB;kCAlCjB,iBAAiB;;;;;;;;CA8I5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-text-glyphs.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-text-glyphs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"use-text-glyphs.d.ts","sourceRoot":"","sources":["../../../../src/hooks/use-text-glyphs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAgB3C,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,EACb,WAAW,MAAM,EACjB,UAAU,SAAS,EACnB,aAAa,MAAM,GAAG,MAAM,KAC3B,SAAS,UAAU,EAyErB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAOpE,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAOpE,eAAO,MAAM,OAAO,yDA+JhB,CAAC;AAcL,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
|
|
@@ -2,9 +2,11 @@ import React from "react";
|
|
|
2
2
|
import { type StyleProp, type TextStyle } from "react-native";
|
|
3
3
|
import type { ComplexAnimationBuilder, EntryExitAnimationFunction } from "react-native-reanimated";
|
|
4
4
|
import type { GlyphToken, LaminarAlign } from "../types";
|
|
5
|
-
export declare const GlyphRun: React.MemoExoticComponent<({ glyphs, layoutTransition, enterTransition, elementEnterTransition, exitTransition, elementExitTransition, leadingGap, align, textStyle, className, }: Readonly<{
|
|
5
|
+
export declare const GlyphRun: React.MemoExoticComponent<({ glyphs, layoutTransition, leadingLayoutTransition, leadingLayoutGroup, enterTransition, elementEnterTransition, exitTransition, elementExitTransition, leadingGap, align, textStyle, className, }: Readonly<{
|
|
6
6
|
glyphs: readonly GlyphToken[];
|
|
7
7
|
layoutTransition?: ComplexAnimationBuilder;
|
|
8
|
+
leadingLayoutTransition?: ComplexAnimationBuilder;
|
|
9
|
+
leadingLayoutGroup?: boolean;
|
|
8
10
|
enterTransition?: EntryExitAnimationFunction;
|
|
9
11
|
elementEnterTransition?: EntryExitAnimationFunction;
|
|
10
12
|
exitTransition?: EntryExitAnimationFunction;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glyph-run.d.ts","sourceRoot":"","sources":["../../../../src/view/glyph-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"glyph-run.d.ts","sourceRoot":"","sources":["../../../../src/view/glyph-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAQ,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EACV,uBAAuB,EACvB,0BAA0B,EAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAqBzD,eAAO,MAAM,QAAQ,kOAchB,QAAQ,CAAC;IACV,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,0BAA0B,CAAC;IAC7C,sBAAsB,CAAC,EAAE,0BAA0B,CAAC;IACpD,cAAc,CAAC,EAAE,0BAA0B,CAAC;IAC5C,qBAAqB,CAAC,EAAE,0BAA0B,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,uBAsDH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { StyleProp, ViewStyle } from "react-native";
|
|
2
|
+
import type { LayoutChangeEvent, StyleProp, ViewStyle } from "react-native";
|
|
3
3
|
import Animated from "react-native-reanimated";
|
|
4
4
|
import type { LaminarAlign } from "../types";
|
|
5
5
|
type MorphViewportProps = {
|
|
@@ -8,9 +8,10 @@ type MorphViewportProps = {
|
|
|
8
8
|
readonly align: LaminarAlign;
|
|
9
9
|
readonly containerStyle?: StyleProp<ViewStyle>;
|
|
10
10
|
readonly animatedWidthStyle?: React.ComponentProps<typeof Animated.View>["style"];
|
|
11
|
+
readonly onVisibleLayout?: (event: LayoutChangeEvent) => void;
|
|
11
12
|
readonly measurement?: React.ReactNode;
|
|
12
13
|
readonly children: React.ReactNode;
|
|
13
14
|
};
|
|
14
|
-
export declare const MorphViewport: React.MemoExoticComponent<({ autoSize, clipToBounds, align, containerStyle, animatedWidthStyle, measurement, children, }: MorphViewportProps) => React.JSX.Element>;
|
|
15
|
+
export declare const MorphViewport: React.MemoExoticComponent<({ autoSize, clipToBounds, align, containerStyle, animatedWidthStyle, onVisibleLayout, measurement, children, }: MorphViewportProps) => React.JSX.Element>;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=morph-viewport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"morph-viewport.d.ts","sourceRoot":"","sources":["../../../../src/view/morph-viewport.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"morph-viewport.d.ts","sourceRoot":"","sources":["../../../../src/view/morph-viewport.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA4C7C,KAAK,kBAAkB,GAAG;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IAClF,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC,CAAC;AAGF,eAAO,MAAM,aAAa,6IAUrB,kBAAkB,uBAwCtB,CAAC"}
|
|
@@ -7,11 +7,13 @@ type TextRunProps = {
|
|
|
7
7
|
readonly motionRecipe: MotionRecipe;
|
|
8
8
|
readonly align: LaminarAlign;
|
|
9
9
|
readonly leading?: ReactNode;
|
|
10
|
+
readonly leadingLayoutGroup?: boolean;
|
|
10
11
|
readonly leadingKey?: string | number;
|
|
11
12
|
readonly leadingGap?: number;
|
|
13
|
+
readonly ready?: boolean;
|
|
12
14
|
readonly textStyle?: StyleProp<TextStyle>;
|
|
13
15
|
readonly className?: string;
|
|
14
16
|
};
|
|
15
|
-
export declare const TextRun: React.MemoExoticComponent<({ value, motionRecipe, align, leading, leadingKey, leadingGap, textStyle, className, }: TextRunProps) => React.JSX.Element>;
|
|
17
|
+
export declare const TextRun: React.MemoExoticComponent<({ value, motionRecipe, align, leading, leadingLayoutGroup, leadingKey, leadingGap, ready, textStyle, className, }: TextRunProps) => React.JSX.Element>;
|
|
16
18
|
export {};
|
|
17
19
|
//# sourceMappingURL=text-run.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-run.d.ts","sourceRoot":"","sources":["../../../../src/view/text-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG3D,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAGF,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"text-run.d.ts","sourceRoot":"","sources":["../../../../src/view/text-run.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOzD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG3D,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAGF,eAAO,MAAM,OAAO,gJAYf,YAAY,uBAsHhB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useCallback,
|
|
3
|
+
useEffect,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
2
8
|
import type { LayoutChangeEvent } from "react-native";
|
|
3
9
|
import { useAnimatedStyle, useSharedValue } from "react-native-reanimated";
|
|
4
10
|
|
|
@@ -8,6 +14,11 @@ type Params = {
|
|
|
8
14
|
measurementKey: string;
|
|
9
15
|
};
|
|
10
16
|
|
|
17
|
+
type PendingProbe = {
|
|
18
|
+
key: string;
|
|
19
|
+
width: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
11
22
|
const WIDTH_CACHE_LIMIT = 64;
|
|
12
23
|
|
|
13
24
|
// measure each content signature once and drive later changes through one width value
|
|
@@ -17,10 +28,24 @@ export const useInlineAutoWidth = ({
|
|
|
17
28
|
measurementKey,
|
|
18
29
|
}: Params) => {
|
|
19
30
|
const widthValue = useSharedValue(0);
|
|
31
|
+
const hasBootstrappedWidth = useSharedValue(false);
|
|
20
32
|
const measuredWidthRef = useRef<number | null>(null);
|
|
21
33
|
const bootstrappedRef = useRef(false);
|
|
22
34
|
const widthCacheRef = useRef(new Map<string, number>());
|
|
23
|
-
const
|
|
35
|
+
const hasCapturedVisibleLayoutRef = useRef(false);
|
|
36
|
+
const initialMeasurementKeyRef = useRef<string | null>(null);
|
|
37
|
+
const firstProbeRef = useRef<PendingProbe | null>(null);
|
|
38
|
+
const latestProbeRef = useRef<PendingProbe | null>(null);
|
|
39
|
+
const bootstrapTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
40
|
+
const [readyMeasurementKey, setReadyMeasurementKey] = useState<string | null>(
|
|
41
|
+
null
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const markMeasurementReady = useCallback((key: string) => {
|
|
45
|
+
setReadyMeasurementKey((currentKey) =>
|
|
46
|
+
currentKey === key ? currentKey : key
|
|
47
|
+
);
|
|
48
|
+
}, []);
|
|
24
49
|
|
|
25
50
|
// the first measurement establishes the shell without animating from zero
|
|
26
51
|
const applyWidth = useCallback(
|
|
@@ -34,7 +59,7 @@ export const useInlineAutoWidth = ({
|
|
|
34
59
|
if (!bootstrappedRef.current) {
|
|
35
60
|
bootstrappedRef.current = true;
|
|
36
61
|
widthValue.value = nextWidth;
|
|
37
|
-
|
|
62
|
+
hasBootstrappedWidth.value = true;
|
|
38
63
|
return;
|
|
39
64
|
}
|
|
40
65
|
|
|
@@ -43,6 +68,68 @@ export const useInlineAutoWidth = ({
|
|
|
43
68
|
[driveToWidth, widthValue]
|
|
44
69
|
);
|
|
45
70
|
|
|
71
|
+
const bootstrapFromProbe = useCallback(() => {
|
|
72
|
+
bootstrapTimerRef.current = null;
|
|
73
|
+
|
|
74
|
+
if (hasCapturedVisibleLayoutRef.current) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const firstProbe = firstProbeRef.current;
|
|
79
|
+
if (!firstProbe) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// The visible layout did not arrive in time, so use the first probe as a
|
|
84
|
+
// safe fallback. A later probe can still animate from this baseline.
|
|
85
|
+
hasCapturedVisibleLayoutRef.current = true;
|
|
86
|
+
initialMeasurementKeyRef.current = firstProbe.key;
|
|
87
|
+
applyWidth(firstProbe.width);
|
|
88
|
+
|
|
89
|
+
const latestProbe = latestProbeRef.current;
|
|
90
|
+
if (latestProbe && latestProbe.key !== firstProbe.key) {
|
|
91
|
+
// The target width is already cached. Defer its animation until the
|
|
92
|
+
// ready render so the shell and the new glyph row start together.
|
|
93
|
+
markMeasurementReady(latestProbe.key);
|
|
94
|
+
} else {
|
|
95
|
+
markMeasurementReady(firstProbe.key);
|
|
96
|
+
}
|
|
97
|
+
}, [applyWidth, markMeasurementReady]);
|
|
98
|
+
|
|
99
|
+
const captureVisibleLayout = useCallback(
|
|
100
|
+
(event: LayoutChangeEvent) => {
|
|
101
|
+
if (!enabled || hasCapturedVisibleLayoutRef.current) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (bootstrapTimerRef.current !== null) {
|
|
106
|
+
clearTimeout(bootstrapTimerRef.current);
|
|
107
|
+
bootstrapTimerRef.current = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
hasCapturedVisibleLayoutRef.current = true;
|
|
111
|
+
// bootstrap from the visible tree so the first explicit width matches
|
|
112
|
+
// the geometry that was already painted to the user
|
|
113
|
+
const nextWidth = Math.max(0, event.nativeEvent.layout.width);
|
|
114
|
+
// retain the visible width for the initial key so a later cache hit does
|
|
115
|
+
// not reintroduce the probe-to-visible mismatch
|
|
116
|
+
widthCacheRef.current.delete(measurementKey);
|
|
117
|
+
widthCacheRef.current.set(measurementKey, nextWidth);
|
|
118
|
+
const firstProbe = firstProbeRef.current;
|
|
119
|
+
if (firstProbe && firstProbe.key !== measurementKey) {
|
|
120
|
+
initialMeasurementKeyRef.current = firstProbe.key;
|
|
121
|
+
applyWidth(firstProbe.width);
|
|
122
|
+
markMeasurementReady(measurementKey);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
initialMeasurementKeyRef.current = measurementKey;
|
|
127
|
+
applyWidth(nextWidth);
|
|
128
|
+
markMeasurementReady(measurementKey);
|
|
129
|
+
},
|
|
130
|
+
[applyWidth, enabled, markMeasurementReady, measurementKey]
|
|
131
|
+
);
|
|
132
|
+
|
|
46
133
|
const captureLayout = useCallback(
|
|
47
134
|
(event: LayoutChangeEvent) => {
|
|
48
135
|
if (!enabled) {
|
|
@@ -52,49 +139,104 @@ export const useInlineAutoWidth = ({
|
|
|
52
139
|
// round up so fractional native measurements cannot clip the final glyph
|
|
53
140
|
const nextWidth = Math.max(0, Math.ceil(event.nativeEvent.layout.width));
|
|
54
141
|
|
|
55
|
-
|
|
56
|
-
|
|
142
|
+
const isInitialMeasurement =
|
|
143
|
+
initialMeasurementKeyRef.current === measurementKey;
|
|
144
|
+
|
|
145
|
+
if (!isInitialMeasurement) {
|
|
146
|
+
// delete before setting so a repeated key moves to the most recent position
|
|
147
|
+
widthCacheRef.current.delete(measurementKey);
|
|
57
148
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
149
|
+
if (widthCacheRef.current.size >= WIDTH_CACHE_LIMIT) {
|
|
150
|
+
// map insertion order gives the lru entry at the front
|
|
151
|
+
const oldestKey = widthCacheRef.current.keys().next().value;
|
|
61
152
|
|
|
62
|
-
|
|
63
|
-
|
|
153
|
+
if (oldestKey !== undefined) {
|
|
154
|
+
widthCacheRef.current.delete(oldestKey);
|
|
155
|
+
}
|
|
64
156
|
}
|
|
157
|
+
|
|
158
|
+
widthCacheRef.current.set(measurementKey, nextWidth);
|
|
65
159
|
}
|
|
66
160
|
|
|
67
|
-
|
|
68
|
-
|
|
161
|
+
const probe = { key: measurementKey, width: nextWidth };
|
|
162
|
+
if (!firstProbeRef.current) {
|
|
163
|
+
firstProbeRef.current = probe;
|
|
164
|
+
}
|
|
165
|
+
latestProbeRef.current = probe;
|
|
166
|
+
|
|
167
|
+
if (
|
|
168
|
+
!hasCapturedVisibleLayoutRef.current &&
|
|
169
|
+
bootstrapTimerRef.current === null
|
|
170
|
+
) {
|
|
171
|
+
bootstrapTimerRef.current = setTimeout(bootstrapFromProbe, 0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Do not let the initial probe override the visible first frame.
|
|
175
|
+
if (hasCapturedVisibleLayoutRef.current && !isInitialMeasurement) {
|
|
176
|
+
// captureLayout only records the target. The cache effect applies the
|
|
177
|
+
// animation during the render that releases the new glyph row.
|
|
178
|
+
markMeasurementReady(measurementKey);
|
|
179
|
+
}
|
|
69
180
|
},
|
|
70
|
-
[
|
|
181
|
+
[
|
|
182
|
+
applyWidth,
|
|
183
|
+
bootstrapFromProbe,
|
|
184
|
+
enabled,
|
|
185
|
+
markMeasurementReady,
|
|
186
|
+
measurementKey,
|
|
187
|
+
]
|
|
71
188
|
);
|
|
72
189
|
|
|
73
190
|
const cachedWidth = widthCacheRef.current.get(measurementKey);
|
|
74
191
|
|
|
75
192
|
// a cached width can restore the shell before the hidden probe renders again
|
|
76
|
-
|
|
77
|
-
if (
|
|
193
|
+
useLayoutEffect(() => {
|
|
194
|
+
if (
|
|
195
|
+
enabled &&
|
|
196
|
+
cachedWidth !== undefined &&
|
|
197
|
+
hasCapturedVisibleLayoutRef.current
|
|
198
|
+
) {
|
|
78
199
|
// promote cache hits so active states stay available longer
|
|
79
200
|
widthCacheRef.current.delete(measurementKey);
|
|
80
201
|
widthCacheRef.current.set(measurementKey, cachedWidth);
|
|
81
202
|
applyWidth(cachedWidth);
|
|
203
|
+
markMeasurementReady(measurementKey);
|
|
82
204
|
}
|
|
83
|
-
}, [
|
|
205
|
+
}, [
|
|
206
|
+
applyWidth,
|
|
207
|
+
cachedWidth,
|
|
208
|
+
enabled,
|
|
209
|
+
markMeasurementReady,
|
|
210
|
+
measurementKey,
|
|
211
|
+
]);
|
|
212
|
+
|
|
213
|
+
useEffect(
|
|
214
|
+
() => () => {
|
|
215
|
+
if (bootstrapTimerRef.current !== null) {
|
|
216
|
+
clearTimeout(bootstrapTimerRef.current);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
[]
|
|
220
|
+
);
|
|
84
221
|
|
|
85
222
|
const animatedWidthStyle = useAnimatedStyle(
|
|
86
223
|
() =>
|
|
87
|
-
enabled && hasBootstrappedWidth
|
|
224
|
+
enabled && hasBootstrappedWidth.value
|
|
88
225
|
? {
|
|
89
226
|
width: widthValue.value,
|
|
90
227
|
}
|
|
91
228
|
: {},
|
|
92
|
-
[enabled
|
|
229
|
+
[enabled]
|
|
93
230
|
);
|
|
94
231
|
|
|
95
232
|
return {
|
|
96
233
|
captureLayout,
|
|
234
|
+
captureVisibleLayout,
|
|
97
235
|
animatedWidthStyle,
|
|
236
|
+
isReady:
|
|
237
|
+
!enabled ||
|
|
238
|
+
cachedWidth !== undefined ||
|
|
239
|
+
readyMeasurementKey === measurementKey,
|
|
98
240
|
shouldMeasure: enabled && cachedWidth === undefined,
|
|
99
241
|
};
|
|
100
242
|
};
|
|
@@ -13,43 +13,37 @@ type TextGlyphLedger = {
|
|
|
13
13
|
nextSeed: number;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
type TextGlyphUnit =
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
type TextGlyphUnit = {
|
|
17
|
+
readonly kind: "text";
|
|
18
|
+
readonly signature: string;
|
|
19
|
+
readonly value: string;
|
|
20
|
+
};
|
|
19
21
|
|
|
20
|
-
// build
|
|
22
|
+
// build text glyphs independently, then prepend a separately keyed leading token
|
|
21
23
|
export const useTextGlyphs = (
|
|
22
24
|
value: string,
|
|
23
25
|
namespace: string,
|
|
24
26
|
leading?: ReactNode,
|
|
25
27
|
leadingKey?: string | number
|
|
26
28
|
): readonly GlyphToken[] => {
|
|
27
|
-
|
|
29
|
+
// Reconcile text independently so inserting/removing a leading token cannot
|
|
30
|
+
// change which repeated text glyphs the LCS ledger preserves.
|
|
31
|
+
const textUnits = useMemo<readonly TextGlyphUnit[]>(
|
|
28
32
|
() => [
|
|
29
|
-
// the map key becomes the identity when leading content is state keyed
|
|
30
|
-
...(leading
|
|
31
|
-
? [
|
|
32
|
-
{
|
|
33
|
-
kind: "element",
|
|
34
|
-
signature: `leading:${String(leadingKey ?? "default")}`,
|
|
35
|
-
element: leading,
|
|
36
|
-
} as const,
|
|
37
|
-
]
|
|
38
|
-
: []),
|
|
39
33
|
...splitDisplayUnits(value).map((unit) => ({
|
|
40
34
|
kind: "text" as const,
|
|
41
35
|
signature: `text:${unit}`,
|
|
42
36
|
value: unit,
|
|
43
37
|
})),
|
|
44
38
|
],
|
|
45
|
-
[
|
|
39
|
+
[value]
|
|
46
40
|
);
|
|
47
|
-
const signatures =
|
|
41
|
+
const signatures = textUnits.map((unit) => unit.signature);
|
|
48
42
|
const ledgerRef = useRef<TextGlyphLedger>({
|
|
49
43
|
previousValue: value,
|
|
50
44
|
previousSignatures: signatures,
|
|
51
|
-
glyphKeys:
|
|
52
|
-
nextSeed:
|
|
45
|
+
glyphKeys: textUnits.map((_, index) => `${namespace}:c${index}`),
|
|
46
|
+
nextSeed: textUnits.length,
|
|
53
47
|
});
|
|
54
48
|
|
|
55
49
|
// reconcile only when a token signature changes so stable glyphs keep their views
|
|
@@ -79,16 +73,29 @@ export const useTextGlyphs = (
|
|
|
79
73
|
|
|
80
74
|
const glyphKeys = ledgerRef.current.glyphKeys;
|
|
81
75
|
|
|
82
|
-
// normalize spaces at the edge where tokens become renderable glyphs
|
|
76
|
+
// normalize spaces at the edge where tokens become renderable glyphs, then
|
|
77
|
+
// prepend the leading token with an identity that is independent of text
|
|
83
78
|
return useMemo(
|
|
84
|
-
() =>
|
|
85
|
-
|
|
79
|
+
() => {
|
|
80
|
+
const textGlyphs = textUnits.map((unit, index) => ({
|
|
86
81
|
id: glyphKeys[index],
|
|
87
|
-
kind:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
kind: "text" as const,
|
|
83
|
+
value: normalizeDisplayUnit(unit.value),
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
if (!leading) {
|
|
87
|
+
return textGlyphs;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return [
|
|
91
|
+
{
|
|
92
|
+
id: `${namespace}:leading:${String(leadingKey ?? "default")}`,
|
|
93
|
+
kind: "element" as const,
|
|
94
|
+
element: leading,
|
|
95
|
+
},
|
|
96
|
+
...textGlyphs,
|
|
97
|
+
];
|
|
98
|
+
},
|
|
99
|
+
[glyphKeys, leading, leadingKey, namespace, textUnits]
|
|
93
100
|
);
|
|
94
101
|
};
|
package/src/index.tsx
CHANGED
|
@@ -79,7 +79,13 @@ export const Laminar = React.memo(function Laminar({
|
|
|
79
79
|
textStyle,
|
|
80
80
|
variant,
|
|
81
81
|
]);
|
|
82
|
-
const {
|
|
82
|
+
const {
|
|
83
|
+
captureLayout,
|
|
84
|
+
captureVisibleLayout,
|
|
85
|
+
animatedWidthStyle,
|
|
86
|
+
isReady: isAutoSizeReady,
|
|
87
|
+
shouldMeasure,
|
|
88
|
+
} =
|
|
83
89
|
useInlineAutoWidth({
|
|
84
90
|
enabled: autoSize,
|
|
85
91
|
driveToWidth: motionRecipe.driveNumber,
|
|
@@ -103,9 +109,11 @@ export const Laminar = React.memo(function Laminar({
|
|
|
103
109
|
align={align}
|
|
104
110
|
containerStyle={containerStyle}
|
|
105
111
|
animatedWidthStyle={animatedWidthStyle}
|
|
112
|
+
onVisibleLayout={autoSize ? captureVisibleLayout : undefined}
|
|
106
113
|
measurement={
|
|
107
114
|
shouldMeasure ? (
|
|
108
115
|
<View
|
|
116
|
+
key={measurementKey}
|
|
109
117
|
onLayout={captureLayout}
|
|
110
118
|
style={{ flexDirection: "row", alignSelf: "flex-start" }}
|
|
111
119
|
>
|
|
@@ -155,8 +163,10 @@ export const Laminar = React.memo(function Laminar({
|
|
|
155
163
|
motionRecipe={motionRecipe}
|
|
156
164
|
align={align}
|
|
157
165
|
leading={resolvedLeading}
|
|
166
|
+
leadingLayoutGroup={Boolean(leading)}
|
|
158
167
|
leadingKey={resolvedLeadingKey}
|
|
159
168
|
leadingGap={leadingGap}
|
|
169
|
+
ready={!autoSize || isAutoSizeReady}
|
|
160
170
|
textStyle={textStyle}
|
|
161
171
|
className={className}
|
|
162
172
|
/>
|