Skip to content

Commit 73b6d92

Browse files
committed
prototyping editing node text via textarea and make size dependant
1 parent 24bf9fb commit 73b6d92

File tree

4 files changed

+113
-33
lines changed

4 files changed

+113
-33
lines changed

apps/vps-web/src/app/custom-nodes/classes/oval-node-class.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class OvalNode extends BaseRectNode {
1111
static readonly category = 'Default test';
1212
static readonly text = 'oval';
1313

14+
childElementSelector = '.child-node-wrapper > *:first-child';
1415
render = (node: FlowNode<NodeInfo>) => {
1516
const nodeInfo = node.nodeInfo as any;
1617
console.log('render rect-node', node.width, node.height);

apps/vps-web/src/app/custom-nodes/classes/rect-node-class.tsx

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,19 @@ w-min h-min
6868
*/
6969
render = (node: FlowNode<NodeInfo>) => {
7070
const nodeInfo = node.nodeInfo as any;
71-
console.log('render rect-node', node.width, node.height);
71+
console.log(
72+
'render rect-node',
73+
node.width,
74+
node.height,
75+
(node?.nodeInfo as any)?.text
76+
);
7277
return (
7378
<div>
7479
<div
7580
getElement={(element: HTMLElement) => {
7681
this.rectElement = element;
7782
}}
78-
class={`rounded justify-center items-center text-center whitespace-pre inline-flex`}
83+
class={`rounded justify-center items-center text-center whitespace-pre inline-flex grow-textarea`}
7984
style={`min-width:${node.width ?? 50}px;min-height:${
8085
node.height ?? 50
8186
}px;background:${nodeInfo?.fillColor ?? 'black'};border: ${
@@ -84,20 +89,7 @@ w-min h-min
8489
nodeInfo?.strokeColor ?? 'white'
8590
}`}
8691
spellcheck="false"
87-
blur={() => {
88-
if (this.rectElement) {
89-
if (this.rectElement.innerHTML.toString().length == 0) {
90-
// hacky solution to prevent caret being aligned to top
91-
this.rectElement.innerHTML = '&nbsp;';
92-
}
93-
}
94-
console.log('blur', this.rectElement?.textContent);
95-
if (this.node?.nodeInfo) {
96-
(this.node.nodeInfo as any).text = this.rectElement?.textContent;
97-
}
98-
this.updated();
99-
}}
100-
contentEditable={true}
92+
contentEditable={false}
10193
pointerdown={(e: PointerEvent) => {
10294
if (e.shiftKey && this.rectElement) {
10395
this.rectElement.contentEditable = 'false';
@@ -109,12 +101,54 @@ w-min h-min
109101
}
110102
}}
111103
>
112-
{nodeInfo?.text ?? ''}
104+
<textarea
105+
class="w-full h-full bg-transparent text-center appearance-none focus-visible:outline-none resize-none"
106+
resize="none"
107+
rows="1"
108+
renderElement={(element: HTMLTextAreaElement) => {
109+
element.value = nodeInfo?.text ?? '';
110+
setTimeout(() => {
111+
element.style.height = 'auto';
112+
console.log('renderElement textarea', element.scrollHeight);
113+
element.style.height = element.scrollHeight + 'px';
114+
}, 0);
115+
}}
116+
input={(event: InputEvent) => {
117+
//w-full h-full
118+
// if (this.rectElement) {
119+
// if (this.rectElement.innerHTML.toString().length == 0) {
120+
// // hacky solution to prevent caret being aligned to top
121+
// this.rectElement.innerHTML = '&nbsp;';
122+
// }
123+
// }
124+
// console.log('blur', this.rectElement?.textContent);
125+
if (
126+
this.node?.nodeInfo &&
127+
this.rectElement &&
128+
(event?.target as HTMLTextAreaElement)?.value
129+
) {
130+
console.log(
131+
'textarea input',
132+
(event?.target as HTMLTextAreaElement)?.value
133+
);
134+
const value = (event?.target as HTMLTextAreaElement)?.value;
135+
136+
(this.node.nodeInfo as any).text = value;
137+
const textarea = event.target as HTMLTextAreaElement;
138+
textarea.style.height = 'auto';
139+
textarea.style.height = textarea.scrollHeight + 'px';
140+
if (this.onResize) {
141+
this.onResize(this.node.width ?? 10, textarea.scrollHeight);
142+
}
143+
}
144+
this.updated();
145+
}}
146+
></textarea>
113147
</div>
114148
</div>
115149
);
116150
};
117-
151+
onResize: ((width: number, height: number) => void) | undefined = undefined;
118152
setSize = (width: number, height: number) => {
119153
if (this.rectElement) {
120154
this.rectElement.style.width = `${width}px`;

apps/vps-web/src/app/custom-nodes/rect-node.tsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,7 @@ export const getRectNode =
5050
const computeAsync = (input: string, loopIndex?: number, payload?: any) => {
5151
return rectNode.compute(input, loopIndex, payload).then((result) => {
5252
if (rect && rect.resize) {
53-
rect.resize(
54-
undefined,
55-
true,
56-
'.child-node-wrapper > *:first-child',
57-
true
58-
);
53+
rect.resize(undefined, true, rectNode.childElementSelector, true);
5954
}
6055
return result;
6156
});
@@ -122,6 +117,28 @@ export const getRectNode =
122117
rectNode = new NodeClass(node.id, updated, node);
123118
rectNode.rectInstance = rect;
124119
rectNode.canvasAppInstance = nodeInstance.contextInstance;
120+
rectNode.onResize = (width: number, height: number) => {
121+
const newHeight =
122+
height > (node.height ?? 10) ? height : node.height ?? 10;
123+
console.log('RECT RESIZE via onResize', width, newHeight);
124+
node.width = width;
125+
node.height = newHeight;
126+
node.isSettingSize = true;
127+
rectNode.setSize(width, newHeight);
128+
129+
rect?.resize(
130+
width,
131+
true,
132+
rectNode.childElementSelector,
133+
true,
134+
newHeight,
135+
true
136+
);
137+
nodeInstance.contextInstance?.nodeTransformer.resizeNodeTransformer(
138+
width,
139+
newHeight
140+
);
141+
};
125142
rectNode.createRunCounterContext = createRunCounterContext;
126143
if (rectNode.getSettingsPopup) {
127144
if (!node.nodeInfo) {
@@ -146,7 +163,7 @@ export const getRectNode =
146163
renderElement(rectNode.render(flowNodeInstance), childNodeWrapper);
147164
nodeRenderElement = (
148165
rect?.nodeComponent?.domElement as HTMLElement
149-
).querySelector('.child-node-wrapper > *:first-child');
166+
).querySelector(rectNode.childElementSelector);
150167
if (nodeRenderElement) {
151168
rectNode.nodeRenderElement = nodeRenderElement;
152169
const resizeObserver = new ResizeObserver(() => {
@@ -159,12 +176,7 @@ export const getRectNode =
159176
rectNode.setSize(node.width ?? 10, node.height ?? 10);
160177
return;
161178
}
162-
rect.resize(
163-
undefined,
164-
true,
165-
'.child-node-wrapper > *:first-child',
166-
true
167-
);
179+
rect.resize(undefined, true, rectNode.childElementSelector, true);
168180
}
169181
});
170182
resizeObserver.observe(nodeRenderElement);
@@ -184,7 +196,7 @@ export const getRectNode =
184196
rect.resize(
185197
undefined,
186198
true,
187-
'.child-node-wrapper > *:first-child',
199+
rectNode.childElementSelector,
188200
true
189201
);
190202
if (result) {

libs/visual-programming-system/src/components/rect.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,47 @@ export class Rect<T extends BaseNodeInfo> {
461461
width?: number,
462462
overrideStaticWidthHeight?: boolean,
463463
selectChildElemenSelectorAsReference?: string,
464-
centerToYPositionThumb?: boolean
464+
centerToYPositionThumb?: boolean,
465+
height?: number,
466+
forceWidthHeight?: boolean
465467
) {
466468
if (
467469
(this.hasStaticWidthHeight && !overrideStaticWidthHeight) ||
468470
!this.nodeComponent
469471
) {
470472
return;
471473
}
474+
if (forceWidthHeight) {
475+
const oldHeight = this.nodeComponent.height;
476+
this.nodeComponent.width = width ?? this.nodeComponent.width;
477+
this.nodeComponent.height = height ?? this.nodeComponent.height;
478+
this.points.width = this.nodeComponent.width ?? this.points.width;
479+
this.points.height = this.nodeComponent.height ?? this.points.height;
480+
481+
const rectContainerDOMElement = this.nodeComponent
482+
.domElement as unknown as HTMLElement;
483+
if (!this.autSizeToContentIfNodeHasNoThumbs) {
484+
rectContainerDOMElement.style.width = `${this.points.width}px`;
485+
rectContainerDOMElement.style.height = `${this.points.height}px`;
486+
}
487+
488+
if (centerToYPositionThumb) {
489+
this.nodeComponent.y =
490+
this.nodeComponent.y + (oldHeight ?? 0) / 2 - this.points.height / 2;
491+
}
492+
if (this.nodeComponent.update) {
493+
this.nodeComponent.update(
494+
this.nodeComponent,
495+
this.nodeComponent.x,
496+
this.nodeComponent.y,
497+
this.nodeComponent
498+
);
499+
}
500+
return {
501+
width: this.points.width,
502+
height: this.points.height,
503+
};
504+
}
472505
const oldHeight = this.nodeComponent.height;
473506
const { scale } = getCamera();
474507
if (this.nodeComponent.thumbConnectors) {

0 commit comments

Comments
 (0)