Feat: dark mode (#3652)
* feat(react/svelte): add dark mode defaults * refactor(darkmode): minimap, edges, edge labels * chore(style): edge label color * feat(colorMode): add colorMode prop light/dark/system * chore(examples): cleanup * test(colorMode): add tests * chore(base.css): add dark base * chore(examples): cleanup
This commit is contained in:
@@ -26,6 +26,6 @@ type DotPatternProps = {
|
||||
|
||||
export function DotPattern({ radius, className }: DotPatternProps) {
|
||||
return (
|
||||
<circle cx={radius} cy={radius} r={radius} className={cc(['react-flow__background-pattern', 'dot', className])} />
|
||||
<circle cx={radius} cy={radius} r={radius} className={cc(['react-flow__background-pattern', 'dots', className])} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { memo, useEffect, useRef, type MouseEvent, useCallback } from 'react';
|
||||
import { memo, useEffect, useRef, type MouseEvent, useCallback, CSSProperties } from 'react';
|
||||
import cc from 'classcat';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { getNodesBounds, getBoundsOfRects, XYMinimap, type Rect, type XYMinimapInstance } from '@xyflow/system';
|
||||
@@ -40,15 +40,15 @@ const ARIA_LABEL_KEY = 'react-flow__minimap-desc';
|
||||
function MiniMap({
|
||||
style,
|
||||
className,
|
||||
nodeStrokeColor = 'transparent',
|
||||
nodeColor = '#e2e2e2',
|
||||
nodeStrokeColor,
|
||||
nodeColor,
|
||||
nodeClassName = '',
|
||||
nodeBorderRadius = 5,
|
||||
nodeStrokeWidth = 2,
|
||||
nodeStrokeWidth,
|
||||
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
|
||||
// a component properly.
|
||||
nodeComponent,
|
||||
maskColor = 'rgb(240, 240, 240, 0.6)',
|
||||
maskColor,
|
||||
maskStrokeColor = 'none',
|
||||
maskStrokeWidth = 1,
|
||||
position = 'bottom-right',
|
||||
@@ -126,7 +126,15 @@ function MiniMap({
|
||||
return (
|
||||
<Panel
|
||||
position={position}
|
||||
style={style}
|
||||
style={
|
||||
{
|
||||
...style,
|
||||
'--minimap-mask-color-props': typeof maskColor === 'string' ? maskColor : undefined,
|
||||
'--minimap-node-background-color-props': typeof nodeColor === 'string' ? nodeColor : undefined,
|
||||
'--minimap-node-stroke-color-props': typeof nodeStrokeColor === 'string' ? nodeStrokeColor : undefined,
|
||||
'--minimap-node-stroke-width-props': typeof nodeStrokeWidth === 'string' ? nodeStrokeWidth : undefined,
|
||||
} as CSSProperties
|
||||
}
|
||||
className={cc(['react-flow__minimap', className])}
|
||||
data-testid="rf__minimap"
|
||||
>
|
||||
@@ -153,7 +161,6 @@ function MiniMap({
|
||||
className="react-flow__minimap-mask"
|
||||
d={`M${x - offset},${y - offset}h${width + offset * 2}v${height + offset * 2}h${-width - offset * 2}z
|
||||
M${viewBB.x},${viewBB.y}h${viewBB.width}v${viewBB.height}h${-viewBB.width}z`}
|
||||
fill={maskColor}
|
||||
fillRule="evenodd"
|
||||
stroke={maskStrokeColor}
|
||||
strokeWidth={maskStrokeWidth}
|
||||
|
||||
@@ -31,9 +31,11 @@ function MiniMapNode({
|
||||
ry={borderRadius}
|
||||
width={width}
|
||||
height={height}
|
||||
fill={fill}
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
style={{
|
||||
fill,
|
||||
stroke: strokeColor,
|
||||
strokeWidth,
|
||||
}}
|
||||
shapeRendering={shapeRendering}
|
||||
onClick={onClick ? (event) => onClick(event, id) : undefined}
|
||||
/>
|
||||
|
||||
@@ -19,11 +19,11 @@ const selectorNodes = (s: ReactFlowState) =>
|
||||
const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func);
|
||||
|
||||
function MiniMapNodes({
|
||||
nodeStrokeColor = 'transparent',
|
||||
nodeColor = '#e2e2e2',
|
||||
nodeStrokeColor,
|
||||
nodeColor,
|
||||
nodeClassName = '',
|
||||
nodeBorderRadius = 5,
|
||||
nodeStrokeWidth = 2,
|
||||
nodeStrokeWidth,
|
||||
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
|
||||
// a component properly.
|
||||
nodeComponent: NodeComponent = MiniMapNode,
|
||||
@@ -41,6 +41,8 @@ function MiniMapNodes({
|
||||
<>
|
||||
{nodes.map((node) => {
|
||||
const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute;
|
||||
const color = nodeColor === undefined ? undefined : nodeColorFunc(node);
|
||||
const strokeColor = nodeStrokeColor === undefined ? undefined : nodeStrokeColorFunc(node);
|
||||
|
||||
return (
|
||||
<NodeComponent
|
||||
@@ -52,9 +54,9 @@ function MiniMapNodes({
|
||||
style={node.style}
|
||||
selected={!!node.selected}
|
||||
className={nodeClassNameFunc(node)}
|
||||
color={nodeColorFunc(node)}
|
||||
color={color}
|
||||
borderRadius={nodeBorderRadius}
|
||||
strokeColor={nodeStrokeColorFunc(node)}
|
||||
strokeColor={strokeColor}
|
||||
strokeWidth={nodeStrokeWidth}
|
||||
shapeRendering={shapeRendering}
|
||||
onClick={onClick}
|
||||
|
||||
@@ -42,10 +42,10 @@ export type MiniMapNodeProps = {
|
||||
height: number;
|
||||
borderRadius: number;
|
||||
className: string;
|
||||
color: string;
|
||||
color?: string;
|
||||
shapeRendering: string;
|
||||
strokeColor: string;
|
||||
strokeWidth: number;
|
||||
strokeColor?: string;
|
||||
strokeWidth?: number;
|
||||
style?: CSSProperties;
|
||||
selected: boolean;
|
||||
onClick?: (event: MouseEvent, id: string) => void;
|
||||
|
||||
@@ -23,6 +23,7 @@ import A11yDescriptions from '../../components/A11yDescriptions';
|
||||
import GraphView from '../GraphView';
|
||||
import Wrapper from './Wrapper';
|
||||
import type { EdgeTypes, NodeTypes, ReactFlowProps, ReactFlowRefType } from '../../types';
|
||||
import useColorModeClass from '../../hooks/useColorModeClass';
|
||||
|
||||
const defaultNodeTypes: NodeTypes = {
|
||||
input: InputNode,
|
||||
@@ -169,18 +170,20 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
|
||||
onViewportChange,
|
||||
width,
|
||||
height,
|
||||
colorMode = 'light',
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const rfId = id || '1';
|
||||
const colorModeClassName = useColorModeClass(colorMode);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...rest}
|
||||
style={{ ...style, ...wrapperStyle }}
|
||||
ref={ref}
|
||||
className={cc(['react-flow', className])}
|
||||
className={cc(['react-flow', className, colorModeClassName])}
|
||||
data-testid="rf__wrapper"
|
||||
id={id}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { ColorMode, ColorModeClass } from '@xyflow/system';
|
||||
|
||||
function getMediaQuery() {
|
||||
if (typeof window === 'undefined' || !window.matchMedia) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return window.matchMedia('(prefers-color-scheme: dark)');
|
||||
}
|
||||
|
||||
export default function useColorModeClass(colorMode: ColorMode): ColorModeClass {
|
||||
const [colorModeClass, setColorModeClass] = useState<ColorModeClass | null>(
|
||||
colorMode === 'system' ? null : colorMode
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (colorMode !== 'system') {
|
||||
setColorModeClass(colorMode);
|
||||
return;
|
||||
}
|
||||
|
||||
const mediaQuery = getMediaQuery();
|
||||
const updateColorModeClass = () => setColorModeClass(mediaQuery?.matches ? 'dark' : 'light');
|
||||
|
||||
updateColorModeClass();
|
||||
mediaQuery?.addEventListener('change', updateColorModeClass);
|
||||
|
||||
return () => {
|
||||
mediaQuery?.removeEventListener('change', updateColorModeClass);
|
||||
};
|
||||
}, [colorMode]);
|
||||
|
||||
return colorModeClass !== null ? colorModeClass : getMediaQuery()?.matches ? 'dark' : 'light';
|
||||
}
|
||||
@@ -73,6 +73,8 @@ export {
|
||||
type Box,
|
||||
type Transform,
|
||||
type CoordinateExtent,
|
||||
type ColorMode,
|
||||
type ColorModeClass,
|
||||
} from '@xyflow/system';
|
||||
|
||||
// system utils
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/* this will be exported as base.css and can be used for a basic styling */
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/base.css';
|
||||
|
||||
.react-flow {
|
||||
--edge-label-background-color-default: #ffffff;
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.react-flow.dark {
|
||||
--edge-label-background-color-default: #141414;
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: var(--edge-label-background-color, var(--edge-label-background-color-default));
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
fill: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -2,3 +2,21 @@
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/style.css';
|
||||
@import '../../../system/src/styles/node-resizer.css';
|
||||
|
||||
.react-flow {
|
||||
--edge-label-background-color-default: #ffffff;
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.react-flow.dark {
|
||||
--edge-label-background-color-default: #141414;
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.react-flow__edge-textbg {
|
||||
fill: var(--edge-label-background-color, var(--edge-label-background-color-default));
|
||||
}
|
||||
|
||||
.react-flow__edge-text {
|
||||
fill: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
SelectionMode,
|
||||
OnError,
|
||||
IsValidConnection,
|
||||
ColorMode,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -155,6 +156,7 @@ export type ReactFlowProps = Omit<HTMLAttributes<HTMLDivElement>, 'onError'> & {
|
||||
nodeDragThreshold?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
colorMode?: ColorMode;
|
||||
};
|
||||
|
||||
export type ReactFlowRefType = HTMLDivElement;
|
||||
|
||||
@@ -15,8 +15,14 @@
|
||||
import { Attribution } from '$lib/components/Attribution';
|
||||
import { key, useStore, createStoreContext } from '$lib/store';
|
||||
import type { SvelteFlowProps } from './types';
|
||||
import { updateStore, updateStoreByKeys, type UpdatableStoreProps } from './utils';
|
||||
import {
|
||||
updateStore,
|
||||
updateStoreByKeys,
|
||||
type UpdatableStoreProps,
|
||||
getColorModeClass
|
||||
} from './utils';
|
||||
import { get } from 'svelte/store';
|
||||
import { useColorModeClass } from '$lib/hooks/useColorModeClass';
|
||||
|
||||
type $$Props = SvelteFlowProps;
|
||||
|
||||
@@ -70,6 +76,7 @@
|
||||
export let defaultEdgeOptions: $$Props['defaultEdgeOptions'] = undefined;
|
||||
export let width: $$Props['width'] = undefined;
|
||||
export let height: $$Props['height'] = undefined;
|
||||
export let colorMode: $$Props['colorMode'] = 'light';
|
||||
|
||||
export let defaultMarkerColor = '#b1b1b7';
|
||||
|
||||
@@ -156,6 +163,8 @@
|
||||
maxZoom,
|
||||
translateExtent
|
||||
});
|
||||
|
||||
$: colorModeClass = useColorModeClass(colorMode);
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -163,7 +172,7 @@
|
||||
bind:clientWidth
|
||||
bind:clientHeight
|
||||
{style}
|
||||
class={cc(['svelte-flow', className])}
|
||||
class={cc(['svelte-flow', className, $colorModeClass])}
|
||||
data-testid="svelte-flow__wrapper"
|
||||
on:dragover
|
||||
on:drop
|
||||
|
||||
@@ -14,7 +14,8 @@ import type {
|
||||
OnError,
|
||||
ConnectionMode,
|
||||
PanelPosition,
|
||||
ProOptions
|
||||
ProOptions,
|
||||
ColorMode
|
||||
} from '@xyflow/system';
|
||||
|
||||
import type {
|
||||
@@ -75,6 +76,7 @@ export type SvelteFlowProps = DOMAttributes<HTMLDivElement> & {
|
||||
defaultEdgeOptions?: DefaultEdgeOptions;
|
||||
width?: number;
|
||||
height?: number;
|
||||
colorMode?: ColorMode;
|
||||
|
||||
class?: string;
|
||||
style?: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SvelteFlowStore } from '$lib/store/types';
|
||||
import type { EdgeTypes, NodeTypes } from '$lib/types';
|
||||
import type { CoordinateExtent } from '@xyflow/system';
|
||||
import type { ColorMode, CoordinateExtent } from '@xyflow/system';
|
||||
import type { Writable } from 'svelte/store';
|
||||
|
||||
// this is helper function for updating the store
|
||||
@@ -77,3 +77,15 @@ export function updateStoreByKeys(store: SvelteFlowStore, keys: UpdatableStorePr
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getColorModeClass(colorMode?: ColorMode) {
|
||||
if (colorMode !== 'system') {
|
||||
return colorMode;
|
||||
}
|
||||
|
||||
if (!colorMode || typeof window === 'undefined' || !window.matchMedia) {
|
||||
return 'light';
|
||||
}
|
||||
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { ColorMode, ColorModeClass } from '@xyflow/system';
|
||||
import { readable, type Readable } from 'svelte/store';
|
||||
|
||||
function getMediaQuery() {
|
||||
if (typeof window === 'undefined' || !window.matchMedia) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return window.matchMedia('(prefers-color-scheme: dark)');
|
||||
}
|
||||
|
||||
export function useColorModeClass(colorMode: ColorMode = 'light'): Readable<ColorModeClass> {
|
||||
const colorModeClass = readable<ColorModeClass>('light', (set) => {
|
||||
if (colorMode !== 'system') {
|
||||
set(colorMode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const mediaQuery = getMediaQuery();
|
||||
const updateColorModeClass = () => set(mediaQuery?.matches ? 'dark' : 'light');
|
||||
|
||||
set(mediaQuery?.matches ? 'dark' : 'light');
|
||||
mediaQuery?.addEventListener('change', updateColorModeClass);
|
||||
|
||||
return () => {
|
||||
mediaQuery?.removeEventListener('change', updateColorModeClass);
|
||||
};
|
||||
});
|
||||
|
||||
return colorModeClass;
|
||||
}
|
||||
@@ -75,7 +75,9 @@ export {
|
||||
type Rect,
|
||||
type Box,
|
||||
type Transform,
|
||||
type CoordinateExtent
|
||||
type CoordinateExtent,
|
||||
type ColorMode,
|
||||
type ColorModeClass
|
||||
} from '@xyflow/system';
|
||||
|
||||
// system utils
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
export let position: $$Props['position'] = 'bottom-right';
|
||||
export let ariaLabel: $$Props['ariaLabel'] = 'Mini map';
|
||||
export let nodeStrokeColor: $$Props['nodeStrokeColor'] = 'transparent';
|
||||
export let nodeColor: $$Props['nodeColor'] = '#e2e2e2';
|
||||
export let nodeColor: $$Props['nodeColor'] = undefined;
|
||||
export let nodeClass: $$Props['nodeClass'] = '';
|
||||
export let nodeBorderRadius: $$Props['nodeBorderRadius'] = 5;
|
||||
export let nodeStrokeWidth: $$Props['nodeStrokeWidth'] = 2;
|
||||
@@ -51,7 +51,7 @@
|
||||
translateExtent
|
||||
} = useStore();
|
||||
|
||||
const nodeColorFunc = getAttrFunction(nodeColor);
|
||||
const nodeColorFunc = nodeColor === undefined ? undefined : getAttrFunction(nodeColor);
|
||||
const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
|
||||
const nodeClassFunc = getAttrFunction(nodeClass);
|
||||
const shapeRendering =
|
||||
@@ -122,7 +122,7 @@
|
||||
width={node.computed?.width ?? node.width ?? 0}
|
||||
height={node.computed?.height ?? node.height ?? 0}
|
||||
selected={node.selected}
|
||||
color={nodeColorFunc(node)}
|
||||
color={nodeColorFunc?.(node)}
|
||||
borderRadius={nodeBorderRadius}
|
||||
strokeColor={nodeStrokeColorFunc(node)}
|
||||
strokeWidth={nodeStrokeWidth}
|
||||
@@ -142,27 +142,3 @@
|
||||
</svg>
|
||||
{/if}
|
||||
</Panel>
|
||||
|
||||
<style>
|
||||
svg {
|
||||
background-color: var(
|
||||
--minimap-background-color-props,
|
||||
var(--minimap-background-color, var(--minimap-background-color-default))
|
||||
);
|
||||
}
|
||||
|
||||
.svelte-flow__minimap-mask {
|
||||
fill: var(
|
||||
--minimap-mask-color-props,
|
||||
var(--minimap-mask-color, var(--minimap-mask-color-default))
|
||||
);
|
||||
stroke: var(
|
||||
--minimap-mask-stroke-color-props,
|
||||
var(--minimap-mask-stroke-color, var(--minimap-mask-stroke-color-default))
|
||||
);
|
||||
stroke-width: var(
|
||||
--minimap-mask-stroke-width-props,
|
||||
var(--minimap-mask-stroke-width, var(--minimap-mask-stroke-width-default))
|
||||
);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
export let width: number = 0;
|
||||
export let height: number = 0;
|
||||
export let borderRadius: number = 5;
|
||||
export let color: string;
|
||||
export let color: string | undefined = undefined;
|
||||
export let shapeRendering: string;
|
||||
export let strokeColor: string;
|
||||
export let strokeColor: string | undefined = undefined;
|
||||
export let strokeWidth: number = 2;
|
||||
export let selected: boolean = false;
|
||||
let className: string = '';
|
||||
@@ -24,8 +24,8 @@
|
||||
ry={borderRadius}
|
||||
{width}
|
||||
{height}
|
||||
fill={color}
|
||||
stroke={strokeColor}
|
||||
stroke-width={strokeWidth}
|
||||
style={`${color ? `fill: ${color};` : ''}${strokeColor ? `stroke: ${strokeColor};` : ''}${
|
||||
strokeWidth ? `stroke-width: ${strokeWidth};` : ''
|
||||
}`}
|
||||
shape-rendering={shapeRendering}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,16 @@
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/base.css';
|
||||
|
||||
.svelte-flow {
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.svelte-flow.dark {
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.svelte-flow__edge-label {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
color: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
@import '../../../system/src/styles/init.css';
|
||||
@import '../../../system/src/styles/style.css';
|
||||
|
||||
.svelte-flow {
|
||||
--edge-label-color-default: inherit;
|
||||
}
|
||||
|
||||
.svelte-flow.dark {
|
||||
--edge-label-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.svelte-flow__edge-label {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
font-size: 10px;
|
||||
color: var(--edge-label-color, var(--edge-label-color-default));
|
||||
}
|
||||
|
||||
.svelte-flow__nodes {
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
--selection-border-default: 1px dotted rgba(155, 155, 155, 0.8);
|
||||
}
|
||||
|
||||
.xy-flow.dark {
|
||||
--node-color-default: #f8f8f8;
|
||||
}
|
||||
|
||||
.xy-flow__handle {
|
||||
background-color: var(--handle-background-color, var(--handle-background-color-default));
|
||||
}
|
||||
@@ -17,6 +21,7 @@
|
||||
.xy-flow__node-output,
|
||||
.xy-flow__node-group {
|
||||
border: var(--node-border, var(--node-border-default));
|
||||
color: var(--node-color, var(--node-color-default));
|
||||
|
||||
&.selected,
|
||||
&:focus,
|
||||
|
||||
@@ -11,12 +11,43 @@
|
||||
--attribution-background-color-default: rgba(255, 255, 255, 0.5);
|
||||
|
||||
--minimap-background-color-default: #fff;
|
||||
--minimap-mask-background-color-default: rgb(240, 240, 240, 0.6);
|
||||
--minimap-node-background-color-default: #e2e2e2;
|
||||
--minimap-node-stroke-color-default: transparent;
|
||||
--minimap-node-stroke-width-default: 2;
|
||||
|
||||
--background-pattern-dot-color-default: #91919a;
|
||||
--background-pattern-line-color-default: #eee;
|
||||
--background-color-default: transparent;
|
||||
--background-pattern-dots-color-default: #91919a;
|
||||
--background-pattern-lines-color-default: #eee;
|
||||
--background-pattern-cross-color-default: #e2e2e2;
|
||||
}
|
||||
|
||||
.xy-flow.dark {
|
||||
--edge-stroke-default: #3c3c3c;
|
||||
--edge-stroke-width-default: 1;
|
||||
--edge-stroke-selected-default: #727272;
|
||||
|
||||
--connectionline-stroke-default: #b1b1b7;
|
||||
--connectionline-stroke-width-default: 1;
|
||||
|
||||
--attribution-background-color-default: rgba(150, 150, 150, 0.25);
|
||||
|
||||
--minimap-background-color-default: #141414;
|
||||
--minimap-mask-background-color-default: rgb(60, 60, 60, 0.6);
|
||||
--minimap-node-background-color-default: #2b2b2b;
|
||||
--minimap-node-stroke-color-default: transparent;
|
||||
--minimap-node-stroke-width-default: 2;
|
||||
|
||||
--background-color-default: #141414;
|
||||
--background-pattern-dots-color-default: #777;
|
||||
--background-pattern-lines-color-default: #777;
|
||||
--background-pattern-cross-color-default: #777;
|
||||
}
|
||||
|
||||
.xy-flow {
|
||||
background-color: var(--background-color-props, var(--background-color-default, 'transparent'));
|
||||
}
|
||||
|
||||
.xy-flow__container {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
@@ -108,16 +139,11 @@
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
&-textbg {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.xy-flow__edge-text {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.xy-flow__connection {
|
||||
pointer-events: none;
|
||||
|
||||
@@ -268,26 +294,47 @@
|
||||
|
||||
.xy-flow__minimap {
|
||||
background: var(--minimap-background-color, var(--minimap-background-color-default));
|
||||
|
||||
&-mask {
|
||||
fill: var(
|
||||
--minimap-mask-background-color-props,
|
||||
var(--minimap-mask-background-color, var(--minimap-mask-background-color-default))
|
||||
);
|
||||
}
|
||||
|
||||
&-node {
|
||||
fill: var(
|
||||
--minimap-node-background-color-props,
|
||||
var(--minimap-node-background-color, var(--minimap-node-background-color-default))
|
||||
);
|
||||
stroke: var(
|
||||
--minimap-node-stroke-color-props,
|
||||
var(--minimap-node-stroke-color, var(--minimap-node-stroke-color-default))
|
||||
);
|
||||
stroke-width: var(
|
||||
--minimap-node-stroke-width-props,
|
||||
var(--minimap-node-stroke-width, var(--minimap-node-stroke-width-default))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.xy-flow__background {
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
background-color: var(--background-color-props, 'transparent');
|
||||
}
|
||||
|
||||
.xy-flow__background-pattern {
|
||||
&.dots {
|
||||
fill: var(
|
||||
--background-pattern-color-props,
|
||||
var(--background-pattern-color, var(--background-pattern-dot-color-default))
|
||||
var(--background-pattern-color, var(--background-pattern-dots-color-default))
|
||||
);
|
||||
}
|
||||
|
||||
&.lines {
|
||||
stroke: var(
|
||||
--background-pattern-color-props,
|
||||
var(--background-pattern-color, var(--background-pattern-line-color-default))
|
||||
var(--background-pattern-color, var(--background-pattern-lines-color-default))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -312,6 +359,7 @@
|
||||
width: 100%;
|
||||
max-width: 12px;
|
||||
max-height: 12px;
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
--node-group-background-color-default: rgba(240, 240, 240, 0.25);
|
||||
--node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
|
||||
--node-boxshadow-selected-default: 0 0 0 0.5px #1a192b;
|
||||
--node-border-radius-default: 3px;
|
||||
|
||||
--handle-background-color-default: #1a192b;
|
||||
--handle-border-color-default: #fff;
|
||||
@@ -20,6 +21,28 @@
|
||||
--controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.xy-flow.dark {
|
||||
--node-color-default: #f8f8f8;
|
||||
--node-border-default: 1px solid #3c3c3c;
|
||||
--node-background-color-default: #1e1e1e;
|
||||
--node-group-background-color-default: rgba(240, 240, 240, 0.25);
|
||||
--node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, 0.08);
|
||||
--node-boxshadow-selected-default: 0 0 0 0.5px #999;
|
||||
|
||||
--handle-background-color-default: #bebebe;
|
||||
--handle-border-color-default: #1e1e1e;
|
||||
|
||||
--selection-background-color-default: rgba(200, 200, 220, 0.08);
|
||||
--selection-border-default: 1px dotted rgba(200, 200, 220, 0.8);
|
||||
|
||||
--controls-button-background-color-default: #2b2b2b;
|
||||
--controls-button-background-color-hover-default: #3e3e3e;
|
||||
--controls-button-color-default: #f8f8f8;
|
||||
--controls-button-color-hover-default: #fff;
|
||||
--controls-button-border-color-default: #5b5b5b;
|
||||
--controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.xy-flow__edge {
|
||||
&.updating {
|
||||
.xy-flow__edge-path {
|
||||
@@ -44,7 +67,7 @@
|
||||
.xy-flow__node-output,
|
||||
.xy-flow__node-group {
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
border-radius: var(--node-border-radius, var(--node-border-radius-default));
|
||||
width: 150px;
|
||||
font-size: 12px;
|
||||
color: var(--node-color, var(--node-color-default));
|
||||
@@ -110,7 +133,7 @@
|
||||
);
|
||||
color: var(
|
||||
--controls-button-color-hover-props,
|
||||
var(--controls-button-hover-color, var(--controls-button-hover-color-default))
|
||||
var(--controls-button-color-hover, var(--controls-button-color-hover-default))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -122,4 +145,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-button:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,3 +136,6 @@ export type UpdateConnection = (params: {
|
||||
connectionStartHandle: ConnectingHandle | null;
|
||||
connectionEndHandle: ConnectingHandle | null;
|
||||
}) => void;
|
||||
|
||||
export type ColorModeClass = 'light' | 'dark';
|
||||
export type ColorMode = ColorModeClass | 'system';
|
||||
|
||||
Reference in New Issue
Block a user