@retikz/react 0.1.0-alpha.1 → 0.1.0-alpha.2

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 (41) hide show
  1. package/dist/es/index.d.ts +2 -2
  2. package/dist/es/index.d.ts.map +1 -1
  3. package/dist/es/index.js +2 -1
  4. package/dist/es/kernel/Node.d.ts +59 -8
  5. package/dist/es/kernel/Node.d.ts.map +1 -1
  6. package/dist/es/kernel/Text.d.ts +31 -0
  7. package/dist/es/kernel/Text.d.ts.map +1 -0
  8. package/dist/es/kernel/Text.js +22 -0
  9. package/dist/es/kernel/_builder.d.ts.map +1 -1
  10. package/dist/es/kernel/_builder.js +92 -14
  11. package/dist/es/kernel/_displayNames.d.ts +2 -0
  12. package/dist/es/kernel/_displayNames.d.ts.map +1 -1
  13. package/dist/es/kernel/_displayNames.js +3 -1
  14. package/dist/es/kernel/_unbuilder.d.ts.map +1 -1
  15. package/dist/es/kernel/_unbuilder.js +20 -1
  16. package/dist/es/kernel/index.d.ts +1 -0
  17. package/dist/es/kernel/index.d.ts.map +1 -1
  18. package/dist/es/kernel/index.js +1 -0
  19. package/dist/es/render/renderPrim.d.ts.map +1 -1
  20. package/dist/es/render/renderPrim.js +31 -13
  21. package/dist/lib/index.cjs +2 -0
  22. package/dist/lib/index.d.ts +2 -2
  23. package/dist/lib/index.d.ts.map +1 -1
  24. package/dist/lib/kernel/Node.d.ts +59 -8
  25. package/dist/lib/kernel/Node.d.ts.map +1 -1
  26. package/dist/lib/kernel/Text.cjs +22 -0
  27. package/dist/lib/kernel/Text.d.ts +31 -0
  28. package/dist/lib/kernel/Text.d.ts.map +1 -0
  29. package/dist/lib/kernel/_builder.cjs +92 -14
  30. package/dist/lib/kernel/_builder.d.ts.map +1 -1
  31. package/dist/lib/kernel/_displayNames.cjs +3 -0
  32. package/dist/lib/kernel/_displayNames.d.ts +2 -0
  33. package/dist/lib/kernel/_displayNames.d.ts.map +1 -1
  34. package/dist/lib/kernel/_unbuilder.cjs +20 -1
  35. package/dist/lib/kernel/_unbuilder.d.ts.map +1 -1
  36. package/dist/lib/kernel/index.cjs +1 -0
  37. package/dist/lib/kernel/index.d.ts +1 -0
  38. package/dist/lib/kernel/index.d.ts.map +1 -1
  39. package/dist/lib/render/renderPrim.cjs +31 -13
  40. package/dist/lib/render/renderPrim.d.ts.map +1 -1
  41. package/package.json +2 -2
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * 渲染管道:buildIR → compileToScene → renderPrim → SVG
8
8
  */
9
- export { Tikz, Node, Path, Step } from './kernel';
10
- export type { TikzProps, NodeProps, PathProps, StepProps } from './kernel';
9
+ export { Tikz, Node, Path, Step, Text } from './kernel';
10
+ export type { TikzProps, NodeProps, PathProps, StepProps, TextProps } from './kernel';
11
11
  export { Draw } from './sugar';
12
12
  export type { DrawProps } from './sugar';
13
13
  export { DrawWay } from '@retikz/core';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE3E,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEtF,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/es/index.js CHANGED
@@ -3,9 +3,10 @@ import { Tikz } from "./kernel/Tikz.js";
3
3
  import { Node } from "./kernel/Node.js";
4
4
  import { Path } from "./kernel/Path.js";
5
5
  import { Step } from "./kernel/Step.js";
6
+ import { Text } from "./kernel/Text.js";
6
7
  import "./kernel/index.js";
7
8
  import { Draw } from "./sugar/Draw.js";
8
9
  import "./sugar/index.js";
9
10
  import { convertIRToReactNode } from "./kernel/_unbuilder.js";
10
11
  import { DrawWay } from "@retikz/core";
11
- export { Draw, DrawWay, Node, Path, Step, Tikz, convertIRToReactNode, buildIR as convertReactNodeToIR };
12
+ export { Draw, DrawWay, Node, Path, Step, Text, Tikz, convertIRToReactNode, buildIR as convertReactNodeToIR };
@@ -1,5 +1,5 @@
1
1
  import { FC, ReactNode } from 'react';
2
- import { IRNode, IRPosition, PolarPosition } from '@retikz/core';
2
+ import { IRFont, IRLineSpec, IRNode, IRPosition, NodeTextAlign, PolarPosition } from '@retikz/core';
3
3
  /** <Node> 组件的 props */
