@fcannizzaro/streamdeck-react 0.1.9 → 0.1.11

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 (74) hide show
  1. package/LICENSE +190 -21
  2. package/README.md +3 -1
  3. package/dist/action.d.ts +2 -2
  4. package/dist/action.js +2 -2
  5. package/dist/bundler-shared.d.ts +11 -0
  6. package/dist/bundler-shared.js +11 -0
  7. package/dist/context/event-bus.d.ts +1 -1
  8. package/dist/context/event-bus.js +1 -1
  9. package/dist/context/touchstrip-context.d.ts +2 -0
  10. package/dist/context/touchstrip-context.js +5 -0
  11. package/dist/devtools/bridge.d.ts +35 -7
  12. package/dist/devtools/bridge.js +153 -46
  13. package/dist/devtools/highlight.d.ts +6 -0
  14. package/dist/devtools/highlight.js +106 -57
  15. package/dist/devtools/index.js +6 -0
  16. package/dist/devtools/observers/lifecycle.d.ts +4 -4
  17. package/dist/devtools/server.d.ts +6 -1
  18. package/dist/devtools/server.js +6 -1
  19. package/dist/devtools/types.d.ts +50 -6
  20. package/dist/font-inline.d.ts +5 -1
  21. package/dist/font-inline.js +8 -3
  22. package/dist/hooks/animation.d.ts +154 -0
  23. package/dist/hooks/animation.js +381 -0
  24. package/dist/hooks/events.js +1 -5
  25. package/dist/hooks/touchstrip.d.ts +6 -0
  26. package/dist/hooks/touchstrip.js +37 -0
  27. package/dist/index.d.ts +7 -2
  28. package/dist/index.js +3 -2
  29. package/dist/manifest-codegen.d.ts +38 -0
  30. package/dist/manifest-codegen.js +110 -0
  31. package/dist/node_modules/.bun/xxhash-wasm@1.1.0/node_modules/xxhash-wasm/esm/xxhash-wasm.js +3157 -0
  32. package/dist/plugin.js +20 -9
  33. package/dist/reconciler/host-config.js +19 -1
  34. package/dist/reconciler/vnode.d.ts +26 -0
  35. package/dist/reconciler/vnode.js +41 -10
  36. package/dist/render/buffer-pool.d.ts +19 -0
  37. package/dist/render/buffer-pool.js +51 -0
  38. package/dist/render/cache.d.ts +41 -0
  39. package/dist/render/cache.js +159 -5
  40. package/dist/render/image-cache.d.ts +53 -0
  41. package/dist/render/image-cache.js +128 -0
  42. package/dist/render/metrics.d.ts +58 -0
  43. package/dist/render/metrics.js +101 -0
  44. package/dist/render/pipeline.d.ts +46 -1
  45. package/dist/render/pipeline.js +370 -36
  46. package/dist/render/png.d.ts +10 -1
  47. package/dist/render/png.js +31 -13
  48. package/dist/render/render-pool.d.ts +26 -0
  49. package/dist/render/render-pool.js +141 -0
  50. package/dist/render/svg.d.ts +7 -0
  51. package/dist/render/svg.js +139 -0
  52. package/dist/render/worker.d.ts +1 -0
  53. package/dist/rollup.d.ts +23 -9
  54. package/dist/rollup.js +24 -9
  55. package/dist/roots/flush-coordinator.d.ts +18 -0
  56. package/dist/roots/flush-coordinator.js +38 -0
  57. package/dist/roots/registry.d.ts +6 -4
  58. package/dist/roots/registry.js +47 -33
  59. package/dist/roots/root.d.ts +32 -2
  60. package/dist/roots/root.js +104 -14
  61. package/dist/roots/settings-equality.d.ts +5 -0
  62. package/dist/roots/settings-equality.js +24 -0
  63. package/dist/roots/touchstrip-root.d.ts +93 -0
  64. package/dist/roots/touchstrip-root.js +383 -0
  65. package/dist/types.d.ts +62 -16
  66. package/dist/vite.d.ts +22 -8
  67. package/dist/vite.js +24 -8
  68. package/package.json +5 -4
  69. package/dist/context/touchbar-context.d.ts +0 -2
  70. package/dist/context/touchbar-context.js +0 -5
  71. package/dist/hooks/touchbar.d.ts +0 -6
  72. package/dist/hooks/touchbar.js +0 -37
  73. package/dist/roots/touchbar-root.d.ts +0 -45
  74. package/dist/roots/touchbar-root.js +0 -175
