@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,64 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IStandardDialogProps } from "./standard-dialog.props";
|
|
5
|
+
import type { EventHandler } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Properties for the {@link StandardPinPadDialog} component.
|
|
9
|
+
*
|
|
10
|
+
* Extends {@link IStandardDialogProps} with PIN pad-specific fields for numeric entry.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-pinpad-dialog}
|
|
13
|
+
*/
|
|
14
|
+
export interface IStandardPinPadDialogProps extends IStandardDialogProps {
|
|
15
|
+
/**
|
|
16
|
+
* The title displayed at the top of the dialog.
|
|
17
|
+
* @default ""
|
|
18
|
+
*/
|
|
19
|
+
title?: string;
|
|
20
|
+
/**
|
|
21
|
+
* One or more blocks of text describing the data to be entered.
|
|
22
|
+
* Each string in the array is displayed as a separate block of text.
|
|
23
|
+
* Minimize message length to avoid automatic scrollbar.
|
|
24
|
+
* @default []
|
|
25
|
+
*/
|
|
26
|
+
message?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* List of button labels to display in the button area at the bottom of the dialog.
|
|
29
|
+
* Minimize the number of buttons to ensure visibility without scrolling.
|
|
30
|
+
* @default []
|
|
31
|
+
*/
|
|
32
|
+
buttons?: string[];
|
|
33
|
+
/**
|
|
34
|
+
* The entered PIN value displayed in the text edit box.
|
|
35
|
+
* Updated with the currently entered value as the user enters each digit.
|
|
36
|
+
* @default ""
|
|
37
|
+
*/
|
|
38
|
+
pin?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Fired whenever the PIN in the text edit box changes (on each digit entry).
|
|
41
|
+
* The handler receives the full current PIN string entered by the user.
|
|
42
|
+
*
|
|
43
|
+
* Use this to react to live input — for example to validate the PIN length
|
|
44
|
+
* or enable/disable action buttons based on what the user has entered so far.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* const [pin, setPin] = createSignal("");
|
|
49
|
+
*
|
|
50
|
+
* <StandardPinPadDialog
|
|
51
|
+
* title="Enter PIN"
|
|
52
|
+
* pin={pin()}
|
|
53
|
+
* onPin={(value) => {
|
|
54
|
+
* // Called on every digit entry with the full current PIN
|
|
55
|
+
* setPin(value);
|
|
56
|
+
* console.log("User is entering PIN:", value);
|
|
57
|
+
* }}
|
|
58
|
+
* buttons={["Submit", "Cancel"]}
|
|
59
|
+
* onButtonSelected={(index) => console.log("Button:", index)}
|
|
60
|
+
* />
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
onPin?: EventHandler<string>;
|
|
64
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { Modal, modalPropKeys } from "../modal-dialog";
|
|
5
|
+
import { retainAsset } from "../retain-asset";
|
|
6
|
+
import StandardPinPadDialogExtXML from "../xml-components/modal/StandardPinPadDialogExt.xml";
|
|
7
|
+
import type { IStandardPinPadDialogProps } from "./standard-pinpad-dialog.props";
|
|
8
|
+
import { Component, splitProps } from "./types";
|
|
9
|
+
export type { IStandardPinPadDialogProps } from "./standard-pinpad-dialog.props";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Displays a PIN pad dialog for text and voice entry of numeric PIN codes.
|
|
13
|
+
*
|
|
14
|
+
* `StandardPinPadDialog` is a pre-built dialog similar to the legacy PinDialog node,
|
|
15
|
+
* but includes voice entry of numeric digits through its internal DynamicPinPad and
|
|
16
|
+
* VoiceTextEditBox nodes.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const [showPinPad, setShowPinPad] = createSignal(false);
|
|
21
|
+
* const [pin, setPin] = createSignal("");
|
|
22
|
+
*
|
|
23
|
+
* {showPinPad() && (
|
|
24
|
+
* <StandardPinPadDialog
|
|
25
|
+
* title="Enter PIN"
|
|
26
|
+
* message={["Please enter your 4-digit PIN:"]}
|
|
27
|
+
* pin={pin()}
|
|
28
|
+
* buttons={["Submit", "Cancel"]}
|
|
29
|
+
* onButtonSelected={(index) => {
|
|
30
|
+
* if (index === 0) {
|
|
31
|
+
* console.log("PIN entered:", pin());
|
|
32
|
+
* }
|
|
33
|
+
* setShowPinPad(false);
|
|
34
|
+
* }}
|
|
35
|
+
* onWasClosed={() => setShowPinPad(false)}
|
|
36
|
+
* />
|
|
37
|
+
* )}
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-pinpad-dialog}
|
|
41
|
+
*/
|
|
42
|
+
export const StandardPinPadDialog: Component<IStandardPinPadDialogProps> = props => {
|
|
43
|
+
retainAsset(StandardPinPadDialogExtXML);
|
|
44
|
+
const [local, rest] = splitProps(props, modalPropKeys);
|
|
45
|
+
return <Modal {...local} dialog={<standardPinPadDialogExt {...rest} />} />;
|
|
46
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IStandardDialogProps } from "./standard-dialog.props";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Properties for the {@link StandardProgressDialog} component.
|
|
8
|
+
*
|
|
9
|
+
* Extends {@link IStandardDialogProps} (omitting button events since progress dialogs have no buttons)
|
|
10
|
+
* with fields for displaying a spinning progress indicator.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-progress-dialog}
|
|
13
|
+
*/
|
|
14
|
+
export interface IStandardProgressDialogProps extends Omit<
|
|
15
|
+
IStandardDialogProps,
|
|
16
|
+
"onButtonSelected" | "onButtonFocused"
|
|
17
|
+
> {
|
|
18
|
+
/**
|
|
19
|
+
* The title displayed at the top of the dialog.
|
|
20
|
+
* If empty, the dialog displays without a title area and uses minimum width.
|
|
21
|
+
* @default ""
|
|
22
|
+
*/
|
|
23
|
+
title?: string;
|
|
24
|
+
/**
|
|
25
|
+
* A string displayed next to the spinning progress indicator.
|
|
26
|
+
* Typically tells the user why they are waiting. Minimize message length.
|
|
27
|
+
* @default ""
|
|
28
|
+
*/
|
|
29
|
+
message?: string;
|
|
30
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { Modal, modalPropKeys } from "../modal-dialog";
|
|
5
|
+
import { retainAsset } from "../retain-asset";
|
|
6
|
+
import StandardProgressDialogExtXML from "../xml-components/modal/StandardProgressDialogExt.xml";
|
|
7
|
+
import type { IStandardProgressDialogProps } from "./standard-progress-dialog.props";
|
|
8
|
+
import { Component, splitProps } from "./types";
|
|
9
|
+
export type { IStandardProgressDialogProps } from "./standard-progress-dialog.props";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Displays a progress dialog with a spinning indicator and message.
|
|
13
|
+
*
|
|
14
|
+
* `StandardProgressDialog` is a pre-built dialog similar to the legacy ProgressDialog node.
|
|
15
|
+
* It displays a spinning progress indicator for tasks with an indeterminate duration.
|
|
16
|
+
*
|
|
17
|
+
* Note: Unlike other standard dialogs, `StandardProgressDialog` has no buttons — it only
|
|
18
|
+
* displays a spinner with a message. Close the dialog programmatically by setting
|
|
19
|
+
* {@link IStandardProgressDialogProps.close | close} to `true` or by unmounting the component.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* const [isLoading, setIsLoading] = createSignal(true);
|
|
24
|
+
*
|
|
25
|
+
* // Show progress dialog while loading
|
|
26
|
+
* {isLoading() && (
|
|
27
|
+
* <StandardProgressDialog
|
|
28
|
+
* title="Loading"
|
|
29
|
+
* message="Please wait..."
|
|
30
|
+
* />
|
|
31
|
+
* )}
|
|
32
|
+
*
|
|
33
|
+
* // When loading completes, hide the dialog
|
|
34
|
+
* setTimeout(() => setIsLoading(false), 3000);
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-progress-dialog}
|
|
38
|
+
*/
|
|
39
|
+
export const StandardProgressDialog: Component<IStandardProgressDialogProps> = props => {
|
|
40
|
+
retainAsset(StandardProgressDialogExtXML);
|
|
41
|
+
const [local, rest] = splitProps(props, modalPropKeys);
|
|
42
|
+
return <Modal {...local} dialog={<standardProgressDialogExt {...rest} />} />;
|
|
43
|
+
};
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IGroupProps } from "./group.props";
|
|
5
|
+
import type { EventHandler, JSX } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Properties for the TargetGroup node.
|
|
9
|
+
*
|
|
10
|
+
* TargetGroup associates a set of rectangular target regions (defined by a
|
|
11
|
+
* {@link ITargetSetProps | TargetSet}) with child items rendered by a compiled
|
|
12
|
+
* XML component. It is typically used to create scrolling lists where the
|
|
13
|
+
* focused item occupies more space than unfocused items, with smooth
|
|
14
|
+
* animations between states.
|
|
15
|
+
*
|
|
16
|
+
* **How it works:**
|
|
17
|
+
* 1. Define target rectangles via a TargetSet — one rectangle per visible
|
|
18
|
+
* slot, including off-screen slots for smooth entry/exit.
|
|
19
|
+
* 2. Specify an XML component via `itemComponentName` to render each item.
|
|
20
|
+
* The TargetGroup creates instances on demand and updates their fields
|
|
21
|
+
* (`currTarget`, `currRect`, `index`, `groupHasFocus`, `itemContent`,
|
|
22
|
+
* `focusPercent`, `itemHasFocus`) as items animate.
|
|
23
|
+
* 3. Navigate by setting `animateToItem` or `jumpToItem` to move the
|
|
24
|
+
* content so that the specified index occupies the focus region.
|
|
25
|
+
* 4. Animate between layouts by setting `animateToTargetSet` to smoothly
|
|
26
|
+
* transition all items from one set of target rectangles to another.
|
|
27
|
+
*
|
|
28
|
+
* @extends IGroupProps
|
|
29
|
+
* @see {@link https://developer.roku.com/dev/docs/targetgroup}
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* import "./compiled-components/MyItem.xml";
|
|
34
|
+
*
|
|
35
|
+
* <TargetGroup
|
|
36
|
+
* itemComponentName="MyItem"
|
|
37
|
+
* targetSet={
|
|
38
|
+
* <TargetSet
|
|
39
|
+
* targetRects={[
|
|
40
|
+
* [0, -200, 1920, 200],
|
|
41
|
+
* [0, 20, 1920, 200],
|
|
42
|
+
* [0, 240, 1920, 400],
|
|
43
|
+
* [0, 660, 1920, 200],
|
|
44
|
+
* [0, 880, 1920, 200],
|
|
45
|
+
* ]}
|
|
46
|
+
* focusIndex={2}
|
|
47
|
+
* />
|
|
48
|
+
* }
|
|
49
|
+
* content={contentNode}
|
|
50
|
+
* onItemFocused={(index) => console.log("Focused:", index)}
|
|
51
|
+
* onItemSelected={(index) => console.log("Selected:", index)}
|
|
52
|
+
* />
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export interface ITargetGroupProps extends IGroupProps {
|
|
56
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
57
|
+
// Item Rendering
|
|
58
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Specifies the name of the XML component used to render each group item.
|
|
62
|
+
* An instance is created on demand for each visible target region.
|
|
63
|
+
*
|
|
64
|
+
* Register the compiled component by importing its XML file before use:
|
|
65
|
+
* ```ts
|
|
66
|
+
* import "./compiled-components/MyItem.xml";
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* The XML component may define interface fields that TargetGroup will
|
|
70
|
+
* automatically update: `currTarget`, `currRect`, `index`,
|
|
71
|
+
* `groupHasFocus`, `itemContent`, `focusPercent`, and `itemHasFocus`.
|
|
72
|
+
*
|
|
73
|
+
* @example "MyItem"
|
|
74
|
+
* @see {@link https://developer.roku.com/dev/docs/targetgroup#targetgroup-xml-component | TargetGroup XML Component}
|
|
75
|
+
*/
|
|
76
|
+
itemComponentName?: string;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Specifies the content for the group.
|
|
80
|
+
*
|
|
81
|
+
* Should be a single root `ContentNode` with one child `ContentNode` per
|
|
82
|
+
* item. Each child node should contain the data required by the XML
|
|
83
|
+
* component specified in `itemComponentName`.
|
|
84
|
+
*
|
|
85
|
+
* **Important:** Place `content` before `jumpToItem` and `animateToItem` in the
|
|
86
|
+
* component. When content is updated dynamically, update `jumpToItem`/`animateToItem`
|
|
87
|
+
* in the same transaction or after content has been updated.
|
|
88
|
+
*
|
|
89
|
+
* @see {@link https://developer.roku.com/dev/docs/targetgroup#data-bindings | Data Bindings}
|
|
90
|
+
*/
|
|
91
|
+
content?: JSX.Element;
|
|
92
|
+
|
|
93
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
94
|
+
// Target Configuration
|
|
95
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Specifies the TargetSet to use to define the target regions of the
|
|
99
|
+
* items in the group. When set or modified, the target regions are
|
|
100
|
+
* immediately adjusted to use the new values.
|
|
101
|
+
*
|
|
102
|
+
* @see {@link https://developer.roku.com/dev/docs/targetgroup | TargetGroup targetSet}
|
|
103
|
+
*/
|
|
104
|
+
targetSet?: JSX.Element;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* For TargetSets that do not specify a `focusIndex`, this value will
|
|
108
|
+
* be used as the index of the target rectangle where the focused item
|
|
109
|
+
* is located. If a TargetSet specifies any value for `focusIndex`,
|
|
110
|
+
* that value will be used instead.
|
|
111
|
+
*
|
|
112
|
+
* @default 0
|
|
113
|
+
*/
|
|
114
|
+
defaultTargetSetFocusIndex?: number;
|
|
115
|
+
|
|
116
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
117
|
+
// Scrolling Behaviour
|
|
118
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Specifies whether the content items wrap around at the end of the
|
|
122
|
+
* TargetGroup to fill all of the target rectangles.
|
|
123
|
+
*
|
|
124
|
+
* @default false
|
|
125
|
+
*/
|
|
126
|
+
wrap?: boolean;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Forces the item index to be interpolated in a forward direction when
|
|
130
|
+
* animating between items. Only has an effect when `wrap` is `true`.
|
|
131
|
+
*
|
|
132
|
+
* For example, when the number of items is 10 and animating from item 9
|
|
133
|
+
* to item 0, enabling this causes the sequence `9 → 0` instead of
|
|
134
|
+
* `9 → 8 → 7 → … → 0`.
|
|
135
|
+
*
|
|
136
|
+
* @default false
|
|
137
|
+
*/
|
|
138
|
+
advancing?: boolean;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Forces the item index to be interpolated in a reverse direction when
|
|
142
|
+
* animating between items. Only has an effect when `wrap` is `true`.
|
|
143
|
+
*
|
|
144
|
+
* For example, when the number of items is 10 and animating from item 0
|
|
145
|
+
* to item 9, enabling this causes the sequence `0 → 9` instead of
|
|
146
|
+
* `0 → 1 → … → 9`.
|
|
147
|
+
*
|
|
148
|
+
* @default false
|
|
149
|
+
*/
|
|
150
|
+
reversing?: boolean;
|
|
151
|
+
|
|
152
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
153
|
+
// Animation
|
|
154
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Specifies the time, in seconds, to perform the animation when the
|
|
158
|
+
* `animateToItem` or `animateToTargetSet` fields are set.
|
|
159
|
+
*
|
|
160
|
+
* @default 0.3
|
|
161
|
+
*/
|
|
162
|
+
duration?: number;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Specifies the interpolator function used in TargetGroup animations
|
|
166
|
+
* between items.
|
|
167
|
+
*
|
|
168
|
+
* @default "inOutCubic"
|
|
169
|
+
*/
|
|
170
|
+
easeFunction?: string;
|
|
171
|
+
|
|
172
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
173
|
+
// Debug
|
|
174
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* When `true`, the current target rectangles (as defined in the
|
|
178
|
+
* `currTargetSet`) are drawn using the color specified in the
|
|
179
|
+
* TargetSet's `color` field. Typically only set to `true` for
|
|
180
|
+
* debugging purposes.
|
|
181
|
+
*
|
|
182
|
+
* @default false
|
|
183
|
+
*/
|
|
184
|
+
showTargetRects?: boolean;
|
|
185
|
+
|
|
186
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
187
|
+
// Navigation (Write-Only)
|
|
188
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* When set to a valid item index, causes the group to immediately
|
|
192
|
+
* update so that the specified index moves to the target region
|
|
193
|
+
* specified by the TargetSet's `focusIndex`.
|
|
194
|
+
*
|
|
195
|
+
* **Important:** Set this property after `content` in the component order. When
|
|
196
|
+
* content is updated dynamically, update `jumpToItem` in the same transaction
|
|
197
|
+
* or after content has been updated.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```tsx
|
|
201
|
+
* <TargetGroup
|
|
202
|
+
* content={contentNode}
|
|
203
|
+
* jumpToItem={jumpToItem}
|
|
204
|
+
* ...
|
|
205
|
+
* />
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* @writeonly
|
|
209
|
+
* @default 0
|
|
210
|
+
*/
|
|
211
|
+
jumpToItem?: number;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* When set to a valid item index, causes the group to smoothly
|
|
215
|
+
* animate so that the specified index moves to the target region
|
|
216
|
+
* specified by the TargetSet's `focusIndex`.
|
|
217
|
+
*
|
|
218
|
+
* **Important:** Set this property after `content` in the component order. When
|
|
219
|
+
* content is updated dynamically, update `animateToItem` in the same transaction
|
|
220
|
+
* or after content has been updated.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```tsx
|
|
224
|
+
* <TargetGroup
|
|
225
|
+
* content={contentNode}
|
|
226
|
+
* animateToItem={animateToItem}
|
|
227
|
+
* ...
|
|
228
|
+
* />
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @writeonly
|
|
232
|
+
* @default 0
|
|
233
|
+
*/
|
|
234
|
+
animateToItem?: number;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* When set to a valid TargetSet, causes the group to smoothly
|
|
238
|
+
* animate all items from the current target regions to the
|
|
239
|
+
* corresponding regions of the new TargetSet. If the two
|
|
240
|
+
* TargetSets have different `focusIndex` values, the focus
|
|
241
|
+
* index is also animated.
|
|
242
|
+
*
|
|
243
|
+
* @writeonly
|
|
244
|
+
*/
|
|
245
|
+
animateToTargetSet?: JSX.Element;
|
|
246
|
+
|
|
247
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
248
|
+
// Events (Read-Only)
|
|
249
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Fired when the current focus item index changes during animation.
|
|
253
|
+
* The value is a `float` — integer when the item occupies the focus
|
|
254
|
+
* target, fractional during animation (e.g., `5.7` means item 6
|
|
255
|
+
* occupies 70% and item 5 occupies 30%).
|
|
256
|
+
*
|
|
257
|
+
* @readonly
|
|
258
|
+
*/
|
|
259
|
+
onCurrFocusItemIndexChange?: EventHandler<number>;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Fired when the current target set changes during an
|
|
263
|
+
* `animateToTargetSet` animation. Contains the interpolated
|
|
264
|
+
* TargetSet as the animation proceeds.
|
|
265
|
+
*
|
|
266
|
+
* @readonly
|
|
267
|
+
*/
|
|
268
|
+
onCurrTargetSetChange?: EventHandler<JSX.Element>;
|
|
269
|
+
|
|
270
|
+
/** Fired when a group item is selected (e.g., OK button press). */
|
|
271
|
+
onItemSelected?: EventHandler<number>;
|
|
272
|
+
|
|
273
|
+
/** Fired when a group item gains the key focus. */
|
|
274
|
+
onItemFocused?: EventHandler<number>;
|
|
275
|
+
|
|
276
|
+
/** Fired when a group item loses the key focus. */
|
|
277
|
+
onItemUnfocused?: EventHandler<number>;
|
|
278
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { ITargetGroupProps } from "./target-group.props";
|
|
5
|
+
import { Component } from "./types";
|
|
6
|
+
export type { ITargetGroupProps } from "./target-group.props";
|
|
7
|
+
|
|
8
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
// TargetGroup Properties
|
|
10
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* TargetGroup creates scrolling lists (or rows) of items where each item's
|
|
14
|
+
* size and position is defined by rectangular target regions in a
|
|
15
|
+
* {@link TargetSet}. The focused item typically occupies a larger region
|
|
16
|
+
* than unfocused items, with smooth animations between states.
|
|
17
|
+
*
|
|
18
|
+
* **Common use cases:**
|
|
19
|
+
* - A full-screen vertical list where the focused item is larger
|
|
20
|
+
* - A list that collapses when unfocused and expands when focused,
|
|
21
|
+
* using two TargetSets animated via `animateToTargetSet`
|
|
22
|
+
* - A horizontal row with a floating focus region
|
|
23
|
+
* - A circular arrangement with fixed positions
|
|
24
|
+
*
|
|
25
|
+
* @see {@link https://developer.roku.com/dev/docs/targetgroup}
|
|
26
|
+
* @see {@link https://github.com/rokudev/samples/blob/master/ux%20components/screen%20elements/target_group/FloatingFocusWrap | FloatingFocusWrap Sample}
|
|
27
|
+
* @see {@link https://github.com/rokudev/samples/blob/master/ux%20components/screen%20elements/target_group/TwoRowFixedFocus | TwoRowFixedFocus Sample}
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* import "./compiled-components/MyItem.xml";
|
|
32
|
+
*
|
|
33
|
+
* <targetGroup
|
|
34
|
+
* itemComponentName="MyItem"
|
|
35
|
+
* targetSet={
|
|
36
|
+
* <targetSet
|
|
37
|
+
* targetRects={[
|
|
38
|
+
* [0, -200, 1920, 200],
|
|
39
|
+
* [0, 20, 1920, 200],
|
|
40
|
+
* [0, 240, 1920, 400],
|
|
41
|
+
* [0, 660, 1920, 200],
|
|
42
|
+
* [0, 880, 1920, 200],
|
|
43
|
+
* ]}
|
|
44
|
+
* focusIndex={2}
|
|
45
|
+
* />
|
|
46
|
+
* }
|
|
47
|
+
* content={
|
|
48
|
+
* <contentNode>
|
|
49
|
+
* <contentNode title="Item 1" description="First item" />
|
|
50
|
+
* <contentNode title="Item 2" description="Second item" />
|
|
51
|
+
* <contentNode title="Item 3" description="Third item" />
|
|
52
|
+
* </contentNode>
|
|
53
|
+
* }
|
|
54
|
+
* duration={0.4}
|
|
55
|
+
* wrap={true}
|
|
56
|
+
* onItemFocused={(index) => console.log("Focused:", index)}
|
|
57
|
+
* onItemSelected={(index) => console.log("Selected:", index)}
|
|
58
|
+
* />
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export const TargetGroup: Component<ITargetGroupProps> = props => {
|
|
62
|
+
return <targetGroup {...props}></targetGroup>;
|
|
63
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { ITargetGroupProps } from "./target-group.props";
|
|
5
|
+
import type { JSX } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Properties for the TargetList node.
|
|
9
|
+
*
|
|
10
|
+
* TargetList extends {@link ITargetGroupProps | TargetGroup} with built-in
|
|
11
|
+
* focused/unfocused transitions, focus management policies (fixed focus,
|
|
12
|
+
* floating focus), and default key handling for navigating the list or row.
|
|
13
|
+
*
|
|
14
|
+
* **Fixed focus:** Set `focusedTargetSet` to a single-element array containing
|
|
15
|
+
* one TargetSet. The focus stays fixed on the target rectangle at the
|
|
16
|
+
* TargetSet's `focusIndex`. Optionally set `unfocusedTargetSet` for a smooth
|
|
17
|
+
* transition when the list gains or loses focus.
|
|
18
|
+
*
|
|
19
|
+
* **Floating focus:** Set `focusedTargetSet` to an array of TargetSets — one
|
|
20
|
+
* per focus position — with incrementing `focusIndex` values. As the user
|
|
21
|
+
* navigates, the list advances through the array until the last element is
|
|
22
|
+
* reached, at which point items begin to scroll.
|
|
23
|
+
*
|
|
24
|
+
* @extends ITargetGroupProps
|
|
25
|
+
* @see {@link https://developer.roku.com/dev/docs/targetlist}
|
|
26
|
+
*
|
|
27
|
+
* @example Fixed focus
|
|
28
|
+
* ```tsx
|
|
29
|
+
* import { TargetList, TargetSet } from "@roku-sdk/components";
|
|
30
|
+
* import "./compiled-components/MyItem.xml";
|
|
31
|
+
*
|
|
32
|
+
* <TargetList
|
|
33
|
+
* itemComponentName="MyItem"
|
|
34
|
+
* focusedTargetSet={[
|
|
35
|
+
* <TargetSet
|
|
36
|
+
* targetRects={[
|
|
37
|
+
* [-178, -64, 240, 134],
|
|
38
|
+
* [72, -96, 360, 202],
|
|
39
|
+
* [442, -64, 240, 134],
|
|
40
|
+
* [692, -64, 240, 134],
|
|
41
|
+
* ]}
|
|
42
|
+
* focusIndex={1}
|
|
43
|
+
* />,
|
|
44
|
+
* ]}
|
|
45
|
+
* unfocusedTargetSet={
|
|
46
|
+
* <TargetSet
|
|
47
|
+
* targetRects={[
|
|
48
|
+
* [-100, -64, 240, 134],
|
|
49
|
+
* [150, -64, 240, 134],
|
|
50
|
+
* [400, -64, 240, 134],
|
|
51
|
+
* [650, -64, 240, 134],
|
|
52
|
+
* ]}
|
|
53
|
+
* />
|
|
54
|
+
* }
|
|
55
|
+
* content={contentNode}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example Floating focus
|
|
60
|
+
* ```tsx
|
|
61
|
+
* <TargetList
|
|
62
|
+
* itemComponentName="MyItem"
|
|
63
|
+
* advanceKey="right"
|
|
64
|
+
* reverseKey="left"
|
|
65
|
+
* focusedTargetSet={[
|
|
66
|
+
* <TargetSet targetRects={rectsForFocus0} focusIndex={0} />,
|
|
67
|
+
* <TargetSet targetRects={rectsForFocus1} focusIndex={1} />,
|
|
68
|
+
* <TargetSet targetRects={rectsForFocus2} focusIndex={2} />,
|
|
69
|
+
* ]}
|
|
70
|
+
* content={contentNode}
|
|
71
|
+
* />
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export interface ITargetListProps extends ITargetGroupProps {
|
|
75
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
76
|
+
// Focus Configuration
|
|
77
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Specifies one or more TargetSets to be used when the TargetList has
|
|
81
|
+
* the focus.
|
|
82
|
+
*
|
|
83
|
+
* - **Fixed focus**: provide a single-element array. Focus stays fixed on
|
|
84
|
+
* the target rectangle corresponding to the TargetSet's `focusIndex`
|
|
85
|
+
* (or the TargetGroup's `defaultTargetSetFocusIndex` if the TargetSet
|
|
86
|
+
* does not specify one).
|
|
87
|
+
* - **Floating focus**: provide multiple TargetSets with incrementing
|
|
88
|
+
* `focusIndex` values. As the user presses `advanceKey`, focus floats
|
|
89
|
+
* from one TargetSet to the next until the last element is reached, at
|
|
90
|
+
* which point items begin to scroll. Reversing works symmetrically.
|
|
91
|
+
*
|
|
92
|
+
* @default []
|
|
93
|
+
* @see {@link https://developer.roku.com/dev/docs/targetlist | TargetList Fields}
|
|
94
|
+
*/
|
|
95
|
+
focusedTargetSet?: JSX.Element[];
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Specifies the TargetSet to be used when the TargetList does **not**
|
|
99
|
+
* have the focus. Setting this enables a smooth transition between the
|
|
100
|
+
* focused and unfocused layouts when the list gains or loses focus.
|
|
101
|
+
*
|
|
102
|
+
* @default invalid
|
|
103
|
+
* @see {@link https://developer.roku.com/dev/docs/targetlist | TargetList Fields}
|
|
104
|
+
*/
|
|
105
|
+
unfocusedTargetSet?: JSX.Element;
|
|
106
|
+
|
|
107
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
108
|
+
// Key Handling
|
|
109
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Specifies which remote button will move the focus forward. For vertical
|
|
113
|
+
* lists, this is typically `"down"`; for horizontal rows, `"right"`.
|
|
114
|
+
*
|
|
115
|
+
* @default "down"
|
|
116
|
+
* @see {@link https://developer.roku.com/dev/docs/targetlist | TargetList Fields}
|
|
117
|
+
*/
|
|
118
|
+
advanceKey?: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Specifies which remote button will move the focus backward. For vertical
|
|
122
|
+
* lists, this is typically `"up"`; for horizontal rows, `"left"`.
|
|
123
|
+
*
|
|
124
|
+
* @default "up"
|
|
125
|
+
* @see {@link https://developer.roku.com/dev/docs/targetlist | TargetList Fields}
|
|
126
|
+
*/
|
|
127
|
+
reverseKey?: string;
|
|
128
|
+
}
|