react-native-livechart 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/LoadingOverlay.d.ts.map +1 -1
- package/dist/components/MarkerOverlay.d.ts.map +1 -1
- package/dist/components/MultiSeriesValueLines.d.ts.map +1 -1
- package/dist/components/ReferenceLineOverlay.d.ts.map +1 -1
- package/dist/components/ValueLineOverlay.d.ts.map +1 -1
- package/dist/components/XAxisOverlay.d.ts.map +1 -1
- package/dist/components/YAxisOverlay.d.ts.map +1 -1
- package/dist/hooks/useBadge.d.ts +2 -2
- package/dist/hooks/useBadge.d.ts.map +1 -1
- package/dist/hooks/useCandlePaths.d.ts +8 -10
- package/dist/hooks/useCandlePaths.d.ts.map +1 -1
- package/dist/hooks/useChartPaths.d.ts +8 -7
- package/dist/hooks/useChartPaths.d.ts.map +1 -1
- package/dist/hooks/useMultiSeriesLinePaths.d.ts +9 -8
- package/dist/hooks/useMultiSeriesLinePaths.d.ts.map +1 -1
- package/dist/hooks/usePathBuilder.d.ts +27 -0
- package/dist/hooks/usePathBuilder.d.ts.map +1 -0
- package/dist/math/spline.d.ts +10 -2
- package/dist/math/spline.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/LoadingOverlay.tsx +15 -29
- package/src/components/MarkerOverlay.tsx +23 -28
- package/src/components/MultiSeriesValueLines.tsx +20 -40
- package/src/components/ReferenceLineOverlay.tsx +65 -107
- package/src/components/ValueLineOverlay.tsx +9 -28
- package/src/components/XAxisOverlay.tsx +9 -29
- package/src/components/YAxisOverlay.tsx +6 -22
- package/src/draw/markerAtlas.ts +9 -9
- package/src/hooks/useBadge.ts +17 -32
- package/src/hooks/useCandlePaths.ts +24 -63
- package/src/hooks/useChartPaths.ts +27 -39
- package/src/hooks/useMultiSeriesLinePaths.ts +26 -28
- package/src/hooks/usePathBuilder.ts +42 -0
- package/src/math/spline.ts +22 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingOverlay.d.ts","sourceRoot":"","sources":["../../src/components/LoadingOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"LoadingOverlay.d.ts","sourceRoot":"","sources":["../../src/components/LoadingOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,MAAM,EACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAK5E,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAOtB,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAkBpE,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,EACJ,MAAM,EACN,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,EACX,KAAa,EACb,SAAgB,EAChB,YAAqC,EACrC,YAA2C,GAC5C,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,iEAAiE;IACjE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iGAAiG;IACjG,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,iCAAiC;IACjC,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC,2CAoNA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkerOverlay.d.ts","sourceRoot":"","sources":["../../src/components/MarkerOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"MarkerOverlay.d.ts","sourceRoot":"","sources":["../../src/components/MarkerOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAejD,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,MAAM,EACN,YAAY,EACb,MAAM,UAAU,CAAC;AA8FlB;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,EACJ,MAAM,EACN,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,CAAC,EAAE,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IACrC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,WAAW,CAAC,cAAc,EAAE,CAAC,CAAC;CAC1C,2CAyHA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSeriesValueLines.d.ts","sourceRoot":"","sources":["../../src/components/MultiSeriesValueLines.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MultiSeriesValueLines.d.ts","sourceRoot":"","sources":["../../src/components/MultiSeriesValueLines.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AA+DnE,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EACP,MAAM,EACN,MAAM,GACP,EAAE;IACD,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,uBAAuB,CAAC;CACjC,2CAeA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReferenceLineOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ReferenceLineOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ReferenceLineOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ReferenceLineOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,MAAM,EACZ,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAUhE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,OAAO,EACP,IAAI,EACJ,OAAO,EACP,WAAW,EACX,IAAI,GACL,EAAE;IACD,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd,2CAoOA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValueLineOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ValueLineOverlay.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ValueLineOverlay.d.ts","sourceRoot":"","sources":["../../src/components/ValueLineOverlay.tsx"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAGpE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,MAAM,EACN,OAAO,EACP,WAAW,EACX,SAAS,EACT,KAAK,GACN,EAAE;IACD,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf,2CAkBA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XAxisOverlay.d.ts","sourceRoot":"","sources":["../../src/components/XAxisOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"XAxisOverlay.d.ts","sourceRoot":"","sources":["../../src/components/XAxisOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAOjD,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,GACL,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IACnC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd,2CA8DA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YAxisOverlay.d.ts","sourceRoot":"","sources":["../../src/components/YAxisOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"YAxisOverlay.d.ts","sourceRoot":"","sources":["../../src/components/YAxisOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,MAAM,EACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAKpE,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,EACJ,KAAa,EACb,SAAgB,EAChB,YAAqC,EACrC,gBAAoB,EACpB,SAAS,GACV,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IACnC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC,2CAsEA"}
|
package/dist/hooks/useBadge.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type SkFont
|
|
1
|
+
import { type SkFont } from "@shopify/react-native-skia";
|
|
2
2
|
import { type SharedValue } from "react-native-reanimated";
|
|
3
3
|
import type { ChartEngineWithLiveValue } from "../core/useLiveChartEngine";
|
|
4
4
|
import { type ChartPadding } from "../draw/line";
|
|
5
5
|
import type { BadgeMetrics, BadgeVariant, LiveChartPalette, Momentum } from "../types";
|
|
6
6
|
export declare function useBadge(engine: ChartEngineWithLiveValue, padding: ChartPadding, palette: LiveChartPalette, formatValue: (v: number) => string, font: SkFont, variant?: BadgeVariant, showTail?: boolean, momentum?: SharedValue<Momentum>, position?: "right" | "left", background?: string, badgeMetrics?: BadgeMetrics, badgeColorSpeed?: number): import("react-native-reanimated").DerivedValue<{
|
|
7
|
-
path: SkPath;
|
|
7
|
+
path: import("@shopify/react-native-skia").SkPath;
|
|
8
8
|
textX: number;
|
|
9
9
|
textY: number;
|
|
10
10
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBadge.d.ts","sourceRoot":"","sources":["../../src/hooks/useBadge.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"useBadge.d.ts","sourceRoot":"","sources":["../../src/hooks/useBadge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAOjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAC3E,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,QAAQ,EACT,MAAM,UAAU,CAAC;AAGlB,wBAAgB,QAAQ,CACtB,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,gBAAgB,EACzB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,YAAwB,EACjC,QAAQ,UAAO,EACf,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,EAChC,QAAQ,GAAE,OAAO,GAAG,MAAgB,EACpC,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,GAAE,YAAqC,EACnD,eAAe,GAAE,MAAgD;;;;;;;GAsJlE"}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { type SkPath } from "@shopify/react-native-skia";
|
|
2
1
|
import { type SharedValue } from "react-native-reanimated";
|
|
3
2
|
import type { SingleEngineState } from "../core/useLiveChartEngine";
|
|
4
3
|
import type { ChartPadding } from "../draw/line";
|
|
5
4
|
import type { CandleMetrics, CandlePoint } from "../types";
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* so
|
|
10
|
-
*
|
|
11
|
-
* ticking).
|
|
6
|
+
* Candle paths (up/down bodies + up/down wicks). Each is built into a reused
|
|
7
|
+
* `Skia.PathBuilder` and finalized with `detach()` each frame — a fresh
|
|
8
|
+
* immutable `SkPath`, so Skia repaints without a per-curve ping-pong and no
|
|
9
|
+
* mutable `SkPath` is retained across frames.
|
|
12
10
|
*/
|
|
13
11
|
export declare function useCandlePaths(engine: SingleEngineState, padding: ChartPadding, candles: SharedValue<CandlePoint[]> | undefined, liveCandle: SharedValue<CandlePoint | null> | undefined, candleWidthSecs: number, active: boolean, candleMetrics?: CandleMetrics): {
|
|
14
|
-
readonly upBodiesPath: import("react-native-reanimated").DerivedValue<SkPath>;
|
|
15
|
-
readonly downBodiesPath: import("react-native-reanimated").DerivedValue<SkPath>;
|
|
16
|
-
readonly upWicksPath: import("react-native-reanimated").DerivedValue<SkPath>;
|
|
17
|
-
readonly downWicksPath: import("react-native-reanimated").DerivedValue<SkPath>;
|
|
12
|
+
readonly upBodiesPath: import("react-native-reanimated").DerivedValue<import("@shopify/react-native-skia").SkPath>;
|
|
13
|
+
readonly downBodiesPath: import("react-native-reanimated").DerivedValue<import("@shopify/react-native-skia").SkPath>;
|
|
14
|
+
readonly upWicksPath: import("react-native-reanimated").DerivedValue<import("@shopify/react-native-skia").SkPath>;
|
|
15
|
+
readonly downWicksPath: import("react-native-reanimated").DerivedValue<import("@shopify/react-native-skia").SkPath>;
|
|
18
16
|
};
|
|
19
17
|
//# sourceMappingURL=useCandlePaths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCandlePaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useCandlePaths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCandlePaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useCandlePaths.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAK3D;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,WAAW,CAAC,WAAW,EAAE,CAAC,GAAG,SAAS,EAC/C,UAAU,EAAE,WAAW,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,SAAS,EACvD,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,OAAO,EACf,aAAa,GAAE,aAAuC;;;;;EAiGvD"}
|
|
@@ -3,14 +3,15 @@ import { type SharedValue } from "react-native-reanimated";
|
|
|
3
3
|
import type { SingleEngineState } from "../core/useLiveChartEngine";
|
|
4
4
|
import { type ChartPadding } from "../draw/line";
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Builds the `linePath` / `fillPath` with `Skia.PathBuilder`s reused across
|
|
7
|
+
* frames (one per curve, held in a SharedValue) and finalized with `detach()` —
|
|
8
|
+
* which returns a fresh immutable `SkPath` each frame and resets the builder.
|
|
9
|
+
* The fresh reference makes Reanimated notify subscribers (re-record + repaint)
|
|
10
|
+
* without the two-SkPath ping-pong the mutable-path pool needed.
|
|
7
11
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* two paths per curve once and ping-pong the reference each frame so Reanimated's
|
|
12
|
-
* value-equality early-return still fires its subscribers (i.e. the Skia reanimated
|
|
13
|
-
* container re-records and repaints).
|
|
12
|
+
* The flat point buffer still ping-pongs (ptsA/ptsB) so the intermediate
|
|
13
|
+
* `flatPts` derived value changes reference each frame and re-runs linePath /
|
|
14
|
+
* fillPath.
|
|
14
15
|
*/
|
|
15
16
|
export declare function useChartPaths(engine: SingleEngineState, padding: ChartPadding, morphT?: SharedValue<number>): {
|
|
16
17
|
readonly linePath: import("react-native-reanimated").DerivedValue<SkPath>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChartPaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useChartPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useChartPaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useChartPaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAKlE;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,YAAY,EACrB,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC;;;EAqF7B"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type SkPath } from "@shopify/react-native-skia";
|
|
2
2
|
import { type SharedValue } from "react-native-reanimated";
|
|
3
3
|
import type { MultiEngineState } from "../core/useLiveChartEngine";
|
|
4
4
|
import { type ChartPadding } from "../draw/line";
|
|
5
5
|
/**
|
|
6
|
-
* One derived shared value holding up to `MAX_MULTI_SERIES` Skia paths (unused
|
|
6
|
+
* One derived shared value holding up to `MAX_MULTI_SERIES` Skia paths (unused
|
|
7
|
+
* slots reuse one cached empty path).
|
|
7
8
|
*
|
|
8
|
-
* Each
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Each visible series' path is built into a per-slot `Skia.PathBuilder` (reused
|
|
10
|
+
* across frames via a SharedValue) and finalized with `detach()` — a fresh
|
|
11
|
+
* immutable `SkPath` per frame, so `MultiSeriesStroke`'s per-slot
|
|
12
|
+
* `useDerivedValue(() => paths.value[index])` repaints without the two-SkPath
|
|
13
|
+
* ping-pong. Only visible series allocate a path.
|
|
13
14
|
*/
|
|
14
|
-
export declare function useMultiSeriesLinePaths(engine: MultiEngineState, padding: ChartPadding): SharedValue<
|
|
15
|
+
export declare function useMultiSeriesLinePaths(engine: MultiEngineState, padding: ChartPadding): SharedValue<SkPath[]>;
|
|
15
16
|
//# sourceMappingURL=useMultiSeriesLinePaths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMultiSeriesLinePaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useMultiSeriesLinePaths.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"useMultiSeriesLinePaths.d.ts","sourceRoot":"","sources":["../../src/hooks/useMultiSeriesLinePaths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAIlE;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,YAAY,GACpB,WAAW,CAAC,MAAM,EAAE,CAAC,CAmDvB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Skia } from "@shopify/react-native-skia";
|
|
2
|
+
import { type SharedValue } from "react-native-reanimated";
|
|
3
|
+
/** A `Skia.PathBuilder` instance (typed without depending on a named export). */
|
|
4
|
+
export type ReanimatedPathBuilder = ReturnType<typeof Skia.PathBuilder.Make>;
|
|
5
|
+
/**
|
|
6
|
+
* A `Skia.PathBuilder` made accessible inside Reanimated worklets.
|
|
7
|
+
*
|
|
8
|
+
* Unlike `SkPath`, an `SkPathBuilder` is **not** a Reanimated-shareable host
|
|
9
|
+
* object: stashing one in a `useRef` and reading it from a `useDerivedValue`
|
|
10
|
+
* worklet yields `undefined`. Wrapping it in a `SharedValue` is the supported
|
|
11
|
+
* way to cross the JS→UI boundary, so the builder is created once on the JS
|
|
12
|
+
* thread and reused every frame on the UI thread.
|
|
13
|
+
*
|
|
14
|
+
* Per-frame usage in a worklet:
|
|
15
|
+
*
|
|
16
|
+
* const b = builder.value;
|
|
17
|
+
* b.moveTo(x, y); b.lineTo(...); // emit verbs
|
|
18
|
+
* return b.detach(); // fresh immutable SkPath; resets the builder
|
|
19
|
+
*
|
|
20
|
+
* `detach()` returns a new `SkPath` and resets the builder for the next frame,
|
|
21
|
+
* so the returned reference changes every frame and Reanimated notifies
|
|
22
|
+
* subscribers without the two-path ping-pong the mutable-`SkPath` pool needs.
|
|
23
|
+
*/
|
|
24
|
+
export declare function usePathBuilder(): SharedValue<ReanimatedPathBuilder>;
|
|
25
|
+
/** Like {@link usePathBuilder} but a fixed-length array of builders (e.g. one per series). */
|
|
26
|
+
export declare function usePathBuilders(count: number): SharedValue<ReanimatedPathBuilder[]>;
|
|
27
|
+
//# sourceMappingURL=usePathBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePathBuilder.d.ts","sourceRoot":"","sources":["../../src/hooks/usePathBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3E,iFAAiF;AACjF,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAAC,qBAAqB,CAAC,CAGnE;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAOtC"}
|
package/dist/math/spline.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { SkPath } from "@shopify/react-native-skia";
|
|
2
1
|
import type { LiveChartPoint } from "../types";
|
|
3
2
|
/**
|
|
4
3
|
* Reusable scratch buffers for {@link drawSpline}. Pass a persistent instance
|
|
@@ -28,7 +27,16 @@ export declare function makeSplineScratch(): SplineScratch;
|
|
|
28
27
|
*
|
|
29
28
|
* @see https://github.com/benjitaylor/liveline
|
|
30
29
|
*/
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Minimal structural sink for {@link drawSpline}: just the verb-emitting methods
|
|
32
|
+
* it calls. Both `SkPath` and `SkPathBuilder` satisfy it, so the spline can be
|
|
33
|
+
* built into either a mutable `SkPath` or a `Skia.PathBuilder`.
|
|
34
|
+
*/
|
|
35
|
+
export type SplinePathSink = {
|
|
36
|
+
lineTo: (x: number, y: number) => unknown;
|
|
37
|
+
cubicTo: (c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number) => unknown;
|
|
38
|
+
};
|
|
39
|
+
export declare function drawSpline(path: SplinePathSink, pts: number[], scratch?: SplineScratch): void;
|
|
32
40
|
/**
|
|
33
41
|
* Value of the Fritsch–Carlson monotone cubic — the same curve {@link drawSpline}
|
|
34
42
|
* renders — at `time`. Use this to anchor overlays (e.g. markers) exactly on the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spline.d.ts","sourceRoot":"","sources":["../../src/math/spline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"spline.d.ts","sourceRoot":"","sources":["../../src/math/spline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,CAAC,EAAE,MAAM,EAAE,CAAC;CACb;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,aAAa,CAEjD;AAED;;;;;;;;;;;;;GAaG;AACH;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,OAAO,EAAE,CACP,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,KACN,OAAO,CAAC;CACd,CAAC;AAEF,wBAAgB,UAAU,CACxB,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,aAAa,QA+DxB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAoEf"}
|
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"module": "./src/index.ts",
|
|
40
40
|
"name": "react-native-livechart",
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@shopify/react-native-skia": ">=2.
|
|
42
|
+
"@shopify/react-native-skia": ">=2.6.0",
|
|
43
43
|
"react": ">=18.0.0",
|
|
44
44
|
"react-native": ">=0.76.0",
|
|
45
45
|
"react-native-gesture-handler": ">=2.0.0",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
},
|
|
69
69
|
"sideEffects": false,
|
|
70
70
|
"types": "./dist/index.d.ts",
|
|
71
|
-
"version": "
|
|
71
|
+
"version": "3.0.0"
|
|
72
72
|
}
|
|
@@ -4,13 +4,10 @@ import {
|
|
|
4
4
|
Path,
|
|
5
5
|
Rect,
|
|
6
6
|
RoundedRect,
|
|
7
|
-
Skia,
|
|
8
7
|
Text as SkiaText,
|
|
9
8
|
vec,
|
|
10
9
|
type SkFont,
|
|
11
|
-
type SkPath,
|
|
12
10
|
} from "@shopify/react-native-skia";
|
|
13
|
-
import { useRef } from "react";
|
|
14
11
|
import { useDerivedValue, type SharedValue } from "react-native-reanimated";
|
|
15
12
|
import {
|
|
16
13
|
BADGE_METRICS_DEFAULTS,
|
|
@@ -22,6 +19,10 @@ import {
|
|
|
22
19
|
pillTextLeftX,
|
|
23
20
|
type ChartPadding,
|
|
24
21
|
} from "../draw/line";
|
|
22
|
+
import {
|
|
23
|
+
usePathBuilder,
|
|
24
|
+
type ReanimatedPathBuilder,
|
|
25
|
+
} from "../hooks/usePathBuilder";
|
|
25
26
|
import { drawSpline } from "../math/spline";
|
|
26
27
|
import { buildSquigglyPts } from "../math/squiggly";
|
|
27
28
|
import type {
|
|
@@ -37,14 +38,14 @@ const RECT_H = 4;
|
|
|
37
38
|
const RECT_R = 4;
|
|
38
39
|
const RECT_SPACING = 32;
|
|
39
40
|
|
|
40
|
-
function
|
|
41
|
+
function buildSplineDetached(b: ReanimatedPathBuilder, pts: number[]) {
|
|
41
42
|
"worklet";
|
|
42
|
-
path.reset();
|
|
43
43
|
const n = pts.length >> 1;
|
|
44
|
-
if (n
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
if (n >= 2) {
|
|
45
|
+
b.moveTo(pts[0], pts[1]);
|
|
46
|
+
drawSpline(b, pts);
|
|
47
|
+
}
|
|
48
|
+
return b.detach();
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export function LoadingOverlay({
|
|
@@ -85,29 +86,14 @@ export function LoadingOverlay({
|
|
|
85
86
|
const leftInset =
|
|
86
87
|
badgeMetrics.dotGap + badgeTailAndCap(font.getSize(), badgeTail, badgeMetrics);
|
|
87
88
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
const squigglyCacheRef = useRef<{
|
|
91
|
-
a: SkPath;
|
|
92
|
-
b: SkPath;
|
|
93
|
-
tick: boolean;
|
|
94
|
-
} | null>(null);
|
|
95
|
-
if (squigglyCacheRef.current === null) {
|
|
96
|
-
squigglyCacheRef.current = {
|
|
97
|
-
a: Skia.Path.Make(),
|
|
98
|
-
b: Skia.Path.Make(),
|
|
99
|
-
tick: false,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
89
|
+
// Squiggly path — built into a reused PathBuilder and detach()-ed each frame.
|
|
90
|
+
const squigglyBuilder = usePathBuilder();
|
|
102
91
|
|
|
103
92
|
// Squiggly path — animated each frame via timestamp
|
|
104
93
|
const squigglyPath = useDerivedValue(() => {
|
|
105
|
-
const
|
|
106
|
-
squigglyCache.tick = !squigglyCache.tick;
|
|
107
|
-
const path = squigglyCache.tick ? squigglyCache.a : squigglyCache.b;
|
|
94
|
+
const b = squigglyBuilder.value;
|
|
108
95
|
if (!isLoading.get() && !isEmpty.value && morphT.get() >= 1) {
|
|
109
|
-
|
|
110
|
-
return path;
|
|
96
|
+
return b.detach();
|
|
111
97
|
}
|
|
112
98
|
const pts = buildSquigglyPts(
|
|
113
99
|
engine.canvasWidth.get(),
|
|
@@ -115,7 +101,7 @@ export function LoadingOverlay({
|
|
|
115
101
|
padding,
|
|
116
102
|
engine.timestamp.get(),
|
|
117
103
|
);
|
|
118
|
-
return
|
|
104
|
+
return buildSplineDetached(b, pts);
|
|
119
105
|
});
|
|
120
106
|
|
|
121
107
|
// Fades out quickly as the reveal animation begins (first 33% of morphT)
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
Path,
|
|
5
5
|
Skia,
|
|
6
6
|
type SkFont,
|
|
7
|
-
type SkPath,
|
|
8
7
|
} from "@shopify/react-native-skia";
|
|
9
8
|
import { useMemo, useRef, useState } from "react";
|
|
10
9
|
import {
|
|
@@ -15,6 +14,7 @@ import {
|
|
|
15
14
|
import { scheduleOnRN } from "react-native-worklets";
|
|
16
15
|
import type { ChartEngineLayout } from "../core/useLiveChartEngine";
|
|
17
16
|
import type { ChartPadding } from "../draw/line";
|
|
17
|
+
import { usePathBuilder } from "../hooks/usePathBuilder";
|
|
18
18
|
import {
|
|
19
19
|
buildMarkerAtlas,
|
|
20
20
|
defaultMarkerColor,
|
|
@@ -84,37 +84,32 @@ function ConnectorGlyph({
|
|
|
84
84
|
|
|
85
85
|
const opacity = useDerivedValue(() => (layout.get().visible ? 1 : 0));
|
|
86
86
|
|
|
87
|
-
const
|
|
88
|
-
if (cacheRef.current === null) {
|
|
89
|
-
cacheRef.current = { a: Skia.Path.Make(), b: Skia.Path.Make(), tick: false };
|
|
90
|
-
}
|
|
87
|
+
const glyphBuilder = usePathBuilder();
|
|
91
88
|
|
|
92
89
|
const glyphPath = useDerivedValue(() => {
|
|
93
|
-
const
|
|
94
|
-
cache.tick = !cache.tick;
|
|
95
|
-
const p: SkPath = cache.tick ? cache.a : cache.b;
|
|
96
|
-
p.reset();
|
|
90
|
+
const b = glyphBuilder.value;
|
|
97
91
|
const l = layout.get();
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
92
|
+
if (l.visible) {
|
|
93
|
+
const x = l.x;
|
|
94
|
+
const y = l.y;
|
|
95
|
+
if (kind === "graduation") {
|
|
96
|
+
b.moveTo(x, axisY.get());
|
|
97
|
+
b.lineTo(x, y);
|
|
98
|
+
b.moveTo(x, y - 7);
|
|
99
|
+
b.lineTo(x + 8, y - 4);
|
|
100
|
+
b.lineTo(x, y - 1);
|
|
101
|
+
b.close();
|
|
102
|
+
} else if (kind === "clawback") {
|
|
103
|
+
const s = 5;
|
|
104
|
+
const ay = axisY.get() - s;
|
|
105
|
+
b.moveTo(x - s, ay);
|
|
106
|
+
b.lineTo(x + s, ay);
|
|
107
|
+
b.lineTo(x + s, ay + s * 2);
|
|
108
|
+
b.lineTo(x - s, ay + s * 2);
|
|
109
|
+
b.close();
|
|
110
|
+
}
|
|
116
111
|
}
|
|
117
|
-
return
|
|
112
|
+
return b.detach();
|
|
118
113
|
});
|
|
119
114
|
|
|
120
115
|
const fill = kind === "clawback";
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DashPathEffect,
|
|
3
|
-
Group,
|
|
4
|
-
Path,
|
|
5
|
-
Skia,
|
|
6
|
-
type SkPath,
|
|
7
|
-
} from "@shopify/react-native-skia";
|
|
1
|
+
import { DashPathEffect, Group, Path } from "@shopify/react-native-skia";
|
|
8
2
|
|
|
9
|
-
import { useRef } from "react";
|
|
10
3
|
import { useDerivedValue } from "react-native-reanimated";
|
|
11
4
|
import { MAX_MULTI_SERIES } from "../constants";
|
|
12
5
|
import type { ChartPadding } from "../draw/line";
|
|
13
6
|
import type { ResolvedValueLineConfig } from "../core/resolveConfig";
|
|
14
7
|
import type { MultiEngineState } from "../core/useLiveChartEngine";
|
|
8
|
+
import { usePathBuilder } from "../hooks/usePathBuilder";
|
|
15
9
|
|
|
16
10
|
function SeriesValueLineAtIndex({
|
|
17
11
|
index,
|
|
@@ -26,44 +20,30 @@ function SeriesValueLineAtIndex({
|
|
|
26
20
|
color: string;
|
|
27
21
|
config: ResolvedValueLineConfig;
|
|
28
22
|
}) {
|
|
29
|
-
const
|
|
30
|
-
a: SkPath;
|
|
31
|
-
b: SkPath;
|
|
32
|
-
tick: boolean;
|
|
33
|
-
} | null>(null);
|
|
34
|
-
if (cacheRef.current === null) {
|
|
35
|
-
cacheRef.current = {
|
|
36
|
-
a: Skia.Path.Make(),
|
|
37
|
-
b: Skia.Path.Make(),
|
|
38
|
-
tick: false,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
23
|
+
const builder = usePathBuilder();
|
|
41
24
|
|
|
42
25
|
const path = useDerivedValue(() => {
|
|
43
|
-
const
|
|
44
|
-
cache.tick = !cache.tick;
|
|
45
|
-
const p = cache.tick ? cache.a : cache.b;
|
|
46
|
-
p.reset();
|
|
26
|
+
const b = builder.value;
|
|
47
27
|
const h = engine.canvasHeight.get();
|
|
48
|
-
if (h === 0) return p;
|
|
49
28
|
const s = engine.series.get();
|
|
50
29
|
const displays = engine.displaySeriesValues.get();
|
|
51
|
-
if (index
|
|
30
|
+
if (h !== 0 && index < s.length) {
|
|
31
|
+
const chartH = h - padding.top - padding.bottom;
|
|
32
|
+
const dMin = engine.displayMin.get();
|
|
33
|
+
const dMax = engine.displayMax.get();
|
|
34
|
+
const valRange = dMax - dMin;
|
|
35
|
+
const v = displays[index] ?? s[index].value;
|
|
36
|
+
const y =
|
|
37
|
+
valRange === 0
|
|
38
|
+
? padding.top + chartH / 2
|
|
39
|
+
: padding.top + ((dMax - v) / valRange) * chartH;
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
valRange === 0
|
|
60
|
-
? padding.top + chartH / 2
|
|
61
|
-
: padding.top + ((dMax - v) / valRange) * chartH;
|
|
62
|
-
|
|
63
|
-
if (y < 0) return p;
|
|
64
|
-
p.moveTo(padding.left, y);
|
|
65
|
-
p.lineTo(engine.canvasWidth.get() - padding.right, y);
|
|
66
|
-
return p;
|
|
41
|
+
if (y >= 0) {
|
|
42
|
+
b.moveTo(padding.left, y);
|
|
43
|
+
b.lineTo(engine.canvasWidth.get() - padding.right, y);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return b.detach();
|
|
67
47
|
});
|
|
68
48
|
|
|
69
49
|
const opacity = useDerivedValue(() => {
|