@@ -0,0 +1,6 @@
1
+ import { TouchStripInfo, TouchStripTapPayload, TouchStripDialRotatePayload, TouchStripDialPressPayload } from '../types';
2
+ export declare function useTouchStrip(): TouchStripInfo;
3
+ export declare function useTouchStripTap(callback: (payload: TouchStripTapPayload) => void): void;
4
+ export declare function useTouchStripDialRotate(callback: (payload: TouchStripDialRotatePayload) => void): void;
5
+ export declare function useTouchStripDialDown(callback: (payload: TouchStripDialPressPayload) => void): void;
6
+ export declare function useTouchStripDialUp(callback: (payload: TouchStripDialPressPayload) => void): void;
@@ -0,0 +1,37 @@
1
+ import { EventBusContext } from "../context/providers.js";
2
+ import { TouchStripContext } from "../context/touchstrip-context.js";
3
+ import { useCallbackRef } from "./internal/useCallbackRef.js";
4
+ import { useContext, useEffect } from "react";
5
+ //#region src/hooks/touchstrip.ts
6
+ function useTouchStripEvent(event, callback) {
7
+ const bus = useContext(EventBusContext);
8
+ const callbackRef = useCallbackRef(callback);
9
+ useEffect(() => {
10
+ const handler = (payload) => {
11
+ callbackRef.current(payload);
12
+ };
13
+ bus.on(event, handler);
14
+ return () => bus.off(event, handler);
15
+ }, [
16
+ bus,
17
+ callbackRef,
18
+ event
19
+ ]);
20
+ }
21
+ function useTouchStrip() {
22
+ return useContext(TouchStripContext);
23
+ }
24
+ function useTouchStripTap(callback) {
25
+ useTouchStripEvent("touchStripTap", callback);
26
+ }
27
+ function useTouchStripDialRotate(callback) {
28
+ useTouchStripEvent("touchStripDialRotate", callback);
29
+ }
30
+ function useTouchStripDialDown(callback) {
31
+ useTouchStripEvent("touchStripDialDown", callback);
32
+ }
33
+ function useTouchStripDialUp(callback) {
34
+ useTouchStripEvent("touchStripDialUp", callback);
35
+ }
36
+ //#endregion
37
+ export { useTouchStrip, useTouchStripDialDown, useTouchStripDialRotate, useTouchStripDialUp, useTouchStripTap };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  export { createPlugin } from './plugin';
2
2
  export { defineAction } from './action';
3
+ export type { RenderProfile } from './render/pipeline';
4
+ export type { CacheStats } from './render/image-cache';
5
+ export type { RenderMetrics } from './render/metrics';
3
6
  export { useKeyDown, useKeyUp, useDialRotate, useDialDown, useDialUp, useTouchTap, useDialHint, } from './hooks/events';
4
7
  export { useTap, useLongPress, useDoubleTap } from './hooks/gestures';
5
8
  export { useSettings, useGlobalSettings } from './hooks/settings';
6
9
  export { useDevice, useAction, useCanvas, useStreamDeck } from './hooks/context';
7
10
  export { useWillAppear, useWillDisappear } from './hooks/lifecycle';
8
11
  export { useInterval, useTimeout, usePrevious, useTick } from './hooks/utility';
12
+ export { useSpring, useTween, SpringPresets, Easings } from './hooks/animation';
13
+ export type { SpringConfig, SpringResult, TweenConfig, TweenResult, EasingName, EasingFn, AnimationTarget, AnimatedValue, } from './hooks/animation';
9
14
  export { useOpenUrl, useSwitchProfile, useSendToPI, usePropertyInspector, useShowAlert, useShowOk, useTitle, } from './hooks/sdk';
10
- export { useTouchBar, useTouchBarTap, useTouchBarDialRotate, useTouchBarDialDown, useTouchBarDialUp, } from './hooks/touchbar';
15
+ export { useTouchStrip, useTouchStripTap, useTouchStripDialRotate, useTouchStripDialDown, useTouchStripDialUp, } from './hooks/touchstrip';
11
16
  export { Box } from './components/Box';
12
17
  export { Text } from './components/Text';
13
18
  export { Image } from './components/Image';
@@ -16,7 +21,7 @@ export { ProgressBar } from './components/ProgressBar';
16
21
  export { CircularGauge } from './components/CircularGauge';
17
22
  export { ErrorBoundary } from './components/ErrorBoundary';
18
23
  export { tw } from './tw/index';
19
- export type { PluginConfig, FontConfig, ActionConfig, ActionDefinition, EncoderLayout, WrapperComponent, DeviceInfo, ActionInfo, CanvasInfo, TouchStripLayout, TouchStripLayoutItem, KeyDownPayload, KeyUpPayload, DialRotatePayload, DialPressPayload, TouchTapPayload, DialHints, StreamDeckAccess, TouchBarInfo, TouchBarTapPayload, TouchBarDialRotatePayload, TouchBarDialPressPayload, } from './types';
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';
20
25
  export type { TapOptions, LongPressOptions, DoubleTapOptions } from './hooks/gestures';
