@yodaos-pkg/ink 0.16.0 → 0.16.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
@@ -297,7 +297,11 @@ Binds common DOM events to the current `InkView`.
297
297
  - The keyboard event target, defaulting to `window` when available
298
298
  - `options.focusTarget?: HTMLElement | HTMLCanvasElement | null`
299
299
  - Optional
300
- - The target used for focus and blur events, defaulting to the canvas
300
+ - The target used for focus synchronization when `syncFocus` is enabled, defaulting to the canvas
301
+ - `options.syncFocus?: boolean`
302
+ - Optional
303
+ - Controls whether DOM `focus` / `blur` and click-to-focus are synchronized into Ink host focus
304
+ - Defaults to `false`
301
305
  - `options.preventWheelDefault?: boolean`
302
306
  - Optional
303
307
  - Controls whether wheel default behavior is prevented
@@ -308,7 +312,7 @@ Binds common DOM events to the current `InkView`.
308
312
  - Binds `pointerdown` / `pointermove` / `pointerup` / `pointercancel`
309
313
  - Binds `wheel`
310
314
  - Binds `keydown` / `keyup`
311
- - Binds `focus` / `blur`
315
+ - Optionally binds `focus` / `blur` when `syncFocus` is enabled
312
316
  - Automatically forwards these browser events into the Ink runtime
313
317
 
314
318
  **Returns**
package/index.d.ts CHANGED
@@ -310,8 +310,50 @@ export interface BindDomEventsOptions {
310
310
  canvas?: HTMLCanvasElement;
311
311
  /** Keyboard event target, typically `window`, `document`, or a focusable element. */
312
312
  keyboardTarget?: EventTarget | null;
313
- /** Element that should receive focus/blur synchronization for the Ink instance. */
313
+ /**
314
+ * DOM element used as the focus signal source when `syncFocus` is enabled.
315
+ *
316
+ * When enabled, Ink listens to this element's native `focus` and `blur`
317
+ * events and forwards them to `inkView.focus()` and `inkView.blur()`.
318
+ * `pointerdown` on the canvas also attempts to call `focus()` on this target.
319
+ *
320
+ * This option is useful when the host does not want the canvas itself to be
321
+ * the browser-focused element. For example, a host may keep keyboard focus on
322
+ * an outer wrapper element while still rendering Ink inside a nested canvas.
323
+ *
324
+ * Important: this follows the target element's own `focus` / `blur` state,
325
+ * not a container-style "focus within" semantic. If focus moves from this
326
+ * element to another focusable node, such as an external `<input>`, Ink will
327
+ * observe that blur when `syncFocus` is enabled.
328
+ *
329
+ * Defaults to the currently bound canvas.
330
+ */
314
331
  focusTarget?: HTMLElement | HTMLCanvasElement | null;
332
+ /**
333
+ * Enables automatic synchronization from browser DOM focus to Ink host focus.
334
+ *
335
+ * When set to `true`, `bindDomEvents()` treats the browser focus state as the
336
+ * source of truth for host focus:
337
+ * - listens to `focusTarget`'s `focus` / `blur` events
338
+ * - calls `inkView.focus()` / `inkView.blur()` automatically
339
+ * - attempts click-to-focus on `pointerdown`
340
+ * - makes the `focusTarget` focusable with `tabindex="0"` when needed
341
+ *
342
+ * When set to `false`, `bindDomEvents()` still binds pointer, wheel, and
343
+ * keyboard events, but it does not change Ink host focus automatically. In
344
+ * that mode, the host should call `inkView.focus()` and `inkView.blur()`
345
+ * explicitly based on product-level lifecycle or visibility state.
346
+ *
347
+ * Recommended usage:
348
+ * - Use `true` only when the host really wants DOM focus to directly control
349
+ * Ink host focus.
350
+ * - Keep `false` when browser focus may temporarily move to another element,
351
+ * such as a sibling or external `<input>`, while the Ink instance should
352
+ * still remain host-focused.
353
+ *
354
+ * Defaults to `false`.
355
+ */
356
+ syncFocus?: boolean;
315
357
  /** Whether wheel events should call `preventDefault()` before forwarding. */
316
358
  preventWheelDefault?: boolean;
317
359
  }
package/index.js CHANGED
@@ -1929,6 +1929,7 @@ export class InkView {
1929
1929
 
1930
1930
  const keyboardTarget = options.keyboardTarget || globalThis.window || canvas;
1931
1931
  const focusTarget = options.focusTarget || canvas;
1932
+ const syncFocus = options.syncFocus === true;
1932
1933
  const listeners = [];
1933
1934
  const addListener = (target, type, listener, listenerOptions) => {
1934
1935
  if (!target || typeof target.addEventListener !== 'function') {
@@ -1938,7 +1939,12 @@ export class InkView {
1938
1939
  listeners.push(() => target.removeEventListener(type, listener, listenerOptions));
1939
1940
  };
1940
1941
 
1941
- if (focusTarget && typeof focusTarget.setAttribute === 'function' && focusTarget.tabIndex < 0) {
1942
+ if (
1943
+ syncFocus &&
1944
+ focusTarget &&
1945
+ typeof focusTarget.setAttribute === 'function' &&
1946
+ focusTarget.tabIndex < 0
1947
+ ) {
1942
1948
  focusTarget.setAttribute('tabindex', '0');
1943
1949
  }
1944
1950
 
@@ -1955,7 +1961,7 @@ export class InkView {
1955
1961
  addListener(canvas, 'pointerdown', (event) => {
1956
1962
  const { x, y } = getPointerPosition(canvas, event);
1957
1963
  this.notifyUserInteraction();
1958
- if (focusTarget && typeof focusTarget.focus === 'function') {
1964
+ if (syncFocus && focusTarget && typeof focusTarget.focus === 'function') {
1959
1965
  focusTarget.focus();
1960
1966
  }
1961
1967
  this.#rawView.dispatchPointer(
@@ -2039,12 +2045,14 @@ export class InkView {
2039
2045
  );
2040
2046
  this.requestRender();
2041
2047
  });
2042
- addListener(focusTarget, 'focus', () => {
2043
- this.focus();
2044
- });
2045
- addListener(focusTarget, 'blur', () => {
2046
- this.blur();
2047
- });
2048
+ if (syncFocus) {
2049
+ addListener(focusTarget, 'focus', () => {
2050
+ this.focus();
2051
+ });
2052
+ addListener(focusTarget, 'blur', () => {
2053
+ this.blur();
2054
+ });
2055
+ }
2048
2056
 
2049
2057
  this.#domCleanup = () => {
2050
2058
  for (const dispose of listeners.splice(0)) {
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "access": "public",
11
11
  "registry": "https://registry.npmjs.com/"
12
12
  },
13
- "version": "0.16.0",
13
+ "version": "0.16.1",
14
14
  "type": "module",
15
15
  "main": "index.js",
16
16
  "types": "index.d.ts",
Binary file