@retikz/react 0.1.0-alpha.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.
- package/LICENSE +21 -0
- package/dist/es/index.d.ts +15 -0
- package/dist/es/index.d.ts.map +1 -0
- package/dist/es/index.js +10 -0
- package/dist/es/kernel/Node.d.ts +34 -0
- package/dist/es/kernel/Node.d.ts.map +1 -0
- package/dist/es/kernel/Node.js +11 -0
- package/dist/es/kernel/Path.d.ts +18 -0
- package/dist/es/kernel/Path.d.ts.map +1 -0
- package/dist/es/kernel/Path.js +9 -0
- package/dist/es/kernel/Step.d.ts +23 -0
- package/dist/es/kernel/Step.d.ts.map +1 -0
- package/dist/es/kernel/Step.js +10 -0
- package/dist/es/kernel/Tikz.d.ts +25 -0
- package/dist/es/kernel/Tikz.d.ts.map +1 -0
- package/dist/es/kernel/Tikz.js +28 -0
- package/dist/es/kernel/_builder.d.ts +8 -0
- package/dist/es/kernel/_builder.d.ts.map +1 -0
- package/dist/es/kernel/_builder.js +97 -0
- package/dist/es/kernel/_displayNames.d.ts +7 -0
- package/dist/es/kernel/_displayNames.d.ts.map +1 -0
- package/dist/es/kernel/_displayNames.js +9 -0
- package/dist/es/kernel/_unbuilder.d.ts +11 -0
- package/dist/es/kernel/_unbuilder.d.ts.map +1 -0
- package/dist/es/kernel/_unbuilder.js +56 -0
- package/dist/es/kernel/index.d.ts +5 -0
- package/dist/es/kernel/index.d.ts.map +1 -0
- package/dist/es/kernel/index.js +4 -0
- package/dist/es/render/browser-measurer.d.ts +7 -0
- package/dist/es/render/browser-measurer.d.ts.map +1 -0
- package/dist/es/render/browser-measurer.js +35 -0
- package/dist/es/render/renderPrim.d.ts +8 -0
- package/dist/es/render/renderPrim.d.ts.map +1 -0
- package/dist/es/render/renderPrim.js +64 -0
- package/dist/es/render/viewBox.d.ts +4 -0
- package/dist/es/render/viewBox.d.ts.map +1 -0
- package/dist/es/render/viewBox.js +5 -0
- package/dist/es/sugar/Draw.d.ts +23 -0
- package/dist/es/sugar/Draw.d.ts.map +1 -0
- package/dist/es/sugar/Draw.js +30 -0
- package/dist/es/sugar/index.d.ts +2 -0
- package/dist/es/sugar/index.d.ts.map +1 -0
- package/dist/es/sugar/index.js +1 -0
- package/dist/lib/index.cjs +17 -0
- package/dist/lib/index.d.ts +15 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/kernel/Node.cjs +11 -0
- package/dist/lib/kernel/Node.d.ts +34 -0
- package/dist/lib/kernel/Node.d.ts.map +1 -0
- package/dist/lib/kernel/Path.cjs +9 -0
- package/dist/lib/kernel/Path.d.ts +18 -0
- package/dist/lib/kernel/Path.d.ts.map +1 -0
- package/dist/lib/kernel/Step.cjs +10 -0
- package/dist/lib/kernel/Step.d.ts +23 -0
- package/dist/lib/kernel/Step.d.ts.map +1 -0
- package/dist/lib/kernel/Tikz.cjs +28 -0
- package/dist/lib/kernel/Tikz.d.ts +25 -0
- package/dist/lib/kernel/Tikz.d.ts.map +1 -0
- package/dist/lib/kernel/_builder.cjs +97 -0
- package/dist/lib/kernel/_builder.d.ts +8 -0
- package/dist/lib/kernel/_builder.d.ts.map +1 -0
- package/dist/lib/kernel/_displayNames.cjs +11 -0
- package/dist/lib/kernel/_displayNames.d.ts +7 -0
- package/dist/lib/kernel/_displayNames.d.ts.map +1 -0
- package/dist/lib/kernel/_unbuilder.cjs +56 -0
- package/dist/lib/kernel/_unbuilder.d.ts +11 -0
- package/dist/lib/kernel/_unbuilder.d.ts.map +1 -0
- package/dist/lib/kernel/index.cjs +4 -0
- package/dist/lib/kernel/index.d.ts +5 -0
- package/dist/lib/kernel/index.d.ts.map +1 -0
- package/dist/lib/render/browser-measurer.cjs +35 -0
- package/dist/lib/render/browser-measurer.d.ts +7 -0
- package/dist/lib/render/browser-measurer.d.ts.map +1 -0
- package/dist/lib/render/renderPrim.cjs +64 -0
- package/dist/lib/render/renderPrim.d.ts +8 -0
- package/dist/lib/render/renderPrim.d.ts.map +1 -0
- package/dist/lib/render/viewBox.cjs +5 -0
- package/dist/lib/render/viewBox.d.ts +4 -0
- package/dist/lib/render/viewBox.d.ts.map +1 -0
- package/dist/lib/sugar/Draw.cjs +30 -0
- package/dist/lib/sugar/Draw.d.ts +23 -0
- package/dist/lib/sugar/Draw.d.ts.map +1 -0
- package/dist/lib/sugar/index.cjs +1 -0
- package/dist/lib/sugar/index.d.ts +2 -0
- package/dist/lib/sugar/index.d.ts.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 pionpill
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @retikz/react 公开 API
|
|
3
|
+
*
|
|
4
|
+
* Kernel 组件:<Tikz> <Node> <Path> <Step>
|
|
5
|
+
* Sugar 组件:<Draw>
|
|
6
|
+
*
|
|
7
|
+
* 渲染管道:buildIR → compileToScene → renderPrim → SVG
|
|
8
|
+
*/
|
|
9
|
+
export { Tikz, Node, Path, Step } from './kernel';
|
|
10
|
+
export type { TikzProps, NodeProps, PathProps, StepProps } from './kernel';
|
|
11
|
+
export { Draw } from './sugar';
|
|
12
|
+
export type { DrawProps } from './sugar';
|
|
13
|
+
export { buildIR as convertReactNodeToIR } from './kernel/_builder';
|
|
14
|
+
export { convertIRToReactNode } from './kernel/_unbuilder';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,IAAI,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { buildIR } from "./kernel/_builder.js";
|
|
2
|
+
import { Tikz } from "./kernel/Tikz.js";
|
|
3
|
+
import { Node } from "./kernel/Node.js";
|
|
4
|
+
import { Path } from "./kernel/Path.js";
|
|
5
|
+
import { Step } from "./kernel/Step.js";
|
|
6
|
+
import "./kernel/index.js";
|
|
7
|
+
import { Draw } from "./sugar/Draw.js";
|
|
8
|
+
import "./sugar/index.js";
|
|
9
|
+
import { convertIRToReactNode } from "./kernel/_unbuilder.js";
|
|
10
|
+
export { Draw, Node, Path, Step, Tikz, convertIRToReactNode, buildIR as convertReactNodeToIR };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { IRNode, IRPosition, PolarPosition } from '@retikz/core';
|
|
3
|
+
/** <Node> 组件的 props */
|
|
4
|
+
export type NodeProps = {
|
|
5
|
+
/** 节点 id;其他 Path/Draw 通过这个 id 引用本节点 */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** 节点中心位置;笛卡尔 [x, y] 或极坐标(编译时解析) */
|
|
8
|
+
position: IRPosition | PolarPosition;
|
|
9
|
+
/** 旋转角度(度数,与 TikZ 一致),绕节点中心;正值顺时针 */
|
|
10
|
+
rotate?: number;
|
|
11
|
+
/** 文本内容;也支持 children 形式(仅字符串) */
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/** 显式 text,优先级高于 children */
|
|
14
|
+
text?: string;
|
|
15
|
+
/** 字号;不填用默认值 */
|
|
16
|
+
fontSize?: number;
|
|
17
|
+
/** 内边距:内容到 border 的距离 */
|
|
18
|
+
padding?: number;
|
|
19
|
+
/** 外边距:border 到 path 附着点的距离;不影响 border 位置;必须 ≥ 0 */
|
|
20
|
+
margin?: number;
|
|
21
|
+
/** 背景色 */
|
|
22
|
+
fill?: IRNode['fill'];
|
|
23
|
+
/** 描边色 */
|
|
24
|
+
stroke?: IRNode['stroke'];
|
|
25
|
+
/** 描边宽度 */
|
|
26
|
+
strokeWidth?: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Node 是 DSL 标记组件——本身不渲染任何 React 元素。
|
|
30
|
+
* 由 <Tikz> 在 children 扫描阶段读出 props 构造 IR,
|
|
31
|
+
* 再由 compileToScene + renderPrim 产出最终 SVG。
|
|
32
|
+
*/
|
|
33
|
+
export declare const Node: FC<NodeProps>;
|
|
34
|
+
//# sourceMappingURL=Node.d.ts.map
|
|
@@ -0,0 +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,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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TIKZ_NODE } from "./_displayNames.js";
|
|
2
|
+
//#region src/kernel/Node.tsx
|
|
3
|
+
/**
|
|
4
|
+
* Node 是 DSL 标记组件——本身不渲染任何 React 元素。
|
|
5
|
+
* 由 <Tikz> 在 children 扫描阶段读出 props 构造 IR,
|
|
6
|
+
* 再由 compileToScene + renderPrim 产出最终 SVG。
|
|
7
|
+
*/
|
|
8
|
+
var Node = () => null;
|
|
9
|
+
Node.displayName = TIKZ_NODE;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Node };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { IRPath } from '@retikz/core';
|
|
3
|
+
/** <Path> 组件的 props */
|
|
4
|
+
export type PathProps = {
|
|
5
|
+
/** 描边色,省略时用 currentColor */
|
|
6
|
+
stroke?: IRPath['stroke'];
|
|
7
|
+
/** 描边宽度,省略时为 1 */
|
|
8
|
+
strokeWidth?: IRPath['strokeWidth'];
|
|
9
|
+
/** SVG stroke-dasharray 模式(如 "4 2") */
|
|
10
|
+
strokeDasharray?: IRPath['strokeDasharray'];
|
|
11
|
+
/** 应当全部是 <Step /> */
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Path 容器——本身不渲染。children 扫描阶段读出其中的 <Step /> 构造 IRPath。
|
|
16
|
+
*/
|
|
17
|
+
export declare const Path: FC<PathProps>;
|
|
18
|
+
//# sourceMappingURL=Path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Path.d.ts","sourceRoot":"","sources":["../../../src/kernel/Path.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG3C,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACpC,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC5C,qBAAqB;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { IRTarget } from '@retikz/core';
|
|
3
|
+
/**
|
|
4
|
+
* <Step> 组件的 props。
|
|
5
|
+
* v0.1.0-alpha 仅支持 'move' 与 'line',kind 默认 'line'。
|
|
6
|
+
*/
|
|
7
|
+
export type StepProps = {
|
|
8
|
+
/** 移动游标但不绘制(类似 SVG path "M") */
|
|
9
|
+
kind: 'move';
|
|
10
|
+
/** 移动目标点 */
|
|
11
|
+
to: IRTarget;
|
|
12
|
+
} | {
|
|
13
|
+
/** 直线动作;省略时默认 'line' */
|
|
14
|
+
kind?: 'line';
|
|
15
|
+
/** 直线终点 */
|
|
16
|
+
to: IRTarget;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Step 是 DSL 标记组件——本身不渲染。
|
|
20
|
+
* 必须作为 <Path> 的直接子节点出现,由 <Path> 的 children 扫描读出。
|
|
21
|
+
*/
|
|
22
|
+
export declare const Step: FC<StepProps>;
|
|
23
|
+
//# sourceMappingURL=Step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../../src/kernel/Step.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB;IACE,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY;IACZ,EAAE,EAAE,QAAQ,CAAC;CACd,GACD;IACE,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW;IACX,EAAE,EAAE,QAAQ,CAAC;CACd,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAAc,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TIKZ_STEP } from "./_displayNames.js";
|
|
2
|
+
//#region src/kernel/Step.tsx
|
|
3
|
+
/**
|
|
4
|
+
* Step 是 DSL 标记组件——本身不渲染。
|
|
5
|
+
* 必须作为 <Path> 的直接子节点出现,由 <Path> 的 children 扫描读出。
|
|
6
|
+
*/
|
|
7
|
+
var Step = () => null;
|
|
8
|
+
Step.displayName = TIKZ_STEP;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { Step };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CSSProperties, FC, ReactNode } from 'react';
|
|
2
|
+
import { IR } from '@retikz/core';
|
|
3
|
+
/** <Tikz> 组件的 props */
|
|
4
|
+
export type TikzProps = {
|
|
5
|
+
/** 直接喂 IR JSON(持久化 / AI / 编辑器场景),与 children 二选一 */
|
|
6
|
+
ir?: IR;
|
|
7
|
+
/** Kernel/Sugar JSX children */
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
/** SVG 元素宽度(CSS 长度或数字) */
|
|
10
|
+
width?: number | string;
|
|
11
|
+
/** SVG 元素高度(CSS 长度或数字) */
|
|
12
|
+
height?: number | string;
|
|
13
|
+
/** 透传到 svg 元素的 className */
|
|
14
|
+
className?: string;
|
|
15
|
+
/** 透传到 svg 元素的内联样式 */
|
|
16
|
+
style?: CSSProperties;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* <Tikz> 顶层容器。
|
|
20
|
+
* 1. 从 children 构造 IR(或直接接受外部 IR)
|
|
21
|
+
* 2. 调 compileToScene 得 Scene
|
|
22
|
+
* 3. 把 Scene primitives 渲染为 SVG 元素
|
|
23
|
+
*/
|
|
24
|
+
export declare const Tikz: FC<TikzProps>;
|
|
25
|
+
//# sourceMappingURL=Tikz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tikz.d.ts","sourceRoot":"","sources":["../../../src/kernel/Tikz.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,EAAE,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,KAAK,EAAE,EAAkB,MAAM,cAAc,CAAC;AAMvD,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,mDAAmD;IACnD,EAAE,CAAC,EAAE,EAAE,CAAC;IACR,gCAAgC;IAChC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAS9B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { buildIR } from "./_builder.js";
|
|
2
|
+
import { browserMeasurer } from "../render/browser-measurer.js";
|
|
3
|
+
import { renderPrim } from "../render/renderPrim.js";
|
|
4
|
+
import { formatViewBox } from "../render/viewBox.js";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { compileToScene } from "@retikz/core";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region src/kernel/Tikz.tsx
|
|
9
|
+
/**
|
|
10
|
+
* <Tikz> 顶层容器。
|
|
11
|
+
* 1. 从 children 构造 IR(或直接接受外部 IR)
|
|
12
|
+
* 2. 调 compileToScene 得 Scene
|
|
13
|
+
* 3. 把 Scene primitives 渲染为 SVG 元素
|
|
14
|
+
*/
|
|
15
|
+
var Tikz = ({ ir: irFromProp, children, width, height, className, style }) => {
|
|
16
|
+
const ir = useMemo(() => irFromProp ?? buildIR(children), [irFromProp, children]);
|
|
17
|
+
const scene = useMemo(() => compileToScene(ir, { measureText: browserMeasurer }), [ir]);
|
|
18
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
19
|
+
viewBox: formatViewBox(scene.viewBox),
|
|
20
|
+
width,
|
|
21
|
+
height,
|
|
22
|
+
className,
|
|
23
|
+
style,
|
|
24
|
+
children: scene.primitives.map((p, i) => renderPrim(p, i))
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { Tikz };
|
|
@@ -0,0 +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;AAoGhE;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,SAAS,KAAG,EAI5C,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { TIKZ_NODE, TIKZ_PATH } from "./_displayNames.js";
|
|
2
|
+
import { Children, isValidElement } from "react";
|
|
3
|
+
import { CURRENT_IR_VERSION } from "@retikz/core";
|
|
4
|
+
//#region src/kernel/_builder.ts
|
|
5
|
+
/** 取 React 元素 type 上的 displayName;type 为字符串时直接返回,用于识别 Kernel/Sugar 组件 */
|
|
6
|
+
var getDisplayName = (el) => {
|
|
7
|
+
const t = el.type;
|
|
8
|
+
if (typeof t === "string") return t;
|
|
9
|
+
return t.displayName;
|
|
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;
|
|
14
|
+
return {
|
|
15
|
+
type: "node",
|
|
16
|
+
id: props.id,
|
|
17
|
+
position: props.position,
|
|
18
|
+
rotate: props.rotate,
|
|
19
|
+
text,
|
|
20
|
+
fill: props.fill,
|
|
21
|
+
stroke: props.stroke,
|
|
22
|
+
strokeWidth: props.strokeWidth,
|
|
23
|
+
padding: props.padding,
|
|
24
|
+
margin: props.margin,
|
|
25
|
+
fontSize: props.fontSize
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* 扫描 <Path> children 收集 <Step> 序列。
|
|
30
|
+
* 至少 2 段;首段不是 move 时强制改为 move(与 SVG path 的 "M …" 语义对齐)。
|
|
31
|
+
*/
|
|
32
|
+
var readPathChildren = (children) => {
|
|
33
|
+
const out = [];
|
|
34
|
+
Children.forEach(children, (child) => {
|
|
35
|
+
if (!isValidElement(child)) return;
|
|
36
|
+
if (getDisplayName(child) !== "@retikz/Step") return;
|
|
37
|
+
const props = child.props;
|
|
38
|
+
const kind = props.kind ?? "line";
|
|
39
|
+
out.push({
|
|
40
|
+
type: "step",
|
|
41
|
+
kind,
|
|
42
|
+
to: props.to
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
if (out.length < 2) throw new Error("<Path> requires at least 2 <Step> children");
|
|
46
|
+
if (out[0].kind !== "move") out[0] = {
|
|
47
|
+
type: "step",
|
|
48
|
+
kind: "move",
|
|
49
|
+
to: out[0].to
|
|
50
|
+
};
|
|
51
|
+
return out;
|
|
52
|
+
};
|
|
53
|
+
/** 把 <Path> props 翻成 IRChild;step 序列由 readPathChildren 收集 */
|
|
54
|
+
var buildPath = (props) => ({
|
|
55
|
+
type: "path",
|
|
56
|
+
stroke: props.stroke,
|
|
57
|
+
strokeWidth: props.strokeWidth,
|
|
58
|
+
strokeDasharray: props.strokeDasharray,
|
|
59
|
+
children: readPathChildren(props.children)
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* 扫描 <Tikz> 直接 children:
|
|
63
|
+
* - Kernel marker(Node / Path)走对应 builder 直接产 IRChild
|
|
64
|
+
* - 其余函数式组件视为 Sugar:同步调用拿 Kernel JSX,递归展开
|
|
65
|
+
* (Sugar 组件不能用 hooks——builder 不在 React 调用栈上)
|
|
66
|
+
* - 非函数(fragment / 字符串 / null / 类组件)静默跳过
|
|
67
|
+
*/
|
|
68
|
+
var readSceneChildren = (children) => {
|
|
69
|
+
const out = [];
|
|
70
|
+
Children.forEach(children, (child) => {
|
|
71
|
+
if (!isValidElement(child)) return;
|
|
72
|
+
switch (getDisplayName(child)) {
|
|
73
|
+
case TIKZ_NODE:
|
|
74
|
+
out.push(buildNode(child.props));
|
|
75
|
+
return;
|
|
76
|
+
case TIKZ_PATH:
|
|
77
|
+
out.push(buildPath(child.props));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (typeof child.type === "function") {
|
|
81
|
+
const expanded = child.type(child.props);
|
|
82
|
+
for (const ir of readSceneChildren(expanded)) out.push(ir);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return out;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* 把 <Tikz> 的 children 同步翻译为 IR。
|
|
89
|
+
* 纯函数,不依赖 effect/state;render 阶段即可直接使用。
|
|
90
|
+
*/
|
|
91
|
+
var buildIR = (children) => ({
|
|
92
|
+
version: CURRENT_IR_VERSION,
|
|
93
|
+
type: "scene",
|
|
94
|
+
children: readSceneChildren(children)
|
|
95
|
+
});
|
|
96
|
+
//#endregion
|
|
97
|
+
export { buildIR };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** <Node> 组件的 displayName */
|
|
2
|
+
export declare const TIKZ_NODE = "@retikz/Node";
|
|
3
|
+
/** <Path> 组件的 displayName */
|
|
4
|
+
export declare const TIKZ_PATH = "@retikz/Path";
|
|
5
|
+
/** <Step> 组件的 displayName */
|
|
6
|
+
export declare const TIKZ_STEP = "@retikz/Step";
|
|
7
|
+
//# sourceMappingURL=_displayNames.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/kernel/_displayNames.ts
|
|
2
|
+
/** <Node> 组件的 displayName */
|
|
3
|
+
var TIKZ_NODE = "@retikz/Node";
|
|
4
|
+
/** <Path> 组件的 displayName */
|
|
5
|
+
var TIKZ_PATH = "@retikz/Path";
|
|
6
|
+
/** <Step> 组件的 displayName */
|
|
7
|
+
var TIKZ_STEP = "@retikz/Step";
|
|
8
|
+
//#endregion
|
|
9
|
+
export { TIKZ_NODE, TIKZ_PATH, TIKZ_STEP };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { IR } from '@retikz/core';
|
|
3
|
+
/**
|
|
4
|
+
* 把 IR JSON 反向还原为 Kernel element 数组(带 key、不裹外壳)。
|
|
5
|
+
* 调用方可 `<Tikz>{convertIRToReactNode(ir)}</Tikz>`,或继续用 `<Tikz ir={ir}/>`。
|
|
6
|
+
*
|
|
7
|
+
* **Sugar 不可逆**:buildIR 在收集阶段就把 <Draw/> 求值展开为 Path+Step,IR 里没有
|
|
8
|
+
* "原本是 Draw" 的痕迹;本函数永远只产 Kernel 三件套。
|
|
9
|
+
*/
|
|
10
|
+
export declare const convertIRToReactNode: (ir: IR) => ReactNode;
|
|
11
|
+
//# sourceMappingURL=_unbuilder.d.ts.map
|
|
@@ -0,0 +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;AA+ChE;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,IAAI,EAAE,KAAG,SACW,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Node } from "./Node.js";
|
|
2
|
+
import { Path } from "./Path.js";
|
|
3
|
+
import { Step } from "./Step.js";
|
|
4
|
+
import { createElement } from "react";
|
|
5
|
+
//#region src/kernel/_unbuilder.ts
|
|
6
|
+
/** IR 'node' child → NodeProps;过滤 undefined 字段,不污染 React DevTools 显示 */
|
|
7
|
+
var nodePropsFromIR = (n) => {
|
|
8
|
+
const props = { position: n.position };
|
|
9
|
+
if (n.id !== void 0) props.id = n.id;
|
|
10
|
+
if (n.rotate !== void 0) props.rotate = n.rotate;
|
|
11
|
+
if (n.text !== void 0) props.text = n.text;
|
|
12
|
+
if (n.fontSize !== void 0) props.fontSize = n.fontSize;
|
|
13
|
+
if (n.padding !== void 0) props.padding = n.padding;
|
|
14
|
+
if (n.margin !== void 0) props.margin = n.margin;
|
|
15
|
+
if (n.fill !== void 0) props.fill = n.fill;
|
|
16
|
+
if (n.stroke !== void 0) props.stroke = n.stroke;
|
|
17
|
+
if (n.strokeWidth !== void 0) props.strokeWidth = n.strokeWidth;
|
|
18
|
+
return props;
|
|
19
|
+
};
|
|
20
|
+
/** 单个 IRStep → <Step /> element */
|
|
21
|
+
var stepToElement = (step, key) => createElement(Step, {
|
|
22
|
+
key,
|
|
23
|
+
kind: step.kind,
|
|
24
|
+
to: step.to
|
|
25
|
+
});
|
|
26
|
+
/** discriminated union 兜底:编译期保证不漏 case,运行时给出明确错误 */
|
|
27
|
+
var assertNever = (x) => {
|
|
28
|
+
throw new Error(`convertIRToReactNode: unknown IR child type: ${JSON.stringify(x)}`);
|
|
29
|
+
};
|
|
30
|
+
/** 单个 IR child → 对应 Kernel element;走 discriminated union 穷举 */
|
|
31
|
+
var childToElement = (child, key) => {
|
|
32
|
+
switch (child.type) {
|
|
33
|
+
case "node": return createElement(Node, {
|
|
34
|
+
key,
|
|
35
|
+
...nodePropsFromIR(child)
|
|
36
|
+
});
|
|
37
|
+
case "path": return createElement(Path, {
|
|
38
|
+
key,
|
|
39
|
+
stroke: child.stroke,
|
|
40
|
+
strokeWidth: child.strokeWidth,
|
|
41
|
+
strokeDasharray: child.strokeDasharray,
|
|
42
|
+
children: child.children.map((s, j) => stepToElement(s, j))
|
|
43
|
+
});
|
|
44
|
+
default: return assertNever(child);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* 把 IR JSON 反向还原为 Kernel element 数组(带 key、不裹外壳)。
|
|
49
|
+
* 调用方可 `<Tikz>{convertIRToReactNode(ir)}</Tikz>`,或继续用 `<Tikz ir={ir}/>`。
|
|
50
|
+
*
|
|
51
|
+
* **Sugar 不可逆**:buildIR 在收集阶段就把 <Draw/> 求值展开为 Path+Step,IR 里没有
|
|
52
|
+
* "原本是 Draw" 的痕迹;本函数永远只产 Kernel 三件套。
|
|
53
|
+
*/
|
|
54
|
+
var convertIRToReactNode = (ir) => ir.children.map((child, i) => childToElement(child, i));
|
|
55
|
+
//#endregion
|
|
56
|
+
export { convertIRToReactNode };
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-measurer.d.ts","sourceRoot":"","sources":["../../../src/render/browser-measurer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAgBjD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,YAoB7B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { fallbackMeasurer } from "@retikz/core";
|
|
2
|
+
//#region src/render/browser-measurer.ts
|
|
3
|
+
var canvas = null;
|
|
4
|
+
var ctx = null;
|
|
5
|
+
/** 懒加载模块级 canvas 2d context;SSR 环境(无 document)下返回 null,由 measurer 走 fallback */
|
|
6
|
+
var getCtx = () => {
|
|
7
|
+
if (typeof document === "undefined") return null;
|
|
8
|
+
if (!canvas) {
|
|
9
|
+
canvas = document.createElement("canvas");
|
|
10
|
+
ctx = canvas.getContext("2d");
|
|
11
|
+
}
|
|
12
|
+
return ctx;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 浏览器端 text measurer:基于 canvas measureText。
|
|
16
|
+
* 在 SSR 路径下走不到这里,会自动降级 fallback。
|
|
17
|
+
*/
|
|
18
|
+
var browserMeasurer = (text, font) => {
|
|
19
|
+
const c = getCtx();
|
|
20
|
+
if (!c) return fallbackMeasurer(text, font);
|
|
21
|
+
const family = font.family ?? "sans-serif";
|
|
22
|
+
const weight = font.weight ?? "normal";
|
|
23
|
+
c.font = `${font.style ?? "normal"} ${weight} ${font.size}px ${family}`;
|
|
24
|
+
const m = c.measureText(text);
|
|
25
|
+
const ascent = m.actualBoundingBoxAscent ?? font.size * .8;
|
|
26
|
+
const descent = m.actualBoundingBoxDescent ?? font.size * .2;
|
|
27
|
+
return {
|
|
28
|
+
width: m.width,
|
|
29
|
+
height: ascent + descent || font.size * 1.2,
|
|
30
|
+
ascent,
|
|
31
|
+
descent
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { browserMeasurer };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Key, ReactElement } from 'react';
|
|
2
|
+
import { ScenePrimitive } from '@retikz/core';
|
|
3
|
+
/**
|
|
4
|
+
* Scene primitive → SVG React 元素。
|
|
5
|
+
* 不读 IR,只读 Scene;约束在 100 行以内(超过说明 Scene 抽象不够下沉,回 core 补)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const renderPrim: (p: ScenePrimitive, key: Key) => ReactElement;
|
|
8
|
+
//# sourceMappingURL=renderPrim.d.ts.map
|
|
@@ -0,0 +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,cAAc,EAAE,MAAM,cAAc,CAAC;AA6BnD;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,GAAG,cAAc,EAAE,KAAK,GAAG,KAAG,YA2DxD,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
//#region src/render/renderPrim.tsx
|
|
3
|
+
/** Scene 的 align 与 SVG textAnchor 同名同义,仅在此做类型收窄 */
|
|
4
|
+
var alignToAnchor = (align) => align;
|
|
5
|
+
/** Scene baseline 名映射到 SVG dominantBaseline 枚举(top/middle/bottom 对应三种边界基线) */
|
|
6
|
+
var baselineToDominant = (b) => {
|
|
7
|
+
switch (b) {
|
|
8
|
+
case "top": return "text-before-edge";
|
|
9
|
+
case "middle": return "central";
|
|
10
|
+
case "bottom": return "text-after-edge";
|
|
11
|
+
case "alphabetic": return "alphabetic";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Scene primitive → SVG React 元素。
|
|
16
|
+
* 不读 IR,只读 Scene;约束在 100 行以内(超过说明 Scene 抽象不够下沉,回 core 补)。
|
|
17
|
+
*/
|
|
18
|
+
var renderPrim = (p, key) => {
|
|
19
|
+
switch (p.type) {
|
|
20
|
+
case "rect": return /* @__PURE__ */ jsx("rect", {
|
|
21
|
+
x: p.x,
|
|
22
|
+
y: p.y,
|
|
23
|
+
width: p.width,
|
|
24
|
+
height: p.height,
|
|
25
|
+
fill: p.fill,
|
|
26
|
+
fillOpacity: p.fillOpacity,
|
|
27
|
+
stroke: p.stroke,
|
|
28
|
+
strokeWidth: p.strokeWidth,
|
|
29
|
+
strokeDasharray: p.strokeDasharray,
|
|
30
|
+
rx: p.cornerRadius,
|
|
31
|
+
ry: p.cornerRadius,
|
|
32
|
+
opacity: p.opacity
|
|
33
|
+
}, key);
|
|
34
|
+
case "text": return /* @__PURE__ */ jsx("text", {
|
|
35
|
+
x: p.x,
|
|
36
|
+
y: p.y,
|
|
37
|
+
fontSize: p.fontSize,
|
|
38
|
+
fontFamily: p.fontFamily,
|
|
39
|
+
fontWeight: p.fontWeight,
|
|
40
|
+
fontStyle: p.fontStyle,
|
|
41
|
+
textAnchor: alignToAnchor(p.align),
|
|
42
|
+
dominantBaseline: baselineToDominant(p.baseline),
|
|
43
|
+
fill: p.fill,
|
|
44
|
+
opacity: p.opacity,
|
|
45
|
+
children: p.content
|
|
46
|
+
}, key);
|
|
47
|
+
case "path": return /* @__PURE__ */ jsx("path", {
|
|
48
|
+
d: p.d,
|
|
49
|
+
fill: p.fill,
|
|
50
|
+
stroke: p.stroke,
|
|
51
|
+
strokeWidth: p.strokeWidth,
|
|
52
|
+
strokeDasharray: p.strokeDasharray,
|
|
53
|
+
strokeLinecap: p.strokeLinecap,
|
|
54
|
+
strokeLinejoin: p.strokeLinejoin,
|
|
55
|
+
opacity: p.opacity
|
|
56
|
+
}, key);
|
|
57
|
+
case "group": return /* @__PURE__ */ jsx("g", {
|
|
58
|
+
transform: p.transform,
|
|
59
|
+
children: p.children.map((c, i) => renderPrim(c, i))
|
|
60
|
+
}, key);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { renderPrim };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewBox.d.ts","sourceRoot":"","sources":["../../../src/render/viewBox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,2CAA2C;AAC3C,eAAO,MAAM,aAAa,GAAI,IAAI,OAAO,KAAG,MACA,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { IRPath, WayDSL } from '@retikz/core';
|
|
3
|
+
/** <Draw> 组件的 props */
|
|
4
|
+
export type DrawProps = {
|
|
5
|
+
/** way 数组 DSL:节点 id 字符串、坐标 [x, y]、极坐标对象 */
|
|
6
|
+
way: WayDSL;
|
|
7
|
+
/** 描边色,省略时用 currentColor */
|
|
8
|
+
stroke?: IRPath['stroke'];
|
|
9
|
+
/** 描边宽度,省略时为 1 */
|
|
10
|
+
strokeWidth?: IRPath['strokeWidth'];
|
|
11
|
+
/** SVG stroke-dasharray 模式(如 "4 2") */
|
|
12
|
+
strokeDasharray?: IRPath['strokeDasharray'];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Sugar 组件——展开为等价的 <Path><Step.../></Path> Kernel 子树。
|
|
16
|
+
* way 数组的解析委托给 core 的 parseWay,保证"Sugar 不引入新能力"。
|
|
17
|
+
*
|
|
18
|
+
* 注意:本组件由 <Tikz> 的 builder 在 IR 构造阶段同步调用以获取 Kernel JSX,
|
|
19
|
+
* 不在 React render 调用栈上,因此实现里不能使用 React hooks
|
|
20
|
+
* (useState / useMemo / useEffect 等会抛 "Invalid hook call")。
|
|
21
|
+
*/
|
|
22
|
+
export declare const Draw: FC<DrawProps>;
|
|
23
|
+
//# sourceMappingURL=Draw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Draw.d.ts","sourceRoot":"","sources":["../../../src/sugar/Draw.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAKnD,uBAAuB;AACvB,MAAM,MAAM,SAAS,GAAG;IACtB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACpC,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;CAC7C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,SAAS,CAW9B,CAAC"}
|