@roku-sdk/components 0.0.0-stage → 2.18.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/BREAKING_CHANGES.md +84 -0
- package/LICENSE +21 -0
- package/README.md +19 -2
- package/core-jsx.d.ts +53 -0
- package/eslint.config.mjs +3 -0
- package/jsx.d.ts +273 -0
- package/package.json +84 -3
- package/src/__tests__/container.test.tsx +150 -0
- package/src/__tests__/glyphs.test.ts +202 -0
- package/src/__tests__/modal-boundary-export.test.ts +12 -0
- package/src/__tests__/native-modal.test.tsx +224 -0
- package/src/__tests__/tween-release.test.tsx +125 -0
- package/src/__tests__/tween-stops-shape.test.tsx +165 -0
- package/src/__tests__/tween-without-compat.test.tsx +64 -0
- package/src/__tests__/tween.test.tsx +195 -0
- package/src/blended-busy-spinner.props.ts +37 -0
- package/src/blended-busy-spinner.tsx +13 -0
- package/src/bounding-tracker.props.ts +18 -0
- package/src/bounding-tracker.tsx +13 -0
- package/src/button-row.tsx +126 -0
- package/src/channel-store.props.ts +425 -0
- package/src/channel-store.tsx +76 -0
- package/src/container.tsx +130 -0
- package/src/core/jsx-runtime.ts +39 -0
- package/src/focusable-group.props.ts +8 -0
- package/src/focusable-group.tsx +17 -0
- package/src/focusable.props.ts +14 -0
- package/src/focusable.tsx +17 -0
- package/src/glyphs.ts +116 -0
- package/src/helpers/index.tsx +4 -0
- package/src/helpers/resolution-context.tsx +68 -0
- package/src/helpers/scale-for-device-resolution.ts +31 -0
- package/src/index.tsx +70 -0
- package/src/jsx-props.ts +87 -0
- package/src/kdfs.d.ts +14 -0
- package/src/kdfs.ts +15 -0
- package/src/key-handler.props.ts +33 -0
- package/src/key-handler.tsx +24 -0
- package/src/modal-dialog.props.ts +38 -0
- package/src/modal-dialog.tsx +41 -0
- package/src/retain-asset.ts +24 -0
- package/src/sg-intrinsics.json +1153 -0
- package/src/sg-nodes/__tests__/__snapshots__/font.test.tsx.snap +13 -0
- package/src/sg-nodes/__tests__/__snapshots__/prop-forwarding.test.tsx.snap +4409 -0
- package/src/sg-nodes/__tests__/core-props.test.ts +301 -0
- package/src/sg-nodes/__tests__/font.test.tsx +141 -0
- package/src/sg-nodes/__tests__/imperative-methods.test.ts +268 -0
- package/src/sg-nodes/__tests__/prop-forwarding.test.tsx +1049 -0
- package/src/sg-nodes/__tests__/solid-integration.test.tsx +719 -0
- package/src/sg-nodes/animated-image.props.ts +64 -0
- package/src/sg-nodes/animated-image.tsx +23 -0
- package/src/sg-nodes/animation.props.ts +292 -0
- package/src/sg-nodes/animation.tsx +190 -0
- package/src/sg-nodes/array-grid.ts +602 -0
- package/src/sg-nodes/audio.props.ts +302 -0
- package/src/sg-nodes/audio.tsx +57 -0
- package/src/sg-nodes/busy-spinner.props.ts +59 -0
- package/src/sg-nodes/busy-spinner.tsx +84 -0
- package/src/sg-nodes/button-group.props.ts +141 -0
- package/src/sg-nodes/button-group.tsx +30 -0
- package/src/sg-nodes/button.props.ts +119 -0
- package/src/sg-nodes/button.tsx +31 -0
- package/src/sg-nodes/check-list.props.ts +71 -0
- package/src/sg-nodes/check-list.tsx +55 -0
- package/src/sg-nodes/content-node.props.ts +1316 -0
- package/src/sg-nodes/content-node.tsx +153 -0
- package/src/sg-nodes/core-props.ts +197 -0
- package/src/sg-nodes/custom-keyboard.props.ts +108 -0
- package/src/sg-nodes/custom-keyboard.tsx +48 -0
- package/src/sg-nodes/dialog.props.ts +159 -0
- package/src/sg-nodes/dialog.tsx +36 -0
- package/src/sg-nodes/dynamic-key-grid.props.ts +22 -0
- package/src/sg-nodes/dynamic-key-grid.tsx +16 -0
- package/src/sg-nodes/dynamic-keyboard.props.ts +30 -0
- package/src/sg-nodes/dynamic-keyboard.tsx +18 -0
- package/src/sg-nodes/dynamic-mini-keyboard.props.ts +22 -0
- package/src/sg-nodes/dynamic-mini-keyboard.tsx +18 -0
- package/src/sg-nodes/dynamic-pinpad.props.ts +57 -0
- package/src/sg-nodes/dynamic-pinpad.tsx +18 -0
- package/src/sg-nodes/effect.props.ts +116 -0
- package/src/sg-nodes/effect.tsx +39 -0
- package/src/sg-nodes/font.props.ts +45 -0
- package/src/sg-nodes/font.tsx +80 -0
- package/src/sg-nodes/group.props.ts +105 -0
- package/src/sg-nodes/group.tsx +30 -0
- package/src/sg-nodes/label-list.props.ts +86 -0
- package/src/sg-nodes/label-list.tsx +64 -0
- package/src/sg-nodes/label.props.ts +207 -0
- package/src/sg-nodes/label.tsx +56 -0
- package/src/sg-nodes/layout-group.props.ts +69 -0
- package/src/sg-nodes/layout-group.tsx +75 -0
- package/src/sg-nodes/list-panel.props.ts +104 -0
- package/src/sg-nodes/list-panel.tsx +49 -0
- package/src/sg-nodes/markup-grid.props.ts +78 -0
- package/src/sg-nodes/markup-grid.tsx +38 -0
- package/src/sg-nodes/markup-list.props.ts +68 -0
- package/src/sg-nodes/markup-list.tsx +38 -0
- package/src/sg-nodes/mask-group.props.ts +78 -0
- package/src/sg-nodes/mask-group.tsx +59 -0
- package/src/sg-nodes/media-playback-methods.ts +20 -0
- package/src/sg-nodes/node.ts +77 -0
- package/src/sg-nodes/overhang.props.ts +169 -0
- package/src/sg-nodes/overhang.tsx +29 -0
- package/src/sg-nodes/panel-set.props.ts +71 -0
- package/src/sg-nodes/panel-set.tsx +53 -0
- package/src/sg-nodes/panel.props.ts +176 -0
- package/src/sg-nodes/panel.tsx +56 -0
- package/src/sg-nodes/poster-grid.props.ts +277 -0
- package/src/sg-nodes/poster-grid.tsx +45 -0
- package/src/sg-nodes/poster.props.ts +125 -0
- package/src/sg-nodes/poster.tsx +44 -0
- package/src/sg-nodes/radio-button-list.props.ts +59 -0
- package/src/sg-nodes/radio-button-list.tsx +68 -0
- package/src/sg-nodes/rectangle.props.ts +29 -0
- package/src/sg-nodes/rectangle.tsx +27 -0
- package/src/sg-nodes/row-list.props.ts +288 -0
- package/src/sg-nodes/row-list.tsx +47 -0
- package/src/sg-nodes/scene.props.ts +65 -0
- package/src/sg-nodes/scene.tsx +15 -0
- package/src/sg-nodes/scrollable-text.props.ts +133 -0
- package/src/sg-nodes/scrollable-text.tsx +64 -0
- package/src/sg-nodes/scrolling-label.props.ts +106 -0
- package/src/sg-nodes/scrolling-label.tsx +42 -0
- package/src/sg-nodes/simple-label.props.ts +156 -0
- package/src/sg-nodes/simple-label.tsx +59 -0
- package/src/sg-nodes/sound-effect.props.ts +130 -0
- package/src/sg-nodes/sound-effect.tsx +65 -0
- package/src/sg-nodes/standard-dialog.props.ts +520 -0
- package/src/sg-nodes/standard-dialog.tsx +428 -0
- package/src/sg-nodes/standard-keyboard-dialog.props.ts +84 -0
- package/src/sg-nodes/standard-keyboard-dialog.tsx +59 -0
- package/src/sg-nodes/standard-message-dialog.props.ts +56 -0
- package/src/sg-nodes/standard-message-dialog.tsx +48 -0
- package/src/sg-nodes/standard-pinpad-dialog.props.ts +64 -0
- package/src/sg-nodes/standard-pinpad-dialog.tsx +46 -0
- package/src/sg-nodes/standard-progress-dialog.props.ts +30 -0
- package/src/sg-nodes/standard-progress-dialog.tsx +43 -0
- package/src/sg-nodes/target-group.props.ts +278 -0
- package/src/sg-nodes/target-group.tsx +63 -0
- package/src/sg-nodes/target-list.props.ts +128 -0
- package/src/sg-nodes/target-list.tsx +66 -0
- package/src/sg-nodes/target-set.props.ts +63 -0
- package/src/sg-nodes/target-set.tsx +42 -0
- package/src/sg-nodes/time-grid.props.ts +646 -0
- package/src/sg-nodes/time-grid.tsx +87 -0
- package/src/sg-nodes/tween.props.ts +115 -0
- package/src/sg-nodes/types.ts +150 -0
- package/src/sg-nodes/video.props.ts +573 -0
- package/src/sg-nodes/video.tsx +73 -0
- package/src/sg-nodes/voice-text-edit-box.props.ts +91 -0
- package/src/sg-nodes/voice-text-edit-box.tsx +15 -0
- package/src/sg-nodes/zoom-row-list.props.ts +416 -0
- package/src/sg-nodes/zoom-row-list.tsx +42 -0
- package/src/standard-dialog-next/__tests__/standard-dialog-next.test.tsx +186 -0
- package/src/standard-dialog-next/index.ts +5 -0
- package/src/standard-dialog-next/standard-dialog-next.props.ts +80 -0
- package/src/standard-dialog-next/standard-dialog-next.tsx +326 -0
- package/src/test-helpers/tween-test-setup.ts +78 -0
- package/src/tween.tsx +173 -0
- package/src/types.ts +8 -0
- package/src/xml-components/blended-busy-spinner/BlendedBusySpinner.brs +13 -0
- package/src/xml-components/blended-busy-spinner/BlendedBusySpinner.xml +10 -0
- package/src/xml-components/blended-busy-spinner/BlendedBusySpinner.xml.d.ts +42 -0
- package/src/xml-components/bounding-tracker/BoundingTracker.brs +26 -0
- package/src/xml-components/bounding-tracker/BoundingTracker.xml +14 -0
- package/src/xml-components/bounding-tracker/BoundingTracker.xml.d.ts +42 -0
- package/src/xml-components/channel-store/channelStoreExt.brs +159 -0
- package/src/xml-components/channel-store/channelStoreExt.xml +29 -0
- package/src/xml-components/channel-store/channelStoreExt.xml.d.ts +57 -0
- package/src/xml-components/focus/focusable-group.brs +251 -0
- package/src/xml-components/focus/focusable-group.xml +15 -0
- package/src/xml-components/focus/focusable-group.xml.d.ts +42 -0
- package/src/xml-components/focus/focusable.xml +18 -0
- package/src/xml-components/focus/focusable.xml.d.ts +48 -0
- package/src/xml-components/keyboards/CustomAddressKDF.keyboard.json +547 -0
- package/src/xml-components/keyboards/CustomKeyboard.brs +322 -0
- package/src/xml-components/keyboards/CustomKeyboard.xml +45 -0
- package/src/xml-components/keyboards/CustomKeyboard.xml.d.ts +73 -0
- package/src/xml-components/keyboards/KeyGridExt.xml +4 -0
- package/src/xml-components/keyboards/KeyGridExt.xml.d.ts +37 -0
- package/src/xml-components/keyboards/KeyboardExt.xml +4 -0
- package/src/xml-components/keyboards/KeyboardExt.xml.d.ts +37 -0
- package/src/xml-components/keyboards/MOPPinPadCustomKDF.keyboard.json +151 -0
- package/src/xml-components/keyboards/MiniKeyboardExt.xml +4 -0
- package/src/xml-components/keyboards/MiniKeyboardExt.xml.d.ts +37 -0
- package/src/xml-components/keyboards/PhonePadCustomKDF.keyboard.json +42 -0
- package/src/xml-components/keyboards/PinPadExt.brs +102 -0
- package/src/xml-components/keyboards/PinPadExt.xml +17 -0
- package/src/xml-components/keyboards/PinPadExt.xml.d.ts +49 -0
- package/src/xml-components/keyboards/WifiCustomKDF.keyboard.json +1242 -0
- package/src/xml-components/keyhandler/KeyHandler.brs +30 -0
- package/src/xml-components/keyhandler/KeyHandler.xml +16 -0
- package/src/xml-components/keyhandler/KeyHandler.xml.d.ts +45 -0
- package/src/xml-components/managed-list-panel/ManagedListPanel.brs +137 -0
- package/src/xml-components/managed-list-panel/ManagedListPanel.xml +10 -0
- package/src/xml-components/managed-list-panel/ManagedListPanel.xml.d.ts +37 -0
- package/src/xml-components/modal/Modal.brs +105 -0
- package/src/xml-components/modal/Modal.xml +22 -0
- package/src/xml-components/modal/Modal.xml.d.ts +54 -0
- package/src/xml-components/modal/StandardDialogExt.xml +10 -0
- package/src/xml-components/modal/StandardDialogExt.xml.d.ts +37 -0
- package/src/xml-components/modal/StandardKeyboardDialogExt.xml +10 -0
- package/src/xml-components/modal/StandardKeyboardDialogExt.xml.d.ts +37 -0
- package/src/xml-components/modal/StandardMessageDialogExt.xml +10 -0
- package/src/xml-components/modal/StandardMessageDialogExt.xml.d.ts +37 -0
- package/src/xml-components/modal/StandardPinPadDialogExt.xml +10 -0
- package/src/xml-components/modal/StandardPinPadDialogExt.xml.d.ts +37 -0
- package/src/xml-components/modal/StandardProgressDialogExt.xml +10 -0
- package/src/xml-components/modal/StandardProgressDialogExt.xml.d.ts +37 -0
- package/src/xml-components/modal/tests/Modal.test.brs +195 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { transactionManager } from "@roku-sdk/common/transaction";
|
|
5
|
+
import { ComponentRef, DomNode } from "@roku-sdk/interfaces";
|
|
6
|
+
import { Component, JSX, splitProps, tmTransaction } from "@roku-sdk/solid";
|
|
7
|
+
|
|
8
|
+
import { IGroupProps } from "./sg-nodes/group";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Reference type for the Container component.
|
|
12
|
+
*
|
|
13
|
+
* Extends {@link ComponentRef} with imperative methods for dynamic node
|
|
14
|
+
* insertion and removal. This provides a typed public API for pooling
|
|
15
|
+
* patterns that need to reparent nodes at runtime.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* let containerRef!: ContainerRef;
|
|
20
|
+
*
|
|
21
|
+
* // Acquire a pooled node and insert it
|
|
22
|
+
* const node = pool.acquire();
|
|
23
|
+
* containerRef.insertNode(node.element);
|
|
24
|
+
*
|
|
25
|
+
* // Later, remove the node (returns it to pool)
|
|
26
|
+
* containerRef.removeNode(node.element);
|
|
27
|
+
* pool.release(node);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export interface ContainerRef extends ComponentRef<IGroupProps> {
|
|
31
|
+
/**
|
|
32
|
+
* Inserts a node as a child of this container.
|
|
33
|
+
* The node is appended to the end of the children list.
|
|
34
|
+
*
|
|
35
|
+
* @param node - The DomNode to insert into this container
|
|
36
|
+
*/
|
|
37
|
+
insertNode: (node: DomNode) => void;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Removes a node from this container.
|
|
41
|
+
* The node is marked for removal and will be detached on the next commit.
|
|
42
|
+
*
|
|
43
|
+
* On firmware 15.2.x the parent link is the only strong reference to a
|
|
44
|
+
* SceneGraph node, so a committed detach destroys it and a later
|
|
45
|
+
* `insertNode` of the same node hands the render thread a deleted
|
|
46
|
+
* reference. Pooling that has to run on 15.2.x should reparent through
|
|
47
|
+
* {@link ContainerRef.insertNode} into a hidden container rather than
|
|
48
|
+
* detaching.
|
|
49
|
+
*
|
|
50
|
+
* @param node - The DomNode to remove from this container
|
|
51
|
+
*/
|
|
52
|
+
removeNode: (node: DomNode) => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Props for the Container component.
|
|
57
|
+
*/
|
|
58
|
+
export interface IContainerProps extends Omit<IGroupProps, "ref"> {
|
|
59
|
+
/** Callback ref to receive the ContainerRef with imperative methods. */
|
|
60
|
+
ref?: (ref: ContainerRef) => void;
|
|
61
|
+
/** Child elements to render inside the container. */
|
|
62
|
+
children?: JSX.Element;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Container is a Group wrapper that exposes typed imperative methods for
|
|
67
|
+
* dynamic node insertion and removal.
|
|
68
|
+
*
|
|
69
|
+
* This component is designed for advanced pooling patterns where nodes need
|
|
70
|
+
* to be reparented at runtime without triggering full reactive re-renders.
|
|
71
|
+
* It wraps the raw `tmTransaction.insertNode/removeNode` calls with a typed
|
|
72
|
+
* API, eliminating the need for `as any` casts and eslint-disable comments.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { Container, ContainerRef } from "@roku-sdk/components";
|
|
77
|
+
*
|
|
78
|
+
* const PooledGrid: Component = () => {
|
|
79
|
+
* let slotContainerRef!: ContainerRef;
|
|
80
|
+
*
|
|
81
|
+
* createEffect(() => {
|
|
82
|
+
* const node = pool.acquire();
|
|
83
|
+
* slotContainerRef.insertNode(node.element);
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* return (
|
|
87
|
+
* <Container ref={(el) => (slotContainerRef = el)}>
|
|
88
|
+
* {/* Pooled nodes are inserted here dynamically *\/}
|
|
89
|
+
* </Container>
|
|
90
|
+
* );
|
|
91
|
+
* };
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* @see {@link ContainerRef} for the imperative methods available on the ref
|
|
95
|
+
*/
|
|
96
|
+
export const Container: Component<IContainerProps> = props => {
|
|
97
|
+
// Use splitProps to preserve reactivity on spread props
|
|
98
|
+
const [local, groupProps] = splitProps(props, ["ref", "children"]);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<group
|
|
102
|
+
{...groupProps}
|
|
103
|
+
ref={(el: DomNode) => {
|
|
104
|
+
// Extend the element with imperative methods
|
|
105
|
+
const containerRef = el as ContainerRef;
|
|
106
|
+
|
|
107
|
+
// `tmTransaction` assumes an open transaction — the Solid renderer
|
|
108
|
+
// opens one before every call it makes. These methods run outside the
|
|
109
|
+
// renderer, so they open it themselves. `insertNode` reaches native
|
|
110
|
+
// `appendNode` synchronously (firmware 15.2.x raises a render-thread
|
|
111
|
+
// exception if no transaction is open) and `removeNode` only queues
|
|
112
|
+
// the detach for the pre-commit hook, which a commit has to drive.
|
|
113
|
+
containerRef.insertNode = (node: DomNode) => {
|
|
114
|
+
transactionManager.startTransaction();
|
|
115
|
+
tmTransaction.insertNode(el, node);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
containerRef.removeNode = (node: DomNode) => {
|
|
119
|
+
transactionManager.startTransaction();
|
|
120
|
+
tmTransaction.removeNode(el, node);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Pass the extended ref to the consumer
|
|
124
|
+
local.ref?.(containerRef);
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
{local.children}
|
|
128
|
+
</group>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* JSX runtime entry point for the **frozen core** property contract.
|
|
6
|
+
*
|
|
7
|
+
* This module exists to be named by `jsxImportSource` in an application's tsconfig:
|
|
8
|
+
*
|
|
9
|
+
* ```jsonc
|
|
10
|
+
* { "compilerOptions": { "jsxImportSource": "@roku-sdk/components/core" } }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* TypeScript then resolves JSX intrinsic element types from
|
|
14
|
+
* `@roku-sdk/components/core/jsx-runtime`, and the sibling `core-jsx.d.ts` augments exactly this
|
|
15
|
+
* specifier with an intrinsic map keyed to the `I*CoreProps` interfaces. So `<poster>` resolves to
|
|
16
|
+
* `IPosterCoreProps` rather than the full `IPosterProps`, and a property outside the frozen subset
|
|
17
|
+
* is a compile error naming the property.
|
|
18
|
+
*
|
|
19
|
+
* Two things make this the enforcement point rather than a convenience:
|
|
20
|
+
*
|
|
21
|
+
* 1. **A module-scoped `JSX` namespace replaces the global one, it does not merge with it.** The
|
|
22
|
+
* full intrinsic map in `rsg-ts/src/types/sg-jsx.d.ts` augments a different specifier, so it is
|
|
23
|
+
* not in scope for a build that points here — provided that map is kept out of the program.
|
|
24
|
+
* That is the one easily-missed part of the setup: an app opting in must also drop
|
|
25
|
+
* `@roku-sdk/components/jsx` from `types[]` and the inherited `sg-jsx.d.ts` from `files[]`,
|
|
26
|
+
* because the star re-export below would otherwise carry those augmentations back in.
|
|
27
|
+
* 2. **Application source is unchanged.** Only the tsconfig differs.
|
|
28
|
+
*
|
|
29
|
+
* The runtime behaviour is unchanged — the factory is re-exported from `@roku-sdk/solid` — because
|
|
30
|
+
* the divergence is purely a compile-time *type* contract, not a second implementation. Builds do
|
|
31
|
+
* not read `jsxImportSource` at all: esbuild is configured with a classic `jsxFactory` and
|
|
32
|
+
* `babel-preset-solid` is pinned to `moduleName: "@roku-sdk/solid"`.
|
|
33
|
+
*
|
|
34
|
+
* The re-export must stay a star re-export. TypeScript resolves `JSX.Element`,
|
|
35
|
+
* `JSX.ElementChildrenAttribute` and `JSX.IntrinsicAttributes` from this same module, and those
|
|
36
|
+
* come from SolidJS; a named re-export of the factory alone would leave them undefined.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
export * from "@roku-sdk/solid/jsx-runtime";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IFocusableGroupProps } from "./focusable-group.props";
|
|
5
|
+
import { Component } from "./index";
|
|
6
|
+
import { retainAsset } from "./retain-asset";
|
|
7
|
+
import FocusableGroupXML from "./xml-components/focus/focusable-group.xml";
|
|
8
|
+
export type { IFocusableGroupProps } from "./focusable-group.props";
|
|
9
|
+
|
|
10
|
+
export const FocusableGroup: Component<IFocusableGroupProps> = props => {
|
|
11
|
+
retainAsset(FocusableGroupXML);
|
|
12
|
+
return (
|
|
13
|
+
<focusable-group focusable={true} {...props}>
|
|
14
|
+
{props.children}
|
|
15
|
+
</focusable-group>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IGroupProps } from "./sg-nodes/group.props";
|
|
5
|
+
|
|
6
|
+
export interface IFocusableProps extends IGroupProps {
|
|
7
|
+
nextFocusRight?: string;
|
|
8
|
+
nextFocusLeft?: string;
|
|
9
|
+
nextFocusUp?: string;
|
|
10
|
+
nextFocusDown?: string;
|
|
11
|
+
nextFocusBack?: string;
|
|
12
|
+
nextFocusOk?: string;
|
|
13
|
+
hasPreferredFocus?: boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IFocusableProps } from "./focusable.props";
|
|
5
|
+
import { retainAsset } from "./retain-asset";
|
|
6
|
+
import { Component } from "./types";
|
|
7
|
+
import FocusableXML from "./xml-components/focus/focusable.xml";
|
|
8
|
+
export type { IFocusableProps } from "./focusable.props";
|
|
9
|
+
|
|
10
|
+
export const Focusable: Component<IFocusableProps> = props => {
|
|
11
|
+
retainAsset(FocusableXML);
|
|
12
|
+
return (
|
|
13
|
+
<focusable focusable={true} {...props}>
|
|
14
|
+
{props.children}
|
|
15
|
+
</focusable>
|
|
16
|
+
);
|
|
17
|
+
};
|
package/src/glyphs.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Named character constants for symbols that are awkward or impossible to type
|
|
6
|
+
* directly in source.
|
|
7
|
+
*
|
|
8
|
+
* The constants are grouped by the property that actually matters at runtime:
|
|
9
|
+
* which font has to supply the character.
|
|
10
|
+
*
|
|
11
|
+
* 1. RokuFont01 characters (the private-use area, plus ● ★ ☆). RokuFont01 is
|
|
12
|
+
* the system-wide fallback font in firmware, so these render under a system
|
|
13
|
+
* font AND under a custom app-supplied font.
|
|
14
|
+
* 2. RokuUI-Regular symbols. RokuUI-Regular is the default UI font but is not
|
|
15
|
+
* in the fallback chain, so these render under a system font but become tofu
|
|
16
|
+
* under a custom app-supplied font unless that font supplies them itself.
|
|
17
|
+
*
|
|
18
|
+
* The practical consequence, verified on device against firmware 15.3.5: if
|
|
19
|
+
* your app ships a custom font, the group that needs care is (2), not (1).
|
|
20
|
+
*
|
|
21
|
+
* A custom font that defines a codepoint itself always wins — no fallback
|
|
22
|
+
* occurs. A font carrying its own U+E0xx private-use glyphs will render those
|
|
23
|
+
* rather than the Roku icons.
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// -----------------------------------------------------------------------------
|
|
29
|
+
// RokuFont01 — private-use area glyphs
|
|
30
|
+
//
|
|
31
|
+
// Supplied by the firmware fallback font, so these survive a custom app font.
|
|
32
|
+
// -----------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
export const OPTIONS_GLYPH = "\uE000";
|
|
35
|
+
export const OK_BUTTON_GLYPH = "\uE001";
|
|
36
|
+
export const OPTIONS_BUTTON_GLYPH = "\uE002";
|
|
37
|
+
export const MICROPHONE_GLYPH = "\uE003";
|
|
38
|
+
export const PLAY_PAUSE_BUTTON_GLYPH = "\uE004";
|
|
39
|
+
export const PLAY_PAUSE_GLYPH = "\uE005";
|
|
40
|
+
/**
|
|
41
|
+
* Baseline-aligned dot, sized and positioned to line up with the other icon
|
|
42
|
+
* glyphs in this block. Use {@link BLACK_CIRCLE} for a dot inside a run of
|
|
43
|
+
* text — that one is raised to text centre.
|
|
44
|
+
*/
|
|
45
|
+
export const DOT_GLYPH = "\uE006";
|
|
46
|
+
export const HOME_GLYPH = "\uE007";
|
|
47
|
+
export const SEARCH_GLYPH = "\uE008";
|
|
48
|
+
export const REMOTE_GLYPH = "\uE009";
|
|
49
|
+
export const REPLAY_GLYPH = "\uE010";
|
|
50
|
+
export const MICROPHONE_BUTTON_GLYPH = "\uE011";
|
|
51
|
+
export const SEARCH_BUTTON_GLYPH = "\uE012";
|
|
52
|
+
export const FAST_FORWARD_GLYPH = "\uE013";
|
|
53
|
+
export const REWIND_GLYPH = "\uE014";
|
|
54
|
+
export const SHORTCUT_ONE_BUTTON_GLYPH = "\uE015";
|
|
55
|
+
export const SHORTCUT_TWO_BUTTON_GLYPH = "\uE016";
|
|
56
|
+
export const CLOSED_CAPTIONS_GLYPH = "\uE017";
|
|
57
|
+
export const LIVE_TV_GLYPH = "\uE018";
|
|
58
|
+
export const SLEEP_TIMER_GLYPH = "\uE019";
|
|
59
|
+
export const GENERAL_APP_GLYPH = "\uE020";
|
|
60
|
+
export const BACK_BUTTON_GLYPH = "\uE021";
|
|
61
|
+
export const HOME_BUTTON_GLYPH = "\uE022";
|
|
62
|
+
export const QUICK_LAUNCH_BUTTON_GLYPH = "\uE023";
|
|
63
|
+
export const DOWN_BUTTON_GLYPH = "\uE024";
|
|
64
|
+
export const LEFT_BUTTON_GLYPH = "\uE025";
|
|
65
|
+
export const RIGHT_BUTTON_GLYPH = "\uE026";
|
|
66
|
+
export const KIDS_PROFILE_GLYPH = "\uE027";
|
|
67
|
+
export const UP_BUTTON_GLYPH = "\uE028";
|
|
68
|
+
export const POWER_BUTTON_GLYPH = "\uE029";
|
|
69
|
+
export const THUMBS_UP_GLYPH = "\uE030";
|
|
70
|
+
export const THUMBS_DOWN_GLYPH = "\uE031";
|
|
71
|
+
|
|
72
|
+
// -----------------------------------------------------------------------------
|
|
73
|
+
// RokuFont01 — standard Unicode symbols
|
|
74
|
+
//
|
|
75
|
+
// These are real Unicode codepoints, but RokuUI-Regular does not contain them:
|
|
76
|
+
// they resolve through the RokuFont01 fallback, exactly like the private-use
|
|
77
|
+
// glyphs above. That fallback applies under a custom app font too, so these are
|
|
78
|
+
// the safe shapes to use in custom-font text.
|
|
79
|
+
// -----------------------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
/** ● U+25CF BLACK CIRCLE — raised to text centre, for a dot inside a text run. */
|
|
82
|
+
export const BLACK_CIRCLE = "\u25CF";
|
|
83
|
+
/** ★ U+2605 BLACK STAR — filled star, e.g. a filled rating position. */
|
|
84
|
+
export const BLACK_STAR = "\u2605";
|
|
85
|
+
/** ☆ U+2606 WHITE STAR — outlined star, e.g. an empty rating position. */
|
|
86
|
+
export const WHITE_STAR = "\u2606";
|
|
87
|
+
|
|
88
|
+
// -----------------------------------------------------------------------------
|
|
89
|
+
// RokuUI-Regular symbols
|
|
90
|
+
//
|
|
91
|
+
// Present in the default UI font, so no fallback is needed under a system font.
|
|
92
|
+
// Under a custom app font there is no RokuFont01 backstop for these either — a
|
|
93
|
+
// custom font that lacks them renders tofu. These are the constants to watch if
|
|
94
|
+
// your app ships its own font.
|
|
95
|
+
// -----------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
/** • U+2022 BULLET */
|
|
98
|
+
export const BULLET = "\u2022";
|
|
99
|
+
/** … U+2026 HORIZONTAL ELLIPSIS */
|
|
100
|
+
export const ELLIPSIS = "\u2026";
|
|
101
|
+
/** – U+2013 EN DASH */
|
|
102
|
+
export const EN_DASH = "\u2013";
|
|
103
|
+
/** — U+2014 EM DASH */
|
|
104
|
+
export const EM_DASH = "\u2014";
|
|
105
|
+
/** ← U+2190 LEFTWARDS ARROW */
|
|
106
|
+
export const LEFT_ARROW = "\u2190";
|
|
107
|
+
/** ↑ U+2191 UPWARDS ARROW */
|
|
108
|
+
export const UP_ARROW = "\u2191";
|
|
109
|
+
/** → U+2192 RIGHTWARDS ARROW */
|
|
110
|
+
export const RIGHT_ARROW = "\u2192";
|
|
111
|
+
/** ↓ U+2193 DOWNWARDS ARROW */
|
|
112
|
+
export const DOWN_ARROW = "\u2193";
|
|
113
|
+
/** ✓ U+2713 CHECK MARK */
|
|
114
|
+
export const CHECK_MARK = "\u2713";
|
|
115
|
+
/** ✗ U+2717 BALLOT X */
|
|
116
|
+
export const BALLOT_X = "\u2717";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { getAppInfo } from "@roku-sdk/runtime/app-info";
|
|
4
|
+
import { useUiResolution } from "@roku-sdk/runtime/device-info-events";
|
|
5
|
+
import type { Component, JSX } from "@roku-sdk/solid";
|
|
6
|
+
import { createContext, createEffect, createSignal, useContext } from "@roku-sdk/solid";
|
|
7
|
+
|
|
8
|
+
export enum Resolution {
|
|
9
|
+
HD = "hd",
|
|
10
|
+
FHD = "fhd",
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
12
|
+
hd = "hd",
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
14
|
+
fhd = "fhd"
|
|
15
|
+
}
|
|
16
|
+
export enum ResolutionScale {
|
|
17
|
+
HD = 1,
|
|
18
|
+
FHD = 1.5,
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
20
|
+
hd = 1,
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
|
22
|
+
fhd = 1.5
|
|
23
|
+
}
|
|
24
|
+
interface ResolutionContextValue {
|
|
25
|
+
isFHDOnly: boolean;
|
|
26
|
+
deviceResolution: () => Resolution | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface IResolutionContextProviderProps {
|
|
30
|
+
children: JSX.Element;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const ResolutionContext = createContext<ResolutionContextValue>();
|
|
34
|
+
|
|
35
|
+
export const ResolutionProvider: Component<IResolutionContextProviderProps> = props => {
|
|
36
|
+
const appInfo = getAppInfo();
|
|
37
|
+
const resolutions = appInfo?.getManifestValue("ui_resolutions")?.split(",");
|
|
38
|
+
const isFHDOnly = resolutions?.includes("fhd") && !resolutions?.includes("hd");
|
|
39
|
+
const { uiResolution } = useUiResolution();
|
|
40
|
+
|
|
41
|
+
const [deviceResolution, setDeviceResolution] = createSignal<Resolution>();
|
|
42
|
+
|
|
43
|
+
createEffect(() => {
|
|
44
|
+
const resolution = uiResolution();
|
|
45
|
+
|
|
46
|
+
if (resolution && !deviceResolution()) {
|
|
47
|
+
setDeviceResolution(resolution.name.toLowerCase() as Resolution);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const value: ResolutionContextValue = {
|
|
52
|
+
isFHDOnly: isFHDOnly === undefined ? true : isFHDOnly,
|
|
53
|
+
deviceResolution
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return <ResolutionContext.Provider value={value}>{props.children}</ResolutionContext.Provider>;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function useResolutionContext() {
|
|
60
|
+
const context = useContext(ResolutionContext);
|
|
61
|
+
if (!context) {
|
|
62
|
+
return {
|
|
63
|
+
isFHDOnly: true,
|
|
64
|
+
deviceResolution: () => Resolution.FHD
|
|
65
|
+
} as ResolutionContextValue;
|
|
66
|
+
}
|
|
67
|
+
return context;
|
|
68
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { Accessor, createMemo } from "@roku-sdk/solid";
|
|
4
|
+
|
|
5
|
+
import { Vector2D } from "../sg-nodes/types";
|
|
6
|
+
import { useResolutionContext } from "./resolution-context";
|
|
7
|
+
|
|
8
|
+
const scale = (value: number) => Math.floor((value * 2) / 3);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Workaround to scale the size based on the device resolution.
|
|
12
|
+
* Used to fix the lack of autoscaling when the device resolution is not FHD.
|
|
13
|
+
* Resolution-related properties of some SceneGraph nodes do not autoscale
|
|
14
|
+
* when the resolution is not FHD, even when autoscaling is enabled
|
|
15
|
+
* (manifest has FHD resolution only).
|
|
16
|
+
*
|
|
17
|
+
* @important This workaround works only under ResolutionProvider.
|
|
18
|
+
*
|
|
19
|
+
* @param size - The size accessor to apply the workaround to.
|
|
20
|
+
* @returns The autoscaled size accessor.
|
|
21
|
+
*/
|
|
22
|
+
export const scaleForDeviceResolution = (size: Accessor<Vector2D>): Accessor<Vector2D> => {
|
|
23
|
+
const { deviceResolution } = useResolutionContext();
|
|
24
|
+
return createMemo<Vector2D>(() => {
|
|
25
|
+
const [width, height] = size();
|
|
26
|
+
if (deviceResolution() === "hd") {
|
|
27
|
+
return [scale(width), scale(height)];
|
|
28
|
+
}
|
|
29
|
+
return [width, height];
|
|
30
|
+
});
|
|
31
|
+
};
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
export * from "./sg-nodes/animation";
|
|
5
|
+
export * from "./sg-nodes/animated-image";
|
|
6
|
+
export * from "./sg-nodes/array-grid";
|
|
7
|
+
export * from "./bounding-tracker";
|
|
8
|
+
export * from "./blended-busy-spinner";
|
|
9
|
+
export { BusySpinner } from "./sg-nodes/busy-spinner";
|
|
10
|
+
export * from "./sg-nodes/button";
|
|
11
|
+
export * from "./sg-nodes/button-group";
|
|
12
|
+
export * from "./channel-store";
|
|
13
|
+
export * from "./container";
|
|
14
|
+
export * from "./sg-nodes/content-node";
|
|
15
|
+
export * from "./sg-nodes/custom-keyboard";
|
|
16
|
+
export * from "./sg-nodes/dialog";
|
|
17
|
+
export * from "./sg-nodes/dynamic-key-grid";
|
|
18
|
+
export * from "./sg-nodes/dynamic-keyboard";
|
|
19
|
+
export * from "./sg-nodes/dynamic-mini-keyboard";
|
|
20
|
+
export * from "./sg-nodes/dynamic-pinpad";
|
|
21
|
+
export * from "./sg-nodes/effect";
|
|
22
|
+
export * from "./focusable";
|
|
23
|
+
export * from "./focusable-group";
|
|
24
|
+
export * from "./sg-nodes/font";
|
|
25
|
+
export * from "./sg-nodes/group";
|
|
26
|
+
export * from "./key-handler";
|
|
27
|
+
export * from "./sg-nodes/label";
|
|
28
|
+
export * from "./sg-nodes/label-list";
|
|
29
|
+
export * from "./sg-nodes/check-list";
|
|
30
|
+
export * from "./sg-nodes/layout-group";
|
|
31
|
+
export * from "./sg-nodes/list-panel";
|
|
32
|
+
export * from "./sg-nodes/markup-list";
|
|
33
|
+
export * from "./sg-nodes/mask-group";
|
|
34
|
+
// Implementation lives in @roku-sdk/navigation. Re-exported here so
|
|
35
|
+
// existing `import { ModalBoundary, useModal } from "@roku-sdk/components"` keeps working.
|
|
36
|
+
export { ModalBoundary, type IModalBoundaryProps, useModal, type UseModalResult } from "@roku-sdk/navigation";
|
|
37
|
+
export * from "./sg-nodes/node";
|
|
38
|
+
export * from "./sg-nodes/overhang";
|
|
39
|
+
export * from "./sg-nodes/panel";
|
|
40
|
+
export * from "./sg-nodes/panel-set";
|
|
41
|
+
export * from "./sg-nodes/poster";
|
|
42
|
+
export * from "./sg-nodes/poster-grid";
|
|
43
|
+
export * from "./sg-nodes/radio-button-list";
|
|
44
|
+
export * from "./sg-nodes/rectangle";
|
|
45
|
+
export * from "./sg-nodes/row-list";
|
|
46
|
+
export * from "./sg-nodes/time-grid";
|
|
47
|
+
export * from "./sg-nodes/zoom-row-list";
|
|
48
|
+
export * from "./sg-nodes/scene";
|
|
49
|
+
export * from "./sg-nodes/scrolling-label";
|
|
50
|
+
export * from "./sg-nodes/scrollable-text";
|
|
51
|
+
export * from "./sg-nodes/simple-label";
|
|
52
|
+
export * from "./sg-nodes/standard-dialog";
|
|
53
|
+
export * from "./sg-nodes/standard-message-dialog";
|
|
54
|
+
export * from "./sg-nodes/standard-keyboard-dialog";
|
|
55
|
+
export * from "./sg-nodes/standard-pinpad-dialog";
|
|
56
|
+
export * from "./sg-nodes/standard-progress-dialog";
|
|
57
|
+
export * from "./sg-nodes/target-set";
|
|
58
|
+
export * from "./sg-nodes/target-group";
|
|
59
|
+
export * from "./sg-nodes/target-list";
|
|
60
|
+
export * from "./types";
|
|
61
|
+
export * from "./sg-nodes/video";
|
|
62
|
+
export * from "./sg-nodes/voice-text-edit-box";
|
|
63
|
+
export * from "./sg-nodes/audio";
|
|
64
|
+
export * from "./sg-nodes/sound-effect";
|
|
65
|
+
export * from "./button-row";
|
|
66
|
+
export * from "./sg-nodes/markup-grid";
|
|
67
|
+
|
|
68
|
+
export { Tween } from "./tween";
|
|
69
|
+
export type { TweenProps } from "./tween";
|
|
70
|
+
export type { ITweenProps } from "./sg-nodes/tween.props";
|
package/src/jsx-props.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
// Types-only barrel for JSX intrinsic augmentations. Imported by jsx.d.ts / sg-jsx.d.ts.
|
|
5
|
+
// Do not re-export from .tsx modules — that reintroduces consumer tsc circular errors.
|
|
6
|
+
|
|
7
|
+
export type { IBlendedBusySpinnerProps } from "./blended-busy-spinner.props";
|
|
8
|
+
export type { IBoundingTrackerProps } from "./bounding-tracker.props";
|
|
9
|
+
export type { IChannelStoreProps } from "./channel-store.props";
|
|
10
|
+
export type { IFocusableGroupProps } from "./focusable-group.props";
|
|
11
|
+
export type { IFocusableProps } from "./focusable.props";
|
|
12
|
+
export type { IKeyHandlerProps } from "./key-handler.props";
|
|
13
|
+
export type { IModalProps } from "./modal-dialog.props";
|
|
14
|
+
export type {
|
|
15
|
+
IAnimationBaseProps,
|
|
16
|
+
IAnimationProps,
|
|
17
|
+
IColorFieldInterpolatorProps,
|
|
18
|
+
IFloatFieldInterpolatorProps,
|
|
19
|
+
IVector2DFieldInterpolatorProps
|
|
20
|
+
} from "./sg-nodes/animation.props";
|
|
21
|
+
export type { IAnimatedImageProps } from "./sg-nodes/animated-image.props";
|
|
22
|
+
export type { IAudioProps } from "./sg-nodes/audio.props";
|
|
23
|
+
export type { IBusySpinnerProps } from "./sg-nodes/busy-spinner.props";
|
|
24
|
+
export type { IButtonGroupProps } from "./sg-nodes/button-group.props";
|
|
25
|
+
export type { IButtonProps } from "./sg-nodes/button.props";
|
|
26
|
+
export type { ICheckListProps } from "./sg-nodes/check-list.props";
|
|
27
|
+
export type { IContentNodeProps } from "./sg-nodes/content-node.props";
|
|
28
|
+
export type { IKeyboardPropsWithVoice } from "./sg-nodes/custom-keyboard.props";
|
|
29
|
+
export type { IDialogProps } from "./sg-nodes/dialog.props";
|
|
30
|
+
export type { IDynamicKeyGridProps } from "./sg-nodes/dynamic-key-grid.props";
|
|
31
|
+
export type { IDynamicKeyboardProps } from "./sg-nodes/dynamic-keyboard.props";
|
|
32
|
+
export type { IDynamicMiniKeyboardProps } from "./sg-nodes/dynamic-mini-keyboard.props";
|
|
33
|
+
export type { IDynamicPinPadProps } from "./sg-nodes/dynamic-pinpad.props";
|
|
34
|
+
export type { IEffectProps } from "./sg-nodes/effect.props";
|
|
35
|
+
export type { IFontProps } from "./sg-nodes/font.props";
|
|
36
|
+
export type { IGroupProps } from "./sg-nodes/group.props";
|
|
37
|
+
export type { ILabelListProps } from "./sg-nodes/label-list.props";
|
|
38
|
+
export type { ILabelProps, IMultiStyleLabelProps } from "./sg-nodes/label.props";
|
|
39
|
+
export type { ILayoutGroupProps } from "./sg-nodes/layout-group.props";
|
|
40
|
+
export type { IFullPanelProps, IListPanelProps } from "./sg-nodes/list-panel.props";
|
|
41
|
+
export type { IMarkupGridProps } from "./sg-nodes/markup-grid.props";
|
|
42
|
+
export type { IMarkupListProps } from "./sg-nodes/markup-list.props";
|
|
43
|
+
export type { IMaskGroupProps } from "./sg-nodes/mask-group.props";
|
|
44
|
+
export type { IOverhangProps } from "./sg-nodes/overhang.props";
|
|
45
|
+
export type { IPanelSetProps } from "./sg-nodes/panel-set.props";
|
|
46
|
+
export type { IPanelProps } from "./sg-nodes/panel.props";
|
|
47
|
+
export type { IPosterGridProps } from "./sg-nodes/poster-grid.props";
|
|
48
|
+
export type { IPosterProps } from "./sg-nodes/poster.props";
|
|
49
|
+
export type { IRadioButtonListProps } from "./sg-nodes/radio-button-list.props";
|
|
50
|
+
export type { IRectangleProps } from "./sg-nodes/rectangle.props";
|
|
51
|
+
export type { IRowListProps } from "./sg-nodes/row-list.props";
|
|
52
|
+
export type { ISceneProps } from "./sg-nodes/scene.props";
|
|
53
|
+
export type { IScrollableTextProps } from "./sg-nodes/scrollable-text.props";
|
|
54
|
+
export type { IScrollingLabelProps } from "./sg-nodes/scrolling-label.props";
|
|
55
|
+
export type { ISimpleLabelProps } from "./sg-nodes/simple-label.props";
|
|
56
|
+
export type { ISoundEffectProps } from "./sg-nodes/sound-effect.props";
|
|
57
|
+
export type {
|
|
58
|
+
IStandardDialogProps,
|
|
59
|
+
IStandardDialogRSGPaletteNodeProps,
|
|
60
|
+
IStdDlgActionCardItemProps,
|
|
61
|
+
IStdDlgBulletTextItemProps,
|
|
62
|
+
IStdDlgButtonAreaProps,
|
|
63
|
+
IStdDlgButtonProps,
|
|
64
|
+
IStdDlgContentAreaProps,
|
|
65
|
+
IStdDlgCustomItemProps,
|
|
66
|
+
IStdDlgDeterminateProgressItemProps,
|
|
67
|
+
IStdDlgGraphicItemProps,
|
|
68
|
+
IStdDlgItemGroupProps,
|
|
69
|
+
IStdDlgKeyboardItemProps,
|
|
70
|
+
IStdDlgMultiStyleTextItemProps,
|
|
71
|
+
IStdDlgProgressItemProps,
|
|
72
|
+
IStdDlgSideCardAreaProps,
|
|
73
|
+
IStdDlgTextItemProps,
|
|
74
|
+
IStdDlgTitleAreaProps
|
|
75
|
+
} from "./sg-nodes/standard-dialog.props";
|
|
76
|
+
export type { IStandardKeyboardDialogProps } from "./sg-nodes/standard-keyboard-dialog.props";
|
|
77
|
+
export type { IStandardMessageDialogProps } from "./sg-nodes/standard-message-dialog.props";
|
|
78
|
+
export type { IStandardPinPadDialogProps } from "./sg-nodes/standard-pinpad-dialog.props";
|
|
79
|
+
export type { IStandardProgressDialogProps } from "./sg-nodes/standard-progress-dialog.props";
|
|
80
|
+
export type { ITargetGroupProps } from "./sg-nodes/target-group.props";
|
|
81
|
+
export type { ITargetListProps } from "./sg-nodes/target-list.props";
|
|
82
|
+
export type { ITargetSetProps } from "./sg-nodes/target-set.props";
|
|
83
|
+
export type { ITimeGridProps } from "./sg-nodes/time-grid.props";
|
|
84
|
+
export type { ITweenProps } from "./sg-nodes/tween.props";
|
|
85
|
+
export type { IBifDisplayProps, IProgressBarProps, ITrickPlayBarProps, IVideoProps } from "./sg-nodes/video.props";
|
|
86
|
+
export type { IVoiceTextEditBoxProps } from "./sg-nodes/voice-text-edit-box.props";
|
|
87
|
+
export type { IZoomRowListProps } from "./sg-nodes/zoom-row-list.props";
|
package/src/kdfs.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Packaged Key Definition File URI exports (resolved to pkg:/components/... at build time).
|
|
6
|
+
*
|
|
7
|
+
* Keep this in sync with `kdfs.ts`: every export added there must be declared here.
|
|
8
|
+
*/
|
|
9
|
+
declare module "@roku-sdk/components/kdfs" {
|
|
10
|
+
export const CustomAddressKDF: string;
|
|
11
|
+
export const MOPPinPadCustomKDF: string;
|
|
12
|
+
export const PhonePadCustomKDF: string;
|
|
13
|
+
export const WifiCustomKDF: string;
|
|
14
|
+
}
|
package/src/kdfs.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Packaged Key Definition File URIs for standard keyboard layouts.
|
|
6
|
+
*
|
|
7
|
+
* Import only the layouts you use so unused KDF files tree-shake out of the build.
|
|
8
|
+
*
|
|
9
|
+
* When adding a new KDF export here, add a matching declaration to `kdfs.d.ts`
|
|
10
|
+
* (the published type surface for `@roku-sdk/components/kdfs`); the two must stay in sync.
|
|
11
|
+
*/
|
|
12
|
+
export { default as CustomAddressKDF } from "./xml-components/keyboards/CustomAddressKDF.keyboard.json";
|
|
13
|
+
export { default as MOPPinPadCustomKDF } from "./xml-components/keyboards/MOPPinPadCustomKDF.keyboard.json";
|
|
14
|
+
export { default as PhonePadCustomKDF } from "./xml-components/keyboards/PhonePadCustomKDF.keyboard.json";
|
|
15
|
+
export { default as WifiCustomKDF } from "./xml-components/keyboards/WifiCustomKDF.keyboard.json";
|