verstak 0.24.269 → 0.24.271

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.
@@ -0,0 +1,323 @@
1
+ import { ElLayoutInfo, InitialElLayoutInfo, SplitView } from "./El.js";
2
+ import { Drivers, isSplitViewPartition } from "./Elements.js";
3
+ import { clamp } from "./ElUtils.js";
4
+ const DEBUG = false;
5
+ const eps = 0.0001;
6
+ export function equal(a, b) {
7
+ return Math.abs(a - b) <= eps;
8
+ }
9
+ export function less(a, b) {
10
+ return b - a > eps;
11
+ }
12
+ export function greater(a, b) {
13
+ return a - b > eps;
14
+ }
15
+ export function relayoutUsingSplitter(splitViewNode, deltaPx, index, initialSizesPx, priorities) {
16
+ var _a, _b, _c, _d;
17
+ if (priorities === undefined) {
18
+ priorities = getPrioritiesForSplitter(index + 1, initialSizesPx.length);
19
+ }
20
+ const containerSizePx = splitViewNode.element.splitView === SplitView.horizontal
21
+ ? (_b = (_a = splitViewNode.element.layoutInfo) === null || _a === void 0 ? void 0 : _a.contentSizeXpx) !== null && _b !== void 0 ? _b : 0
22
+ : (_d = (_c = splitViewNode.element.layoutInfo) === null || _c === void 0 ? void 0 : _c.contentSizeYpx) !== null && _d !== void 0 ? _d : 0;
23
+ DEBUG && console.log(`(splitter) delta = ${deltaPx}, container = ${containerSizePx}, size = ${initialSizesPx.reduce((p, c) => p + c.sizePx, 0)}, index = ${index}`);
24
+ resizeUsingDelta(splitViewNode, deltaPx, index + 1, priorities, initialSizesPx, true);
25
+ layout(splitViewNode);
26
+ }
27
+ export function relayout(splitViewNode, priorities, manuallyResizablePriorities, sizesPx) {
28
+ var _a, _b, _c, _d;
29
+ const containerSizePx = splitViewNode.element.splitView === SplitView.horizontal
30
+ ? (_b = (_a = splitViewNode.element.layoutInfo) === null || _a === void 0 ? void 0 : _a.contentSizeXpx) !== null && _b !== void 0 ? _b : 0
31
+ : (_d = (_c = splitViewNode.element.layoutInfo) === null || _c === void 0 ? void 0 : _c.contentSizeYpx) !== null && _d !== void 0 ? _d : 0;
32
+ const totalSizePx = sizesPx.reduce((p, c) => p + c.sizePx, 0);
33
+ let deltaPx = containerSizePx - totalSizePx;
34
+ DEBUG && console.log(printPriorities(priorities, manuallyResizablePriorities), "color: grey", "color:", "color: grey", "color:");
35
+ DEBUG && console.log(`(relayout) ∆ = ${n(deltaPx)}px, container = ${n(containerSizePx)}px, total = ${totalSizePx}`);
36
+ deltaPx = resizeUsingDelta(splitViewNode, deltaPx, sizesPx.length, priorities, sizesPx);
37
+ DEBUG && console.log(`(relayout) ~∆ = ${n(deltaPx)}, container = ${n(containerSizePx, 3)}px, total = ${n(sizesPx.reduce((p, c) => p + c.sizePx, 0), 3)}px`);
38
+ if (deltaPx < -(1 / devicePixelRatio)) {
39
+ DEBUG && console.log(`%c${deltaPx}px`, "color: lime");
40
+ resizeUsingDelta(splitViewNode, deltaPx, sizesPx.length, manuallyResizablePriorities, sizesPx, true);
41
+ }
42
+ layout(splitViewNode);
43
+ }
44
+ export function resizeUsingDelta(splitViewNode, deltaPx, index, priorities, sizesPx, force = false) {
45
+ const isHorizontal = splitViewNode.element.splitView === SplitView.horizontal;
46
+ let beforeDeltaPx = 0;
47
+ if (sizesPx.length > 0 && deltaPx !== 0) {
48
+ let minBeforeDeltaPx = 0;
49
+ let maxBeforeDeltaPx = 0;
50
+ for (let i = 0; i < index; i++) {
51
+ const size = isHorizontal ? sizesPx[i].node.element.widthPx : sizesPx[i].node.element.heightPx;
52
+ minBeforeDeltaPx += size.minPx - sizesPx[i].sizePx;
53
+ maxBeforeDeltaPx += size.maxPx - sizesPx[i].sizePx;
54
+ }
55
+ const hasAfter = index < sizesPx.length;
56
+ let minAfterDeltaPx = hasAfter ? 0 : Number.NEGATIVE_INFINITY;
57
+ let maxAfterDeltaPx = hasAfter ? 0 : Number.POSITIVE_INFINITY;
58
+ for (let i = index; i < sizesPx.length; i++) {
59
+ const size = isHorizontal ? sizesPx[i].node.element.widthPx : sizesPx[i].node.element.heightPx;
60
+ minAfterDeltaPx += sizesPx[i].sizePx - size.maxPx;
61
+ maxAfterDeltaPx += sizesPx[i].sizePx - size.minPx;
62
+ }
63
+ const minDeltaPx = Math.max(minBeforeDeltaPx, minAfterDeltaPx);
64
+ const maxDeltaPx = Math.min(maxBeforeDeltaPx, maxAfterDeltaPx);
65
+ const clampedDeltaPx = clamp(deltaPx, minDeltaPx, maxDeltaPx);
66
+ DEBUG && console.log(`%c${sizesPx.map((x, i) => {
67
+ const size = isHorizontal ? x.node.element.widthPx : x.node.element.heightPx;
68
+ return `${i}: ${size.minPx}..${x.sizePx}..${size.maxPx} (px)`;
69
+ }).join("\n")}`, "color: skyblue");
70
+ DEBUG && console.log(`[%c${Array.from({ length: index }).map((x, i) => i).join(",")}%c | %c${Array.from({ length: Math.max(0, sizesPx.length - index) }).map((x, i) => index + i).join(",")}%c]\n∆ = ${n(minDeltaPx)}px..${n(deltaPx)}px -> %c${n(clampedDeltaPx)}px%c..${n(maxDeltaPx)}px`, "color: #00BB00", "color:", "color: orange", "color:", "color: yellow", "color:");
71
+ if (clampedDeltaPx !== 0) {
72
+ if (index > 0)
73
+ beforeDeltaPx = distribute(1, clampedDeltaPx, index, priorities, sizesPx, isHorizontal, force);
74
+ if (hasAfter)
75
+ distribute(-1, clampedDeltaPx, index, priorities, sizesPx, isHorizontal, force);
76
+ }
77
+ }
78
+ for (let i = 0; i < sizesPx.length; i++) {
79
+ const el = sizesPx[i].node.element;
80
+ if (el.layoutInfo === undefined)
81
+ el.layoutInfo = new ElLayoutInfo(InitialElLayoutInfo);
82
+ el.layoutInfo.effectiveSizePx = sizesPx[i].sizePx;
83
+ DEBUG && console.log(`[${i}]: set size = ${n(sizesPx[i].sizePx)}px`);
84
+ }
85
+ return beforeDeltaPx;
86
+ }
87
+ export function layout(splitViewNode) {
88
+ var _a, _b, _c, _d, _e, _f, _g, _h;
89
+ const isHorizontal = splitViewNode.element.splitView === SplitView.horizontal;
90
+ let posPx = 0;
91
+ let shrinkBefore = false;
92
+ let growBefore = false;
93
+ let isSplitterEnabled = false;
94
+ const sizesPx = [];
95
+ const layoutInfo = splitViewNode.element.layoutInfo;
96
+ const offsetXpx = (_a = layoutInfo === null || layoutInfo === void 0 ? void 0 : layoutInfo.offsetXpx) !== null && _a !== void 0 ? _a : 0;
97
+ const offsetYpx = (_b = layoutInfo === null || layoutInfo === void 0 ? void 0 : layoutInfo.offsetYpx) !== null && _b !== void 0 ? _b : 0;
98
+ for (const item of splitViewNode.children.items()) {
99
+ const child = item.instance;
100
+ if (isSplitViewPartition(child.driver)) {
101
+ const el = child.element;
102
+ if (el.native !== undefined) {
103
+ const current = item;
104
+ const sizePx = isHorizontal ? el.widthPx : el.heightPx;
105
+ const effectiveSizePx = (_d = (_c = el.layoutInfo) === null || _c === void 0 ? void 0 : _c.effectiveSizePx) !== null && _d !== void 0 ? _d : 0;
106
+ posPx += effectiveSizePx;
107
+ sizesPx.push(effectiveSizePx);
108
+ el.native.setAttribute("rx-max", equal(effectiveSizePx, sizePx.maxPx) ? "true" : "false");
109
+ el.native.setAttribute("rx-min", equal(effectiveSizePx, sizePx.minPx) ? "true" : "false");
110
+ shrinkBefore || (shrinkBefore = greater(effectiveSizePx - sizePx.minPx, 0));
111
+ growBefore || (growBefore = greater(sizePx.maxPx - effectiveSizePx, 0));
112
+ let shrinkAfter = false;
113
+ let growAfter = false;
114
+ for (const item of splitViewNode.children.items(current)) {
115
+ const child = item.instance;
116
+ if (isSplitViewPartition(child.driver)) {
117
+ const el = child.element;
118
+ if (el.native !== undefined) {
119
+ const sizePx = isHorizontal ? el.widthPx : el.heightPx;
120
+ const effectiveSizePx = (_f = (_e = el.layoutInfo) === null || _e === void 0 ? void 0 : _e.effectiveSizePx) !== null && _f !== void 0 ? _f : 0;
121
+ shrinkAfter || (shrinkAfter = greater(effectiveSizePx - sizePx.minPx, 0));
122
+ growAfter || (growAfter = greater(sizePx.maxPx - effectiveSizePx, 0));
123
+ isSplitterEnabled = growBefore && shrinkAfter || growAfter && shrinkBefore;
124
+ if (isSplitterEnabled)
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ else if (child.driver === Drivers.splitter) {
132
+ const el = child.element;
133
+ if (el.native !== undefined) {
134
+ el.style.display = isSplitterEnabled ? "block" : "none";
135
+ if (isHorizontal)
136
+ el.style.left = `${offsetXpx + posPx}px`;
137
+ else
138
+ el.style.top = `${offsetYpx + posPx}px`;
139
+ }
140
+ }
141
+ }
142
+ const containerSizePx = (_g = (isHorizontal ? layoutInfo === null || layoutInfo === void 0 ? void 0 : layoutInfo.contentSizeXpx : layoutInfo === null || layoutInfo === void 0 ? void 0 : layoutInfo.contentSizeYpx)) !== null && _g !== void 0 ? _g : 0;
143
+ const isOverflowing = greater(posPx, containerSizePx);
144
+ const wrapper = (_h = splitViewNode.children.firstMergedItem()) === null || _h === void 0 ? void 0 : _h.instance;
145
+ if (wrapper !== undefined) {
146
+ if (isHorizontal)
147
+ wrapper.element.style.gridTemplateColumns = sizesPx.map(x => `${x}px`).join(" ");
148
+ else
149
+ wrapper.element.style.gridTemplateRows = sizesPx.map(x => `${x}px`).join(" ");
150
+ if (isOverflowing) {
151
+ if (isHorizontal)
152
+ wrapper.element.style.overflow = "scroll hidden";
153
+ else
154
+ wrapper.element.style.overflow = "hidden scroll";
155
+ }
156
+ else {
157
+ wrapper.element.style.overflow = "hidden";
158
+ }
159
+ }
160
+ }
161
+ export function getPrioritiesForSplitter(index, size) {
162
+ const result = [];
163
+ let i = index - 1;
164
+ let j = index;
165
+ while (i >= 0 || j < size) {
166
+ if (i >= 0 && j < size) {
167
+ result.push((1 << i--) | (1 << j++));
168
+ }
169
+ else if (i >= 0) {
170
+ result.push(1 << i--);
171
+ }
172
+ else {
173
+ result.push(1 << j++);
174
+ }
175
+ }
176
+ return result;
177
+ }
178
+ export function getPrioritiesForSizeChanging(isHorizontal, children, indexes) {
179
+ var _a, _b;
180
+ const resizable = [];
181
+ const manuallyResizable = [];
182
+ const items = Array.from(children.items()).filter(x => isSplitViewPartition(x.instance.driver));
183
+ for (let i = items.length - 1; i >= 0; i--) {
184
+ const item = items[i];
185
+ const el = item.instance.element;
186
+ const strength = (_a = (isHorizontal ? el.stretchingStrengthX : el.stretchingStrengthY)) !== null && _a !== void 0 ? _a : 1;
187
+ if (!indexes.includes(i)) {
188
+ if (strength > 0)
189
+ resizable.push(1 << i);
190
+ else
191
+ manuallyResizable.push(1 << i);
192
+ }
193
+ }
194
+ for (const i of indexes) {
195
+ const item = items[i];
196
+ const el = item.instance.element;
197
+ const strength = (_b = (isHorizontal ? el.stretchingStrengthX : el.stretchingStrengthY)) !== null && _b !== void 0 ? _b : 1;
198
+ if (strength > 0)
199
+ resizable.push(1 << i);
200
+ else
201
+ manuallyResizable.push(1 << i);
202
+ }
203
+ return { resizable, manuallyResizable };
204
+ }
205
+ export function getPrioritiesForEmptySpaceDistribution(isHorizontal, children) {
206
+ var _a;
207
+ let r = 0;
208
+ let mr = 0;
209
+ let i = 0;
210
+ for (const child of children.items()) {
211
+ if (isSplitViewPartition(child.instance.driver)) {
212
+ const el = child.instance.element;
213
+ const strength = (_a = (isHorizontal ? el.stretchingStrengthX : el.stretchingStrengthY)) !== null && _a !== void 0 ? _a : 1;
214
+ if (strength > 0)
215
+ r |= 1 << i;
216
+ else
217
+ mr |= 1 << i;
218
+ i++;
219
+ }
220
+ }
221
+ return { resizable: [r], manuallyResizable: [mr] };
222
+ }
223
+ function getFractionCount(isHorizontal, children, vector, index, force = false) {
224
+ var _a;
225
+ let result = 0;
226
+ for (const i of indexes(vector, index)) {
227
+ const growth = (_a = (isHorizontal ? children[i].element.stretchingStrengthX : children[i].element.stretchingStrengthY)) !== null && _a !== void 0 ? _a : 1;
228
+ result += growth > 0 ? growth : (force ? 1 : 0);
229
+ }
230
+ return result;
231
+ }
232
+ function getFractionSizePx(spacePx, fractionCount) {
233
+ return fractionCount > 0 ? spacePx / fractionCount : 0;
234
+ }
235
+ function* indexes(vector, index) {
236
+ let i = 0;
237
+ if (index < 0) {
238
+ i = -index;
239
+ vector >>>= i;
240
+ while (vector > 0) {
241
+ if (vector & 1) {
242
+ yield i;
243
+ }
244
+ vector >>>= 1;
245
+ i++;
246
+ }
247
+ }
248
+ else {
249
+ while (i < index) {
250
+ if (vector & 1) {
251
+ yield i;
252
+ }
253
+ vector >>>= 1;
254
+ i++;
255
+ }
256
+ }
257
+ }
258
+ function n(value, fractionDigits = 2) {
259
+ return value === 0 ? "0" : value.toFixed(fractionDigits);
260
+ }
261
+ function distribute(sign, deltaPx, index, priorities, sizesPx, isHorizontal, force) {
262
+ var _a, _b;
263
+ for (let priority = 0; priority < priorities.length; priority++) {
264
+ const vector = priorities[priority];
265
+ let fractionCount = getFractionCount(isHorizontal, sizesPx.map(x => x.node), vector, sign * index, force);
266
+ do {
267
+ const fractionSizePx = getFractionSizePx(deltaPx, fractionCount);
268
+ fractionCount = 0;
269
+ for (const i of indexes(vector, sign * index)) {
270
+ const child = sizesPx[i].node;
271
+ const initialSizePx = sizesPx[i].sizePx;
272
+ const strength = isHorizontal ? ((_a = child.element.stretchingStrengthX) !== null && _a !== void 0 ? _a : 1) : ((_b = child.element.stretchingStrengthY) !== null && _b !== void 0 ? _b : 1);
273
+ const growth = strength > 0 ? strength : (force ? 1 : 0);
274
+ const newSizePx = initialSizePx + sign * (growth * fractionSizePx);
275
+ const size = isHorizontal ? sizesPx[i].node.element.widthPx : sizesPx[i].node.element.heightPx;
276
+ const sizePx = clamp(newSizePx, size.minPx, size.maxPx);
277
+ deltaPx = deltaPx - sign * (sizePx - initialSizePx);
278
+ sizesPx[i].sizePx = sizePx;
279
+ if (sizesPx[i].sizePx > size.minPx && sizesPx[i].sizePx < size.maxPx) {
280
+ fractionCount += growth;
281
+ }
282
+ }
283
+ } while (Math.abs(deltaPx) > eps && fractionCount > 0);
284
+ if (Math.abs(deltaPx) <= eps) {
285
+ break;
286
+ }
287
+ }
288
+ return deltaPx;
289
+ }
290
+ function printPriorities(priorities, manuallyResizablePriorities) {
291
+ let text = "";
292
+ if (priorities.length > 0) {
293
+ text += `Automatically Resizable:\n%c(${priorities.map(x => `0x${x.toString(2)}`).join(", ")})%c\n`;
294
+ for (let i = 0; i < priorities.length; i++) {
295
+ let vector = priorities[i];
296
+ const parts = [];
297
+ let j = 0;
298
+ while (vector) {
299
+ if (vector & 1)
300
+ parts.push(j);
301
+ j++;
302
+ vector >>= 1;
303
+ }
304
+ text += `${i}: ${parts.join(", ")}\n`;
305
+ }
306
+ }
307
+ if (manuallyResizablePriorities.length > 0) {
308
+ text += `Manually Resizable:\n%c(${manuallyResizablePriorities.map(x => `0x${x.toString(2)}`).join(", ")})%c\n`;
309
+ for (let i = 0; i < manuallyResizablePriorities.length; i++) {
310
+ let vector = manuallyResizablePriorities[i];
311
+ const parts = [];
312
+ let j = 0;
313
+ while (vector) {
314
+ if (vector & 1)
315
+ parts.push(j);
316
+ j++;
317
+ vector >>= 1;
318
+ }
319
+ text += `${i}: ${parts.join(", ")}\n`;
320
+ }
321
+ }
322
+ return text;
323
+ }
@@ -5,6 +5,8 @@ export * from "./HtmlElements.js";
5
5
  export * from "./HtmlApiExt.js";
6
6
  export * from "./Elements.js";
7
7
  export * from "./Handlers.js";
8
+ export * from "./Sizes.js";
9
+ export * from "./SplitViewMath.js";
8
10
  export * from "./sensors/Sensor.js";
9
11
  export * from "./sensors/PointerSensor.js";
10
12
  export * from "./sensors/BasePointerSensor.js";
@@ -5,6 +5,8 @@ export * from "./HtmlElements.js";
5
5
  export * from "./HtmlApiExt.js";
6
6
  export * from "./Elements.js";
7
7
  export * from "./Handlers.js";
8
+ export * from "./Sizes.js";
9
+ export * from "./SplitViewMath.js";
8
10
  export * from "./sensors/Sensor.js";
9
11
  export * from "./sensors/PointerSensor.js";
10
12
  export * from "./sensors/BasePointerSensor.js";
@@ -25,6 +25,7 @@ export declare class KeyboardSensor extends HtmlElementSensor {
25
25
  reset(): void;
26
26
  protected onKeyDown(e: KeyboardEvent): void;
27
27
  protected onKeyUp(e: KeyboardEvent): void;
28
+ protected doWindowBlur(e: FocusEvent): void;
28
29
  protected keyDown(e: KeyboardEvent): void;
29
30
  protected keyUp(e: KeyboardEvent): void;
30
31
  protected updateSensorData(e: KeyboardEvent): void;
@@ -40,10 +40,12 @@ export class KeyboardSensor extends HtmlElementSensor {
40
40
  if (enabled) {
41
41
  element.addEventListener("keydown", this.onKeyDown.bind(this), { capture: true });
42
42
  element.addEventListener("keyup", this.onKeyUp.bind(this), { capture: true });
43
+ window.addEventListener("blur", this.doWindowBlur.bind(this), { capture: true });
43
44
  }
44
45
  else {
45
46
  element.removeEventListener("keydown", this.onKeyDown.bind(this), { capture: true });
46
47
  element.removeEventListener("keyup", this.onKeyUp.bind(this), { capture: true });
48
+ window.removeEventListener("blur", this.doWindowBlur.bind(this), { capture: true });
47
49
  }
48
50
  }
49
51
  reset() {
@@ -61,6 +63,9 @@ export class KeyboardSensor extends HtmlElementSensor {
61
63
  this.keyUp(e);
62
64
  this.setPreventDefaultAndStopPropagation(e);
63
65
  }
66
+ doWindowBlur(e) {
67
+ this.reset();
68
+ }
64
69
  keyDown(e) {
65
70
  this.updateSensorData(e);
66
71
  this.up = "";
@@ -64,6 +64,8 @@ export class PointerSensor extends BasePointerSensor {
64
64
  }
65
65
  }
66
66
  onPointerDown(e) {
67
+ var _a;
68
+ (_a = this.sourceElement) === null || _a === void 0 ? void 0 : _a.setPointerCapture(e.pointerId);
67
69
  const button = extractPointerButton(e);
68
70
  if (!this.dragStarted && this.clickable === undefined &&
69
71
  (button === PointerButton.left || button === PointerButton.right)) {
@@ -97,6 +99,8 @@ export class PointerSensor extends BasePointerSensor {
97
99
  }
98
100
  }
99
101
  onPointerUp(e) {
102
+ var _a;
103
+ (_a = this.sourceElement) === null || _a === void 0 ? void 0 : _a.releasePointerCapture(e.pointerId);
100
104
  if (this.draggingOver) {
101
105
  this.drop(e);
102
106
  this.finishDragging();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verstak",
3
- "version": "0.24.269",
3
+ "version": "0.24.271",
4
4
  "description": "Verstak - Front-End Library",
5
5
  "publisher": "Nezaboodka Software",
6
6
  "license": "Apache-2.0",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "homepage": "https://github.com/nezaboodka/verstak/blob/master/README.md#readme",
33
33
  "dependencies": {
34
- "reactronic": "^0.24.268"
34
+ "reactronic": "^0.24.270"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "20.11.17",