@roku-sdk/rsg-ts 0.0.0-stage → 2.19.0
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/LICENSE +21 -0
- package/README.md +11 -2
- package/package.json +67 -3
- package/roku-config.ts +57 -0
- package/src/dcl.ts +77 -0
- package/src/interfaces.ts +4 -0
- package/src/main.ts +19 -0
- package/src/module-registry.ts +40 -0
- package/src/runtime.ts +35 -0
- package/src/types/sg-jsx.d.ts +188 -0
- package/src/types/xml.d.ts +4 -0
- package/src/use-delay.ts +63 -0
- package/tsconfig/tsconfig.base.json +0 -0
- package/tsconfig.base.json +0 -0
- package/tsconfig.json +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Roku, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @roku-sdk/rsg-ts
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Core SDK package for building Roku SceneGraph applications with TypeScript. Re-exports APIs from internal packages (`@roku-sdk/native`, `@roku-sdk/ts-core`) so that application code only needs to depend on `@roku-sdk/rsg-ts`.
|
|
4
|
+
|
|
5
|
+
## DCL module registry
|
|
6
|
+
|
|
7
|
+
`@roku-sdk/rsg-ts/module-registry` is an opt-in side-effect import for apps that host TypeScript DCLs. It publishes the SDK barrels on `globalThis.__ROKU_MODULES__` so a DCL's `require()` calls resolve. The main entry point no longer imports it, so ordinary apps tree-shake the runtime APIs they do not use. See [DCL: host app entry point](../../documentation/core-concepts/dcl.md#opting-in-to-the-module-registry).
|
|
8
|
+
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
- [Exception Handling](../../documentation/runtime-and-debugging/exception-handling.md) — Forward uncaught exceptions to monitoring services
|
|
12
|
+
- [Full SDK Documentation](../../documentation/README.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roku-sdk/rsg-ts",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "2.19.0",
|
|
4
|
+
"description": "Roku SceneGraph TypeScript Components",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"./src/module-registry.ts"
|
|
8
|
+
],
|
|
9
|
+
"main": "./src/main.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/main.ts",
|
|
12
|
+
"./tsconfig.json": "./tsconfig.json",
|
|
13
|
+
"./tsconfig.base.json": "./tsconfig/tsconfig.base.json",
|
|
14
|
+
"./roku-config": "./roku-config.ts",
|
|
15
|
+
"./runtime": "./src/runtime.ts",
|
|
16
|
+
"./interfaces": "./src/interfaces.ts",
|
|
17
|
+
"./dcl": "./src/dcl.ts",
|
|
18
|
+
"./module-registry": "./src/module-registry.ts"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"npm": ">=8.5.0",
|
|
22
|
+
"node": ">=24.0.0"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src/",
|
|
26
|
+
"tsconfig/",
|
|
27
|
+
"tsconfig.json",
|
|
28
|
+
"tsconfig.base.json",
|
|
29
|
+
"roku-config.ts"
|
|
30
|
+
],
|
|
31
|
+
"compilerOptions": {
|
|
32
|
+
"target": "es2020"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@jest/globals": "^30.4.1",
|
|
36
|
+
"@roku-sdk/dev-tools": "2.19.0",
|
|
37
|
+
"@roku-sdk/testing-library": "2.19.0"
|
|
38
|
+
},
|
|
39
|
+
"author": "Roku Inc",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://gitlab.com/rokudev/rsg-sdk.git",
|
|
44
|
+
"directory": "packages/rsg-ts"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://gitlab.com/rokudev/rsg-sdk/-/tree/main/packages/rsg-ts#readme",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://gitlab.com/rokudev/rsg-sdk/-/issues"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@roku-sdk/components": "2.19.0",
|
|
55
|
+
"@roku-sdk/common": "2.19.0",
|
|
56
|
+
"@roku-sdk/runtime": "2.19.0",
|
|
57
|
+
"@roku-sdk/native": "2.19.0",
|
|
58
|
+
"@roku-sdk/interfaces": "2.19.0",
|
|
59
|
+
"@roku-sdk/sdk-config": "2.19.0",
|
|
60
|
+
"@roku-sdk/solid": "2.19.0",
|
|
61
|
+
"@roku-sdk/ts-core": "2.19.0"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"rk": "rk",
|
|
65
|
+
"test": "jest",
|
|
66
|
+
"coverage": "jest --coverage --runInBand --passWithNoTests --testTimeout=60000 --forceExit",
|
|
67
|
+
"clean": "rm -rf dist",
|
|
68
|
+
"lint": "eslint --no-error-on-unmatched-pattern \"src/**/*.{ts,tsx,mjs,cjs,js}\""
|
|
69
|
+
}
|
|
6
70
|
}
|
package/roku-config.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { SdkConfig as InternalRokuConfig, UserSdkConfig as RokuConfig } from "@roku-sdk/sdk-config";
|
|
5
|
+
|
|
6
|
+
export type { RokuConfig, InternalRokuConfig };
|
|
7
|
+
|
|
8
|
+
// Pipeline extension types — re-exported here so consumers have a single
|
|
9
|
+
// canonical import path (`@roku-sdk/rsg-ts/roku-config`) for everything
|
|
10
|
+
// needed to type `roku-config.ts`, including lifecycle hooks and plugin slots.
|
|
11
|
+
export type {
|
|
12
|
+
RokuPipeline,
|
|
13
|
+
BuildPipeline,
|
|
14
|
+
StartDevPipeline,
|
|
15
|
+
BuildHookContext,
|
|
16
|
+
PostBuildHookContext,
|
|
17
|
+
DeployHookContext,
|
|
18
|
+
DeployHookDevice,
|
|
19
|
+
ManifestEntries,
|
|
20
|
+
PipelinePlugin,
|
|
21
|
+
BuildPluginSlot,
|
|
22
|
+
StartDevPluginSlot,
|
|
23
|
+
PositionFor
|
|
24
|
+
} from "@roku-sdk/sdk-config";
|
|
25
|
+
|
|
26
|
+
/** Minimal Node process.env ambient so consumers without `@types/node` can typecheck this helper. */
|
|
27
|
+
declare const process: { env: Record<string, string | undefined> };
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the current build type from the environment
|
|
31
|
+
* @returns The `--build-type` value, or the command's default when none is given: `"production"`
|
|
32
|
+
* for `rk build`, `"development"` for `rk dev`. `"unknown"` when the config is loaded outside `rk`.
|
|
33
|
+
* @description This function can be called within roku-config.ts to conditionally configure
|
|
34
|
+
* manifest entries or other settings based on the build type. Build types can be specified
|
|
35
|
+
* via command line: `npx rk build --build-type staging` or `npx rk dev --build-type staging`
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import type { RokuConfig } from "@roku-sdk/rsg-ts/roku-config";
|
|
40
|
+
* import { getBuildType } from "@roku-sdk/rsg-ts/roku-config";
|
|
41
|
+
*
|
|
42
|
+
* const buildType = getBuildType();
|
|
43
|
+
*
|
|
44
|
+
* const configuration: RokuConfig = {
|
|
45
|
+
* app: {
|
|
46
|
+
* entryPoint: "src/index.ts",
|
|
47
|
+
* manifestEntries: {
|
|
48
|
+
* title: buildType === "production" ? "My App" : `My App (${buildType})`,
|
|
49
|
+
* hidden: buildType === "development" ? 1 : 0,
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
* };
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export const getBuildType = (): string => {
|
|
56
|
+
return process.env.ROKU_BUILD_TYPE || "unknown";
|
|
57
|
+
};
|
package/src/dcl.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { Component, JSX } from "@roku-sdk/solid";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves a TS DCL component from the global registry and returns it as a SolidJS-compatible
|
|
8
|
+
* component function that can be used directly in JSX.
|
|
9
|
+
*
|
|
10
|
+
* This is the recommended way to render TS DCL components inside a TypeScript host app.
|
|
11
|
+
* Since both host and DCL are TypeScript, no firmware communication is required — the DCL
|
|
12
|
+
* component is composed directly into the host's render tree as a plain SolidJS function.
|
|
13
|
+
*
|
|
14
|
+
* Call this after `LoadStatus.READY` has fired for the given library.
|
|
15
|
+
*
|
|
16
|
+
* @param libraryName - The DCL library name (matches the library provided by the DCL app)
|
|
17
|
+
* @param componentName - The component name as declared in its descriptor
|
|
18
|
+
* @returns A SolidJS `Component` function suitable for JSX usage
|
|
19
|
+
*
|
|
20
|
+
* @throws {Error} If the library or component is not found in the global registry
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { getDCLComponent } from "@roku-sdk/rsg-ts";
|
|
25
|
+
*
|
|
26
|
+
* // Inside LoadStatus.READY handler:
|
|
27
|
+
* const Cowboy = getDCLComponent("tsDCL", "Cowboy");
|
|
28
|
+
* setCowboyComponent(() => Cowboy);
|
|
29
|
+
*
|
|
30
|
+
* // In JSX:
|
|
31
|
+
* <Show when={CowboyComponent()}>{(Comp) => <Comp />}</Show>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function getDCLComponent<P extends Record<string, unknown> = Record<string, unknown>>(
|
|
35
|
+
libraryName: string,
|
|
36
|
+
componentName: string
|
|
37
|
+
): Component<P> {
|
|
38
|
+
const registry = (
|
|
39
|
+
globalThis as typeof globalThis & {
|
|
40
|
+
__LOADED_DCL_COMPONENTS?: Record<
|
|
41
|
+
string,
|
|
42
|
+
Array<{
|
|
43
|
+
description: {
|
|
44
|
+
componentName: string;
|
|
45
|
+
extends: string;
|
|
46
|
+
inputFields: Record<string, unknown>;
|
|
47
|
+
outputFields: Record<string, unknown>;
|
|
48
|
+
libraryName?: string;
|
|
49
|
+
};
|
|
50
|
+
component: (inputs: unknown, outputs: unknown) => unknown;
|
|
51
|
+
}>
|
|
52
|
+
>;
|
|
53
|
+
}
|
|
54
|
+
).__LOADED_DCL_COMPONENTS;
|
|
55
|
+
if (!registry || !registry[libraryName]) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`DCL library "${libraryName}" not found. Make sure getDCLComponent is called after LoadStatus.READY.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const libraryComponents = registry[libraryName];
|
|
62
|
+
const entry = libraryComponents.find(
|
|
63
|
+
(componentEntry: { description: { componentName: string } }) =>
|
|
64
|
+
componentEntry.description.componentName === componentName
|
|
65
|
+
);
|
|
66
|
+
if (!entry) {
|
|
67
|
+
throw new Error(`Component "${componentName}" not found in DCL library "${libraryName}".`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const noopOutputs: Record<string, () => void> = {};
|
|
71
|
+
for (const key of Object.keys(entry.description.outputFields)) {
|
|
72
|
+
noopOutputs[key] = () => {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { component } = entry;
|
|
76
|
+
return (props: P) => component(props, noopOutputs) as unknown as JSX.Element;
|
|
77
|
+
}
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
export { logger } from "@roku-sdk/common";
|
|
5
|
+
export {
|
|
6
|
+
declareTsComponent, //Deprecated: use declareAnchorNode instead
|
|
7
|
+
defineAnchorNode,
|
|
8
|
+
registerAnchorNode,
|
|
9
|
+
FieldType
|
|
10
|
+
} from "@roku-sdk/ts-core";
|
|
11
|
+
export type {
|
|
12
|
+
TsComponent, //Deprecated: Use AnchorNodeImplementation instead
|
|
13
|
+
TsComponentDeclaration, //Deprecated: Use AnchorNodeDescriptor instead
|
|
14
|
+
AnchorNodeDescriptor,
|
|
15
|
+
AnchorNodeImplementation
|
|
16
|
+
} from "@roku-sdk/ts-core";
|
|
17
|
+
export { main, enableExceptionTagging, setUncaughtExceptionHandler } from "@roku-sdk/native";
|
|
18
|
+
export { useDelay } from "./use-delay";
|
|
19
|
+
export { getDCLComponent } from "./dcl";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import * as rsgTs from "@roku-sdk/rsg-ts";
|
|
5
|
+
import * as interfaces from "@roku-sdk/rsg-ts/interfaces";
|
|
6
|
+
import * as runtime from "@roku-sdk/rsg-ts/runtime";
|
|
7
|
+
import * as solid from "@roku-sdk/solid";
|
|
8
|
+
|
|
9
|
+
// Extend globalThis type to include Roku module registry
|
|
10
|
+
declare global {
|
|
11
|
+
var __ROKU_MODULES__: Record<string, unknown>;
|
|
12
|
+
var require: (moduleName: string) => unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Framework provides SDK modules via global registry for DCL require() calls
|
|
16
|
+
// No exports needed - DCLs use globalThis.require() instead
|
|
17
|
+
// Register framework exports in global namespace for DCL require() calls
|
|
18
|
+
// Create global module registry
|
|
19
|
+
globalThis.__ROKU_MODULES__ = globalThis.__ROKU_MODULES__ || {};
|
|
20
|
+
Object.assign(globalThis.__ROKU_MODULES__, {
|
|
21
|
+
"@roku-sdk/rsg-ts/interfaces": interfaces,
|
|
22
|
+
"@roku-sdk/rsg-ts": rsgTs,
|
|
23
|
+
"@roku-sdk/solid": solid,
|
|
24
|
+
"@roku-sdk/rsg-ts/runtime": runtime
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Provide global require function for DCLs
|
|
28
|
+
globalThis.require = function (moduleName: string) {
|
|
29
|
+
const modules = globalThis.__ROKU_MODULES__;
|
|
30
|
+
if (modules && modules[moduleName]) {
|
|
31
|
+
return modules[moduleName];
|
|
32
|
+
}
|
|
33
|
+
// Hermes CDP inspector probes require("module") during debug session setup
|
|
34
|
+
// to detect CommonJS environments. Silently return undefined for this probe
|
|
35
|
+
// so it doesn't trigger "break on all exceptions" in the debugger.
|
|
36
|
+
if (moduleName === "module") {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
throw new Error(`Module not found: ${moduleName}`);
|
|
40
|
+
};
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
export { getRegistry } from "@roku-sdk/runtime/registry";
|
|
5
|
+
export { useLaunchConfig } from "@roku-sdk/runtime/launch-config";
|
|
6
|
+
export { getAppInfo } from "@roku-sdk/runtime/app-info";
|
|
7
|
+
export { useCec, useCEC } from "@roku-sdk/runtime/cec";
|
|
8
|
+
export { getHdmiStatus, useHdmiStatus } from "@roku-sdk/runtime/hdmi-status";
|
|
9
|
+
export type { HdmiStatus } from "@roku-sdk/runtime/hdmi-status";
|
|
10
|
+
export { getAppMemoryMonitor, useAppMemoryMonitor } from "@roku-sdk/runtime/app-memory-monitor";
|
|
11
|
+
export type { AppMemoryMonitor } from "@roku-sdk/runtime/app-memory-monitor";
|
|
12
|
+
export { getDeviceInfo } from "@roku-sdk/runtime/device-info";
|
|
13
|
+
export { hasFeature } from "@roku-sdk/runtime/has-feature";
|
|
14
|
+
export type { DeviceInfoStatic } from "@roku-sdk/runtime/device-info";
|
|
15
|
+
export { useDeviceInfoEvents, useUiResolution } from "@roku-sdk/runtime/device-info-events";
|
|
16
|
+
/** @deprecated Use useUiResolution instead */
|
|
17
|
+
export { useUIResolution } from "@roku-sdk/runtime/device-info-events";
|
|
18
|
+
export type { DeviceInfoEventsHook, UIResolution } from "@roku-sdk/runtime/device-info-events";
|
|
19
|
+
export { useInput } from "@roku-sdk/runtime/input";
|
|
20
|
+
export type { InputEventsHook } from "@roku-sdk/runtime/input";
|
|
21
|
+
export { useLifecycle } from "@roku-sdk/runtime/lifecycle";
|
|
22
|
+
export { getFileSystem, useFileSystem } from "@roku-sdk/runtime/file-system";
|
|
23
|
+
export { crypto } from "@roku-sdk/runtime/crypto";
|
|
24
|
+
export { getFontMeasure, whenFontReady, createFontReady } from "@roku-sdk/runtime/font";
|
|
25
|
+
export type { FontReadyAbortSignal, WhenFontReadyOptions } from "@roku-sdk/runtime/font";
|
|
26
|
+
export type { LifecycleEventsHook } from "@roku-sdk/runtime/lifecycle";
|
|
27
|
+
export { getAudioGuide } from "@roku-sdk/runtime/audio-guide";
|
|
28
|
+
export { getTextToSpeech } from "@roku-sdk/runtime/text-to-speech";
|
|
29
|
+
export { getVoiceDictation, useVoiceDictation } from "@roku-sdk/runtime/voice-dictation";
|
|
30
|
+
export type { VoiceDictationHook } from "@roku-sdk/runtime/voice-dictation";
|
|
31
|
+
export { useVoiceCommands } from "@roku-sdk/runtime/voice-commands";
|
|
32
|
+
export type { VoiceCommandHook } from "@roku-sdk/runtime/voice-commands";
|
|
33
|
+
export { DictationEvent, DictationKeyboardType } from "@roku-sdk/interfaces";
|
|
34
|
+
export type { DictationInputParams, VoiceDictation } from "@roku-sdk/interfaces";
|
|
35
|
+
export { getPerfetto } from "@roku-sdk/runtime/perfetto";
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// Auto-generated. DO NOT EDIT.
|
|
2
|
+
// Source: ../components/src/sg-intrinsics.json — run `pnpm generate:sg-intrinsics` in @roku-sdk/components to regenerate.
|
|
3
|
+
//
|
|
4
|
+
// `export {}` makes this a TypeScript MODULE file (not a script), enabling proper
|
|
5
|
+
// module augmentation. Without it, `declare module` creates a standalone ambient
|
|
6
|
+
// namespace that shadows JSX.ElementChildrenAttribute from solid-js, breaking
|
|
7
|
+
// automatic `children` handling in <Show>, <For>, <ErrorBoundary>, etc.
|
|
8
|
+
export {};
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
IAnimatedImageProps,
|
|
12
|
+
IAnimationBaseProps,
|
|
13
|
+
IAnimationProps,
|
|
14
|
+
IAudioProps,
|
|
15
|
+
IBifDisplayProps,
|
|
16
|
+
IBlendedBusySpinnerProps,
|
|
17
|
+
IBoundingTrackerProps,
|
|
18
|
+
IBusySpinnerProps,
|
|
19
|
+
IButtonGroupProps,
|
|
20
|
+
IButtonProps,
|
|
21
|
+
IChannelStoreProps,
|
|
22
|
+
ICheckListProps,
|
|
23
|
+
IColorFieldInterpolatorProps,
|
|
24
|
+
IContentNodeProps,
|
|
25
|
+
IDialogProps,
|
|
26
|
+
IDynamicKeyboardProps,
|
|
27
|
+
IDynamicKeyGridProps,
|
|
28
|
+
IDynamicMiniKeyboardProps,
|
|
29
|
+
IDynamicPinPadProps,
|
|
30
|
+
IEffectProps,
|
|
31
|
+
IFloatFieldInterpolatorProps,
|
|
32
|
+
IFocusableGroupProps,
|
|
33
|
+
IFocusableProps,
|
|
34
|
+
IFontProps,
|
|
35
|
+
IFullPanelProps,
|
|
36
|
+
IGroupProps,
|
|
37
|
+
IKeyboardPropsWithVoice,
|
|
38
|
+
IKeyHandlerProps,
|
|
39
|
+
ILabelListProps,
|
|
40
|
+
ILabelProps,
|
|
41
|
+
ILayoutGroupProps,
|
|
42
|
+
IListPanelProps,
|
|
43
|
+
IMarkupGridProps,
|
|
44
|
+
IMarkupListProps,
|
|
45
|
+
IMaskGroupProps,
|
|
46
|
+
IModalProps,
|
|
47
|
+
IMultiStyleLabelProps,
|
|
48
|
+
IOverhangProps,
|
|
49
|
+
IPanelProps,
|
|
50
|
+
IPanelSetProps,
|
|
51
|
+
IPosterGridProps,
|
|
52
|
+
IPosterProps,
|
|
53
|
+
IProgressBarProps,
|
|
54
|
+
IRadioButtonListProps,
|
|
55
|
+
IRectangleProps,
|
|
56
|
+
IRowListProps,
|
|
57
|
+
ISceneProps,
|
|
58
|
+
IScrollableTextProps,
|
|
59
|
+
IScrollingLabelProps,
|
|
60
|
+
ISimpleLabelProps,
|
|
61
|
+
ISoundEffectProps,
|
|
62
|
+
IStandardDialogProps,
|
|
63
|
+
IStandardDialogRSGPaletteNodeProps,
|
|
64
|
+
IStandardKeyboardDialogProps,
|
|
65
|
+
IStandardMessageDialogProps,
|
|
66
|
+
IStandardPinPadDialogProps,
|
|
67
|
+
IStandardProgressDialogProps,
|
|
68
|
+
IStdDlgActionCardItemProps,
|
|
69
|
+
IStdDlgBulletTextItemProps,
|
|
70
|
+
IStdDlgButtonAreaProps,
|
|
71
|
+
IStdDlgButtonProps,
|
|
72
|
+
IStdDlgContentAreaProps,
|
|
73
|
+
IStdDlgCustomItemProps,
|
|
74
|
+
IStdDlgDeterminateProgressItemProps,
|
|
75
|
+
IStdDlgGraphicItemProps,
|
|
76
|
+
IStdDlgItemGroupProps,
|
|
77
|
+
IStdDlgKeyboardItemProps,
|
|
78
|
+
IStdDlgMultiStyleTextItemProps,
|
|
79
|
+
IStdDlgProgressItemProps,
|
|
80
|
+
IStdDlgSideCardAreaProps,
|
|
81
|
+
IStdDlgTextItemProps,
|
|
82
|
+
IStdDlgTitleAreaProps,
|
|
83
|
+
ITargetGroupProps,
|
|
84
|
+
ITargetListProps,
|
|
85
|
+
ITargetSetProps,
|
|
86
|
+
ITimeGridProps,
|
|
87
|
+
ITrickPlayBarProps,
|
|
88
|
+
ITweenProps,
|
|
89
|
+
IVector2DFieldInterpolatorProps,
|
|
90
|
+
IVideoProps,
|
|
91
|
+
IVoiceTextEditBoxProps,
|
|
92
|
+
IZoomRowListProps
|
|
93
|
+
} from "@roku-sdk/components/jsx-props";
|
|
94
|
+
|
|
95
|
+
declare module "@roku-sdk/solid/jsx-runtime" {
|
|
96
|
+
namespace JSX {
|
|
97
|
+
interface IntrinsicElements {
|
|
98
|
+
checkList: ICheckListProps;
|
|
99
|
+
labelList: ILabelListProps;
|
|
100
|
+
markupList: IMarkupListProps;
|
|
101
|
+
maskGroup: IMaskGroupProps;
|
|
102
|
+
label: ILabelProps;
|
|
103
|
+
scrollingLabel: IScrollingLabelProps;
|
|
104
|
+
scrollableText: IScrollableTextProps;
|
|
105
|
+
simpleLabel: ISimpleLabelProps;
|
|
106
|
+
multiStyleLabel: IMultiStyleLabelProps;
|
|
107
|
+
button: IButtonProps;
|
|
108
|
+
buttonGroup: IButtonGroupProps;
|
|
109
|
+
busySpinner: IBusySpinnerProps;
|
|
110
|
+
blendedBusySpinner: IBlendedBusySpinnerProps;
|
|
111
|
+
group: IGroupProps;
|
|
112
|
+
"key-handler": IKeyHandlerProps;
|
|
113
|
+
animatedImage: IAnimatedImageProps;
|
|
114
|
+
poster: IPosterProps;
|
|
115
|
+
overhang: IOverhangProps;
|
|
116
|
+
animation: IAnimationProps;
|
|
117
|
+
sequentialAnimation: IAnimationBaseProps;
|
|
118
|
+
floatFieldInterpolator: IFloatFieldInterpolatorProps;
|
|
119
|
+
colorFieldInterpolator: IColorFieldInterpolatorProps;
|
|
120
|
+
vector2dFieldInterpolator: IVector2DFieldInterpolatorProps;
|
|
121
|
+
rectangle: IRectangleProps;
|
|
122
|
+
rowList: IRowListProps;
|
|
123
|
+
timeGrid: ITimeGridProps;
|
|
124
|
+
zoomRowList: IZoomRowListProps;
|
|
125
|
+
scene: ISceneProps;
|
|
126
|
+
layoutGroup: ILayoutGroupProps;
|
|
127
|
+
managedListPanel: IListPanelProps;
|
|
128
|
+
listPanel: IFullPanelProps;
|
|
129
|
+
panelSet: IPanelSetProps;
|
|
130
|
+
panel: IPanelProps;
|
|
131
|
+
radioButtonList: IRadioButtonListProps;
|
|
132
|
+
modal: IModalProps;
|
|
133
|
+
"modal-dialog": IModalProps;
|
|
134
|
+
standardDialogExt: IStandardDialogProps;
|
|
135
|
+
standardDialog: IStandardDialogProps;
|
|
136
|
+
standardKeyboardDialogExt: IStandardKeyboardDialogProps;
|
|
137
|
+
standardMessageDialogExt: IStandardMessageDialogProps;
|
|
138
|
+
standardPinPadDialogExt: IStandardPinPadDialogProps;
|
|
139
|
+
standardProgressDialogExt: IStandardProgressDialogProps;
|
|
140
|
+
dialog: IDialogProps;
|
|
141
|
+
stdDlgTitleArea: IStdDlgTitleAreaProps;
|
|
142
|
+
stdDlgContentArea: IStdDlgContentAreaProps;
|
|
143
|
+
stdDlgButtonArea: IStdDlgButtonAreaProps;
|
|
144
|
+
stdDlgSideCardArea: IStdDlgSideCardAreaProps;
|
|
145
|
+
stdDlgButton: IStdDlgButtonProps;
|
|
146
|
+
stdDlgItemGroup: IStdDlgItemGroupProps;
|
|
147
|
+
stdDlgActionCardItem: IStdDlgActionCardItemProps;
|
|
148
|
+
stdDlgBulletTextItem: IStdDlgBulletTextItemProps;
|
|
149
|
+
stdDlgDeterminateProgressItem: IStdDlgDeterminateProgressItemProps;
|
|
150
|
+
stdDlgGraphicItem: IStdDlgGraphicItemProps;
|
|
151
|
+
stdDlgMultiStyleTextItem: IStdDlgMultiStyleTextItemProps;
|
|
152
|
+
stdDlgKeyboardItem: IStdDlgKeyboardItemProps;
|
|
153
|
+
stdDlgProgressItem: IStdDlgProgressItemProps;
|
|
154
|
+
stdDlgTextItem: IStdDlgTextItemProps;
|
|
155
|
+
stdDlgCustomItem: IStdDlgCustomItemProps;
|
|
156
|
+
contentNode: IContentNodeProps;
|
|
157
|
+
posterGrid: IPosterGridProps;
|
|
158
|
+
markupGrid: IMarkupGridProps;
|
|
159
|
+
video: IVideoProps;
|
|
160
|
+
bifDisplay: IBifDisplayProps;
|
|
161
|
+
trickPlayBar: ITrickPlayBarProps;
|
|
162
|
+
progressBar: IProgressBarProps;
|
|
163
|
+
"bounding-tracker": IBoundingTrackerProps;
|
|
164
|
+
"focusable-group": IFocusableGroupProps;
|
|
165
|
+
focusable: IFocusableProps;
|
|
166
|
+
font: IFontProps;
|
|
167
|
+
channelStoreExt: IChannelStoreProps;
|
|
168
|
+
audio: IAudioProps;
|
|
169
|
+
soundEffect: ISoundEffectProps;
|
|
170
|
+
rsgPalette: IStandardDialogRSGPaletteNodeProps;
|
|
171
|
+
effect: IEffectProps;
|
|
172
|
+
targetGroup: ITargetGroupProps;
|
|
173
|
+
targetList: ITargetListProps;
|
|
174
|
+
targetSet: ITargetSetProps;
|
|
175
|
+
customKeyboard: IKeyboardPropsWithVoice;
|
|
176
|
+
dynamicKeyGrid: IDynamicKeyGridProps;
|
|
177
|
+
keyGridExt: IDynamicKeyGridProps;
|
|
178
|
+
dynamicKeyboard: IDynamicKeyboardProps;
|
|
179
|
+
keyboardExt: IDynamicKeyboardProps;
|
|
180
|
+
dynamicMiniKeyboard: IDynamicMiniKeyboardProps;
|
|
181
|
+
miniKeyboardExt: IDynamicMiniKeyboardProps;
|
|
182
|
+
dynamicPinPad: IDynamicPinPadProps;
|
|
183
|
+
pinPadExt: IDynamicPinPadProps;
|
|
184
|
+
voiceTextEditBox: IVoiceTextEditBoxProps;
|
|
185
|
+
tween: ITweenProps;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
package/src/use-delay.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
// These helpers map the type of timeoutId to a number
|
|
5
|
+
const setTimeout = (handler: (...args: unknown[]) => void, timeout?: number, ...args: unknown[]): number => {
|
|
6
|
+
return globalThis.setTimeout(handler, timeout, ...args) as unknown as number;
|
|
7
|
+
};
|
|
8
|
+
const clearTimeout = (handle: number): void => {
|
|
9
|
+
globalThis.clearTimeout(handle);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A custom hook that provides a delay function and a mechanism to resolve all pending delays early.
|
|
14
|
+
*
|
|
15
|
+
* @returns {[ (ms: number) => Promise<void>, () => void ]}
|
|
16
|
+
* - `delay(ms: number): Promise<void>`: A function that returns a promise which resolves after the specified delay in milliseconds.
|
|
17
|
+
* - `resolveDelaysEarly(): void`: A function that resolves all pending delay promises immediately and clears their timeouts.
|
|
18
|
+
*
|
|
19
|
+
* ### Example Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const [delay, resolveDelaysEarly] = useDelay();
|
|
22
|
+
*
|
|
23
|
+
* // Using the delay function
|
|
24
|
+
* await delay(1000); // Waits for 1 second
|
|
25
|
+
*
|
|
26
|
+
* // Resolving delays early
|
|
27
|
+
* const promise = delay(5000); // Starts a 5-second delay
|
|
28
|
+
* resolveDelaysEarly(); // Resolves the promise immediately
|
|
29
|
+
* await promise; // The promise resolves without waiting for 5 seconds
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* This hook is useful for scenarios where you need to manage delays but also require the ability
|
|
33
|
+
* to cancel or resolve them early, such as in testing or cleanup operations.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
export const useDelay = (): [
|
|
37
|
+
(ms: number) => Promise<void>, // delay function
|
|
38
|
+
() => void // resolveDelaysEarly function
|
|
39
|
+
] => {
|
|
40
|
+
const timeouts = new Map<number, () => void>(); // Map to track timeouts and their resolve functions
|
|
41
|
+
|
|
42
|
+
const delay = (ms: number): Promise<void> => {
|
|
43
|
+
return new Promise(resolve => {
|
|
44
|
+
const timeoutId = setTimeout(() => {
|
|
45
|
+
resolve();
|
|
46
|
+
timeouts.delete(timeoutId); // Cleanup after the timeout finishes
|
|
47
|
+
}, ms);
|
|
48
|
+
|
|
49
|
+
// Store the timeout ID and resolve function
|
|
50
|
+
timeouts.set(timeoutId, resolve);
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const resolveDelaysEarly = () => {
|
|
55
|
+
for (const [timeoutId, resolve] of timeouts) {
|
|
56
|
+
clearTimeout(timeoutId); // Clear all timeouts
|
|
57
|
+
resolve(); // Resolve all pending promises early
|
|
58
|
+
}
|
|
59
|
+
timeouts.clear(); // Clear the map after resolving
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return [delay, resolveDelaysEarly];
|
|
63
|
+
};
|
|
File without changes
|
|
File without changes
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@roku-sdk/dev-tools/typescript-config/tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"types": ["@roku-sdk/interfaces/global", "@roku-sdk/components/jsx"]
|
|
7
|
+
},
|
|
8
|
+
"include": ["src/**/*"],
|
|
9
|
+
"files": ["src/types/xml.d.ts", "src/types/sg-jsx.d.ts"]
|
|
10
|
+
}
|