21
26
  export type { BoxProps } from './components/Box';
22
27
  export type { TextProps } from './components/Text';
package/dist/index.js CHANGED
@@ -6,8 +6,9 @@ import { useGlobalSettings, useSettings } from "./hooks/settings.js";
6
6
  import { useAction, useCanvas, useDevice, useStreamDeck } from "./hooks/context.js";
7
7
  import { useWillAppear, useWillDisappear } from "./hooks/lifecycle.js";
8
8
  import { useInterval, usePrevious, useTick, useTimeout } from "./hooks/utility.js";
9
+ import { Easings, SpringPresets, useSpring, useTween } from "./hooks/animation.js";
9
10
  import { useOpenUrl, usePropertyInspector, useSendToPI, useShowAlert, useShowOk, useSwitchProfile, useTitle } from "./hooks/sdk.js";
10
- import { useTouchBar, useTouchBarDialDown, useTouchBarDialRotate, useTouchBarDialUp, useTouchBarTap } from "./hooks/touchbar.js";
11
+ import { useTouchStrip, useTouchStripDialDown, useTouchStripDialRotate, useTouchStripDialUp, useTouchStripTap } from "./hooks/touchstrip.js";
11
12
  import { Box } from "./components/Box.js";
12
13
  import { Text } from "./components/Text.js";
13
14
  import { Image } from "./components/Image.js";
@@ -16,4 +17,4 @@ import { ProgressBar } from "./components/ProgressBar.js";
16
17
  import { CircularGauge } from "./components/CircularGauge.js";
17
18
  import { ErrorBoundary } from "./components/ErrorBoundary.js";
18
19
  import { tw } from "./tw/index.js";
