@hpcc-js/graph 3.6.5 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +43 -43
  2. package/README.md +256 -256
  3. package/dist/assets/dagre-B-z4SP0u.js.map +1 -1
  4. package/dist/assets/{graphviz-DQ0E8zfY.js.map → graphviz-DJ070oMZ.js.map} +1 -1
  5. package/dist/index.js +4 -4
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.umd.cjs +13 -13
  8. package/dist/index.umd.cjs.map +1 -1
  9. package/package.json +9 -9
  10. package/src/AdjacencyGraph.ts +224 -224
  11. package/src/Edge.css +23 -23
  12. package/src/Edge.ts +257 -257
  13. package/src/Graph.css +18 -18
  14. package/src/Graph.ts +1077 -1077
  15. package/src/GraphData.ts +187 -187
  16. package/src/GraphLayouts.ts +214 -214
  17. package/src/Sankey.css +45 -46
  18. package/src/Sankey.ts +304 -304
  19. package/src/Subgraph.css +10 -10
  20. package/src/Subgraph.ts +165 -165
  21. package/src/Vertex.css +3 -3
  22. package/src/Vertex.ts +282 -282
  23. package/src/__package__.ts +3 -3
  24. package/src/__tests__/data.ts +444 -444
  25. package/src/__tests__/index.ts +1 -1
  26. package/src/__tests__/test1.ts +18 -18
  27. package/src/__tests__/test2.ts +80 -80
  28. package/src/__tests__/test3.ts +46 -46
  29. package/src/__tests__/test4.ts +66 -66
  30. package/src/__tests__/test5.ts +85 -85
  31. package/src/common/graphT.css +38 -38
  32. package/src/common/graphT.ts +1363 -1363
  33. package/src/common/index.ts +3 -3
  34. package/src/common/layouts/circle.ts +37 -37
  35. package/src/common/layouts/dagre.ts +145 -145
  36. package/src/common/layouts/dagreWorker.ts +24 -24
  37. package/src/common/layouts/forceDirected.ts +117 -117
  38. package/src/common/layouts/forceDirectedWorker.ts +22 -22
  39. package/src/common/layouts/geoForceDirected.ts +112 -112
  40. package/src/common/layouts/graphviz.ts +137 -137
  41. package/src/common/layouts/graphvizWorker.ts +27 -27
  42. package/src/common/layouts/index.ts +7 -7
  43. package/src/common/layouts/layout.ts +147 -147
  44. package/src/common/layouts/null.ts +39 -39
  45. package/src/common/layouts/placeholders.ts +113 -113
  46. package/src/common/layouts/tree.ts +326 -326
  47. package/src/common/layouts/workers/dagre.ts +46 -46
  48. package/src/common/layouts/workers/dagreOptions.ts +35 -35
  49. package/src/common/layouts/workers/forceDirected.ts +38 -38
  50. package/src/common/layouts/workers/forceDirectedOptions.ts +30 -30
  51. package/src/common/layouts/workers/graphviz.ts +225 -225
  52. package/src/common/layouts/workers/graphvizOptions.ts +70 -70
  53. package/src/common/liteMap.ts +72 -72
  54. package/src/common/liteSVGZooom.ts +61 -61
  55. package/src/common/sankeyGraph.css +45 -45
  56. package/src/common/sankeyGraph.ts +345 -345
  57. package/src/html/annotation.ts +71 -71
  58. package/src/html/component.ts +18 -18
  59. package/src/html/edge.ts +15 -15
  60. package/src/html/graphHtml.ts +11 -11
  61. package/src/html/graphHtmlT.ts +117 -117
  62. package/src/html/icon.ts +64 -64
  63. package/src/html/image.ts +26 -26
  64. package/src/html/imageChar.ts +18 -18
  65. package/src/html/index.ts +8 -8
  66. package/src/html/intersection.ts +110 -110
  67. package/src/html/shape.ts +141 -141
  68. package/src/html/text.ts +59 -59
  69. package/src/html/textBox.ts +45 -45
  70. package/src/html/vertex.ts +67 -67
  71. package/src/index.ts +10 -10
  72. package/src/react/dataGraph.ts +345 -345
  73. package/src/react/graphReact.ts +177 -177
  74. package/src/react/graphReactT.ts +44 -44
  75. package/src/react/index.ts +4 -4
  76. package/src/react/subgraph.tsx +30 -30
  77. package/src/react/vertex.tsx +31 -31
