diff --git a/code/CHANGELOG.md b/code/CHANGELOG.md index dd8bbc041..0e0b608e6 100644 --- a/code/CHANGELOG.md +++ b/code/CHANGELOG.md @@ -18,6 +18,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#305](https://github.com/InditexTech/weavejs/issues/305) Don't allow to transform when more than one element is selected - [#308](https://github.com/InditexTech/weavejs/issues/308) Allow to configure transformer configuration per node +### Changed + +- [#219](https://github.com/InditexTech/weavejs/issues/219) Improve frame + ### Fixed - [#291](https://github.com/InditexTech/weavejs/issues/291) Group of elements moving not maintaining position (all layers) diff --git a/code/packages/sdk/src/actions/frame-tool/frame-tool.ts b/code/packages/sdk/src/actions/frame-tool/frame-tool.ts index 052200633..5076e7788 100644 --- a/code/packages/sdk/src/actions/frame-tool/frame-tool.ts +++ b/code/packages/sdk/src/actions/frame-tool/frame-tool.ts @@ -155,7 +155,7 @@ export class WeaveFrameToolAction extends WeaveAction { const selectionPlugin = this.instance.getPlugin('nodesSelection'); if (selectionPlugin) { - const node = stage.findOne(`#${this.frameId}`); + const node = stage.findOne(`#${this.frameId}-selector-area`); if (node) { selectionPlugin.setSelectedNodes([node]); } diff --git a/code/packages/sdk/src/index.ts b/code/packages/sdk/src/index.ts index 21120e084..da40fbdf3 100644 --- a/code/packages/sdk/src/index.ts +++ b/code/packages/sdk/src/index.ts @@ -6,7 +6,6 @@ export { Weave } from './weave'; export { WeaveStore } from './stores/store'; export * from './stores/types'; export { WeaveNode } from './nodes/node'; -export * from './nodes/constants'; export { WeaveAction } from './actions/action'; export * from './actions/types'; export { WeavePlugin } from './plugins/plugin'; diff --git a/code/packages/sdk/src/nodes/constants.ts b/code/packages/sdk/src/nodes/constants.ts deleted file mode 100644 index f7cdcd3c1..000000000 --- a/code/packages/sdk/src/nodes/constants.ts +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) -// -// SPDX-License-Identifier: Apache-2.0 - -export const DEFAULT_ANCHORS_ENABLED: string[] = [ - 'top-left', - 'top-center', - 'top-right', - 'middle-right', - 'middle-left', - 'bottom-left', - 'bottom-center', - 'bottom-right', -]; diff --git a/code/packages/sdk/src/nodes/frame/constants.ts b/code/packages/sdk/src/nodes/frame/constants.ts index 83f89007b..cc4d862e3 100644 --- a/code/packages/sdk/src/nodes/frame/constants.ts +++ b/code/packages/sdk/src/nodes/frame/constants.ts @@ -70,10 +70,10 @@ export const WEAVE_FRAME_NODE_SIZES: WeaveFrameNodeSizesInfo = { export const WEAVE_FRAME_NODE_DEFAULT_CONFIG = { fontFamily: 'Arial', - fontStyle: 'normal', + fontStyle: 'bold', titleHeight: 30, borderColor: '#000000ff', - borderWidth: 2, + borderWidth: 1, onTargetLeave: { borderColor: '#000000ff', fill: '#ffffffff', @@ -86,6 +86,8 @@ export const WEAVE_FRAME_NODE_DEFAULT_CONFIG = { rotateEnabled: false, resizeEnabled: false, enabledAnchors: [] as string[], + borderStrokeWidth: 3, + padding: 0, }, }; diff --git a/code/packages/sdk/src/nodes/frame/frame.ts b/code/packages/sdk/src/nodes/frame/frame.ts index 3846759d5..8aa3afb47 100644 --- a/code/packages/sdk/src/nodes/frame/frame.ts +++ b/code/packages/sdk/src/nodes/frame/frame.ts @@ -20,6 +20,9 @@ import type { WeaveFrameNodeParams, WeaveFrameProperties, } from './types'; +import type { KonvaEventObject } from 'konva/lib/Node'; +import type { Rect } from 'konva/lib/shapes/Rect'; +import type { WeaveNodesSnappingPlugin } from '@/plugins/nodes-snapping/nodes-snapping'; export class WeaveFrameNode extends WeaveNode { private config: WeaveFrameProperties; @@ -93,41 +96,47 @@ export class WeaveFrameNode extends WeaveNode { containerOffsetX: 0, containerOffsetY: titleHeight, width: props.frameWidth, - height: props.frameHeight + titleHeight, - fill: '#ffffffff', - clipX: 0, - clipY: 0, - clipWidth: props.frameWidth, - clipHeight: props.frameHeight + titleHeight, - name: 'node', + height: props.frameHeight, + fill: 'transparent', + draggable: false, }); - frame.getTransformerProperties = () => { - return this.config.transform; - }; + const frameInternalGroup = new Konva.Group({ + id: `${id}-selector`, + x: 0, + y: 0, + width: props.frameWidth, + height: props.frameHeight, + strokeScaleEnabled: false, + draggable: false, + }); + + frame.add(frameInternalGroup); const background = new Konva.Rect({ id: `${id}-bg`, nodeId: id, x: 0, - y: titleHeight, + y: 0, width: props.frameWidth, stroke: borderColor, strokeWidth: borderWidth, strokeScaleEnabled: false, + shadowForStrokeEnabled: false, height: props.frameHeight, fill: '#ffffffff', + listening: false, draggable: false, }); - frame.add(background); + frameInternalGroup.add(background); const text = new Konva.Text({ id: `${id}-title`, x: 0, - y: 0, + y: -titleHeight, width: props.frameWidth, - height: titleHeight - 10, + height: titleHeight, fontSize: 20, fontFamily, fontStyle, @@ -140,7 +149,137 @@ export class WeaveFrameNode extends WeaveNode { draggable: false, }); - frame.add(text); + frameInternalGroup.add(text); + + const selectorArea = new Konva.Rect({ + ...frameParams, + id: `${id}-selector-area`, + name: 'node', + nodeId: id, + containerId: `${id}-group-internal`, + x: 0, + y: 0, + strokeWidth: 0, + strokeScaleEnabled: false, + width: props.frameWidth, + height: props.frameHeight, + fill: 'transparent', + draggable: false, + }); + + selectorArea.getTransformerProperties = () => { + return this.config.transform; + }; + + selectorArea.updatePosition = (position) => { + frame.setAbsolutePosition(position); + selectorArea.setAttrs({ + x: 0, + y: 0, + }); + this.instance.updateNode( + this.serialize(selectorArea as WeaveElementInstance) + ); + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateFrame = (e: KonvaEventObject) => { + const selectorArea = e.target; + const stage = selectorArea.getStage(); + if (!stage) return; + + const absPos = selectorArea.getAbsolutePosition(); + const absRot = selectorArea.getAbsoluteRotation(); + + const scaleX = selectorArea.scaleX(); + const scaleY = selectorArea.scaleY(); + selectorArea.x(0); + selectorArea.y(0); + + frame.setAbsolutePosition(absPos); + frame.rotation(absRot); + frame.width(selectorArea.width()); + frame.height(selectorArea.height()); + + frameInternalGroup.width(Math.max(5, selectorArea.width() * scaleX)); + frameInternalGroup.height(Math.max(5, selectorArea.height() * scaleY)); + + background.width(Math.max(5, selectorArea.width() * scaleX)); + background.height(Math.max(5, selectorArea.height() * scaleY)); + + text.width(Math.max(5, selectorArea.width() * scaleX)); + text.height(titleHeight * scaleY); + + frameInternal.width(Math.max(5, selectorArea.width() * scaleX)); + frameInternal.height(Math.max(5, selectorArea.height() * scaleY)); + }; + + selectorArea.on('transform', (e) => { + updateFrame(e); + + const node = e.target; + + const nodesSnappingPlugin = + this.instance.getPlugin('nodesSnapping'); + + if ( + nodesSnappingPlugin && + this.isSelecting() && + this.isNodeSelected(node) + ) { + nodesSnappingPlugin.evaluateGuidelines(e); + } + + const clonedSA = selectorArea.clone(); + const scaleX = clonedSA.scaleX(); + const scaleY = clonedSA.scaleY(); + + clonedSA.x(0); + clonedSA.y(0); + clonedSA.width(Math.max(5, clonedSA.width() * scaleX)); + clonedSA.height(Math.max(5, clonedSA.height() * scaleY)); + clonedSA.scaleX(1); + clonedSA.scaleY(1); + + this.instance.updateNode( + this.serialize(clonedSA as WeaveElementInstance) + ); + + e.cancelBubble = true; + }); + + selectorArea.on('transformend', (e) => { + const node = e.target; + + const nodesSnappingPlugin = + this.instance.getPlugin('nodesSnapping'); + + if ( + nodesSnappingPlugin && + this.isSelecting() && + this.isNodeSelected(node) + ) { + nodesSnappingPlugin.cleanupEvaluateGuidelines(); + } + + const scaleX = selectorArea.scaleX(); + const scaleY = selectorArea.scaleY(); + + selectorArea.x(0); + selectorArea.y(0); + selectorArea.width(Math.max(5, selectorArea.width() * scaleX)); + selectorArea.height(Math.max(5, selectorArea.height() * scaleY)); + selectorArea.scaleX(1); + selectorArea.scaleY(1); + + updateFrame(e); + + this.instance.updateNode( + this.serialize(selectorArea as WeaveElementInstance) + ); + }); + + frameInternalGroup.add(selectorArea); const frameInternal = new Konva.Group({ id: `${id}-group-internal`, @@ -149,20 +288,23 @@ export class WeaveFrameNode extends WeaveNode { y: titleHeight, width: props.frameWidth, height: props.frameHeight, - draggable: false, - stroke: 'transparent', strokeScaleEnabled: false, - borderWidth: 0, - clipX: 0, - clipY: 0, - clipWidth: props.frameWidth, - clipHeight: props.frameHeight, + draggable: false, + }); + + frameInternal.clipFunc((ctx) => { + const width = frameInternal.width() * frameInternal.scaleX(); + const height = frameInternal.height() * frameInternal.scaleY(); + ctx.rect(0, -titleHeight, width, height); }); - frame.add(frameInternal); + frameInternalGroup.add(frameInternal); this.setupDefaultNodeEvents(frame); + frame.on('dragmove', () => {}); + frame.on('dragend', () => {}); + frame.on(WEAVE_NODE_CUSTOM_EVENTS.onTargetLeave, () => { background.setAttrs({ stroke: onTargetLeaveBorderColor, @@ -192,24 +334,74 @@ export class WeaveFrameNode extends WeaveNode { const newProps = { ...nextProps }; + const { titleHeight } = this.config; + nodeInstance.setAttrs({ ...newProps, }); - const frameTitle = frameNode.findOne(`#${id}-title`); - if (frameTitle) { - frameTitle.setAttrs({ - text: nextProps.title, + const selectorArea = frameNode.findOne(`#${id}-selector-area`); + if (selectorArea) { + selectorArea.setAttrs({ + x: 0, + y: 0, + width: nextProps.width, + height: nextProps.height, }); + + const frameInternalGroup = frameNode.findOne(`#${id}-selector`); + if (frameInternalGroup) { + frameInternalGroup.setAttrs({ + x: 0, + y: 0, + width: nextProps.width * selectorArea.scaleX(), + height: nextProps.height * selectorArea.scaleY(), + }); + } + + const background = frameNode.findOne(`#${id}-bg`); + if (background) { + background.setAttrs({ + x: 0, + y: 0, + width: nextProps.width * selectorArea.scaleX(), + height: nextProps.height * selectorArea.scaleY(), + }); + } + + const text = frameNode.findOne(`#${id}-title`); + if (text) { + text.setAttrs({ + x: 0, + y: -titleHeight, + text: nextProps.title, + width: nextProps.width * selectorArea.scaleX(), + }); + } + + const frameInternal = frameNode.findOne(`#${id}-group-internal`); + if (frameInternal) { + frameInternal.setAttrs({ + x: 0, + y: titleHeight, + width: nextProps.width * selectorArea.scaleX(), + height: nextProps.height * selectorArea.scaleY(), + }); + } } } serialize(instance: WeaveElementInstance): WeaveStateElement { + const stage = this.instance.getStage(); const attrs = instance.getAttrs(); - const frameInternal = (instance as Konva.Group).findOne( - `#${attrs.containerId}` - ) as Konva.Group | undefined; + const mainNode = stage?.findOne(`#${attrs.nodeId}`) as + | Konva.Group + | undefined; + + const frameInternal = mainNode?.findOne(`#${attrs.containerId}`) as + | Konva.Group + | undefined; const childrenMapped: WeaveStateElement[] = []; if (frameInternal) { @@ -224,16 +416,22 @@ export class WeaveFrameNode extends WeaveNode { } } - const cleanedAttrs = { ...attrs }; + const realAttrs = mainNode?.getAttrs(); + + const cleanedAttrs = { ...realAttrs }; delete cleanedAttrs.draggable; return { - key: attrs.id ?? '', - type: attrs.nodeType, + key: realAttrs?.id ?? '', + type: realAttrs?.nodeType, props: { ...cleanedAttrs, - id: attrs.id ?? '', - nodeType: attrs.nodeType, + id: realAttrs?.id ?? '', + // x: instance.x(), + // y: instance.y(), + // width: instance.width(), + // height: instance.height(), + nodeType: realAttrs?.nodeType, children: childrenMapped, }, }; diff --git a/code/packages/sdk/src/nodes/frame/types.ts b/code/packages/sdk/src/nodes/frame/types.ts index 2ea4bb52b..4d4c1d8e4 100644 --- a/code/packages/sdk/src/nodes/frame/types.ts +++ b/code/packages/sdk/src/nodes/frame/types.ts @@ -2,12 +2,14 @@ // // SPDX-License-Identifier: Apache-2.0 -import type { WeaveElementAttributes } from '@inditextech/weave-types'; +import type { + WeaveElementAttributes, + WeaveNodeTransformerProperties, +} from '@inditextech/weave-types'; import type { WEAVE_FRAME_NODE_SIZES_ORIENTATION, WEAVE_FRAME_NODE_SIZES_TYPES, } from './constants'; -import type { WeaveNodeTransformerProperties } from '../types'; export type WeaveFrameNodeSizesOrientationKeys = keyof typeof WEAVE_FRAME_NODE_SIZES_ORIENTATION; diff --git a/code/packages/sdk/src/nodes/group/group.ts b/code/packages/sdk/src/nodes/group/group.ts index c621c8875..92539e088 100644 --- a/code/packages/sdk/src/nodes/group/group.ts +++ b/code/packages/sdk/src/nodes/group/group.ts @@ -4,22 +4,42 @@ import Konva from 'konva'; import { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, type WeaveElementAttributes, type WeaveElementInstance, type WeaveStateElement, } from '@inditextech/weave-types'; import { WeaveNode } from '../node'; import { WEAVE_GROUP_NODE_TYPE } from './constants'; +import type { WeaveGroupNodeParams, WeaveGroupProperties } from './types'; export class WeaveGroupNode extends WeaveNode { + private config: WeaveGroupProperties; protected nodeType: string = WEAVE_GROUP_NODE_TYPE; + constructor(params?: WeaveGroupNodeParams) { + super(); + + const { config } = params ?? {}; + + this.config = { + transform: { + ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...config?.transform, + }, + }; + } + onRender(props: WeaveElementAttributes): WeaveElementInstance { const group = new Konva.Group({ ...props, name: 'node', }); + group.getTransformerProperties = () => { + return this.config.transform; + }; + this.setupDefaultNodeEvents(group); return group; diff --git a/code/packages/sdk/src/nodes/group/types.ts b/code/packages/sdk/src/nodes/group/types.ts new file mode 100644 index 000000000..5835bdeab --- /dev/null +++ b/code/packages/sdk/src/nodes/group/types.ts @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +// +// SPDX-License-Identifier: Apache-2.0 + +import type { WeaveNodeTransformerProperties } from '@inditextech/weave-types'; + +export type WeaveGroupProperties = { + transform: WeaveNodeTransformerProperties; +}; + +export type WeaveGroupNodeParams = { + config: Partial; +}; diff --git a/code/packages/sdk/src/nodes/image/image.ts b/code/packages/sdk/src/nodes/image/image.ts index 96750347b..b3ec9c50f 100644 --- a/code/packages/sdk/src/nodes/image/image.ts +++ b/code/packages/sdk/src/nodes/image/image.ts @@ -4,23 +4,38 @@ import Konva from 'konva'; import { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, type WeaveElementAttributes, type WeaveElementInstance, } from '@inditextech/weave-types'; import { WeaveNode } from '../node'; -import { type ImageProps } from './types'; +import { + type ImageProps, + type WeaveImageNodeParams, + type WeaveImageProperties, +} from './types'; import { WeaveImageToolAction } from '@/actions/image-tool/image-tool'; import { WeaveImageClip } from './clip'; import { WEAVE_IMAGE_NODE_TYPE } from './constants'; export class WeaveImageNode extends WeaveNode { + private config: WeaveImageProperties; protected nodeType: string = WEAVE_IMAGE_NODE_TYPE; private imageLoaded: boolean; cropping: boolean; - constructor() { + constructor(params?: WeaveImageNodeParams) { super(); + const { config } = params ?? {}; + + this.config = { + transform: { + ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...config?.transform, + }, + }; + this.imageLoaded = false; this.cropping = false; } @@ -52,6 +67,10 @@ export class WeaveImageNode extends WeaveNode { name: 'node', }); + image.getTransformerProperties = () => { + return this.config.transform; + }; + const imagePlaceholder = new Konva.Rect({ ...groupImageProps, id: `${id}-placeholder`, diff --git a/code/packages/sdk/src/nodes/image/types.ts b/code/packages/sdk/src/nodes/image/types.ts index 02ff049fd..d7dc3d5fc 100644 --- a/code/packages/sdk/src/nodes/image/types.ts +++ b/code/packages/sdk/src/nodes/image/types.ts @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: Apache-2.0 -import { type WeaveElementAttributes } from '@inditextech/weave-types'; +import { + type WeaveElementAttributes, + type WeaveNodeTransformerProperties, +} from '@inditextech/weave-types'; export type ImageProps = WeaveElementAttributes & { id: string; @@ -14,3 +17,11 @@ export type ImageProps = WeaveElementAttributes & { height: number; }; }; + +export type WeaveImageProperties = { + transform: WeaveNodeTransformerProperties; +}; + +export type WeaveImageNodeParams = { + config: Partial; +}; diff --git a/code/packages/sdk/src/nodes/line/line.ts b/code/packages/sdk/src/nodes/line/line.ts index 2bac6051f..a78f0a200 100644 --- a/code/packages/sdk/src/nodes/line/line.ts +++ b/code/packages/sdk/src/nodes/line/line.ts @@ -4,21 +4,41 @@ import Konva from 'konva'; import { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, type WeaveElementAttributes, type WeaveElementInstance, } from '@inditextech/weave-types'; import { WeaveNode } from '../node'; import { WEAVE_LINE_NODE_TYPE } from './constants'; +import type { WeaveLineNodeParams, WeaveLineProperties } from './types'; export class WeaveLineNode extends WeaveNode { + private config: WeaveLineProperties; protected nodeType: string = WEAVE_LINE_NODE_TYPE; + constructor(params?: WeaveLineNodeParams) { + super(); + + const { config } = params ?? {}; + + this.config = { + transform: { + ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...config?.transform, + }, + }; + } + onRender(props: WeaveElementAttributes): WeaveElementInstance { const line = new Konva.Line({ ...props, name: 'node', }); + line.getTransformerProperties = () => { + return this.config.transform; + }; + this.setupDefaultNodeEvents(line); return line; diff --git a/code/packages/sdk/src/nodes/line/types.ts b/code/packages/sdk/src/nodes/line/types.ts new file mode 100644 index 000000000..6617f67be --- /dev/null +++ b/code/packages/sdk/src/nodes/line/types.ts @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +// +// SPDX-License-Identifier: Apache-2.0 + +import type { WeaveNodeTransformerProperties } from '@inditextech/weave-types'; + +export type WeaveLineProperties = { + transform: WeaveNodeTransformerProperties; +}; + +export type WeaveLineNodeParams = { + config: Partial; +}; diff --git a/code/packages/sdk/src/nodes/node-extensions.d.ts b/code/packages/sdk/src/nodes/node-extensions.d.ts index a2138a340..1e9bbd38f 100644 --- a/code/packages/sdk/src/nodes/node-extensions.d.ts +++ b/code/packages/sdk/src/nodes/node-extensions.d.ts @@ -3,9 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 import 'konva'; +import type { Vector2d } from 'konva/lib/types'; declare module 'konva/lib/Node' { interface Node { getTransformerProperties(): WeaveNodeTransformerProperties; + updatePosition(position: Vector2d): void; } } diff --git a/code/packages/sdk/src/nodes/node.ts b/code/packages/sdk/src/nodes/node.ts index 91bb4c4ac..63a83030a 100644 --- a/code/packages/sdk/src/nodes/node.ts +++ b/code/packages/sdk/src/nodes/node.ts @@ -9,6 +9,8 @@ import { type WeaveStateElement, type WeaveNodeBase, WEAVE_NODE_CUSTOM_EVENTS, + type WeaveNodeConfiguration, + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, } from '@inditextech/weave-types'; import { type Logger } from 'pino'; import { WeaveNodesSelectionPlugin } from '@/plugins/nodes-selection/nodes-selection'; @@ -22,14 +24,19 @@ import { } from '@/utils'; import type { WeaveNodesSnappingPlugin } from '@/plugins/nodes-snapping/nodes-snapping'; import './node-extensions.d'; -import { DEFAULT_ANCHORS_ENABLED } from './constants'; -Konva.Node.prototype.getTransformerProperties = function () { - return { - rotateEnabled: true, - resizeEnabled: true, - enabledAnchors: DEFAULT_ANCHORS_ENABLED, +export const setNodesDefaultConfiguration = ( + config?: WeaveNodeConfiguration +): void => { + const { transform } = config ?? {}; + + Konva.Node.prototype.getTransformerProperties = function () { + return { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...transform, + }; }; + Konva.Node.prototype.updatePosition = function () {}; }; export abstract class WeaveNode implements WeaveNodeBase { diff --git a/code/packages/sdk/src/nodes/rectangle/rectangle.ts b/code/packages/sdk/src/nodes/rectangle/rectangle.ts index f66fb6b27..f86196827 100644 --- a/code/packages/sdk/src/nodes/rectangle/rectangle.ts +++ b/code/packages/sdk/src/nodes/rectangle/rectangle.ts @@ -4,21 +4,44 @@ import Konva from 'konva'; import { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, type WeaveElementAttributes, type WeaveElementInstance, } from '@inditextech/weave-types'; import { WeaveNode } from '../node'; import { WEAVE_RECTANGLE_NODE_TYPE } from './constants'; +import type { + WeaveRectangleNodeParams, + WeaveRectangleProperties, +} from './types'; export class WeaveRectangleNode extends WeaveNode { + private config: WeaveRectangleProperties; protected nodeType: string = WEAVE_RECTANGLE_NODE_TYPE; + constructor(params?: WeaveRectangleNodeParams) { + super(); + + const { config } = params ?? {}; + + this.config = { + transform: { + ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...config?.transform, + }, + }; + } + onRender(props: WeaveElementAttributes): WeaveElementInstance { const rectangle = new Konva.Rect({ ...props, name: 'node', }); + rectangle.getTransformerProperties = () => { + return this.config.transform; + }; + this.setupDefaultNodeEvents(rectangle); return rectangle; diff --git a/code/packages/sdk/src/nodes/rectangle/types.ts b/code/packages/sdk/src/nodes/rectangle/types.ts new file mode 100644 index 000000000..020a63b44 --- /dev/null +++ b/code/packages/sdk/src/nodes/rectangle/types.ts @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +// +// SPDX-License-Identifier: Apache-2.0 + +import { type WeaveNodeTransformerProperties } from '@inditextech/weave-types'; + +export type WeaveRectangleProperties = { + transform: WeaveNodeTransformerProperties; +}; + +export type WeaveRectangleNodeParams = { + config: Partial; +}; diff --git a/code/packages/sdk/src/nodes/text/text.ts b/code/packages/sdk/src/nodes/text/text.ts index c55b97b69..3a7b97c4b 100644 --- a/code/packages/sdk/src/nodes/text/text.ts +++ b/code/packages/sdk/src/nodes/text/text.ts @@ -4,6 +4,7 @@ import Konva from 'konva'; import { + WEAVE_DEFAULT_TRANSFORM_PROPERTIES, type WeaveElementAttributes, type WeaveElementInstance, type WeaveStateElement, @@ -15,14 +16,25 @@ import { resetScale } from '@/utils'; import { WEAVE_TEXT_NODE_TYPE } from './constants'; import { SELECTION_TOOL_ACTION_NAME } from '@/actions/selection-tool/constants'; import { TEXT_LAYOUT } from '@/actions/text-tool/constants'; +import type { WeaveTextNodeParams, WeaveTextProperties } from './types'; export class WeaveTextNode extends WeaveNode { + private config: WeaveTextProperties; protected nodeType: string = WEAVE_TEXT_NODE_TYPE; private editing: boolean = false; - constructor() { + constructor(params?: WeaveTextNodeParams) { super(); + const { config } = params ?? {}; + + this.config = { + transform: { + ...WEAVE_DEFAULT_TRANSFORM_PROPERTIES, + ...config?.transform, + }, + }; + this.editing = false; } @@ -39,6 +51,10 @@ export class WeaveTextNode extends WeaveNode { name: 'node', }); + text.getTransformerProperties = () => { + return this.config.transform; + }; + text.setAttrs({ measureMultilineText: this.measureMultilineText(text), }); diff --git a/code/packages/sdk/src/nodes/text/types.ts b/code/packages/sdk/src/nodes/text/types.ts index f71541b5d..dd220d583 100644 --- a/code/packages/sdk/src/nodes/text/types.ts +++ b/code/packages/sdk/src/nodes/text/types.ts @@ -3,10 +3,21 @@ // SPDX-License-Identifier: Apache-2.0 import Konva from 'konva'; -import { type NodeSerializable } from '@inditextech/weave-types'; +import { + type NodeSerializable, + type WeaveNodeTransformerProperties, +} from '@inditextech/weave-types'; export type TextSerializable = Konva.TextConfig & NodeSerializable & { type: 'text'; id: string; }; + +export type WeaveTextProperties = { + transform: WeaveNodeTransformerProperties; +}; + +export type WeaveTextNodeParams = { + config: Partial; +}; diff --git a/code/packages/sdk/src/nodes/types.ts b/code/packages/sdk/src/nodes/types.ts deleted file mode 100644 index 78672b3cf..000000000 --- a/code/packages/sdk/src/nodes/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) -// -// SPDX-License-Identifier: Apache-2.0 - -export type WeaveNodeTransformerProperties = { - rotateEnabled: boolean; - resizeEnabled: boolean; - enabledAnchors: string[]; -}; diff --git a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts index 72bfd7dfa..8ebeaeedb 100644 --- a/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts +++ b/code/packages/sdk/src/plugins/nodes-selection/nodes-selection.ts @@ -83,7 +83,7 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { anchor.offsetX(4); } }, - borderStroke: '#1e40afff', + borderStroke: '#0074ffcc', ...config?.transformer, }, transformations: { @@ -186,7 +186,35 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { } }); + tr.on('transformstart', () => { + this.triggerSelectedNodesEvent(); + }); + + tr.on('transform', () => { + this.triggerSelectedNodesEvent(); + }); + + tr.on('transformend', () => { + this.triggerSelectedNodesEvent(); + }); + + tr.on('dragstart', (e) => { + for (const node of tr.nodes()) { + node.updatePosition(e.target.getAbsolutePosition()); + } + + tr.forceUpdate(); + + e.cancelBubble = true; + }); + tr.on('dragmove', (e) => { + for (const node of tr.nodes()) { + node.updatePosition(e.target.getAbsolutePosition()); + } + + e.cancelBubble = true; + if (this.isSelecting() && tr.nodes().length > 1) { clearContainerTargets(this.instance); @@ -207,9 +235,17 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { ); } } + + tr.forceUpdate(); }); - tr.on('dragend', () => { + tr.on('dragend', (e) => { + for (const node of tr.nodes()) { + node.updatePosition(e.target.getAbsolutePosition()); + } + + e.cancelBubble = true; + if (this.isSelecting() && tr.nodes().length > 1) { clearContainerTargets(this.instance); @@ -228,6 +264,8 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { ); } } + + tr.forceUpdate(); }); this.tr = tr; @@ -447,9 +485,16 @@ export class WeaveNodesSelectionPlugin extends WeavePlugin { }); const box = this.selectionRectangle.getClientRect(); const selected = shapes.filter((shape) => { - const parent = this.instance.getInstanceRecursive( + let parent = this.instance.getInstanceRecursive( shape.getParent() as Konva.Node ); + + if (parent.getAttrs().nodeId) { + parent = this.instance + .getStage() + .findOne(`#${parent.getAttrs().nodeId}`) as Konva.Node; + } + if ( shape.getAttrs().nodeType && shape.getAttrs().nodeType === 'frame' diff --git a/code/packages/sdk/src/plugins/nodes-snapping/nodes-snapping.ts b/code/packages/sdk/src/plugins/nodes-snapping/nodes-snapping.ts index b3ef99cff..9d6530732 100644 --- a/code/packages/sdk/src/plugins/nodes-snapping/nodes-snapping.ts +++ b/code/packages/sdk/src/plugins/nodes-snapping/nodes-snapping.ts @@ -99,6 +99,14 @@ export class WeaveNodesSnappingPlugin extends WeavePlugin { }; } + deleteGuides(): void { + const utilityLayer = this.instance.getUtilityLayer(); + + if (utilityLayer) { + utilityLayer.find(`.${GUIDE_LINE_NAME}`).forEach((l) => l.destroy()); + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any evaluateGuidelines(e: KonvaEventObject): void { const utilityLayer = this.instance.getUtilityLayer(); @@ -119,22 +127,20 @@ export class WeaveNodesSnappingPlugin extends WeavePlugin { if ( e.type === 'dragmove' && nodesSelectionPlugin && - e.target instanceof Konva.Transformer && - e.target.getNodes().length === 1 + nodesSelectionPlugin.getTransformer().nodes().length === 1 ) { - const actualTarget: Konva.Transformer = - e.target as unknown as Konva.Transformer; - node = actualTarget.getNodes()[0]; + node = nodesSelectionPlugin.getTransformer().nodes()[0]; skipNodes.push(node.getAttrs().id ?? ''); } if ( e.type === 'dragmove' && nodesSelectionPlugin && - e.target instanceof Konva.Transformer && - e.target.getNodes().length > 1 + nodesSelectionPlugin.getTransformer().nodes().length > 1 ) { - const { nodes } = this.getSelectedNodesMetadata(e.target); - node = e.target; + const { nodes } = this.getSelectedNodesMetadata( + nodesSelectionPlugin.getTransformer() + ); + node = nodesSelectionPlugin.getTransformer(); skipNodes = [...nodes]; } if (e.type === 'transform') { @@ -197,9 +203,11 @@ export class WeaveNodesSnappingPlugin extends WeavePlugin { }; n.setAbsolutePosition(newPos); + // n.fire('dragmove', { target: n, absPos }, true); }); } else { node.absolutePosition(absPos); + // node.fire('dragmove', { target: node, absPos }, true); } } if (e.type === 'transform') { @@ -449,7 +457,6 @@ export class WeaveNodesSnappingPlugin extends WeavePlugin { drawGuides(guides: Guide[]): void { const stage = this.instance.getStage(); - // const mainLayer = this.instance.getMainLayer(); const utilityLayer = this.instance.getUtilityLayer(); if (utilityLayer) { diff --git a/code/packages/sdk/src/weave.ts b/code/packages/sdk/src/weave.ts index 8ccefbfe0..177992d2a 100644 --- a/code/packages/sdk/src/weave.ts +++ b/code/packages/sdk/src/weave.ts @@ -22,9 +22,10 @@ import { type WeaveSerializedGroup, type WeaveFont, type WeaveNodeFound, + type WeaveNodeConfiguration, } from '@inditextech/weave-types'; import { WeaveStore } from './stores/store'; -import { WeaveNode } from './nodes/node'; +import { setNodesDefaultConfiguration, WeaveNode } from './nodes/node'; import { WeaveAction } from './actions/action'; import { WeavePlugin } from './plugins/plugin'; import { WeaveReconciler } from './reconciler/reconciler'; @@ -171,6 +172,7 @@ export class Weave extends Emittery { // Register all the nodes, plugins and actions that come from the configuration this.registerManager.registerNodesHandlers(); + this.setNodesDefaultConfiguration(); this.registerManager.registerPlugins(); this.registerManager.registerActionsHandlers(); @@ -225,6 +227,10 @@ export class Weave extends Emittery { return this.config; } + setNodesDefaultConfiguration(config?: WeaveNodeConfiguration): void { + setNodesDefaultConfiguration(config); + } + // EVENTS METHODS emitEvent(event: string, payload?: T): void { diff --git a/code/packages/types/src/constants.ts b/code/packages/types/src/constants.ts index bbdc9aead..1856f8ce0 100644 --- a/code/packages/types/src/constants.ts +++ b/code/packages/types/src/constants.ts @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: Apache-2.0 +import type { WeaveNodeTransformerProperties } from './types'; + export const WEAVE_NODE_LAYER_ID = 'mainLayer'; export const WEAVE_AWARENESS_LAYER_ID = 'usersPointersLayer'; export const WEAVE_UTILITY_LAYER_ID = 'utilityLayer'; @@ -42,3 +44,27 @@ export const WEAVE_NODE_CUSTOM_EVENTS = { onTargetEnter: 'onTargetEnter', onTargetLeave: 'onTargetLeave', } as const; + +export const WEAVE_TRANSFORMER_ANCHORS = { + ['TOP_LEFT']: 'top-left', + ['TOP_CENTER']: 'top-center', + ['TOP_RIGHT']: 'top-right', + ['MIDDLE_RIGHT']: 'middle-right', + ['MIDDLE_LEFT']: 'middle-left', + ['BOTTOM_LEFT']: 'bottom-left', + ['BOTTOM_CENTER']: 'bottom-center', + ['BOTTOM_RIGHT']: 'bottom-right', +}; + +export const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +export const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = + { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, + }; diff --git a/code/packages/types/src/types.ts b/code/packages/types/src/types.ts index 0384edb63..92a734066 100644 --- a/code/packages/types/src/types.ts +++ b/code/packages/types/src/types.ts @@ -10,6 +10,7 @@ import { WEAVE_EXPORT_FILE_FORMAT, WEAVE_INSTANCE_STATUS, WEAVE_NODE_POSITION, + WEAVE_TRANSFORMER_ANCHORS, } from './constants'; import { type WeaveNodeBase } from '@/base/node'; import { type WeaveActionBase } from '@/base/action'; @@ -216,3 +217,16 @@ export declare function crdtDoc( doc: Y.Doc, typeDescription: T ): MappedTypeDescription; + +// Configuration + +export type WeaveTransformerAnchorsKeys = + keyof typeof WEAVE_TRANSFORMER_ANCHORS; +export type WeaveTransformerAnchors = + (typeof WEAVE_TRANSFORMER_ANCHORS)[WeaveTransformerAnchorsKeys]; + +export type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +export type WeaveNodeConfiguration = { + transform: Partial; +}; diff --git a/docs/content/docs/main/changelog/prerelease/0.20.0.mdx b/docs/content/docs/main/changelog/prerelease/0.20.0.mdx index eb91b49a2..272bfe5f7 100644 --- a/docs/content/docs/main/changelog/prerelease/0.20.0.mdx +++ b/docs/content/docs/main/changelog/prerelease/0.20.0.mdx @@ -12,6 +12,10 @@ description: Selection & grouping bugfixes - [#305](https://github.com/InditexTech/weavejs/issues/305) Don't allow to transform when more than one element is selected - [#308](https://github.com/InditexTech/weavejs/issues/308) Allow to configure transformer configuration per node +### Changed + +- [#219](https://github.com/InditexTech/weavejs/issues/219) Improve frame + ### Fixed - [#291](https://github.com/InditexTech/weavejs/issues/291) Group of elements moving not maintaining position (all layers) diff --git a/docs/content/docs/sdk/api-reference/nodes/frame.mdx b/docs/content/docs/sdk/api-reference/nodes/frame.mdx index 51b0ae513..0af375539 100644 --- a/docs/content/docs/sdk/api-reference/nodes/frame.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/frame.mdx @@ -123,6 +123,8 @@ type WeaveFrameNodeSizesInfo = { }; }; +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + type WeaveFrameProperties = { fontFamily: string; fontStyle: string; @@ -137,6 +139,7 @@ type WeaveFrameProperties = { borderColor: string; fill: string; }; + transform: WeaveNodeTransformerProperties; }; type WeaveFrameAttributes = WeaveElementAttributes & { @@ -173,51 +176,57 @@ For `WeaveFrameProperties`: ["fontFamily"]: { description: "The font family to use on the frame title.", type: "string", - default: "Arial", + default: "check default values", }, ["fontStyle"]: { description: "The font style to use on the frame title.", type: "string", - default: "normal", + default: "check default values", }, ["titleHeight"]: { description: "The height of the title (px) to use on the frame.", type: "number", - default: "30", + default: "check default values", }, ["borderWidth"]: { description: "The border width (px) of the frame.", type: "number", - default: "2", + default: "check default values", }, ["borderColor"]: { description: "The border color (HEX with alpha) of the frame.", type: "string", - default: "#000000ff", + default: "#000check default values0ff", }, ["onTargetLeave.borderColor"]: { description: "The border color (HEX with alpha) of the frame when no target is added.", type: "string", - default: "#000000ff", + default: "check default values", }, ["onTargetLeave.fill"]: { description: "The frame background color (HEX with alpha) of the frame when no target is added.", type: "string", - default: "#ffffffff", + default: "check default values", }, ["onTargetEnter.borderColor"]: { description: "The border color (HEX with alpha) of the frame when a target is going to be added.", type: "string", - default: "#ff6863ff", + default: "check default values", }, ["onTargetEnter.fill"]: { description: "The frame background color (HEX with alpha) of the frame when a target going to be added.", type: "string", - default: "#ecececff", + default: "check default values", + }, + ["transform"]: { + description: + "Setup the transform properties for the frame (if can be resized, rotated, anchors, etc.).", + type: "object", + default: "check default values", }, }} /> @@ -230,14 +239,21 @@ const WEAVE_FRAME_NODE_DEFAULT_CONFIG = { fontStyle: "normal", titleHeight: 30, borderColor: "#000000ff", - borderWidth: 2, + borderWidth: 1, onTargetLeave: { borderColor: "#000000ff", fill: "#ffffffff", }, onTargetEnter: { borderColor: "#ff6863ff", - fill: "#ecececff", + fill: "#ffffffff", + }, + transform: { + rotateEnabled: false, + resizeEnabled: false, + enabledAnchors: [] as string[], + borderStrokeWidth: 3, + padding: 0, }, }; diff --git a/docs/content/docs/sdk/api-reference/nodes/group.mdx b/docs/content/docs/sdk/api-reference/nodes/group.mdx index d0fdaf54f..34d899f54 100644 --- a/docs/content/docs/sdk/api-reference/nodes/group.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/group.mdx @@ -3,6 +3,8 @@ title: WeaveGroupNode description: Group node API Reference --- +import { TypeTable } from "fumadocs-ui/components/type-table"; + ## Overview The [WeaveGroupNode](https://github.com/InditexTech/weavejs/blob/main/code/packages/sdk/src/nodes/group/group.ts) @@ -34,5 +36,73 @@ import { WeaveGroupNode } from "@inditextech/weave-sdk"; ## Instantiation ```ts -new WeaveGroupNode(); +new WeaveGroupNode(params?: WeaveGroupNodeParams); +``` + +## TypeScript types + +```ts +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +type WeaveGroupProperties = { + transform: WeaveNodeTransformerProperties; +}; + +type WeaveGroupNodeParams = { + config: Partial; +}; +``` + +## Parameters + +For `WeaveGroupNodeParams`: + +", + }, + }} +/> + +For `WeaveGroupProperties`: + + + +## Default values + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, +}; ``` diff --git a/docs/content/docs/sdk/api-reference/nodes/image.mdx b/docs/content/docs/sdk/api-reference/nodes/image.mdx index 26becf3c5..54475ad5b 100644 --- a/docs/content/docs/sdk/api-reference/nodes/image.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/image.mdx @@ -3,6 +3,8 @@ title: WeaveImageNode description: Text node API Reference --- +import { TypeTable } from "fumadocs-ui/components/type-table"; + ## Overview The [WeaveImageNode](https://github.com/InditexTech/weavejs/blob/main/code/packages/sdk/src/nodes/image/image.ts) @@ -35,5 +37,73 @@ import { WeaveImageNode } from "@inditextech/weave-sdk"; ## Instantiation ```ts -new WeaveImageNode(); +new WeaveImageNode(params?: WeaveImageNodeParams); +``` + +## TypeScript types + +```ts +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +type WeaveImageProperties = { + transform: WeaveNodeTransformerProperties; +}; + +type WeaveImageNodeParams = { + config: Partial; +}; +``` + +## Parameters + +For `WeaveImageNodeParams`: + +", + }, + }} +/> + +For `WeaveImageProperties`: + + + +## Default values + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, +}; ``` diff --git a/docs/content/docs/sdk/api-reference/nodes/line.mdx b/docs/content/docs/sdk/api-reference/nodes/line.mdx index 5b7f5bd5f..7e459139b 100644 --- a/docs/content/docs/sdk/api-reference/nodes/line.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/line.mdx @@ -3,6 +3,8 @@ title: WeaveLineNode description: Line node API Reference --- +import { TypeTable } from "fumadocs-ui/components/type-table"; + ## Overview The [WeaveLineNode](https://github.com/InditexTech/weavejs/blob/main/code/packages/sdk/src/nodes/line/line.ts) @@ -34,5 +36,73 @@ import { WeaveLineNode } from "@inditextech/weave-sdk"; ## Instantiation ```ts -new WeaveLineNode(); +new WeaveLineNode(params?: WeaveLineNodeParams); +``` + +## TypeScript types + +```ts +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +type WeaveLineProperties = { + transform: WeaveNodeTransformerProperties; +}; + +type WeaveLineNodeParams = { + config: Partial; +}; +``` + +## Parameters + +For `WeaveLineNodeParams`: + +", + }, + }} +/> + +For `WeaveLineProperties`: + + + +## Default values + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, +}; ``` diff --git a/docs/content/docs/sdk/api-reference/nodes/rectangle.mdx b/docs/content/docs/sdk/api-reference/nodes/rectangle.mdx index 16792ff3a..a7a13cd5f 100644 --- a/docs/content/docs/sdk/api-reference/nodes/rectangle.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/rectangle.mdx @@ -3,6 +3,8 @@ title: WeaveRectangleNode description: Rectangle node API Reference --- +import { TypeTable } from "fumadocs-ui/components/type-table"; + ## Overview The [WeaveRectangleNode](https://github.com/InditexTech/weavejs/blob/main/code/packages/sdk/src/nodes/rectangle/rectangle.ts) @@ -33,5 +35,73 @@ import { WeaveRectangleNode } from "@inditextech/weave-sdk"; ## Instantiation ```ts -new WeaveRectangleNode(); +new WeaveRectangleNode(params?: WeaveRectangleNodeParams); +``` + +## TypeScript types + +```ts +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +type WeaveRectangleProperties = { + transform: WeaveNodeTransformerProperties; +}; + +type WeaveRectangleNodeParams = { + config: Partial; +}; +``` + +## Parameters + +For `WeaveRectangleNodeParams`: + +", + }, + }} +/> + +For `WeaveRectangleProperties`: + + + +## Default values + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, +}; ``` diff --git a/docs/content/docs/sdk/api-reference/nodes/text.mdx b/docs/content/docs/sdk/api-reference/nodes/text.mdx index 763d7651f..9727c44b6 100644 --- a/docs/content/docs/sdk/api-reference/nodes/text.mdx +++ b/docs/content/docs/sdk/api-reference/nodes/text.mdx @@ -3,6 +3,8 @@ title: WeaveTextNode description: Text node API Reference --- +import { TypeTable } from "fumadocs-ui/components/type-table"; + ## Overview The [WeaveTextNode](https://github.com/InditexTech/weavejs/blob/main/code/packages/sdk/src/nodes/text/text.ts) @@ -34,5 +36,73 @@ import { WeaveTextNode } from "@inditextech/weave-sdk"; ## Instantiation ```ts -new WeaveTextNode(); +new WeaveTextNode(params?: WeaveTextNodeParams); +``` + +## TypeScript types + +```ts +type WeaveNodeTransformerProperties = Konva.TransformerConfig; + +type WeaveTextProperties = { + transform: WeaveNodeTransformerProperties; +}; + +type WeaveTextNodeParams = { + config: Partial; +}; +``` + +## Parameters + +For `WeaveTextNodeParams`: + +", + }, + }} +/> + +For `WeaveTextProperties`: + + + +## Default values + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const WEAVE_DEFAULT_TRANSFORM_PROPERTIES: WeaveNodeTransformerProperties = { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, +}; ``` diff --git a/docs/content/docs/sdk/api-reference/weave.mdx b/docs/content/docs/sdk/api-reference/weave.mdx index 6744e9762..e90cdff78 100644 --- a/docs/content/docs/sdk/api-reference/weave.mdx +++ b/docs/content/docs/sdk/api-reference/weave.mdx @@ -107,6 +107,45 @@ getId(): string This method gets the id of the Weave instance. +### Instance configuration + +#### setNodesDefaultConfiguration + +```ts +setNodesDefaultConfiguration(config?: WeaveNodeConfiguration): void +``` + +This method set the Node default configuration properties. + +By default: + +```ts +const WEAVE_TRANSFORMER_ANCHORS = { + ["TOP_LEFT"]: "top-left", + ["TOP_CENTER"]: "top-center", + ["TOP_RIGHT"]: "top-right", + ["MIDDLE_RIGHT"]: "middle-right", + ["MIDDLE_LEFT"]: "middle-left", + ["BOTTOM_LEFT"]: "bottom-left", + ["BOTTOM_CENTER"]: "bottom-center", + ["BOTTOM_RIGHT"]: "bottom-right", +}; + +const WEAVE_DEFAULT_ENABLED_ANCHORS: string[] = Object.values( + WEAVE_TRANSFORMER_ANCHORS +); + +const defaultNodeConfig: WeaveNodeConfiguration = { + transform: { + rotateEnabled: true, + resizeEnabled: true, + enabledAnchors: WEAVE_DEFAULT_ENABLED_ANCHORS, + borderStrokeWidth: 3, + padding: 0, + }, +}; +``` + ### Events #### emitEvent