@elicdavis/node-flow 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +294 -212
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +294 -212
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/graph.ts +7 -3
- package/src/input.ts +6 -8
- package/src/node.ts +53 -1
- package/src/port.ts +6 -1
- package/src/theme.ts +179 -179
- package/src/widgets/hidden_ports.ts +49 -0
- package/test/hidden_port.test.ts +6 -5
- package/test/hidden_ports_toggle.test.ts +102 -0
- package/test/pinch_zoom.test.ts +78 -0
package/dist/index.d.mts
CHANGED
|
@@ -227,9 +227,11 @@ declare class Port {
|
|
|
227
227
|
slots(): number;
|
|
228
228
|
setHidden(hidden: boolean): void;
|
|
229
229
|
/**
|
|
230
|
-
* A port asked to hide still shows while anything is connected to it
|
|
230
|
+
* A port asked to hide still shows while anything is connected to it,
|
|
231
|
+
* and while its node is showing its hidden ports.
|
|
231
232
|
*/
|
|
232
233
|
hidden(): boolean;
|
|
234
|
+
tucked(): boolean;
|
|
233
235
|
addConnectionRemovedListener(callback: ConnectionChangeCallback): void;
|
|
234
236
|
clearConnection(connection: Connection): void;
|
|
235
237
|
getDataType(): string;
|
|
@@ -644,6 +646,9 @@ declare class FlowNode {
|
|
|
644
646
|
calculateBounds(ctx: CanvasRenderingContext2D, camera: Camera): Box;
|
|
645
647
|
addInput(config: PortConfig): Port;
|
|
646
648
|
addOutput(config: PortConfig): Port;
|
|
649
|
+
hiddenPortsShown(): boolean;
|
|
650
|
+
setHiddenPortsShown(shown: boolean): void;
|
|
651
|
+
hiddenPortCount(): number;
|
|
647
652
|
addWidget(widget: Widget): void;
|
|
648
653
|
insertWidget(index: number, widget: Widget): void;
|
|
649
654
|
removeWidget(widget: Widget): void;
|
|
@@ -1089,7 +1094,7 @@ declare const defaults: {
|
|
|
1089
1094
|
};
|
|
1090
1095
|
type ThemeValues = typeof defaults;
|
|
1091
1096
|
type DeepPartial<T> = {
|
|
1092
|
-
[K in keyof T]?: T[K] extends
|
|
1097
|
+
[K in keyof T]?: T[K] extends BevelColors | null ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
1093
1098
|
};
|
|
1094
1099
|
type ThemeConfig = DeepPartial<ThemeValues>;
|
|
1095
1100
|
declare const DefaultTheme: Readonly<ThemeValues>;
|
package/dist/index.d.ts
CHANGED
|
@@ -227,9 +227,11 @@ declare class Port {
|
|
|
227
227
|
slots(): number;
|
|
228
228
|
setHidden(hidden: boolean): void;
|
|
229
229
|
/**
|
|
230
|
-
* A port asked to hide still shows while anything is connected to it
|
|
230
|
+
* A port asked to hide still shows while anything is connected to it,
|
|
231
|
+
* and while its node is showing its hidden ports.
|
|
231
232
|
*/
|
|
232
233
|
hidden(): boolean;
|
|
234
|
+
tucked(): boolean;
|
|
233
235
|
addConnectionRemovedListener(callback: ConnectionChangeCallback): void;
|
|
234
236
|
clearConnection(connection: Connection): void;
|
|
235
237
|
getDataType(): string;
|
|
@@ -644,6 +646,9 @@ declare class FlowNode {
|
|
|
644
646
|
calculateBounds(ctx: CanvasRenderingContext2D, camera: Camera): Box;
|
|
645
647
|
addInput(config: PortConfig): Port;
|
|
646
648
|
addOutput(config: PortConfig): Port;
|
|
649
|
+
hiddenPortsShown(): boolean;
|
|
650
|
+
setHiddenPortsShown(shown: boolean): void;
|
|
651
|
+
hiddenPortCount(): number;
|
|
647
652
|
addWidget(widget: Widget): void;
|
|
648
653
|
insertWidget(index: number, widget: Widget): void;
|
|
649
654
|
removeWidget(widget: Widget): void;
|
|
@@ -1089,7 +1094,7 @@ declare const defaults: {
|
|
|
1089
1094
|
};
|
|
1090
1095
|
type ThemeValues = typeof defaults;
|
|
1091
1096
|
type DeepPartial<T> = {
|
|
1092
|
-
[K in keyof T]?: T[K] extends
|
|
1097
|
+
[K in keyof T]?: T[K] extends BevelColors | null ? T[K] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
1093
1098
|
};
|
|
1094
1099
|
type ThemeConfig = DeepPartial<ThemeValues>;
|
|
1095
1100
|
declare const DefaultTheme: Readonly<ThemeValues>;
|
package/dist/index.js
CHANGED
|
@@ -805,7 +805,7 @@ var ContextMenu = class _ContextMenu {
|
|
|
805
805
|
// src/input.ts
|
|
806
806
|
var LONG_PRESS_MS = 500;
|
|
807
807
|
var LONG_PRESS_SLOP = 12;
|
|
808
|
-
var
|
|
808
|
+
var WHEEL_ZOOM_PER_PIXEL = 5e-4;
|
|
809
809
|
var SUPPRESS_MOUSE_MS = 600;
|
|
810
810
|
var MouseObserver = class {
|
|
811
811
|
#clicked;
|
|
@@ -903,13 +903,12 @@ var MouseObserver = class {
|
|
|
903
903
|
} else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
|
904
904
|
dy *= this.#ele.clientHeight;
|
|
905
905
|
}
|
|
906
|
-
|
|
907
|
-
if (amount === 0) {
|
|
906
|
+
if (dy === 0) {
|
|
908
907
|
return;
|
|
909
908
|
}
|
|
910
909
|
const anchor = this.#mousePos(event);
|
|
911
910
|
this.#moveCallback(anchor);
|
|
912
|
-
this.#zoomCallback(
|
|
911
|
+
this.#zoomCallback(Math.exp(-dy * WHEEL_ZOOM_PER_PIXEL), anchor);
|
|
913
912
|
}
|
|
914
913
|
#move(event) {
|
|
915
914
|
if (this.#fromTouch()) {
|
|
@@ -985,7 +984,7 @@ var MouseObserver = class {
|
|
|
985
984
|
const anchor = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
986
985
|
if (this.#pinchDist > 0) {
|
|
987
986
|
this.#moveCallback(anchor);
|
|
988
|
-
this.#zoomCallback(
|
|
987
|
+
this.#zoomCallback(dist / this.#pinchDist, anchor);
|
|
989
988
|
}
|
|
990
989
|
this.#pinchDist = dist;
|
|
991
990
|
return;
|
|
@@ -1835,9 +1834,13 @@ var Port = class {
|
|
|
1835
1834
|
}
|
|
1836
1835
|
}
|
|
1837
1836
|
/**
|
|
1838
|
-
* A port asked to hide still shows while anything is connected to it
|
|
1837
|
+
* A port asked to hide still shows while anything is connected to it,
|
|
1838
|
+
* and while its node is showing its hidden ports.
|
|
1839
1839
|
*/
|
|
1840
1840
|
hidden() {
|
|
1841
|
+
return this.tucked() && !(this.#node?.hiddenPortsShown() ?? false);
|
|
1842
|
+
}
|
|
1843
|
+
tucked() {
|
|
1841
1844
|
return this.#hidden && this.#connections.length === 0;
|
|
1842
1845
|
}
|
|
1843
1846
|
addConnectionRemovedListener(callback) {
|
|
@@ -1939,117 +1942,6 @@ var Port = class {
|
|
|
1939
1942
|
}
|
|
1940
1943
|
};
|
|
1941
1944
|
|
|
1942
|
-
// src/styles/stroke.ts
|
|
1943
|
-
function StrokeStyleWithFallback(input, fallback) {
|
|
1944
|
-
return {
|
|
1945
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1946
|
-
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
var StrokeStyle = class {
|
|
1950
|
-
#size;
|
|
1951
|
-
#color;
|
|
1952
|
-
constructor(config) {
|
|
1953
|
-
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
1954
|
-
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
1955
|
-
}
|
|
1956
|
-
setupStyle(ctx, scale) {
|
|
1957
|
-
ctx.strokeStyle = this.#color;
|
|
1958
|
-
ctx.lineWidth = scale * this.#size;
|
|
1959
|
-
}
|
|
1960
|
-
setColor(newColor) {
|
|
1961
|
-
this.#color = newColor;
|
|
1962
|
-
}
|
|
1963
|
-
setSize(newSize) {
|
|
1964
|
-
this.#size = newSize;
|
|
1965
|
-
}
|
|
1966
|
-
size() {
|
|
1967
|
-
return this.#size;
|
|
1968
|
-
}
|
|
1969
|
-
};
|
|
1970
|
-
|
|
1971
|
-
// src/styles/box.ts
|
|
1972
|
-
function BoxStyleWithFallback(input, fallback) {
|
|
1973
|
-
return {
|
|
1974
|
-
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
1975
|
-
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
1976
|
-
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
var BoxStyle = class {
|
|
1980
|
-
#border;
|
|
1981
|
-
#color;
|
|
1982
|
-
#radius;
|
|
1983
|
-
constructor(config) {
|
|
1984
|
-
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
1985
|
-
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
1986
|
-
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
1987
|
-
}
|
|
1988
|
-
#box(ctx, box, scale, radius) {
|
|
1989
|
-
ctx.fillStyle = this.#color;
|
|
1990
|
-
this.#border?.setupStyle(ctx, scale);
|
|
1991
|
-
ctx.beginPath();
|
|
1992
|
-
ctx.roundRect(
|
|
1993
|
-
box.Position.x,
|
|
1994
|
-
box.Position.y,
|
|
1995
|
-
box.Size.x,
|
|
1996
|
-
box.Size.y,
|
|
1997
|
-
radius
|
|
1998
|
-
);
|
|
1999
|
-
ctx.fill();
|
|
2000
|
-
}
|
|
2001
|
-
#draw(ctx, box, scale, radius) {
|
|
2002
|
-
this.#box(ctx, box, scale, radius);
|
|
2003
|
-
ctx.stroke();
|
|
2004
|
-
}
|
|
2005
|
-
Outline(ctx, box, scale, radius) {
|
|
2006
|
-
this.#border?.setupStyle(ctx, scale);
|
|
2007
|
-
ctx.beginPath();
|
|
2008
|
-
ctx.roundRect(
|
|
2009
|
-
box.Position.x,
|
|
2010
|
-
box.Position.y,
|
|
2011
|
-
box.Size.x,
|
|
2012
|
-
box.Size.y,
|
|
2013
|
-
radius
|
|
2014
|
-
);
|
|
2015
|
-
ctx.stroke();
|
|
2016
|
-
}
|
|
2017
|
-
Draw(ctx, box, scale) {
|
|
2018
|
-
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
2019
|
-
}
|
|
2020
|
-
DrawRoundedTopOnly(ctx, box, scale) {
|
|
2021
|
-
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2022
|
-
}
|
|
2023
|
-
DrawUnderline(ctx, box, scale) {
|
|
2024
|
-
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2025
|
-
ctx.beginPath();
|
|
2026
|
-
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
2027
|
-
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
2028
|
-
ctx.stroke();
|
|
2029
|
-
}
|
|
2030
|
-
borderSize() {
|
|
2031
|
-
if (this.#border === null) {
|
|
2032
|
-
return 0;
|
|
2033
|
-
}
|
|
2034
|
-
return this.#border.size();
|
|
2035
|
-
}
|
|
2036
|
-
radius() {
|
|
2037
|
-
return this.#radius;
|
|
2038
|
-
}
|
|
2039
|
-
setColor(color) {
|
|
2040
|
-
this.#color = color;
|
|
2041
|
-
}
|
|
2042
|
-
setBorderColor(color) {
|
|
2043
|
-
if (this.#border === null) {
|
|
2044
|
-
this.#border = new StrokeStyle({
|
|
2045
|
-
color
|
|
2046
|
-
});
|
|
2047
|
-
} else {
|
|
2048
|
-
this.#border.setColor(color);
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
};
|
|
2052
|
-
|
|
2053
1945
|
// src/styles/cursor.ts
|
|
2054
1946
|
var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
2055
1947
|
CursorStyle2["Default"] = "default";
|
|
@@ -2071,97 +1963,6 @@ var CursorStyle = /* @__PURE__ */ ((CursorStyle2) => {
|
|
|
2071
1963
|
return CursorStyle2;
|
|
2072
1964
|
})(CursorStyle || {});
|
|
2073
1965
|
|
|
2074
|
-
// src/styles/bevel.ts
|
|
2075
|
-
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2076
|
-
const width2 = Math.max(1, 2 * scale);
|
|
2077
|
-
const half = width2 / 2;
|
|
2078
|
-
const left = box.Position.x + half;
|
|
2079
|
-
const top = box.Position.y + half;
|
|
2080
|
-
const right = box.Position.x + box.Size.x - half;
|
|
2081
|
-
const bottom = box.Position.y + box.Size.y - half;
|
|
2082
|
-
ctx.save();
|
|
2083
|
-
ctx.lineWidth = width2;
|
|
2084
|
-
ctx.lineCap = "square";
|
|
2085
|
-
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2086
|
-
ctx.beginPath();
|
|
2087
|
-
ctx.moveTo(left, bottom);
|
|
2088
|
-
ctx.lineTo(left, top);
|
|
2089
|
-
ctx.lineTo(right, top);
|
|
2090
|
-
ctx.stroke();
|
|
2091
|
-
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2092
|
-
ctx.beginPath();
|
|
2093
|
-
ctx.moveTo(right, top);
|
|
2094
|
-
ctx.lineTo(right, bottom);
|
|
2095
|
-
ctx.lineTo(left, bottom);
|
|
2096
|
-
ctx.stroke();
|
|
2097
|
-
ctx.restore();
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
// src/widgets/field.ts
|
|
2101
|
-
function widgetFont(scale) {
|
|
2102
|
-
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2103
|
-
}
|
|
2104
|
-
function fieldBackground(look) {
|
|
2105
|
-
if (look.background !== void 0) {
|
|
2106
|
-
return look.background;
|
|
2107
|
-
}
|
|
2108
|
-
if (look.input) {
|
|
2109
|
-
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2110
|
-
}
|
|
2111
|
-
if (look.pressed) {
|
|
2112
|
-
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2113
|
-
}
|
|
2114
|
-
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2115
|
-
}
|
|
2116
|
-
function drawFieldBox(ctx, box, scale, look) {
|
|
2117
|
-
ctx.fillStyle = fieldBackground(look);
|
|
2118
|
-
ctx.beginPath();
|
|
2119
|
-
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2120
|
-
ctx.fill();
|
|
2121
|
-
if (Theme.Widget.Border.Size > 0) {
|
|
2122
|
-
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2123
|
-
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2124
|
-
ctx.stroke();
|
|
2125
|
-
}
|
|
2126
|
-
if (Theme.Widget.Bevel !== null) {
|
|
2127
|
-
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
function drawField(ctx, box, scale, look) {
|
|
2131
|
-
drawFieldBox(ctx, box, scale, look);
|
|
2132
|
-
drawFieldText(ctx, box, scale, look);
|
|
2133
|
-
}
|
|
2134
|
-
function drawFieldText(ctx, box, scale, look) {
|
|
2135
|
-
const padding = Theme.Widget.Padding * scale;
|
|
2136
|
-
const middle = box.Position.y + box.Size.y / 2;
|
|
2137
|
-
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2138
|
-
ctx.font = widgetFont(scale);
|
|
2139
|
-
ctx.textBaseline = "middle";
|
|
2140
|
-
if (look.label === void 0 || look.label === "") {
|
|
2141
|
-
ctx.textAlign = "center";
|
|
2142
|
-
ctx.fillStyle = textColor;
|
|
2143
|
-
ctx.fillText(
|
|
2144
|
-
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2145
|
-
box.Position.x + box.Size.x / 2,
|
|
2146
|
-
middle
|
|
2147
|
-
);
|
|
2148
|
-
return;
|
|
2149
|
-
}
|
|
2150
|
-
const room = box.Size.x - padding * 2;
|
|
2151
|
-
const label = fitString(ctx, look.label, room / 2);
|
|
2152
|
-
const labelWidth = ctx.measureText(label).width;
|
|
2153
|
-
ctx.textAlign = "left";
|
|
2154
|
-
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2155
|
-
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2156
|
-
ctx.textAlign = "right";
|
|
2157
|
-
ctx.fillStyle = textColor;
|
|
2158
|
-
ctx.fillText(
|
|
2159
|
-
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2160
|
-
box.Position.x + box.Size.x - padding,
|
|
2161
|
-
middle
|
|
2162
|
-
);
|
|
2163
|
-
}
|
|
2164
|
-
|
|
2165
1966
|
// src/widgets/inplace.ts
|
|
2166
1967
|
var open = /* @__PURE__ */ new Set();
|
|
2167
1968
|
function placeEditsDuring(canvas, draw) {
|
|
@@ -2382,6 +2183,242 @@ function startingWidgetValue(node, property, configured, fallback) {
|
|
|
2382
2183
|
return fallback;
|
|
2383
2184
|
}
|
|
2384
2185
|
|
|
2186
|
+
// src/widgets/hidden_ports.ts
|
|
2187
|
+
var HiddenPortsToggle = class extends WidgetBase {
|
|
2188
|
+
constructor(owner) {
|
|
2189
|
+
super();
|
|
2190
|
+
this.owner = owner;
|
|
2191
|
+
}
|
|
2192
|
+
Size() {
|
|
2193
|
+
return { x: 150, y: 16 };
|
|
2194
|
+
}
|
|
2195
|
+
render(ctx, box, scale) {
|
|
2196
|
+
const label = this.owner.hiddenPortsShown() ? "\u25B4 less" : `\u25BE ${this.owner.hiddenPortCount()} more`;
|
|
2197
|
+
const midY = box.Position.y + box.Size.y / 2;
|
|
2198
|
+
const centerX = box.Position.x + box.Size.x / 2;
|
|
2199
|
+
ctx.font = `${11 * scale}px ${Theme.FontFamily}`;
|
|
2200
|
+
const half = ctx.measureText(label).width / 2 + 6 * scale;
|
|
2201
|
+
ctx.globalAlpha = this.hovered() ? 1 : 0.5;
|
|
2202
|
+
ctx.strokeStyle = Theme.Widget.FontColor;
|
|
2203
|
+
ctx.fillStyle = Theme.Widget.FontColor;
|
|
2204
|
+
ctx.lineWidth = Math.max(1, scale);
|
|
2205
|
+
ctx.beginPath();
|
|
2206
|
+
ctx.moveTo(box.Position.x, midY);
|
|
2207
|
+
ctx.lineTo(centerX - half, midY);
|
|
2208
|
+
ctx.moveTo(centerX + half, midY);
|
|
2209
|
+
ctx.lineTo(box.Position.x + box.Size.x, midY);
|
|
2210
|
+
ctx.stroke();
|
|
2211
|
+
ctx.textAlign = "center";
|
|
2212
|
+
ctx.textBaseline = "middle";
|
|
2213
|
+
ctx.fillText(label, centerX, midY);
|
|
2214
|
+
}
|
|
2215
|
+
onClick() {
|
|
2216
|
+
this.owner.setHiddenPortsShown(!this.owner.hiddenPortsShown());
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
|
|
2220
|
+
// src/styles/stroke.ts
|
|
2221
|
+
function StrokeStyleWithFallback(input, fallback) {
|
|
2222
|
+
return {
|
|
2223
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2224
|
+
size: input?.size === void 0 ? fallback?.size : input?.size
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
var StrokeStyle = class {
|
|
2228
|
+
#size;
|
|
2229
|
+
#color;
|
|
2230
|
+
constructor(config) {
|
|
2231
|
+
this.#size = config?.size === void 0 ? 0.5 : config.size;
|
|
2232
|
+
this.#color = config?.color === void 0 ? "black" : config.color;
|
|
2233
|
+
}
|
|
2234
|
+
setupStyle(ctx, scale) {
|
|
2235
|
+
ctx.strokeStyle = this.#color;
|
|
2236
|
+
ctx.lineWidth = scale * this.#size;
|
|
2237
|
+
}
|
|
2238
|
+
setColor(newColor) {
|
|
2239
|
+
this.#color = newColor;
|
|
2240
|
+
}
|
|
2241
|
+
setSize(newSize) {
|
|
2242
|
+
this.#size = newSize;
|
|
2243
|
+
}
|
|
2244
|
+
size() {
|
|
2245
|
+
return this.#size;
|
|
2246
|
+
}
|
|
2247
|
+
};
|
|
2248
|
+
|
|
2249
|
+
// src/styles/box.ts
|
|
2250
|
+
function BoxStyleWithFallback(input, fallback) {
|
|
2251
|
+
return {
|
|
2252
|
+
radius: input?.radius === void 0 ? fallback?.radius : input?.radius,
|
|
2253
|
+
color: input?.color === void 0 ? fallback?.color : input?.color,
|
|
2254
|
+
border: StrokeStyleWithFallback(input?.border, fallback?.border)
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
var BoxStyle = class {
|
|
2258
|
+
#border;
|
|
2259
|
+
#color;
|
|
2260
|
+
#radius;
|
|
2261
|
+
constructor(config) {
|
|
2262
|
+
this.#color = config?.color === void 0 ? "#CCCCCC" : config.color;
|
|
2263
|
+
this.#border = config?.border === void 0 ? null : new StrokeStyle(config.border);
|
|
2264
|
+
this.#radius = config?.radius === void 0 ? 2 : config.radius;
|
|
2265
|
+
}
|
|
2266
|
+
#box(ctx, box, scale, radius) {
|
|
2267
|
+
ctx.fillStyle = this.#color;
|
|
2268
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2269
|
+
ctx.beginPath();
|
|
2270
|
+
ctx.roundRect(
|
|
2271
|
+
box.Position.x,
|
|
2272
|
+
box.Position.y,
|
|
2273
|
+
box.Size.x,
|
|
2274
|
+
box.Size.y,
|
|
2275
|
+
radius
|
|
2276
|
+
);
|
|
2277
|
+
ctx.fill();
|
|
2278
|
+
}
|
|
2279
|
+
#draw(ctx, box, scale, radius) {
|
|
2280
|
+
this.#box(ctx, box, scale, radius);
|
|
2281
|
+
ctx.stroke();
|
|
2282
|
+
}
|
|
2283
|
+
Outline(ctx, box, scale, radius) {
|
|
2284
|
+
this.#border?.setupStyle(ctx, scale);
|
|
2285
|
+
ctx.beginPath();
|
|
2286
|
+
ctx.roundRect(
|
|
2287
|
+
box.Position.x,
|
|
2288
|
+
box.Position.y,
|
|
2289
|
+
box.Size.x,
|
|
2290
|
+
box.Size.y,
|
|
2291
|
+
radius
|
|
2292
|
+
);
|
|
2293
|
+
ctx.stroke();
|
|
2294
|
+
}
|
|
2295
|
+
Draw(ctx, box, scale) {
|
|
2296
|
+
this.#draw(ctx, box, scale, this.#radius * scale);
|
|
2297
|
+
}
|
|
2298
|
+
DrawRoundedTopOnly(ctx, box, scale) {
|
|
2299
|
+
this.#draw(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2300
|
+
}
|
|
2301
|
+
DrawUnderline(ctx, box, scale) {
|
|
2302
|
+
this.#box(ctx, box, scale, [this.#radius * scale * 2, this.#radius * scale * 2, 0, 0]);
|
|
2303
|
+
ctx.beginPath();
|
|
2304
|
+
ctx.moveTo(box.Position.x, box.Position.y + box.Size.y);
|
|
2305
|
+
ctx.lineTo(box.Position.x + box.Size.x, box.Position.y + box.Size.y);
|
|
2306
|
+
ctx.stroke();
|
|
2307
|
+
}
|
|
2308
|
+
borderSize() {
|
|
2309
|
+
if (this.#border === null) {
|
|
2310
|
+
return 0;
|
|
2311
|
+
}
|
|
2312
|
+
return this.#border.size();
|
|
2313
|
+
}
|
|
2314
|
+
radius() {
|
|
2315
|
+
return this.#radius;
|
|
2316
|
+
}
|
|
2317
|
+
setColor(color) {
|
|
2318
|
+
this.#color = color;
|
|
2319
|
+
}
|
|
2320
|
+
setBorderColor(color) {
|
|
2321
|
+
if (this.#border === null) {
|
|
2322
|
+
this.#border = new StrokeStyle({
|
|
2323
|
+
color
|
|
2324
|
+
});
|
|
2325
|
+
} else {
|
|
2326
|
+
this.#border.setColor(color);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2330
|
+
|
|
2331
|
+
// src/styles/bevel.ts
|
|
2332
|
+
function drawBevel(ctx, box, scale, colors, sunken) {
|
|
2333
|
+
const width2 = Math.max(1, 2 * scale);
|
|
2334
|
+
const half = width2 / 2;
|
|
2335
|
+
const left = box.Position.x + half;
|
|
2336
|
+
const top = box.Position.y + half;
|
|
2337
|
+
const right = box.Position.x + box.Size.x - half;
|
|
2338
|
+
const bottom = box.Position.y + box.Size.y - half;
|
|
2339
|
+
ctx.save();
|
|
2340
|
+
ctx.lineWidth = width2;
|
|
2341
|
+
ctx.lineCap = "square";
|
|
2342
|
+
ctx.strokeStyle = sunken ? colors.Dark : colors.Light;
|
|
2343
|
+
ctx.beginPath();
|
|
2344
|
+
ctx.moveTo(left, bottom);
|
|
2345
|
+
ctx.lineTo(left, top);
|
|
2346
|
+
ctx.lineTo(right, top);
|
|
2347
|
+
ctx.stroke();
|
|
2348
|
+
ctx.strokeStyle = sunken ? colors.Light : colors.Dark;
|
|
2349
|
+
ctx.beginPath();
|
|
2350
|
+
ctx.moveTo(right, top);
|
|
2351
|
+
ctx.lineTo(right, bottom);
|
|
2352
|
+
ctx.lineTo(left, bottom);
|
|
2353
|
+
ctx.stroke();
|
|
2354
|
+
ctx.restore();
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
// src/widgets/field.ts
|
|
2358
|
+
function widgetFont(scale) {
|
|
2359
|
+
return `${Theme.Widget.FontSize * scale}px ${Theme.FontFamily}`;
|
|
2360
|
+
}
|
|
2361
|
+
function fieldBackground(look) {
|
|
2362
|
+
if (look.background !== void 0) {
|
|
2363
|
+
return look.background;
|
|
2364
|
+
}
|
|
2365
|
+
if (look.input) {
|
|
2366
|
+
return look.hovered ? Theme.Widget.Input.HoverBackgroundColor : Theme.Widget.Input.BackgroundColor;
|
|
2367
|
+
}
|
|
2368
|
+
if (look.pressed) {
|
|
2369
|
+
return Theme.Widget.Button.Click.BackgroundColor;
|
|
2370
|
+
}
|
|
2371
|
+
return look.hovered ? Theme.Widget.Hover.BackgroundColor : Theme.Widget.BackgroundColor;
|
|
2372
|
+
}
|
|
2373
|
+
function drawFieldBox(ctx, box, scale, look) {
|
|
2374
|
+
ctx.fillStyle = fieldBackground(look);
|
|
2375
|
+
ctx.beginPath();
|
|
2376
|
+
ctx.roundRect(box.Position.x, box.Position.y, box.Size.x, box.Size.y, Theme.Widget.Border.Radius * scale);
|
|
2377
|
+
ctx.fill();
|
|
2378
|
+
if (Theme.Widget.Border.Size > 0) {
|
|
2379
|
+
ctx.strokeStyle = look.border ?? Theme.Widget.Border.Color;
|
|
2380
|
+
ctx.lineWidth = Theme.Widget.Border.Size * scale;
|
|
2381
|
+
ctx.stroke();
|
|
2382
|
+
}
|
|
2383
|
+
if (Theme.Widget.Bevel !== null) {
|
|
2384
|
+
drawBevel(ctx, box, scale, Theme.Widget.Bevel, look.input === true || look.pressed === true);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
function drawField(ctx, box, scale, look) {
|
|
2388
|
+
drawFieldBox(ctx, box, scale, look);
|
|
2389
|
+
drawFieldText(ctx, box, scale, look);
|
|
2390
|
+
}
|
|
2391
|
+
function drawFieldText(ctx, box, scale, look) {
|
|
2392
|
+
const padding = Theme.Widget.Padding * scale;
|
|
2393
|
+
const middle = box.Position.y + box.Size.y / 2;
|
|
2394
|
+
const textColor = look.textColor ?? (look.input ? Theme.Widget.Input.FontColor : Theme.Widget.FontColor);
|
|
2395
|
+
ctx.font = widgetFont(scale);
|
|
2396
|
+
ctx.textBaseline = "middle";
|
|
2397
|
+
if (look.label === void 0 || look.label === "") {
|
|
2398
|
+
ctx.textAlign = "center";
|
|
2399
|
+
ctx.fillStyle = textColor;
|
|
2400
|
+
ctx.fillText(
|
|
2401
|
+
fitString(ctx, look.value, box.Size.x - padding * 2),
|
|
2402
|
+
box.Position.x + box.Size.x / 2,
|
|
2403
|
+
middle
|
|
2404
|
+
);
|
|
2405
|
+
return;
|
|
2406
|
+
}
|
|
2407
|
+
const room = box.Size.x - padding * 2;
|
|
2408
|
+
const label = fitString(ctx, look.label, room / 2);
|
|
2409
|
+
const labelWidth = ctx.measureText(label).width;
|
|
2410
|
+
ctx.textAlign = "left";
|
|
2411
|
+
ctx.fillStyle = look.textColor ?? Theme.Widget.LabelColor;
|
|
2412
|
+
ctx.fillText(label, box.Position.x + padding, middle);
|
|
2413
|
+
ctx.textAlign = "right";
|
|
2414
|
+
ctx.fillStyle = textColor;
|
|
2415
|
+
ctx.fillText(
|
|
2416
|
+
fitString(ctx, look.value, room - labelWidth - padding),
|
|
2417
|
+
box.Position.x + box.Size.x - padding,
|
|
2418
|
+
middle
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2385
2422
|
// src/widgets/value.ts
|
|
2386
2423
|
var ValueWidget = class extends WidgetBase {
|
|
2387
2424
|
#node;
|
|
@@ -5638,7 +5675,8 @@ var FlowNode = class {
|
|
|
5638
5675
|
size.y += this.#portRowHeight(port, tempMeasurement.y) + this.#elementSpacing;
|
|
5639
5676
|
size.x = Math.max(size.x, tempMeasurement.x + doublePadding);
|
|
5640
5677
|
}
|
|
5641
|
-
|
|
5678
|
+
const widgets = this.#hasHiddenPortsToggle() ? [this.#hiddenPortsToggle, ...this.#widgets] : this.#widgets;
|
|
5679
|
+
for (const widget of widgets) {
|
|
5642
5680
|
if (widget.Hidden?.()) {
|
|
5643
5681
|
continue;
|
|
5644
5682
|
}
|
|
@@ -5664,6 +5702,31 @@ var FlowNode = class {
|
|
|
5664
5702
|
this.#output.push(port);
|
|
5665
5703
|
return port;
|
|
5666
5704
|
}
|
|
5705
|
+
#hiddenPortsShown = false;
|
|
5706
|
+
#hiddenPortsToggle = new HiddenPortsToggle(this);
|
|
5707
|
+
#hiddenPortsTogglePosition = null;
|
|
5708
|
+
hiddenPortsShown() {
|
|
5709
|
+
return this.#hiddenPortsShown;
|
|
5710
|
+
}
|
|
5711
|
+
setHiddenPortsShown(shown) {
|
|
5712
|
+
if (shown === this.#hiddenPortsShown) {
|
|
5713
|
+
return;
|
|
5714
|
+
}
|
|
5715
|
+
this.#hiddenPortsShown = shown;
|
|
5716
|
+
this.invalidateLayout();
|
|
5717
|
+
}
|
|
5718
|
+
hiddenPortCount() {
|
|
5719
|
+
let count = 0;
|
|
5720
|
+
for (const port of [...this.#input, ...this.#output]) {
|
|
5721
|
+
if (port.tucked()) {
|
|
5722
|
+
count++;
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5725
|
+
return count;
|
|
5726
|
+
}
|
|
5727
|
+
#hasHiddenPortsToggle() {
|
|
5728
|
+
return this.hiddenPortCount() > 0;
|
|
5729
|
+
}
|
|
5667
5730
|
addWidget(widget) {
|
|
5668
5731
|
this.#widgets.push(widget);
|
|
5669
5732
|
requestRender();
|
|
@@ -5742,6 +5805,11 @@ var FlowNode = class {
|
|
|
5742
5805
|
intersection.Port = this.#output[i];
|
|
5743
5806
|
}
|
|
5744
5807
|
}
|
|
5808
|
+
if (this.#hiddenPortsTogglePosition !== null && InBox(this.#hiddenPortsTogglePosition, position)) {
|
|
5809
|
+
intersection.Node = this;
|
|
5810
|
+
intersection.Widget = this.#hiddenPortsToggle;
|
|
5811
|
+
intersection.WidgetBox = this.#hiddenPortsTogglePosition;
|
|
5812
|
+
}
|
|
5745
5813
|
for (let i = 0; i < this.#widgetPositions.Count(); i++) {
|
|
5746
5814
|
const widget = this.#widgets[i];
|
|
5747
5815
|
if (widget !== void 0 && !widget.Hidden?.() && InBox(this.#widgetPositions.At(i), position)) {
|
|
@@ -6011,6 +6079,16 @@ var FlowNode = class {
|
|
|
6011
6079
|
this.#outputPortPositions.Push(port.render(ctx, position, camera, mousePosition, postProcess));
|
|
6012
6080
|
startY += portHeight + scaledElementSpacing;
|
|
6013
6081
|
}
|
|
6082
|
+
this.#hiddenPortsTogglePosition = null;
|
|
6083
|
+
if (this.#hasHiddenPortsToggle()) {
|
|
6084
|
+
const box = {
|
|
6085
|
+
Position: { x: nodeBounds.Position.x + scaledPadding, y: startY },
|
|
6086
|
+
Size: { x: nodeBounds.Size.x - scaledPadding * 2, y: this.#hiddenPortsToggle.Size().y * camera.zoom }
|
|
6087
|
+
};
|
|
6088
|
+
this.#hiddenPortsToggle.Draw(ctx, box, camera.zoom, mousePosition);
|
|
6089
|
+
this.#hiddenPortsTogglePosition = box;
|
|
6090
|
+
startY += box.Size.y + scaledElementSpacing;
|
|
6091
|
+
}
|
|
6014
6092
|
for (let i = 0; i < this.#widgets.length; i++) {
|
|
6015
6093
|
const widget = this.#widgets[i];
|
|
6016
6094
|
if (widget.Hidden?.()) {
|
|
@@ -6065,6 +6143,7 @@ var FlowNode = class {
|
|
|
6065
6143
|
return false;
|
|
6066
6144
|
}
|
|
6067
6145
|
this.#widgetPositions.Clear();
|
|
6146
|
+
this.#hiddenPortsTogglePosition = null;
|
|
6068
6147
|
return true;
|
|
6069
6148
|
}
|
|
6070
6149
|
placePorts(bounds, zoom) {
|
|
@@ -7725,8 +7804,8 @@ var NodeFlowGraph = class {
|
|
|
7725
7804
|
this.#clickEnd.bind(this),
|
|
7726
7805
|
this.#openContextMenu.bind(this),
|
|
7727
7806
|
this.#fileDrop.bind(this),
|
|
7728
|
-
(
|
|
7729
|
-
this
|
|
7807
|
+
(factor, anchor) => {
|
|
7808
|
+
this.#zoomBy(factor, anchor);
|
|
7730
7809
|
}
|
|
7731
7810
|
);
|
|
7732
7811
|
document.addEventListener(
|
|
@@ -7854,12 +7933,15 @@ var NodeFlowGraph = class {
|
|
|
7854
7933
|
this.#mainNoteSubsystem.addNoteDragStopListener(callback);
|
|
7855
7934
|
}
|
|
7856
7935
|
zoom(amount, anchor) {
|
|
7936
|
+
this.#zoomBy(1 + amount * 0.05, anchor);
|
|
7937
|
+
}
|
|
7938
|
+
#zoomBy(factor, anchor) {
|
|
7857
7939
|
const anchorPos = anchor ?? this.#mousePosition;
|
|
7858
7940
|
let oldPos = void 0;
|
|
7859
7941
|
if (anchorPos !== void 0) {
|
|
7860
7942
|
oldPos = this.#sceenPositionToGraphPosition(anchorPos);
|
|
7861
7943
|
}
|
|
7862
|
-
this.#camera.zoom
|
|
7944
|
+
this.#camera.zoom *= factor;
|
|
7863
7945
|
if (!oldPos || anchorPos === void 0) {
|
|
7864
7946
|
return;
|
|
7865
7947
|
}
|