@fcannizzaro/streamdeck-react 0.1.10 → 0.1.12

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.
Files changed (76) hide show
  1. package/LICENSE +190 -21
  2. package/README.md +2 -0
  3. package/dist/action.d.ts +2 -2
  4. package/dist/action.js +1 -2
  5. package/dist/adapter/index.d.ts +2 -0
  6. package/dist/adapter/physical-device.d.ts +2 -0
  7. package/dist/adapter/physical-device.js +153 -0
  8. package/dist/adapter/types.d.ts +127 -0
  9. package/dist/bundler-shared.d.ts +11 -0
  10. package/dist/bundler-shared.js +11 -0
  11. package/dist/context/event-bus.d.ts +1 -1
  12. package/dist/context/event-bus.js +1 -1
  13. package/dist/context/touchstrip-context.d.ts +2 -0
  14. package/dist/context/touchstrip-context.js +5 -0
  15. package/dist/devtools/bridge.d.ts +35 -7
  16. package/dist/devtools/bridge.js +152 -46
  17. package/dist/devtools/highlight.d.ts +5 -0
  18. package/dist/devtools/highlight.js +107 -57
  19. package/dist/devtools/index.js +6 -0
  20. package/dist/devtools/observers/lifecycle.d.ts +4 -4
  21. package/dist/devtools/server.d.ts +6 -1
  22. package/dist/devtools/server.js +6 -1
  23. package/dist/devtools/types.d.ts +50 -6
  24. package/dist/font-inline.d.ts +5 -1
  25. package/dist/font-inline.js +8 -3
  26. package/dist/hooks/animation.d.ts +154 -0
  27. package/dist/hooks/animation.js +381 -0
  28. package/dist/hooks/events.js +2 -6
  29. package/dist/hooks/sdk.js +11 -11
  30. package/dist/hooks/touchstrip.d.ts +6 -0
  31. package/dist/hooks/touchstrip.js +37 -0
  32. package/dist/hooks/utility.js +3 -2
  33. package/dist/index.d.ts +9 -2
  34. package/dist/index.js +4 -2
  35. package/dist/manifest-codegen.d.ts +38 -0
  36. package/dist/manifest-codegen.js +110 -0
  37. package/dist/plugin.js +86 -106
  38. package/dist/reconciler/host-config.js +19 -1
  39. package/dist/reconciler/vnode.d.ts +26 -2
  40. package/dist/reconciler/vnode.js +40 -10
  41. package/dist/render/buffer-pool.d.ts +19 -0
  42. package/dist/render/buffer-pool.js +51 -0
  43. package/dist/render/cache.d.ts +29 -0
  44. package/dist/render/cache.js +137 -5
  45. package/dist/render/image-cache.d.ts +54 -0
  46. package/dist/render/image-cache.js +144 -0
  47. package/dist/render/metrics.d.ts +57 -0
  48. package/dist/render/metrics.js +98 -0
  49. package/dist/render/pipeline.d.ts +36 -1
  50. package/dist/render/pipeline.js +304 -34
  51. package/dist/render/png.d.ts +1 -1
  52. package/dist/render/png.js +26 -11
  53. package/dist/render/render-pool.d.ts +24 -0
  54. package/dist/render/render-pool.js +130 -0
  55. package/dist/render/svg.d.ts +7 -0
  56. package/dist/render/svg.js +139 -0
  57. package/dist/render/worker.d.ts +1 -0
  58. package/dist/rollup.d.ts +23 -9
  59. package/dist/rollup.js +24 -9
  60. package/dist/roots/registry.d.ts +9 -11
  61. package/dist/roots/registry.js +39 -42
  62. package/dist/roots/root.d.ts +9 -6
  63. package/dist/roots/root.js +52 -29
  64. package/dist/roots/settings-equality.d.ts +5 -0
  65. package/dist/roots/settings-equality.js +24 -0
  66. package/dist/roots/{touchbar-root.d.ts → touchstrip-root.d.ts} +30 -8
  67. package/dist/roots/touchstrip-root.js +263 -0
  68. package/dist/types.d.ts +73 -23
  69. package/dist/vite.d.ts +22 -8
  70. package/dist/vite.js +24 -8
  71. package/package.json +7 -4
  72. package/dist/context/touchbar-context.d.ts +0 -2
  73. package/dist/context/touchbar-context.js +0 -5
  74. package/dist/hooks/touchbar.d.ts +0 -6
  75. package/dist/hooks/touchbar.js +0 -37
  76. package/dist/roots/touchbar-root.js +0 -175
