panelui-native 0.68.0 → 0.73.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/README.md +13 -2
- package/lib/module/components/accordion/index.js +38 -13
- package/lib/module/components/accordion/index.js.map +1 -1
- package/lib/module/components/area-chart/index.js +1 -0
- package/lib/module/components/area-chart/index.js.map +1 -1
- package/lib/module/components/breadcrumb/index.js +2 -1
- package/lib/module/components/breadcrumb/index.js.map +1 -1
- package/lib/module/components/button/index.js +21 -12
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/carousel/index.js +1 -1
- package/lib/module/components/carousel/index.js.map +1 -1
- package/lib/module/components/chip/index.js +2 -2
- package/lib/module/components/chip/index.js.map +1 -1
- package/lib/module/components/code-block/index.js.map +1 -1
- package/lib/module/components/collapsible/index.js +284 -0
- package/lib/module/components/collapsible/index.js.map +1 -0
- package/lib/module/components/color-picker/index.js.map +1 -1
- package/lib/module/components/fab/index.js +7 -6
- package/lib/module/components/fab/index.js.map +1 -1
- package/lib/module/components/flow/index.js +67 -4
- package/lib/module/components/flow/index.js.map +1 -1
- package/lib/module/components/frame/index.js +2 -2
- package/lib/module/components/frame/index.js.map +1 -1
- package/lib/module/components/grid-item/index.js +2 -2
- package/lib/module/components/grid-item/index.js.map +1 -1
- package/lib/module/components/heatmap-chart/index.js +1 -0
- package/lib/module/components/heatmap-chart/index.js.map +1 -1
- package/lib/module/components/hex-chart/index.js +1 -0
- package/lib/module/components/hex-chart/index.js.map +1 -1
- package/lib/module/components/input-group/index.js +7 -2
- package/lib/module/components/input-group/index.js.map +1 -1
- package/lib/module/components/item/index.js +2 -2
- package/lib/module/components/item/index.js.map +1 -1
- package/lib/module/components/line-chart/index.js +1 -0
- package/lib/module/components/line-chart/index.js.map +1 -1
- package/lib/module/components/live-line-chart/index.js +103 -9
- package/lib/module/components/live-line-chart/index.js.map +1 -1
- package/lib/module/components/live-line-chart/live-line-accessibility.js +47 -0
- package/lib/module/components/live-line-chart/live-line-accessibility.js.map +1 -0
- package/lib/module/components/live-line-chart/live-line-lifecycle.js +33 -0
- package/lib/module/components/live-line-chart/live-line-lifecycle.js.map +1 -0
- package/lib/module/components/marker/index.js +2 -2
- package/lib/module/components/marker/index.js.map +1 -1
- package/lib/module/components/marquee/index.js +191 -0
- package/lib/module/components/marquee/index.js.map +1 -0
- package/lib/module/components/marquee/marquee-math.js +39 -0
- package/lib/module/components/marquee/marquee-math.js.map +1 -0
- package/lib/module/components/menu/index.js +11 -3
- package/lib/module/components/menu/index.js.map +1 -1
- package/lib/module/components/meter/index.js +38 -20
- package/lib/module/components/meter/index.js.map +1 -1
- package/lib/module/components/meter/meter-scale.js +62 -8
- package/lib/module/components/meter/meter-scale.js.map +1 -1
- package/lib/module/components/pagination/index.js +27 -11
- package/lib/module/components/pagination/index.js.map +1 -1
- package/lib/module/components/panelside/index.js +7 -2
- package/lib/module/components/panelside/index.js.map +1 -1
- package/lib/module/components/planner/index.js +159 -64
- package/lib/module/components/planner/index.js.map +1 -1
- package/lib/module/components/planner/planner-announcement.js +30 -0
- package/lib/module/components/planner/planner-announcement.js.map +1 -0
- package/lib/module/components/planner/planner-entries.js +15 -7
- package/lib/module/components/planner/planner-entries.js.map +1 -1
- package/lib/module/components/planner/planner-grid-navigation.js +33 -0
- package/lib/module/components/planner/planner-grid-navigation.js.map +1 -0
- package/lib/module/components/planner/planner-lifecycle.js +45 -0
- package/lib/module/components/planner/planner-lifecycle.js.map +1 -0
- package/lib/module/components/plot/index.js +105 -42
- package/lib/module/components/plot/index.js.map +1 -1
- package/lib/module/components/popover/index.js +2 -2
- package/lib/module/components/popover/index.js.map +1 -1
- package/lib/module/components/post/index.js +4 -4
- package/lib/module/components/post/index.js.map +1 -1
- package/lib/module/components/search-bar/index.js +331 -0
- package/lib/module/components/search-bar/index.js.map +1 -0
- package/lib/module/components/table/index.js +3 -4
- package/lib/module/components/table/index.js.map +1 -1
- package/lib/module/components/timeline/index.js +288 -39
- package/lib/module/components/timeline/index.js.map +1 -1
- package/lib/module/components/toggle-button/index.js +1 -1
- package/lib/module/components/toggle-button/index.js.map +1 -1
- package/lib/module/components/tree/index.js +13 -8
- package/lib/module/components/tree/index.js.map +1 -1
- package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/primitives/focus-restoration-store.js +52 -0
- package/lib/module/primitives/focus-restoration-store.js.map +1 -0
- package/lib/module/primitives/portal.js +36 -2
- package/lib/module/primitives/portal.js.map +1 -1
- package/lib/module/utils/chart.js +50 -7
- package/lib/module/utils/chart.js.map +1 -1
- package/lib/typescript/src/components/accordion/index.d.ts +6 -2
- package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
- package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/breadcrumb/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/code-block/index.d.ts +3 -3
- package/lib/typescript/src/components/code-block/index.d.ts.map +1 -1
- package/lib/typescript/src/components/collapsible/index.d.ts +76 -0
- package/lib/typescript/src/components/collapsible/index.d.ts.map +1 -0
- package/lib/typescript/src/components/color-picker/index.d.ts.map +1 -1
- package/lib/typescript/src/components/fab/index.d.ts +4 -2
- package/lib/typescript/src/components/fab/index.d.ts.map +1 -1
- package/lib/typescript/src/components/flow/index.d.ts +7 -1
- package/lib/typescript/src/components/flow/index.d.ts.map +1 -1
- package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/hex-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/live-line-chart/index.d.ts +21 -7
- package/lib/typescript/src/components/live-line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/live-line-chart/live-line-accessibility.d.ts +22 -0
- package/lib/typescript/src/components/live-line-chart/live-line-accessibility.d.ts.map +1 -0
- package/lib/typescript/src/components/live-line-chart/live-line-lifecycle.d.ts +23 -0
- package/lib/typescript/src/components/live-line-chart/live-line-lifecycle.d.ts.map +1 -0
- package/lib/typescript/src/components/marquee/index.d.ts +73 -0
- package/lib/typescript/src/components/marquee/index.d.ts.map +1 -0
- package/lib/typescript/src/components/marquee/marquee-math.d.ts +21 -0
- package/lib/typescript/src/components/marquee/marquee-math.d.ts.map +1 -0
- package/lib/typescript/src/components/menu/index.d.ts +1 -1
- package/lib/typescript/src/components/menu/index.d.ts.map +1 -1
- package/lib/typescript/src/components/meter/index.d.ts +7 -4
- package/lib/typescript/src/components/meter/index.d.ts.map +1 -1
- package/lib/typescript/src/components/meter/meter-scale.d.ts +39 -0
- package/lib/typescript/src/components/meter/meter-scale.d.ts.map +1 -1
- package/lib/typescript/src/components/pagination/index.d.ts.map +1 -1
- package/lib/typescript/src/components/panelside/index.d.ts +1 -1
- package/lib/typescript/src/components/panelside/index.d.ts.map +1 -1
- package/lib/typescript/src/components/plan/index.d.ts +2 -2
- package/lib/typescript/src/components/planner/index.d.ts.map +1 -1
- package/lib/typescript/src/components/planner/planner-announcement.d.ts +15 -0
- package/lib/typescript/src/components/planner/planner-announcement.d.ts.map +1 -0
- package/lib/typescript/src/components/planner/planner-entries.d.ts +1 -1
- package/lib/typescript/src/components/planner/planner-entries.d.ts.map +1 -1
- package/lib/typescript/src/components/planner/planner-grid-navigation.d.ts +4 -0
- package/lib/typescript/src/components/planner/planner-grid-navigation.d.ts.map +1 -0
- package/lib/typescript/src/components/planner/planner-lifecycle.d.ts +20 -0
- package/lib/typescript/src/components/planner/planner-lifecycle.d.ts.map +1 -0
- package/lib/typescript/src/components/plot/index.d.ts +59 -5
- package/lib/typescript/src/components/plot/index.d.ts.map +1 -1
- package/lib/typescript/src/components/search-bar/index.d.ts +216 -0
- package/lib/typescript/src/components/search-bar/index.d.ts.map +1 -0
- package/lib/typescript/src/components/timeline/index.d.ts +35 -2
- package/lib/typescript/src/components/timeline/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tree/index.d.ts +3 -4
- package/lib/typescript/src/components/tree/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts +2 -2
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/primitives/focus-restoration-store.d.ts +24 -0
- package/lib/typescript/src/primitives/focus-restoration-store.d.ts.map +1 -0
- package/lib/typescript/src/primitives/portal.d.ts +4 -0
- package/lib/typescript/src/primitives/portal.d.ts.map +1 -1
- package/lib/typescript/src/utils/chart.d.ts +28 -3
- package/lib/typescript/src/utils/chart.d.ts.map +1 -1
- package/package.json +36 -3
- package/src/components/accordion/index.tsx +48 -15
- package/src/components/area-chart/index.tsx +8 -0
- package/src/components/breadcrumb/index.tsx +2 -1
- package/src/components/button/index.tsx +14 -6
- package/src/components/carousel/index.tsx +1 -1
- package/src/components/chip/index.tsx +2 -2
- package/src/components/code-block/index.tsx +3 -3
- package/src/components/collapsible/index.tsx +287 -0
- package/src/components/color-picker/index.tsx +3 -2
- package/src/components/fab/index.tsx +21 -11
- package/src/components/flow/index.tsx +94 -15
- package/src/components/frame/index.tsx +2 -2
- package/src/components/grid-item/index.tsx +2 -2
- package/src/components/heatmap-chart/index.tsx +7 -1
- package/src/components/hex-chart/index.tsx +7 -1
- package/src/components/input-group/index.tsx +7 -2
- package/src/components/item/index.tsx +2 -2
- package/src/components/line-chart/index.tsx +9 -0
- package/src/components/live-line-chart/index.tsx +130 -13
- package/src/components/live-line-chart/live-line-accessibility.ts +61 -0
- package/src/components/live-line-chart/live-line-lifecycle.ts +63 -0
- package/src/components/marker/index.tsx +2 -2
- package/src/components/marquee/index.tsx +234 -0
- package/src/components/marquee/marquee-math.ts +37 -0
- package/src/components/menu/index.tsx +11 -3
- package/src/components/meter/index.tsx +49 -26
- package/src/components/meter/meter-scale.ts +84 -8
- package/src/components/pagination/index.tsx +26 -13
- package/src/components/panelside/index.tsx +7 -2
- package/src/components/plan/index.tsx +2 -2
- package/src/components/planner/index.tsx +202 -76
- package/src/components/planner/planner-announcement.ts +37 -0
- package/src/components/planner/planner-entries.ts +16 -7
- package/src/components/planner/planner-grid-navigation.ts +45 -0
- package/src/components/planner/planner-lifecycle.ts +76 -0
- package/src/components/plot/index.tsx +183 -39
- package/src/components/popover/index.tsx +3 -3
- package/src/components/post/index.tsx +4 -4
- package/src/components/search-bar/index.tsx +436 -0
- package/src/components/table/index.tsx +2 -2
- package/src/components/timeline/index.tsx +335 -39
- package/src/components/toggle-button/index.tsx +1 -1
- package/src/components/tree/index.tsx +17 -12
- package/src/hooks/use-keyboard-avoidance.ts +7 -2
- package/src/index.ts +15 -0
- package/src/primitives/focus-restoration-store.ts +70 -0
- package/src/primitives/portal.tsx +34 -2
- package/src/utils/chart.ts +66 -7
|
@@ -105,6 +105,7 @@ import {
|
|
|
105
105
|
columnValues,
|
|
106
106
|
compactNumber,
|
|
107
107
|
linePath,
|
|
108
|
+
niceDomain,
|
|
108
109
|
useSeriesColor,
|
|
109
110
|
xOf,
|
|
110
111
|
yOf,
|
|
@@ -281,6 +282,17 @@ export interface PlotProps extends ViewProps {
|
|
|
281
282
|
* arrives.
|
|
282
283
|
*/
|
|
283
284
|
yDomain?: [PlotBound, PlotBound];
|
|
285
|
+
/**
|
|
286
|
+
* Round the derived ends of the y-domain out to whole numbers.
|
|
287
|
+
*
|
|
288
|
+
* Left off, an axis ends a tenth of the span past the largest value, so it
|
|
289
|
+
* gets labelled 34,650 — true, and not a number anybody was looking for. On,
|
|
290
|
+
* the ends move out to a step of 1, 2 or 5 times a power of ten, and the
|
|
291
|
+
* labels become values a reader can measure against.
|
|
292
|
+
*
|
|
293
|
+
* It only ever widens the axis, and a pinned end is left alone.
|
|
294
|
+
*/
|
|
295
|
+
nice?: boolean;
|
|
284
296
|
/**
|
|
285
297
|
* How an index becomes an x. Derived from the marks when left out: a plot
|
|
286
298
|
* with bars in it is banded, and anything else is on points.
|
|
@@ -317,6 +329,7 @@ const PlotRoot = forwardRef<PlotHandle, PlotProps>(function PlotRoot(
|
|
|
317
329
|
animationDuration = 700,
|
|
318
330
|
domainDuration = 500,
|
|
319
331
|
yDomain,
|
|
332
|
+
nice = false,
|
|
320
333
|
xScale: xScaleProp,
|
|
321
334
|
curve = 'monotone',
|
|
322
335
|
onActiveIndexChange,
|
|
@@ -450,11 +463,20 @@ const PlotRoot = forwardRef<PlotHandle, PlotProps>(function PlotRoot(
|
|
|
450
463
|
* drifting off the axis is exactly what pinning it was for.
|
|
451
464
|
*/
|
|
452
465
|
const headroom = (max - min) * 0.1;
|
|
466
|
+
/*
|
|
467
|
+
* `nice` replaces the headroom rather than adding to it: rounding out to a
|
|
468
|
+
* whole step is already room, and doing both would leave a tenth of the
|
|
469
|
+
* span of empty axis above a top the reader was told is round.
|
|
470
|
+
*/
|
|
471
|
+
const [niceLow, niceHigh] = nice ? niceDomain(min, max) : [min, max];
|
|
472
|
+
const derivedLow = nice ? niceLow : min - headroom * lowRoom;
|
|
473
|
+
const derivedHigh = nice ? niceHigh : max + headroom * highRoom;
|
|
474
|
+
|
|
453
475
|
return [
|
|
454
|
-
typeof lowPin === 'number' ? lowPin :
|
|
455
|
-
typeof highPin === 'number' ? highPin :
|
|
476
|
+
typeof lowPin === 'number' ? lowPin : derivedLow,
|
|
477
|
+
typeof highPin === 'number' ? highPin : derivedHigh,
|
|
456
478
|
];
|
|
457
|
-
}, [data, yDomain, seriesKeys, hasBars]);
|
|
479
|
+
}, [data, yDomain, seriesKeys, hasBars, nice]);
|
|
458
480
|
|
|
459
481
|
const loading = status === 'loading';
|
|
460
482
|
// Nothing has said what the axis is yet — no mark has registered and no
|
|
@@ -603,11 +625,19 @@ const PlotRoot = forwardRef<PlotHandle, PlotProps>(function PlotRoot(
|
|
|
603
625
|
* read as the chart arriving, rather than as four separate
|
|
604
626
|
* things animating in at once — which is the thing a composed
|
|
605
627
|
* chart is most at risk of looking like.
|
|
628
|
+
*
|
|
629
|
+
* `width` is set statically as well as animated, and it has
|
|
630
|
+
* to be. Animated props on an element inside `Defs` do not
|
|
631
|
+
* reach the native clip on every platform, and with the width
|
|
632
|
+
* coming only from the animation there is no width at all
|
|
633
|
+
* when they do not — an empty clip, and marks that never
|
|
634
|
+
* appear while the axes draw normally.
|
|
606
635
|
*/}
|
|
607
636
|
<ClipPath id={clipId}>
|
|
608
637
|
<AnimatedRect
|
|
609
638
|
x={plot.left}
|
|
610
639
|
y={0}
|
|
640
|
+
width={plot.width}
|
|
611
641
|
height={size.height}
|
|
612
642
|
animatedProps={clipProps}
|
|
613
643
|
/>
|
|
@@ -759,28 +789,12 @@ function PlotLine({
|
|
|
759
789
|
const max = domainMax.value;
|
|
760
790
|
if (max === min || plot.width <= 0) return { d: '' };
|
|
761
791
|
|
|
762
|
-
if (!banded) return { d: linePath(values, plot, min, max, curve, false) };
|
|
763
|
-
|
|
764
792
|
/*
|
|
765
|
-
*
|
|
766
|
-
*
|
|
767
|
-
*
|
|
768
|
-
* a slice left of the bar it is describing.
|
|
793
|
+
* `banded` moves the points to the middle of their own slice, which is
|
|
794
|
+
* where a line drawn over columns has to sit — spread edge to edge it
|
|
795
|
+
* starts half a slice left of the bar it is describing.
|
|
769
796
|
*/
|
|
770
|
-
|
|
771
|
-
let drawn = 0;
|
|
772
|
-
for (let index = 0; index < values.length; index += 1) {
|
|
773
|
-
const value = values[index];
|
|
774
|
-
if (value === null || value === undefined) {
|
|
775
|
-
drawn = 0;
|
|
776
|
-
continue;
|
|
777
|
-
}
|
|
778
|
-
const x = bandOf(index, values.length, plot);
|
|
779
|
-
const y = yOf(value, plot, min, max);
|
|
780
|
-
d += `${drawn === 0 ? 'M' : 'L'}${x},${y}`;
|
|
781
|
-
drawn += 1;
|
|
782
|
-
}
|
|
783
|
-
return { d };
|
|
797
|
+
return { d: linePath(values, plot, min, max, curve, false, undefined, banded) };
|
|
784
798
|
});
|
|
785
799
|
|
|
786
800
|
if (status === 'loading') return null;
|
|
@@ -820,15 +834,19 @@ function PlotArea({
|
|
|
820
834
|
opacity = 0.18,
|
|
821
835
|
curve = 'monotone',
|
|
822
836
|
}: PlotAreaProps) {
|
|
823
|
-
const { data, plot, domainMin, domainMax, status, clipId } =
|
|
837
|
+
const { data, plot, xScale, domainMin, domainMax, status, clipId } =
|
|
838
|
+
useChart('Plot.Area');
|
|
824
839
|
const fill = useMark(dataKey, color, colorIndex);
|
|
825
840
|
const values = useMemo(() => columnValues(data, dataKey), [data, dataKey]);
|
|
841
|
+
const banded = xScale === 'band';
|
|
826
842
|
|
|
827
843
|
const animatedProps = useAnimatedProps(() => {
|
|
828
844
|
const min = domainMin.value;
|
|
829
845
|
const max = domainMax.value;
|
|
830
846
|
if (max === min || plot.width <= 0) return { d: '' };
|
|
831
|
-
|
|
847
|
+
// Band-aware for the same reason the line is: an area on a plot that also
|
|
848
|
+
// carries columns has to close over the same slices they occupy.
|
|
849
|
+
return { d: areaPath(values, plot, min, max, curve, false, undefined, banded) };
|
|
832
850
|
});
|
|
833
851
|
|
|
834
852
|
if (status === 'loading') return null;
|
|
@@ -848,6 +866,18 @@ export interface PlotBarsProps extends PlotSeriesProps {
|
|
|
848
866
|
/** Rounds the end the bar grows towards, in points. */
|
|
849
867
|
radius?: number;
|
|
850
868
|
opacity?: number;
|
|
869
|
+
/**
|
|
870
|
+
* The value the columns grow from. Zero by default, and zero is nearly always
|
|
871
|
+
* right — a bar is a length, and a length has to start where the quantity
|
|
872
|
+
* does.
|
|
873
|
+
*
|
|
874
|
+
* Set it for the case where the reader is being shown movement rather than
|
|
875
|
+
* size: temperatures against a seasonal average, a score against a pass mark.
|
|
876
|
+
* Columns then run up and down from that line instead of all standing on the
|
|
877
|
+
* floor. It is clamped into the axis, so a baseline the domain does not cover
|
|
878
|
+
* falls back to the nearer edge.
|
|
879
|
+
*/
|
|
880
|
+
baseline?: number;
|
|
851
881
|
}
|
|
852
882
|
|
|
853
883
|
/**
|
|
@@ -866,6 +896,7 @@ function PlotBars({
|
|
|
866
896
|
gap = 0.35,
|
|
867
897
|
radius = 4,
|
|
868
898
|
opacity = 1,
|
|
899
|
+
baseline = 0,
|
|
869
900
|
}: PlotBarsProps) {
|
|
870
901
|
const { data, plot, domainMin, domainMax, status, clipId } = useChart('Plot.Bars');
|
|
871
902
|
const fill = useMark(dataKey, color, colorIndex);
|
|
@@ -881,12 +912,12 @@ function PlotBars({
|
|
|
881
912
|
if (max === min || plot.width <= 0 || total === 0) return { d: '' };
|
|
882
913
|
|
|
883
914
|
/*
|
|
884
|
-
* Bars grow from the baseline
|
|
885
|
-
*
|
|
915
|
+
* Bars grow from the baseline — zero unless the caller moved it — clamped
|
|
916
|
+
* into the domain where the axis does not reach it. A bar drawn from the
|
|
886
917
|
* bottom of a plot whose axis starts at 40 is a length that is not in the
|
|
887
918
|
* data.
|
|
888
919
|
*/
|
|
889
|
-
const base = yOf(Math.min(Math.max(
|
|
920
|
+
const base = yOf(Math.min(Math.max(baseline, min), max), plot, min, max);
|
|
890
921
|
let path = '';
|
|
891
922
|
|
|
892
923
|
for (let index = 0; index < total; index += 1) {
|
|
@@ -1059,11 +1090,36 @@ PlotOverlay.displayName = 'Plot.Overlay';
|
|
|
1059
1090
|
PlotOverlay.layer = 'overlay' as Layer;
|
|
1060
1091
|
|
|
1061
1092
|
export interface PlotRuleProps {
|
|
1062
|
-
/**
|
|
1063
|
-
|
|
1093
|
+
/**
|
|
1094
|
+
* Where to draw it, in the data's own units. Omit it and pass `x` instead for
|
|
1095
|
+
* a rule down the plot rather than across it.
|
|
1096
|
+
*/
|
|
1097
|
+
y?: number;
|
|
1098
|
+
/**
|
|
1099
|
+
* A row to draw a vertical rule at, by index — the release the numbers are
|
|
1100
|
+
* read against, the day a change landed.
|
|
1101
|
+
*
|
|
1102
|
+
* The x axis here carries positions rather than quantities, so this is which
|
|
1103
|
+
* row rather than what value. Exactly one of `y` and `x` is drawn; `y` wins
|
|
1104
|
+
* if both are given.
|
|
1105
|
+
*/
|
|
1106
|
+
x?: number;
|
|
1064
1107
|
/** A name for what the line means. Nothing is drawn without one. */
|
|
1065
1108
|
label?: string;
|
|
1109
|
+
/** Overrides the line *and* its caption, so the two cannot drift apart. */
|
|
1066
1110
|
color?: string;
|
|
1111
|
+
/** Thickness in points. */
|
|
1112
|
+
strokeWidth?: number;
|
|
1113
|
+
/**
|
|
1114
|
+
* Break the line into dashes, for a rule that should read as an annotation
|
|
1115
|
+
* rather than as a series the chart is drawing.
|
|
1116
|
+
*/
|
|
1117
|
+
dashed?: boolean;
|
|
1118
|
+
/** Fades the line and its caption together. */
|
|
1119
|
+
opacity?: number;
|
|
1120
|
+
/** Which end of the rule the caption sits at. */
|
|
1121
|
+
labelPlacement?: 'start' | 'end';
|
|
1122
|
+
labelClassName?: string;
|
|
1067
1123
|
className?: string;
|
|
1068
1124
|
}
|
|
1069
1125
|
|
|
@@ -1071,15 +1127,34 @@ export interface PlotRuleProps {
|
|
|
1071
1127
|
* A reference line across the plot — a target, a limit, an average.
|
|
1072
1128
|
*
|
|
1073
1129
|
* A view rather than an SVG line, so its label is real text and follows the
|
|
1074
|
-
* theme. Its
|
|
1130
|
+
* theme. Its thickness is a border and its position is a transform, so it costs
|
|
1075
1131
|
* no more than the SVG line would while gaining a legible caption.
|
|
1132
|
+
*
|
|
1133
|
+
* It is drawn at full strength in the foreground colour, and it is meant to be.
|
|
1134
|
+
* A reference line is the number the series is being judged against — a target
|
|
1135
|
+
* nobody can read is a target the chart is not actually stating — so what keeps
|
|
1136
|
+
* it from being mistaken for a series is that it is neutral and optionally
|
|
1137
|
+
* dashed, not that it is faint.
|
|
1076
1138
|
*/
|
|
1077
|
-
function PlotRule({
|
|
1078
|
-
|
|
1079
|
-
|
|
1139
|
+
function PlotRule({
|
|
1140
|
+
y,
|
|
1141
|
+
x,
|
|
1142
|
+
label,
|
|
1143
|
+
color,
|
|
1144
|
+
strokeWidth = 1,
|
|
1145
|
+
dashed = false,
|
|
1146
|
+
opacity = 1,
|
|
1147
|
+
labelPlacement = 'end',
|
|
1148
|
+
labelClassName,
|
|
1149
|
+
className,
|
|
1150
|
+
}: PlotRuleProps) {
|
|
1151
|
+
const { plot, domainMin, domainMax, status, data } = useChart('Plot.Rule');
|
|
1152
|
+
const token = useCSSVariable('--color-foreground');
|
|
1080
1153
|
const stroke = color ?? (typeof token === 'string' ? token : '#888888');
|
|
1154
|
+
const vertical = y === undefined && x !== undefined;
|
|
1081
1155
|
|
|
1082
|
-
const
|
|
1156
|
+
const horizontalStyle = useAnimatedStyle(() => {
|
|
1157
|
+
if (vertical || y === undefined) return { opacity: 0 };
|
|
1083
1158
|
const min = domainMin.value;
|
|
1084
1159
|
const max = domainMax.value;
|
|
1085
1160
|
if (max === min) return { opacity: 0 };
|
|
@@ -1087,23 +1162,92 @@ function PlotRule({ y, label, color, className }: PlotRuleProps) {
|
|
|
1087
1162
|
// Off the top or bottom of the plot is out of the chart's range, and a rule
|
|
1088
1163
|
// pinned to the edge would claim a value the axis does not cover.
|
|
1089
1164
|
const inside = at >= plot.top - 0.5 && at <= plot.top + plot.height + 0.5;
|
|
1090
|
-
return { opacity: inside ?
|
|
1165
|
+
return { opacity: inside ? opacity : 0, transform: [{ translateY: at }] };
|
|
1091
1166
|
});
|
|
1092
1167
|
|
|
1093
1168
|
if (status === 'loading') return null;
|
|
1094
1169
|
|
|
1170
|
+
const line = dashed
|
|
1171
|
+
? {
|
|
1172
|
+
borderColor: stroke,
|
|
1173
|
+
borderStyle: 'dashed' as const,
|
|
1174
|
+
borderTopWidth: strokeWidth,
|
|
1175
|
+
}
|
|
1176
|
+
: { backgroundColor: stroke, height: strokeWidth };
|
|
1177
|
+
|
|
1178
|
+
if (vertical) {
|
|
1179
|
+
/*
|
|
1180
|
+
* The x axis carries positions, not quantities, so a vertical rule is
|
|
1181
|
+
* placed from the row's own geometry rather than from the tweening domain —
|
|
1182
|
+
* there is nothing on this axis for it to tween against.
|
|
1183
|
+
*/
|
|
1184
|
+
const total = data.length;
|
|
1185
|
+
const at =
|
|
1186
|
+
total > 0
|
|
1187
|
+
? xOf(Math.max(0, Math.min(total - 1, x!)), total, plot)
|
|
1188
|
+
: plot.left + plot.width / 2;
|
|
1189
|
+
|
|
1190
|
+
return (
|
|
1191
|
+
<View
|
|
1192
|
+
pointerEvents="none"
|
|
1193
|
+
style={{
|
|
1194
|
+
position: 'absolute',
|
|
1195
|
+
left: at,
|
|
1196
|
+
top: plot.top,
|
|
1197
|
+
height: plot.height,
|
|
1198
|
+
opacity,
|
|
1199
|
+
}}
|
|
1200
|
+
className={className}
|
|
1201
|
+
>
|
|
1202
|
+
<View
|
|
1203
|
+
style={
|
|
1204
|
+
dashed
|
|
1205
|
+
? {
|
|
1206
|
+
borderColor: stroke,
|
|
1207
|
+
borderStyle: 'dashed',
|
|
1208
|
+
borderLeftWidth: strokeWidth,
|
|
1209
|
+
flex: 1,
|
|
1210
|
+
}
|
|
1211
|
+
: { backgroundColor: stroke, width: strokeWidth, flex: 1 }
|
|
1212
|
+
}
|
|
1213
|
+
/>
|
|
1214
|
+
{label ? (
|
|
1215
|
+
<Text
|
|
1216
|
+
size="xs"
|
|
1217
|
+
weight="medium"
|
|
1218
|
+
numberOfLines={1}
|
|
1219
|
+
style={color ? { color } : undefined}
|
|
1220
|
+
className={cn('absolute left-1 top-0', labelClassName)}
|
|
1221
|
+
>
|
|
1222
|
+
{label}
|
|
1223
|
+
</Text>
|
|
1224
|
+
) : null}
|
|
1225
|
+
</View>
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1095
1229
|
return (
|
|
1096
1230
|
<Animated.View
|
|
1097
1231
|
pointerEvents="none"
|
|
1098
1232
|
style={[
|
|
1099
1233
|
{ position: 'absolute', left: plot.left, width: plot.width, top: 0 },
|
|
1100
|
-
|
|
1234
|
+
horizontalStyle,
|
|
1101
1235
|
]}
|
|
1102
1236
|
className={className}
|
|
1103
1237
|
>
|
|
1104
|
-
<View style={
|
|
1238
|
+
<View style={line} />
|
|
1105
1239
|
{label ? (
|
|
1106
|
-
<Text
|
|
1240
|
+
<Text
|
|
1241
|
+
size="xs"
|
|
1242
|
+
weight="medium"
|
|
1243
|
+
numberOfLines={1}
|
|
1244
|
+
style={color ? { color } : undefined}
|
|
1245
|
+
className={cn(
|
|
1246
|
+
'pt-0.5',
|
|
1247
|
+
labelPlacement === 'start' ? 'self-start' : 'self-end',
|
|
1248
|
+
labelClassName
|
|
1249
|
+
)}
|
|
1250
|
+
>
|
|
1107
1251
|
{label}
|
|
1108
1252
|
</Text>
|
|
1109
1253
|
) : null}
|
|
@@ -59,7 +59,7 @@ import Animated, {
|
|
|
59
59
|
withTiming,
|
|
60
60
|
} from 'react-native-reanimated';
|
|
61
61
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
62
|
-
import {
|
|
62
|
+
import { FocusRestorePortal } from '../../primitives/portal';
|
|
63
63
|
import { Scrim } from '../../primitives/scrim';
|
|
64
64
|
import { useBackHandler } from '../../hooks/use-back-handler';
|
|
65
65
|
import { BottomSheet } from '../bottom-sheet';
|
|
@@ -535,7 +535,7 @@ function PopoverContent({
|
|
|
535
535
|
if (!open || !trigger) return null;
|
|
536
536
|
|
|
537
537
|
return (
|
|
538
|
-
<
|
|
538
|
+
<FocusRestorePortal>
|
|
539
539
|
{/* Portal content mounts under PortalHost, outside this provider's
|
|
540
540
|
subtree — re-provide the context so Popover.Close and Popover.Arrow
|
|
541
541
|
keep working. */}
|
|
@@ -609,7 +609,7 @@ function PopoverContent({
|
|
|
609
609
|
</Animated.View>
|
|
610
610
|
</View>
|
|
611
611
|
</PopoverContext.Provider>
|
|
612
|
-
</
|
|
612
|
+
</FocusRestorePortal>
|
|
613
613
|
);
|
|
614
614
|
}
|
|
615
615
|
|
|
@@ -198,7 +198,7 @@ const PostRoot = forwardRef<View, PostProps>(
|
|
|
198
198
|
|
|
199
199
|
if (!onPress) {
|
|
200
200
|
return (
|
|
201
|
-
<View ref={ref} className={root({ className })}
|
|
201
|
+
<View ref={ref} {...props} className={root({ className })}>
|
|
202
202
|
{body}
|
|
203
203
|
</View>
|
|
204
204
|
);
|
|
@@ -210,10 +210,10 @@ const PostRoot = forwardRef<View, PostProps>(
|
|
|
210
210
|
// as one button buries them.
|
|
211
211
|
<AnimatedPressable
|
|
212
212
|
ref={ref}
|
|
213
|
+
{...props}
|
|
213
214
|
accessibilityRole="link"
|
|
214
215
|
onPress={onPress}
|
|
215
216
|
className={root({ className })}
|
|
216
|
-
{...props}
|
|
217
217
|
>
|
|
218
218
|
{body}
|
|
219
219
|
</AnimatedPressable>
|
|
@@ -681,7 +681,7 @@ const PostMedia = forwardRef<View, PostMediaProps>(
|
|
|
681
681
|
|
|
682
682
|
if (!onPress) {
|
|
683
683
|
return (
|
|
684
|
-
<View ref={ref} className={media({ className })} style={{ aspectRatio }}
|
|
684
|
+
<View ref={ref} {...props} className={media({ className })} style={{ aspectRatio }}>
|
|
685
685
|
{picture}
|
|
686
686
|
</View>
|
|
687
687
|
);
|
|
@@ -690,12 +690,12 @@ const PostMedia = forwardRef<View, PostMediaProps>(
|
|
|
690
690
|
return (
|
|
691
691
|
<Pressable
|
|
692
692
|
ref={ref}
|
|
693
|
+
{...props}
|
|
693
694
|
accessibilityRole="imagebutton"
|
|
694
695
|
accessibilityLabel={alt}
|
|
695
696
|
onPress={onPress}
|
|
696
697
|
className={media({ className })}
|
|
697
698
|
style={{ aspectRatio }}
|
|
698
|
-
{...props}
|
|
699
699
|
>
|
|
700
700
|
{picture}
|
|
701
701
|
</Pressable>
|