gpucanvas 0.4.0 → 0.4.1

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/README.md CHANGED
@@ -34,7 +34,8 @@ components. Recorded in Chrome from the demo.
34
34
  Open **[berkantay.github.io/gpucanvas](https://berkantay.github.io/gpucanvas/)** in Chrome 157 or
35
35
  later. Thirty agent cursors build the first view, then the camera pulls out to all 5,000 screens.
36
36
 
37
- - Click a screen to select it, double-click to go deeper, drag to move it.
37
+ - Click a screen to select it, double-click to go deeper, drag to move it. Double-click a text
38
+ field to type in it.
38
39
  - Pick a shader effect in the toolbar, or open one directly:
39
40
  [glass](https://berkantay.github.io/gpucanvas/?effect=glass),
40
41
  [shockwave](https://berkantay.github.io/gpucanvas/?effect=shockwave) (click anywhere),
@@ -100,10 +101,10 @@ so every double-click visibly changes something.
100
101
 
101
102
  | Input | Does |
102
103
  | ------------------ | ---------------------------------------------------------------------------- |
103
- | Double-click | One layer deeper |
104
+ | Double-click | One layer deeper; on a text field, starts typing in it |
104
105
  | Enter, Shift+Enter | First child, parent |
105
106
  | Tab, Shift+Tab | Next and previous sibling |
106
- | Escape | Cancels a drag, then goes up a layer, then clears |
107
+ | Escape | Ends typing, cancels a drag, then goes up a layer, then clears |
107
108
  | Drag | Moves, snapping to the edges and centers of neighbors (Shift locks the axis) |
108
109
  | Handles | Resize (Shift on a corner keeps the ratio) |
109
110
  | Drag on open space | A box that selects the layers it touches, inside the layer you are in |
@@ -3016,6 +3016,7 @@ function bindEditor(canvas, options = {}) {
3016
3016
  let pointer = null;
3017
3017
  let shift = false;
3018
3018
  let swallowClick = false;
3019
+ let keepFocus = false;
3019
3020
  const commit = (next, nextScopes = scopes) => {
3020
3021
  selection = next.filter((layer, i) => next.findIndex((other) => sameLayer(layer, other)) === i);
3021
3022
  scopes = selection.length ? nextScopes : [];
@@ -3034,6 +3035,15 @@ function bindEditor(canvas, options = {}) {
3034
3035
  return { x: event.clientX - bounds.left, y: event.clientY - bounds.top };
3035
3036
  };
3036
3037
  const chainAt = (point) => layers.chainAt(canvas.screenToWorld(point));
3038
+ const fieldAt = (point) => {
3039
+ const element = canvas.getElementAt(canvas.screenToWorld(point));
3040
+ const field = element?.closest("input, textarea, select, [contenteditable]") ?? null;
3041
+ return isEditable(field) ? field : null;
3042
+ };
3043
+ const typingIn = () => {
3044
+ const active = document.activeElement;
3045
+ return isEditable(active) && canvas.getNodeOf(active) ? active : null;
3046
+ };
3037
3047
  const targetIn = (chain) => {
3038
3048
  if (!chain.length) return null;
3039
3049
  for (let i = scopes.length - 1; i >= 0; i--) {
@@ -3187,8 +3197,15 @@ function bindEditor(canvas, options = {}) {
3187
3197
  swallowClick = false;
3188
3198
  if (event.button !== 0) return;
3189
3199
  const point = at(event);
3200
+ const field = typingIn();
3201
+ keepFocus = false;
3202
+ if (field && field.contains(fieldAt(point))) {
3203
+ keepFocus = !field.contains(event.target);
3204
+ return;
3205
+ }
3190
3206
  const take = () => {
3191
3207
  event.stopPropagation();
3208
+ field?.blur();
3192
3209
  swallowClick = true;
3193
3210
  surface.setPointerCapture(event.pointerId);
3194
3211
  };
@@ -3261,7 +3278,20 @@ function bindEditor(canvas, options = {}) {
3261
3278
  if (!selecting(event.shiftKey)) return;
3262
3279
  event.preventDefault();
3263
3280
  event.stopPropagation();
3264
- const chain = chainAt(at(event));
3281
+ const point = at(event);
3282
+ const field = trigger === "click" ? fieldAt(point) : null;
3283
+ if (field) {
3284
+ if (selection.length) commit([], []);
3285
+ field.focus();
3286
+ if (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement) {
3287
+ try {
3288
+ field.setSelectionRange(field.value.length, field.value.length);
3289
+ } catch {
3290
+ }
3291
+ }
3292
+ return;
3293
+ }
3294
+ const chain = chainAt(point);
3265
3295
  let depth = -1;
3266
3296
  chain.forEach((layer, i) => {
3267
3297
  if (layerIn(layer, selection)) depth = i;
@@ -3273,6 +3303,11 @@ function bindEditor(canvas, options = {}) {
3273
3303
  setHovered(null);
3274
3304
  };
3275
3305
  const onMouseDown = (event) => {
3306
+ if (keepFocus) {
3307
+ keepFocus = false;
3308
+ event.preventDefault();
3309
+ return;
3310
+ }
3276
3311
  if (!swallowClick) return;
3277
3312
  event.preventDefault();
3278
3313
  event.stopPropagation();
@@ -3292,7 +3327,11 @@ function bindEditor(canvas, options = {}) {
3292
3327
  shift = event.type === "keydown";
3293
3328
  return updateHover();
3294
3329
  }
3295
- if (event.type !== "keydown" || isEditable(document.activeElement)) return;
3330
+ if (event.type !== "keydown") return;
3331
+ if (isEditable(document.activeElement)) {
3332
+ if (event.key === "Escape" && trigger === "click") typingIn()?.blur();
3333
+ return;
3334
+ }
3296
3335
  if (event.key === "Escape") {
3297
3336
  if (gesture?.kind === "move" || gesture?.kind === "resize") {
3298
3337
  emit("cancel");
@@ -3773,4 +3812,4 @@ export {
3773
3812
  swapNodes,
3774
3813
  createGpuCanvas2 as createGpuCanvas
3775
3814
  };
3776
- //# sourceMappingURL=chunk-BQQVSR4B.js.map
3815
+ //# sourceMappingURL=chunk-DPCICAYZ.js.map