panelui-native 0.65.0 → 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.
- package/README.md +21 -1
- package/lib/module/components/area-chart/index.js +18 -1
- package/lib/module/components/area-chart/index.js.map +1 -1
- package/lib/module/components/bar-chart/index.js +18 -1
- package/lib/module/components/bar-chart/index.js.map +1 -1
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/candlestick-chart/index.js +18 -1
- package/lib/module/components/candlestick-chart/index.js.map +1 -1
- package/lib/module/components/carousel/carousel-lifecycle.js +51 -0
- package/lib/module/components/carousel/carousel-lifecycle.js.map +1 -0
- package/lib/module/components/carousel/index.js +61 -24
- package/lib/module/components/carousel/index.js.map +1 -1
- package/lib/module/components/context-menu/context-menu-invocation.js +23 -0
- package/lib/module/components/context-menu/context-menu-invocation.js.map +1 -0
- package/lib/module/components/context-menu/index.js +78 -9
- package/lib/module/components/context-menu/index.js.map +1 -1
- package/lib/module/components/dialog/index.js.map +1 -1
- package/lib/module/components/drawer/index.js.map +1 -1
- package/lib/module/components/flow/flow-accessibility.js +18 -2
- package/lib/module/components/flow/flow-accessibility.js.map +1 -1
- package/lib/module/components/flow/flow-identifiers.js +81 -0
- package/lib/module/components/flow/flow-identifiers.js.map +1 -0
- package/lib/module/components/flow/index.js +12 -18
- package/lib/module/components/flow/index.js.map +1 -1
- package/lib/module/components/form/index.js +7 -5
- package/lib/module/components/form/index.js.map +1 -1
- package/lib/module/components/form/typed-form.js +11 -0
- package/lib/module/components/form/typed-form.js.map +1 -0
- package/lib/module/components/form/use-form.js +4 -0
- package/lib/module/components/form/use-form.js.map +1 -1
- package/lib/module/components/heatmap-chart/index.js +27 -1
- package/lib/module/components/heatmap-chart/index.js.map +1 -1
- package/lib/module/components/line-chart/index.js +18 -1
- package/lib/module/components/line-chart/index.js.map +1 -1
- package/lib/module/components/message-scroller/index.js +187 -17
- package/lib/module/components/message-scroller/index.js.map +1 -1
- package/lib/module/components/message-scroller/message-scroller-math.js +43 -0
- package/lib/module/components/message-scroller/message-scroller-math.js.map +1 -0
- package/lib/module/components/meter/index.js +250 -0
- package/lib/module/components/meter/index.js.map +1 -0
- package/lib/module/components/meter/meter-scale.js +88 -0
- package/lib/module/components/meter/meter-scale.js.map +1 -0
- package/lib/module/components/planner/index.js +714 -0
- package/lib/module/components/planner/index.js.map +1 -0
- package/lib/module/components/planner/planner-entries.js +124 -0
- package/lib/module/components/planner/planner-entries.js.map +1 -0
- package/lib/module/components/popover/index.js.map +1 -1
- package/lib/module/components/radar-chart/index.js +18 -1
- package/lib/module/components/radar-chart/index.js.map +1 -1
- package/lib/module/components/scatter-chart/index.js +18 -1
- package/lib/module/components/scatter-chart/index.js.map +1 -1
- package/lib/module/components/selection-mode/index.js +26 -31
- package/lib/module/components/selection-mode/index.js.map +1 -1
- package/lib/module/components/selection-mode/selection-mode-contracts.js +48 -0
- package/lib/module/components/selection-mode/selection-mode-contracts.js.map +1 -0
- package/lib/module/components/signature/index.js +62 -20
- package/lib/module/components/signature/index.js.map +1 -1
- package/lib/module/components/signature/signature-accessibility.js +58 -0
- package/lib/module/components/signature/signature-accessibility.js.map +1 -0
- package/lib/module/components/skeleton/index.js +45 -7
- package/lib/module/components/skeleton/index.js.map +1 -1
- package/lib/module/components/slider/index.js +22 -18
- package/lib/module/components/slider/index.js.map +1 -1
- package/lib/module/components/spinner/index.js +63 -14
- package/lib/module/components/spinner/index.js.map +1 -1
- package/lib/module/components/time-picker/index.js +46 -21
- package/lib/module/components/time-picker/index.js.map +1 -1
- package/lib/module/components/time-picker/ruler-window.js +25 -0
- package/lib/module/components/time-picker/ruler-window.js.map +1 -0
- package/lib/module/hooks/breakpoint-contract.js +29 -0
- package/lib/module/hooks/breakpoint-contract.js.map +1 -0
- package/lib/module/hooks/index.js +1 -1
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/use-breakpoint.js +46 -1
- package/lib/module/hooks/use-breakpoint.js.map +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/primitives/chart-accessibility.js +68 -0
- package/lib/module/primitives/chart-accessibility.js.map +1 -0
- package/lib/module/primitives/scrim.js +94 -3
- package/lib/module/primitives/scrim.js.map +1 -1
- package/lib/typescript/src/components/area-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/bar-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/bar-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/bottom-sheet/index.d.ts +3 -0
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/candlestick-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/candlestick-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/carousel/carousel-lifecycle.d.ts +23 -0
- package/lib/typescript/src/components/carousel/carousel-lifecycle.d.ts.map +1 -0
- package/lib/typescript/src/components/carousel/index.d.ts +5 -2
- package/lib/typescript/src/components/carousel/index.d.ts.map +1 -1
- package/lib/typescript/src/components/context-menu/context-menu-invocation.d.ts +20 -0
- package/lib/typescript/src/components/context-menu/context-menu-invocation.d.ts.map +1 -0
- package/lib/typescript/src/components/context-menu/index.d.ts +18 -8
- package/lib/typescript/src/components/context-menu/index.d.ts.map +1 -1
- package/lib/typescript/src/components/dialog/index.d.ts +3 -0
- package/lib/typescript/src/components/dialog/index.d.ts.map +1 -1
- package/lib/typescript/src/components/drawer/index.d.ts +3 -0
- package/lib/typescript/src/components/drawer/index.d.ts.map +1 -1
- package/lib/typescript/src/components/flow/flow-accessibility.d.ts +8 -0
- package/lib/typescript/src/components/flow/flow-accessibility.d.ts.map +1 -1
- package/lib/typescript/src/components/flow/flow-identifiers.d.ts +24 -0
- package/lib/typescript/src/components/flow/flow-identifiers.d.ts.map +1 -0
- package/lib/typescript/src/components/flow/index.d.ts +6 -5
- package/lib/typescript/src/components/flow/index.d.ts.map +1 -1
- package/lib/typescript/src/components/form/index.d.ts +18 -5
- package/lib/typescript/src/components/form/index.d.ts.map +1 -1
- package/lib/typescript/src/components/form/typed-form.d.ts +7 -0
- package/lib/typescript/src/components/form/typed-form.d.ts.map +1 -0
- package/lib/typescript/src/components/form/use-form.d.ts +4 -0
- package/lib/typescript/src/components/form/use-form.d.ts.map +1 -1
- package/lib/typescript/src/components/heatmap-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/line-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/message-scroller/index.d.ts +30 -2
- package/lib/typescript/src/components/message-scroller/index.d.ts.map +1 -1
- package/lib/typescript/src/components/message-scroller/message-scroller-math.d.ts +18 -0
- package/lib/typescript/src/components/message-scroller/message-scroller-math.d.ts.map +1 -0
- package/lib/typescript/src/components/meter/index.d.ts +270 -0
- package/lib/typescript/src/components/meter/index.d.ts.map +1 -0
- package/lib/typescript/src/components/meter/meter-scale.d.ts +57 -0
- package/lib/typescript/src/components/meter/meter-scale.d.ts.map +1 -0
- package/lib/typescript/src/components/planner/index.d.ts +274 -0
- package/lib/typescript/src/components/planner/index.d.ts.map +1 -0
- package/lib/typescript/src/components/planner/planner-entries.d.ts +75 -0
- package/lib/typescript/src/components/planner/planner-entries.d.ts.map +1 -0
- package/lib/typescript/src/components/popover/index.d.ts +3 -0
- package/lib/typescript/src/components/popover/index.d.ts.map +1 -1
- package/lib/typescript/src/components/radar-chart/index.d.ts +4 -0
- package/lib/typescript/src/components/radar-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/scatter-chart/index.d.ts +2 -1
- package/lib/typescript/src/components/scatter-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/selection-mode/index.d.ts +6 -4
- package/lib/typescript/src/components/selection-mode/index.d.ts.map +1 -1
- package/lib/typescript/src/components/selection-mode/selection-mode-contracts.d.ts +18 -0
- package/lib/typescript/src/components/selection-mode/selection-mode-contracts.d.ts.map +1 -0
- package/lib/typescript/src/components/signature/index.d.ts +6 -0
- package/lib/typescript/src/components/signature/index.d.ts.map +1 -1
- package/lib/typescript/src/components/signature/signature-accessibility.d.ts +27 -0
- package/lib/typescript/src/components/signature/signature-accessibility.d.ts.map +1 -0
- package/lib/typescript/src/components/skeleton/index.d.ts +25 -2
- package/lib/typescript/src/components/skeleton/index.d.ts.map +1 -1
- package/lib/typescript/src/components/slider/index.d.ts.map +1 -1
- package/lib/typescript/src/components/spinner/index.d.ts +25 -2
- package/lib/typescript/src/components/spinner/index.d.ts.map +1 -1
- package/lib/typescript/src/components/time-picker/index.d.ts +5 -6
- package/lib/typescript/src/components/time-picker/index.d.ts.map +1 -1
- package/lib/typescript/src/components/time-picker/ruler-window.d.ts +12 -0
- package/lib/typescript/src/components/time-picker/ruler-window.d.ts.map +1 -0
- package/lib/typescript/src/hooks/breakpoint-contract.d.ts +6 -0
- package/lib/typescript/src/hooks/breakpoint-contract.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +1 -1
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-breakpoint.d.ts +22 -0
- package/lib/typescript/src/hooks/use-breakpoint.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/primitives/chart-accessibility.d.ts +33 -0
- package/lib/typescript/src/primitives/chart-accessibility.d.ts.map +1 -0
- package/lib/typescript/src/primitives/scrim.d.ts +5 -3
- package/lib/typescript/src/primitives/scrim.d.ts.map +1 -1
- package/lib/typescript/types/form-api.type-test.d.ts +2 -0
- package/lib/typescript/types/form-api.type-test.d.ts.map +1 -0
- package/package.json +34 -5
- package/src/components/area-chart/index.tsx +27 -2
- package/src/components/bar-chart/index.tsx +27 -2
- package/src/components/bottom-sheet/index.tsx +3 -0
- package/src/components/candlestick-chart/index.tsx +30 -2
- package/src/components/carousel/carousel-lifecycle.ts +74 -0
- package/src/components/carousel/index.tsx +80 -25
- package/src/components/context-menu/context-menu-invocation.ts +44 -0
- package/src/components/context-menu/index.tsx +113 -13
- package/src/components/dialog/index.tsx +3 -0
- package/src/components/drawer/index.tsx +3 -0
- package/src/components/flow/flow-accessibility.ts +16 -2
- package/src/components/flow/flow-identifiers.ts +98 -0
- package/src/components/flow/index.tsx +29 -19
- package/src/components/form/index.tsx +32 -5
- package/src/components/form/typed-form.ts +13 -0
- package/src/components/form/use-form.ts +9 -0
- package/src/components/heatmap-chart/index.tsx +49 -3
- package/src/components/line-chart/index.tsx +27 -2
- package/src/components/message-scroller/index.tsx +273 -13
- package/src/components/message-scroller/message-scroller-math.ts +62 -0
- package/src/components/meter/index.tsx +318 -0
- package/src/components/meter/meter-scale.ts +109 -0
- package/src/components/planner/index.tsx +886 -0
- package/src/components/planner/planner-entries.ts +146 -0
- package/src/components/popover/index.tsx +3 -0
- package/src/components/radar-chart/index.tsx +24 -0
- package/src/components/scatter-chart/index.tsx +27 -2
- package/src/components/selection-mode/index.tsx +37 -30
- package/src/components/selection-mode/selection-mode-contracts.ts +53 -0
- package/src/components/signature/index.tsx +107 -20
- package/src/components/signature/signature-accessibility.ts +67 -0
- package/src/components/skeleton/index.tsx +59 -5
- package/src/components/slider/index.tsx +28 -18
- package/src/components/spinner/index.tsx +80 -13
- package/src/components/time-picker/index.tsx +57 -29
- package/src/components/time-picker/ruler-window.ts +24 -0
- package/src/hooks/breakpoint-contract.ts +31 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/use-breakpoint.ts +61 -10
- package/src/index.ts +32 -0
- package/src/primitives/chart-accessibility.ts +102 -0
- package/src/primitives/scrim.tsx +127 -7
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const FLOW_TOKEN_PREFIX = 'panelui-flow:';
|
|
2
|
+
|
|
3
|
+
export interface FlowEndpoint {
|
|
4
|
+
node: string;
|
|
5
|
+
handle?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type FlowEndpointReference = string | FlowEndpoint;
|
|
9
|
+
|
|
10
|
+
type EncodedReference = ['legacy', string] | ['endpoint', string] | ['endpoint', string, string];
|
|
11
|
+
|
|
12
|
+
function encodedReference(reference: FlowEndpointReference): EncodedReference {
|
|
13
|
+
if (typeof reference === 'string') return ['legacy', reference];
|
|
14
|
+
return reference.handle === undefined
|
|
15
|
+
? ['endpoint', reference.node]
|
|
16
|
+
: ['endpoint', reference.node, reference.handle];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function decodedReference(value: unknown): FlowEndpointReference | undefined {
|
|
20
|
+
if (!Array.isArray(value)) return undefined;
|
|
21
|
+
if (value.length === 2 && value[0] === 'legacy' && typeof value[1] === 'string') {
|
|
22
|
+
return value[1];
|
|
23
|
+
}
|
|
24
|
+
if (
|
|
25
|
+
(value.length === 2 || value.length === 3) &&
|
|
26
|
+
value[0] === 'endpoint' &&
|
|
27
|
+
typeof value[1] === 'string' &&
|
|
28
|
+
(value.length === 2 || typeof value[2] === 'string')
|
|
29
|
+
) {
|
|
30
|
+
return value.length === 2 ? { node: value[1] } : { node: value[1], handle: value[2] };
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function decodeToken(token: string): unknown[] | undefined {
|
|
36
|
+
if (!token.startsWith(FLOW_TOKEN_PREFIX)) return undefined;
|
|
37
|
+
try {
|
|
38
|
+
const value: unknown = JSON.parse(token.slice(FLOW_TOKEN_PREFIX.length));
|
|
39
|
+
return Array.isArray(value) ? value : undefined;
|
|
40
|
+
} catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Opaque identity for a registered handle. Node and handle text remain untouched. */
|
|
46
|
+
export function encodeFlowHandleKey(node: string, handle: string): string {
|
|
47
|
+
return FLOW_TOKEN_PREFIX + JSON.stringify(['handle', node, handle]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function decodeFlowHandleKey(token: string): FlowEndpoint | undefined {
|
|
51
|
+
const value = decodeToken(token);
|
|
52
|
+
if (
|
|
53
|
+
value?.length !== 3 ||
|
|
54
|
+
value[0] !== 'handle' ||
|
|
55
|
+
typeof value[1] !== 'string' ||
|
|
56
|
+
typeof value[2] !== 'string'
|
|
57
|
+
) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return { node: value[1], handle: value[2] };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Opaque identity for an edge registration or accessibility connection action. */
|
|
64
|
+
export function encodeFlowEdgeKey(
|
|
65
|
+
from: FlowEndpointReference,
|
|
66
|
+
to: FlowEndpointReference
|
|
67
|
+
): string {
|
|
68
|
+
return FLOW_TOKEN_PREFIX + JSON.stringify(['edge', encodedReference(from), encodedReference(to)]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function decodeFlowEdgeKey(
|
|
72
|
+
token: string
|
|
73
|
+
): { from: FlowEndpointReference; to: FlowEndpointReference } | undefined {
|
|
74
|
+
const value = decodeToken(token);
|
|
75
|
+
if (value?.length !== 3 || value[0] !== 'edge') return undefined;
|
|
76
|
+
const from = decodedReference(value[1]);
|
|
77
|
+
const to = decodedReference(value[2]);
|
|
78
|
+
return from === undefined || to === undefined ? undefined : { from, to };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a public endpoint without splitting its identifiers. Exact node ids
|
|
83
|
+
* win; legacy `node.handle` text is accepted only when it names one registered
|
|
84
|
+
* handle. Structured endpoints cover the otherwise ambiguous case.
|
|
85
|
+
*/
|
|
86
|
+
export function resolveFlowEndpoint(
|
|
87
|
+
reference: FlowEndpointReference,
|
|
88
|
+
nodes: readonly string[],
|
|
89
|
+
handles: readonly { node: string; id: string }[]
|
|
90
|
+
): FlowEndpoint {
|
|
91
|
+
if (typeof reference !== 'string') return reference;
|
|
92
|
+
if (nodes.includes(reference)) return { node: reference };
|
|
93
|
+
|
|
94
|
+
const matches = handles.filter((handle) => `${handle.node}.${handle.id}` === reference);
|
|
95
|
+
return matches.length === 1
|
|
96
|
+
? { node: matches[0]!.node, handle: matches[0]!.id }
|
|
97
|
+
: { node: reference };
|
|
98
|
+
}
|
|
@@ -107,6 +107,13 @@ import {
|
|
|
107
107
|
type FlowAccessibilityHandle,
|
|
108
108
|
type FlowAccessibilityNode,
|
|
109
109
|
} from './flow-accessibility';
|
|
110
|
+
import {
|
|
111
|
+
encodeFlowEdgeKey,
|
|
112
|
+
encodeFlowHandleKey,
|
|
113
|
+
resolveFlowEndpoint,
|
|
114
|
+
type FlowEndpoint,
|
|
115
|
+
type FlowEndpointReference,
|
|
116
|
+
} from './flow-identifiers';
|
|
110
117
|
|
|
111
118
|
const AnimatedPath = Animated.createAnimatedComponent(Path);
|
|
112
119
|
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
@@ -1314,7 +1321,7 @@ function FlowHandle({
|
|
|
1314
1321
|
unregisterHandle,
|
|
1315
1322
|
connectNodes,
|
|
1316
1323
|
} = flow;
|
|
1317
|
-
const key =
|
|
1324
|
+
const key = encodeFlowHandleKey(node, id);
|
|
1318
1325
|
|
|
1319
1326
|
useEffect(() => {
|
|
1320
1327
|
registerHandle({
|
|
@@ -1481,10 +1488,10 @@ FlowHandle.displayName = 'Flow.Handle';
|
|
|
1481
1488
|
/* -------------------------------------------------------------------------- */
|
|
1482
1489
|
|
|
1483
1490
|
export interface FlowEdgeProps {
|
|
1484
|
-
/** Source
|
|
1485
|
-
from:
|
|
1486
|
-
/** Target, same shape. */
|
|
1487
|
-
to:
|
|
1491
|
+
/** Source node or handle. Strings retain the `"nodeId.handleId"` shorthand. */
|
|
1492
|
+
from: FlowEndpointReference;
|
|
1493
|
+
/** Target node or handle, in the same shape. */
|
|
1494
|
+
to: FlowEndpointReference;
|
|
1488
1495
|
/** How the edge is routed. */
|
|
1489
1496
|
variant?: FlowEdgeVariant;
|
|
1490
1497
|
/**
|
|
@@ -1530,7 +1537,7 @@ export interface FlowEdgeProps {
|
|
|
1530
1537
|
*/
|
|
1531
1538
|
function FlowEdge(props: FlowEdgeProps) {
|
|
1532
1539
|
const { registerEdge, unregisterEdge } = useFlow('Flow.Edge');
|
|
1533
|
-
const key =
|
|
1540
|
+
const key = encodeFlowEdgeKey(props.from, props.to);
|
|
1534
1541
|
|
|
1535
1542
|
// Re-registered whenever any prop changes, so `animated` toggling or a
|
|
1536
1543
|
// variant switch reaches the layer that draws it.
|
|
@@ -1571,8 +1578,9 @@ function FlowEdgePath({
|
|
|
1571
1578
|
tint: string;
|
|
1572
1579
|
origin: { x: number; y: number };
|
|
1573
1580
|
}) {
|
|
1574
|
-
const
|
|
1575
|
-
const
|
|
1581
|
+
const nodes = Object.keys(boxes);
|
|
1582
|
+
const source = resolveEnd(from, fromSide, nodes, handles);
|
|
1583
|
+
const target = resolveEnd(to, toSide, nodes, handles);
|
|
1576
1584
|
|
|
1577
1585
|
const fromRect = boxes[source.node];
|
|
1578
1586
|
const toRect = boxes[target.node];
|
|
@@ -1631,22 +1639,24 @@ function FlowEdgePath({
|
|
|
1631
1639
|
}
|
|
1632
1640
|
|
|
1633
1641
|
/**
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1642
|
+
* Resolves a node or handle without parsing either identifier. Legacy
|
|
1643
|
+
* `"node.handle"` references are matched against the structured registry.
|
|
1636
1644
|
*/
|
|
1637
1645
|
function resolveEnd(
|
|
1638
|
-
reference:
|
|
1646
|
+
reference: FlowEndpointReference,
|
|
1639
1647
|
explicit: FlowSide | undefined,
|
|
1648
|
+
nodes: string[],
|
|
1640
1649
|
handles: HandleEntry[]
|
|
1641
1650
|
): { node: string; side: FlowSide | undefined; offset: number } {
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1651
|
+
const endpoint = resolveFlowEndpoint(reference, nodes, handles);
|
|
1652
|
+
const entry =
|
|
1653
|
+
endpoint.handle === undefined
|
|
1654
|
+
? undefined
|
|
1655
|
+
: handles.find(
|
|
1656
|
+
(handle) => handle.node === endpoint.node && handle.id === endpoint.handle
|
|
1657
|
+
);
|
|
1648
1658
|
return {
|
|
1649
|
-
node,
|
|
1659
|
+
node: endpoint.node,
|
|
1650
1660
|
side: explicit ?? entry?.side,
|
|
1651
1661
|
offset: entry?.offset ?? 0.5,
|
|
1652
1662
|
};
|
|
@@ -2199,4 +2209,4 @@ export const Flow = Object.assign(FlowRoot, {
|
|
|
2199
2209
|
MiniMap: FlowMiniMap,
|
|
2200
2210
|
});
|
|
2201
2211
|
|
|
2202
|
-
export type { FlowSide, FlowRect, FlowPoint };
|
|
2212
|
+
export type { FlowEndpoint, FlowEndpointReference, FlowSide, FlowRect, FlowPoint };
|
|
@@ -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
|
-
* `
|
|
11
|
-
* field
|
|
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
|
|
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
|
|
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
|
-
<
|
|
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}>
|