@@ -0,0 +1,139 @@
1
+ //#region src/render/svg.ts
2
+ var SVG_CAMEL_ATTRS = new Set([
3
+ "accentHeight",
4
+ "alignmentBaseline",
5
+ "arabicForm",
6
+ "baselineShift",
7
+ "capHeight",
8
+ "clipPath",
9
+ "clipPathUnits",
10
+ "clipRule",
11
+ "colorInterpolation",
12
+ "colorInterpolationFilters",
13
+ "colorProfile",
14
+ "colorRendering",
15
+ "enableBackground",
16
+ "fillOpacity",
17
+ "fillRule",
18
+ "floodColor",
19
+ "floodOpacity",
20
+ "fontFamily",
21
+ "fontSize",
22
+ "fontSizeAdjust",
23
+ "fontStretch",
24
+ "fontStyle",
25
+ "fontVariant",
26
+ "fontWeight",
27
+ "glyphName",
28
+ "glyphOrientationHorizontal",
29
+ "glyphOrientationVertical",
30
+ "horizAdvX",
31
+ "horizOriginX",
32
+ "imageRendering",
33
+ "letterSpacing",
34
+ "lightingColor",
35
+ "markerEnd",
36
+ "markerMid",
37
+ "markerStart",
38
+ "overlinePosition",
39
+ "overlineThickness",
40
+ "paintOrder",
41
+ "pointerEvents",
42
+ "preserveAspectRatio",
43
+ "shapeRendering",
44
+ "stopColor",
45
+ "stopOpacity",
46
+ "strokeDasharray",
47
+ "strokeDashoffset",
48
+ "strokeLinecap",
49
+ "strokeLinejoin",
50
+ "strokeMiterlimit",
51
+ "strokeOpacity",
52
+ "strokeWidth",
53
+ "textAnchor",
54
+ "textDecoration",
55
+ "textRendering",
56
+ "transformOrigin",
57
+ "underlinePosition",
58
+ "underlineThickness",
59
+ "unicodeBidi",
60
+ "unicodeRange",
61
+ "unitsPerEm",
62
+ "vAlphabetic",
63
+ "vHanging",
64
+ "vIdeographic",
65
+ "vMathematical",
66
+ "vectorEffect",
67
+ "vertAdvY",
68
+ "vertOriginX",
69
+ "vertOriginY",
70
+ "wordSpacing",
71
+ "writingMode"
72
+ ]);
73
+ var SKIP_PROPS = new Set([
74
+ "children",
75
+ "key",
76
+ "ref",
77
+ "__self",
78
+ "__source"
79
+ ]);
80
+ function camelToKebab(str) {
81
+ return str.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`);
82
+ }
83
+ function escapeAttr(value) {
84
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
85
+ }
86
+ function serializeStyle(style) {
87
+ const parts = [];
88
+ for (const key of Object.keys(style)) {
89
+ const value = style[key];
90
+ if (value == null) continue;
91
+ parts.push(`${camelToKebab(key)}:${String(value).trim()}`);
92
+ }
93
+ return parts.join(";");
94
+ }
95
+ function serializeAttr(key, value) {
96
+ if (SKIP_PROPS.has(key) || value == null) return null;
97
+ let attrName;
98
+ if (key === "className") attrName = "class";
99
+ else if (SVG_CAMEL_ATTRS.has(key)) attrName = camelToKebab(key);
100
+ else attrName = key;
101
+ if (key === "style" && typeof value === "object") {
102
+ const css = serializeStyle(value);
103
+ if (!css) return null;
104
+ return `${attrName}="${escapeAttr(css)}"`;
105
+ }
106
+ if (typeof value === "boolean") return `${attrName}="${String(value)}"`;
107
+ return `${attrName}="${escapeAttr(String(value))}"`;
108
+ }
109
+ function serializeVNode(node) {
110
+ if (node.type === "#text") return node.text ?? "";
111
+ const attrs = [];
112
+ for (const [key, value] of Object.entries(node.props)) {
113
+ const attr = serializeAttr(key, value);
114
+ if (attr != null) attrs.push(attr);
115
+ }
116
+ const childMarkup = node.children.map(serializeVNode).join("");
117
+ const attrStr = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
118
+ return `<${node.type}${attrStr}>${childMarkup}</${node.type}>`;
119
+ }
120
+ /**
121
+ * Serialize an `<svg>` VNode (and its entire subtree) to an SVG markup string.
122
+ * Auto-injects `xmlns="http://www.w3.org/2000/svg"` if not present.
123
+ * The returned string can be used as the `src` of a Takumi ImageNode.
124
+ */
125
+ function serializeSvgTree(svgNode) {
126
+ if (!("xmlns" in svgNode.props)) {
127
+ const original = svgNode.props;
128
+ svgNode.props = {
129
+ ...original,
130
+ xmlns: "http://www.w3.org/2000/svg"
131
+ };
132
+ const result = serializeVNode(svgNode);
133
+ svgNode.props = original;
134
+ return result;
135
+ }
136
+ return serializeVNode(svgNode);
137
+ }
138
+ //#endregion
139
+ export { serializeSvgTree };
@@ -0,0 +1 @@
1
+ export {};
package/dist/rollup.d.ts CHANGED
@@ -1,16 +1,30 @@
1
1
  import { Plugin } from 'rollup';
2
2
  import { StreamDeckTargetOptions } from './bundler-shared';
3
3
  export type { StreamDeckPlatform, StreamDeckArch, StreamDeckTarget, StreamDeckTargetOptions, } from './bundler-shared';
4
+ export interface StreamDeckRollupOptions extends StreamDeckTargetOptions {
5
+ /**
6
+ * Path to the plugin `manifest.json`. When omitted, the plugin
7
+ * auto-detects by scanning the project root for a `*.sdPlugin/manifest.json`.
8
+ *
9
+ * Set to `false` to disable manifest type generation entirely.
10
+ */
11
+ manifest?: string | false;
12
+ }
4
13
  /**
5
- * Rollup plugin that copies the `@takumi-rs/core` platform-specific native
6
- * binding (`.node` file) into the bundle output directory so the Stream Deck
7
- * Node.js runtime can find it at startup.
14
+ * Rollup plugin for Stream Deck React projects.
8
15
  *
9
- * Font files (`.ttf`, `.otf`, `.woff`, `.woff2`) imported by the project are
10
- * automatically inlined into the bundle as `Buffer` instances so no runtime
11
- * filesystem access is needed.
16
+ * Same responsibilities as the Vite plugin (see vite.ts) with
17
+ * Rollup-specific differences:
12
18
  *
13
- * In production builds (non-watch mode), the devtools module is replaced with
14
- * a noop stub so the entire devtools tree and `ws` dependency are eliminated.
19
+ * - No `configResolved` dev mode detected via `this.meta.watchMode`
20
+ * - `onLog` suppresses `MODULE_LEVEL_DIRECTIVE` warnings (caused by
21
+ * "use client" directives in React dependencies)
22
+ * - `buildStart` resolves root via `resolve(".")` (no Vite config)
23
+ * - `writeBundle` reads output dir from `outputOptions.dir` or
24
+ * `dirname(outputOptions.file)` (Rollup supports both)
25
+ * - No `closeBundle` restart hook (handled externally)
26
+ *
27
+ * Font inlining and manifest codegen are shared via bundler-shared.ts,
28
+ * font-inline.ts, and manifest-codegen.ts.
15
29
  */
16
- export declare function streamDeckReact(options?: StreamDeckTargetOptions): Plugin;
30
+ export declare function streamDeckReact(options?: StreamDeckRollupOptions): Plugin;
package/dist/rollup.js CHANGED
@@ -1,18 +1,24 @@
1
1
  import { NOOP_DEVTOOLS_CODE, NOOP_DEVTOOLS_ID, copyNativeBindings, isDevelopmentMode, isLibraryDevtoolsImport, shouldStripDevtools } from "./bundler-shared.js";
2
2
  import { loadFont, resolveFontId } from "./font-inline.js";
3
- import { dirname } from "node:path";
3
+ import { generateManifestTypes } from "./manifest-codegen.js";
4
+ import { dirname, resolve } from "node:path";
4
5
  //#region src/rollup.ts
5
6
  /**
6
- * Rollup plugin that copies the `@takumi-rs/core` platform-specific native
7
- * binding (`.node` file) into the bundle output directory so the Stream Deck
8
- * Node.js runtime can find it at startup.
7
+ * Rollup plugin for Stream Deck React projects.
9
8
  *
10
- * Font files (`.ttf`, `.otf`, `.woff`, `.woff2`) imported by the project are
11
- * automatically inlined into the bundle as `Buffer` instances so no runtime
12
- * filesystem access is needed.
9
+ * Same responsibilities as the Vite plugin (see vite.ts) with
10
+ * Rollup-specific differences:
13
11
  *
14
- * In production builds (non-watch mode), the devtools module is replaced with
15
- * a noop stub so the entire devtools tree and `ws` dependency are eliminated.
12
+ * - No `configResolved` dev mode detected via `this.meta.watchMode`
13
+ * - `onLog` suppresses `MODULE_LEVEL_DIRECTIVE` warnings (caused by
14
+ * "use client" directives in React dependencies)
15
+ * - `buildStart` resolves root via `resolve(".")` (no Vite config)
16
+ * - `writeBundle` reads output dir from `outputOptions.dir` or
17
+ * `dirname(outputOptions.file)` (Rollup supports both)
18
+ * - No `closeBundle` restart hook (handled externally)
19
+ *
20
+ * Font inlining and manifest codegen are shared via bundler-shared.ts,
21
+ * font-inline.ts, and manifest-codegen.ts.
16
22
  */
17
23
  function streamDeckReact(options = {}) {
18
24
  return {
@@ -20,6 +26,15 @@ function streamDeckReact(options = {}) {
20
26
  onLog(_level, log) {
21
27
  if (log.code === "MODULE_LEVEL_DIRECTIVE") return false;
22
28
  },
29
+ buildStart() {
30
+ const root = resolve(".");
31
+ const warn = (msg) => this.warn(msg);
32
+ const result = generateManifestTypes(root, options.manifest, warn);
33
+ if (result) {
34
+ this.addWatchFile(result.manifestPath);
35
+ if (result.written) console.log("[@fcannizzaro/streamdeck-react] Generated src/streamdeck-env.d.ts");
36
+ }
37
+ },
23
38
  resolveId: {
24
39
  order: "pre",
25
40
  handler(source, importer) {
@@ -1,29 +1,27 @@
1
1
  import { ComponentType } from 'react';
2
- import { WillAppearEvent } from '@elgato/streamdeck';
3
2
  import { JsonObject } from '@elgato/utils';
4
- import { ActionDefinition, EventMap, StreamDeckAccess, WrapperComponent } from '../types';
3
+ import { AdapterWillAppearEvent, StreamDeckAdapter } from '../adapter/types';
4
+ import { ActionDefinition, EventMap, WrapperComponent } from '../types';
5
5
  import { RenderConfig } from '../render/pipeline';
6
6
  import { RegistryObserver } from '../devtools/observers/lifecycle';
7
7
  export declare class RootRegistry {
8
8
  private roots;
9
- private touchBarRoots;
10
- private touchBarActions;
9
+ private touchStripRoots;
10
+ private touchStripActions;
11
11
  private renderConfig;
12
- private renderDebounceMs;
13
- private sdkInstance;
12
+ private adapter;
14
13
  private globalSettings;
15
14
  private onGlobalSettingsChange;
16
15
  private wrapper?;
17
16
  /** DevTools observer. Set externally by startDevtoolsServer(). null when devtools is off. */
18
17
  observer: RegistryObserver | null;
19
- constructor(renderConfig: RenderConfig, renderDebounceMs: number, sdkInstance: StreamDeckAccess["sdk"], onGlobalSettingsChange: (settings: JsonObject) => Promise<void>, wrapper?: WrapperComponent);
18
+ constructor(renderConfig: RenderConfig, adapter: StreamDeckAdapter, onGlobalSettingsChange: (settings: JsonObject) => Promise<void>, wrapper?: WrapperComponent);
20
19
  setGlobalSettings(settings: JsonObject): void;
21
- create(ev: WillAppearEvent<JsonObject>, component: ComponentType, definition: ActionDefinition): void;
22
- private registerTouchBarColumn;
23
- private getEncoderColumn;
20
+ create(ev: AdapterWillAppearEvent, component: ComponentType, definition: ActionDefinition): void;
21
+ private registerTouchStripColumn;
24
22
  destroy(contextId: string): void;
25
23
  dispatch<K extends keyof EventMap>(contextId: string, event: K, payload: EventMap[K]): void;
26
- private dispatchToTouchBar;
24
+ private dispatchToTouchStrip;
27
25
  updateSettings(contextId: string, settings: JsonObject): void;
28
26
  destroyAll(): void;
29
27
  }
@@ -1,5 +1,6 @@
1
+ import { shallowEqualSettings } from "./settings-equality.js";
1
2
  import { ReactRoot } from "./root.js";
2
- import { TouchBarRoot } from "./touchbar-root.js";
3
+ import { TouchStripRoot } from "./touchstrip-root.js";
3
4
  //#region src/roots/registry.ts
4
5
  var SEGMENT_WIDTH = 200;
5
6
  var KEY_SIZES = {
@@ -79,36 +80,35 @@ function getCanvasInfo(deviceType, surfaceType) {
79
80
  }
80
81
  var RootRegistry = class {
81
82
  roots = /* @__PURE__ */ new Map();
82
- touchBarRoots = /* @__PURE__ */ new Map();
83
- touchBarActions = /* @__PURE__ */ new Map();
83
+ touchStripRoots = /* @__PURE__ */ new Map();
84
+ touchStripActions = /* @__PURE__ */ new Map();
84
85
  renderConfig;
85
- renderDebounceMs;
86
- sdkInstance;
86
+ adapter;
87
87
  globalSettings = {};
88
88
  onGlobalSettingsChange;
89
89
  wrapper;
90
90
  /** DevTools observer. Set externally by startDevtoolsServer(). null when devtools is off. */
91
91
  observer = null;
92
- constructor(renderConfig, renderDebounceMs, sdkInstance, onGlobalSettingsChange, wrapper) {
92
+ constructor(renderConfig, adapter, onGlobalSettingsChange, wrapper) {
93
93
  this.renderConfig = renderConfig;
94
- this.renderDebounceMs = renderDebounceMs;
95
- this.sdkInstance = sdkInstance;
94
+ this.adapter = adapter;
96
95
  this.onGlobalSettingsChange = onGlobalSettingsChange;
97
96
  this.wrapper = wrapper;
98
97
  }
99
98
  setGlobalSettings(settings) {
99
+ if (shallowEqualSettings(this.globalSettings, settings)) return;
100
100
  this.globalSettings = settings;
101
101
  for (const root of this.roots.values()) root.updateGlobalSettings(settings);
102
- for (const tbRoot of this.touchBarRoots.values()) tbRoot.updateGlobalSettings(settings);
102
+ for (const tbRoot of this.touchStripRoots.values()) tbRoot.updateGlobalSettings(settings);
103
103
  }
104
104
  create(ev, component, definition) {
105
105
  const contextId = ev.action.id;
106
- if (this.roots.has(contextId) || this.touchBarActions.has(contextId)) return;
106
+ if (this.roots.has(contextId) || this.touchStripActions.has(contextId)) return;
107
107
  const device = ev.action.device;
108
108
  const controller = ev.action.controllerType;
109
109
  const isEncoder = controller === "Encoder";
110
- if (isEncoder && definition.touchBar) {
111
- this.registerTouchBarColumn(ev, definition);
110
+ if (isEncoder && definition.touchStrip) {
111
+ this.registerTouchStripColumn(ev, definition);
112
112
  return;
113
113
  }
114
114
  let surfaceType = "key";
@@ -123,11 +123,11 @@ var RootRegistry = class {
123
123
  id: contextId,
124
124
  uuid: definition.uuid,
125
125
  controller,
126
- coordinates: "coordinates" in ev.action ? ev.action.coordinates : void 0,
126
+ coordinates: ev.action.coordinates,
127
127
  isInMultiAction: ev.payload.isInMultiAction
128
128
  };
129
129
  const canvas = getCanvasInfo(device.type, surfaceType);
130
- const root = new ReactRoot(component, actionInfo, deviceInfo, canvas, ev.payload.settings, this.globalSettings, ev.action, this.sdkInstance, this.renderConfig, this.renderDebounceMs, async (settings) => {
130
+ const root = new ReactRoot(component, actionInfo, deviceInfo, canvas, ev.payload.settings, this.globalSettings, ev.action, this.adapter, this.renderConfig, async (settings) => {
131
131
  await ev.action.setSettings(settings);
132
132
  }, this.onGlobalSettingsChange, this.wrapper, definition.wrapper, definition.dialLayout);
133
133
  root.eventBus.emitSticky("willAppear", {
@@ -147,16 +147,16 @@ var RootRegistry = class {
147
147
  } : void 0
148
148
  });
149
149
  }
150
- registerTouchBarColumn(ev, definition) {
150
+ registerTouchStripColumn(ev, definition) {
151
151
  const actionId = ev.action.id;
152
152
  const device = ev.action.device;
153
153
  const deviceId = device.id;
154
- const column = this.getEncoderColumn(ev);
154
+ const column = ev.action.coordinates?.column;
155
155
  if (column === void 0) {
156
- console.warn("[@fcannizzaro/streamdeck-react] Cannot determine encoder column for touchbar action:", actionId);
156
+ console.warn("[@fcannizzaro/streamdeck-react] Cannot determine encoder column for TouchStrip action:", actionId);
157
157
  return;
158
158
  }
159
- let tbRoot = this.touchBarRoots.get(deviceId);
159
+ let tbRoot = this.touchStripRoots.get(deviceId);
160
160
  if (!tbRoot) {
161
161
  const deviceInfo = {
162
162
  id: deviceId,
@@ -164,31 +164,28 @@ var RootRegistry = class {
164
164
  size: device.size,
165
165
  name: device.name
166
166
  };
167
- tbRoot = new TouchBarRoot(definition.touchBar, deviceInfo, this.globalSettings, this.renderConfig, this.renderDebounceMs, this.onGlobalSettingsChange, this.wrapper, definition.touchBarFPS);
168
- this.touchBarRoots.set(deviceId, tbRoot);
169
- this.observer?.onTouchBarCreated(deviceId, tbRoot, deviceInfo);
167
+ tbRoot = new TouchStripRoot(definition.touchStrip, deviceInfo, this.globalSettings, this.renderConfig, this.onGlobalSettingsChange, this.wrapper);
168
+ this.touchStripRoots.set(deviceId, tbRoot);
169
+ this.observer?.onTouchStripCreated(deviceId, tbRoot, deviceInfo);
170
170
  }
171
171
  tbRoot.addColumn(column, actionId, ev.action);
172
- this.observer?.onTouchBarColumnChanged(deviceId, [...tbRoot.columnNumbers], tbRoot.columnActionMap);
173
- this.touchBarActions.set(actionId, deviceId);
174
- }
175
- getEncoderColumn(ev) {
176
- return ev.action.coordinates?.column;
172
+ this.observer?.onTouchStripColumnChanged(deviceId, [...tbRoot.columnNumbers], tbRoot.columnActionMap);
173
+ this.touchStripActions.set(actionId, deviceId);
177
174
  }
178
175
  destroy(contextId) {
179
- const deviceId = this.touchBarActions.get(contextId);
176
+ const deviceId = this.touchStripActions.get(contextId);
180
177
  if (deviceId) {
181
- const tbRoot = this.touchBarRoots.get(deviceId);
178
+ const tbRoot = this.touchStripRoots.get(deviceId);
182
179
  if (tbRoot) {
183
180
  const column = tbRoot.findColumnByActionId(contextId);
184
181
  if (column !== void 0) tbRoot.removeColumn(column);
185
182
  if (tbRoot.isEmpty) {
186
- this.observer?.onTouchBarDestroyed(deviceId);
183
+ this.observer?.onTouchStripDestroyed(deviceId);
187
184
  tbRoot.unmount();
188
- this.touchBarRoots.delete(deviceId);
185
+ this.touchStripRoots.delete(deviceId);
189
186
  }
190
187
  }
191
- this.touchBarActions.delete(contextId);
188
+ this.touchStripActions.delete(contextId);
192
189
  return;
193
190
  }
194
191
  const root = this.roots.get(contextId);
@@ -205,22 +202,22 @@ var RootRegistry = class {
205
202
  this.observer?.onDispatch(contextId, event, payload);
206
203
  return;
207
204
  }
208
- const deviceId = this.touchBarActions.get(contextId);
205
+ const deviceId = this.touchStripActions.get(contextId);
209
206
  if (deviceId) {
210
- const tbRoot = this.touchBarRoots.get(deviceId);
207
+ const tbRoot = this.touchStripRoots.get(deviceId);
211
208
  if (tbRoot) {
212
- this.dispatchToTouchBar(tbRoot, contextId, event, payload);
209
+ this.dispatchToTouchStrip(tbRoot, contextId, event, payload);
213
210
  this.observer?.onDispatch(contextId, event, payload);
214
211
  }
215
212
  }
216
213
  }
217
- dispatchToTouchBar(tbRoot, actionId, event, payload) {
214
+ dispatchToTouchStrip(tbRoot, actionId, event, payload) {
218
215
  const column = tbRoot.findColumnByActionId(actionId);
219
216
  if (column === void 0) return;
220
217
  switch (event) {
221
218
  case "touchTap": {
222
219
  const tp = payload;
223
- tbRoot.eventBus.emit("touchBarTap", {
220
+ tbRoot.eventBus.emit("touchStripTap", {
224
221
  tapPos: [column * SEGMENT_WIDTH + tp.tapPos[0], tp.tapPos[1]],
225
222
  hold: tp.hold,
226
223
  column
@@ -229,7 +226,7 @@ var RootRegistry = class {
229
226
  }
230
227
  case "dialRotate": {
231
228
  const dr = payload;
232
- tbRoot.eventBus.emit("touchBarDialRotate", {
229
+ tbRoot.eventBus.emit("touchStripDialRotate", {
233
230
  column,
234
231
  ticks: dr.ticks,
235
232
  pressed: dr.pressed
@@ -237,10 +234,10 @@ var RootRegistry = class {
237
234
  break;
238
235
  }
239
236
  case "dialDown":
240
- tbRoot.eventBus.emit("touchBarDialDown", { column });
237
+ tbRoot.eventBus.emit("touchStripDialDown", { column });
241
238
  break;
242
239
  case "dialUp":
243
- tbRoot.eventBus.emit("touchBarDialUp", { column });
240
+ tbRoot.eventBus.emit("touchStripDialUp", { column });
244
241
  break;
245
242
  }
246
243
  }
@@ -251,9 +248,9 @@ var RootRegistry = class {
251
248
  destroyAll() {
252
249
  for (const [_, root] of this.roots) root.unmount();
253
250
  this.roots.clear();
254
- for (const [_, tbRoot] of this.touchBarRoots) tbRoot.unmount();
255
- this.touchBarRoots.clear();
256
- this.touchBarActions.clear();
251
+ for (const [_, tbRoot] of this.touchStripRoots) tbRoot.unmount();
252
+ this.touchStripRoots.clear();
253
+ this.touchStripActions.clear();
257
254
  }
258
255
  };
259
256
  //#endregion
@@ -2,9 +2,9 @@ import { ComponentType } from 'react';
2
2
  import { VContainer } from '../reconciler/vnode';
3
3
  import { RenderConfig } from '../render/pipeline';
4
4
  import { EventBus } from '../context/event-bus';
5
- import { ActionInfo, CanvasInfo, DeviceInfo, EncoderLayout, StreamDeckAccess, WrapperComponent } from '../types';
5
+ import { ActionInfo, CanvasInfo, DeviceInfo, EncoderLayout, WrapperComponent } from '../types';
6
6
  import { JsonObject } from '@elgato/utils';
7
- import { Action, DialAction, KeyAction } from '@elgato/streamdeck';
7
+ import { AdapterActionHandle, StreamDeckAdapter } from '../adapter/types';
8
8
  export declare class ReactRoot {
9
9
  private component;
10
10
  private actionInfo;
@@ -18,13 +18,16 @@ export declare class ReactRoot {
18
18
  private globalSettings;
19
19
  private setSettingsFn;
20
20
  private setGlobalSettingsFn;
21
- private renderDebounceMs;
21
+ private readonly renderDebounceMs;
22
22
  private renderConfig;
23
23
  private canvas;
24
24
  private resolvedDialLayout;
25
- private sdkAction;
26
- private sdkInstance;
25
+ private action;
26
+ private adapter;
27
27
  private disposed;
28
+ private _renderCount;
29
+ private _lastRenderReport;
30
+ private static readonly RENDER_WARN_THRESHOLD;
28
31
  /** Last data URI successfully sent to hardware. Used by devtools snapshots. */
29
32
  lastDataUri: string | null;
30
33
  /**
@@ -41,7 +44,7 @@ export declare class ReactRoot {
41
44
  private streamDeckValue;
42
45
  private settingsValue;
43
46
  private globalSettingsValue;
44
- constructor(component: ComponentType, actionInfo: ActionInfo, deviceInfo: DeviceInfo, canvas: CanvasInfo, initialSettings: JsonObject, initialGlobalSettings: JsonObject, sdkAction: Action | DialAction | KeyAction, sdkInstance: StreamDeckAccess["sdk"], renderConfig: RenderConfig, renderDebounceMs: number, onSettingsChange: (settings: JsonObject) => Promise<void>, onGlobalSettingsChange: (settings: JsonObject) => Promise<void>, pluginWrapper?: WrapperComponent | undefined, actionWrapper?: WrapperComponent | undefined, dialLayout?: EncoderLayout);
47
+ constructor(component: ComponentType, actionInfo: ActionInfo, deviceInfo: DeviceInfo, canvas: CanvasInfo, initialSettings: JsonObject, initialGlobalSettings: JsonObject, action: AdapterActionHandle, adapter: StreamDeckAdapter, renderConfig: RenderConfig, onSettingsChange: (settings: JsonObject) => Promise<void>, onGlobalSettingsChange: (settings: JsonObject) => Promise<void>, pluginWrapper?: WrapperComponent | undefined, actionWrapper?: WrapperComponent | undefined, dialLayout?: EncoderLayout);
45
48
  private render;
46
49
  private buildTree;
47
50
  private scheduleRerender;