@@ -1,18 +1,18 @@
1
- import { Utility } from "@hpcc-js/common";
2
- import { TextLine, TextProps } from "./text.ts";
3
-
4
- export const ImageChar = ({
5
- text = "",
6
- fill,
7
- fontFamily = "FontAwesome",
8
- fontSize = 12
9
- }: TextProps) => {
10
- const renderChar = fontFamily === "FontAwesome" ? Utility.faChar(text) : text;
11
- return TextLine({
12
- text: renderChar,
13
- fill,
14
- fontFamily,
15
- fontSize,
16
- dominantBaseline: fontFamily === "FontAwesome" ? "ideographic" : undefined
17
- });
18
- };
1
+ import { Utility } from "@hpcc-js/common";
2
+ import { TextLine, TextProps } from "./text.ts";
3
+
4
+ export const ImageChar = ({
5
+ text = "",
6
+ fill,
7
+ fontFamily = "FontAwesome",
8
+ fontSize = 12
9
+ }: TextProps) => {
10
+ const renderChar = fontFamily === "FontAwesome" ? Utility.faChar(text) : text;
11
+ return TextLine({
12
+ text: renderChar,
13
+ fill,
14
+ fontFamily,
15
+ fontSize,
16
+ dominantBaseline: fontFamily === "FontAwesome" ? "ideographic" : undefined
17
+ });
18
+ };
package/src/html/index.ts CHANGED
@@ -1,8 +1,8 @@
1
- export * from "./annotation.ts";
2
- export * from "./graphHtml.ts";
3
- export * from "./icon.ts";
4
- export * from "./image.ts";
5
- export * from "./imageChar.ts";
6
- export * from "./shape.ts";
7
- export * from "./text.ts";
8
- export * from "./vertex.ts";
1
+ export * from "./annotation.ts";
2
+ export * from "./graphHtml.ts";
3
+ export * from "./icon.ts";
4
+ export * from "./image.ts";
5
+ export * from "./imageChar.ts";
6
+ export * from "./shape.ts";
7
+ export * from "./text.ts";
8
+ export * from "./vertex.ts";
@@ -1,110 +1,110 @@
1
- export interface Pos {
2
- x: number;
3
- y: number;
4
- }
5
-
6
- export interface Extent {
7
- width: number;
8
- height: number;
9
- }
10
-
11
- export interface Segment {
12
- start: Pos;
13
- end: Pos;
14
- }
15
-
16
- export interface Rectangle {
17
- x: number;
18
- y: number;
19
- width: number;
20
- height: number;
21
- }
22
-
23
- function segmentSegment(s1: Segment, s2: Segment): Pos | undefined {
24
- const { x: x1, y: y1 } = s1.start;
25
- const { x: x2, y: y2 } = s1.end;
26
- const { x: x3, y: y3 } = s2.start;
27
- const { x: x4, y: y4 } = s2.end;
28
-
29
- const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
30
- if (denom === 0) {
31
- // Parallel lines ---
32
- return undefined;
33
- }
34
-
35
- const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
36
- const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom;
37
-
38
- if (t > 0 && t < 1 && u > 0 && u < 1) {
39
- return {
40
- x: x1 + t * (x2 - x1),
41
- y: y1 + t * (y2 - y1)
42
- };
43
- }
44
-
45
- return undefined;
46
- }
47
-
48
- function rectEdges(rect: Rectangle): Segment[] {
49
- const r = {
50
- topLeft: { x: rect.x - rect.width / 2, y: rect.y - rect.height / 2 },
51
- topRight: { x: rect.x + rect.width / 2, y: rect.y - rect.height / 2 },
52
- bottomRight: { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 },
53
- bottomLeft: { x: rect.x - rect.width / 2, y: rect.y + rect.height / 2 }
54
- };
55
- return [
56
- { start: r.bottomLeft, end: r.topLeft },
57
- { start: r.topLeft, end: r.topRight },
58
- { start: r.topRight, end: r.bottomRight },
59
- { start: r.bottomRight, end: r.bottomLeft },
60
- ];
61
- }
62
-
63
- export function rectangleSegment(rect: Rectangle, line: Segment): Pos | undefined {
64
- for (const edge of rectEdges(rect)) {
65
- const intersectionPoint = segmentSegment(edge, line);
66
- if (intersectionPoint) {
67
- return intersectionPoint;
68
- }
69
- }
70
- return undefined;
71
- }
72
-
73
- function sortSegment(pos: Pos, line: Segment): Segment {
74
- const distStart = Math.hypot(line.start.x - pos.x, line.start.y - pos.y);
75
- const distEnd = Math.hypot(line.end.x - pos.x, line.end.y - pos.y);
76
-
77
- if (distStart <= distEnd) {
78
- return line;
79
- } else {
80
- return { start: line.end, end: line.start };
81
- }
82
- }
83
-
84
- export function circleSegment(pos: Pos, r: number, line: Segment): Pos | undefined {
85
- line = sortSegment(pos, line);
86
- const { x: x1, y: y1 } = line.start;
87
- const { x: x2, y: y2 } = line.end;
88
-
89
- const dx = x2 - x1;
90
- const dy = y2 - y1;
91
-
92
- const a = dx * dx + dy * dy;
93
- const b = 2 * (dx * (x1 - pos.x) + dy * (y1 - pos.y));
94
- const c = (x1 - pos.x) * (x1 - pos.x) + (y1 - pos.y) * (y1 - pos.y) - r * r;
95
-
96
- const discriminant = b * b - 4 * a * c;
97
-
98
- if (discriminant < 0) {
99
- return undefined;
100
- }
101
-
102
- const t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
103
-
104
- if (t1 >= 0 && t1 <= 1) {
105
- return {
106
- x: x1 + t1 * dx,
107
- y: y1 + t1 * dy
108
- };
109
- }
110
- }
1
+ export interface Pos {
2
+ x: number;
3
+ y: number;
4
+ }
5
+
6
+ export interface Extent {
7
+ width: number;
8
+ height: number;
9
+ }
10
+
11
+ export interface Segment {
12
+ start: Pos;
13
+ end: Pos;
14
+ }
15
+
16
+ export interface Rectangle {
17
+ x: number;
18
+ y: number;
19
+ width: number;
20
+ height: number;
21
+ }
22
+
23
+ function segmentSegment(s1: Segment, s2: Segment): Pos | undefined {
24
+ const { x: x1, y: y1 } = s1.start;
25
+ const { x: x2, y: y2 } = s1.end;
26
+ const { x: x3, y: y3 } = s2.start;
27
+ const { x: x4, y: y4 } = s2.end;
28
+
29
+ const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
30
+ if (denom === 0) {
31
+ // Parallel lines ---
32
+ return undefined;
33
+ }
34
+
35
+ const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
36
+ const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom;
37
+
38
+ if (t > 0 && t < 1 && u > 0 && u < 1) {
39
+ return {
40
+ x: x1 + t * (x2 - x1),
41
+ y: y1 + t * (y2 - y1)
42
+ };
43
+ }
44
+
45
+ return undefined;
46
+ }
47
+
48
+ function rectEdges(rect: Rectangle): Segment[] {
49
+ const r = {
50
+ topLeft: { x: rect.x - rect.width / 2, y: rect.y - rect.height / 2 },
51
+ topRight: { x: rect.x + rect.width / 2, y: rect.y - rect.height / 2 },
52
+ bottomRight: { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 },
53
+ bottomLeft: { x: rect.x - rect.width / 2, y: rect.y + rect.height / 2 }
54
+ };
55
+ return [
56
+ { start: r.bottomLeft, end: r.topLeft },
57
+ { start: r.topLeft, end: r.topRight },
58
+ { start: r.topRight, end: r.bottomRight },
59
+ { start: r.bottomRight, end: r.bottomLeft },
60
+ ];
61
+ }
62
+
63
+ export function rectangleSegment(rect: Rectangle, line: Segment): Pos | undefined {
64
+ for (const edge of rectEdges(rect)) {
65
+ const intersectionPoint = segmentSegment(edge, line);
66
+ if (intersectionPoint) {
67
+ return intersectionPoint;
68
+ }
69
+ }
70
+ return undefined;
71
+ }
72
+
73
+ function sortSegment(pos: Pos, line: Segment): Segment {
74
+ const distStart = Math.hypot(line.start.x - pos.x, line.start.y - pos.y);
75
+ const distEnd = Math.hypot(line.end.x - pos.x, line.end.y - pos.y);
76
+
77
+ if (distStart <= distEnd) {
78
+ return line;
79
+ } else {
80
+ return { start: line.end, end: line.start };
81
+ }
82
+ }
83
+
84
+ export function circleSegment(pos: Pos, r: number, line: Segment): Pos | undefined {
85
+ line = sortSegment(pos, line);
86
+ const { x: x1, y: y1 } = line.start;
87
+ const { x: x2, y: y2 } = line.end;
88
+
89
+ const dx = x2 - x1;
90
+ const dy = y2 - y1;
91
+
92
+ const a = dx * dx + dy * dy;
93
+ const b = 2 * (dx * (x1 - pos.x) + dy * (y1 - pos.y));
94
+ const c = (x1 - pos.x) * (x1 - pos.x) + (y1 - pos.y) * (y1 - pos.y) - r * r;
95
+
96
+ const discriminant = b * b - 4 * a * c;
97
+
98
+ if (discriminant < 0) {
99
+ return undefined;
100
+ }
101
+
102
+ const t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
103
+
104
+ if (t1 >= 0 && t1 <= 1) {
105
+ return {
106
+ x: x1 + t1 * dx,
107
+ y: y1 + t1 * dy
108
+ };
109
+ }
110
+ }
package/src/html/shape.ts CHANGED
@@ -1,141 +1,141 @@
1
- import { svg } from "lit-html";
2
- import { extend } from "./component.ts";
3
- import { circleSegment, rectangleSegment } from "./intersection.ts";
4
-
5
- export const DEFAULT_SHAPE_SIZE = 32;
6
-
7
- interface BaseProps {
8
- fill?: string;
9
- stroke?: string;
10
- strokeWidth?: number;
11
- shapeRendering?: "auto" | "optimizeSpeed" | "crispEdges" | "geometricPrecision";
12
- }
13
-
14
- export interface CircleProps extends BaseProps {
15
- diameter?: number;
16
- }
17
- export const circle = ({
18
- diameter = DEFAULT_SHAPE_SIZE,
19
- fill = "whiteSmoke",
20
- stroke = fill,
21
- strokeWidth = 1,
22
- shapeRendering = "auto"
23
- }: CircleProps) => {
24
- return extend(svg`\
25
- <circle
26
- r=${diameter / 2}
27
- fill=${fill}
28
- stroke=${stroke}
29
- stroke-width=${strokeWidth}
30
- shape-rendering=${shapeRendering}
31
- />`, diameter, diameter, (pos, line) => {
32
- return circleSegment(pos, diameter / 2, line);
33
- });
34
- };
35
-
36
- export interface RectangleProps extends BaseProps {
37
- width: number;
38
- height: number;
39
- cornerRadius?: number;
40
- }
41
-
42
- export const rectangle = ({
43
- width = DEFAULT_SHAPE_SIZE,
44
- height = DEFAULT_SHAPE_SIZE,
45
- cornerRadius = 4,
46
- fill = "whiteSmoke",
47
- stroke = fill,
48
- strokeWidth = 1,
49
- shapeRendering = "crispEdges"
50
- }: RectangleProps) => {
51
- return extend(svg`\
52
- <rect
53
- x=${-width / 2}
54
- y=${-height / 2}
55
- rx=${cornerRadius}
56
- ry=${cornerRadius}
57
- width=${width}
58
- height=${height}
59
- fill=${fill}
60
- stroke=${stroke}
61
- stroke-width=${strokeWidth}
62
- shape-rendering=${shapeRendering}
63
- />`, width, height, (pos, line) => {
64
- return rectangleSegment({ x: pos.x, y: pos.y, width, height }, line);
65
- });
66
- };
67
-
68
- export interface SquareProps extends BaseProps {
69
- width?: number;
70
- cornerRadius?: number;
71
- }
72
-
73
- export const square = ({
74
- width = DEFAULT_SHAPE_SIZE,
75
- cornerRadius,
76
- fill,
77
- stroke,
78
- strokeWidth,
79
- shapeRendering
80
- }: SquareProps) => {
81
- return rectangle({
82
- width,
83
- height: width,
84
- cornerRadius,
85
- fill,
86
- stroke,
87
- strokeWidth,
88
- shapeRendering
89
- });
90
- };
91
-
92
- export interface ShapeProps extends BaseProps {
93
- shape?: "circle" | "square" | "rectangle";
94
- diameter?: number;
95
- width?: number;
96
- height?: number;
97
- cornerRadius?: number;
98
- }
99
-
100
- export const shape = ({
101
- shape = "circle",
102
- diameter,
103
- width,
104
- height,
105
- fill,
106
- stroke,
107
- strokeWidth = 1,
108
- shapeRendering = "auto",
109
- cornerRadius
110
- }: ShapeProps) => {
111
- switch (shape) {
112
- case "square":
113
- return square({
114
- width: width ?? height ?? diameter ?? DEFAULT_SHAPE_SIZE,
115
- fill,
116
- stroke,
117
- strokeWidth,
118
- shapeRendering,
119
- cornerRadius
120
- });
121
- case "rectangle":
122
- return rectangle({
123
- width: width ?? height ?? diameter ?? DEFAULT_SHAPE_SIZE,
124
- height: height ?? width ?? diameter ?? DEFAULT_SHAPE_SIZE,
125
- fill,
126
- stroke,
127
- strokeWidth,
128
- shapeRendering,
129
- cornerRadius
130
- });
131
- case "circle":
132
- default:
133
- return circle({
134
- diameter: diameter ?? width ?? height ?? DEFAULT_SHAPE_SIZE,
135
- fill,
136
- stroke,
137
- strokeWidth,
138
- shapeRendering
139
- });
140
- }
141
- };
1
+ import { svg } from "lit-html";
2
+ import { extend } from "./component.ts";
3
+ import { circleSegment, rectangleSegment } from "./intersection.ts";
4
+
5
+ export const DEFAULT_SHAPE_SIZE = 32;
6
+
7
+ interface BaseProps {
8
+ fill?: string;
9
+ stroke?: string;
10
+ strokeWidth?: number;
11
+ shapeRendering?: "auto" | "optimizeSpeed" | "crispEdges" | "geometricPrecision";
12
+ }
13
+
14
+ export interface CircleProps extends BaseProps {
15
+ diameter?: number;
16
+ }
17
+ export const circle = ({
18
+ diameter = DEFAULT_SHAPE_SIZE,
19
+ fill = "whiteSmoke",
20
+ stroke = fill,
21
+ strokeWidth = 1,
22
+ shapeRendering = "auto"
23
+ }: CircleProps) => {
24
+ return extend(svg`\
25
+ <circle
26
+ r=${diameter / 2}
27
+ fill=${fill}
28
+ stroke=${stroke}
29
+ stroke-width=${strokeWidth}
30
+ shape-rendering=${shapeRendering}
31
+ />`, diameter, diameter, (pos, line) => {
32
+ return circleSegment(pos, diameter / 2, line);
33
+ });
34
+ };
35
+
36
+ export interface RectangleProps extends BaseProps {
37
+ width: number;
38
+ height: number;
39
+ cornerRadius?: number;
40
+ }
41
+
42
+ export const rectangle = ({
43
+ width = DEFAULT_SHAPE_SIZE,
44
+ height = DEFAULT_SHAPE_SIZE,
45
+ cornerRadius = 4,
46
+ fill = "whiteSmoke",
47
+ stroke = fill,
48
+ strokeWidth = 1,
49
+ shapeRendering = "crispEdges"
50
+ }: RectangleProps) => {
51
+ return extend(svg`\
52
+ <rect
53
+ x=${-width / 2}
54
+ y=${-height / 2}
55
+ rx=${cornerRadius}
56
+ ry=${cornerRadius}
57
+ width=${width}
58
+ height=${height}
59
+ fill=${fill}
60
+ stroke=${stroke}
61
+ stroke-width=${strokeWidth}
62
+ shape-rendering=${shapeRendering}
63
+ />`, width, height, (pos, line) => {
64
+ return rectangleSegment({ x: pos.x, y: pos.y, width, height }, line);
65
+ });
66
+ };
67
+
68
+ export interface SquareProps extends BaseProps {
69
+ width?: number;
70
+ cornerRadius?: number;
71
+ }
72
+
73
+ export const square = ({
74
+ width = DEFAULT_SHAPE_SIZE,
75
+ cornerRadius,
76
+ fill,
77
+ stroke,
78
+ strokeWidth,
79
+ shapeRendering
80
+ }: SquareProps) => {
81
+ return rectangle({
82
+ width,
83
+ height: width,
84
+ cornerRadius,
85
+ fill,
86
+ stroke,
87
+ strokeWidth,
88
+ shapeRendering
89
+ });
90
+ };
91
+
92
+ export interface ShapeProps extends BaseProps {
93
+ shape?: "circle" | "square" | "rectangle";
94
+ diameter?: number;
95
+ width?: number;
96
+ height?: number;
97
+ cornerRadius?: number;
98
+ }
99
+
100
+ export const shape = ({
101
+ shape = "circle",
102
+ diameter,
103
+ width,
104
+ height,
105
+ fill,
106
+ stroke,
107
+ strokeWidth = 1,
108
+ shapeRendering = "auto",
109
+ cornerRadius
110
+ }: ShapeProps) => {
111
+ switch (shape) {
112
+ case "square":
113
+ return square({
114
+ width: width ?? height ?? diameter ?? DEFAULT_SHAPE_SIZE,
115
+ fill,
116
+ stroke,
117
+ strokeWidth,
118
+ shapeRendering,
119
+ cornerRadius
120
+ });
121
+ case "rectangle":
122
+ return rectangle({
123
+ width: width ?? height ?? diameter ?? DEFAULT_SHAPE_SIZE,
124
+ height: height ?? width ?? diameter ?? DEFAULT_SHAPE_SIZE,
125
+ fill,
126
+ stroke,
127
+ strokeWidth,
128
+ shapeRendering,
129
+ cornerRadius
130
+ });
131
+ case "circle":
132
+ default:
133
+ return circle({
134
+ diameter: diameter ?? width ?? height ?? DEFAULT_SHAPE_SIZE,
135
+ fill,
136
+ stroke,
137
+ strokeWidth,
138
+ shapeRendering
139
+ });
140
+ }
141
+ };
package/src/html/text.ts CHANGED
@@ -1,59 +1,59 @@
1
- import { svg } from "lit-html";
2
- import { Utility } from "@hpcc-js/common";
3
- import { extend } from "./component.ts";
4
-
5
- export interface TextProps {
6
- text: string;
7
- anchor?: "left" | "middle" | "end";
8
- fill?: string;
9
- fontFamily?: string;
10
- fontSize?: number;
11
- dominantBaseline?: string;
12
- }
13
-
14
- export const TextLine = ({
15
- text,
16
- anchor = "middle",
17
- fill = "black",
18
- fontFamily = "Verdana",
19
- fontSize = 12,
20
- dominantBaseline = "middle",
21
- }: TextProps) => {
22
- const { width, height } = Utility.textSize(text, fontFamily, fontSize);
23
- return extend(svg`\
24
- <text y=${height / 2} font-family=${fontFamily} font-size=${`${fontSize}px`} text-anchor=${anchor} fill=${fill} dominant-baseline=${dominantBaseline}>
25
- ${text}
26
- </text>`, width, height);
27
- };
28
-
29
- export const Text = ({
30
- text,
31
- anchor = "middle",
32
- fill = "black",
33
- fontFamily = "Verdana",
34
- fontSize = 12,
35
- }: TextProps) => {
36
- const parts = text.split("\n").map(line => TextLine({ text: line, anchor, fill, fontFamily, fontSize }));
37
- const { width, height } = parts.reduce((acc, part) => {
38
- return {
39
- width: Math.max(acc.width, part.extent.width),
40
- height: acc.height + part.extent.height
41
- };
42
- }, { width: 0, height: 0 });
43
-
44
- let xOffset = 0;
45
- if (anchor === "left") {
46
- xOffset = -width / 2;
47
- } else if (anchor === "end") {
48
- xOffset = width / 2;
49
- }
50
- const lineHeight = height / parts.length;
51
- const TextLines = parts.map((p, i) => {
52
- return svg`\
53
- <g key=${`key-${i}`} transform="translate(${xOffset} ${-height / 2 + i * lineHeight})">
54
- ${p}
55
- </g>`;
56
- });
57
-
58
- return extend(svg`${TextLines}`, width, height);
59
- };
1
+ import { svg } from "lit-html";
2
+ import { Utility } from "@hpcc-js/common";
3
+ import { extend } from "./component.ts";
4
+
5
+ export interface TextProps {
6
+ text: string;
7
+ anchor?: "left" | "middle" | "end";
8
+ fill?: string;
9
+ fontFamily?: string;
10
+ fontSize?: number;
11
+ dominantBaseline?: string;
12
+ }
13
+
14
+ export const TextLine = ({
15
+ text,
16
+ anchor = "middle",
17
+ fill = "black",
18
+ fontFamily = "Verdana",
19
+ fontSize = 12,
20
+ dominantBaseline = "middle",
21
+ }: TextProps) => {
22
+ const { width, height } = Utility.textSize(text, fontFamily, fontSize);
23
+ return extend(svg`\
24
+ <text y=${height / 2} font-family=${fontFamily} font-size=${`${fontSize}px`} text-anchor=${anchor} fill=${fill} dominant-baseline=${dominantBaseline}>
25
+ ${text}
26
+ </text>`, width, height);
27
+ };
28
+
29
+ export const Text = ({
30
+ text,
31
+ anchor = "middle",
32
+ fill = "black",
33
+ fontFamily = "Verdana",
34
+ fontSize = 12,
35
+ }: TextProps) => {
36
+ const parts = text.split("\n").map(line => TextLine({ text: line, anchor, fill, fontFamily, fontSize }));
37
+ const { width, height } = parts.reduce((acc, part) => {
38
+ return {
39
+ width: Math.max(acc.width, part.extent.width),
40
+ height: acc.height + part.extent.height
41
+ };
42
+ }, { width: 0, height: 0 });
43
+
44
+ let xOffset = 0;
45
+ if (anchor === "left") {
46
+ xOffset = -width / 2;
47
+ } else if (anchor === "end") {
48
+ xOffset = width / 2;
49
+ }
50
+ const lineHeight = height / parts.length;
51
+ const TextLines = parts.map((p, i) => {
52
+ return svg`\
53
+ <g key=${`key-${i}`} transform="translate(${xOffset} ${-height / 2 + i * lineHeight})">
54
+ ${p}
55
+ </g>`;
56
+ });
57
+
58
+ return extend(svg`${TextLines}`, width, height);
59
+ };