panelui-native 0.66.1 → 0.68.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.
Files changed (129) hide show
  1. package/README.md +21 -1
  2. package/lib/module/components/area-chart/index.js +18 -1
  3. package/lib/module/components/area-chart/index.js.map +1 -1
  4. package/lib/module/components/bar-chart/index.js +18 -1
  5. package/lib/module/components/bar-chart/index.js.map +1 -1
  6. package/lib/module/components/candlestick-chart/index.js +18 -1
  7. package/lib/module/components/candlestick-chart/index.js.map +1 -1
  8. package/lib/module/components/form/index.js +7 -5
  9. package/lib/module/components/form/index.js.map +1 -1
  10. package/lib/module/components/form/typed-form.js +11 -0
  11. package/lib/module/components/form/typed-form.js.map +1 -0
  12. package/lib/module/components/form/use-form.js +4 -0
  13. package/lib/module/components/form/use-form.js.map +1 -1
  14. package/lib/module/components/heatmap-chart/index.js +27 -1
  15. package/lib/module/components/heatmap-chart/index.js.map +1 -1
  16. package/lib/module/components/line-chart/index.js +18 -1
  17. package/lib/module/components/line-chart/index.js.map +1 -1
  18. package/lib/module/components/message-scroller/index.js +172 -10
  19. package/lib/module/components/message-scroller/index.js.map +1 -1
  20. package/lib/module/components/message-scroller/message-scroller-math.js +23 -0
  21. package/lib/module/components/message-scroller/message-scroller-math.js.map +1 -1
  22. package/lib/module/components/meter/index.js +250 -0
  23. package/lib/module/components/meter/index.js.map +1 -0
  24. package/lib/module/components/meter/meter-scale.js +88 -0
  25. package/lib/module/components/meter/meter-scale.js.map +1 -0
  26. package/lib/module/components/planner/index.js +714 -0
  27. package/lib/module/components/planner/index.js.map +1 -0
  28. package/lib/module/components/planner/planner-entries.js +124 -0
  29. package/lib/module/components/planner/planner-entries.js.map +1 -0
  30. package/lib/module/components/radar-chart/index.js +18 -1
  31. package/lib/module/components/radar-chart/index.js.map +1 -1
  32. package/lib/module/components/scatter-chart/index.js +18 -1
  33. package/lib/module/components/scatter-chart/index.js.map +1 -1
  34. package/lib/module/components/skeleton/index.js +45 -7
  35. package/lib/module/components/skeleton/index.js.map +1 -1
  36. package/lib/module/components/spinner/index.js +63 -14
  37. package/lib/module/components/spinner/index.js.map +1 -1
  38. package/lib/module/components/time-picker/index.js +46 -21
  39. package/lib/module/components/time-picker/index.js.map +1 -1
  40. package/lib/module/components/time-picker/ruler-window.js +25 -0
  41. package/lib/module/components/time-picker/ruler-window.js.map +1 -0
  42. package/lib/module/hooks/breakpoint-contract.js +29 -0
  43. package/lib/module/hooks/breakpoint-contract.js.map +1 -0
  44. package/lib/module/hooks/index.js +1 -1
  45. package/lib/module/hooks/index.js.map +1 -1
  46. package/lib/module/hooks/use-breakpoint.js +46 -1
  47. package/lib/module/hooks/use-breakpoint.js.map +1 -1
  48. package/lib/module/index.js +3 -1
  49. package/lib/module/index.js.map +1 -1
  50. package/lib/module/primitives/chart-accessibility.js +68 -0
  51. package/lib/module/primitives/chart-accessibility.js.map +1 -0
  52. package/lib/typescript/src/components/area-chart/index.d.ts +2 -1
  53. package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
  54. package/lib/typescript/src/components/bar-chart/index.d.ts +2 -1
  55. package/lib/typescript/src/components/bar-chart/index.d.ts.map +1 -1
  56. package/lib/typescript/src/components/candlestick-chart/index.d.ts +2 -1
  57. package/lib/typescript/src/components/candlestick-chart/index.d.ts.map +1 -1
  58. package/lib/typescript/src/components/form/index.d.ts +18 -5
  59. package/lib/typescript/src/components/form/index.d.ts.map +1 -1
  60. package/lib/typescript/src/components/form/typed-form.d.ts +7 -0
  61. package/lib/typescript/src/components/form/typed-form.d.ts.map +1 -0
  62. package/lib/typescript/src/components/form/use-form.d.ts +4 -0
  63. package/lib/typescript/src/components/form/use-form.d.ts.map +1 -1
  64. package/lib/typescript/src/components/heatmap-chart/index.d.ts +2 -1
  65. package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
  66. package/lib/typescript/src/components/line-chart/index.d.ts +2 -1
  67. package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
  68. package/lib/typescript/src/components/message-scroller/index.d.ts +30 -2
  69. package/lib/typescript/src/components/message-scroller/index.d.ts.map +1 -1
  70. package/lib/typescript/src/components/message-scroller/message-scroller-math.d.ts +10 -0
  71. package/lib/typescript/src/components/message-scroller/message-scroller-math.d.ts.map +1 -1
  72. package/lib/typescript/src/components/meter/index.d.ts +270 -0
  73. package/lib/typescript/src/components/meter/index.d.ts.map +1 -0
  74. package/lib/typescript/src/components/meter/meter-scale.d.ts +57 -0
  75. package/lib/typescript/src/components/meter/meter-scale.d.ts.map +1 -0
  76. package/lib/typescript/src/components/planner/index.d.ts +274 -0
  77. package/lib/typescript/src/components/planner/index.d.ts.map +1 -0
  78. package/lib/typescript/src/components/planner/planner-entries.d.ts +75 -0
  79. package/lib/typescript/src/components/planner/planner-entries.d.ts.map +1 -0
  80. package/lib/typescript/src/components/radar-chart/index.d.ts +4 -0
  81. package/lib/typescript/src/components/radar-chart/index.d.ts.map +1 -1
  82. package/lib/typescript/src/components/scatter-chart/index.d.ts +2 -1
  83. package/lib/typescript/src/components/scatter-chart/index.d.ts.map +1 -1
  84. package/lib/typescript/src/components/skeleton/index.d.ts +25 -2
  85. package/lib/typescript/src/components/skeleton/index.d.ts.map +1 -1
  86. package/lib/typescript/src/components/spinner/index.d.ts +25 -2
  87. package/lib/typescript/src/components/spinner/index.d.ts.map +1 -1
  88. package/lib/typescript/src/components/time-picker/index.d.ts +5 -6
  89. package/lib/typescript/src/components/time-picker/index.d.ts.map +1 -1
  90. package/lib/typescript/src/components/time-picker/ruler-window.d.ts +12 -0
  91. package/lib/typescript/src/components/time-picker/ruler-window.d.ts.map +1 -0
  92. package/lib/typescript/src/hooks/breakpoint-contract.d.ts +6 -0
  93. package/lib/typescript/src/hooks/breakpoint-contract.d.ts.map +1 -0
  94. package/lib/typescript/src/hooks/index.d.ts +1 -1
  95. package/lib/typescript/src/hooks/index.d.ts.map +1 -1
  96. package/lib/typescript/src/hooks/use-breakpoint.d.ts +22 -0
  97. package/lib/typescript/src/hooks/use-breakpoint.d.ts.map +1 -1
  98. package/lib/typescript/src/index.d.ts +3 -1
  99. package/lib/typescript/src/index.d.ts.map +1 -1
  100. package/lib/typescript/src/primitives/chart-accessibility.d.ts +33 -0
  101. package/lib/typescript/src/primitives/chart-accessibility.d.ts.map +1 -0
  102. package/lib/typescript/types/form-api.type-test.d.ts +2 -0
  103. package/lib/typescript/types/form-api.type-test.d.ts.map +1 -0
  104. package/package.json +28 -2
  105. package/src/components/area-chart/index.tsx +27 -2
  106. package/src/components/bar-chart/index.tsx +27 -2
  107. package/src/components/candlestick-chart/index.tsx +30 -2
  108. package/src/components/form/index.tsx +32 -5
  109. package/src/components/form/typed-form.ts +13 -0
  110. package/src/components/form/use-form.ts +9 -0
  111. package/src/components/heatmap-chart/index.tsx +49 -3
  112. package/src/components/line-chart/index.tsx +27 -2
  113. package/src/components/message-scroller/index.tsx +234 -6
  114. package/src/components/message-scroller/message-scroller-math.ts +38 -0
  115. package/src/components/meter/index.tsx +318 -0
  116. package/src/components/meter/meter-scale.ts +109 -0
  117. package/src/components/planner/index.tsx +886 -0
  118. package/src/components/planner/planner-entries.ts +146 -0
  119. package/src/components/radar-chart/index.tsx +24 -0
  120. package/src/components/scatter-chart/index.tsx +27 -2
  121. package/src/components/skeleton/index.tsx +59 -5
  122. package/src/components/spinner/index.tsx +80 -13
  123. package/src/components/time-picker/index.tsx +57 -29
  124. package/src/components/time-picker/ruler-window.ts +24 -0
  125. package/src/hooks/breakpoint-contract.ts +31 -0
  126. package/src/hooks/index.ts +4 -0
  127. package/src/hooks/use-breakpoint.ts +61 -10
  128. package/src/index.ts +30 -0
  129. package/src/primitives/chart-accessibility.ts +102 -0
