@fcannizzaro/streamdeck-react 0.1.11 → 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 (43) hide show
  1. package/dist/action.js +0 -1
  2. package/dist/adapter/index.d.ts +2 -0
  3. package/dist/adapter/physical-device.d.ts +2 -0
  4. package/dist/adapter/physical-device.js +153 -0
  5. package/dist/adapter/types.d.ts +127 -0
  6. package/dist/devtools/bridge.d.ts +2 -2
  7. package/dist/devtools/bridge.js +7 -8
  8. package/dist/devtools/highlight.d.ts +1 -2
  9. package/dist/devtools/highlight.js +4 -3
  10. package/dist/devtools/types.d.ts +5 -5
  11. package/dist/hooks/animation.d.ts +1 -1
  12. package/dist/hooks/animation.js +2 -2
  13. package/dist/hooks/events.js +1 -1
  14. package/dist/hooks/sdk.js +11 -11
  15. package/dist/hooks/utility.js +3 -2
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.js +2 -1
  18. package/dist/plugin.js +69 -100
  19. package/dist/reconciler/vnode.d.ts +0 -2
  20. package/dist/reconciler/vnode.js +0 -1
  21. package/dist/render/cache.d.ts +5 -17
  22. package/dist/render/cache.js +7 -29
  23. package/dist/render/image-cache.d.ts +8 -7
  24. package/dist/render/image-cache.js +33 -17
  25. package/dist/render/metrics.d.ts +9 -10
  26. package/dist/render/metrics.js +36 -39
  27. package/dist/render/pipeline.d.ts +4 -14
  28. package/dist/render/pipeline.js +47 -111
  29. package/dist/render/png.d.ts +0 -9
  30. package/dist/render/png.js +5 -8
  31. package/dist/render/render-pool.d.ts +0 -2
  32. package/dist/render/render-pool.js +1 -12
  33. package/dist/roots/registry.d.ts +5 -9
  34. package/dist/roots/registry.js +10 -27
  35. package/dist/roots/root.d.ts +7 -34
  36. package/dist/roots/root.js +23 -90
  37. package/dist/roots/touchstrip-root.d.ts +6 -32
  38. package/dist/roots/touchstrip-root.js +61 -181
  39. package/dist/types.d.ts +23 -19
  40. package/package.json +6 -4
  41. package/dist/node_modules/.bun/xxhash-wasm@1.1.0/node_modules/xxhash-wasm/esm/xxhash-wasm.js +0 -3157
  42. package/dist/roots/flush-coordinator.d.ts +0 -18
  43. package/dist/roots/flush-coordinator.js +0 -38
