chore: rename LabelConfig -> AriaLabelConfig, update dict names
This commit is contained in:
@@ -4,5 +4,5 @@
|
||||
"@xyflow/system": patch
|
||||
---
|
||||
|
||||
Add `labelConfig` prop for customizing UI text like aria labels and descriptions.
|
||||
Add `ariaLabelConfig` prop for customizing UI text like aria labels and descriptions.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Node,
|
||||
Edge,
|
||||
OnNodeDrag,
|
||||
LabelConfig,
|
||||
AriaLabelConfig,
|
||||
} from '@xyflow/react';
|
||||
|
||||
const onNodeDrag: OnNodeDrag = (_, node: Node, nodes: Node[]) => console.log('drag', node, nodes);
|
||||
@@ -44,17 +44,17 @@ const initialEdges: Edge[] = [
|
||||
{ id: 'e1-3', source: '1', target: '3' },
|
||||
];
|
||||
|
||||
const labelConfig: Partial<LabelConfig> = {
|
||||
'a11yDescription.node.default': 'Custom Node Desc.',
|
||||
'a11yDescription.node.keyboardDisabled': 'Custom Keyboard Desc.',
|
||||
'a11yDescription.edge.default': 'Custom Edge Desc.',
|
||||
const ariaLabelConfig: Partial<AriaLabelConfig> = {
|
||||
'node.a11yDescription.default': 'Custom Node Desc.',
|
||||
'node.a11yDescription.keyboardDisabled': 'Custom Keyboard Desc.',
|
||||
'edge.a11yDescription.default': 'Custom Edge Desc.',
|
||||
'a11yDescription.ariaLiveMessage': ({ direction, x, y }) =>
|
||||
`Custom Moved selected node ${direction}. New position, x: ${x}, y: ${y}`,
|
||||
'controls.ariaLabel': 'Custom Controls Aria Label',
|
||||
'controls.zoomin.title': 'Custom Zoom in',
|
||||
'controls.zoomout.title': 'Custom Zoom Out',
|
||||
// 'controls.fitview.title': 'Custom Fit View',
|
||||
'controls.interactive.title': 'Custom Toggle Interactivity',
|
||||
'controls.zoomin.ariaLabel': 'Custom Zoom in',
|
||||
'controls.zoomout.ariaLabel': 'Custom Zoom Out',
|
||||
// 'controls.fitview.ariaLabel': 'Custom Fit View',
|
||||
'controls.interactive.ariaLabel': 'Custom Toggle Interactivity',
|
||||
'minimap.ariaLabel': 'Custom Aria Label',
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ const A11y = () => {
|
||||
elevateEdgesOnSelect
|
||||
elevateNodesOnSelect={false}
|
||||
nodeDragThreshold={0}
|
||||
labelConfig={labelConfig}
|
||||
ariaLabelConfig={ariaLabelConfig}
|
||||
>
|
||||
<Background variant={BackgroundVariant.Dots} />
|
||||
<MiniMap />
|
||||
|
||||
@@ -25,17 +25,17 @@
|
||||
bind:nodes
|
||||
bind:edges
|
||||
fitView
|
||||
labelConfig={{
|
||||
'a11yDescription.node.default': 'Svelte Custom Node Desc.',
|
||||
'a11yDescription.node.keyboardDisabled': 'Svelte Custom Keyboard Desc.',
|
||||
'a11yDescription.edge.default': 'Svelte Custom Edge Desc.',
|
||||
ariaLabelConfig={{
|
||||
'node.a11yDescription.default': 'Svelte Custom Node Desc.',
|
||||
'node.a11yDescription.keyboardDisabled': 'Svelte Custom Keyboard Desc.',
|
||||
'edge.a11yDescription.default': 'Svelte Custom Edge Desc.',
|
||||
'a11yDescription.ariaLiveMessage': ({ direction, x, y }) =>
|
||||
`Custom Moved selected node ${direction}. New position, x: ${x}, y: ${y}`,
|
||||
'controls.ariaLabel': 'Svelte Custom Control Aria Label',
|
||||
'controls.zoomin.title': 'Svelte Custom Zoom in',
|
||||
'controls.zoomout.title': 'Svelte Custom Zoom Out',
|
||||
// 'controls.fitview.title': 'Svelte Custom Fit View',
|
||||
'controls.interactive.title': 'Svelte Custom Toggle Interactivity',
|
||||
'controls.zoomin.ariaLabel': 'Svelte Custom Zoom in',
|
||||
'controls.zoomout.ariaLabel': 'Svelte Custom Zoom Out',
|
||||
// 'controls.fitview.ariaLabel': 'Svelte Custom Fit View',
|
||||
'controls.interactive.ariaLabel': 'Svelte Custom Toggle Interactivity',
|
||||
'minimap.ariaLabel': 'Svelte Custom Minimap'
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -19,7 +19,7 @@ const selector = (s: ReactFlowState) => ({
|
||||
isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable,
|
||||
minZoomReached: s.transform[2] <= s.minZoom,
|
||||
maxZoomReached: s.transform[2] >= s.maxZoom,
|
||||
labelConfig: s.labelConfig,
|
||||
ariaLabelConfig: s.ariaLabelConfig,
|
||||
});
|
||||
|
||||
function ControlsComponent({
|
||||
@@ -39,7 +39,7 @@ function ControlsComponent({
|
||||
'aria-label': ariaLabel,
|
||||
}: ControlProps) {
|
||||
const store = useStoreApi();
|
||||
const { isInteractive, minZoomReached, maxZoomReached, labelConfig } = useStore(selector, shallow);
|
||||
const { isInteractive, minZoomReached, maxZoomReached, ariaLabelConfig } = useStore(selector, shallow);
|
||||
const { zoomIn, zoomOut, fitView } = useReactFlow();
|
||||
|
||||
const onZoomInHandler = () => {
|
||||
@@ -74,15 +74,15 @@ function ControlsComponent({
|
||||
position={position}
|
||||
style={style}
|
||||
data-testid="rf__controls"
|
||||
aria-label={ariaLabel ?? labelConfig['controls.ariaLabel']}
|
||||
aria-label={ariaLabel ?? ariaLabelConfig['controls.ariaLabel']}
|
||||
>
|
||||
{showZoom && (
|
||||
<>
|
||||
<ControlButton
|
||||
onClick={onZoomInHandler}
|
||||
className="react-flow__controls-zoomin"
|
||||
title={labelConfig['controls.zoomin.title']}
|
||||
aria-label={labelConfig['controls.zoomin.title']}
|
||||
title={ariaLabelConfig['controls.zoomin.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.zoomin.ariaLabel']}
|
||||
disabled={maxZoomReached}
|
||||
>
|
||||
<PlusIcon />
|
||||
@@ -90,8 +90,8 @@ function ControlsComponent({
|
||||
<ControlButton
|
||||
onClick={onZoomOutHandler}
|
||||
className="react-flow__controls-zoomout"
|
||||
title={labelConfig['controls.zoomout.title']}
|
||||
aria-label={labelConfig['controls.zoomout.title']}
|
||||
title={ariaLabelConfig['controls.zoomout.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.zoomout.ariaLabel']}
|
||||
disabled={minZoomReached}
|
||||
>
|
||||
<MinusIcon />
|
||||
@@ -102,8 +102,8 @@ function ControlsComponent({
|
||||
<ControlButton
|
||||
className="react-flow__controls-fitview"
|
||||
onClick={onFitViewHandler}
|
||||
title={labelConfig['controls.fitview.title']}
|
||||
aria-label={labelConfig['controls.fitview.title']}
|
||||
title={ariaLabelConfig['controls.fitview.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.fitview.ariaLabel']}
|
||||
>
|
||||
<FitViewIcon />
|
||||
</ControlButton>
|
||||
@@ -112,8 +112,8 @@ function ControlsComponent({
|
||||
<ControlButton
|
||||
className="react-flow__controls-interactive"
|
||||
onClick={onToggleInteractivity}
|
||||
title={labelConfig['controls.interactive.title']}
|
||||
aria-label={labelConfig['controls.interactive.title']}
|
||||
title={ariaLabelConfig['controls.interactive.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.interactive.ariaLabel']}
|
||||
>
|
||||
{isInteractive ? <UnlockIcon /> : <LockIcon />}
|
||||
</ControlButton>
|
||||
|
||||
@@ -36,7 +36,7 @@ const selector = (s: ReactFlowState) => {
|
||||
translateExtent: s.translateExtent,
|
||||
flowWidth: s.width,
|
||||
flowHeight: s.height,
|
||||
labelConfig: s.labelConfig,
|
||||
ariaLabelConfig: s.ariaLabelConfig,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ function MiniMapComponent<NodeType extends Node = Node>({
|
||||
}: MiniMapProps<NodeType>) {
|
||||
const store = useStoreApi<NodeType>();
|
||||
const svg = useRef<SVGSVGElement>(null);
|
||||
const { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight, labelConfig } = useStore(
|
||||
const { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight, ariaLabelConfig } = useStore(
|
||||
selector,
|
||||
shallow
|
||||
);
|
||||
@@ -133,7 +133,7 @@ function MiniMapComponent<NodeType extends Node = Node>({
|
||||
}, [])
|
||||
: undefined;
|
||||
|
||||
const _ariaLabel = ariaLabel ?? labelConfig['minimap.ariaLabel'];
|
||||
const _ariaLabel = ariaLabel ?? ariaLabelConfig['minimap.ariaLabel'];
|
||||
|
||||
return (
|
||||
<Panel
|
||||
|
||||
@@ -21,7 +21,7 @@ export const ARIA_EDGE_DESC_KEY = 'react-flow__edge-desc';
|
||||
export const ARIA_LIVE_MESSAGE = 'react-flow__aria-live';
|
||||
|
||||
const ariaLiveSelector = (s: ReactFlowState) => s.ariaLiveMessage;
|
||||
const labelConfigSelector = (s: ReactFlowState) => s.labelConfig;
|
||||
const ariaLabelConfigSelector = (s: ReactFlowState) => s.ariaLabelConfig;
|
||||
|
||||
function AriaLiveMessage({ rfId }: { rfId: string }) {
|
||||
const ariaLiveMessage = useStore(ariaLiveSelector);
|
||||
@@ -34,17 +34,17 @@ function AriaLiveMessage({ rfId }: { rfId: string }) {
|
||||
}
|
||||
|
||||
export function A11yDescriptions({ rfId, disableKeyboardA11y }: { rfId: string; disableKeyboardA11y: boolean }) {
|
||||
const labelConfig = useStore(labelConfigSelector);
|
||||
const ariaLabelConfig = useStore(ariaLabelConfigSelector);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id={`${ARIA_NODE_DESC_KEY}-${rfId}`} style={style}>
|
||||
{disableKeyboardA11y
|
||||
? labelConfig['a11yDescription.node.default']
|
||||
: labelConfig['a11yDescription.node.keyboardDisabled']}
|
||||
? ariaLabelConfig['node.a11yDescription.default']
|
||||
: ariaLabelConfig['node.a11yDescription.keyboardDisabled']}
|
||||
</div>
|
||||
<div id={`${ARIA_EDGE_DESC_KEY}-${rfId}`} style={style}>
|
||||
{labelConfig['a11yDescription.edge.default']}
|
||||
{ariaLabelConfig['edge.a11yDescription.default']}
|
||||
</div>
|
||||
{!disableKeyboardA11y && <AriaLiveMessage rfId={rfId} />}
|
||||
</>
|
||||
|
||||
@@ -142,10 +142,10 @@ export function NodeWrapper<NodeType extends Node>({
|
||||
// prevent default scrolling behavior on arrow key press when node is moved
|
||||
event.preventDefault();
|
||||
|
||||
const { labelConfig } = store.getState();
|
||||
const { ariaLabelConfig } = store.getState();
|
||||
|
||||
store.setState({
|
||||
ariaLiveMessage: labelConfig['a11yDescription.ariaLiveMessage']({
|
||||
ariaLiveMessage: ariaLabelConfig['a11yDescription.ariaLiveMessage']({
|
||||
direction: event.key.replace('Arrow', '').toLowerCase(),
|
||||
x: ~~internals.positionAbsolute.x,
|
||||
y: ~~internals.positionAbsolute.y,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { infiniteExtent, type CoordinateExtent, mergeLabelConfig, LabelConfig } from '@xyflow/system';
|
||||
import { infiniteExtent, type CoordinateExtent, mergeAriaLabelConfig, AriaLabelConfig } from '@xyflow/system';
|
||||
|
||||
import { useStore, useStoreApi } from '../../hooks/useStore';
|
||||
import type { Node, Edge, ReactFlowState, ReactFlowProps, FitViewOptions } from '../../types';
|
||||
@@ -68,7 +68,7 @@ const reactFlowFieldsToTrack = [
|
||||
'debug',
|
||||
'autoPanSpeed',
|
||||
'paneClickDistance',
|
||||
'labelConfig',
|
||||
'ariaLabelConfig',
|
||||
] as const;
|
||||
|
||||
type ReactFlowFieldsToTrack = (typeof reactFlowFieldsToTrack)[number];
|
||||
@@ -158,8 +158,8 @@ export function StoreUpdater<NodeType extends Node = Node, EdgeType extends Edge
|
||||
else if (fieldName === 'fitView') store.setState({ fitViewQueued: fieldValue as boolean });
|
||||
else if (fieldName === 'fitViewOptions') store.setState({ fitViewOptions: fieldValue as FitViewOptions });
|
||||
|
||||
if (fieldName === 'labelConfig') {
|
||||
store.setState({ labelConfig: mergeLabelConfig(fieldValue as LabelConfig) });
|
||||
if (fieldName === 'ariaLabelConfig') {
|
||||
store.setState({ ariaLabelConfig: mergeAriaLabelConfig(fieldValue as AriaLabelConfig) });
|
||||
}
|
||||
// General case
|
||||
else store.setState({ [fieldName]: fieldValue });
|
||||
|
||||
@@ -145,7 +145,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
colorMode = 'light',
|
||||
debug,
|
||||
onScroll,
|
||||
labelConfig,
|
||||
ariaLabelConfig,
|
||||
...rest
|
||||
}: ReactFlowProps<NodeType, EdgeType>,
|
||||
ref: ForwardedRef<HTMLDivElement>
|
||||
@@ -306,7 +306,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
|
||||
onBeforeDelete={onBeforeDelete}
|
||||
paneClickDistance={paneClickDistance}
|
||||
debug={debug}
|
||||
labelConfig={labelConfig}
|
||||
ariaLabelConfig={ariaLabelConfig}
|
||||
/>
|
||||
<SelectionListener<NodeType, EdgeType> onSelectionChange={onSelectionChange} />
|
||||
{children}
|
||||
|
||||
@@ -108,7 +108,7 @@ export {
|
||||
type NoConnection,
|
||||
type NodeConnection,
|
||||
type OnReconnect,
|
||||
type LabelConfig,
|
||||
type AriaLabelConfig,
|
||||
} from '@xyflow/system';
|
||||
|
||||
// we need this workaround to prevent a duplicate identifier error
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
NodeOrigin,
|
||||
initialConnection,
|
||||
CoordinateExtent,
|
||||
defaultLabelConfig,
|
||||
defaultAriaLabelConfig,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type { Edge, FitViewOptions, InternalNode, Node, ReactFlowStore } from '../types';
|
||||
@@ -142,7 +142,7 @@ const getInitialState = ({
|
||||
|
||||
lib: 'react',
|
||||
debug: false,
|
||||
labelConfig: defaultLabelConfig,
|
||||
ariaLabelConfig: defaultAriaLabelConfig,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import type {
|
||||
ColorMode,
|
||||
SnapGrid,
|
||||
OnReconnect,
|
||||
LabelConfig,
|
||||
AriaLabelConfig,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -671,5 +671,5 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
|
||||
* Configuration for customizable labels, descriptions, and UI text. Provided keys will override the corresponding defaults.
|
||||
* Allows localization, customization of ARIA descriptions, control labels, minimap labels, and other UI strings.
|
||||
*/
|
||||
labelConfig?: Partial<LabelConfig>;
|
||||
ariaLabelConfig?: Partial<AriaLabelConfig>;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
type NodeChange,
|
||||
type EdgeChange,
|
||||
type ParentLookup,
|
||||
type LabelConfig,
|
||||
type AriaLabelConfig,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -148,7 +148,7 @@ export type ReactFlowStore<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
|
||||
lib: string;
|
||||
debug: boolean;
|
||||
labelConfig: LabelConfig;
|
||||
ariaLabelConfig: AriaLabelConfig;
|
||||
};
|
||||
|
||||
export type ReactFlowActions<NodeType extends Node, EdgeType extends Edge> = {
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
<div id={`${ARIA_NODE_DESC_KEY}-${store.flowId}`} class="a11y-hidden">
|
||||
{store.disableKeyboardA11y
|
||||
? store.labelConfig['a11yDescription.node.default']
|
||||
: store.labelConfig['a11yDescription.node.keyboardDisabled']}
|
||||
? store.ariaLabelConfig['node.a11yDescription.default']
|
||||
: store.ariaLabelConfig['node.a11yDescription.keyboardDisabled']}
|
||||
</div>
|
||||
<div id={`${ARIA_EDGE_DESC_KEY}-${store.flowId}`} class="a11y-hidden">
|
||||
{store.labelConfig['a11yDescription.edge.default']}
|
||||
{store.ariaLabelConfig['edge.a11yDescription.default']}
|
||||
</div>
|
||||
|
||||
{#if !store.disableKeyboardA11y}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
);
|
||||
|
||||
let store = useStore();
|
||||
let labelConfig = $derived(store.labelConfig);
|
||||
let ariaLabelConfig = $derived(store.ariaLabelConfig);
|
||||
|
||||
|
||||
let prevConnections: Map<string, HandleConnection> | null = null;
|
||||
@@ -229,7 +229,7 @@ The Handle component is the part of a node that can be used to connect nodes.
|
||||
onkeypress={() => {}}
|
||||
{style}
|
||||
role="button"
|
||||
aria-label={labelConfig[`handle.ariaLabel`]}
|
||||
aria-label={ariaLabelConfig[`handle.ariaLabel`]}
|
||||
tabindex="-1"
|
||||
{...rest}
|
||||
>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
let prevTargetPosition: Position | undefined = targetPosition;
|
||||
|
||||
let NodeComponent = $derived(store.nodeTypes[type] ?? DefaultNode);
|
||||
let labelConfig = $derived(store.labelConfig);
|
||||
let ariaLabelConfig = $derived(store.ariaLabelConfig);
|
||||
|
||||
let connectableContext: ConnectableContext = {
|
||||
get value() {
|
||||
@@ -189,7 +189,7 @@
|
||||
) {
|
||||
// prevent default scrolling behavior on arrow key press when node is moved
|
||||
event.preventDefault();
|
||||
store.ariaLiveMessage = labelConfig['a11yDescription.ariaLiveMessage']({
|
||||
store.ariaLiveMessage = ariaLabelConfig['a11yDescription.ariaLiveMessage']({
|
||||
direction: event.key.replace('Arrow', '').toLowerCase(),
|
||||
x: ~~node.internals.positionAbsolute.x,
|
||||
y: ~~node.internals.positionAbsolute.y
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
noDragClass,
|
||||
noPanClass,
|
||||
noWheelClass,
|
||||
labelConfig,
|
||||
ariaLabelConfig,
|
||||
...divAttributes
|
||||
} = $derived(rest);
|
||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||
|
||||
@@ -21,7 +21,7 @@ import type {
|
||||
OnReconnect,
|
||||
OnReconnectStart,
|
||||
OnReconnectEnd,
|
||||
LabelConfig
|
||||
AriaLabelConfig
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -476,5 +476,5 @@ export type SvelteFlowProps<
|
||||
* Configuration for customizable labels, descriptions, and UI text. Provided keys will override the corresponding defaults.
|
||||
* Allows localization, customization of ARIA descriptions, control labels, minimap labels, and other UI strings.
|
||||
*/
|
||||
labelConfig?: Partial<LabelConfig>;
|
||||
ariaLabelConfig?: Partial<AriaLabelConfig>;
|
||||
};
|
||||
|
||||
@@ -113,7 +113,7 @@ export {
|
||||
type ResizeDragEvent,
|
||||
type IsValidConnection,
|
||||
type NodeConnection,
|
||||
type LabelConfig
|
||||
type AriaLabelConfig
|
||||
} from '@xyflow/system';
|
||||
|
||||
// system utils
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
);
|
||||
let minZoomReached = $derived(store.viewport.zoom <= store.minZoom);
|
||||
let maxZoomReached = $derived(store.viewport.zoom >= store.maxZoom);
|
||||
let labelConfig = $derived(store.labelConfig);
|
||||
let ariaLabelConfig = $derived(store.ariaLabelConfig);
|
||||
let orientationClass = $derived(orientation === 'horizontal' ? 'horizontal' : 'vertical');
|
||||
|
||||
const onZoomInHandler = () => {
|
||||
@@ -73,7 +73,7 @@
|
||||
class={['svelte-flow__controls', orientationClass, className]}
|
||||
{position}
|
||||
data-testid="svelte-flow__controls"
|
||||
aria-label={labelConfig['controls.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.ariaLabel']}
|
||||
{style}
|
||||
{...rest}
|
||||
>
|
||||
@@ -84,8 +84,8 @@
|
||||
<ControlButton
|
||||
onclick={onZoomInHandler}
|
||||
class="svelte-flow__controls-zoomin"
|
||||
title={labelConfig['controls.zoomin.title']}
|
||||
aria-label={labelConfig['controls.zoomin.title']}
|
||||
title={ariaLabelConfig['controls.zoomin.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.zoomin.ariaLabel']}
|
||||
disabled={maxZoomReached}
|
||||
{...buttonProps}
|
||||
>
|
||||
@@ -94,8 +94,8 @@
|
||||
<ControlButton
|
||||
onclick={onZoomOutHandler}
|
||||
class="svelte-flow__controls-zoomout"
|
||||
title={labelConfig['controls.zoomout.title']}
|
||||
aria-label={labelConfig['controls.zoomout.title']}
|
||||
title={ariaLabelConfig['controls.zoomout.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.zoomout.ariaLabel']}
|
||||
disabled={minZoomReached}
|
||||
{...buttonProps}
|
||||
>
|
||||
@@ -106,8 +106,8 @@
|
||||
<ControlButton
|
||||
class="svelte-flow__controls-fitview"
|
||||
onclick={onFitViewHandler}
|
||||
title={labelConfig['controls.fitview.title']}
|
||||
aria-label={labelConfig['controls.fitview.title']}
|
||||
title={ariaLabelConfig['controls.fitview.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.fitview.ariaLabel']}
|
||||
{...buttonProps}
|
||||
>
|
||||
<FitViewIcon />
|
||||
@@ -117,8 +117,8 @@
|
||||
<ControlButton
|
||||
class="svelte-flow__controls-interactive"
|
||||
onclick={onToggleInteractivity}
|
||||
title={labelConfig['controls.interactive.title']}
|
||||
aria-label={labelConfig['controls.interactive.title']}
|
||||
title={ariaLabelConfig['controls.interactive.ariaLabel']}
|
||||
aria-label={ariaLabelConfig['controls.interactive.ariaLabel']}
|
||||
{...buttonProps}
|
||||
>
|
||||
{#if isInteractive}<UnlockIcon />{:else}<LockIcon />{/if}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
}: MiniMapProps = $props();
|
||||
|
||||
let store = $derived(useStore());
|
||||
let labelConfig = $derived(store.labelConfig);
|
||||
let ariaLabelConfig = $derived(store.ariaLabelConfig);
|
||||
|
||||
const nodeColorFunc = nodeColor === undefined ? undefined : getAttrFunction(nodeColor);
|
||||
const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
|
||||
@@ -114,8 +114,8 @@
|
||||
zoomable
|
||||
}}
|
||||
>
|
||||
{#if ariaLabel ?? labelConfig['minimap.ariaLabel']}
|
||||
<title id={labelledBy}>{ariaLabel ?? labelConfig['minimap.ariaLabel']}</title>
|
||||
{#if ariaLabel ?? ariaLabelConfig['minimap.ariaLabel']}
|
||||
<title id={labelledBy}>{ariaLabel ?? ariaLabelConfig['minimap.ariaLabel']}</title>
|
||||
{/if}
|
||||
|
||||
{#each store.nodes as userNode (userNode.id)}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
getViewportForBounds,
|
||||
updateConnectionLookup,
|
||||
initialConnection,
|
||||
mergeLabelConfig,
|
||||
mergeAriaLabelConfig,
|
||||
type SelectionRect,
|
||||
type SnapGrid,
|
||||
type MarkerProps,
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
type OnReconnect,
|
||||
type OnReconnectStart,
|
||||
type OnReconnectEnd,
|
||||
type LabelConfig
|
||||
type AriaLabelConfig
|
||||
} from '@xyflow/system';
|
||||
|
||||
import DefaultNode from '$lib/components/nodes/DefaultNode.svelte';
|
||||
@@ -291,7 +291,9 @@ export function getInitialStore<NodeType extends Node = Node, EdgeType extends E
|
||||
noPanClass: string = $derived(signals.props.noPanClass ?? 'nopan');
|
||||
noDragClass: string = $derived(signals.props.noDragClass ?? 'nodrag');
|
||||
noWheelClass: string = $derived(signals.props.noWheelClass ?? 'nowheel');
|
||||
labelConfig: LabelConfig = $derived(mergeLabelConfig(signals.props.labelConfig));
|
||||
ariaLabelConfig: AriaLabelConfig = $derived(
|
||||
mergeAriaLabelConfig(signals.props.ariaLabelConfig)
|
||||
);
|
||||
|
||||
// _viewport is the internal viewport.
|
||||
// when binding to viewport, we operate on signals.viewport instead
|
||||
|
||||
@@ -37,22 +37,22 @@ export const infiniteExtent: CoordinateExtent = [
|
||||
|
||||
export const elementSelectionKeys = ['Enter', ' ', 'Escape'];
|
||||
|
||||
export const defaultLabelConfig = {
|
||||
'a11yDescription.node.default':
|
||||
export const defaultAriaLabelConfig = {
|
||||
'node.a11yDescription.default':
|
||||
'Press enter or space to select a node. Press delete to remove it and escape to cancel.',
|
||||
'a11yDescription.node.keyboardDisabled':
|
||||
'node.a11yDescription.keyboardDisabled':
|
||||
'Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.',
|
||||
'a11yDescription.edge.default':
|
||||
'edge.a11yDescription.default':
|
||||
'Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.',
|
||||
'a11yDescription.ariaLiveMessage': ({ direction, x, y }: { direction: string; x: number; y: number }) =>
|
||||
`Moved selected node ${direction}. New position, x: ${x}, y: ${y}`,
|
||||
|
||||
// Control elements
|
||||
'controls.ariaLabel': 'Control Panel',
|
||||
'controls.zoomin.title': 'Zoom In',
|
||||
'controls.zoomout.title': 'Zoom Out',
|
||||
'controls.fitview.title': 'Fit View',
|
||||
'controls.interactive.title': 'Toggle Interactivity',
|
||||
'controls.zoomin.ariaLabel': 'Zoom In',
|
||||
'controls.zoomout.ariaLabel': 'Zoom Out',
|
||||
'controls.fitview.ariaLabel': 'Fit View',
|
||||
'controls.interactive.ariaLabel': 'Toggle Interactivity',
|
||||
|
||||
// Mini map
|
||||
'minimap.ariaLabel': 'Mini Map',
|
||||
@@ -61,4 +61,4 @@ export const defaultLabelConfig = {
|
||||
'handle.ariaLabel': 'Handle',
|
||||
};
|
||||
|
||||
export type LabelConfig = typeof defaultLabelConfig;
|
||||
export type AriaLabelConfig = typeof defaultAriaLabelConfig;
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
import { type Viewport } from '../types';
|
||||
import { getNodePositionWithOrigin, isInternalNodeBase } from './graph';
|
||||
|
||||
import { defaultLabelConfig, type LabelConfig } from '../constants';
|
||||
import { defaultAriaLabelConfig, type AriaLabelConfig } from '../constants';
|
||||
|
||||
export const clamp = (val: number, min = 0, max = 1): number => Math.min(Math.max(val, min), max);
|
||||
|
||||
@@ -421,6 +421,6 @@ export function withResolvers<T>(): {
|
||||
return { promise, resolve, reject };
|
||||
}
|
||||
|
||||
export function mergeLabelConfig(partial?: Partial<LabelConfig>): LabelConfig {
|
||||
return { ...defaultLabelConfig, ...(partial || {}) };
|
||||
export function mergeAriaLabelConfig(partial?: Partial<AriaLabelConfig>): AriaLabelConfig {
|
||||
return { ...defaultAriaLabelConfig, ...(partial || {}) };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user