19
- export { Box, CircularGauge, ErrorBoundary, Icon, Image, ProgressBar, Text, createPlugin, defineAction, tw, useAction, useCanvas, useDevice, useDialDown, useDialHint, useDialRotate, useDialUp, useDoubleTap, useGlobalSettings, useInterval, useKeyDown, useKeyUp, useLongPress, useOpenUrl, usePrevious, usePropertyInspector, useSendToPI, useSettings, useShowAlert, useShowOk, useStreamDeck, useSwitchProfile, useTap, useTick, useTimeout, useTitle, useTouchBar, useTouchBarDialDown, useTouchBarDialRotate, useTouchBarDialUp, useTouchBarTap, useTouchTap, useWillAppear, useWillDisappear };
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 };
@@ -0,0 +1,38 @@
1
+ export interface ParsedAction {
2
+ uuid: string;
3
+ controllers: readonly ("Keypad" | "Encoder")[];
4
+ }
5
+ /**
6
+ * Find the manifest.json inside a `*.sdPlugin` directory.
7
+ *
8
+ * - If `explicit` is a string, it is resolved against `root`.
9
+ * - If `explicit` is `false`, codegen is disabled (returns `null`).
10
+ * - Otherwise, auto-detects by scanning `root` for `*.sdPlugin/manifest.json`.
11
+ */
12
+ export declare function findManifestPath(root: string, explicit?: string | false, warn?: (msg: string) => void): string | null;
13
+ /**
14
+ * Parse a Stream Deck plugin manifest and extract action metadata.
15
+ * Returns an empty array on failure (with a warning).
16
+ */
17
+ export declare function parseManifest(path: string, warn?: (msg: string) => void): ParsedAction[];
18
+ /**
19
+ * Generate the `declare module` augmentation string from parsed actions.
20
+ * Returns an empty string when there are no actions.
21
+ */
22
+ export declare function generateManifestDts(actions: ParsedAction[]): string;
23
+ /**
24
+ * Write the generated `.d.ts` file only when the content has changed.
25
+ * Creates the parent directory if it does not exist.
26
+ *
27
+ * @returns `true` if the file was written, `false` if content was unchanged.
28
+ */
29
+ export declare function writeManifestDtsIfChanged(outPath: string, content: string): boolean;
30
+ /**
31
+ * High-level helper: find, parse, generate, and write manifest types.
32
+ *
33
+ * @returns The resolved manifest path (for watch registration), or `null`.
34
+ */
35
+ export declare function generateManifestTypes(root: string, manifestOption: string | false | undefined, warn?: (msg: string) => void): {
36
+ manifestPath: string;
37
+ written: boolean;
38
+ } | null;
@@ -0,0 +1,110 @@
1
+ import { dirname, join, resolve } from "node:path";
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
3
+ //#region src/manifest-codegen.ts
4
+ /**
5
+ * Find the manifest.json inside a `*.sdPlugin` directory.
6
+ *
7
+ * - If `explicit` is a string, it is resolved against `root`.
8
+ * - If `explicit` is `false`, codegen is disabled (returns `null`).
9
+ * - Otherwise, auto-detects by scanning `root` for `*.sdPlugin/manifest.json`.
10
+ */
11
+ function findManifestPath(root, explicit, warn) {
12
+ if (explicit === false) return null;
13
+ if (typeof explicit === "string") {
14
+ const resolved = resolve(root, explicit);
15
+ if (!existsSync(resolved)) {
16
+ warn?.(`[@fcannizzaro/streamdeck-react] Manifest not found at ${resolved}`);
17
+ return null;
18
+ }
19
+ return resolved;
20
+ }
21
+ const sdPluginDirs = readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.endsWith(".sdPlugin"));
22
+ if (sdPluginDirs.length === 0) return null;
23
+ if (sdPluginDirs.length > 1) warn?.(`[@fcannizzaro/streamdeck-react] Multiple .sdPlugin directories found. Using "${sdPluginDirs[0].name}". Set the \`manifest\` option to specify one explicitly.`);
24
+ const manifestPath = join(root, sdPluginDirs[0].name, "manifest.json");
25
+ return existsSync(manifestPath) ? manifestPath : null;
26
+ }
27
+ /**
28
+ * Parse a Stream Deck plugin manifest and extract action metadata.
29
+ * Returns an empty array on failure (with a warning).
30
+ */
31
+ function parseManifest(path, warn) {
32
+ try {
33
+ const content = readFileSync(path, "utf-8");
34
+ const manifest = JSON.parse(content);
35
+ if (!Array.isArray(manifest.Actions)) {
36
+ warn?.(`[@fcannizzaro/streamdeck-react] manifest.json has no Actions array`);
37
+ return [];
38
+ }
39
+ const actions = [];
40
+ for (const action of manifest.Actions) {
41
+ if (!action.UUID) {
42
+ warn?.(`[@fcannizzaro/streamdeck-react] Skipping manifest action with missing UUID`);
43
+ continue;
44
+ }
45
+ actions.push({
46
+ uuid: action.UUID,
47
+ controllers: action.Controllers ?? ["Keypad"]
48
+ });
49
+ }
50
+ return actions;
51
+ } catch (err) {
52
+ warn?.(`[@fcannizzaro/streamdeck-react] Failed to parse manifest: ${err instanceof Error ? err.message : String(err)}`);
53
+ return [];
54
+ }
55
+ }
56
+ var HEADER = ["// This file is auto-generated by @fcannizzaro/streamdeck-react", "// Do not edit this file manually. It is regenerated from the plugin manifest."].join("\n");
57
+ /**
58
+ * Generate the `declare module` augmentation string from parsed actions.
59
+ * Returns an empty string when there are no actions.
60
+ */
61
+ function generateManifestDts(actions) {
62
+ if (actions.length === 0) return "";
63
+ return [
64
+ HEADER,
65
+ "",
66
+ "import \"@fcannizzaro/streamdeck-react\";",
67
+ "",
68
+ "declare module \"@fcannizzaro/streamdeck-react\" {",
69
+ " interface ManifestActions {",
70
+ ...actions.map((action) => {
71
+ const controllers = action.controllers.map((c) => `"${c}"`).join(", ");
72
+ return ` "${action.uuid}": {\n controllers: readonly [${controllers}];\n };`;
73
+ }),
74
+ " }",
75
+ "}",
76
+ ""
77
+ ].join("\n");
78
+ }
79
+ /**
80
+ * Write the generated `.d.ts` file only when the content has changed.
81
+ * Creates the parent directory if it does not exist.
82
+ *
83
+ * @returns `true` if the file was written, `false` if content was unchanged.
84
+ */
85
+ function writeManifestDtsIfChanged(outPath, content) {
86
+ if (content === "") return false;
87
+ if (existsSync(outPath)) {
88
+ if (readFileSync(outPath, "utf-8") === content) return false;
89
+ }
90
+ const dir = dirname(outPath);
91
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
92
+ writeFileSync(outPath, content);
93
+ return true;
94
+ }
95
+ /**
96
+ * High-level helper: find, parse, generate, and write manifest types.
97
+ *
98
+ * @returns The resolved manifest path (for watch registration), or `null`.
99
+ */
100
+ function generateManifestTypes(root, manifestOption, warn) {
101
+ const manifestPath = findManifestPath(root, manifestOption, warn);
102
+ if (!manifestPath) return null;
103
+ const content = generateManifestDts(parseManifest(manifestPath, warn));
104
+ return {
105
+ manifestPath,
106
+ written: writeManifestDtsIfChanged(resolve(root, "src/streamdeck-env.d.ts"), content)
107
+ };
108
+ }
109
+ //#endregion
110
+ export { generateManifestTypes };