package/dist/action.js CHANGED
@@ -5,7 +5,6 @@ function defineAction(config) {
5
5
  key: config.key,
6
6
  dial: config.dial,
7
7
  touchStrip: config.touchStrip,
8
- touchStripFPS: config.touchStripFPS,
9
8
  dialLayout: config.dialLayout,
10
9
  wrapper: config.wrapper,
11
10
  defaultSettings: config.defaultSettings ?? {}
@@ -0,0 +1,2 @@
1
+ export type { StreamDeckAdapter, AdapterActionHandle, AdapterActionCallbacks, AdapterWillAppearEvent, AdapterActionDevice, AdapterController, AdapterCoordinates, AdapterSize, AdapterTriggerDescription, AdapterKeyDownPayload, AdapterKeyUpPayload, AdapterDialRotatePayload, AdapterDialPressPayload, AdapterTouchTapPayload, } from './types';
2
+ export { physicalDevice } from './physical-device';
@@ -0,0 +1,2 @@
1
+ import { StreamDeckAdapter } from './types';
2
+ export declare function physicalDevice(): StreamDeckAdapter;
@@ -0,0 +1,153 @@
1
+ import streamDeck, { SingletonAction } from "@elgato/streamdeck";
2
+ //#region src/adapter/physical-device.ts
3
+ function wrapSdkAction(action) {
4
+ return {
5
+ id: action.id,
6
+ device: {
7
+ id: action.device.id,
8
+ type: action.device.type,
9
+ size: action.device.size,
10
+ name: action.device.name
11
+ },
12
+ controllerType: action.controllerType,
13
+ coordinates: "coordinates" in action ? action.coordinates : void 0,
14
+ async setImage(dataUri) {
15
+ if ("setImage" in action) await action.setImage(dataUri);
16
+ },
17
+ async setTitle(title) {
18
+ if ("setTitle" in action) await action.setTitle(title);
19
+ },
20
+ async showOk() {
21
+ if ("showOk" in action) await action.showOk();
22
+ },
23
+ async showAlert() {
24
+ await action.showAlert();
25
+ },
26
+ async setSettings(settings) {
27
+ await action.setSettings(settings);
28
+ },
29
+ async setFeedback(payload) {
30
+ if ("setFeedback" in action) await action.setFeedback(payload);
31
+ },
32
+ async setFeedbackLayout(layout) {
33
+ if ("setFeedbackLayout" in action) await action.setFeedbackLayout(layout);
34
+ },
35
+ async setTriggerDescription(hints) {
36
+ if ("setTriggerDescription" in action) await action.setTriggerDescription({
37
+ rotate: hints.rotate,
38
+ push: hints.push,
39
+ touch: hints.touch,
40
+ longTouch: hints.longTouch
41
+ });
42
+ }
43
+ };
44
+ }
45
+ function physicalDevice() {
46
+ return {
47
+ pluginUUID: streamDeck.info.plugin.uuid,
48
+ async connect() {
49
+ await streamDeck.connect();
50
+ },
51
+ async getGlobalSettings() {
52
+ return streamDeck.settings.getGlobalSettings();
53
+ },
54
+ async setGlobalSettings(settings) {
55
+ await streamDeck.settings.setGlobalSettings(settings);
56
+ },
57
+ onGlobalSettingsChanged(callback) {
58
+ streamDeck.settings.onDidReceiveGlobalSettings((ev) => {
59
+ callback(ev.settings);
60
+ });
61
+ },
62
+ registerAction(uuid, callbacks) {
63
+ const singletonAction = new class extends SingletonAction {
64
+ manifestId = uuid;
65
+ onWillAppear(ev) {
66
+ callbacks.onWillAppear({
67
+ action: wrapSdkAction(ev.action),
68
+ payload: {
69
+ settings: ev.payload.settings,
70
+ controller: ev.payload.controller,
71
+ isInMultiAction: ev.payload.isInMultiAction
72
+ }
73
+ });
74
+ }
75
+ onWillDisappear(ev) {
76
+ callbacks.onWillDisappear(ev.action.id);
77
+ }
78
+ onKeyDown(ev) {
79
+ callbacks.onKeyDown(ev.action.id, {
80
+ settings: ev.payload.settings,
81
+ isInMultiAction: ev.payload.isInMultiAction,
82
+ state: ev.payload.state,
83
+ userDesiredState: "userDesiredState" in ev.payload ? ev.payload.userDesiredState : void 0
84
+ });
85
+ }
86
+ onKeyUp(ev) {
87
+ callbacks.onKeyUp(ev.action.id, {
88
+ settings: ev.payload.settings,
89
+ isInMultiAction: ev.payload.isInMultiAction,
90
+ state: ev.payload.state,
91
+ userDesiredState: "userDesiredState" in ev.payload ? ev.payload.userDesiredState : void 0
92
+ });
93
+ }
94
+ onDialRotate(ev) {
95
+ callbacks.onDialRotate(ev.action.id, {
96
+ ticks: ev.payload.ticks,
97
+ pressed: ev.payload.pressed,
98
+ settings: ev.payload.settings
99
+ });
100
+ }
101
+ onDialDown(ev) {
102
+ callbacks.onDialDown(ev.action.id, {
103
+ settings: ev.payload.settings,
104
+ controller: "Encoder"
105
+ });
106
+ }
107
+ onDialUp(ev) {
108
+ callbacks.onDialUp(ev.action.id, {
109
+ settings: ev.payload.settings,
110
+ controller: "Encoder"
111
+ });
112
+ }
113
+ onTouchTap(ev) {
114
+ callbacks.onTouchTap(ev.action.id, {
115
+ tapPos: ev.payload.tapPos,
116
+ hold: ev.payload.hold,
117
+ settings: ev.payload.settings
118
+ });
119
+ }
120
+ onDidReceiveSettings(ev) {
121
+ callbacks.onDidReceiveSettings(ev.action.id, ev.payload.settings);
122
+ }
123
+ onSendToPlugin(ev) {
124
+ callbacks.onSendToPlugin(ev.action.id, ev.payload);
125
+ }
126
+ onPropertyInspectorDidAppear(ev) {
127
+ callbacks.onPropertyInspectorDidAppear(ev.action.id);
128
+ }
129
+ onPropertyInspectorDidDisappear(ev) {
130
+ callbacks.onPropertyInspectorDidDisappear(ev.action.id);
131
+ }
132
+ onTitleParametersDidChange(ev) {
133
+ callbacks.onTitleParametersDidChange(ev.action.id, {
134
+ title: ev.payload.title,
135
+ settings: ev.payload.settings
136
+ });
137
+ }
138
+ }();
139
+ streamDeck.actions.registerAction(singletonAction);
140
+ },
141
+ async openUrl(url) {
142
+ await streamDeck.system.openUrl(url);
143
+ },
144
+ async switchToProfile(deviceId, profile) {
145
+ await streamDeck.profiles.switchToProfile(deviceId, profile);
146
+ },
147
+ async sendToPropertyInspector(payload) {
148
+ await streamDeck.ui.sendToPropertyInspector(payload);
149
+ }
150
+ };
151
+ }
152
+ //#endregion
153
+ export { physicalDevice };
@@ -0,0 +1,127 @@
1
+ import { JsonObject, JsonValue } from '@elgato/utils';
2
+ /** Controller surface type. Matches SDK Controller values exactly. */
3
+ export type AdapterController = "Keypad" | "Encoder";
4
+ /** Grid coordinates for a key or encoder on a device. */
5
+ export interface AdapterCoordinates {
6
+ readonly column: number;
7
+ readonly row: number;
8
+ }
9
+ /** Device grid size (number of key columns and rows). */
10
+ export interface AdapterSize {
11
+ readonly columns: number;
12
+ readonly rows: number;
13
+ }
14
+ /** Hint labels for dial/encoder trigger zones shown on the Stream Deck LCD. */
15
+ export interface AdapterTriggerDescription {
16
+ rotate?: string;
17
+ push?: string;
18
+ touch?: string;
19
+ longTouch?: string;
20
+ }
21
+ export interface AdapterActionHandle {
22
+ readonly id: string;
23
+ readonly device: AdapterActionDevice;
24
+ readonly controllerType: AdapterController;
25
+ readonly coordinates?: AdapterCoordinates;
26
+ /** Push a rendered data URI to the key display. No-op on encoder surfaces. */
27
+ setImage(dataUri: string): Promise<void>;
28
+ /** Set the key title overlay. No-op on encoder surfaces. */
29
+ setTitle(title: string): Promise<void>;
30
+ /** Flash the OK checkmark on the key. No-op on encoder surfaces. */
31
+ showOk(): Promise<void>;
32
+ /** Flash the alert triangle on the action. */
33
+ showAlert(): Promise<void>;
34
+ /** Persist action settings to the Stream Deck. */
35
+ setSettings(settings: JsonObject): Promise<void>;
36
+ /** Push dial/touchstrip feedback payload. No-op on key surfaces. */
37
+ setFeedback(payload: Record<string, unknown>): Promise<void>;
38
+ /** Set the encoder feedback layout (JSON or layout ID). No-op on key surfaces. */
39
+ setFeedbackLayout(layout: string | Record<string, unknown>): Promise<void>;
40
+ /** Set dial hint text (rotate, push, touch labels). No-op on key surfaces. */
41
+ setTriggerDescription(hints: AdapterTriggerDescription): Promise<void>;
42
+ }
43
+ /** Device info as seen from an action event. */
44
+ export interface AdapterActionDevice {
45
+ readonly id: string;
46
+ /**
47
+ * Numeric device type matching Elgato DeviceType enum values.
48
+ * Using `number` instead of the SDK's enum avoids coupling to specific
49
+ * device models while remaining compatible with the KEY_SIZES lookup
50
+ * table in registry.ts.
51
+ */
52
+ readonly type: number;
53
+ readonly size: AdapterSize;
54
+ readonly name: string;
55
+ }
56
+ /** Event payload provided to onWillAppear callbacks. */
57
+ export interface AdapterWillAppearEvent {
58
+ action: AdapterActionHandle;
59
+ payload: {
60
+ settings: JsonObject;
61
+ controller: AdapterController;
62
+ isInMultiAction: boolean;
63
+ };
64
+ }
65
+ export interface AdapterKeyDownPayload {
66
+ settings: JsonObject;
67
+ isInMultiAction: boolean;
68
+ state?: number;
69
+ userDesiredState?: number;
70
+ }
71
+ export interface AdapterKeyUpPayload {
72
+ settings: JsonObject;
73
+ isInMultiAction: boolean;
74
+ state?: number;
75
+ userDesiredState?: number;
76
+ }
77
+ export interface AdapterDialRotatePayload {
78
+ ticks: number;
79
+ pressed: boolean;
80
+ settings: JsonObject;
81
+ }
82
+ export interface AdapterDialPressPayload {
83
+ settings: JsonObject;
84
+ controller: "Encoder";
85
+ }
86
+ export interface AdapterTouchTapPayload {
87
+ tapPos: [x: number, y: number];
88
+ hold: boolean;
89
+ settings: JsonObject;
90
+ }
91
+ export interface AdapterActionCallbacks {
92
+ onWillAppear(ev: AdapterWillAppearEvent): void;
93
+ onWillDisappear(actionId: string): void;
94
+ onKeyDown(actionId: string, payload: AdapterKeyDownPayload): void;
95
+ onKeyUp(actionId: string, payload: AdapterKeyUpPayload): void;
96
+ onDialRotate(actionId: string, payload: AdapterDialRotatePayload): void;
97
+ onDialDown(actionId: string, payload: AdapterDialPressPayload): void;
98
+ onDialUp(actionId: string, payload: AdapterDialPressPayload): void;
99
+ onTouchTap(actionId: string, payload: AdapterTouchTapPayload): void;
100
+ onDidReceiveSettings(actionId: string, settings: JsonObject): void;
101
+ onSendToPlugin(actionId: string, payload: JsonValue): void;
102
+ onPropertyInspectorDidAppear(actionId: string): void;
103
+ onPropertyInspectorDidDisappear(actionId: string): void;
104
+ onTitleParametersDidChange(actionId: string, payload: {
105
+ title: string;
106
+ settings: JsonObject;
107
+ }): void;
108
+ }
109
+ export interface StreamDeckAdapter {
110
+ /** Plugin UUID, used for devtools identification. */
111
+ readonly pluginUUID: string;
112
+ /** Initialize the adapter and connect to the backend. */
113
+ connect(): Promise<void>;
114
+ /** Retrieve plugin-wide global settings. */
115
+ getGlobalSettings<T extends JsonObject = JsonObject>(): Promise<T>;
116
+ /** Persist plugin-wide global settings. */
117
+ setGlobalSettings<T extends JsonObject = JsonObject>(settings: T): Promise<void>;
118
+ /** Subscribe to external global settings changes (e.g. from Property Inspector). */
119
+ onGlobalSettingsChanged(callback: (settings: JsonObject) => void): void;
120
+ registerAction(uuid: string, callbacks: AdapterActionCallbacks): void;
121
+ /** Open a URL in the user's default browser. */
122
+ openUrl(url: string): Promise<void>;
123
+ /** Switch the active Stream Deck profile. */
124
+ switchToProfile(deviceId: string, profile: string): Promise<void>;
125
+ /** Send a payload to the Property Inspector. */
126
+ sendToPropertyInspector(payload: JsonValue): Promise<void>;
127
+ }
@@ -63,7 +63,7 @@ export declare class DevtoolsBridge implements RegistryObserver {
63
63
  private static readonly TB_PREFIX;
64
64
  private handleHighlight;
65
65
  /**
66
- * Restore a highlighted action or touchstrip to its normal state.
66
+ * Restore a highlighted action or TouchStrip to its normal state.
67
67
  * Un-suppresses hardware pushes and restores the original image(s).
68
68
  */
69
69
  private restoreHighlight;
@@ -73,7 +73,7 @@ export declare class DevtoolsBridge implements RegistryObserver {
73
73
  private broadcastHighlightRender;
74
74
  /**
75
75
  * Clear highlight URIs for the given actionId.
76
- * For touchstrip IDs, clears all per-segment keys (touchstrip:*:seg:N).
76
+ * For TouchStrip IDs, clears all per-segment keys (touchStrip:*:seg:N).
77
77
  * For regular actions, clears the single actionId key.
78
78
  */
79
79
  private broadcastHighlightClear;
@@ -141,7 +141,7 @@ var DevtoolsBridge = class DevtoolsBridge {
141
141
  columns: /* @__PURE__ */ new Map()
142
142
  });
143
143
  this.eventBusOwners.set(root.eventBus, {
144
- actionId: `touchstrip:${deviceId}`,
144
+ actionId: `touchStrip:${deviceId}`,
145
145
  uuid: ""
146
146
  });
147
147
  }
@@ -339,8 +339,7 @@ var DevtoolsBridge = class DevtoolsBridge {
339
339
  /** Convert internal RenderProfile to wire-protocol ProfileData. */
340
340
  toProfileData(profile) {
341
341
  return {
342
- vnodeToElementMs: profile.vnodeToElementMs,
343
- fromJsxMs: profile.fromJsxMs,
342
+ vnodeConversionMs: profile.vnodeConversionMs,
344
343
  takumiRenderMs: profile.takumiRenderMs,
345
344
  hashMs: profile.hashMs,
346
345
  base64Ms: profile.base64Ms,
@@ -363,7 +362,7 @@ var DevtoolsBridge = class DevtoolsBridge {
363
362
  });
364
363
  }
365
364
  const msg = {
366
- type: "render:touchstrip",
365
+ type: "render:touchStrip",
367
366
  ts: Date.now(),
368
367
  deviceId,
369
368
  canvas: {
@@ -377,7 +376,7 @@ var DevtoolsBridge = class DevtoolsBridge {
377
376
  };
378
377
  this.server.broadcast(msg);
379
378
  }
380
- static TB_PREFIX = "touchstrip:";
379
+ static TB_PREFIX = "touchStrip:";
381
380
  async handleHighlight(actionId, nodeId) {
382
381
  try {
383
382
  const prevId = this.highlightedActionId;
@@ -419,7 +418,7 @@ var DevtoolsBridge = class DevtoolsBridge {
419
418
  } catch {}
420
419
  }
421
420
  /**
422
- * Restore a highlighted action or touchstrip to its normal state.
421
+ * Restore a highlighted action or TouchStrip to its normal state.
423
422
  * Un-suppresses hardware pushes and restores the original image(s).
424
423
  */
425
424
  async restoreHighlight(id) {
@@ -454,7 +453,7 @@ var DevtoolsBridge = class DevtoolsBridge {
454
453
  const segmentWidth = 200;
455
454
  const segmentHeight = 100;
456
455
  const fullWidth = (Math.max(...columns) + 1) * segmentWidth;
457
- const result = await renderTouchStripWithHighlight(tb.root.vcontainer, fullWidth, segmentHeight, columns, segmentWidth, this.renderConfig.touchstripImageFormat, this.renderConfig, nodeId);
456
+ const result = await renderTouchStripWithHighlight(tb.root.vcontainer, fullWidth, segmentHeight, columns, segmentWidth, this.renderConfig, nodeId);
458
457
  if (result && this.highlightedActionId === actionId && this.highlightedNodeId === nodeId) {
459
458
  await tb.root.pushSegmentImages(result.segmentUris);
460
459
  for (const [col, uri] of result.segmentUris) this.broadcastHighlightRender(`${actionId}:seg:${col}`, uri);
@@ -473,7 +472,7 @@ var DevtoolsBridge = class DevtoolsBridge {
473
472
  }
474
473
  /**
475
474
  * Clear highlight URIs for the given actionId.
476
- * For touchstrip IDs, clears all per-segment keys (touchstrip:*:seg:N).
475
+ * For TouchStrip IDs, clears all per-segment keys (touchStrip:*:seg:N).
477
476
  * For regular actions, clears the single actionId key.
478
477
  */
479
478
  broadcastHighlightClear(id) {
@@ -1,4 +1,3 @@
1
- import { OutputFormat } from '@takumi-rs/core';
2
1
  import { VContainer } from '../reconciler/vnode';
3
2
  import { RenderConfig } from '../render/pipeline';
4
3
  export declare function renderWithHighlight(container: VContainer, width: number, height: number, config: RenderConfig, targetNid: number): Promise<string | null>;
@@ -6,4 +5,4 @@ export interface TouchStripHighlightResult {
6
5
  /** Per-column data URIs for ALL segments. */
7
6
  segmentUris: Map<number, string>;
8
7
  }
9
- export declare function renderTouchStripWithHighlight(container: VContainer, fullWidth: number, segmentHeight: number, columns: number[], segmentWidth: number, format: OutputFormat, config: RenderConfig, targetNid: number): Promise<TouchStripHighlightResult | null>;
8
+ export declare function renderTouchStripWithHighlight(container: VContainer, fullWidth: number, segmentHeight: number, columns: number[], segmentWidth: number, config: RenderConfig, targetNid: number): Promise<TouchStripHighlightResult | null>;
@@ -18,7 +18,8 @@ async function renderWithHighlight(container, width, height, config, targetNid)
18
18
  devicePixelRatio: config.devicePixelRatio
19
19
  }), config.imageFormat);
20
20
  }
21
- async function renderTouchStripWithHighlight(container, fullWidth, segmentHeight, columns, segmentWidth, format, config, targetNid) {
21
+ var TOUCHSTRIP_HIGHLIGHT_FORMAT = "png";
22
+ async function renderTouchStripWithHighlight(container, fullWidth, segmentHeight, columns, segmentWidth, config, targetNid) {
22
23
  if (container.children.length === 0) return null;
23
24
  const effectiveNid = resolveTargetNid(container, targetNid);
24
25
  const rootNode = buildTakumiRoot(container);
@@ -50,10 +51,10 @@ async function renderTouchStripWithHighlight(container, fullWidth, segmentHeight
50
51
  const segBuffer = await config.renderer.render(clipNode, {
51
52
  width: segmentWidth,
52
53
  height: segmentHeight,
53
- format,
54
+ format: TOUCHSTRIP_HIGHLIGHT_FORMAT,
54
55
  devicePixelRatio: config.devicePixelRatio
55
56
  });
56
- segmentUris.set(column, bufferToDataUri(segBuffer, format));
57
+ segmentUris.set(column, bufferToDataUri(segBuffer, TOUCHSTRIP_HIGHLIGHT_FORMAT));
57
58
  });
58
59
  await Promise.all(segmentPromises);
59
60
  return { segmentUris };
@@ -150,7 +150,7 @@ export interface RenderMessage extends BaseMessage {
150
150
  profile?: ProfileData;
151
151
  }
152
152
  export interface TouchStripRenderMessage extends BaseMessage {
153
- type: "render:touchstrip";
153
+ type: "render:touchStrip";
154
154
  deviceId: string;
155
155
  canvas: {
156
156
  width: number;
@@ -179,7 +179,7 @@ export interface LifecycleMessage extends BaseMessage {
179
179
  event: "appear" | "disappear";
180
180
  actionId: string;
181
181
  actionUuid: string;
182
- surface: "key" | "dial" | "touch" | "touchstrip";
182
+ surface: "key" | "dial" | "touch" | "touchStrip";
183
183
  device: {
184
184
  id: string;
185
185
  type: number;
@@ -203,8 +203,8 @@ export interface HighlightRenderMessage extends BaseMessage {
203
203
  }
204
204
  /** Per-render pipeline timing data, embedded in RenderMessage. */
205
205
  export interface ProfileData {
206
- vnodeToElementMs: number;
207
- fromJsxMs: number;
206
+ /** Time to convert VNode tree to Takumi node tree (ms). */
207
+ vnodeConversionMs: number;
208
208
  takumiRenderMs: number;
209
209
  hashMs: number;
210
210
  base64Ms: number;
@@ -234,7 +234,7 @@ export interface MetricsData {
234
234
  /** Image cache memory usage in bytes. */
235
235
  imageCacheBytes: number;
236
236
  /** TouchStrip cache memory usage in bytes. */
237
- touchstripCacheBytes: number;
237
+ touchStripCacheBytes: number;
238
238
  }
239
239
  export interface MetricsMessage extends BaseMessage {
240
240
  type: "metrics";
@@ -35,7 +35,7 @@ export interface TweenConfig {
35
35
  duration: number;
36
36
  /** Easing function name or custom (t: number) => number. @default "easeOut" */
37
37
  easing: EasingName | EasingFn;
38
- /** Target FPS for the animation tick loop. @default 60 */
38
+ /** Target FPS for the animation tick loop. @default 30 */
39
39
  fps: number;
40
40
  }
41
41
  export interface TweenResult<T extends AnimationTarget> {
@@ -12,7 +12,7 @@ var SPRING_DEFAULTS = {
12
12
  var TWEEN_DEFAULTS = {
13
13
  duration: 300,
14
14
  easing: "easeOut",
15
- fps: 60
15
+ fps: 30
16
16
  };
17
17
  /** Max dt cap to prevent spring explosion after long pauses.
18
18
  * If the process is suspended (debugger, GC pause), dt could be
@@ -196,7 +196,7 @@ function useSpring(target, config) {
196
196
  config?.displacementThreshold,
197
197
  config?.clamp
198
198
  ]);
199
- const fps = config?.fps ?? 60;
199
+ const fps = config?.fps ?? 30;
200
200
  const isObject = typeof target === "object" && target !== null;
201
201
  const stateRef = useRef(null);
202
202
  if (stateRef.current === null) stateRef.current = initializeSpringState(target);
@@ -38,7 +38,7 @@ function useTouchTap(callback) {
38
38
  function useDialHint(hints) {
39
39
  const { action } = useContext(StreamDeckContext);
40
40
  useEffect(() => {
41
- if ("setTriggerDescription" in action) action.setTriggerDescription({
41
+ action.setTriggerDescription({
42
42
  rotate: hints.rotate,
43
43
  push: hints.press,
44
44
  touch: hints.touch,
package/dist/hooks/sdk.js CHANGED
@@ -3,23 +3,23 @@ import { useCallbackRef } from "./internal/useCallbackRef.js";
3
3
  import { useCallback, useContext, useEffect } from "react";
4
4
  //#region src/hooks/sdk.ts
5
5
  function useOpenUrl() {
6
- const { sdk } = useContext(StreamDeckContext);
6
+ const { adapter } = useContext(StreamDeckContext);
7
7
  return useCallback(async (url) => {
8
- await sdk.system.openUrl(url);
9
- }, [sdk]);
8
+ await adapter.openUrl(url);
9
+ }, [adapter]);
10
10
  }
11
11
  function useSwitchProfile() {
12
- const { sdk, action } = useContext(StreamDeckContext);
12
+ const { adapter, action } = useContext(StreamDeckContext);
13
13
  return useCallback(async (profile, deviceId) => {
14
14
  const devId = deviceId ?? action.device.id;
15
- await sdk.profiles.switchToProfile(devId, profile);
16
- }, [sdk, action]);
15
+ await adapter.switchToProfile(devId, profile);
16
+ }, [adapter, action]);
17
17
  }
18
18
  function useSendToPI() {
19
- const { sdk } = useContext(StreamDeckContext);
19
+ const { adapter } = useContext(StreamDeckContext);
20
20
  return useCallback(async (payload) => {
21
- await sdk.ui.sendToPropertyInspector(payload);
22
- }, [sdk]);
21
+ await adapter.sendToPropertyInspector(payload);
22
+ }, [adapter]);
23
23
  }
24
24
  function usePropertyInspector(callback) {
25
25
  const bus = useContext(EventBusContext);
@@ -41,13 +41,13 @@ function useShowAlert() {
41
41
  function useShowOk() {
42
42
  const { action } = useContext(StreamDeckContext);
43
43
  return useCallback(async () => {
44
- if ("showOk" in action) await action.showOk();
44
+ await action.showOk();
45
45
  }, [action]);
46
46
  }
47
47
  function useTitle() {
48
48
  const { action } = useContext(StreamDeckContext);
49
49
  return useCallback(async (title) => {
50
- if ("setTitle" in action) await action.setTitle(title);
50
+ await action.setTitle(title);
51
51
  }, [action]);
52
52
  }
53
53
  //#endregion
@@ -1,10 +1,11 @@
1
1
  import { useCallbackRef } from "./internal/useCallbackRef.js";
2
2
  import { useCallback, useEffect, useMemo, useRef } from "react";
3
3
  //#region src/hooks/utility.ts
4
- var DEFAULT_TICK_FPS = 60;
4
+ var DEFAULT_TICK_FPS = 30;
5
+ var MAX_TICK_FPS = 30;
5
6
  function toTickIntervalMs(fps) {
6
7
  if (!Number.isFinite(fps) || fps <= 0) return Math.round(1e3 / DEFAULT_TICK_FPS);
7
- return Math.max(1, Math.round(1e3 / fps));
8
+ return Math.max(1, Math.round(1e3 / Math.min(fps, MAX_TICK_FPS)));
8
9
  }
9
10
  function useInterval(callback, delayMs) {
10
11
  const callbackRef = useCallbackRef(callback);
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export { defineAction } from './action';
3
3
  export type { RenderProfile } from './render/pipeline';
4
4
  export type { CacheStats } from './render/image-cache';
5
5
  export type { RenderMetrics } from './render/metrics';
6
+ export { physicalDevice } from './adapter/physical-device';
7
+ export type { StreamDeckAdapter, AdapterActionHandle, AdapterActionCallbacks, AdapterWillAppearEvent, AdapterActionDevice, AdapterController, AdapterCoordinates, AdapterSize, AdapterTriggerDescription, } from './adapter/types';
6
8
  export { useKeyDown, useKeyUp, useDialRotate, useDialDown, useDialUp, useTouchTap, useDialHint, } from './hooks/events';
7
9
  export { useTap, useLongPress, useDoubleTap } from './hooks/gestures';
8
10
  export { useSettings, useGlobalSettings } from './hooks/settings';
@@ -21,7 +23,7 @@ export { ProgressBar } from './components/ProgressBar';
21
23
  export { CircularGauge } from './components/CircularGauge';
22
24
  export { ErrorBoundary } from './components/ErrorBoundary';
23
25
  export { tw } from './tw/index';
24
- export type { PluginConfig, FontConfig, ActionConfig, ActionConfigInput, ActionDefinition, ActionUUID, ManifestActions, EncoderLayout, WrapperComponent, DeviceInfo, ActionInfo, CanvasInfo, TouchStripLayout, TouchStripLayoutItem, KeyDownPayload, KeyUpPayload, DialRotatePayload, DialPressPayload, TouchTapPayload, DialHints, StreamDeckAccess, TouchStripInfo, TouchStripTapPayload, TouchStripDialRotatePayload, TouchStripDialPressPayload, } from './types';
26
+ export type { PluginConfig, FontConfig, ActionConfig, ActionConfigInput, ActionDefinition, ActionUUID, ManifestActions, EncoderLayout, WrapperComponent, Controller, Coordinates, Size, DeviceInfo, ActionInfo, CanvasInfo, TouchStripLayout, TouchStripLayoutItem, KeyDownPayload, KeyUpPayload, DialRotatePayload, DialPressPayload, TouchTapPayload, DialHints, StreamDeckAccess, TouchStripInfo, TouchStripTapPayload, TouchStripDialRotatePayload, TouchStripDialPressPayload, } from './types';
25
27
  export type { TapOptions, LongPressOptions, DoubleTapOptions } from './hooks/gestures';
26
28
  export type { BoxProps } from './components/Box';
27
29
  export type { TextProps } from './components/Text';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { physicalDevice } from "./adapter/physical-device.js";
1
2
  import { createPlugin } from "./plugin.js";
2
3
  import { defineAction } from "./action.js";
3
4
  import { useDialDown, useDialHint, useDialRotate, useDialUp, useKeyDown, useKeyUp, useTouchTap } from "./hooks/events.js";
@@ -17,4 +18,4 @@ import { ProgressBar } from "./components/ProgressBar.js";
17
18
  import { CircularGauge } from "./components/CircularGauge.js";
18
19
  import { ErrorBoundary } from "./components/ErrorBoundary.js";
19
20
  import { tw } from "./tw/index.js";
20
- export { Box, CircularGauge, Easings, ErrorBoundary, Icon, Image, ProgressBar, SpringPresets, Text, createPlugin, defineAction, tw, useAction, useCanvas, useDevice, useDialDown, useDialHint, useDialRotate, useDialUp, useDoubleTap, useGlobalSettings, useInterval, useKeyDown, useKeyUp, useLongPress, useOpenUrl, usePrevious, usePropertyInspector, useSendToPI, useSettings, useShowAlert, useShowOk, useSpring, useStreamDeck, useSwitchProfile, useTap, useTick, useTimeout, useTitle, useTouchStrip, useTouchStripDialDown, useTouchStripDialRotate, useTouchStripDialUp, useTouchStripTap, useTouchTap, useTween, useWillAppear, useWillDisappear };
21
+ export { Box, CircularGauge, Easings, ErrorBoundary, Icon, Image, ProgressBar, SpringPresets, Text, createPlugin, defineAction, physicalDevice, tw, useAction, useCanvas, useDevice, useDialDown, useDialHint, useDialRotate, useDialUp, useDoubleTap, useGlobalSettings, useInterval, useKeyDown, useKeyUp, useLongPress, useOpenUrl, usePrevious, usePropertyInspector, useSendToPI, useSettings, useShowAlert, useShowOk, useSpring, useStreamDeck, useSwitchProfile, useTap, useTick, useTimeout, useTitle, useTouchStrip, useTouchStripDialDown, useTouchStripDialRotate, useTouchStripDialUp, useTouchStripTap, useTouchTap, useTween, useWillAppear, useWillDisappear };