mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-02-04 07:13:25 +08:00
Merge branch 'develop' into update-class-diagram and fix conflicts
This commit is contained in:
commit
b315d70af5
@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:90](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L90)
|
[packages/mermaid/src/types.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L95)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L80)
|
[packages/mermaid/src/types.ts:85](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L85)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -63,4 +63,4 @@ The svg code for the rendered graph.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[packages/mermaid/src/types.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L76)
|
[packages/mermaid/src/types.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L81)
|
||||||
|
@ -3,6 +3,21 @@ import ELK from 'elkjs/lib/elk.bundled.js';
|
|||||||
import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid';
|
import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid';
|
||||||
import { type TreeData, findCommonAncestor } from './find-common-ancestor.js';
|
import { type TreeData, findCommonAncestor } from './find-common-ancestor.js';
|
||||||
|
|
||||||
|
type Node = LayoutData['nodes'][number];
|
||||||
|
|
||||||
|
interface LabelData {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
wrappingWidth?: number;
|
||||||
|
labelNode?: SVGGElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NodeWithVertex extends Omit<Node, 'domId'> {
|
||||||
|
children?: unknown[];
|
||||||
|
labelData?: LabelData;
|
||||||
|
domId?: Node['domId'] | SVGGroup | d3.Selection<SVGAElement, unknown, Element | null, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
export const render = async (
|
export const render = async (
|
||||||
data4Layout: LayoutData,
|
data4Layout: LayoutData,
|
||||||
svg: SVG,
|
svg: SVG,
|
||||||
@ -24,27 +39,37 @@ export const render = async (
|
|||||||
const nodeDb: Record<string, any> = {};
|
const nodeDb: Record<string, any> = {};
|
||||||
const clusterDb: Record<string, any> = {};
|
const clusterDb: Record<string, any> = {};
|
||||||
|
|
||||||
const addVertex = async (nodeEl: any, graph: { children: any[] }, nodeArr: any, node: any) => {
|
const addVertex = async (
|
||||||
const labelData: any = { width: 0, height: 0 };
|
nodeEl: SVGGroup,
|
||||||
|
graph: { children: NodeWithVertex[] },
|
||||||
|
nodeArr: Node[],
|
||||||
|
node: Node
|
||||||
|
) => {
|
||||||
|
const labelData: LabelData = { width: 0, height: 0 };
|
||||||
|
|
||||||
let boundingBox;
|
|
||||||
const child = {
|
|
||||||
...node,
|
|
||||||
};
|
|
||||||
graph.children.push(child);
|
|
||||||
nodeDb[node.id] = child;
|
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
|
|
||||||
// Add the element to the DOM
|
// Add the element to the DOM
|
||||||
if (!node.isGroup) {
|
if (!node.isGroup) {
|
||||||
|
const child: NodeWithVertex = {
|
||||||
|
...node,
|
||||||
|
};
|
||||||
|
graph.children.push(child);
|
||||||
|
nodeDb[node.id] = child;
|
||||||
|
|
||||||
const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir });
|
const childNodeEl = await insertNode(nodeEl, node, { config, dir: node.dir });
|
||||||
boundingBox = childNodeEl.node().getBBox();
|
const boundingBox = childNodeEl.node()!.getBBox();
|
||||||
child.domId = childNodeEl;
|
child.domId = childNodeEl;
|
||||||
child.width = boundingBox.width;
|
child.width = boundingBox.width;
|
||||||
child.height = boundingBox.height;
|
child.height = boundingBox.height;
|
||||||
} else {
|
} else {
|
||||||
// A subgraph
|
// A subgraph
|
||||||
child.children = [];
|
const child: NodeWithVertex & { children: NodeWithVertex[] } = {
|
||||||
|
...node,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
graph.children.push(child);
|
||||||
|
nodeDb[node.id] = child;
|
||||||
await addVertices(nodeEl, nodeArr, child, node.id);
|
await addVertices(nodeEl, nodeArr, child, node.id);
|
||||||
|
|
||||||
if (node.label) {
|
if (node.label) {
|
||||||
@ -68,28 +93,16 @@ export const render = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const addVertices = async function (
|
const addVertices = async function (
|
||||||
nodeEl: any,
|
nodeEl: SVGGroup,
|
||||||
nodeArr: any[],
|
nodeArr: Node[],
|
||||||
graph: {
|
graph: { children: NodeWithVertex[] },
|
||||||
id: string;
|
parentId?: string
|
||||||
layoutOptions: {
|
|
||||||
'elk.hierarchyHandling': string;
|
|
||||||
'elk.algorithm': any;
|
|
||||||
'nodePlacement.strategy': any;
|
|
||||||
'elk.layered.mergeEdges': any;
|
|
||||||
'elk.direction': string;
|
|
||||||
'spacing.baseValue': number;
|
|
||||||
};
|
|
||||||
children: never[];
|
|
||||||
edges: never[];
|
|
||||||
},
|
|
||||||
parentId?: undefined
|
|
||||||
) {
|
) {
|
||||||
const siblings = nodeArr.filter((node: { parentId: any }) => node.parentId === parentId);
|
const siblings = nodeArr.filter((node) => node?.parentId === parentId);
|
||||||
log.info('addVertices APA12', siblings, parentId);
|
log.info('addVertices APA12', siblings, parentId);
|
||||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
siblings.map(async (node: any) => {
|
siblings.map(async (node) => {
|
||||||
await addVertex(nodeEl, graph, nodeArr, node);
|
await addVertex(nodeEl, graph, nodeArr, node);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -8,15 +8,16 @@ import { createText } from '../../rendering-util/createText.js';
|
|||||||
import { evaluate, hasKatex } from '../common/common.js';
|
import { evaluate, hasKatex } from '../common/common.js';
|
||||||
import type { Node } from '../../rendering-util/types.js';
|
import type { Node } from '../../rendering-util/types.js';
|
||||||
import type { MermaidConfig } from '../../config.type.js';
|
import type { MermaidConfig } from '../../config.type.js';
|
||||||
|
import type { D3Selection } from '../../types.js';
|
||||||
|
|
||||||
// Creates the shapeSvg and inserts text
|
// Creates the shapeSvg and inserts text
|
||||||
export const textHelper = async (
|
export async function textHelper<T extends SVGGraphicsElement>(
|
||||||
parent: SVGAElement,
|
parent: D3Selection<T>,
|
||||||
node: any,
|
node: any,
|
||||||
config: MermaidConfig,
|
config: MermaidConfig,
|
||||||
useHtmlLabels: boolean,
|
useHtmlLabels: boolean,
|
||||||
GAP = config.class!.padding ?? 12
|
GAP = config.class!.padding ?? 12
|
||||||
) => {
|
) {
|
||||||
const TEXT_PADDING = !useHtmlLabels ? 3 : 0;
|
const TEXT_PADDING = !useHtmlLabels ? 3 : 0;
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
// @ts-ignore: Ignore error for using .insert on SVGAElement
|
// @ts-ignore: Ignore error for using .insert on SVGAElement
|
||||||
@ -38,13 +39,13 @@ export const textHelper = async (
|
|||||||
const annotation = node.annotations[0];
|
const annotation = node.annotations[0];
|
||||||
await addText(annotationGroup, { text: `«${annotation}»` } as unknown as ClassMember, 0);
|
await addText(annotationGroup, { text: `«${annotation}»` } as unknown as ClassMember, 0);
|
||||||
|
|
||||||
const annotationGroupBBox = annotationGroup.node().getBBox();
|
const annotationGroupBBox = annotationGroup.node()!.getBBox();
|
||||||
annotationGroupHeight = annotationGroupBBox.height;
|
annotationGroupHeight = annotationGroupBBox.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
labelGroup = shapeSvg.insert('g').attr('class', 'label-group text');
|
labelGroup = shapeSvg.insert('g').attr('class', 'label-group text');
|
||||||
await addText(labelGroup, node, 0, ['font-weight: bolder']);
|
await addText(labelGroup, node, 0, ['font-weight: bolder']);
|
||||||
const labelGroupBBox = labelGroup.node().getBBox();
|
const labelGroupBBox = labelGroup.node()!.getBBox();
|
||||||
labelGroupHeight = labelGroupBBox.height;
|
labelGroupHeight = labelGroupBBox.height;
|
||||||
|
|
||||||
membersGroup = shapeSvg.insert('g').attr('class', 'members-group text');
|
membersGroup = shapeSvg.insert('g').attr('class', 'members-group text');
|
||||||
@ -53,7 +54,7 @@ export const textHelper = async (
|
|||||||
const height = await addText(membersGroup, member, yOffset, [member.parseClassifier()]);
|
const height = await addText(membersGroup, member, yOffset, [member.parseClassifier()]);
|
||||||
yOffset += height + TEXT_PADDING;
|
yOffset += height + TEXT_PADDING;
|
||||||
}
|
}
|
||||||
membersGroupHeight = membersGroup.node().getBBox().height;
|
membersGroupHeight = membersGroup.node()!.getBBox().height;
|
||||||
if (membersGroupHeight <= 0) {
|
if (membersGroupHeight <= 0) {
|
||||||
membersGroupHeight = GAP / 2;
|
membersGroupHeight = GAP / 2;
|
||||||
}
|
}
|
||||||
@ -65,41 +66,41 @@ export const textHelper = async (
|
|||||||
methodsYOffset += height + TEXT_PADDING;
|
methodsYOffset += height + TEXT_PADDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bbox = shapeSvg.node().getBBox();
|
let bbox = shapeSvg.node()!.getBBox();
|
||||||
|
|
||||||
// Center annotation
|
// Center annotation
|
||||||
if (annotationGroup !== null) {
|
if (annotationGroup !== null) {
|
||||||
const annotationGroupBBox = annotationGroup.node().getBBox();
|
const annotationGroupBBox = annotationGroup.node()!.getBBox();
|
||||||
annotationGroup.attr('transform', `translate(${-annotationGroupBBox.width / 2})`);
|
annotationGroup.attr('transform', `translate(${-annotationGroupBBox.width / 2})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust label
|
// Adjust label
|
||||||
labelGroup.attr('transform', `translate(${-labelGroupBBox.width / 2}, ${annotationGroupHeight})`);
|
labelGroup.attr('transform', `translate(${-labelGroupBBox.width / 2}, ${annotationGroupHeight})`);
|
||||||
|
|
||||||
bbox = shapeSvg.node().getBBox();
|
bbox = shapeSvg.node()!.getBBox();
|
||||||
|
|
||||||
membersGroup.attr(
|
membersGroup.attr(
|
||||||
'transform',
|
'transform',
|
||||||
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + GAP * 2})`
|
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + GAP * 2})`
|
||||||
);
|
);
|
||||||
bbox = shapeSvg.node().getBBox();
|
bbox = shapeSvg.node()!.getBBox();
|
||||||
methodsGroup.attr(
|
methodsGroup.attr(
|
||||||
'transform',
|
'transform',
|
||||||
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + (membersGroupHeight ? membersGroupHeight + GAP * 4 : GAP * 2)})`
|
`translate(${0}, ${annotationGroupHeight + labelGroupHeight + (membersGroupHeight ? membersGroupHeight + GAP * 4 : GAP * 2)})`
|
||||||
);
|
);
|
||||||
|
|
||||||
bbox = shapeSvg.node().getBBox();
|
bbox = shapeSvg.node()!.getBBox();
|
||||||
|
|
||||||
return { shapeSvg, bbox };
|
return { shapeSvg, bbox };
|
||||||
};
|
}
|
||||||
|
|
||||||
// Modified version of labelHelper() to help create and place text for classes
|
// Modified version of labelHelper() to help create and place text for classes
|
||||||
const addText = async (
|
async function addText<T extends SVGGraphicsElement>(
|
||||||
parentGroup: d3.Selection<SVGGElement, unknown, null, undefined>,
|
parentGroup: D3Selection<T>,
|
||||||
node: Node | ClassNode | ClassMember,
|
node: Node | ClassNode | ClassMember,
|
||||||
yOffset: number,
|
yOffset: number,
|
||||||
styles: string[] = []
|
styles: string[] = []
|
||||||
) => {
|
) {
|
||||||
const textEl = parentGroup.insert('g').attr('class', 'label').attr('style', styles.join('; '));
|
const textEl = parentGroup.insert('g').attr('class', 'label').attr('style', styles.join('; '));
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
let useHtmlLabels =
|
let useHtmlLabels =
|
||||||
@ -219,4 +220,4 @@ const addText = async (
|
|||||||
// Center text and offset by yOffset
|
// Center text and offset by yOffset
|
||||||
textEl.attr('transform', 'translate(0,' + (-bbox.height / (2 * numberOfLines) + yOffset) + ')');
|
textEl.attr('transform', 'translate(0,' + (-bbox.height / (2 * numberOfLines) + yOffset) + ')');
|
||||||
return bbox.height;
|
return bbox.height;
|
||||||
};
|
}
|
||||||
|
@ -204,7 +204,7 @@ export const createText = async (
|
|||||||
width = 200,
|
width = 200,
|
||||||
addSvgBackground = false,
|
addSvgBackground = false,
|
||||||
} = {},
|
} = {},
|
||||||
config: MermaidConfig
|
config?: MermaidConfig
|
||||||
) => {
|
) => {
|
||||||
log.debug(
|
log.debug(
|
||||||
'XYZ createText',
|
'XYZ createText',
|
||||||
|
@ -84,7 +84,7 @@ describe('Test Alias for shapes', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should support alias for shadedProcess shape ', function () {
|
it('should support alias for shadedProcess shape ', function () {
|
||||||
const aliases = ['lined-process', 'lined-rectangle', 'lin-proc', 'lin-rect'];
|
const aliases = ['lined-process', 'lined-rectangle', 'lin-proc', 'lin-rect'] as const;
|
||||||
for (const alias of aliases) {
|
for (const alias of aliases) {
|
||||||
expect(shapes[alias]).toBe(shapes['shaded-process']);
|
expect(shapes[alias]).toBe(shapes['shaded-process']);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import { shapes } from './shapes.js';
|
import { shapes } from './shapes.js';
|
||||||
|
import type { Node, ShapeRenderOptions } from '../types.js';
|
||||||
|
import type { SVGGroup } from '../../mermaid.js';
|
||||||
|
import type { D3Selection } from '../../types.js';
|
||||||
|
import type { graphlib } from 'dagre-d3-es';
|
||||||
|
|
||||||
const nodeElems = new Map();
|
type ShapeHandler = (typeof shapes)[keyof typeof shapes];
|
||||||
|
type NodeElement = D3Selection<SVGAElement> | Awaited<ReturnType<ShapeHandler>>;
|
||||||
|
|
||||||
export const insertNode = async (elem, node, renderOptions) => {
|
const nodeElems = new Map<string, NodeElement>();
|
||||||
let newEl;
|
|
||||||
|
export async function insertNode(elem: SVGGroup, node: Node, renderOptions: ShapeRenderOptions) {
|
||||||
|
let newEl: NodeElement | undefined;
|
||||||
let el;
|
let el;
|
||||||
|
|
||||||
//special check for rect shape (with or without rounded corners)
|
//special check for rect shape (with or without rounded corners)
|
||||||
@ -16,7 +23,7 @@ export const insertNode = async (elem, node, renderOptions) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const shapeHandler = shapes[node.shape];
|
const shapeHandler = shapes[(node.shape ?? 'undefined') as keyof typeof shapes];
|
||||||
|
|
||||||
if (!shapeHandler) {
|
if (!shapeHandler) {
|
||||||
throw new Error(`No such shape: ${node.shape}. Please check your syntax.`);
|
throw new Error(`No such shape: ${node.shape}. Please check your syntax.`);
|
||||||
@ -30,7 +37,10 @@ export const insertNode = async (elem, node, renderOptions) => {
|
|||||||
} else if (node.linkTarget) {
|
} else if (node.linkTarget) {
|
||||||
target = node.linkTarget || '_blank';
|
target = node.linkTarget || '_blank';
|
||||||
}
|
}
|
||||||
newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target);
|
newEl = elem
|
||||||
|
.insert<SVGAElement>('svg:a')
|
||||||
|
.attr('xlink:href', node.link)
|
||||||
|
.attr('target', target ?? null);
|
||||||
el = await shapeHandler(newEl, node, renderOptions);
|
el = await shapeHandler(newEl, node, renderOptions);
|
||||||
} else {
|
} else {
|
||||||
el = await shapeHandler(elem, node, renderOptions);
|
el = await shapeHandler(elem, node, renderOptions);
|
||||||
@ -43,12 +53,12 @@ export const insertNode = async (elem, node, renderOptions) => {
|
|||||||
nodeElems.set(node.id, newEl);
|
nodeElems.set(node.id, newEl);
|
||||||
|
|
||||||
if (node.haveCallback) {
|
if (node.haveCallback) {
|
||||||
nodeElems.get(node.id).attr('class', nodeElems.get(node.id).attr('class') + ' clickable');
|
newEl.attr('class', newEl.attr('class') + ' clickable');
|
||||||
}
|
}
|
||||||
return newEl;
|
return newEl;
|
||||||
};
|
}
|
||||||
|
|
||||||
export const setNodeElem = (elem, node) => {
|
export const setNodeElem = (elem: NodeElement, node: Pick<Node, 'id'>) => {
|
||||||
nodeElems.set(node.id, elem);
|
nodeElems.set(node.id, elem);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,8 +66,8 @@ export const clear = () => {
|
|||||||
nodeElems.clear();
|
nodeElems.clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const positionNode = (node) => {
|
export const positionNode = (node: ReturnType<graphlib.Graph['node']>) => {
|
||||||
const el = nodeElems.get(node.id);
|
const el = nodeElems.get(node.id)!;
|
||||||
log.trace(
|
log.trace(
|
||||||
'Transforming node',
|
'Transforming node',
|
||||||
node.diff,
|
node.diff,
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { Entries } from 'type-fest';
|
||||||
|
import type { D3Selection, MaybePromise } from '../../types.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../types.js';
|
import type { Node, ShapeRenderOptions } from '../types.js';
|
||||||
import { anchor } from './shapes/anchor.js';
|
import { anchor } from './shapes/anchor.js';
|
||||||
import { bowTieRect } from './shapes/bowTieRect.js';
|
import { bowTieRect } from './shapes/bowTieRect.js';
|
||||||
@ -57,8 +59,11 @@ import { waveRectangle } from './shapes/waveRectangle.js';
|
|||||||
import { windowPane } from './shapes/windowPane.js';
|
import { windowPane } from './shapes/windowPane.js';
|
||||||
import { classBox } from './shapes/classBox.js';
|
import { classBox } from './shapes/classBox.js';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
type ShapeHandler = <T extends SVGGraphicsElement>(
|
||||||
type ShapeHandler = (parent: any, node: Node, options: ShapeRenderOptions) => unknown;
|
parent: D3Selection<T>,
|
||||||
|
node: Node,
|
||||||
|
options: ShapeRenderOptions
|
||||||
|
) => MaybePromise<D3Selection<SVGGElement>>;
|
||||||
|
|
||||||
export interface ShapeDefinition {
|
export interface ShapeDefinition {
|
||||||
semanticName: string;
|
semanticName: string;
|
||||||
@ -76,7 +81,7 @@ export interface ShapeDefinition {
|
|||||||
handler: ShapeHandler;
|
handler: ShapeHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shapesDefs: ShapeDefinition[] = [
|
export const shapesDefs = [
|
||||||
{
|
{
|
||||||
semanticName: 'Process',
|
semanticName: 'Process',
|
||||||
name: 'Rectangle',
|
name: 'Rectangle',
|
||||||
@ -451,11 +456,11 @@ export const shapesDefs: ShapeDefinition[] = [
|
|||||||
aliases: ['class-box'],
|
aliases: ['class-box'],
|
||||||
handler: classBox,
|
handler: classBox,
|
||||||
},
|
},
|
||||||
];
|
] as const satisfies ShapeDefinition[];
|
||||||
|
|
||||||
const generateShapeMap = () => {
|
const generateShapeMap = () => {
|
||||||
// These are the shapes that didn't have documentation present
|
// These are the shapes that didn't have documentation present
|
||||||
const shapeMap: Record<string, ShapeHandler> = {
|
const undocumentedShapes = {
|
||||||
// States
|
// States
|
||||||
state,
|
state,
|
||||||
choice,
|
choice,
|
||||||
@ -473,18 +478,25 @@ const generateShapeMap = () => {
|
|||||||
imageSquare,
|
imageSquare,
|
||||||
|
|
||||||
anchor,
|
anchor,
|
||||||
};
|
} as const;
|
||||||
|
|
||||||
for (const shape of shapesDefs) {
|
const entries = [
|
||||||
for (const alias of [
|
...(Object.entries(undocumentedShapes) as Entries<typeof undocumentedShapes>),
|
||||||
shape.shortName,
|
...shapesDefs.flatMap((shape) => {
|
||||||
...(shape.aliases ?? []),
|
const aliases = [
|
||||||
...(shape.internalAliases ?? []),
|
shape.shortName,
|
||||||
]) {
|
...('aliases' in shape ? shape.aliases : []),
|
||||||
shapeMap[alias] = shape.handler;
|
...('internalAliases' in shape ? shape.internalAliases : []),
|
||||||
}
|
];
|
||||||
}
|
return aliases.map((alias) => [alias, shape.handler] as const);
|
||||||
return shapeMap;
|
}),
|
||||||
|
];
|
||||||
|
return Object.fromEntries(entries) as Record<
|
||||||
|
(typeof entries)[number][0],
|
||||||
|
(typeof entries)[number][1]
|
||||||
|
> satisfies Record<string, ShapeHandler>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const shapes = generateShapeMap();
|
export const shapes = generateShapeMap();
|
||||||
|
|
||||||
|
export type ShapeID = keyof typeof shapes;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { updateNodeBounds, getNodeClasses } from './util.js';
|
import { updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export function anchor<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles } = styles2String(node);
|
const { labelStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const classes = getNodeClasses(node);
|
const classes = getNodeClasses(node);
|
||||||
@ -14,7 +16,6 @@ export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> =>
|
|||||||
cssClasses = 'anchor';
|
cssClasses = 'anchor';
|
||||||
}
|
}
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
// @ts-ignore - SVGElement is not typed
|
|
||||||
.insert('g')
|
.insert('g')
|
||||||
.attr('class', cssClasses)
|
.attr('class', cssClasses)
|
||||||
.attr('id', node.domId || node.id);
|
.attr('id', node.domId || node.id);
|
||||||
@ -23,6 +24,7 @@ export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> =>
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { fill: 'black', stroke: 'none', fillStyle: 'solid' });
|
const options = userNodeOverrides(node, { fill: 'black', stroke: 'none', fillStyle: 'solid' });
|
||||||
|
|
||||||
@ -31,7 +33,7 @@ export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> =>
|
|||||||
}
|
}
|
||||||
const roughNode = rc.circle(0, 0, radius * 2, options);
|
const roughNode = rc.circle(0, 0, radius * 2, options);
|
||||||
const circleElem = shapeSvg.insert(() => roughNode, ':first-child');
|
const circleElem = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
circleElem.attr('class', 'anchor').attr('style', cssStyles);
|
circleElem.attr('class', 'anchor').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
|
|
||||||
updateNodeBounds(node, circleElem);
|
updateNodeBounds(node, circleElem);
|
||||||
|
|
||||||
@ -41,4 +43,4 @@ export const anchor = (parent: SVGAElement, node: Node): Promise<SVGAElement> =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
function generateArcPoints(
|
function generateArcPoints(
|
||||||
x1: number,
|
x1: number,
|
||||||
@ -70,7 +71,7 @@ function generateArcPoints(
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const bowTieRect = async (parent: SVGAElement, node: Node) => {
|
export async function bowTieRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -91,6 +92,7 @@ export const bowTieRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true),
|
...generateArcPoints(w / 2, h / 2, w / 2, -h / 2, rx, ry, true),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -122,4 +124,4 @@ export const bowTieRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
import { createPathFromPoints } from './util.js';
|
import { createPathFromPoints } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
// const createPathFromPoints = (points: { x: number; y: number }[]): string => {
|
// const createPathFromPoints = (points: { x: number; y: number }[]): string => {
|
||||||
// const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`);
|
// const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`);
|
||||||
@ -13,7 +14,7 @@ import { createPathFromPoints } from './util.js';
|
|||||||
// return pointStrings.join(' ');
|
// return pointStrings.join(' ');
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export async function card(parent: SVGAElement, node: Node): Promise<SVGAElement> {
|
export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -34,10 +35,11 @@ export async function card(parent: SVGAElement, node: Node): Promise<SVGAElement
|
|||||||
{ x: left + padding, y: top },
|
{ x: left + padding, y: top },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: D3Selection<SVGGElement> | Awaited<ReturnType<typeof insertPolygonShape>>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createPathFromPoints(points);
|
const pathData = createPathFromPoints(points);
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
// @ts-ignore TODO: Fix rough typings
|
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { createPathFromPoints, getNodeClasses } from './util.js';
|
import { createPathFromPoints, getNodeClasses } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const choice = (parent: SVG, node: Node) => {
|
export function choice<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { nodeStyles } = styles2String(node);
|
const { nodeStyles } = styles2String(node);
|
||||||
node.label = '';
|
node.label = '';
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
@ -24,7 +23,7 @@ export const choice = (parent: SVG, node: Node) => {
|
|||||||
{ x: -s / 2, y: 0 },
|
{ x: -s / 2, y: 0 },
|
||||||
];
|
];
|
||||||
|
|
||||||
// @ts-ignore TODO: Fix rough typings
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -53,4 +52,4 @@ export const choice = (parent: SVG, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,8 +4,10 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function circle<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -15,12 +17,13 @@ export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAEleme
|
|||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const roughNode = rc.circle(0, 0, radius * 2, options);
|
const roughNode = rc.circle(0, 0, radius * 2, options);
|
||||||
|
|
||||||
circleElem = shapeSvg.insert(() => roughNode, ':first-child');
|
circleElem = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
circleElem.attr('class', 'basic label-container').attr('style', cssStyles);
|
circleElem.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
} else {
|
} else {
|
||||||
circleElem = shapeSvg
|
circleElem = shapeSvg
|
||||||
.insert('circle', ':first-child')
|
.insert('circle', ':first-child')
|
||||||
@ -39,4 +42,4 @@ export const circle = async (parent: SVGAElement, node: Node): Promise<SVGAEleme
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -8,8 +8,9 @@ import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { textHelper } from '../../../diagrams/class/shapeUtil.js';
|
import { textHelper } from '../../../diagrams/class/shapeUtil.js';
|
||||||
import { evaluate } from '../../../diagrams/common/common.js';
|
import { evaluate } from '../../../diagrams/common/common.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function classBox<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
const PADDING = config.class!.padding ?? 12;
|
const PADDING = config.class!.padding ?? 12;
|
||||||
const GAP = PADDING;
|
const GAP = PADDING;
|
||||||
@ -81,7 +82,7 @@ export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
|
|
||||||
const rect = shapeSvg.insert(() => roughRect, ':first-child');
|
const rect = shapeSvg.insert(() => roughRect, ':first-child');
|
||||||
rect.attr('class', 'basic label-container');
|
rect.attr('class', 'basic label-container');
|
||||||
const rectBBox = rect.node().getBBox();
|
const rectBBox = rect.node()!.getBBox();
|
||||||
|
|
||||||
// Rect is centered so now adjust labels.
|
// Rect is centered so now adjust labels.
|
||||||
// TODO: Fix types
|
// TODO: Fix types
|
||||||
@ -132,13 +133,13 @@ export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
|
|
||||||
// Render divider lines.
|
// Render divider lines.
|
||||||
const annotationGroupHeight =
|
const annotationGroupHeight =
|
||||||
shapeSvg.select('.annotation-group').node().getBBox().height -
|
(shapeSvg.select('.annotation-group').node() as SVGGraphicsElement).getBBox().height -
|
||||||
(renderExtraBox ? PADDING / 2 : 0) || 0;
|
(renderExtraBox ? PADDING / 2 : 0) || 0;
|
||||||
const labelGroupHeight =
|
const labelGroupHeight =
|
||||||
shapeSvg.select('.label-group').node().getBBox().height - (renderExtraBox ? PADDING / 2 : 0) ||
|
(shapeSvg.select('.label-group').node() as SVGGraphicsElement).getBBox().height -
|
||||||
0;
|
(renderExtraBox ? PADDING / 2 : 0) || 0;
|
||||||
const membersGroupHeight =
|
const membersGroupHeight =
|
||||||
shapeSvg.select('.members-group').node().getBBox().height -
|
(shapeSvg.select('.members-group').node() as SVGGraphicsElement).getBBox().height -
|
||||||
(renderExtraBox ? PADDING / 2 : 0) || 0;
|
(renderExtraBox ? PADDING / 2 : 0) || 0;
|
||||||
// First line (under label)
|
// First line (under label)
|
||||||
if (classNode.members.length > 0 || classNode.methods.length > 0 || renderExtraBox) {
|
if (classNode.members.length > 0 || classNode.methods.length > 0 || renderExtraBox) {
|
||||||
@ -150,7 +151,7 @@ export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
options
|
options
|
||||||
);
|
);
|
||||||
const line = shapeSvg.insert(() => roughLine);
|
const line = shapeSvg.insert(() => roughLine);
|
||||||
line.attr('class', 'divider', 'style', styles);
|
line.attr('class', 'divider').attr('style', styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second line (under members)
|
// Second line (under members)
|
||||||
@ -163,7 +164,7 @@ export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
options
|
options
|
||||||
);
|
);
|
||||||
const line = shapeSvg.insert(() => roughLine);
|
const line = shapeSvg.insert(() => roughLine);
|
||||||
line.attr('class', 'divider', 'style', styles);
|
line.attr('class', 'divider').attr('style', styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply styles ///
|
/// Apply styles ///
|
||||||
@ -203,4 +204,4 @@ export const classBox = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
import type { Node } from '../../types.js';
|
||||||
import type { Node } from '../../types.ts';
|
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
function createLine(r: number) {
|
function createLine(r: number) {
|
||||||
const xAxis45 = Math.cos(Math.PI / 4); // cosine of 45 degrees
|
const xAxis45 = Math.cos(Math.PI / 4); // cosine of 45 degrees
|
||||||
@ -20,7 +20,7 @@ function createLine(r: number) {
|
|||||||
M ${pointQ1.x},${pointQ1.y} L ${pointQ3.x},${pointQ3.y}`;
|
M ${pointQ1.x},${pointQ1.y} L ${pointQ3.x},${pointQ3.y}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const crossedCircle = (parent: SVG, node: Node) => {
|
export function crossedCircle<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
node.label = '';
|
node.label = '';
|
||||||
@ -31,7 +31,7 @@ export const crossedCircle = (parent: SVG, node: Node) => {
|
|||||||
const radius = Math.max(30, node?.width ?? 0);
|
const radius = Math.max(30, node?.width ?? 0);
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
// @ts-expect-error shapeSvg d3 class is incorrect?
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -64,4 +64,4 @@ export const crossedCircle = (parent: SVG, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
function generateCirclePoints(
|
function generateCirclePoints(
|
||||||
centerX: number,
|
centerX: number,
|
||||||
@ -34,7 +35,10 @@ function generateCirclePoints(
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const curlyBraceLeft = async (parent: SVGAElement, node: Node) => {
|
export async function curlyBraceLeft<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -66,6 +70,7 @@ export const curlyBraceLeft = async (parent: SVGAElement, node: Node) => {
|
|||||||
{ x: w / 2, y: h / 2 + radius },
|
{ x: w / 2, y: h / 2 + radius },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { fill: 'none' });
|
const options = userNodeOverrides(node, { fill: 'none' });
|
||||||
|
|
||||||
@ -107,4 +112,4 @@ export const curlyBraceLeft = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
function generateCirclePoints(
|
function generateCirclePoints(
|
||||||
centerX: number,
|
centerX: number,
|
||||||
@ -34,7 +35,10 @@ function generateCirclePoints(
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const curlyBraceRight = async (parent: SVGAElement, node: Node) => {
|
export async function curlyBraceRight<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -66,6 +70,7 @@ export const curlyBraceRight = async (parent: SVGAElement, node: Node) => {
|
|||||||
{ x: -w / 2, y: h / 2 + radius },
|
{ x: -w / 2, y: h / 2 + radius },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { fill: 'none' });
|
const options = userNodeOverrides(node, { fill: 'none' });
|
||||||
|
|
||||||
@ -107,4 +112,4 @@ export const curlyBraceRight = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
function generateCirclePoints(
|
function generateCirclePoints(
|
||||||
centerX: number,
|
centerX: number,
|
||||||
@ -34,7 +35,10 @@ function generateCirclePoints(
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const curlyBraces = async (parent: SVGAElement, node: Node) => {
|
export async function curlyBraces<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -81,6 +85,7 @@ export const curlyBraces = async (parent: SVGAElement, node: Node) => {
|
|||||||
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
|
...generateCirclePoints(-w / 2 + radius + radius / 2, h / 2, radius, 30, -180, -270),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { fill: 'none' });
|
const options = userNodeOverrides(node, { fill: 'none' });
|
||||||
|
|
||||||
@ -126,4 +131,4 @@ export const curlyBraces = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -6,11 +6,15 @@ import {
|
|||||||
generateCirclePoints,
|
generateCirclePoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const curvedTrapezoid = async (parent: SVGAElement, node: Node) => {
|
export async function curvedTrapezoid<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -21,6 +25,7 @@ export const curvedTrapezoid = async (parent: SVGAElement, node: Node) => {
|
|||||||
const radius = h / 2;
|
const radius = h / 2;
|
||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -67,4 +72,4 @@ export const curvedTrapezoid = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -3,6 +3,8 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createCylinderPathD = (
|
export const createCylinderPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -48,7 +50,7 @@ export const createInnerCylinderPathD = (
|
|||||||
): string => {
|
): string => {
|
||||||
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
||||||
};
|
};
|
||||||
export const cylinder = async (parent: SVGAElement, node: Node) => {
|
export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -57,10 +59,11 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
const ry = rx / (2.5 + w / 50);
|
const ry = rx / (2.5 + w / 50);
|
||||||
const h = Math.max(bbox.height + ry + node.padding, node.height ?? 0);
|
const h = Math.max(bbox.height + ry + node.padding, node.height ?? 0);
|
||||||
|
|
||||||
let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
|
let cylinder: D3Selection<SVGPathElement> | D3Selection<SVGGElement>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
||||||
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
||||||
@ -79,7 +82,7 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
.insert('path', ':first-child')
|
.insert('path', ':first-child')
|
||||||
.attr('d', pathData)
|
.attr('d', pathData)
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', cssStyles)
|
.attr('style', handleUndefinedAttr(cssStyles))
|
||||||
.attr('style', nodeStyles);
|
.attr('style', nodeStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,4 +122,4 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const dividedRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function dividedRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -17,6 +21,7 @@ export const dividedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
if (node.look !== 'handDrawn') {
|
if (node.look !== 'handDrawn') {
|
||||||
@ -63,4 +68,4 @@ export const dividedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createCylinderPathD = (
|
export const createCylinderPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -48,7 +50,7 @@ export const createInnerCylinderPathD = (
|
|||||||
): string => {
|
): string => {
|
||||||
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
||||||
};
|
};
|
||||||
export const cylinder = async (parent: SVGAElement, node: Node) => {
|
export async function cylinder<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -57,10 +59,11 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
const ry = rx / (2.5 + w / 50);
|
const ry = rx / (2.5 + w / 50);
|
||||||
const h = bbox.height + ry + node.padding;
|
const h = bbox.height + ry + node.padding;
|
||||||
|
|
||||||
let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
|
let cylinder: D3Selection<SVGPathElement> | D3Selection<SVGGElement>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
||||||
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
||||||
@ -79,7 +82,7 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
.insert('path', ':first-child')
|
.insert('path', ':first-child')
|
||||||
.attr('d', pathData)
|
.attr('d', pathData)
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', cssStyles)
|
.attr('style', handleUndefinedAttr(cssStyles))
|
||||||
.attr('style', nodeStyles);
|
.attr('style', nodeStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,4 +117,4 @@ export const cylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,8 +4,13 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function doublecircle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -17,6 +22,7 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
|
|||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });
|
const outerOptions = userNodeOverrides(node, { roughness: 0.2, strokeWidth: 2.5 });
|
||||||
|
|
||||||
@ -26,7 +32,9 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
|
|||||||
|
|
||||||
circleGroup = shapeSvg.insert('g', ':first-child');
|
circleGroup = shapeSvg.insert('g', ':first-child');
|
||||||
// circleGroup = circleGroup.insert(() => outerRoughNode, ':first-child');
|
// circleGroup = circleGroup.insert(() => outerRoughNode, ':first-child');
|
||||||
circleGroup.attr('class', node.cssClasses).attr('style', cssStyles);
|
circleGroup
|
||||||
|
.attr('class', handleUndefinedAttr(node.cssClasses))
|
||||||
|
.attr('style', handleUndefinedAttr(cssStyles));
|
||||||
|
|
||||||
circleGroup.node()?.appendChild(outerRoughNode);
|
circleGroup.node()?.appendChild(outerRoughNode);
|
||||||
circleGroup.node()?.appendChild(innerRoughNode);
|
circleGroup.node()?.appendChild(innerRoughNode);
|
||||||
@ -60,4 +68,4 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise<SVG
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,8 +4,14 @@ import type { Node, RectOptions } from '../../types.js';
|
|||||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js';
|
import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => {
|
export async function drawRect<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node,
|
||||||
|
options: RectOptions
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
// console.log('IPI labelStyles:', labelStyles);
|
// console.log('IPI labelStyles:', labelStyles);
|
||||||
@ -39,15 +45,15 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt
|
|||||||
: rc.rectangle(x, y, totalWidth, totalHeight, options);
|
: rc.rectangle(x, y, totalWidth, totalHeight, options);
|
||||||
|
|
||||||
rect = shapeSvg.insert(() => roughNode, ':first-child');
|
rect = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
rect.attr('class', 'basic label-container').attr('style', cssStyles);
|
rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
} else {
|
} else {
|
||||||
rect = shapeSvg.insert('rect', ':first-child');
|
rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
rect
|
rect
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', nodeStyles)
|
.attr('style', nodeStyles)
|
||||||
.attr('rx', rx)
|
.attr('rx', handleUndefinedAttr(rx))
|
||||||
.attr('ry', ry)
|
.attr('ry', handleUndefinedAttr(ry))
|
||||||
.attr('x', x)
|
.attr('x', x)
|
||||||
.attr('y', y)
|
.attr('y', y)
|
||||||
.attr('width', totalWidth)
|
.attr('width', totalWidth)
|
||||||
@ -61,4 +67,4 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const filledCircle = (
|
export function filledCircle<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables } }: ShapeRenderOptions
|
{ config: { themeVariables } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.label = '';
|
node.label = '';
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
@ -21,7 +21,7 @@ export const filledCircle = (
|
|||||||
const radius = 7;
|
const radius = 7;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
// @ts-expect-error shapeSvg d3 class is incorrect?
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const { nodeBorder } = themeVariables;
|
const { nodeBorder } = themeVariables;
|
||||||
const options = userNodeOverrides(node, { fillStyle: 'solid' });
|
const options = userNodeOverrides(node, { fillStyle: 'solid' });
|
||||||
@ -53,4 +53,4 @@ export const filledCircle = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { createPathFromPoints } from './util.js';
|
import { createPathFromPoints } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const flippedTriangle = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function flippedTriangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -23,6 +27,7 @@ export const flippedTriangle = async (parent: SVGAElement, node: Node): Promise<
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
if (node.look !== 'handDrawn') {
|
if (node.look !== 'handDrawn') {
|
||||||
@ -60,4 +65,4 @@ export const flippedTriangle = async (parent: SVGAElement, node: Node): Promise<
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.js';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const forkJoin = (
|
export function forkJoin<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ dir, config: { state, themeVariables } }: ShapeRenderOptions
|
{ dir, config: { state, themeVariables } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { nodeStyles } = styles2String(node);
|
const { nodeStyles } = styles2String(node);
|
||||||
node.label = '';
|
node.label = '';
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
@ -29,7 +29,7 @@ export const forkJoin = (
|
|||||||
const x = (-1 * width) / 2;
|
const x = (-1 * width) / 2;
|
||||||
const y = (-1 * height) / 2;
|
const y = (-1 * height) / 2;
|
||||||
|
|
||||||
// @ts-ignore TODO: Fix rough typings
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {
|
const options = userNodeOverrides(node, {
|
||||||
stroke: themeVariables.lineColor,
|
stroke: themeVariables.lineColor,
|
||||||
@ -63,4 +63,4 @@ export const forkJoin = (
|
|||||||
return intersect.rect(node, point);
|
return intersect.rect(node, point);
|
||||||
};
|
};
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -7,11 +7,15 @@ import {
|
|||||||
generateCirclePoints,
|
generateCirclePoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const halfRoundedRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function halfRoundedRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const minWidth = 80,
|
const minWidth = 80,
|
||||||
@ -22,6 +26,7 @@ export const halfRoundedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
const radius = h / 2;
|
const radius = h / 2;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -64,4 +69,4 @@ export const halfRoundedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -3,8 +3,8 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const createHexagonPathD = (
|
export const createHexagonPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -24,7 +24,7 @@ export const createHexagonPathD = (
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function hexagon<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -42,10 +42,11 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElem
|
|||||||
{ x: 0, y: -h / 2 },
|
{ x: 0, y: -h / 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: D3Selection<SVGGElement> | Awaited<ReturnType<typeof insertPolygonShape>>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createHexagonPathD(0, 0, w, h, m);
|
const pathData = createHexagonPathD(0, 0, w, h, m);
|
||||||
@ -76,4 +77,4 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise<SVGAElem
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const hourglass = async (parent: SVGAElement, node: Node) => {
|
export async function hourglass<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.label = '';
|
node.label = '';
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
@ -16,6 +17,7 @@ export const hourglass = async (parent: SVGAElement, node: Node) => {
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -57,4 +59,4 @@ export const hourglass = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getIconSVG } from '../../icons.js';
|
import { getIconSVG } from '../../icons.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const icon = async (
|
export async function icon<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles } = styles2String(node);
|
const { labelStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const assetHeight = node.assetHeight ?? 48;
|
const assetHeight = node.assetHeight ?? 48;
|
||||||
@ -33,6 +33,7 @@ export const icon = async (
|
|||||||
|
|
||||||
const labelPadding = node.label ? 8 : 0;
|
const labelPadding = node.label ? 8 : 0;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' });
|
const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' });
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ export const icon = async (
|
|||||||
fallbackPrefix: '',
|
fallbackPrefix: '',
|
||||||
})}</g>`
|
})}</g>`
|
||||||
);
|
);
|
||||||
const iconBBox = iconElem.node().getBBox();
|
const iconBBox = iconElem.node()!.getBBox();
|
||||||
const iconWidth = iconBBox.width;
|
const iconWidth = iconBBox.width;
|
||||||
const iconHeight = iconBBox.height;
|
const iconHeight = iconBBox.height;
|
||||||
const iconX = iconBBox.x;
|
const iconX = iconBBox.x;
|
||||||
@ -134,4 +135,4 @@ export const icon = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getIconSVG } from '../../icons.js';
|
import { getIconSVG } from '../../icons.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const iconCircle = async (
|
export async function iconCircle<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles } = styles2String(node);
|
const { labelStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const assetHeight = node.assetHeight ?? 48;
|
const assetHeight = node.assetHeight ?? 48;
|
||||||
@ -28,6 +28,7 @@ export const iconCircle = async (
|
|||||||
|
|
||||||
const { nodeBorder } = themeVariables;
|
const { nodeBorder } = themeVariables;
|
||||||
const { stylesMap } = compileStyles(node);
|
const { stylesMap } = compileStyles(node);
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ export const iconCircle = async (
|
|||||||
})}</g>`
|
})}</g>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const iconBBox = iconElem.node().getBBox();
|
const iconBBox = iconElem.node()!.getBBox();
|
||||||
const iconWidth = iconBBox.width;
|
const iconWidth = iconBBox.width;
|
||||||
const iconHeight = iconBBox.height;
|
const iconHeight = iconBBox.height;
|
||||||
const iconX = iconBBox.x;
|
const iconX = iconBBox.x;
|
||||||
@ -98,4 +99,4 @@ export const iconCircle = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getIconSVG } from '../../icons.js';
|
import { getIconSVG } from '../../icons.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const iconRounded = async (
|
export async function iconRounded<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles } = styles2String(node);
|
const { labelStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const assetHeight = node.assetHeight ?? 48;
|
const assetHeight = node.assetHeight ?? 48;
|
||||||
@ -38,6 +38,7 @@ export const iconRounded = async (
|
|||||||
|
|
||||||
const labelPadding = node.label ? 8 : 0;
|
const labelPadding = node.label ? 8 : 0;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ export const iconRounded = async (
|
|||||||
fallbackPrefix: '',
|
fallbackPrefix: '',
|
||||||
})}</g>`
|
})}</g>`
|
||||||
);
|
);
|
||||||
const iconBBox = iconElem.node().getBBox();
|
const iconBBox = iconElem.node()!.getBBox();
|
||||||
const iconWidth = iconBBox.width;
|
const iconWidth = iconBBox.width;
|
||||||
const iconHeight = iconBBox.height;
|
const iconHeight = iconBBox.height;
|
||||||
const iconX = iconBBox.x;
|
const iconX = iconBBox.x;
|
||||||
@ -139,4 +140,4 @@ export const iconRounded = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getIconSVG } from '../../icons.js';
|
import { getIconSVG } from '../../icons.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const iconSquare = async (
|
export async function iconSquare<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
{ config: { themeVariables, flowchart } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles } = styles2String(node);
|
const { labelStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const assetHeight = node.assetHeight ?? 48;
|
const assetHeight = node.assetHeight ?? 48;
|
||||||
@ -37,6 +37,7 @@ export const iconSquare = async (
|
|||||||
|
|
||||||
const labelPadding = node.label ? 8 : 0;
|
const labelPadding = node.label ? 8 : 0;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
const options = userNodeOverrides(node, { stroke: 'transparent' });
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ export const iconSquare = async (
|
|||||||
fallbackPrefix: '',
|
fallbackPrefix: '',
|
||||||
})}</g>`
|
})}</g>`
|
||||||
);
|
);
|
||||||
const iconBBox = iconElem.node().getBBox();
|
const iconBBox = iconElem.node()!.getBBox();
|
||||||
const iconWidth = iconBBox.width;
|
const iconWidth = iconBBox.width;
|
||||||
const iconHeight = iconBBox.height;
|
const iconHeight = iconBBox.height;
|
||||||
const iconX = iconBBox.x;
|
const iconX = iconBBox.x;
|
||||||
@ -138,4 +139,4 @@ export const iconSquare = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.ts';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const imageSquare = async (
|
export async function imageSquare<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { flowchart } }: ShapeRenderOptions
|
{ config: { flowchart } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = node?.img ?? '';
|
img.src = node?.img ?? '';
|
||||||
await img.decode();
|
await img.decode();
|
||||||
@ -52,6 +52,7 @@ export const imageSquare = async (
|
|||||||
|
|
||||||
const labelPadding = node.label ? 8 : 0;
|
const labelPadding = node.label ? 8 : 0;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -145,4 +146,4 @@ export const imageSquare = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
export function insertPolygonShape(
|
import type { D3Selection } from '../../../types.js';
|
||||||
parent: any,
|
|
||||||
|
export function insertPolygonShape<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
points: { x: number; y: number }[]
|
points: { x: number; y: number }[]
|
||||||
|
@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
// export const createInvertedTrapezoidPathD = (
|
// export const createInvertedTrapezoidPathD = (
|
||||||
// x: number,
|
// x: number,
|
||||||
@ -20,7 +21,10 @@ import { insertPolygonShape } from './insertPolygonShape.js';
|
|||||||
// ].join(' ');
|
// ].join(' ');
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function inv_trapezoid<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -35,10 +39,11 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SV
|
|||||||
{ x: (-3 * h) / 6, y: -h },
|
{ x: (-3 * h) / 6, y: -h },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: typeof shapeSvg | ReturnType<typeof insertPolygonShape>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createPathFromPoints(points);
|
const pathData = createPathFromPoints(points);
|
||||||
@ -70,4 +75,4 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise<SV
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -2,8 +2,12 @@ import type { Node, RectOptions } from '../../types.js';
|
|||||||
import { drawRect } from './drawRect.js';
|
import { drawRect } from './drawRect.js';
|
||||||
import { labelHelper, updateNodeBounds } from './util.js';
|
import { labelHelper, updateNodeBounds } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const roundedRect = async (parent: SVGAElement, node: Node) => {
|
export async function roundedRect<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const options = {
|
const options = {
|
||||||
rx: 5,
|
rx: 5,
|
||||||
ry: 5,
|
ry: 5,
|
||||||
@ -13,9 +17,9 @@ export const roundedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
} as RectOptions;
|
} as RectOptions;
|
||||||
|
|
||||||
return drawRect(parent, node, options);
|
return drawRect(parent, node, options);
|
||||||
};
|
}
|
||||||
|
|
||||||
export const labelRect = async (parent: SVGElement, node: Node) => {
|
export async function labelRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'label');
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'label');
|
||||||
|
|
||||||
// log.trace('Classes = ', node.class);
|
// log.trace('Classes = ', node.class);
|
||||||
@ -52,4 +56,4 @@ export const labelRect = async (parent: SVGElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,8 +4,9 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function lean_left<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -18,10 +19,11 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAEl
|
|||||||
{ x: -(3 * h) / 6, y: -h },
|
{ x: -(3 * h) / 6, y: -h },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: typeof shapeSvg | ReturnType<typeof insertPolygonShape>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createPathFromPoints(points);
|
const pathData = createPathFromPoints(points);
|
||||||
@ -53,4 +55,4 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise<SVGAEl
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,8 +4,9 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function lean_right<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -18,10 +19,11 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAE
|
|||||||
{ x: 0, y: -h },
|
{ x: 0, y: -h },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: typeof shapeSvg | ReturnType<typeof insertPolygonShape>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createPathFromPoints(points);
|
const pathData = createPathFromPoints(points);
|
||||||
@ -52,4 +54,4 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise<SVGAE
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { getNodeClasses, updateNodeBounds } from './util.js';
|
import { getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { createPathFromPoints } from './util.js';
|
import { createPathFromPoints } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const lightningBolt = (parent: SVG, node: Node) => {
|
export function lightningBolt<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.label = '';
|
node.label = '';
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
@ -63,4 +63,4 @@ export const lightningBolt = (parent: SVG, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -3,6 +3,8 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createCylinderPathD = (
|
export const createCylinderPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -54,7 +56,10 @@ export const createInnerCylinderPathD = (
|
|||||||
): string => {
|
): string => {
|
||||||
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' ');
|
||||||
};
|
};
|
||||||
export const linedCylinder = async (parent: SVGAElement, node: Node) => {
|
export async function linedCylinder<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -64,10 +69,11 @@ export const linedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
const h = Math.max(bbox.height + ry + (node.padding ?? 0), node.height ?? 0);
|
const h = Math.max(bbox.height + ry + (node.padding ?? 0), node.height ?? 0);
|
||||||
const outerOffset = h * 0.1; // 10% of height
|
const outerOffset = h * 0.1; // 10% of height
|
||||||
|
|
||||||
let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
|
let cylinder: typeof shapeSvg | D3Selection<SVGPathElement>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry, outerOffset);
|
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry, outerOffset);
|
||||||
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry);
|
||||||
@ -89,7 +95,7 @@ export const linedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
.insert('path', ':first-child')
|
.insert('path', ':first-child')
|
||||||
.attr('d', pathData)
|
.attr('d', pathData)
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', cssStyles)
|
.attr('style', handleUndefinedAttr(cssStyles))
|
||||||
.attr('style', nodeStyles);
|
.attr('style', nodeStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,4 +136,4 @@ export const linedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -5,11 +5,15 @@ import {
|
|||||||
generateFullSineWavePoints,
|
generateFullSineWavePoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const linedWaveEdgedRect = async (parent: SVGAElement, node: Node) => {
|
export async function linedWaveEdgedRect<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -19,6 +23,7 @@ export const linedWaveEdgedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
const finalH = h + waveAmplitude;
|
const finalH = h + waveAmplitude;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -75,4 +80,4 @@ export const linedWaveEdgedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
|
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const multiRect = async (parent: SVGAElement, node: Node) => {
|
export async function multiRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -15,6 +16,7 @@ export const multiRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
const y = -h / 2;
|
const y = -h / 2;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -78,4 +80,4 @@ export const multiRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -6,11 +6,15 @@ import {
|
|||||||
generateFullSineWavePoints,
|
generateFullSineWavePoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const multiWaveEdgedRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function multiWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -59,6 +63,7 @@ export const multiWaveEdgedRectangle = async (parent: SVGAElement, node: Node) =
|
|||||||
{ x, y },
|
{ x, y },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -100,4 +105,4 @@ export const multiWaveEdgedRectangle = async (parent: SVGAElement, node: Node) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -3,12 +3,13 @@ import type { Node, ShapeRenderOptions } from '../../types.js';
|
|||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const note = async (
|
export async function note<T extends SVGGraphicsElement>(
|
||||||
parent: SVGAElement,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables } }: ShapeRenderOptions
|
{ config: { themeVariables } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -55,4 +56,4 @@ export const note = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -5,6 +5,7 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const createDecisionBoxPathD = (x: number, y: number, size: number): string => {
|
export const createDecisionBoxPathD = (x: number, y: number, size: number): string => {
|
||||||
return [
|
return [
|
||||||
@ -16,7 +17,7 @@ export const createDecisionBoxPathD = (x: number, y: number, size: number): stri
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const question = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function question<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -32,10 +33,11 @@ export const question = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
{ x: 0, y: -s / 2 },
|
{ x: 0, y: -s / 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: typeof shapeSvg | ReturnType<typeof insertPolygonShape>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createDecisionBoxPathD(0, 0, s);
|
const pathData = createDecisionBoxPathD(0, 0, s);
|
||||||
@ -71,4 +73,4 @@ export const question = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -3,11 +3,12 @@ import intersect from '../intersect/index.js';
|
|||||||
import type { Node } from '../../types.js';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const rect_left_inv_arrow = async (
|
export async function rect_left_inv_arrow<T extends SVGGraphicsElement>(
|
||||||
parent: SVGAElement,
|
parent: D3Selection<T>,
|
||||||
node: Node
|
node: Node
|
||||||
): Promise<SVGAElement> => {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -28,6 +29,7 @@ export const rect_left_inv_arrow = async (
|
|||||||
];
|
];
|
||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -63,4 +65,4 @@ export const rect_left_inv_arrow = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -9,8 +9,12 @@ import rough from 'roughjs';
|
|||||||
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
export async function rectWithTitle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
let classes;
|
let classes;
|
||||||
@ -36,7 +40,7 @@ export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
|||||||
|
|
||||||
const title = node.label;
|
const title = node.label;
|
||||||
|
|
||||||
const text = label.node().appendChild(await createLabel(title, node.labelStyle, true, true));
|
const text = label.node()!.appendChild(await createLabel(title, node.labelStyle, true, true));
|
||||||
let bbox = { width: 0, height: 0 };
|
let bbox = { width: 0, height: 0 };
|
||||||
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
|
if (evaluate(getConfig()?.flowchart?.htmlLabels)) {
|
||||||
const div = text.children[0];
|
const div = text.children[0];
|
||||||
@ -49,7 +53,7 @@ export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
|||||||
const textRows = description || [];
|
const textRows = description || [];
|
||||||
const titleBox = text.getBBox();
|
const titleBox = text.getBBox();
|
||||||
const descr = label
|
const descr = label
|
||||||
.node()
|
.node()!
|
||||||
.appendChild(
|
.appendChild(
|
||||||
await createLabel(
|
await createLabel(
|
||||||
textRows.join ? textRows.join('<br/>') : textRows,
|
textRows.join ? textRows.join('<br/>') : textRows,
|
||||||
@ -87,7 +91,7 @@ export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
|||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
|
|
||||||
// Bounding box for title and text
|
// Bounding box for title and text
|
||||||
bbox = label.node().getBBox();
|
bbox = label.node()!.getBBox();
|
||||||
|
|
||||||
// Center the label
|
// Center the label
|
||||||
label.attr(
|
label.attr(
|
||||||
@ -151,4 +155,4 @@ export const rectWithTitle = async (parent: SVGElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import type { Node, RectOptions } from '../../types.js';
|
import type { Node, RectOptions } from '../../types.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
import { drawRect } from './drawRect.js';
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
export const roundedRect = async (parent: SVGAElement, node: Node) => {
|
export async function roundedRect<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const options = {
|
const options = {
|
||||||
rx: 5,
|
rx: 5,
|
||||||
ry: 5,
|
ry: 5,
|
||||||
@ -11,4 +15,4 @@ export const roundedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
} as RectOptions;
|
} as RectOptions;
|
||||||
|
|
||||||
return drawRect(parent, node, options);
|
return drawRect(parent, node, options);
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const shadedProcess = async (parent: SVGAElement, node: Node) => {
|
export async function shadedProcess<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -15,6 +20,7 @@ export const shadedProcess = async (parent: SVGAElement, node: Node) => {
|
|||||||
const y = -bbox.height / 2 - halfPadding;
|
const y = -bbox.height / 2 - halfPadding;
|
||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -40,7 +46,7 @@ export const shadedProcess = async (parent: SVGAElement, node: Node) => {
|
|||||||
|
|
||||||
const rect = shapeSvg.insert(() => roughNode, ':first-child');
|
const rect = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
|
|
||||||
rect.attr('class', 'basic label-container').attr('style', cssStyles);
|
rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
|
|
||||||
if (nodeStyles && node.look !== 'handDrawn') {
|
if (nodeStyles && node.look !== 'handDrawn') {
|
||||||
rect.selectAll('path').attr('style', nodeStyles);
|
rect.selectAll('path').attr('style', nodeStyles);
|
||||||
@ -62,4 +68,4 @@ export const shadedProcess = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const slopedRect = async (parent: SVGAElement, node: Node) => {
|
export async function slopedRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -15,6 +16,7 @@ export const slopedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -58,4 +60,4 @@ export const slopedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import type { Node, RectOptions } from '../../types.js';
|
import type { Node, RectOptions } from '../../types.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
import { drawRect } from './drawRect.js';
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
export const squareRect = async (parent: SVGAElement, node: Node) => {
|
export async function squareRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const options = {
|
const options = {
|
||||||
rx: 0,
|
rx: 0,
|
||||||
ry: 0,
|
ry: 0,
|
||||||
@ -10,4 +11,4 @@ export const squareRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
labelPaddingY: (node?.padding || 0) * 1,
|
labelPaddingY: (node?.padding || 0) * 1,
|
||||||
} as RectOptions;
|
} as RectOptions;
|
||||||
return drawRect(parent, node, options);
|
return drawRect(parent, node, options);
|
||||||
};
|
}
|
||||||
|
@ -4,6 +4,8 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { createRoundedRectPathD } from './roundedRectPath.js';
|
import { createRoundedRectPathD } from './roundedRectPath.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createStadiumPathD = (
|
export const createStadiumPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -50,7 +52,7 @@ export const createStadiumPathD = (
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const stadium = async (parent: SVGAElement, node: Node) => {
|
export async function stadium<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -61,6 +63,7 @@ export const stadium = async (parent: SVGAElement, node: Node) => {
|
|||||||
let rect;
|
let rect;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -68,7 +71,7 @@ export const stadium = async (parent: SVGAElement, node: Node) => {
|
|||||||
const roughNode = rc.path(pathData, options);
|
const roughNode = rc.path(pathData, options);
|
||||||
|
|
||||||
rect = shapeSvg.insert(() => roughNode, ':first-child');
|
rect = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
rect.attr('class', 'basic label-container').attr('style', cssStyles);
|
rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
} else {
|
} else {
|
||||||
rect = shapeSvg.insert('rect', ':first-child');
|
rect = shapeSvg.insert('rect', ':first-child');
|
||||||
|
|
||||||
@ -90,4 +93,4 @@ export const stadium = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import type { Node, RectOptions } from '../../types.js';
|
import type { Node, RectOptions } from '../../types.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
import { drawRect } from './drawRect.js';
|
import { drawRect } from './drawRect.js';
|
||||||
|
|
||||||
export const state = async (parent: SVGAElement, node: Node) => {
|
export async function state<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const options = {
|
const options = {
|
||||||
rx: 5,
|
rx: 5,
|
||||||
ry: 5,
|
ry: 5,
|
||||||
classes: 'flowchart-node',
|
classes: 'flowchart-node',
|
||||||
} as RectOptions;
|
} as RectOptions;
|
||||||
return drawRect(parent, node, options);
|
return drawRect(parent, node, options);
|
||||||
};
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.js';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import { updateNodeBounds } from './util.js';
|
import { updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const stateEnd = (
|
export function stateEnd<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables } }: ShapeRenderOptions
|
{ config: { themeVariables } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
@ -59,4 +59,4 @@ export const stateEnd = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import type { SVG } from '../../../diagram-api/types.js';
|
|
||||||
import type { Node, ShapeRenderOptions } from '../../types.js';
|
import type { Node, ShapeRenderOptions } from '../../types.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import { solidStateFill } from './handDrawnShapeStyles.js';
|
import { solidStateFill } from './handDrawnShapeStyles.js';
|
||||||
import { updateNodeBounds } from './util.js';
|
import { updateNodeBounds } from './util.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const stateStart = (
|
export function stateStart<T extends SVGGraphicsElement>(
|
||||||
parent: SVG,
|
parent: D3Selection<T>,
|
||||||
node: Node,
|
node: Node,
|
||||||
{ config: { themeVariables } }: ShapeRenderOptions
|
{ config: { themeVariables } }: ShapeRenderOptions
|
||||||
) => {
|
) {
|
||||||
const { lineColor } = themeVariables;
|
const { lineColor } = themeVariables;
|
||||||
|
|
||||||
const shapeSvg = parent
|
const shapeSvg = parent
|
||||||
@ -17,20 +17,20 @@ export const stateStart = (
|
|||||||
.attr('class', 'node default')
|
.attr('class', 'node default')
|
||||||
.attr('id', node.domId || node.id);
|
.attr('id', node.domId || node.id);
|
||||||
|
|
||||||
let circle;
|
let circle: D3Selection<SVGCircleElement> | D3Selection<SVGGElement>;
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
// @ts-ignore TODO: Fix rough typings
|
// @ts-ignore TODO: Fix rough typings
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor));
|
const roughNode = rc.circle(0, 0, 14, solidStateFill(lineColor));
|
||||||
circle = shapeSvg.insert(() => roughNode);
|
circle = shapeSvg.insert(() => roughNode);
|
||||||
|
// center the circle around its coordinate
|
||||||
|
circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14);
|
||||||
} else {
|
} else {
|
||||||
circle = shapeSvg.insert('circle', ':first-child');
|
circle = shapeSvg.insert('circle', ':first-child');
|
||||||
|
// center the circle around its coordinate
|
||||||
|
circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
// center the circle around its coordinate
|
|
||||||
// @ts-ignore TODO: Fix typings
|
|
||||||
circle.attr('class', 'state-start').attr('r', 7).attr('width', 14).attr('height', 14);
|
|
||||||
|
|
||||||
updateNodeBounds(node, circle);
|
updateNodeBounds(node, circle);
|
||||||
|
|
||||||
node.intersect = function (point) {
|
node.intersect = function (point) {
|
||||||
@ -38,4 +38,4 @@ export const stateStart = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,6 +4,8 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createSubroutinePathD = (
|
export const createSubroutinePathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -31,7 +33,7 @@ export const createSubroutinePathD = (
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const subroutine = async (parent: SVGAElement, node: Node) => {
|
export async function subroutine<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -55,6 +57,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -66,7 +69,7 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
|
|||||||
shapeSvg.insert(() => l2, ':first-child');
|
shapeSvg.insert(() => l2, ':first-child');
|
||||||
const rect = shapeSvg.insert(() => roughNode, ':first-child');
|
const rect = shapeSvg.insert(() => roughNode, ':first-child');
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
rect.attr('class', 'basic label-container').attr('style', cssStyles);
|
rect.attr('class', 'basic label-container').attr('style', handleUndefinedAttr(cssStyles));
|
||||||
updateNodeBounds(node, rect);
|
updateNodeBounds(node, rect);
|
||||||
} else {
|
} else {
|
||||||
const el = insertPolygonShape(shapeSvg, w, h, points);
|
const el = insertPolygonShape(shapeSvg, w, h, points);
|
||||||
@ -81,4 +84,4 @@ export const subroutine = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
|
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const taggedRect = async (parent: SVGAElement, node: Node) => {
|
export async function taggedRect<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -16,6 +17,7 @@ export const taggedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
const tagHeight = 0.2 * h;
|
const tagHeight = 0.2 * h;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -65,4 +67,4 @@ export const taggedRect = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -6,11 +6,15 @@ import {
|
|||||||
createPathFromPoints,
|
createPathFromPoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const taggedWaveEdgedRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function taggedWaveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -22,6 +26,7 @@ export const taggedWaveEdgedRectangle = async (parent: SVGAElement, node: Node)
|
|||||||
const finalH = h + waveAmplitude;
|
const finalH = h + waveAmplitude;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -97,4 +102,4 @@ export const taggedWaveEdgedRectangle = async (parent: SVGAElement, node: Node)
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String } from './handDrawnShapeStyles.js';
|
import { styles2String } from './handDrawnShapeStyles.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export async function text(parent: SVGAElement, node: Node): Promise<SVGAElement> {
|
export async function text<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
|
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
import { handleUndefinedAttr } from '../../../utils.js';
|
||||||
|
|
||||||
export const createCylinderPathD = (
|
export const createCylinderPathD = (
|
||||||
x: number,
|
x: number,
|
||||||
@ -49,7 +51,10 @@ export const createInnerCylinderPathD = (
|
|||||||
return [`M${x + width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 0,${height}`].join(' ');
|
return [`M${x + width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 0,${height}`].join(' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const tiltedCylinder = async (parent: SVGAElement, node: Node) => {
|
export async function tiltedCylinder<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label, halfPadding } = await labelHelper(
|
const { shapeSvg, bbox, label, halfPadding } = await labelHelper(
|
||||||
@ -64,9 +69,10 @@ export const tiltedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
const w = bbox.width + rx + labelPadding;
|
const w = bbox.width + rx + labelPadding;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
let cylinder: d3.Selection<SVGPathElement | SVGGElement, unknown, null, undefined>;
|
let cylinder: D3Selection<SVGGElement> | D3Selection<SVGPathElement>;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry);
|
||||||
const innerPathData = createInnerCylinderPathD(0, 0, w, h, rx, ry);
|
const innerPathData = createInnerCylinderPathD(0, 0, w, h, rx, ry);
|
||||||
@ -84,19 +90,19 @@ export const tiltedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
.insert('path', ':first-child')
|
.insert('path', ':first-child')
|
||||||
.attr('d', pathData)
|
.attr('d', pathData)
|
||||||
.attr('class', 'basic label-container')
|
.attr('class', 'basic label-container')
|
||||||
.attr('style', cssStyles)
|
.attr('style', handleUndefinedAttr(cssStyles))
|
||||||
.attr('style', nodeStyles);
|
.attr('style', nodeStyles);
|
||||||
|
cylinder.attr('class', 'basic label-container');
|
||||||
|
|
||||||
|
if (cssStyles) {
|
||||||
|
cylinder.selectAll('path').attr('style', cssStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeStyles) {
|
||||||
|
cylinder.selectAll('path').attr('style', nodeStyles);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cylinder.attr('class', 'basic label-container');
|
|
||||||
|
|
||||||
if (cssStyles && node.look !== 'handDrawn') {
|
|
||||||
cylinder.selectAll('path').attr('style', cssStyles);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nodeStyles && node.look !== 'handDrawn') {
|
|
||||||
cylinder.selectAll('path').attr('style', nodeStyles);
|
|
||||||
}
|
|
||||||
cylinder.attr('label-offset-x', rx);
|
cylinder.attr('label-offset-x', rx);
|
||||||
cylinder.attr('transform', `translate(${-w / 2}, ${h / 2} )`);
|
cylinder.attr('transform', `translate(${-w / 2}, ${h / 2} )`);
|
||||||
|
|
||||||
@ -133,4 +139,4 @@ export const tiltedCylinder = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -4,6 +4,7 @@ import type { Node } from '../../types.js';
|
|||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { insertPolygonShape } from './insertPolygonShape.js';
|
import { insertPolygonShape } from './insertPolygonShape.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
// export const createTrapezoidPathD = (
|
// export const createTrapezoidPathD = (
|
||||||
// x: number,
|
// x: number,
|
||||||
@ -20,7 +21,7 @@ import { insertPolygonShape } from './insertPolygonShape.js';
|
|||||||
// ].join(' ');
|
// ].join(' ');
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export const trapezoid = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function trapezoid<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -34,10 +35,11 @@ export const trapezoid = async (parent: SVGAElement, node: Node): Promise<SVGAEl
|
|||||||
{ x: 0, y: -h },
|
{ x: 0, y: -h },
|
||||||
];
|
];
|
||||||
|
|
||||||
let polygon: d3.Selection<SVGPolygonElement | SVGGElement, unknown, null, undefined>;
|
let polygon: typeof shapeSvg | ReturnType<typeof insertPolygonShape>;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
if (node.look === 'handDrawn') {
|
if (node.look === 'handDrawn') {
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
const pathData = createPathFromPoints(points);
|
const pathData = createPathFromPoints(points);
|
||||||
@ -68,4 +70,4 @@ export const trapezoid = async (parent: SVGAElement, node: Node): Promise<SVGAEl
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const trapezoidalPentagon = async (parent: SVGAElement, node: Node) => {
|
export async function trapezoidalPentagon<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -14,6 +18,7 @@ export const trapezoidalPentagon = async (parent: SVGAElement, node: Node) => {
|
|||||||
const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
|
const h = Math.max(minHeight, bbox.height + (node.padding ?? 0) * 2, node?.height ?? 0);
|
||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -53,4 +58,4 @@ export const trapezoidalPentagon = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { log } from '../../../logger.js';
|
import { log } from '../../../logger.js';
|
||||||
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { createPathFromPoints } from './util.js';
|
import { createPathFromPoints } from './util.js';
|
||||||
import { evaluate } from '../../../diagrams/common/common.js';
|
import { evaluate } from '../../../diagrams/common/common.js';
|
||||||
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const triangle = async (parent: SVGAElement, node: Node): Promise<SVGAElement> => {
|
export async function triangle<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -26,6 +27,7 @@ export const triangle = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
|
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
if (node.look !== 'handDrawn') {
|
if (node.look !== 'handDrawn') {
|
||||||
@ -63,4 +65,4 @@ export const triangle = async (parent: SVGAElement, node: Node): Promise<SVGAEle
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import { createText } from '../../createText.js';
|
import { createText } from '../../createText.js';
|
||||||
|
import type { Node } from '../../types.js';
|
||||||
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../../diagram-api/diagramAPI.js';
|
||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
|
import defaultConfig from '../../../defaultConfig.js';
|
||||||
import { evaluate, sanitizeText } from '../../../diagrams/common/common.js';
|
import { evaluate, sanitizeText } from '../../../diagrams/common/common.js';
|
||||||
import { decodeEntities } from '../../../utils.js';
|
import { decodeEntities, handleUndefinedAttr, parseFontSize } from '../../../utils.js';
|
||||||
|
import type { D3Selection, Point } from '../../../types.js';
|
||||||
|
|
||||||
export const labelHelper = async (parent, node, _classes) => {
|
export const labelHelper = async <T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node,
|
||||||
|
_classes?: string
|
||||||
|
) => {
|
||||||
let cssClasses;
|
let cssClasses;
|
||||||
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig().flowchart.htmlLabels);
|
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.flowchart?.htmlLabels);
|
||||||
if (!_classes) {
|
if (!_classes) {
|
||||||
cssClasses = 'node default';
|
cssClasses = 'node default';
|
||||||
} else {
|
} else {
|
||||||
@ -20,7 +27,10 @@ export const labelHelper = async (parent, node, _classes) => {
|
|||||||
.attr('id', node.domId || node.id);
|
.attr('id', node.domId || node.id);
|
||||||
|
|
||||||
// Create the label and insert it after the rect
|
// Create the label and insert it after the rect
|
||||||
const labelEl = shapeSvg.insert('g').attr('class', 'label').attr('style', node.labelStyle);
|
const labelEl = shapeSvg
|
||||||
|
.insert('g')
|
||||||
|
.attr('class', 'label')
|
||||||
|
.attr('style', handleUndefinedAttr(node.labelStyle));
|
||||||
|
|
||||||
// Replace label with default value if undefined
|
// Replace label with default value if undefined
|
||||||
let label;
|
let label;
|
||||||
@ -30,19 +40,19 @@ export const labelHelper = async (parent, node, _classes) => {
|
|||||||
label = typeof node.label === 'string' ? node.label : node.label[0];
|
label = typeof node.label === 'string' ? node.label : node.label[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
let text;
|
const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
|
||||||
text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
|
|
||||||
useHtmlLabels,
|
useHtmlLabels,
|
||||||
width: node.width || getConfig().flowchart.wrappingWidth,
|
width: node.width || getConfig().flowchart?.wrappingWidth,
|
||||||
|
// @ts-expect-error -- This is currently not used. Should this be `classes` instead?
|
||||||
cssClasses: 'markdown-node-label',
|
cssClasses: 'markdown-node-label',
|
||||||
style: node.labelStyle,
|
style: node.labelStyle,
|
||||||
addSvgBackground: !!node.icon || !!node.img,
|
addSvgBackground: !!node.icon || !!node.img,
|
||||||
});
|
});
|
||||||
// Get the size of the label
|
// Get the size of the label
|
||||||
let bbox = text.getBBox();
|
let bbox = text.getBBox();
|
||||||
const halfPadding = node.padding / 2;
|
const halfPadding = (node?.padding ?? 0) / 2;
|
||||||
|
|
||||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
if (evaluate(getConfig().flowchart?.htmlLabels)) {
|
||||||
const div = text.children[0];
|
const div = text.children[0];
|
||||||
const dv = select(text);
|
const dv = select(text);
|
||||||
|
|
||||||
@ -68,7 +78,8 @@ export const labelHelper = async (parent, node, _classes) => {
|
|||||||
? getConfig().fontSize
|
? getConfig().fontSize
|
||||||
: window.getComputedStyle(document.body).fontSize;
|
: window.getComputedStyle(document.body).fontSize;
|
||||||
const enlargingFactor = 5;
|
const enlargingFactor = 5;
|
||||||
const width = parseInt(bodyFontSize, 10) * enlargingFactor + 'px';
|
const [parsedBodyFontSize = defaultConfig.fontSize] = parseFontSize(bodyFontSize);
|
||||||
|
const width = parsedBodyFontSize * enlargingFactor + 'px';
|
||||||
img.style.minWidth = width;
|
img.style.minWidth = width;
|
||||||
img.style.maxWidth = width;
|
img.style.maxWidth = width;
|
||||||
} else {
|
} else {
|
||||||
@ -106,19 +117,28 @@ export const labelHelper = async (parent, node, _classes) => {
|
|||||||
return { shapeSvg, bbox, halfPadding, label: labelEl };
|
return { shapeSvg, bbox, halfPadding, label: labelEl };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateNodeBounds = (node, element) => {
|
export const updateNodeBounds = <T extends SVGGraphicsElement>(
|
||||||
const bbox = element.node().getBBox();
|
node: Node,
|
||||||
|
// D3Selection<SVGGElement> is for the roughjs case, D3Selection<T> is for the non-roughjs case
|
||||||
|
element: D3Selection<SVGGElement> | D3Selection<T>
|
||||||
|
) => {
|
||||||
|
const bbox = element.node()!.getBBox();
|
||||||
node.width = bbox.width;
|
node.width = bbox.width;
|
||||||
node.height = bbox.height;
|
node.height = bbox.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parent
|
* @param parent - Parent element to append the polygon to
|
||||||
* @param w
|
* @param w - Width of the polygon
|
||||||
* @param h
|
* @param h - Height of the polygon
|
||||||
* @param points
|
* @param points - Array of points to create the polygon
|
||||||
*/
|
*/
|
||||||
export function insertPolygonShape(parent, w, h, points) {
|
export function insertPolygonShape(
|
||||||
|
parent: D3Selection<SVGGElement>,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
points: Point[]
|
||||||
|
) {
|
||||||
return parent
|
return parent
|
||||||
.insert('polygon', ':first-child')
|
.insert('polygon', ':first-child')
|
||||||
.attr(
|
.attr(
|
||||||
@ -133,16 +153,23 @@ export function insertPolygonShape(parent, w, h, points) {
|
|||||||
.attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')');
|
.attr('transform', 'translate(' + -w / 2 + ',' + h / 2 + ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getNodeClasses = (node, extra) =>
|
export const getNodeClasses = (node: Node, extra?: string) =>
|
||||||
(node.look === 'handDrawn' ? 'rough-node' : 'node') + ' ' + node.cssClasses + ' ' + (extra || '');
|
(node.look === 'handDrawn' ? 'rough-node' : 'node') + ' ' + node.cssClasses + ' ' + (extra || '');
|
||||||
|
|
||||||
export function createPathFromPoints(points) {
|
export function createPathFromPoints(points: Point[]) {
|
||||||
const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`);
|
const pointStrings = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`);
|
||||||
pointStrings.push('Z');
|
pointStrings.push('Z');
|
||||||
return pointStrings.join(' ');
|
return pointStrings.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateFullSineWavePoints(x1, y1, x2, y2, amplitude, numCycles) {
|
export function generateFullSineWavePoints(
|
||||||
|
x1: number,
|
||||||
|
y1: number,
|
||||||
|
x2: number,
|
||||||
|
y2: number,
|
||||||
|
amplitude: number,
|
||||||
|
numCycles: number
|
||||||
|
) {
|
||||||
const points = [];
|
const points = [];
|
||||||
const steps = 50; // Number of segments to create a smooth curve
|
const steps = 50; // Number of segments to create a smooth curve
|
||||||
const deltaX = x2 - x1;
|
const deltaX = x2 - x1;
|
||||||
@ -164,13 +191,21 @@ export function generateFullSineWavePoints(x1, y1, x2, y2, amplitude, numCycles)
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param centerX - x-coordinate of center of circle
|
||||||
|
* @param centerY - y-coordinate of center of circle
|
||||||
|
* @param radius - radius of circle
|
||||||
|
* @param numPoints - total points required
|
||||||
|
* @param startAngle - angle where arc will start
|
||||||
|
* @param endAngle - angle where arc will end
|
||||||
|
*/
|
||||||
export function generateCirclePoints(
|
export function generateCirclePoints(
|
||||||
centerX, // x-coordinate of center of circle
|
centerX: number,
|
||||||
centerY, // x-coordinate of center of circle
|
centerY: number,
|
||||||
radius, // radius of circle
|
radius: number,
|
||||||
numPoints, // total points required
|
numPoints: number,
|
||||||
startAngle, // angle where arc will start
|
startAngle: number,
|
||||||
endAngle // angle where arc will end
|
endAngle: number
|
||||||
) {
|
) {
|
||||||
const points = [];
|
const points = [];
|
||||||
|
|
@ -6,11 +6,15 @@ import {
|
|||||||
createPathFromPoints,
|
createPathFromPoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const waveEdgedRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function waveEdgedRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -25,6 +29,7 @@ export const waveEdgedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
const widthDif = minWidth - w;
|
const widthDif = minWidth - w;
|
||||||
const extraW = widthDif > 0 ? widthDif / 2 : 0;
|
const extraW = widthDif > 0 ? widthDif / 2 : 0;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -75,4 +80,4 @@ export const waveEdgedRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -6,11 +6,15 @@ import {
|
|||||||
generateFullSineWavePoints,
|
generateFullSineWavePoints,
|
||||||
} from './util.js';
|
} from './util.js';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const waveRectangle = async (parent: SVGAElement, node: Node) => {
|
export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||||
|
parent: D3Selection<T>,
|
||||||
|
node: Node
|
||||||
|
) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -39,6 +43,7 @@ export const waveRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
const finalH = h + waveAmplitude * 2;
|
const finalH = h + waveAmplitude * 2;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -76,4 +81,4 @@ export const waveRectangle = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
|
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
|
||||||
import type { Node } from '../../types.ts';
|
import type { Node } from '../../types.js';
|
||||||
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
|
||||||
import rough from 'roughjs';
|
import rough from 'roughjs';
|
||||||
import intersect from '../intersect/index.js';
|
import intersect from '../intersect/index.js';
|
||||||
|
import type { D3Selection } from '../../../types.js';
|
||||||
|
|
||||||
export const windowPane = async (parent: SVGAElement, node: Node) => {
|
export async function windowPane<T extends SVGGraphicsElement>(parent: D3Selection<T>, node: Node) {
|
||||||
const { labelStyles, nodeStyles } = styles2String(node);
|
const { labelStyles, nodeStyles } = styles2String(node);
|
||||||
node.labelStyle = labelStyles;
|
node.labelStyle = labelStyles;
|
||||||
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node));
|
||||||
@ -15,6 +16,7 @@ export const windowPane = async (parent: SVGAElement, node: Node) => {
|
|||||||
const y = -h / 2;
|
const y = -h / 2;
|
||||||
const { cssStyles } = node;
|
const { cssStyles } = node;
|
||||||
|
|
||||||
|
// @ts-expect-error -- Passing a D3.Selection seems to work for some reason
|
||||||
const rc = rough.svg(shapeSvg);
|
const rc = rough.svg(shapeSvg);
|
||||||
const options = userNodeOverrides(node, {});
|
const options = userNodeOverrides(node, {});
|
||||||
|
|
||||||
@ -62,4 +64,4 @@ export const windowPane = async (parent: SVGAElement, node: Node) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return shapeSvg;
|
return shapeSvg;
|
||||||
};
|
}
|
||||||
|
@ -149,5 +149,6 @@ export type LayoutMethod =
|
|||||||
|
|
||||||
export interface ShapeRenderOptions {
|
export interface ShapeRenderOptions {
|
||||||
config: MermaidConfig;
|
config: MermaidConfig;
|
||||||
dir: string;
|
/** Some shapes render differently if a diagram has a direction `LR` */
|
||||||
|
dir?: Node['dir'];
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,11 @@ export interface ParseResult {
|
|||||||
// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type.
|
// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type.
|
||||||
export type D3Element = any;
|
export type D3Element = any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper type for d3 selections.
|
||||||
|
*/
|
||||||
|
export type D3Selection<T extends SVGElement> = d3.Selection<T, unknown, Element | null, unknown>;
|
||||||
|
|
||||||
export interface RenderResult {
|
export interface RenderResult {
|
||||||
/**
|
/**
|
||||||
* The svg code for the rendered graph.
|
* The svg code for the rendered graph.
|
||||||
@ -89,3 +94,10 @@ export interface RenderResult {
|
|||||||
*/
|
*/
|
||||||
bindFunctions?: (element: Element) => void;
|
bindFunctions?: (element: Element) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be converted back to `T` by awaiting/`Awaited<T>`.
|
||||||
|
*
|
||||||
|
* This is useful for function types that may be either synchronous or asynchronous.
|
||||||
|
*/
|
||||||
|
export type MaybePromise<T> = T | Promise<T>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
import type { CurveFactory } from 'd3';
|
import type { BaseType, CurveFactory } from 'd3';
|
||||||
import {
|
import {
|
||||||
curveBasis,
|
curveBasis,
|
||||||
curveBasisClosed,
|
curveBasisClosed,
|
||||||
@ -941,3 +941,15 @@ export const getEdgeId = (
|
|||||||
) => {
|
) => {
|
||||||
return `${prefix ? `${prefix}_` : ''}${from}_${to}_${counter}${suffix ? `_${suffix}` : ''}`;
|
return `${prefix ? `${prefix}_` : ''}${from}_${to}_${counter}${suffix ? `_${suffix}` : ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* D3's `selection.attr` method doesn't officially support `undefined`.
|
||||||
|
*
|
||||||
|
* However, it seems if you do pass `undefined`, it seems to be treated as `null`
|
||||||
|
* (e.g. it removes the attribute).
|
||||||
|
*/
|
||||||
|
export function handleUndefinedAttr(
|
||||||
|
attrValue: Parameters<d3.Selection<BaseType, unknown, HTMLElement, any>['attr']>[1] | undefined
|
||||||
|
) {
|
||||||
|
return attrValue ?? null;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user