@@ -70,6 +70,7 @@ import Svg, {
70
70
  } from 'react-native-svg';
71
71
  import { useCSSVariable } from 'uniwind';
72
72
  import { Text } from '../../primitives/text';
73
+ import { ChartAccessibilityData, type ChartAccessibilityProps } from '../../primitives/chart-accessibility';
73
74
  import {
74
75
  areaPath,
75
76
  columnValues,
@@ -157,7 +158,7 @@ export function useAreaChart() {
157
158
  };
158
159
  }
159
160
 
160
- export interface AreaChartProps extends ViewProps {
161
+ export interface AreaChartProps extends ViewProps, ChartAccessibilityProps<AreaChartDatum> {
161
162
  className?: string;
162
163
  /** The rows. Each one is a point along the x-axis. */
163
164
  data: AreaChartDatum[];
@@ -233,6 +234,11 @@ const AreaChartRoot = forwardRef<AreaChartHandle, AreaChartProps>(function AreaC
233
234
  stacked = false,
234
235
  curve = 'monotone',
235
236
  onActiveIndexChange,
237
+ accessible,
238
+ accessibilityLabel,
239
+ accessibilityHint,
240
+ accessibilityLabelForDatum,
241
+ onAccessibilityDatumPress,
236
242
  compact = false,
237
243
  children,
238
244
  ...props
@@ -456,7 +462,26 @@ const AreaChartRoot = forwardRef<AreaChartHandle, AreaChartProps>(function AreaC
456
462
  <AreaChartContext.Provider value={context}>
457
463
  <View {...props} style={props.style} className={cn('w-full', className)}>
458
464
  {header}
459
- <View onLayout={onLayout} style={{ aspectRatio }} className="w-full">
465
+ <ChartAccessibilityData
466
+ chart="Area chart"
467
+ data={data}
468
+ disabled={accessible === false || loading}
469
+ accessibilityLabel={accessibilityLabel}
470
+ accessibilityHint={accessibilityHint}
471
+ accessibilityLabelForDatum={accessibilityLabelForDatum}
472
+ onAccessibilityDatumPress={onAccessibilityDatumPress}
473
+ valueOf={(datum) => [
474
+ [xDataKey, datum[xDataKey]],
475
+ ...series.map(([key]) => [key, datum[key]] as [string, unknown]),
476
+ ]}
477
+ />
478
+ <View
479
+ onLayout={onLayout}
480
+ style={{ aspectRatio }}
481
+ className="w-full"
482
+ accessibilityElementsHidden
483
+ importantForAccessibility="no-hide-descendants"
484
+ >
460
485
  {plot.width > 0 ? (
461
486
  <>
462
487
  <Svg width="100%" height="100%" style={StyleSheet.absoluteFill}>
@@ -65,6 +65,7 @@ import Animated, {
65
65
  import Svg, { Defs, G, Line as SvgLine, LinearGradient, Path, Stop } from 'react-native-svg';
66
66
  import { useCSSVariable } from 'uniwind';
67
67
  import { Text } from '../../primitives/text';
68
+ import { ChartAccessibilityData, type ChartAccessibilityProps } from '../../primitives/chart-accessibility';
68
69
  import {
69
70
  bandOf,
70
71
  barPath,
@@ -159,7 +160,7 @@ export function useBarChart() {
159
160
  };
160
161
  }
161
162
 
162
- export interface BarChartProps extends ViewProps {
163
+ export interface BarChartProps extends ViewProps, ChartAccessibilityProps<BarChartDatum> {
163
164
  className?: string;
164
165
  /** The rows. Each one is a band along the category axis. */
165
166
  data: BarChartDatum[];
@@ -257,6 +258,11 @@ const BarChartRoot = forwardRef<BarChartHandle, BarChartProps>(function BarChart
257
258
  minBarLength = 0,
258
259
  fadedOpacity = 0.3,
259
260
  onActiveIndexChange,
261
+ accessible,
262
+ accessibilityLabel,
263
+ accessibilityHint,
264
+ accessibilityLabelForDatum,
265
+ onAccessibilityDatumPress,
260
266
  compact = false,
261
267
  children,
262
268
  ...props
@@ -484,7 +490,26 @@ const BarChartRoot = forwardRef<BarChartHandle, BarChartProps>(function BarChart
484
490
  <BarChartContext.Provider value={context}>
485
491
  <View {...props} style={props.style} className={cn('w-full', className)}>
486
492
  {header}
487
- <View onLayout={onLayout} style={{ aspectRatio }} className="w-full">
493
+ <ChartAccessibilityData
494
+ chart="Bar chart"
495
+ data={data}
496
+ disabled={accessible === false || loading}
497
+ accessibilityLabel={accessibilityLabel}
498
+ accessibilityHint={accessibilityHint}
499
+ accessibilityLabelForDatum={accessibilityLabelForDatum}
500
+ onAccessibilityDatumPress={onAccessibilityDatumPress}
501
+ valueOf={(datum) => [
502
+ [xDataKey, datum[xDataKey]],
503
+ ...series.map(([key]) => [key, datum[key]] as [string, unknown]),
504
+ ]}
505
+ />
506
+ <View
507
+ onLayout={onLayout}
508
+ style={{ aspectRatio }}
509
+ className="w-full"
510
+ accessibilityElementsHidden
511
+ importantForAccessibility="no-hide-descendants"
512
+ >
488
513
  {plot.width > 0 ? (
489
514
  <>
490
515
  <Svg width="100%" height="100%" style={StyleSheet.absoluteFill}>
@@ -70,6 +70,7 @@ import Animated, {
70
70
  import Svg, { G, Line as SvgLine, Path } from 'react-native-svg';
71
71
  import { useCSSVariable } from 'uniwind';
72
72
  import { Text } from '../../primitives/text';
73
+ import { ChartAccessibilityData, type ChartAccessibilityProps } from '../../primitives/chart-accessibility';
73
74
  import { bandOf, compactNumber, yOf, type Plot } from '../../utils/chart';
74
75
  import { cn } from '../../utils/cn';
75
76
 
@@ -234,7 +235,7 @@ function ohlcOf(
234
235
  return { open, high, low, close };
235
236
  }
236
237
 
237
- export interface CandlestickChartProps extends ViewProps {
238
+ export interface CandlestickChartProps extends ViewProps, ChartAccessibilityProps<CandlestickChartDatum> {
238
239
  className?: string;
239
240
  /** The rows. Each one is a period along the x-axis. */
240
241
  data: CandlestickChartDatum[];
@@ -333,6 +334,11 @@ const CandlestickChartRoot = forwardRef<CandlestickChartHandle, CandlestickChart
333
334
  candleWidth,
334
335
  fadedOpacity = 0.3,
335
336
  onActiveIndexChange,
337
+ accessible,
338
+ accessibilityLabel,
339
+ accessibilityHint,
340
+ accessibilityLabelForDatum,
341
+ onAccessibilityDatumPress,
336
342
  compact = false,
337
343
  children,
338
344
  ...props
@@ -532,7 +538,29 @@ const CandlestickChartRoot = forwardRef<CandlestickChartHandle, CandlestickChart
532
538
  <CandlestickChartContext.Provider value={context}>
533
539
  <View {...props} style={props.style} className={cn('w-full', className)}>
534
540
  {header}
535
- <View onLayout={onLayout} style={{ aspectRatio }} className="w-full">
541
+ <ChartAccessibilityData
542
+ chart="Candlestick chart"
543
+ data={data}
544
+ disabled={accessible === false || loading}
545
+ accessibilityLabel={accessibilityLabel}
546
+ accessibilityHint={accessibilityHint}
547
+ accessibilityLabelForDatum={accessibilityLabelForDatum}
548
+ onAccessibilityDatumPress={onAccessibilityDatumPress}
549
+ valueOf={(datum) => [
550
+ [xDataKey, datum[xDataKey]],
551
+ [openDataKey, datum[openDataKey]],
552
+ [highDataKey, datum[highDataKey]],
553
+ [lowDataKey, datum[lowDataKey]],
554
+ [closeDataKey, datum[closeDataKey]],
555
+ ]}
556
+ />
557
+ <View
558
+ onLayout={onLayout}
559
+ style={{ aspectRatio }}
560
+ className="w-full"
561
+ accessibilityElementsHidden
562
+ importantForAccessibility="no-hide-descendants"
563
+ >
536
564
  {plot.width > 0 ? (
537
565
  <>
538
566
  <Svg width="100%" height="100%" style={StyleSheet.absoluteFill}>
@@ -7,11 +7,8 @@
7
7
  * take differently-shaped change props, and only the caller knows which one
8
8
  * a given field needs to wire up.
9
9
  *
10
- * `Form`/`Form.Field` trade some type precision for that JSX ergonomics — a
11
- * field's `name` isn't checked against `keyof YourValues` here, because a
12
- * value's shape can't flow through `useContext` generically. Reach for
13
- * `useField(form, name)` directly when a field's name should be checked
14
- * against the form's own value type.
10
+ * `createForm<Values>()` binds that value shape to the same runtime components
11
+ * when field names and render values should stay typed through JSX.
15
12
  *
16
13
  * ```tsx
17
14
  * const form = useForm({
@@ -37,6 +34,7 @@
37
34
  import { createContext, useContext, type ReactNode } from 'react';
38
35
  import { useField, type FormFieldRenderProps, type UseFieldOptions } from './use-field';
39
36
  import { useForm, type FormApi, type FieldErrors, type FieldTouched, type FieldState, type UseFormOptions, type Validator } from './use-form';
37
+ import { bindFormRuntime } from './typed-form';
40
38
 
41
39
  export { useForm, useField };
42
40
  export type {
@@ -57,6 +55,11 @@ export interface FormProps {
57
55
  children?: ReactNode;
58
56
  }
59
57
 
58
+ export interface TypedFormProps<T extends Record<string, any>> {
59
+ form: FormApi<T>;
60
+ children?: ReactNode;
61
+ }
62
+
60
63
  function FormRoot({ form, children }: FormProps) {
61
64
  return <FormContext.Provider value={form}>{children}</FormContext.Provider>;
62
65
  }
@@ -70,6 +73,14 @@ export interface FormFieldProps {
70
73
  children: (field: FormFieldRenderProps<any>) => ReactNode;
71
74
  }
72
75
 
76
+ export interface TypedFormFieldProps<
77
+ T extends Record<string, any>,
78
+ K extends keyof T,
79
+ > extends UseFieldOptions<T, K> {
80
+ name: K;
81
+ children: (field: FormFieldRenderProps<T[K]>) => ReactNode;
82
+ }
83
+
73
84
  function FormField({ name, validate, validateOn, children }: FormFieldProps) {
74
85
  const form = useContext(FormContext);
75
86
  if (!form) {
@@ -83,3 +94,19 @@ FormField.displayName = 'Form.Field';
83
94
  export const Form = Object.assign(FormRoot, {
84
95
  Field: FormField,
85
96
  });
97
+
98
+ export interface TypedForm<T extends Record<string, any>> {
99
+ (props: TypedFormProps<T>): ReactNode;
100
+ Field: <K extends keyof T>(props: TypedFormFieldProps<T, K>) => ReactNode;
101
+ useForm: (options: UseFormOptions<T>) => FormApi<T>;
102
+ useField: <K extends keyof T>(
103
+ form: FormApi<T>,
104
+ name: K,
105
+ options?: UseFieldOptions<T, K>
106
+ ) => FormFieldRenderProps<T[K]>;
107
+ }
108
+
109
+ /** Bind a value shape to Form's existing runtime without creating new state. */
110
+ export function createForm<T extends Record<string, any>>(): TypedForm<T> {
111
+ return bindFormRuntime(FormRoot, FormField, useForm, useField) as TypedForm<T>;
112
+ }
@@ -0,0 +1,13 @@
1
+ /** Attach bound helpers to the existing runtime components; no state is cloned. */
2
+ export function bindFormRuntime<
3
+ Root,
4
+ Field,
5
+ UseForm,
6
+ UseField,
7
+ >(root: Root, field: Field, useForm: UseForm, useField: UseField) {
8
+ return Object.assign(root as object, { Field: field, useForm, useField }) as Root & {
9
+ Field: Field;
10
+ useForm: UseForm;
11
+ useField: UseField;
12
+ };
13
+ }
@@ -67,6 +67,10 @@ export interface FormApi<T extends Record<string, any>> {
67
67
  setFieldValue: <K extends keyof T>(name: K, value: T[K]) => void;
68
68
  setFieldTouched: <K extends keyof T>(name: K, touched?: boolean) => void;
69
69
  setFieldError: <K extends keyof T>(name: K, error: string | undefined) => void;
70
+ /** Read the latest value, including a change made before React renders again. */
71
+ getValue: <K extends keyof T>(name: K) => T[K];
72
+ /** Read a field from this render so a component naturally follows its changes. */
73
+ watch: <K extends keyof T>(name: K) => T[K];
70
74
  getFieldState: <K extends keyof T>(name: K) => FieldState<T[K]>;
71
75
  /** Used by `useField`/`Form.Field` to attach a field's validation rule. */
72
76
  registerValidator: <K extends keyof T>(name: K, validator?: Validator<T, K>) => void;
@@ -249,6 +253,9 @@ export function useForm<T extends Record<string, any>>({
249
253
  [state.values, state.errors, state.touched]
250
254
  );
251
255
 
256
+ const getValue = useCallback(<K extends keyof T>(name: K): T[K] => valuesRef.current[name], []);
257
+ const watch = useCallback(<K extends keyof T>(name: K): T[K] => state.values[name], [state.values]);
258
+
252
259
  const validateField = useCallback(async <K extends keyof T>(name: K) => {
253
260
  const validator = validatorsRef.current[name];
254
261
  if (!validator) return true;
@@ -369,6 +376,8 @@ export function useForm<T extends Record<string, any>>({
369
376
  setFieldValue,
370
377
  setFieldTouched,
371
378
  setFieldError,
379
+ getValue,
380
+ watch,
372
381
  getFieldState,
373
382
  registerValidator,
374
383
  validateField,
@@ -61,6 +61,7 @@ import Animated, {
61
61
  import Svg, { ClipPath, Defs, G, Line as SvgLine, Rect } from 'react-native-svg';
62
62
  import { useCSSVariable } from 'uniwind';
63
63
  import { Text } from '../../primitives/text';
64
+ import { ChartAccessibilityData, type ChartAccessibilityProps } from '../../primitives/chart-accessibility';
64
65
  import { cn } from '../../utils/cn';
65
66
  import { normalizeWeekStart, startOfDay } from '../../utils/date';
66
67
 
@@ -309,7 +310,7 @@ function deriveLevels(data: HeatmapColumn[]): number[] {
309
310
  /* Root */
310
311
  /* -------------------------------------------------------------------------- */
311
312
 
312
- export interface HeatmapChartProps extends ViewProps {
313
+ export interface HeatmapChartProps extends ViewProps, ChartAccessibilityProps<HeatmapCell> {
313
314
  className?: string;
314
315
  /** One column per period, with its row bins inside. */
315
316
  data: HeatmapColumn[];
@@ -396,6 +397,11 @@ const HeatmapChartRoot = forwardRef<View, HeatmapChartProps>(function HeatmapCha
396
397
  animationDuration = 900,
397
398
  inactiveOpacity = 1,
398
399
  onActiveCellChange,
400
+ accessible,
401
+ accessibilityLabel,
402
+ accessibilityHint,
403
+ accessibilityLabelForDatum,
404
+ onAccessibilityDatumPress,
399
405
  children,
400
406
  ...props
401
407
  },
@@ -491,6 +497,20 @@ const HeatmapChartRoot = forwardRef<View, HeatmapChartProps>(function HeatmapCha
491
497
  [data, levelOf]
492
498
  );
493
499
 
500
+ const accessibilityCells = useMemo(
501
+ () =>
502
+ data.flatMap((column) =>
503
+ column.bins.map((bin) => ({
504
+ column: column.bin,
505
+ row: bin.bin,
506
+ count: bin.count,
507
+ level: levelOf(bin.count),
508
+ date: bin.date,
509
+ }))
510
+ ),
511
+ [data, levelOf]
512
+ );
513
+
494
514
  const setActiveCell = useMemo(
495
515
  () => (cell: HeatmapCell | null) => {
496
516
  setActiveCellState(cell);
@@ -570,11 +590,37 @@ const HeatmapChartRoot = forwardRef<View, HeatmapChartProps>(function HeatmapCha
570
590
  whole chart, so it starts at the chart's edge, not the grid's. */}
571
591
  {parts.header}
572
592
 
593
+ <ChartAccessibilityData
594
+ chart="Heatmap chart"
595
+ data={accessibilityCells}
596
+ disabled={accessible === false}
597
+ accessibilityLabel={accessibilityLabel}
598
+ accessibilityHint={accessibilityHint}
599
+ accessibilityLabelForDatum={accessibilityLabelForDatum}
600
+ onAccessibilityDatumPress={onAccessibilityDatumPress}
601
+ valueOf={(cell) => [
602
+ ['date', cell.date],
603
+ ['column', cell.column],
604
+ ['row', cell.row],
605
+ ['count', cell.count],
606
+ ]}
607
+ />
608
+
573
609
  {parts.x ? (
574
- <View style={{ paddingLeft: axisWidth }}>{parts.x}</View>
610
+ <View
611
+ style={{ paddingLeft: axisWidth }}
612
+ accessibilityElementsHidden
613
+ importantForAccessibility="no-hide-descendants"
614
+ >
615
+ {parts.x}
616
+ </View>
575
617
  ) : null}
576
618
 
577
- <View className="flex-row">
619
+ <View
620
+ className="flex-row"
621
+ accessibilityElementsHidden
622
+ importantForAccessibility="no-hide-descendants"
623
+ >
578
624
  {parts.y}
579
625
  <View style={{ width: grid.width, height: grid.height }}>
580
626
  {grid.width > 0 ? (
@@ -82,6 +82,7 @@ import Svg, {
82
82
  } from 'react-native-svg';
83
83
  import { useCSSVariable } from 'uniwind';
84
84
  import { Text } from '../../primitives/text';
85
+ import { ChartAccessibilityData, type ChartAccessibilityProps } from '../../primitives/chart-accessibility';
85
86
  import {
86
87
  areaPath,
87
88
  columnValues,
@@ -172,7 +173,7 @@ export function useLineChart() {
172
173
  };
173
174
  }
174
175
 
175
- export interface LineChartProps extends ViewProps {
176
+ export interface LineChartProps extends ViewProps, ChartAccessibilityProps<LineChartDatum> {
176
177
  className?: string;
177
178
  /** The rows. Each one is a point along the x-axis. */
178
179
  data: LineChartDatum[];
@@ -227,6 +228,11 @@ const LineChartRoot = forwardRef<LineChartHandle, LineChartProps>(function LineC
227
228
  yDomain,
228
229
  curve = 'monotone',
229
230
  onActiveIndexChange,
231
+ accessible,
232
+ accessibilityLabel,
233
+ accessibilityHint,
234
+ accessibilityLabelForDatum,
235
+ onAccessibilityDatumPress,
230
236
  compact = false,
231
237
  children,
232
238
  ...props
@@ -443,7 +449,26 @@ const LineChartRoot = forwardRef<LineChartHandle, LineChartProps>(function LineC
443
449
  <LineChartContext.Provider value={context}>
444
450
  <View {...props} style={props.style} className={cn('w-full', className)}>
445
451
  {header}
446
- <View onLayout={onLayout} style={{ aspectRatio }} className="w-full">
452
+ <ChartAccessibilityData
453
+ chart="Line chart"
454
+ data={data}
455
+ disabled={accessible === false || loading}
456
+ accessibilityLabel={accessibilityLabel}
457
+ accessibilityHint={accessibilityHint}
458
+ accessibilityLabelForDatum={accessibilityLabelForDatum}
459
+ onAccessibilityDatumPress={onAccessibilityDatumPress}
460
+ valueOf={(datum) => [
461
+ [xDataKey, datum[xDataKey]],
462
+ ...series.map(([key]) => [key, datum[key]] as [string, unknown]),
463
+ ]}
464
+ />
465
+ <View
466
+ onLayout={onLayout}
467
+ style={{ aspectRatio }}
468
+ className="w-full"
469
+ accessibilityElementsHidden
470
+ importantForAccessibility="no-hide-descendants"
471
+ >
447
472
  {plot.width > 0 ? (
448
473
  <>
449
474
  <Svg width="100%" height="100%" style={StyleSheet.absoluteFill}>