4
4
  export type NodeProps = {
5
5
  /** 节点 id;其他 Path/Draw 通过这个 id 引用本节点 */
@@ -10,22 +10,73 @@ export type NodeProps = {
10
10
  position: IRPosition | PolarPosition;
11
11
  /** 旋转角度(度数,与 TikZ 一致),绕节点中心;正值顺时针 */
12
12
  rotate?: number;
13
- /** 文本内容;也支持 children 形式(仅字符串) */
13
+ /**
14
+ * 文本内容(也可以用 children 写);与 `text` 二选一,`text` 优先。
15
+ *
16
+ * children 多行写法:
17
+ * - `<Node>{'Line 1\nLine 2'}</Node>`(字符串内嵌 `\n`)
18
+ * - ``<Node>{`Line 1\nLine 2`}</Node>``(模板字面量)
19
+ * - `<Node>{['Line 1', 'Line 2']}</Node>`(数组)
20
+ * - `<Node><Text fill="red">L1</Text>L2</Node>`(混 `<Text>` 带样式行)
21
+ */
14
22
  children?: ReactNode;
15
- /** 显式 text,优先级高于 children */
16
- text?: string;
17
- /** 字号;不填用默认值 */
18
- fontSize?: number;
19
- /** 内边距:内容到 border 的距离 */
23
+ /**
24
+ * 显式 text,优先级高于 children:
25
+ * - `string` — 单行
26
+ * - `Array<string>` — 多行无样式覆盖
27
+ * - `Array<string | LineSpec>` — 多行,可对单行覆盖 fill / opacity / font
28
+ */
29
+ text?: string | Array<IRLineSpec>;
30
+ /** 多行文本对齐:left / center(默认)/ right;只影响多行块内各行的水平对齐 */
31
+ align?: NodeTextAlign;
32
+ /** 行高(user units);不填走 `font.size × 1.2` 默认 */
33
+ lineHeight?: number;
34
+ /** 字体规格:family / size / weight / style 全部可选;不填走渲染端默认值 */
35
+ font?: IRFont;
36
+ /** 横向内边距(text → 左右 border);不填走 `padding` 兜底,再走默认 */
37
+ innerXSep?: number;
38
+ /** 纵向内边距(text → 上下 border);不填走 `padding` 兜底,再走默认 */
39
+ innerYSep?: number;
40
+ /** 外边距(border → path 附着点);不影响 border 位置;不填走 `margin` 兜底 */
41
+ outerSep?: number;
42
+ /** 内边距对称别名——等价于同时设 `innerXSep` 和 `innerYSep`;轴特化字段优先 */
20
43
  padding?: number;
21
- /** 外边距:border path 附着点的距离;不影响 border 位置;必须 ≥ 0 */
44
+ /** 外边距对称别名——等价于 `outerSep`;轴特化字段优先 */
22
45
  margin?: number;
23
46
  /** 背景色 */
24
47
  fill?: IRNode['fill'];
48
+ /** 填充透明度 0~1 */
49
+ fillOpacity?: number;
25
50
  /** 描边色 */
26
51
  stroke?: IRNode['stroke'];
52
+ /** 描边透明度 0~1(TikZ `draw opacity`) */
53
+ drawOpacity?: number;
27
54
  /** 描边宽度 */
28
55
  strokeWidth?: number;
56
+ /** 描边虚线预设:等价于 dashArray="4 2";与 `dotted` / `dashArray` 优先级:dashArray > dashed > dotted */
57
+ dashed?: boolean;
58
+ /** 描边点线预设:等价于 dashArray="1 2" */
59
+ dotted?: boolean;
60
+ /** 显式 SVG stroke-dasharray 值(如 "4 2");优先级最高 */
61
+ dashArray?: string;
62
+ /** 圆角半径(user units);只对 `rectangle` shape 生效 */
63
+ roundedCorners?: number;
64
+ /** 最小 border 宽度(user units);不足时撑开 bbox */
65
+ minimumWidth?: number;
66
+ /** 最小 border 高度(user units) */
67
+ minimumHeight?: number;
68
+ /** 对称最小尺寸别名——等价于同时设 `minimumWidth` 与 `minimumHeight`;轴特化字段优先 */
69
+ minimumSize?: number;
70
+ /** 均匀缩放因子;同时影响 bbox / 字号 / padding / margin / 路径附着点(与 TikZ scale 一致) */
71
+ scale?: number;
72
+ /** 横向缩放,优先于 `scale` */
73
+ xScale?: number;
74
+ /** 纵向缩放,优先于 `scale` */
75
+ yScale?: number;
76
+ /** 文字颜色(块级默认;行级 LineSpec.fill 可覆盖);不填走 `currentColor` */
77
+ textColor?: string;
78
+ /** 整节点透明度 0~1(同时作用于 shape 与 text) */
79
+ opacity?: number;
29
80
  };
30
81
  /**
31
82
  * Node 是 DSL 标记组件——本身不渲染任何 React 元素。
@@ -1 +1 @@
1
- {"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../../src/kernel/Node.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGtE,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACxB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,GAAG,aAAa,CAAC;IACrC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
1
+ {"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../../src/kernel/Node.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,MAAM,EACN,UAAU,EACV,aAAa,EACb,aAAa,EACd,MAAM,cAAc,CAAC;AAGtB,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACxB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,GAAG,aAAa,CAAC;IACrC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC,qDAAqD;IACrD,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { FC } from 'react';
2
+ import { IRFont } from '@retikz/core';
3
+ /** <Text> 组件的 props——Node 多行文本里给某一行带覆盖样式 */
4
+ export type TextProps = {
5
+ /** 行内容(必须是字符串) */
6
+ children: string;
7
+ /** 行级覆盖颜色;不填走 Node 块级默认 */
8
+ fill?: string;
9
+ /** 行级透明度 0~1;不填走 Node 块级默认 */
10
+ opacity?: number;
11
+ /** 行级字体覆盖;missing 字段继承 Node 的 `font` 块级值 */
12
+ font?: IRFont;
13
+ };
14
+ /**
15
+ * Text 是 Node 内的"行级"标记组件——本身不渲染,
16
+ * 由 buildIR 在扫描 Node children 时识别为 LineSpec。
17
+ *
18
+ * 和字符串 children 平等参与——String 按 `'\n'` 拆纯样式行;
19
+ * `<Text>` 一次贡献一行带样式行;保持 JSX 顺序。
20
+ *
21
+ * 用法:
22
+ * ```tsx
23
+ * <Node>
24
+ * <Text fill="red" font={{ weight: 'bold' }}>Heading</Text>
25
+ * body line 1
26
+ * body line 2
27
+ * </Node>
28
+ * ```
29
+ */
30
+ export declare const Text: FC<TextProps>;
31
+ //# sourceMappingURL=Text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/kernel/Text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG;IACtB,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { TIKZ_TEXT } from "./_displayNames.js";
2
+ //#region src/kernel/Text.tsx
3
+ /**
4
+ * Text 是 Node 内的"行级"标记组件——本身不渲染,
5
+ * 由 buildIR 在扫描 Node children 时识别为 LineSpec。
6
+ *
7
+ * 和字符串 children 平等参与——String 按 `'\n'` 拆纯样式行;
8
+ * `<Text>` 一次贡献一行带样式行;保持 JSX 顺序。
9
+ *
10
+ * 用法:
11
+ * ```tsx
12
+ * <Node>
13
+ * <Text fill="red" font={{ weight: 'bold' }}>Heading</Text>
14
+ * body line 1
15
+ * body line 2
16
+ * </Node>
17
+ * ```
18
+ */
19
+ var Text = () => null;
20
+ Text.displayName = TIKZ_TEXT;
21
+ //#endregion
22
+ export { Text };
@@ -1 +1 @@
1
- {"version":3,"file":"_builder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AAoIhE;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,SAAS,KAAG,EAI5C,CAAC"}
1
+ {"version":3,"file":"_builder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,EAAE,EAA+C,MAAM,cAAc,CAAC;AA6NpF;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,SAAS,KAAG,EAI5C,CAAC"}
@@ -8,24 +8,102 @@ var getDisplayName = (el) => {
8
8
  if (typeof t === "string") return t;
9
9
  return t.displayName;
10
10
  };
11
- /** 把 <Node> props 翻成 IRChild;text 优先取 props.text,其次取字符串 children */
12
- var buildNode = (props) => {
13
- const text = typeof props.text === "string" ? props.text : typeof props.children === "string" ? props.children : void 0;
11
+ /**
12
+ * <Text> 元素的 props + children 串解析为 IRLineSpec 对象形式。
13
+ * children 必须是 string;非字符串 children 静默跳过此 <Text> 元素。
14
+ */
15
+ var textElementToLineSpec = (el) => {
16
+ const props = el.props;
17
+ if (typeof props.children !== "string") return void 0;
18
+ if (props.fill === void 0 && props.opacity === void 0 && props.font === void 0) return props.children;
14
19
  return {
15
- type: "node",
16
- id: props.id,
17
- shape: props.shape,
18
- position: props.position,
19
- rotate: props.rotate,
20
- text,
20
+ text: props.children,
21
21
  fill: props.fill,
22
- stroke: props.stroke,
23
- strokeWidth: props.strokeWidth,
24
- padding: props.padding,
25
- margin: props.margin,
26
- fontSize: props.fontSize
22
+ opacity: props.opacity,
23
+ font: props.font
24
+ };
25
+ };
26
+ /**
27
+ * 递归收集 Node children 中的行:
28
+ * - 字符串按 `'\n'` 拆行(每段 → 字符串 LineSpec)
29
+ * - 数组(JSX 多 child 自动展平)逐项递归
30
+ * - <Text> 元素 → 对象 LineSpec(带覆盖样式)
31
+ * - 其它类型(其它 React 元素 / null / 数字等)忽略——附带让 `<br/>` 当软分段
32
+ *
33
+ * 顺序保留——按 JSX 写的顺序行就是 IR 行顺序。
34
+ */
35
+ var collectChildLines = (children) => {
36
+ const out = [];
37
+ const visit = (node) => {
38
+ if (typeof node === "string") {
39
+ for (const part of node.split("\n")) out.push(part);
40
+ return;
41
+ }
42
+ if (Array.isArray(node)) {
43
+ for (const c of node) visit(c);
44
+ return;
45
+ }
46
+ if (isValidElement(node) && getDisplayName(node) === "@retikz/Text") {
47
+ const spec = textElementToLineSpec(node);
48
+ if (spec !== void 0) out.push(spec);
49
+ }
27
50
  };
51
+ visit(children);
52
+ return out;
53
+ };
54
+ /**
55
+ * Node 文本读取顺序:
56
+ * 1. `props.text`(string / string[] / LineSpec[])— 显式优先,直接透传到 IR
57
+ * 2. `props.children` — 字符串按 `'\n'` 拆行;`<Text>` 元素带样式贡献一行;保持 JSX 顺序
58
+ *
59
+ * 用 children 写多行的几种姿势:
60
+ * - 字符串带换行:`<Node>{'Line 1\nLine 2'}</Node>`
61
+ * - 模板字面量:``<Node>{`Line 1\nLine 2`}</Node>``
62
+ * - 数组:`<Node>{['Line 1', 'Line 2']}</Node>`
63
+ * - <Text>(带样式):`<Node><Text fill="red">Heading</Text>body</Node>`
64
+ */
65
+ var readNodeText = (props) => {
66
+ if (typeof props.text === "string") return props.text;
67
+ if (Array.isArray(props.text)) return props.text;
68
+ const lines = collectChildLines(props.children);
69
+ if (lines.length === 0) return void 0;
70
+ if (lines.length === 1 && typeof lines[0] === "string") return lines[0];
71
+ return lines;
28
72
  };
73
+ /** 把 <Node> props 翻成 IRChild;text 优先取 props.text,其次取字符串 children */
74
+ var buildNode = (props) => ({
75
+ type: "node",
76
+ id: props.id,
77
+ shape: props.shape,
78
+ position: props.position,
79
+ rotate: props.rotate,
80
+ text: readNodeText(props),
81
+ align: props.align,
82
+ lineHeight: props.lineHeight,
83
+ fill: props.fill,
84
+ fillOpacity: props.fillOpacity,
85
+ stroke: props.stroke,
86
+ drawOpacity: props.drawOpacity,
87
+ strokeWidth: props.strokeWidth,
88
+ dashed: props.dashed,
89
+ dotted: props.dotted,
90
+ dashArray: props.dashArray,
91
+ roundedCorners: props.roundedCorners,
92
+ minimumWidth: props.minimumWidth,
93
+ minimumHeight: props.minimumHeight,
94
+ minimumSize: props.minimumSize,
95
+ scale: props.scale,
96
+ xScale: props.xScale,
97
+ yScale: props.yScale,
98
+ textColor: props.textColor,
99
+ opacity: props.opacity,
100
+ innerXSep: props.innerXSep,
101
+ innerYSep: props.innerYSep,
102
+ outerSep: props.outerSep,
103
+ padding: props.padding,
104
+ margin: props.margin,
105
+ font: props.font
106
+ });
29
107
  /**
30
108
  * 扫描 <Path> children 收集 <Step> 序列。
31
109
  * 至少 2 段;首段不是 move 时强制改为 move(与 SVG path 的 "M …" 语义对齐);
@@ -4,4 +4,6 @@ export declare const TIKZ_NODE = "@retikz/Node";
4
4
  export declare const TIKZ_PATH = "@retikz/Path";
5
5
  /** <Step> 组件的 displayName */
6
6
  export declare const TIKZ_STEP = "@retikz/Step";
7
+ /** <Text> 组件的 displayName(Node 内多行文本带样式) */
8
+ export declare const TIKZ_TEXT = "@retikz/Text";
7
9
  //# sourceMappingURL=_displayNames.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_displayNames.d.ts","sourceRoot":"","sources":["../../../src/kernel/_displayNames.ts"],"names":[],"mappings":"AAKA,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC"}
1
+ {"version":3,"file":"_displayNames.d.ts","sourceRoot":"","sources":["../../../src/kernel/_displayNames.ts"],"names":[],"mappings":"AAKA,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,4CAA4C;AAC5C,eAAO,MAAM,SAAS,iBAAiB,CAAC"}
@@ -5,5 +5,7 @@ var TIKZ_NODE = "@retikz/Node";
5
5
  var TIKZ_PATH = "@retikz/Path";
6
6
  /** <Step> 组件的 displayName */
7
7
  var TIKZ_STEP = "@retikz/Step";
8
+ /** <Text> 组件的 displayName(Node 内多行文本带样式) */
9
+ var TIKZ_TEXT = "@retikz/Text";
8
10
  //#endregion
9
- export { TIKZ_NODE, TIKZ_PATH, TIKZ_STEP };
11
+ export { TIKZ_NODE, TIKZ_PATH, TIKZ_STEP, TIKZ_TEXT };
@@ -1 +1 @@
1
- {"version":3,"file":"_unbuilder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_unbuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AA2DhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,KAAG,SACW,CAAC"}
1
+ {"version":3,"file":"_unbuilder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_unbuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AA8EhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,KAAG,SACW,CAAC"}
@@ -10,12 +10,31 @@ var nodePropsFromIR = (n) => {
10
10
  if (n.shape !== void 0) props.shape = n.shape;
11
11
  if (n.rotate !== void 0) props.rotate = n.rotate;
12
12
  if (n.text !== void 0) props.text = n.text;
13
- if (n.fontSize !== void 0) props.fontSize = n.fontSize;
13
+ if (n.align !== void 0) props.align = n.align;
14
+ if (n.lineHeight !== void 0) props.lineHeight = n.lineHeight;
15
+ if (n.font !== void 0) props.font = n.font;
16
+ if (n.innerXSep !== void 0) props.innerXSep = n.innerXSep;
17
+ if (n.innerYSep !== void 0) props.innerYSep = n.innerYSep;
18
+ if (n.outerSep !== void 0) props.outerSep = n.outerSep;
14
19
  if (n.padding !== void 0) props.padding = n.padding;
15
20
  if (n.margin !== void 0) props.margin = n.margin;
16
21
  if (n.fill !== void 0) props.fill = n.fill;
22
+ if (n.fillOpacity !== void 0) props.fillOpacity = n.fillOpacity;
17
23
  if (n.stroke !== void 0) props.stroke = n.stroke;
24
+ if (n.drawOpacity !== void 0) props.drawOpacity = n.drawOpacity;
18
25
  if (n.strokeWidth !== void 0) props.strokeWidth = n.strokeWidth;
26
+ if (n.dashed !== void 0) props.dashed = n.dashed;
27
+ if (n.dotted !== void 0) props.dotted = n.dotted;
28
+ if (n.dashArray !== void 0) props.dashArray = n.dashArray;
29
+ if (n.roundedCorners !== void 0) props.roundedCorners = n.roundedCorners;
30
+ if (n.minimumWidth !== void 0) props.minimumWidth = n.minimumWidth;
31
+ if (n.minimumHeight !== void 0) props.minimumHeight = n.minimumHeight;
32
+ if (n.minimumSize !== void 0) props.minimumSize = n.minimumSize;
33
+ if (n.scale !== void 0) props.scale = n.scale;
34
+ if (n.xScale !== void 0) props.xScale = n.xScale;
35
+ if (n.yScale !== void 0) props.yScale = n.yScale;
36
+ if (n.textColor !== void 0) props.textColor = n.textColor;
37
+ if (n.opacity !== void 0) props.opacity = n.opacity;
19
38
  return props;
20
39
  };
21
40
  /** 单个 IRStep → <Step /> element */
@@ -2,4 +2,5 @@ export * from './Tikz';
2
2
  export * from './Node';
3
3
  export * from './Path';
4
4
  export * from './Step';
5
+ export * from './Text';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/kernel/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/kernel/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
@@ -2,3 +2,4 @@ import "./Tikz.js";
2
2
  import "./Node.js";
3
3
  import "./Path.js";
4
4
  import "./Step.js";
5
+ import "./Text.js";
@@ -1 +1 @@
1
- {"version":3,"file":"renderPrim.d.ts","sourceRoot":"","sources":["../../../src/render/renderPrim.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6B/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAClD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,cAAc,EACjB,KAAK,GAAG,EACR,MAAK,aAAkB,KACtB,YAsFF,CAAC"}
1
+ {"version":3,"file":"renderPrim.d.ts","sourceRoot":"","sources":["../../../src/render/renderPrim.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6B/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAClD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,cAAc,EACjB,KAAK,GAAG,EACR,MAAK,aAAkB,KACtB,YAqHF,CAAC"}
@@ -25,6 +25,7 @@ var renderPrim = (p, key, ctx = {}) => {
25
25
  fill: p.fill,
26
26
  fillOpacity: p.fillOpacity,
27
27
  stroke: p.stroke,
28
+ strokeOpacity: p.strokeOpacity,
28
29
  strokeWidth: p.strokeWidth,
29
30
  strokeDasharray: p.strokeDasharray,
30
31
  rx: p.cornerRadius,
@@ -42,32 +43,49 @@ var renderPrim = (p, key, ctx = {}) => {
42
43
  fill: p.fill,
43
44
  fillOpacity: p.fillOpacity,
44
45
  stroke: p.stroke,
46
+ strokeOpacity: p.strokeOpacity,
45
47
  strokeWidth: p.strokeWidth,
46
48
  strokeDasharray: p.strokeDasharray,
47
49
  opacity: p.opacity
48
50
  }, key);
49
51
  }
50
- case "text": return /* @__PURE__ */ jsx("text", {
51
- x: p.x,
52
- y: p.y,
53
- fontSize: p.fontSize,
54
- fontFamily: p.fontFamily,
55
- fontWeight: p.fontWeight,
56
- fontStyle: p.fontStyle,
57
- textAnchor: alignToAnchor(p.align),
58
- dominantBaseline: baselineToDominant(p.baseline),
59
- fill: p.fill,
60
- opacity: p.opacity,
61
- children: p.content
62
- }, key);
52
+ case "text": {
53
+ const n = p.lines.length;
54
+ const firstDy = p.baseline === "middle" ? -(n - 1) / 2 * p.lineHeight : p.baseline === "bottom" ? -(n - 1) * p.lineHeight : 0;
55
+ return /* @__PURE__ */ jsx("text", {
56
+ x: p.x,
57
+ y: p.y,
58
+ fontSize: p.fontSize,
59
+ fontFamily: p.fontFamily,
60
+ fontWeight: p.fontWeight,
61
+ fontStyle: p.fontStyle,
62
+ textAnchor: alignToAnchor(p.align),
63
+ dominantBaseline: baselineToDominant(p.baseline),
64
+ fill: p.fill,
65
+ opacity: p.opacity,
66
+ children: p.lines.map((line, i) => /* @__PURE__ */ jsx("tspan", {
67
+ x: p.x,
68
+ dy: i === 0 ? firstDy : p.lineHeight,
69
+ fill: line.fill,
70
+ opacity: line.opacity,
71
+ fontSize: line.fontSize,
72
+ fontFamily: line.fontFamily,
73
+ fontWeight: line.fontWeight,
74
+ fontStyle: line.fontStyle,
75
+ children: line.text
76
+ }, i))
77
+ }, key);
78
+ }
63
79
  case "path": {
64
80
  const startId = p.arrowStart && ctx.arrowMarkerIdFor ? ctx.arrowMarkerIdFor(p.arrowStart) : void 0;
65
81
  const endId = p.arrowEnd && ctx.arrowMarkerIdFor ? ctx.arrowMarkerIdFor(p.arrowEnd) : void 0;
66
82
  return /* @__PURE__ */ jsx("path", {
67
83
  d: p.d,
68
84
  fill: p.fill,
85
+ fillOpacity: p.fillOpacity,
69
86
  fillRule: p.fillRule,
70
87
  stroke: p.stroke,
88
+ strokeOpacity: p.strokeOpacity,
71
89
  strokeWidth: p.strokeWidth,
72
90
  strokeDasharray: p.strokeDasharray,
73
91
  strokeLinecap: p.strokeLinecap,
@@ -4,6 +4,7 @@ const require_Tikz = require("./kernel/Tikz.cjs");
4
4
  const require_Node = require("./kernel/Node.cjs");
5
5
  const require_Path = require("./kernel/Path.cjs");
6
6
  const require_Step = require("./kernel/Step.cjs");
7
+ const require_Text = require("./kernel/Text.cjs");
7
8
  require("./kernel/index.cjs");
8
9
  const require_Draw = require("./sugar/Draw.cjs");
9
10
  require("./sugar/index.cjs");
@@ -19,6 +20,7 @@ Object.defineProperty(exports, "DrawWay", {
19
20
  exports.Node = require_Node.Node;
20
21
  exports.Path = require_Path.Path;
21
22
  exports.Step = require_Step.Step;
23
+ exports.Text = require_Text.Text;
22
24
  exports.Tikz = require_Tikz.Tikz;
23
25
  exports.convertIRToReactNode = require__unbuilder.convertIRToReactNode;
24
26
  exports.convertReactNodeToIR = require__builder.buildIR;
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * 渲染管道:buildIR → compileToScene → renderPrim → SVG
8
8
  */
9
- export { Tikz, Node, Path, Step } from './kernel';
10
- export type { TikzProps, NodeProps, PathProps, StepProps } from './kernel';
9
+ export { Tikz, Node, Path, Step, Text } from './kernel';
10
+ export type { TikzProps, NodeProps, PathProps, StepProps, TextProps } from './kernel';
11
11
  export { Draw } from './sugar';
12
12
  export type { DrawProps } from './sugar';
13
13
  export { DrawWay } from '@retikz/core';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE3E,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEtF,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtE,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { FC, ReactNode } from 'react';
2
- import { IRNode, IRPosition, PolarPosition } from '@retikz/core';
2
+ import { IRFont, IRLineSpec, IRNode, IRPosition, NodeTextAlign, PolarPosition } from '@retikz/core';
3
3
  /** <Node> 组件的 props */
4
4
  export type NodeProps = {
5
5
  /** 节点 id;其他 Path/Draw 通过这个 id 引用本节点 */
@@ -10,22 +10,73 @@ export type NodeProps = {
10
10
  position: IRPosition | PolarPosition;
11
11
  /** 旋转角度(度数,与 TikZ 一致),绕节点中心;正值顺时针 */
12
12
  rotate?: number;
13
- /** 文本内容;也支持 children 形式(仅字符串) */
13
+ /**
14
+ * 文本内容(也可以用 children 写);与 `text` 二选一,`text` 优先。
15
+ *
16
+ * children 多行写法:
17
+ * - `<Node>{'Line 1\nLine 2'}</Node>`(字符串内嵌 `\n`)
18
+ * - ``<Node>{`Line 1\nLine 2`}</Node>``(模板字面量)
19
+ * - `<Node>{['Line 1', 'Line 2']}</Node>`(数组)
20
+ * - `<Node><Text fill="red">L1</Text>L2</Node>`(混 `<Text>` 带样式行)
21
+ */
14
22
  children?: ReactNode;
15
- /** 显式 text,优先级高于 children */
16
- text?: string;
17
- /** 字号;不填用默认值 */
18
- fontSize?: number;
19
- /** 内边距:内容到 border 的距离 */
23
+ /**
24
+ * 显式 text,优先级高于 children:
25
+ * - `string` — 单行
26
+ * - `Array<string>` — 多行无样式覆盖
27
+ * - `Array<string | LineSpec>` — 多行,可对单行覆盖 fill / opacity / font
28
+ */
29
+ text?: string | Array<IRLineSpec>;
30
+ /** 多行文本对齐:left / center(默认)/ right;只影响多行块内各行的水平对齐 */
31
+ align?: NodeTextAlign;
32
+ /** 行高(user units);不填走 `font.size × 1.2` 默认 */
33
+ lineHeight?: number;
34
+ /** 字体规格:family / size / weight / style 全部可选;不填走渲染端默认值 */
35
+ font?: IRFont;
36
+ /** 横向内边距(text → 左右 border);不填走 `padding` 兜底,再走默认 */
37
+ innerXSep?: number;
38
+ /** 纵向内边距(text → 上下 border);不填走 `padding` 兜底,再走默认 */
39
+ innerYSep?: number;
40
+ /** 外边距(border → path 附着点);不影响 border 位置;不填走 `margin` 兜底 */
41
+ outerSep?: number;
42
+ /** 内边距对称别名——等价于同时设 `innerXSep` 和 `innerYSep`;轴特化字段优先 */
20
43
  padding?: number;
21
- /** 外边距:border path 附着点的距离;不影响 border 位置;必须 ≥ 0 */
44
+ /** 外边距对称别名——等价于 `outerSep`;轴特化字段优先 */
22
45
  margin?: number;
23
46
  /** 背景色 */
24
47
  fill?: IRNode['fill'];
48
+ /** 填充透明度 0~1 */
49
+ fillOpacity?: number;
25
50
  /** 描边色 */
26
51
  stroke?: IRNode['stroke'];
52
+ /** 描边透明度 0~1(TikZ `draw opacity`) */
53
+ drawOpacity?: number;
27
54
  /** 描边宽度 */
28
55
  strokeWidth?: number;
56
+ /** 描边虚线预设:等价于 dashArray="4 2";与 `dotted` / `dashArray` 优先级:dashArray > dashed > dotted */
57
+ dashed?: boolean;
58
+ /** 描边点线预设:等价于 dashArray="1 2" */
59
+ dotted?: boolean;
60
+ /** 显式 SVG stroke-dasharray 值(如 "4 2");优先级最高 */
61
+ dashArray?: string;
62
+ /** 圆角半径(user units);只对 `rectangle` shape 生效 */
63
+ roundedCorners?: number;
64
+ /** 最小 border 宽度(user units);不足时撑开 bbox */
65
+ minimumWidth?: number;
66
+ /** 最小 border 高度(user units) */
67
+ minimumHeight?: number;
68
+ /** 对称最小尺寸别名——等价于同时设 `minimumWidth` 与 `minimumHeight`;轴特化字段优先 */
69
+ minimumSize?: number;
70
+ /** 均匀缩放因子;同时影响 bbox / 字号 / padding / margin / 路径附着点(与 TikZ scale 一致) */
71
+ scale?: number;
72
+ /** 横向缩放,优先于 `scale` */
73
+ xScale?: number;
74
+ /** 纵向缩放,优先于 `scale` */
75
+ yScale?: number;
76
+ /** 文字颜色(块级默认;行级 LineSpec.fill 可覆盖);不填走 `currentColor` */
77
+ textColor?: string;
78
+ /** 整节点透明度 0~1(同时作用于 shape 与 text) */
79
+ opacity?: number;
29
80
  };
30
81
  /**
31
82
  * Node 是 DSL 标记组件——本身不渲染任何 React 元素。
@@ -1 +1 @@
1
- {"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../../src/kernel/Node.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGtE,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACxB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,GAAG,aAAa,CAAC;IACrC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
1
+ {"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../../src/kernel/Node.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,MAAM,EACN,UAAU,EACV,aAAa,EACb,aAAa,EACd,MAAM,cAAc,CAAC;AAGtB,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,uCAAuC;IACvC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACxB,oCAAoC;IACpC,QAAQ,EAAE,UAAU,GAAG,aAAa,CAAC;IACrC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC,qDAAqD;IACrD,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
@@ -0,0 +1,22 @@
1
+ const require__displayNames = require("./_displayNames.cjs");
2
+ //#region src/kernel/Text.tsx
3
+ /**
4
+ * Text 是 Node 内的"行级"标记组件——本身不渲染,
5
+ * 由 buildIR 在扫描 Node children 时识别为 LineSpec。
6
+ *
7
+ * 和字符串 children 平等参与——String 按 `'\n'` 拆纯样式行;
8
+ * `<Text>` 一次贡献一行带样式行;保持 JSX 顺序。
9
+ *
10
+ * 用法:
11
+ * ```tsx
12
+ * <Node>
13
+ * <Text fill="red" font={{ weight: 'bold' }}>Heading</Text>
14
+ * body line 1
15
+ * body line 2
16
+ * </Node>
17
+ * ```
18
+ */
19
+ var Text = () => null;
20
+ Text.displayName = require__displayNames.TIKZ_TEXT;
21
+ //#endregion
22
+ exports.Text = Text;
@@ -0,0 +1,31 @@
1
+ import { FC } from 'react';
2
+ import { IRFont } from '@retikz/core';
3
+ /** <Text> 组件的 props——Node 多行文本里给某一行带覆盖样式 */
4
+ export type TextProps = {
5
+ /** 行内容(必须是字符串) */
6
+ children: string;
7
+ /** 行级覆盖颜色;不填走 Node 块级默认 */
8
+ fill?: string;
9
+ /** 行级透明度 0~1;不填走 Node 块级默认 */
10
+ opacity?: number;
11
+ /** 行级字体覆盖;missing 字段继承 Node 的 `font` 块级值 */
12
+ font?: IRFont;
13
+ };
14
+ /**
15
+ * Text 是 Node 内的"行级"标记组件——本身不渲染,
16
+ * 由 buildIR 在扫描 Node children 时识别为 LineSpec。
17
+ *
18
+ * 和字符串 children 平等参与——String 按 `'\n'` 拆纯样式行;
19
+ * `<Text>` 一次贡献一行带样式行;保持 JSX 顺序。
20
+ *
21
+ * 用法:
22
+ * ```tsx
23
+ * <Node>
24
+ * <Text fill="red" font={{ weight: 'bold' }}>Heading</Text>
25
+ * body line 1
26
+ * body line 2
27
+ * </Node>
28
+ * ```
29
+ */
30
+ export declare const Text: FC<TextProps>;
31
+ //# sourceMappingURL=Text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../src/kernel/Text.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GAAG;IACtB,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
@@ -8,24 +8,102 @@ var getDisplayName = (el) => {
8
8
  if (typeof t === "string") return t;
9
9
  return t.displayName;
10
10
  };
11
- /** 把 <Node> props 翻成 IRChild;text 优先取 props.text,其次取字符串 children */
12
- var buildNode = (props) => {
13
- const text = typeof props.text === "string" ? props.text : typeof props.children === "string" ? props.children : void 0;
11
+ /**
12
+ * <Text> 元素的 props + children 串解析为 IRLineSpec 对象形式。
13
+ * children 必须是 string;非字符串 children 静默跳过此 <Text> 元素。
14
+ */
15
+ var textElementToLineSpec = (el) => {
16
+ const props = el.props;
17
+ if (typeof props.children !== "string") return void 0;
18
+ if (props.fill === void 0 && props.opacity === void 0 && props.font === void 0) return props.children;
14
19
  return {
15
- type: "node",
16
- id: props.id,
17
- shape: props.shape,
18
- position: props.position,
19
- rotate: props.rotate,
20
- text,
20
+ text: props.children,
21
21
  fill: props.fill,
22
- stroke: props.stroke,
23
- strokeWidth: props.strokeWidth,
24
- padding: props.padding,
25
- margin: props.margin,
26
- fontSize: props.fontSize
22
+ opacity: props.opacity,
23
+ font: props.font
24
+ };
25
+ };
26
+ /**
27
+ * 递归收集 Node children 中的行:
28
+ * - 字符串按 `'\n'` 拆行(每段 → 字符串 LineSpec)
29
+ * - 数组(JSX 多 child 自动展平)逐项递归
30
+ * - <Text> 元素 → 对象 LineSpec(带覆盖样式)
31
+ * - 其它类型(其它 React 元素 / null / 数字等)忽略——附带让 `<br/>` 当软分段
32
+ *
33
+ * 顺序保留——按 JSX 写的顺序行就是 IR 行顺序。
34
+ */
35
+ var collectChildLines = (children) => {
36
+ const out = [];
37
+ const visit = (node) => {
38
+ if (typeof node === "string") {
39
+ for (const part of node.split("\n")) out.push(part);
40
+ return;
41
+ }
42
+ if (Array.isArray(node)) {
43
+ for (const c of node) visit(c);
44
+ return;
45
+ }
46
+ if ((0, react.isValidElement)(node) && getDisplayName(node) === "@retikz/Text") {
47
+ const spec = textElementToLineSpec(node);
48
+ if (spec !== void 0) out.push(spec);
49
+ }
27
50
  };
51
+ visit(children);
52
+ return out;
53
+ };
54
+ /**
55
+ * Node 文本读取顺序:
56
+ * 1. `props.text`(string / string[] / LineSpec[])— 显式优先,直接透传到 IR
57
+ * 2. `props.children` — 字符串按 `'\n'` 拆行;`<Text>` 元素带样式贡献一行;保持 JSX 顺序
58
+ *
59
+ * 用 children 写多行的几种姿势:
60
+ * - 字符串带换行:`<Node>{'Line 1\nLine 2'}</Node>`
61
+ * - 模板字面量:``<Node>{`Line 1\nLine 2`}</Node>``
62
+ * - 数组:`<Node>{['Line 1', 'Line 2']}</Node>`
63
+ * - <Text>(带样式):`<Node><Text fill="red">Heading</Text>body</Node>`
64
+ */
65
+ var readNodeText = (props) => {
66
+ if (typeof props.text === "string") return props.text;
67
+ if (Array.isArray(props.text)) return props.text;
68
+ const lines = collectChildLines(props.children);
69
+ if (lines.length === 0) return void 0;
70
+ if (lines.length === 1 && typeof lines[0] === "string") return lines[0];
71
+ return lines;
28
72
  };
73
+ /** 把 <Node> props 翻成 IRChild;text 优先取 props.text,其次取字符串 children */
74
+ var buildNode = (props) => ({
75
+ type: "node",
76
+ id: props.id,
77
+ shape: props.shape,
78
+ position: props.position,
79
+ rotate: props.rotate,
80
+ text: readNodeText(props),
81
+ align: props.align,
82
+ lineHeight: props.lineHeight,
83
+ fill: props.fill,
84
+ fillOpacity: props.fillOpacity,
85
+ stroke: props.stroke,
86
+ drawOpacity: props.drawOpacity,
87
+ strokeWidth: props.strokeWidth,
88
+ dashed: props.dashed,
89
+ dotted: props.dotted,
90
+ dashArray: props.dashArray,
91
+ roundedCorners: props.roundedCorners,
92
+ minimumWidth: props.minimumWidth,
93
+ minimumHeight: props.minimumHeight,
94
+ minimumSize: props.minimumSize,
95
+ scale: props.scale,
96
+ xScale: props.xScale,
97
+ yScale: props.yScale,
98
+ textColor: props.textColor,
99
+ opacity: props.opacity,
100
+ innerXSep: props.innerXSep,
101
+ innerYSep: props.innerYSep,
102
+ outerSep: props.outerSep,
103
+ padding: props.padding,
104
+ margin: props.margin,
105
+ font: props.font
106
+ });
29
107
  /**
30
108
  * 扫描 <Path> children 收集 <Step> 序列。
31
109
  * 至少 2 段;首段不是 move 时强制改为 move(与 SVG path 的 "M …" 语义对齐);
@@ -1 +1 @@
1
- {"version":3,"file":"_builder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AAoIhE;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,SAAS,KAAG,EAI5C,CAAC"}
1
+ {"version":3,"file":"_builder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AACpF,OAAO,KAAK,EAAE,EAAE,EAA+C,MAAM,cAAc,CAAC;AA6NpF;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,SAAS,KAAG,EAI5C,CAAC"}
@@ -5,7 +5,10 @@ var TIKZ_NODE = "@retikz/Node";
5
5
  var TIKZ_PATH = "@retikz/Path";
6
6
  /** <Step> 组件的 displayName */
7
7
  var TIKZ_STEP = "@retikz/Step";
8
+ /** <Text> 组件的 displayName(Node 内多行文本带样式) */
9
+ var TIKZ_TEXT = "@retikz/Text";
8
10
  //#endregion
9
11
  exports.TIKZ_NODE = TIKZ_NODE;
10
12
  exports.TIKZ_PATH = TIKZ_PATH;
11
13
  exports.TIKZ_STEP = TIKZ_STEP;
14
+ exports.TIKZ_TEXT = TIKZ_TEXT;
@@ -4,4 +4,6 @@ export declare const TIKZ_NODE = "@retikz/Node";
4
4
  export declare const TIKZ_PATH = "@retikz/Path";
5
5
  /** <Step> 组件的 displayName */
6
6
  export declare const TIKZ_STEP = "@retikz/Step";
7
+ /** <Text> 组件的 displayName(Node 内多行文本带样式) */
8
+ export declare const TIKZ_TEXT = "@retikz/Text";
7
9
  //# sourceMappingURL=_displayNames.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_displayNames.d.ts","sourceRoot":"","sources":["../../../src/kernel/_displayNames.ts"],"names":[],"mappings":"AAKA,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC"}
1
+ {"version":3,"file":"_displayNames.d.ts","sourceRoot":"","sources":["../../../src/kernel/_displayNames.ts"],"names":[],"mappings":"AAKA,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,6BAA6B;AAC7B,eAAO,MAAM,SAAS,iBAAiB,CAAC;AAExC,4CAA4C;AAC5C,eAAO,MAAM,SAAS,iBAAiB,CAAC"}
@@ -10,12 +10,31 @@ var nodePropsFromIR = (n) => {
10
10
  if (n.shape !== void 0) props.shape = n.shape;
11
11
  if (n.rotate !== void 0) props.rotate = n.rotate;
12
12
  if (n.text !== void 0) props.text = n.text;
13
- if (n.fontSize !== void 0) props.fontSize = n.fontSize;
13
+ if (n.align !== void 0) props.align = n.align;
14
+ if (n.lineHeight !== void 0) props.lineHeight = n.lineHeight;
15
+ if (n.font !== void 0) props.font = n.font;
16
+ if (n.innerXSep !== void 0) props.innerXSep = n.innerXSep;
17
+ if (n.innerYSep !== void 0) props.innerYSep = n.innerYSep;
18
+ if (n.outerSep !== void 0) props.outerSep = n.outerSep;
14
19
  if (n.padding !== void 0) props.padding = n.padding;
15
20
  if (n.margin !== void 0) props.margin = n.margin;
16
21
  if (n.fill !== void 0) props.fill = n.fill;
22
+ if (n.fillOpacity !== void 0) props.fillOpacity = n.fillOpacity;
17
23
  if (n.stroke !== void 0) props.stroke = n.stroke;
24
+ if (n.drawOpacity !== void 0) props.drawOpacity = n.drawOpacity;
18
25
  if (n.strokeWidth !== void 0) props.strokeWidth = n.strokeWidth;
26
+ if (n.dashed !== void 0) props.dashed = n.dashed;
27
+ if (n.dotted !== void 0) props.dotted = n.dotted;
28
+ if (n.dashArray !== void 0) props.dashArray = n.dashArray;
29
+ if (n.roundedCorners !== void 0) props.roundedCorners = n.roundedCorners;
30
+ if (n.minimumWidth !== void 0) props.minimumWidth = n.minimumWidth;
31
+ if (n.minimumHeight !== void 0) props.minimumHeight = n.minimumHeight;
32
+ if (n.minimumSize !== void 0) props.minimumSize = n.minimumSize;
33
+ if (n.scale !== void 0) props.scale = n.scale;
34
+ if (n.xScale !== void 0) props.xScale = n.xScale;
35
+ if (n.yScale !== void 0) props.yScale = n.yScale;
36
+ if (n.textColor !== void 0) props.textColor = n.textColor;
37
+ if (n.opacity !== void 0) props.opacity = n.opacity;
19
38
  return props;
20
39
  };
21
40
  /** 单个 IRStep → <Step /> element */
@@ -1 +1 @@
1
- {"version":3,"file":"_unbuilder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_unbuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AA2DhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,KAAG,SACW,CAAC"}
1
+ {"version":3,"file":"_unbuilder.d.ts","sourceRoot":"","sources":["../../../src/kernel/_unbuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,EAAE,EAA2B,MAAM,cAAc,CAAC;AA8EhE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,KAAG,SACW,CAAC"}
@@ -2,3 +2,4 @@ require("./Tikz.cjs");
2
2
  require("./Node.cjs");
3
3
  require("./Path.cjs");
4
4
  require("./Step.cjs");
5
+ require("./Text.cjs");
@@ -2,4 +2,5 @@ export * from './Tikz';
2
2
  export * from './Node';
3
3
  export * from './Path';
4
4
  export * from './Step';
5
+ export * from './Text';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/kernel/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/kernel/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
@@ -25,6 +25,7 @@ var renderPrim = (p, key, ctx = {}) => {
25
25
  fill: p.fill,
26
26
  fillOpacity: p.fillOpacity,
27
27
  stroke: p.stroke,
28
+ strokeOpacity: p.strokeOpacity,
28
29
  strokeWidth: p.strokeWidth,
29
30
  strokeDasharray: p.strokeDasharray,
30
31
  rx: p.cornerRadius,
@@ -42,32 +43,49 @@ var renderPrim = (p, key, ctx = {}) => {
42
43
  fill: p.fill,
43
44
  fillOpacity: p.fillOpacity,
44
45
  stroke: p.stroke,
46
+ strokeOpacity: p.strokeOpacity,
45
47
  strokeWidth: p.strokeWidth,
46
48
  strokeDasharray: p.strokeDasharray,
47
49
  opacity: p.opacity
48
50
  }, key);
49
51
  }
50
- case "text": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
51
- x: p.x,
52
- y: p.y,
53
- fontSize: p.fontSize,
54
- fontFamily: p.fontFamily,
55
- fontWeight: p.fontWeight,
56
- fontStyle: p.fontStyle,
57
- textAnchor: alignToAnchor(p.align),
58
- dominantBaseline: baselineToDominant(p.baseline),
59
- fill: p.fill,
60
- opacity: p.opacity,
61
- children: p.content
62
- }, key);
52
+ case "text": {
53
+ const n = p.lines.length;
54
+ const firstDy = p.baseline === "middle" ? -(n - 1) / 2 * p.lineHeight : p.baseline === "bottom" ? -(n - 1) * p.lineHeight : 0;
55
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
56
+ x: p.x,
57
+ y: p.y,
58
+ fontSize: p.fontSize,
59
+ fontFamily: p.fontFamily,
60
+ fontWeight: p.fontWeight,
61
+ fontStyle: p.fontStyle,
62
+ textAnchor: alignToAnchor(p.align),
63
+ dominantBaseline: baselineToDominant(p.baseline),
64
+ fill: p.fill,
65
+ opacity: p.opacity,
66
+ children: p.lines.map((line, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tspan", {
67
+ x: p.x,
68
+ dy: i === 0 ? firstDy : p.lineHeight,
69
+ fill: line.fill,
70
+ opacity: line.opacity,
71
+ fontSize: line.fontSize,
72
+ fontFamily: line.fontFamily,
73
+ fontWeight: line.fontWeight,
74
+ fontStyle: line.fontStyle,
75
+ children: line.text
76
+ }, i))
77
+ }, key);
78
+ }
63
79
  case "path": {
64
80
  const startId = p.arrowStart && ctx.arrowMarkerIdFor ? ctx.arrowMarkerIdFor(p.arrowStart) : void 0;
65
81
  const endId = p.arrowEnd && ctx.arrowMarkerIdFor ? ctx.arrowMarkerIdFor(p.arrowEnd) : void 0;
66
82
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
67
83
  d: p.d,
68
84
  fill: p.fill,
85
+ fillOpacity: p.fillOpacity,
69
86
  fillRule: p.fillRule,
70
87
  stroke: p.stroke,
88
+ strokeOpacity: p.strokeOpacity,
71
89
  strokeWidth: p.strokeWidth,
72
90
  strokeDasharray: p.strokeDasharray,
73
91
  strokeLinecap: p.strokeLinecap,
@@ -1 +1 @@
1
- {"version":3,"file":"renderPrim.d.ts","sourceRoot":"","sources":["../../../src/render/renderPrim.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6B/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAClD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,cAAc,EACjB,KAAK,GAAG,EACR,MAAK,aAAkB,KACtB,YAsFF,CAAC"}
1
+ {"version":3,"file":"renderPrim.d.ts","sourceRoot":"","sources":["../../../src/render/renderPrim.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6B/D;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAClD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,cAAc,EACjB,KAAK,GAAG,EACR,MAAK,aAAkB,KACtB,YAqHF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retikz/react",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "React adapter for retikz: Kernel/Sugar JSX components and SVG renderer.",
5
5
  "type": "module",
6
6
  "main": "dist/lib/index.cjs",
@@ -24,7 +24,7 @@
24
24
  "react-dom": ">=18"
25
25
  },
26
26
  "dependencies": {
27
- "@retikz/core": "0.1.0-alpha.1"
27
+ "@retikz/core": "0.1.0-alpha.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^25.6.0",