@univerjs-pro/engine-shape 1.0.0-alpha.7 → 1.0.0-beta.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.
@@ -20,7 +20,7 @@ import { FShape } from './f-shape';
20
20
  * const fConnectorShape = fDocument.insertShape({
21
21
  * shapeType: univerAPI.Enum.ShapeTypeEnum.StraightConnector1,
22
22
  * placement: {
23
- * wrappingStyle: univerAPI.Enum.DocsShapeWrappingStyle.WRAP_SQUARE,
23
+ * wrappingStyle: univerAPI.Enum.TextWrappingStyle.WRAP_SQUARE,
24
24
  * anchor: {
25
25
  * paragraphId: paragraph.getId(),
26
26
  * segmentId: paragraph.getSegmentId(),
@@ -20,6 +20,9 @@ export interface IShapeTextImageFillOptions {
20
20
  /**
21
21
  * A live text facade for a Shape in any supported host.
22
22
  *
23
+ * Sheet, Doc, Slide, and Board Shapes share this rich-text effect path. Glow and outer shadow support here does not
24
+ * imply that a host's standalone document text UI exposes the same authoring controls.
25
+ *
23
26
  * @example Sheet
24
27
  * ```ts
25
28
  * const fWorkbook = univerAPI.getActiveWorkbook();
@@ -35,7 +38,7 @@ export interface IShapeTextImageFillOptions {
35
38
  * const fShape = fDocument.insertShape({
36
39
  * shapeType: univerAPI.Enum.ShapeTypeEnum.Rect,
37
40
  * placement: {
38
- * wrappingStyle: univerAPI.Enum.DocsShapeWrappingStyle.INLINE,
41
+ * wrappingStyle: univerAPI.Enum.TextWrappingStyle.INLINE,
39
42
  * anchor: {
40
43
  * paragraphId: paragraph.getId(),
41
44
  * segmentId: paragraph.getSegmentId(),
@@ -123,7 +126,18 @@ export declare class FShapeText {
123
126
  * @returns {FShapeText} This Shape text facade for chaining.
124
127
  * @example
125
128
  * ```ts
126
- * fShapeText.setTextStyle({ ff: 'Inter', fs: 18 });
129
+ * fShapeText.setTextStyle({
130
+ * ff: 'Inter',
131
+ * fs: 18,
132
+ * glow: { color: '#f97316', radius: 6 },
133
+ * outerShadow: {
134
+ * color: '#000000',
135
+ * opacity: 0.35,
136
+ * blurRadius: 4,
137
+ * distance: 3,
138
+ * direction: 45,
139
+ * },
140
+ * });
127
141
  * ```
128
142
  */
129
143
  setTextStyle(style: ITextStyle): this;
@@ -1,6 +1,7 @@
1
- import type { IBasicShapeData, ImageSourceTypeEnum, IPresetShapeConfig, IShapeData, IShapeHostAdapter, IShapeLineStyle, IShapePointWithAdjName, IShapeRef, IShapeRelationItem, IShapeSnapshot, IShapeTransform, IShapeUpdateInput, ShapeGradientTypeEnum, ShapeHostType, ShapeLineCapEnum, ShapeLineDashEnum, ShapeLineJoinEnum, ShapeTypeEnum } from '@univerjs-pro/engine-shape';
1
+ import type { IBasicShapeData, ImageSourceTypeEnum, IPresetShapeConfig, IShapeAdjustItemResolved, IShapeData, IShapeHostAdapter, IShapeLineStyle, IShapePath, IShapeRef, IShapeRelationItem, IShapeSnapshot, IShapeTransform, IShapeUpdateInput, ShapeGradientTypeEnum, ShapeHostType, ShapeLineCapEnum, ShapeLineDashEnum, ShapeLineJoinEnum, ShapeTypeEnum } from '@univerjs-pro/engine-shape';
2
2
  import type { Injector } from '@univerjs/core';
3
- import { ShapeLineTypeEnum } from '@univerjs-pro/engine-shape';
3
+ import { IShapeHostAdapterRegistry, ShapeLineTypeEnum } from '@univerjs-pro/engine-shape';
4
+ import { ICommandService } from '@univerjs/core';
4
5
  import { FBase } from '@univerjs/core/facade';
5
6
  import { FShapeText } from './f-shape-text';
6
7
  type ShapeFill = NonNullable<IBasicShapeData['fill']>;
@@ -23,6 +24,25 @@ export interface IShapeConnectionSite {
23
24
  /** Outward site angle in OOXML angle units (1/60000 degree). */
24
25
  ang: number;
25
26
  }
27
+ /**
28
+ * A single SVG path accepted by `FShape.setCustomGeometryFromSvgPath()`.
29
+ *
30
+ * `pathData` is the value of an SVG `<path d="...">` attribute, not complete SVG markup or a data
31
+ * URL. Fill and stroke colors remain Shape styles; `fill` and `stroke` only control whether this
32
+ * geometry path participates in filling and stroking.
33
+ */
34
+ export interface IShapeSvgPathGeometryOptions {
35
+ /** SVG `<path>` `d` attribute value. */
36
+ pathData: string;
37
+ /** Optional virtual SVG coordinate-space width. The path scales to the Shape width when set. */
38
+ width?: number;
39
+ /** Optional virtual SVG coordinate-space height. The path scales to the Shape height when set. */
40
+ height?: number;
41
+ /** Optional geometry fill mode. Use `'none'` for an open or stroke-only path. */
42
+ fill?: IShapePath['fill'];
43
+ /** Whether the Shape stroke is applied to this geometry path. */
44
+ stroke?: boolean;
45
+ }
26
46
  /** Optional image-fill properties accepted by `FShape.setImageFill()`. */
27
47
  export type IShapeImageFillOptions = Pick<ShapeFill, 'imageFillMode' | 'imageOpacity' | 'imageRotateWithShape' | 'stretchFillRect' | 'srcRect' | 'imageTile'>;
28
48
  /**
@@ -44,7 +64,7 @@ export type IShapeImageFillOptions = Pick<ShapeFill, 'imageFillMode' | 'imageOpa
44
64
  * const fShape = fDocument.insertShape({
45
65
  * shapeType: univerAPI.Enum.ShapeTypeEnum.Rect,
46
66
  * placement: {
47
- * wrappingStyle: univerAPI.Enum.DocsShapeWrappingStyle.INLINE,
67
+ * wrappingStyle: univerAPI.Enum.TextWrappingStyle.INLINE,
48
68
  * anchor: {
49
69
  * paragraphId: paragraph.getId(),
50
70
  * segmentId: paragraph.getSegmentId(),
@@ -94,7 +114,9 @@ export type IShapeImageFillOptions = Pick<ShapeFill, 'imageFillMode' | 'imageOpa
94
114
  export declare class FShape extends FBase {
95
115
  protected readonly _shapeRef: IShapeRef;
96
116
  protected readonly _injector: Injector;
97
- constructor(_shapeRef: IShapeRef, _injector: Injector);
117
+ protected readonly _shapeHostAdapterRegistry: IShapeHostAdapterRegistry;
118
+ protected readonly _commandService: Pick<ICommandService, 'syncExecuteCommand'>;
119
+ constructor(_shapeRef: IShapeRef, _injector: Injector, _shapeHostAdapterRegistry: IShapeHostAdapterRegistry, _commandService: Pick<ICommandService, 'syncExecuteCommand'>);
98
120
  /**
99
121
  * Whether this Shape is a Connector preset type.
100
122
  * @returns {boolean} Whether this Shape is a Connector preset type.
@@ -389,6 +411,59 @@ export declare class FShape extends FBase {
389
411
  * ```
390
412
  */
391
413
  setCustomGeometry(customGeometry: IPresetShapeConfig): this;
414
+ /**
415
+ * Replaces this Shape's geometry with one SVG path.
416
+ *
417
+ * Use this method when the source is an SVG `<path>` `d` attribute. Do not pass complete
418
+ * `<svg>`/`<path>` markup, a data URL, CSS, transforms, fill colors, or stroke colors in
419
+ * `options.pathData`. Configure visual styles with Shape facade methods such as
420
+ * `setSolidFill()`, `setNoneFill()`, and `setStroke()`.
421
+ *
422
+ * All standard SVG path commands are supported: `M/m`, `L/l`, `H/h`, `V/v`, `C/c`, `S/s`,
423
+ * `Q/q`, `T/t`, `A/a`, and `Z/z`. Relative commands and repeated coordinate groups are
424
+ * converted to absolute engine-shape commands. SVG arcs are converted to cubic Bézier segments
425
+ * instead of being misinterpreted as engine-shape's semantically different OOXML `A` command.
426
+ *
427
+ * Parsing finishes before the host Shape is updated. Invalid or unsupported path data throws a
428
+ * `SyntaxError` and leaves the existing Shape geometry unchanged.
429
+ *
430
+ * @param {IShapeSvgPathGeometryOptions} options SVG path geometry and optional virtual bounds.
431
+ * @returns {FShape} This Shape facade for chaining.
432
+ *
433
+ * @example Board — executable with `univer execute`
434
+ * ```ts
435
+ * const board = univerAPI.getActiveBoard();
436
+ * if (!board) throw new Error('No active board');
437
+ *
438
+ * const shape = board.insertShape({
439
+ * shapeType: univerAPI.Enum.ShapeTypeEnum.Rect,
440
+ * transform: { left: 300, top: 100, width: 160, height: 200 },
441
+ * });
442
+ * if (!shape) throw new Error('Cannot insert shape');
443
+ *
444
+ * shape
445
+ * .setCustomGeometryFromSvgPath({
446
+ * // This is only the value of <path d="...">.
447
+ * pathData: 'M 50,10 C 34,20 24,64 22,92 L 78,92 C 76,64 66,20 50,10 Z',
448
+ * width: 100,
449
+ * height: 100,
450
+ * fill: 'none',
451
+ * stroke: true,
452
+ * })
453
+ * .setNoneFill()
454
+ * .setStroke({
455
+ * lineStrokeType: univerAPI.Enum.ShapeLineTypeEnum.SolidLine,
456
+ * color: '#F0509B',
457
+ * width: 3,
458
+ * });
459
+ *
460
+ * return {
461
+ * id: shape.getId(),
462
+ * pathCount: shape.getCustomGeometry()?.pathLst?.length ?? 0,
463
+ * };
464
+ * ```
465
+ */
466
+ setCustomGeometryFromSvgPath(options: IShapeSvgPathGeometryOptions): this;
392
467
  /**
393
468
  * Returns the sites where Connector endpoints can attach to this Shape.
394
469
  * Coordinates are local to the unrotated Shape bounds. Shapes without
@@ -401,17 +476,6 @@ export declare class FShape extends FBase {
401
476
  * ```
402
477
  */
403
478
  getConnectionSites(): IShapeConnectionSite[];
404
- /**
405
- * Returns the geometry adjustment handles exposed by this Shape preset.
406
- * Coordinates are local to the unrotated Shape bounds and `adjName` identifies
407
- * the corresponding entry in `shapeData.adjustValues`.
408
- * @returns {IShapePointWithAdjName[]} The geometry adjustment handles exposed by this Shape preset.
409
- * @example
410
- * ```ts
411
- * console.log(fShape.getAdjustPoints());
412
- * ```
413
- */
414
- getAdjustPoints(): IShapePointWithAdjName[];
415
479
  /**
416
480
  * Returns the Shape and connection-site index bound to a Connector's start point, or `null` when unbound.
417
481
  * @returns {IShapeRelationItem | null} The Shape and connection-site index bound to a Connector's start point, or `null` when unbound.
@@ -430,6 +494,51 @@ export declare class FShape extends FBase {
430
494
  * ```
431
495
  */
432
496
  getEndConnectInfo(): IShapeRelationItem | null;
497
+ /**
498
+ * Returns complete information for every adjustment handle exposed by this Shape.
499
+ * @returns {IShapeAdjustItemResolved[]} Detached resolved adjustment handles in preset order.
500
+ * @example
501
+ * ```ts
502
+ * fShape.setShapeType(univerAPI.Enum.ShapeTypeEnum.BlockArc);
503
+ *
504
+ * const handle = fShape.getAdjustHandles().find(({ gdRefR }) => gdRefR === 'adj3');
505
+ * console.log(handle?.type); // 'ahPolar'
506
+ * console.log(handle?.gdRefAng, handle?.gdRefR); // 'adj2', 'adj3'
507
+ * console.log(handle?.currentAdjustValues); // { adj2: 0, adj3: 25000 }
508
+ * console.log(handle?.resolvedMinR, handle?.resolvedMaxR); // 0, 50000
509
+ * ```
510
+ */
511
+ getAdjustHandles(): IShapeAdjustItemResolved[];
512
+ /**
513
+ * Updates only the supplied Shape adjustment values and clamps them to their handle ranges.
514
+ * @param {Record<string, number>} adjustValues Adjustment names and values to update.
515
+ * @returns {FShape} This Shape facade for chaining.
516
+ * @example
517
+ * ```ts
518
+ * fShape
519
+ * .setShapeType(univerAPI.Enum.ShapeTypeEnum.RoundRect)
520
+ * .setAdjustValues({ adj: 75000 });
521
+ *
522
+ * const [handle] = fShape.getAdjustHandles();
523
+ * console.log(handle.currentAdjustValues.adj); // 50000
524
+ * ```
525
+ */
526
+ setAdjustValues(adjustValues: Record<string, number>): this;
527
+ /**
528
+ * Removes all Shape adjustment overrides and restores preset defaults.
529
+ * @returns {FShape} This Shape facade for chaining.
530
+ * @example
531
+ * ```ts
532
+ * fShape
533
+ * .setShapeType(univerAPI.Enum.ShapeTypeEnum.RoundRect)
534
+ * .setAdjustValues({ adj: 40000 });
535
+ * fShape.resetAdjustValues();
536
+ *
537
+ * const [handle] = fShape.getAdjustHandles();
538
+ * console.log(handle.currentAdjustValues.adj); // 16667
539
+ * ```
540
+ */
541
+ resetAdjustValues(): this;
433
542
  /**
434
543
  * Replaces the current fill with a solid color and optional opacity.
435
544
  * @param {string} color The new fill color.
@@ -627,6 +736,6 @@ export declare class FShape extends FBase {
627
736
  private _patchStroke;
628
737
  private _getSnapshot;
629
738
  private _getGeometryModel;
630
- private _mutate;
739
+ protected _mutate(operation: string, callback: (adapter: IShapeHostAdapter) => boolean): boolean;
631
740
  }
632
741
  export {};
@@ -1,6 +1,6 @@
1
1
  import './f-enum';
2
2
  export { FConnectorShape } from './f-connector-shape';
3
3
  export { FShape } from './f-shape';
4
- export type { IShapeConnectionSite, IShapeGradientStop, IShapeImageFillOptions } from './f-shape';
4
+ export type { IShapeConnectionSite, IShapeGradientStop, IShapeImageFillOptions, IShapeSvgPathGeometryOptions, } from './f-shape';
5
5
  export { FShapeText } from './f-shape-text';
6
6
  export type { IShapeTextImageFillOptions } from './f-shape-text';
@@ -1,10 +1,8 @@
1
1
  export { BasicShapeModel as ShapeModel } from '../src/models/shape-model';
2
2
  export { BaseShapeRenderModel } from '../src/render-engine/shape-render-model';
3
3
  export { ImageFillModeEnum, ImageSourceTypeEnum, ShapeArrowSizeEnum, ShapeArrowTypeEnum, ShapeFillEnum, ShapeGradientTypeEnum, ShapeLineCapEnum, ShapeLineDashEnum, ShapeLineJoinEnum, ShapeLineTypeEnum, ShapeOperatorEnum, ShapePresetShadowValEnum, ShapeRenderModeEnum, ShapeSketchTypeEnum, ShapeTypeEnum, } from '../src/shape-enum';
4
- export type { IBasicShapeData, IConnectorLayoutResult, IConnectPointInfo, ICustomShapeTextData, ICxnShapeData, IDrawingRect, IGdContext, ILineType, IPathCommand, IPresetShapeConfig, IShapeAdjustItemResolved, IShapeData, IShapeFormulaBinding, IShapeJSONData, IShapeLineStyle, IShapePath, IShapePoint, IShapePointWithAdjName, IShapeRect, IShapeRelation, IShapeRelationItem, IShapeShadowEffect, IShapeText, IShapeTextBodyBehavior, IShapeTextBoxOptions, IShapeTextData, IShapeTextDataModel, IShapeTextRectPadding, ShapeShadowAlignment, ShapeTextHorizontalAnchor, } from '../src/shape-type';
4
+ export type { IBasicShapeData, IConnectorLayoutResult, IConnectPointInfo, ICustomShapeTextData, ICxnShapeData, IDrawingRect, IGdContext, ILineType, IPathCommand, IPresetShapeConfig, IShapeAdjustItemResolved, IShapeData, IShapeFormulaBinding, IShapeJSONData, IShapeLineStyle, IShapePath, IShapePoint, IShapePointWithAdjName, IShapeRect, IShapeRelation, IShapeRelationItem, IShapeText, IShapeTextBodyBehavior, IShapeTextBoxOptions, IShapeTextData, IShapeTextDataModel, IShapeTextRectPadding, ShapeTextHorizontalAnchor, } from '../src/shape-type';
5
5
  export { ShapeTextAutoFitType, ShapeTextDirection, ShapeTextWrapType } from '../src/shape-type';
6
- export type { IResolvedShapeShadow } from '../src/utils/shape-shadow.util';
7
- export { resolveShapeShadow } from '../src/utils/shape-shadow.util';
8
6
  export { applyShapeTextBoxOptions, resolveShapeTextBodyBehavior, resolveShapeTextBoxOptions, shouldUseFullShapeTextRectForAutoFit, } from '../src/utils/shape-text-behavior.util';
9
7
  export type { IResolvedShapeTextBoxOptions } from '../src/utils/shape-text-behavior.util';
10
8
  export { UniverShapePlugin } from './plugin';
@@ -12,8 +10,8 @@ export { computeConnectorRouteLayout, getBasicShapeRotateBound, routeConnectorLi
12
10
  export { ConnectorShapeHostAdapter } from './services/connector-shape-host-adapter';
13
11
  export { IConnectorShapeHostAdapter } from './services/connector-shape-host-adapter.service';
14
12
  export type { IConnectorArrow, IConnectorEndpoint, IConnectorShapeSnapshot, } from './services/connector-shape-host-adapter.service';
15
- export { IShapeHostAdapterRegistry, isShapeHostType, ShapeHostAdapterRegistry, } from './services/shape-host-adapter.service';
16
- export type { IShapeCreateInput, IShapeHostAdapter, IShapeRef, IShapeScope, IShapeSnapshot, IShapeTransform, IShapeUpdateInput, ShapeHostType, } from './services/shape-host-adapter.service';
13
+ export { canApplyShapeFormulaLastValue, IShapeHostAdapterRegistry, isShapeHostType, ShapeHostAdapterRegistry, } from './services/shape-host-adapter.service';
14
+ export type { IShapeCreateInput, IShapeFormulaLastValueGuard, IShapeHostAdapter, IShapeHostChange, IShapeHostChangeStream, IShapeRef, IShapeScope, IShapeSnapshot, IShapeTransform, IShapeUpdateInput, ShapeHostType, } from './services/shape-host-adapter.service';
17
15
  export { ShapeDefaultConfig } from './shape-default';
18
16
  export { resolveShapeDefaultInsertSize } from './shape-default-size';
19
17
  export { ConnectorCoordinateTransform } from './util/connector-transform';
@@ -22,3 +20,4 @@ export { isConnectorShape, isCurvedConnectorShape, } from './util/shape-util';
22
20
  export { buildConnectorEndpointUpdate, buildConnectorRoutePointsUpdate, createFreeConnectorPointInfo, resolveConnectorRoutePoints, resolveShapeConnectionPoint, } from './utils/connector.util';
23
21
  export { applyDocumentToShapeText, applyRichTextToShapeText, applyShapeTextAlignment, applyShapeTextStyle, applyTextToShapeText, normalizeShapeTextData, shapeTextToRichTextValue, } from './utils/shape-text-converter';
24
22
  export type { IShapeTextAlignmentOptions } from './utils/shape-text-converter';
23
+ export { parseSvgPathData } from './utils/svg-path-data';
@@ -1,3 +1,4 @@
1
+ import type { IBoundRectNoAngle } from '@univerjs/engine-render';
1
2
  import type { ShapeTypeEnum } from '../shape-enum';
2
3
  import type { IGdContext, IPresetShapeConfig, IShapeAdjustItemResolved, IShapeContextOptions, IShapeData, IShapeJSONData, IShapeModel, IShapePoint, IShapePointWithAdjName, IShapeRect, IShapeRelation, IShapeRelationItem, IShapeRenderParameters, IShapeTextData } from '../shape-type';
3
4
  import { BasicShapeEnum } from '../shape-enum';
@@ -68,6 +69,7 @@ export declare class BasicShapeModel implements IShapeModel {
68
69
  getAdjustInfoByName(adjName: string): IShapeAdjustItemResolved | undefined;
69
70
  getAdjustInfo(index: number): IShapeAdjustItemResolved | undefined;
70
71
  private _getAdjustIndexByName;
72
+ private _getAdjustNames;
71
73
  private _getAdjScope;
72
74
  private _setAdjustValue;
73
75
  clearAdjustValue(): void;
@@ -111,6 +113,7 @@ export declare class BasicShapeModel implements IShapeModel {
111
113
  */
112
114
  isHitLine(pointX: number, pointY: number, width: number, height: number, tolerance?: number): boolean;
113
115
  render(canvasContext: CanvasRenderingContext2D, rect: IShapeRect, renderOption: IShapeRenderParameters): void;
116
+ getDrawingEffectBounds(rect: IShapeRect): IBoundRectNoAngle | undefined;
114
117
  /**
115
118
  * Build the shape outline path on the canvas context and clip.
116
119
  * This only builds paths and clips — no fill or stroke is applied.
@@ -119,7 +122,13 @@ export declare class BasicShapeModel implements IShapeModel {
119
122
  */
120
123
  buildClipPath(canvasContext: CanvasRenderingContext2D, rect: IShapeRect): IShapeRect | false;
121
124
  getDrawingPoints(): IShapePointWithAdjName[];
122
- calcAdjValue(rect: IShapeRect, point: IShapePoint, adjustInfo: IShapeAdjustItemResolved, _isFlipH: boolean, _isFlipV: boolean): number;
125
+ calcAdjValues(rect: IShapeRect, point: IShapePoint, info: IShapeAdjustItemResolved, _isFlipH: boolean, _isFlipV: boolean): Record<string, number>;
126
+ private _getAdjustRefs;
127
+ private _seedAngleAdjustValue;
128
+ private _evaluateAdjustPosition;
129
+ private _calcAdjustDerivative;
130
+ private _solveAdjustDelta;
131
+ private _clamp;
123
132
  dispose(): void;
124
133
  private _getSnapshotAdjustValues;
125
134
  private _cloneShapeDataWithSnapshotAdjustValues;
@@ -4,8 +4,8 @@ export declare abstract class BaseShapeRenderModel {
4
4
  protected _isLineShape: boolean;
5
5
  abstract readonly name: string;
6
6
  abstract readonly presetShapeConfig: IPresetShapeConfig;
7
- private _inverseCache;
8
7
  isLineShape(): boolean;
8
+ protected _isStrokeVisible(shapeData: IShapeData): boolean;
9
9
  getConnectorLinePoints(): IShapeGdContextKeyPoint[];
10
10
  /**
11
11
  * This method tests whether a point (pointX, pointY) hits any interactive parts of the shape,
@@ -152,29 +152,6 @@ export declare abstract class BaseShapeRenderModel {
152
152
  * Apply coordinate scaling to resolved path points in-place.
153
153
  */
154
154
  private _scalePathPoints;
155
- /**
156
- * Check if the adjust handle at the given index has an inverse relationship.
157
- * Uses cache to avoid recalculating.
158
- * @param index The index of the adjust handle in ahLst
159
- * @returns true if inverse relationship exists
160
- */
161
- isInverse(index: number): boolean;
162
- /**
163
- * Detect if there's an inverse relationship between adj value and position.
164
- * Analyzes the gd formula chain to find subtract patterns like "r - adj*k" or "b - adj*k".
165
- * @param adjustInfo The adjust handle info
166
- * @returns true if inverse relationship is detected
167
- */
168
- private _detectInverseRelationship;
169
- /**
170
- * Recursively analyze gd formula to detect inverse relationship.
171
- * Looking for patterns like: pos = r - f(adj) or pos = b - f(adj)
172
- */
173
- private _analyzeFormulaForInverse;
174
- /**
175
- * Check if a gd variable depends on (is derived from) adjName
176
- */
177
- private _dependsOnAdj;
178
155
  getGdValue(key: number | IGdContextKey, gdRecord: Partial<IGdContext>): number;
179
156
  private _renderAdjustHandles;
180
157
  }
@@ -1,6 +1,8 @@
1
- import type { IDisposable, UniverInstanceType } from '@univerjs/core';
1
+ import type { IFormulaLastValue } from '@univerjs-pro/engine-formula';
2
+ import type { IAccessor, IDisposable, IMutationInfo } from '@univerjs/core';
2
3
  import type { ShapeTypeEnum } from '../shape-enum';
3
4
  import type { IShapeData } from '../shape-type';
5
+ import { UniverInstanceType } from '@univerjs/core';
4
6
  export type ShapeHostType = UniverInstanceType.UNIVER_SHEET | UniverInstanceType.UNIVER_DOC | UniverInstanceType.UNIVER_SLIDE | UniverInstanceType.UNIVER_BOARD;
5
7
  export declare function isShapeHostType(type: UniverInstanceType): type is ShapeHostType;
6
8
  export interface IShapeScope {
@@ -15,6 +17,15 @@ export interface IShapeRef extends IShapeScope {
15
17
  /** Stable Shape identifier within the host subunit. */
16
18
  shapeId: string;
17
19
  }
20
+ export interface IShapeHostChange {
21
+ /** Host unit whose persisted Shape projection may have changed. */
22
+ unitId: string;
23
+ }
24
+ export interface IShapeHostChangeStream {
25
+ subscribe(listener: (change: IShapeHostChange) => void): {
26
+ unsubscribe(): void;
27
+ };
28
+ }
18
29
  export interface IShapeTransform {
19
30
  /** Horizontal position in host coordinates. */
20
31
  left: number;
@@ -79,12 +90,44 @@ export interface IShapeUpdateInput {
79
90
  /** Canvas selectability to update. Omit to preserve the current value. */
80
91
  selectable?: boolean;
81
92
  }
93
+ /**
94
+ * Ephemeral compare-and-set guard carried by a derived Formula last-value mutation.
95
+ *
96
+ * The guard is deliberately excluded from persisted Shape data. It prevents an
97
+ * asynchronous result calculated from an older formula or External Reference
98
+ * binding from overwriting a newer user edit.
99
+ */
100
+ export interface IShapeFormulaLastValueGuard {
101
+ expectedFormula: string;
102
+ expectedReferenceRevision: number;
103
+ }
104
+ /** Revalidates a Formula Shape result immediately before its Host mutation writes. */
105
+ export declare function canApplyShapeFormulaLastValue(accessor: IAccessor, ref: IShapeRef, currentFormula: string | undefined, guard: IShapeFormulaLastValueGuard | undefined): boolean;
82
106
  export interface IShapeHostAdapter {
83
107
  readonly hostType: ShapeHostType;
108
+ /** Emits after a Shape mutation has changed this host's persisted Shape data. */
109
+ readonly shapeChanged$?: IShapeHostChangeStream;
84
110
  getShape(ref: IShapeRef): IShapeSnapshot | null;
85
111
  listShapes(scope: IShapeScope): IShapeSnapshot[];
112
+ /**
113
+ * Lists Shapes from every subunit owned by one host Unit.
114
+ * Core consumers use this optional hook to rebuild runtime projections from persisted snapshots.
115
+ */
116
+ listShapesInUnit?(unitId: string): IShapeSnapshot[];
86
117
  createShape(scope: IShapeScope, input: IShapeCreateInput): IShapeSnapshot | null;
118
+ /**
119
+ * Creates Shapes atomically and returns snapshots in input order.
120
+ * Implementations must return `null` without retaining partial changes when any input or the host command fails.
121
+ */
122
+ createShapes?(scope: IShapeScope, inputs: IShapeCreateInput[]): IShapeSnapshot[] | null;
87
123
  updateShape(ref: IShapeRef, input: IShapeUpdateInput): boolean;
124
+ /**
125
+ * Builds the Host's existing Shape mutation for a successful Formula result.
126
+ *
127
+ * Implementations must include `guard` in the mutation params and validate it
128
+ * in the mutation handler before replacing `formulaBinding.lastValue`.
129
+ */
130
+ createFormulaLastValueMutation?(ref: IShapeRef, guard: IShapeFormulaLastValueGuard, lastValue: IFormulaLastValue): IMutationInfo | null;
88
131
  removeShape(ref: IShapeRef): boolean;
89
132
  bringToFront(ref: IShapeRef): boolean;
90
133
  bringForward(ref: IShapeRef): boolean;
@@ -81,7 +81,7 @@ export declare enum ShapePresetShadowValEnum {
81
81
  }
82
82
  /**
83
83
  * Shape fill type enum
84
- * Currently, PatternFill and PictureFill are not supported, but we define them for future use, if will be treat as Nofill currently.
84
+ * Shape fill types supported by the renderer.
85
85
  */
86
86
  export declare enum ShapeFillEnum {
87
87
  NoFill = 1,
@@ -1,5 +1,6 @@
1
- import type { HorizontalAlign, IDocumentData, VerticalAlign } from '@univerjs/core';
2
- import type { BasicShapeEnum, ImageFillModeEnum, ImageSourceTypeEnum, ShapeArrowSizeEnum, ShapeArrowTypeEnum, ShapeFillEnum, ShapeGradientTypeEnum, ShapeLineCapEnum, ShapeLineDashEnum, ShapeLineJoinEnum, ShapeLineTypeEnum, ShapeOperatorEnum, ShapePresetShadowValEnum, ShapeRenderModeEnum, ShapeSketchTypeEnum, ShapeTypeEnum } from './shape-enum';
1
+ import type { IFormulaLastValue } from '@univerjs-pro/engine-formula';
2
+ import type { HorizontalAlign, IDocumentData, IGlowEffect, IShadowEffect, VerticalAlign } from '@univerjs/core';
3
+ import type { BasicShapeEnum, ImageFillModeEnum, ImageSourceTypeEnum, ShapeArrowSizeEnum, ShapeArrowTypeEnum, ShapeFillEnum, ShapeGradientTypeEnum, ShapeLineCapEnum, ShapeLineDashEnum, ShapeLineJoinEnum, ShapeLineTypeEnum, ShapeOperatorEnum, ShapeRenderModeEnum, ShapeSketchTypeEnum, ShapeTypeEnum } from './shape-enum';
3
4
  /**
4
5
  * GdContext 用来计算 OOXML Shape 的 Geometry Definitions (gd)
5
6
  * 包含:
@@ -575,7 +576,6 @@ export declare enum ShapeTextWrapType {
575
576
  /** Wrap text inside the shape text box. */
576
577
  Square = "square"
577
578
  }
578
- export type ShapeShadowAlignment = 'tl' | 't' | 'tr' | 'l' | 'ctr' | 'r' | 'bl' | 'b' | 'br';
579
579
  export declare enum ShapeTextAutoFitType {
580
580
  /** Do not automatically adjust overflowing text. */
581
581
  NoAutoFit = "noAutoFit",
@@ -665,39 +665,17 @@ export interface ICustomShapeTextData extends IShapeTextAlign, IShapeTextBodyBeh
665
665
  dataModel?: IShapeTextDataModel;
666
666
  }
667
667
  export type IShapeTextData = IShapeText | ICustomShapeTextData;
668
- /**
669
- * A shape outer-shadow effect. Distances and blur radius use slide drawing
670
- * units; direction is in degrees where 0 points right and 90 points down.
671
- */
672
- export interface IShapeShadowEffect {
673
- /** Shadow color as a CSS color string. */
674
- color: string;
675
- /** OOXML preset shadow value, when the shadow originated from `<a:prstShdw>`. */
676
- preset?: ShapePresetShadowValEnum;
677
- /** Shadow opacity, from 0 (transparent) to 1 (opaque). */
678
- opacity?: number;
679
- /** Blur radius in slide drawing units. */
680
- blurRadius?: number;
681
- /** Direction angle in degrees, with 0 pointing right and 90 pointing down. */
682
- direction?: number;
683
- /** Offset distance from the shape in slide drawing units. */
684
- distance?: number;
685
- /** Horizontal shadow scale factor; 1 means 100%. */
686
- sx?: number;
687
- /** Vertical shadow scale factor; 1 means 100%. */
688
- sy?: number;
689
- /** Horizontal shadow skew angle in degrees. */
690
- skewX?: number;
691
- /** Vertical shadow skew angle in degrees. */
692
- skewY?: number;
693
- /** Alignment point used while scaling or skewing the shadow. */
694
- alignment?: ShapeShadowAlignment;
695
- /** Whether the shadow rotates together with the shape. */
696
- rotateWithShape?: boolean;
697
- }
698
668
  /** Formula data persisted by a formula-backed text-box shape. */
699
669
  export interface IShapeFormulaBinding {
700
- /** The complete formula string, including the leading equals sign. */
670
+ /**
671
+ * The complete formula string, including the leading equals sign.
672
+ *
673
+ * Every reference must include its worksheet or table name; unqualified references
674
+ * such as `=A1` are unsupported. For a Shape hosted by a Document, Slide, or Board,
675
+ * every reference must also include the workbook or Base name. Examples:
676
+ * `=Sheet1!A1`, `=Orders[Amount]`, `='[Sales Workbook]Sheet1'!A1`, and
677
+ * `=[Sales Base]!Orders[Amount]`.
678
+ */
701
679
  formula: string;
702
680
  /** Whether value changes should be animated. Defaults to true. */
703
681
  animationEnabled?: boolean;
@@ -705,6 +683,8 @@ export interface IShapeFormulaBinding {
705
683
  numberFormat?: {
706
684
  pattern: string;
707
685
  };
686
+ /** Last successful scalar value persisted with the Shape for stale-first reload rendering. */
687
+ lastValue?: IFormulaLastValue;
708
688
  }
709
689
  /**
710
690
  * This interface defines the shape data structure , and this part will save in json
@@ -774,8 +754,10 @@ export interface IBasicShapeData {
774
754
  adjustValues?: Record<string, number>;
775
755
  isCustom?: boolean;
776
756
  customGeometry?: IPresetShapeConfig;
777
- /** Basic outer shadow effect applied while rendering the shape path. */
778
- outerShadow?: IShapeShadowEffect;
757
+ /** Outer shadow applied while rendering the shape path. */
758
+ outerShadow?: IShadowEffect;
759
+ /** Glow applied around the rendered shape path. */
760
+ glow?: IGlowEffect;
779
761
  shapeText?: IShapeTextData;
780
762
  /**
781
763
  * Text box inset used to calculate the editable/rendered text rect.
@@ -844,9 +826,9 @@ export interface IPresetShapeConfig {
844
826
  /** Angle in degrees (cd4 = 90°, cd2 = 180°, 3cd4 = 270°) */
845
827
  ang: string | number;
846
828
  /** X coordinate */
847
- x?: string | number;
829
+ x: string | number;
848
830
  /** Y coordinate */
849
- y?: string | number;
831
+ y: string | number;
850
832
  }>;
851
833
  /** Text rectangle definition */
852
834
  rect?: {
@@ -934,14 +916,8 @@ export interface IShapeAdjustItemResolved extends IShapeAdjustItem {
934
916
  x: number;
935
917
  y: number;
936
918
  };
937
- /** Current value of the adj parameter being controlled */
938
- currentAdjValue?: number;
939
- /**
940
- * Indicates inverse relationship between adj value and position.
941
- * Calculated at runtime by analyzing gd formulas.
942
- * When true, increasing adj value will decrease the position value.
943
- */
944
- inverse?: boolean;
919
+ /** Current values of all adjustment parameters controlled by this handle. */
920
+ currentAdjustValues: Record<string, number>;
945
921
  }
946
922
  export interface IShapeRenderParameters {
947
923
  renderMode?: ShapeRenderModeEnum;
@@ -0,0 +1,48 @@
1
+ import type { IPathCommand } from '../shape-type';
2
+ /**
3
+ * Parses an SVG `<path>` element's `d` attribute into engine-shape path commands.
4
+ *
5
+ * This helper parses path geometry only. It does not accept complete `<svg>` or `<path>` markup,
6
+ * data URLs, transforms, fill colors, or stroke styles. Configure those properties separately on
7
+ * the Shape.
8
+ *
9
+ * Supported SVG commands:
10
+ *
11
+ * - `M` / `m` — move to
12
+ * - `L` / `l` — line to
13
+ * - `H` / `h` — horizontal line to
14
+ * - `V` / `v` — vertical line to
15
+ * - `C` / `c` — cubic Bézier curve
16
+ * - `S` / `s` — smooth cubic Bézier curve
17
+ * - `Q` / `q` — quadratic Bézier curve
18
+ * - `T` / `t` — smooth quadratic Bézier curve
19
+ * - `A` / `a` — elliptical arc
20
+ * - `Z` / `z` — close path
21
+ *
22
+ * Repeated coordinate groups and relative commands are normalized to absolute `IPathCommand`
23
+ * values. `H` and `V` become `L`, smooth commands expand their reflected control points, and SVG
24
+ * arcs become one or more cubic `C` segments. SVG arcs are never forwarded as engine-shape `A`
25
+ * commands because that command follows different OOXML arc semantics.
26
+ *
27
+ * @param data The value of an SVG `<path d="...">` attribute.
28
+ * @returns Parsed, absolute engine-shape path commands.
29
+ * @throws {SyntaxError} When the path is empty, malformed, starts without `M`/`m`, or uses an
30
+ * unsupported SVG command.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const commands = parseSvgPathData(
35
+ * 'M 50,10 C 34,20 24,64 22,92 L 78,92 C 76,64 66,20 50,10 Z'
36
+ * );
37
+ *
38
+ * console.log(commands);
39
+ * // [
40
+ * // { command: 'M', points: [50, 10] },
41
+ * // { command: 'C', points: [34, 20, 24, 64, 22, 92] },
42
+ * // { command: 'L', points: [78, 92] },
43
+ * // { command: 'C', points: [76, 64, 66, 20, 50, 10] },
44
+ * // { command: 'z', points: [] },
45
+ * // ]
46
+ * ```
47
+ */
48
+ export declare function parseSvgPathData(data: string): IPathCommand[];