@roku-sdk/components 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/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 +85 -3
- package/src/__tests__/container.test.tsx +150 -0
- package/src/__tests__/effect-gradient-validation.test.tsx +133 -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 +276 -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 +119 -0
- package/src/sg-nodes/effect.tsx +167 -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 +103 -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 +66 -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 +58 -0
- package/src/sg-nodes/standard-message-dialog.props.ts +56 -0
- package/src/sg-nodes/standard-message-dialog.tsx +47 -0
- package/src/sg-nodes/standard-pinpad-dialog.props.ts +64 -0
- package/src/sg-nodes/standard-pinpad-dialog.tsx +44 -0
- package/src/sg-nodes/standard-progress-dialog.props.ts +30 -0
- package/src/sg-nodes/standard-progress-dialog.tsx +40 -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 +642 -0
- package/src/sg-nodes/video.tsx +75 -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,428 @@
|
|
|
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 StandardDialogExtXML from "../xml-components/modal/StandardDialogExt.xml";
|
|
7
|
+
import type {
|
|
8
|
+
IStandardDialogProps,
|
|
9
|
+
IStandardDialogRSGPaletteNodeProps,
|
|
10
|
+
IStdDlgActionCardItemProps,
|
|
11
|
+
IStdDlgBulletTextItemProps,
|
|
12
|
+
IStdDlgButtonAreaProps,
|
|
13
|
+
IStdDlgButtonProps,
|
|
14
|
+
IStdDlgContentAreaProps,
|
|
15
|
+
IStdDlgCustomItemProps,
|
|
16
|
+
IStdDlgDeterminateProgressItemProps,
|
|
17
|
+
IStdDlgGraphicItemProps,
|
|
18
|
+
IStdDlgItemGroupProps,
|
|
19
|
+
IStdDlgKeyboardItemProps,
|
|
20
|
+
IStdDlgMultiStyleTextItemProps,
|
|
21
|
+
IStdDlgProgressItemProps,
|
|
22
|
+
IStdDlgSideCardAreaProps,
|
|
23
|
+
IStdDlgTextItemProps,
|
|
24
|
+
IStdDlgTitleAreaProps
|
|
25
|
+
} from "./standard-dialog.props";
|
|
26
|
+
import { Component, splitProps } from "./types";
|
|
27
|
+
export { StdDlgKeyboardLayoutType } from "./standard-dialog.props";
|
|
28
|
+
|
|
29
|
+
export type {
|
|
30
|
+
IStandardDialogRSGPaletteNodeProps,
|
|
31
|
+
IStandardDialogProps,
|
|
32
|
+
IStdDlgAreaBaseProps,
|
|
33
|
+
IStdDlgTitleAreaProps,
|
|
34
|
+
IStdDlgContentAreaProps,
|
|
35
|
+
IStdDlgButtonAreaProps,
|
|
36
|
+
IStdDlgSideCardAreaProps,
|
|
37
|
+
IStdDlgButtonProps,
|
|
38
|
+
IStdDlgItemBaseProps,
|
|
39
|
+
IStdDlgItemGroupProps,
|
|
40
|
+
IStdDlgActionIconType,
|
|
41
|
+
IStdDlgActionCardItemProps,
|
|
42
|
+
IStdDialogBulletType,
|
|
43
|
+
IStdDlgBulletTextItemProps,
|
|
44
|
+
IStdDlgDeterminateProgressItemProps,
|
|
45
|
+
IStdDlgGraphicAlign,
|
|
46
|
+
IStdDlgGraphicItemProps,
|
|
47
|
+
IStdDlgKeyboardItemProps,
|
|
48
|
+
IStdDlgDrawingStyle,
|
|
49
|
+
IStdDlgMultiStyleTextItemProps,
|
|
50
|
+
IStdDlgProgressItemProps,
|
|
51
|
+
INamedTextStyles,
|
|
52
|
+
IStdDlgTextItemProps,
|
|
53
|
+
IStdDlgCustomItemProps
|
|
54
|
+
} from "./standard-dialog.props";
|
|
55
|
+
|
|
56
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
57
|
+
// RSGPalette
|
|
58
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sets the color palette used by a {@link StandardDialog} and its child elements.
|
|
62
|
+
*
|
|
63
|
+
* The RSGPalette node defines 10 color values that control the appearance of dialog backgrounds,
|
|
64
|
+
* text, buttons, focus indicators, keyboards, and other elements. By default, dialogs inherit
|
|
65
|
+
* their palette from ancestor nodes in the scene graph (typically from the Scene node).
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <StandardDialog>
|
|
70
|
+
* <rsgPalette colors={{
|
|
71
|
+
* dialogBackgroundColor: "0x1E1E1EFF",
|
|
72
|
+
* dialogTextColor: "0xFFFFFFFF",
|
|
73
|
+
* dialogFocusColor: "0x0066FFFF",
|
|
74
|
+
* }} />
|
|
75
|
+
* <stdDlgTitleArea primaryTitle="Settings" />
|
|
76
|
+
* <stdDlgContentArea>
|
|
77
|
+
* <stdDlgTextItem text="Choose an option below." />
|
|
78
|
+
* </stdDlgContentArea>
|
|
79
|
+
* </StandardDialog>
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-dialog | StandardDialog palette field}
|
|
83
|
+
*/
|
|
84
|
+
export const RsgPalette: Component<IStandardDialogRSGPaletteNodeProps> = props => {
|
|
85
|
+
return <rsgPalette {...props}></rsgPalette>;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @deprecated Renamed to {@link RsgPalette}. Use `RsgPalette` instead — `RSGPalette` will be removed in a future release.
|
|
90
|
+
*/
|
|
91
|
+
export const RSGPalette = RsgPalette;
|
|
92
|
+
|
|
93
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
94
|
+
// StandardDialog
|
|
95
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Base dialog node for the Roku standard dialog framework.
|
|
99
|
+
*
|
|
100
|
+
* `StandardDialog` provides a structured dialog layout with optional title, content, button,
|
|
101
|
+
* and side-card areas. Use the StdDlg* area and item components as children to compose the
|
|
102
|
+
* dialog's UI.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```tsx
|
|
106
|
+
* const [showDialog, setShowDialog] = createSignal(false);
|
|
107
|
+
*
|
|
108
|
+
* {showDialog() && (
|
|
109
|
+
* <StandardDialog
|
|
110
|
+
* onButtonSelected={(index) => {
|
|
111
|
+
* console.log(`Button ${index} selected`);
|
|
112
|
+
* setShowDialog(false);
|
|
113
|
+
* }}
|
|
114
|
+
* onWasClosed={() => setShowDialog(false)}
|
|
115
|
+
* >
|
|
116
|
+
* <stdDlgTitleArea primaryTitle="Confirm Action" />
|
|
117
|
+
* <stdDlgContentArea>
|
|
118
|
+
* <stdDlgTextItem text="Are you sure you want to continue?" />
|
|
119
|
+
* </stdDlgContentArea>
|
|
120
|
+
* <stdDlgButtonArea>
|
|
121
|
+
* <stdDlgButton text="OK" />
|
|
122
|
+
* <stdDlgButton text="Cancel" />
|
|
123
|
+
* </stdDlgButtonArea>
|
|
124
|
+
* </StandardDialog>
|
|
125
|
+
* )}
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-dialog}
|
|
129
|
+
*/
|
|
130
|
+
export const StandardDialog: Component<IStandardDialogProps> = props => {
|
|
131
|
+
retainAsset(StandardDialogExtXML);
|
|
132
|
+
const [local, rest] = splitProps(props, modalPropKeys);
|
|
133
|
+
return <Modal {...local} dialog={<standardDialogExt {...rest} />} />;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
137
|
+
// Area nodes
|
|
138
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Title area component displayed at the top of a {@link StandardDialog}.
|
|
142
|
+
*
|
|
143
|
+
* A dialog may contain a single optional title area. Use it to display a title string
|
|
144
|
+
* with optional primary (left) and secondary (right) icons.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```tsx
|
|
148
|
+
* <stdDlgTitleArea
|
|
149
|
+
* primaryTitle="Settings"
|
|
150
|
+
* primaryIcon="pkg:/images/settings-icon.png"
|
|
151
|
+
* />
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-title-area}
|
|
155
|
+
*/
|
|
156
|
+
export const StdDlgTitleArea: Component<IStdDlgTitleAreaProps> = props => {
|
|
157
|
+
return <stdDlgTitleArea {...props}></stdDlgTitleArea>;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Content area containing the main body of a {@link StandardDialog}.
|
|
162
|
+
*
|
|
163
|
+
* Positioned between the title area and button area. Add StdDlg*Item child nodes
|
|
164
|
+
* (e.g., {@link StdDlgTextItem}, {@link StdDlgGraphicItem}) which are arranged vertically.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```tsx
|
|
168
|
+
* <stdDlgContentArea>
|
|
169
|
+
* <stdDlgTextItem text="Welcome to the app." />
|
|
170
|
+
* <stdDlgTextItem text="Please review the following:" namedTextStyle="secondary" />
|
|
171
|
+
* <stdDlgBulletTextItem bulletText={["Item A", "Item B", "Item C"]} />
|
|
172
|
+
* </stdDlgContentArea>
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-content-area}
|
|
176
|
+
*/
|
|
177
|
+
export const StdDlgContentArea: Component<IStdDlgContentAreaProps> = props => {
|
|
178
|
+
return <stdDlgContentArea {...props}></stdDlgContentArea>;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Button area positioned at the bottom of a {@link StandardDialog}.
|
|
183
|
+
*
|
|
184
|
+
* Contains zero or more {@link StdDlgButton} children arranged vertically. A dialog
|
|
185
|
+
* may have a single optional button area.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```tsx
|
|
189
|
+
* <stdDlgButtonArea>
|
|
190
|
+
* <stdDlgButton text="Accept" />
|
|
191
|
+
* <stdDlgButton text="Decline" />
|
|
192
|
+
* <stdDlgButton text="More Info" disabled={true} />
|
|
193
|
+
* </stdDlgButtonArea>
|
|
194
|
+
* ```
|
|
195
|
+
*
|
|
196
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-button-area}
|
|
197
|
+
*/
|
|
198
|
+
export const StdDlgButtonArea: Component<IStdDlgButtonAreaProps> = props => {
|
|
199
|
+
return <stdDlgButtonArea {...props}></stdDlgButtonArea>;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Freeform side card area on the left or right side of a {@link StandardDialog}.
|
|
204
|
+
*
|
|
205
|
+
* Use for decorative images or annotative text. The side card area never gains key focus.
|
|
206
|
+
* A dialog may contain only a single side card area.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```tsx
|
|
210
|
+
* <stdDlgSideCardArea width={300} horizAlign="right" showDivider={true}>
|
|
211
|
+
* <poster uri="pkg:/images/promo.jpg" width={280} height={400} />
|
|
212
|
+
* </stdDlgSideCardArea>
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-side-card-area}
|
|
216
|
+
*/
|
|
217
|
+
export const StdDlgSideCardArea: Component<IStdDlgSideCardAreaProps> = props => {
|
|
218
|
+
return <stdDlgSideCardArea {...props}></stdDlgSideCardArea>;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
222
|
+
// Button & item structural nodes
|
|
223
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* A button in a {@link StdDlgButtonArea}. Should only be a direct child of StdDlgButtonArea.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```tsx
|
|
230
|
+
* <stdDlgButtonArea>
|
|
231
|
+
* <stdDlgButton text="OK" />
|
|
232
|
+
* <stdDlgButton text="Cancel" />
|
|
233
|
+
* </stdDlgButtonArea>
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-button}
|
|
237
|
+
*/
|
|
238
|
+
export const StdDlgButton: Component<IStdDlgButtonProps> = props => {
|
|
239
|
+
return <stdDlgButton {...props}></stdDlgButton>;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Groups StdDlg item nodes with reduced spacing and optional radio-button exclusivity.
|
|
244
|
+
*
|
|
245
|
+
* Attach `onSelected` to each {@link StdDlgActionCardItem} to handle selection changes.
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* ```tsx
|
|
249
|
+
* const [selectedOption, setSelectedOption] = createSignal(0);
|
|
250
|
+
*
|
|
251
|
+
* <stdDlgItemGroup selectedIndex={selectedOption()}>
|
|
252
|
+
* <stdDlgActionCardItem iconType="radiobutton" onSelected={() => setSelectedOption(0)}>
|
|
253
|
+
* <stdDlgTextItem text="Option A" />
|
|
254
|
+
* </stdDlgActionCardItem>
|
|
255
|
+
* <stdDlgActionCardItem iconType="radiobutton" onSelected={() => setSelectedOption(1)}>
|
|
256
|
+
* <stdDlgTextItem text="Option B" />
|
|
257
|
+
* </stdDlgActionCardItem>
|
|
258
|
+
* <stdDlgActionCardItem iconType="radiobutton" onSelected={() => setSelectedOption(2)}>
|
|
259
|
+
* <stdDlgTextItem text="Option C" />
|
|
260
|
+
* </stdDlgActionCardItem>
|
|
261
|
+
* </stdDlgItemGroup>
|
|
262
|
+
* ```
|
|
263
|
+
*
|
|
264
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-item-group}
|
|
265
|
+
*/
|
|
266
|
+
export const StdDlgItemGroup: Component<IStdDlgItemGroupProps> = props => {
|
|
267
|
+
return <stdDlgItemGroup {...props}></stdDlgItemGroup>;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
271
|
+
// Content item nodes
|
|
272
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Focusable action card that highlights child items with optional icons.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```tsx
|
|
279
|
+
* <stdDlgActionCardItem iconType="checkbox" iconStatus={isChecked()}>
|
|
280
|
+
* <stdDlgTextItem text="Enable notifications" />
|
|
281
|
+
* </stdDlgActionCardItem>
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-action-card-item}
|
|
285
|
+
*/
|
|
286
|
+
export const StdDlgActionCardItem: Component<IStdDlgActionCardItemProps> = props => {
|
|
287
|
+
return <stdDlgActionCardItem {...props}></stdDlgActionCardItem>;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Displays a bulleted list of text in a {@link StdDlgContentArea}.
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```tsx
|
|
295
|
+
* <stdDlgBulletTextItem
|
|
296
|
+
* bulletType="numbered"
|
|
297
|
+
* bulletText={["Connect to Wi-Fi", "Sign in to your account", "Start streaming"]}
|
|
298
|
+
* />
|
|
299
|
+
* ```
|
|
300
|
+
*
|
|
301
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-bullet-text-item}
|
|
302
|
+
*/
|
|
303
|
+
export const StdDlgBulletTextItem: Component<IStdDlgBulletTextItemProps> = props => {
|
|
304
|
+
return <stdDlgBulletTextItem {...props}></stdDlgBulletTextItem>;
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Displays a determinate progress indicator for tasks with a known duration.
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* ```tsx
|
|
312
|
+
* <stdDlgDeterminateProgressItem percent={65} text="Downloading update…" />
|
|
313
|
+
* ```
|
|
314
|
+
*
|
|
315
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-determinate-progress-item}
|
|
316
|
+
*/
|
|
317
|
+
export const StdDlgDeterminateProgressItem: Component<IStdDlgDeterminateProgressItemProps> = props => {
|
|
318
|
+
return <stdDlgDeterminateProgressItem {...props}></stdDlgDeterminateProgressItem>;
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Displays an image with optional text in a {@link StdDlgContentArea}.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```tsx
|
|
326
|
+
* <stdDlgGraphicItem
|
|
327
|
+
* graphicUri="pkg:/images/info-icon.png"
|
|
328
|
+
* graphicWidth={48}
|
|
329
|
+
* graphicHeight={48}
|
|
330
|
+
* graphicAlign="left"
|
|
331
|
+
* text="Your device is up to date."
|
|
332
|
+
* />
|
|
333
|
+
* ```
|
|
334
|
+
*
|
|
335
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-graphic-item}
|
|
336
|
+
*/
|
|
337
|
+
export const StdDlgGraphicItem: Component<IStdDlgGraphicItemProps> = props => {
|
|
338
|
+
return <stdDlgGraphicItem {...props}></stdDlgGraphicItem>;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Displays a keyboard or PIN pad in a {@link StdDlgContentArea}.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```tsx
|
|
346
|
+
* <stdDlgKeyboardItem keyLayoutType={StdDlgKeyboardLayoutType.Keyboard} text="" />
|
|
347
|
+
* ```
|
|
348
|
+
*
|
|
349
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-keyboard-item}
|
|
350
|
+
*/
|
|
351
|
+
export const StdDlgKeyboardItem: Component<IStdDlgKeyboardItemProps> = props => {
|
|
352
|
+
return <stdDlgKeyboardItem {...props}></stdDlgKeyboardItem>;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Displays text with multiple styles in a {@link StdDlgContentArea}.
|
|
357
|
+
*
|
|
358
|
+
* Define named drawing styles and reference them as markup tags in the text content.
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* ```tsx
|
|
362
|
+
* <stdDlgMultiStyleTextItem
|
|
363
|
+
* text="Press <key>OK</key> to <action>confirm</action>."
|
|
364
|
+
* drawingStyles={{
|
|
365
|
+
* key: { fontUri: "font:MediumBoldSystemFont", color: "0xFFFF00FF" },
|
|
366
|
+
* action: { fontUri: "font:MediumSystemFont", color: "0x00FF00FF" }
|
|
367
|
+
* }}
|
|
368
|
+
* audioGuideText="Press OK to confirm."
|
|
369
|
+
* />
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-multi-style-text-item}
|
|
373
|
+
*/
|
|
374
|
+
export const StdDlgMultiStyleTextItem: Component<IStdDlgMultiStyleTextItemProps> = props => {
|
|
375
|
+
return <stdDlgMultiStyleTextItem {...props}></stdDlgMultiStyleTextItem>;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Displays an indeterminate spinning progress indicator in a {@link StdDlgContentArea}.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* <stdDlgProgressItem text="Loading, please wait…" />
|
|
384
|
+
* ```
|
|
385
|
+
*
|
|
386
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-progress-item}
|
|
387
|
+
*/
|
|
388
|
+
export const StdDlgProgressItem: Component<IStdDlgProgressItemProps> = props => {
|
|
389
|
+
return <stdDlgProgressItem {...props}></stdDlgProgressItem>;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Displays a block of text in a {@link StdDlgContentArea}.
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```tsx
|
|
397
|
+
* <stdDlgTextItem text="Your account has been updated." />
|
|
398
|
+
* <stdDlgTextItem text="Contact support if you have questions." namedTextStyle="secondary" />
|
|
399
|
+
* ```
|
|
400
|
+
*
|
|
401
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-text-item}
|
|
402
|
+
*/
|
|
403
|
+
export const StdDlgTextItem: Component<IStdDlgTextItemProps> = props => {
|
|
404
|
+
return <stdDlgTextItem {...props}></stdDlgTextItem>;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Free-form custom item in a {@link StdDlgContentArea} for content requiring custom layout.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* ```tsx
|
|
412
|
+
* <stdDlgCustomItem fixedWidthField={600}>
|
|
413
|
+
* <rectangle width={600} height={200} color="0x333333FF" />
|
|
414
|
+
* </stdDlgCustomItem>
|
|
415
|
+
* ```
|
|
416
|
+
*
|
|
417
|
+
* @see {@link https://developer.roku.com/dev/docs/std-dlg-custom-item}
|
|
418
|
+
*/
|
|
419
|
+
export const StdDlgCustomItem: Component<IStdDlgCustomItemProps> = props => {
|
|
420
|
+
return <stdDlgCustomItem {...props}></stdDlgCustomItem>;
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
424
|
+
// Pre-built Dialog Nodes
|
|
425
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
426
|
+
// StandardMessageDialog, StandardKeyboardDialog, StandardPinPadDialog, and
|
|
427
|
+
// StandardProgressDialog live in their own modules so unused dialogs and their XML
|
|
428
|
+
// assets tree-shake out of consuming apps. They are re-exported from the package barrel.
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
/** Keyboard input domain type for {@link StandardKeyboardDialog}. */
|
|
8
|
+
export type IKeyboardDomain = "email" | "numeric" | "alphanumeric" | "generic" | "password";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Properties for the {@link StandardKeyboardDialog} component.
|
|
12
|
+
*
|
|
13
|
+
* Extends {@link IStandardDialogProps} with keyboard-specific fields for text entry.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-keyboard-dialog}
|
|
16
|
+
*/
|
|
17
|
+
export interface IStandardKeyboardDialogProps extends IStandardDialogProps {
|
|
18
|
+
/**
|
|
19
|
+
* The title displayed at the top of the dialog.
|
|
20
|
+
* @default ""
|
|
21
|
+
*/
|
|
22
|
+
title?: string;
|
|
23
|
+
/**
|
|
24
|
+
* One or more blocks of text describing the data to be entered.
|
|
25
|
+
* Each string in the array is displayed as a separate block of text.
|
|
26
|
+
* Minimize message length to avoid automatic scrollbar.
|
|
27
|
+
* @default []
|
|
28
|
+
*/
|
|
29
|
+
message?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* List of button labels to display in the button area at the bottom of the dialog.
|
|
32
|
+
* Minimize the number of buttons to ensure visibility without scrolling.
|
|
33
|
+
* @default []
|
|
34
|
+
*/
|
|
35
|
+
buttons?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* The type of text to be entered. Used by the keyboard to modify voice entry method
|
|
38
|
+
* and determine when a valid string has been entered.
|
|
39
|
+
* - `"email"`: letter-by-letter dictation for emails
|
|
40
|
+
* - `"numeric"`: letter-by-letter dictation for PIN codes, zip codes
|
|
41
|
+
* - `"alphanumeric"`: letter-by-letter dictation for addresses
|
|
42
|
+
* - `"generic"`: full word input for search queries (default)
|
|
43
|
+
* - `"password"`: letter-by-letter dictation for passwords
|
|
44
|
+
* @default "generic"
|
|
45
|
+
*/
|
|
46
|
+
keyboardDomain?: IKeyboardDomain;
|
|
47
|
+
/**
|
|
48
|
+
* The default string displayed in the keyboard's text edit box.
|
|
49
|
+
* Updated with the currently entered string as the user types.
|
|
50
|
+
*
|
|
51
|
+
* @note Reactivity on this field has been intentionally removed. Binding a signal directly
|
|
52
|
+
* to `text` would cause an infinite loop: the user types → `onText` fires → signal updates →
|
|
53
|
+
* `text` prop changes → the keyboard resets the field → cursor jumps back. Use `onText` to
|
|
54
|
+
* track the live value and only set `text` as an initial/default value.
|
|
55
|
+
* @default ""
|
|
56
|
+
*/
|
|
57
|
+
text?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Fired whenever the text in the keyboard's text edit box changes (on each keystroke).
|
|
60
|
+
* The handler receives the full current string entered by the user.
|
|
61
|
+
*
|
|
62
|
+
* Use this to react to live input — for example to validate input, update a search
|
|
63
|
+
* suggestion list, or enable/disable action buttons based on what the user has typed so far.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* const [inputText, setInputText] = createSignal("");
|
|
68
|
+
*
|
|
69
|
+
* <StandardKeyboardDialog
|
|
70
|
+
* title="Search"
|
|
71
|
+
* keyboardDomain="generic"
|
|
72
|
+
* text={inputText()}
|
|
73
|
+
* onText={(text) => {
|
|
74
|
+
* // Called on every keystroke with the full current text
|
|
75
|
+
* setInputText(text);
|
|
76
|
+
* console.log("User is typing:", text);
|
|
77
|
+
* }}
|
|
78
|
+
* buttons={["Search", "Cancel"]}
|
|
79
|
+
* onButtonSelected={(index) => console.log("Button:", index)}
|
|
80
|
+
* />
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
onText?: EventHandler<string>;
|
|
84
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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 StandardKeyboardDialogExtXML from "../xml-components/modal/StandardKeyboardDialogExt.xml";
|
|
7
|
+
import type { IStandardKeyboardDialogProps } from "./standard-keyboard-dialog.props";
|
|
8
|
+
import { Component, splitProps } from "./types";
|
|
9
|
+
export type { IKeyboardDomain, IStandardKeyboardDialogProps } from "./standard-keyboard-dialog.props";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Displays a keyboard dialog for text and voice entry of alphanumeric characters and symbols.
|
|
13
|
+
*
|
|
14
|
+
* StandardKeyboardDialog is a pre-built dialog similar to the legacy KeyboardDialog node, but includes voice entry functionality through its internal DynamicKeyboard node.
|
|
15
|
+
*
|
|
16
|
+
* The {@link IStandardKeyboardDialogProps.keyboardDomain | keyboardDomain} property controls
|
|
17
|
+
* how voice input is processed:
|
|
18
|
+
* - `"generic"`: full word input for search queries
|
|
19
|
+
* - `"email"`: letter-by-letter for email addresses
|
|
20
|
+
* - `"password"`: letter-by-letter for passwords
|
|
21
|
+
* - `"numeric"`: letter-by-letter for PINs and zip codes
|
|
22
|
+
* - `"alphanumeric"`: letter-by-letter for street addresses
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* const [showKeyboard, setShowKeyboard] = createSignal(false);
|
|
27
|
+
* const [searchText, setSearchText] = createSignal("");
|
|
28
|
+
*
|
|
29
|
+
* {showKeyboard() && (
|
|
30
|
+
* <StandardKeyboardDialog
|
|
31
|
+
* title="Search"
|
|
32
|
+
* message={["Enter your search query:"]}
|
|
33
|
+
* keyboardDomain="generic"
|
|
34
|
+
* text={searchText()}
|
|
35
|
+
* buttons={["Search", "Cancel"]}
|
|
36
|
+
* // onText fires on every keystroke with the full current string
|
|
37
|
+
* onText={(text) => {
|
|
38
|
+
* setSearchText(text);
|
|
39
|
+
* console.log("Live input:", text);
|
|
40
|
+
* }}
|
|
41
|
+
* onButtonSelected={(index) => {
|
|
42
|
+
* if (index === 0) {
|
|
43
|
+
* console.log("Searching for:", searchText());
|
|
44
|
+
* }
|
|
45
|
+
* setShowKeyboard(false);
|
|
46
|
+
* }}
|
|
47
|
+
* onWasClosed={() => setShowKeyboard(false)}
|
|
48
|
+
* />
|
|
49
|
+
* )}
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-keyboard-dialog}
|
|
53
|
+
*/
|
|
54
|
+
export const StandardKeyboardDialog: Component<IStandardKeyboardDialogProps> = props => {
|
|
55
|
+
retainAsset(StandardKeyboardDialogExtXML);
|
|
56
|
+
const [local, rest] = splitProps(props, modalPropKeys);
|
|
57
|
+
return <Modal {...local} dialog={<standardKeyboardDialogExt {...rest} />} />;
|
|
58
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IStandardDialogProps } from "./standard-dialog.props";
|
|
5
|
+
|
|
6
|
+
/** Bullet list delimiter type for {@link StandardMessageDialog}. */
|
|
7
|
+
export type IStandardBulletType = "bullet" | "numbered" | "lettered";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Properties for the {@link StandardMessageDialog} component.
|
|
11
|
+
*
|
|
12
|
+
* Extends {@link IStandardDialogProps} with message-specific fields for displaying
|
|
13
|
+
* informational text blocks and bulleted lists.
|
|
14
|
+
*
|
|
15
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-message-dialog}
|
|
16
|
+
*/
|
|
17
|
+
export interface IStandardMessageDialogProps extends IStandardDialogProps {
|
|
18
|
+
/**
|
|
19
|
+
* The title displayed at the top of the dialog.
|
|
20
|
+
* @default ""
|
|
21
|
+
*/
|
|
22
|
+
title?: string;
|
|
23
|
+
/**
|
|
24
|
+
* One or more blocks of informational text displayed at the top of the dialog's content area.
|
|
25
|
+
* Each string in the array is displayed as a separate block of text with standard spacing.
|
|
26
|
+
* To separate lines of text, add each line as an element in the array (do not use newline characters).
|
|
27
|
+
* @default []
|
|
28
|
+
*/
|
|
29
|
+
message?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* An array of strings displayed as a bulleted or numbered list in the content area,
|
|
32
|
+
* below the message and above the bottom message.
|
|
33
|
+
* @default []
|
|
34
|
+
*/
|
|
35
|
+
bulletText?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Specifies the type of list item delimiter when {@link bulletText} is set.
|
|
38
|
+
* - `"bullet"`: bullet points (default)
|
|
39
|
+
* - `"numbered"`: numbered list (1, 2, 3...)
|
|
40
|
+
* - `"lettered"`: lettered list (a, b, c...)
|
|
41
|
+
* @default "bullet"
|
|
42
|
+
*/
|
|
43
|
+
bulletType?: IStandardBulletType;
|
|
44
|
+
/**
|
|
45
|
+
* One or more blocks of informational text displayed at the bottom of the dialog's content area.
|
|
46
|
+
* Each string in the array is displayed as a separate block of text with standard spacing.
|
|
47
|
+
* @default []
|
|
48
|
+
*/
|
|
49
|
+
bottomMessage?: string[];
|
|
50
|
+
/**
|
|
51
|
+
* List of button labels to display in the button area at the bottom of the dialog.
|
|
52
|
+
* Each string adds a new button. Minimize the number of buttons to ensure visibility.
|
|
53
|
+
* @default []
|
|
54
|
+
*/
|
|
55
|
+
buttons?: string[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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 StandardMessageDialogExtXML from "../xml-components/modal/StandardMessageDialogExt.xml";
|
|
7
|
+
import type { IStandardMessageDialogProps } from "./standard-message-dialog.props";
|
|
8
|
+
import { Component, splitProps } from "./types";
|
|
9
|
+
export type { IStandardBulletType, IStandardMessageDialogProps } from "./standard-message-dialog.props";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Displays a message dialog with optional title, text blocks, bulleted list, and buttons.
|
|
13
|
+
*
|
|
14
|
+
* StandardMessageDialog is a pre-built dialog similar to the legacy Dialog node. It provides a convenient way to display informational messages with:
|
|
15
|
+
* - One or more text blocks at the top ({@link IStandardMessageDialogProps.message | message})
|
|
16
|
+
* - An optional bulleted/numbered/lettered list ({@link IStandardMessageDialogProps.bulletText | bulletText})
|
|
17
|
+
* - One or more text blocks at the bottom ({@link IStandardMessageDialogProps.bottomMessage | bottomMessage})
|
|
18
|
+
* - A row of buttons ({@link IStandardMessageDialogProps.buttons | buttons})
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const [showDialog, setShowDialog] = createSignal(false);
|
|
23
|
+
*
|
|
24
|
+
* {showDialog() && (
|
|
25
|
+
* <StandardMessageDialog
|
|
26
|
+
* title="Terms of Service"
|
|
27
|
+
* message={["Please review the following terms:"]}
|
|
28
|
+
* bulletText={["You must be 18 or older", "Content is for personal use only", "Subscription auto-renews monthly"]}
|
|
29
|
+
* bulletType="numbered"
|
|
30
|
+
* bottomMessage={["By continuing, you agree to these terms."]}
|
|
31
|
+
* buttons={["Accept", "Decline"]}
|
|
32
|
+
* onButtonSelected={(index) => {
|
|
33
|
+
* console.log(index === 0 ? "Accepted" : "Declined");
|
|
34
|
+
* setShowDialog(false);
|
|
35
|
+
* }}
|
|
36
|
+
* onWasClosed={() => setShowDialog(false)}
|
|
37
|
+
* />
|
|
38
|
+
* )}
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @see {@link https://developer.roku.com/dev/docs/standard-message-dialog}
|
|
42
|
+
*/
|
|
43
|
+
export const StandardMessageDialog: Component<IStandardMessageDialogProps> = props => {
|
|
44
|
+
retainAsset(StandardMessageDialogExtXML);
|
|
45
|
+
const [local, rest] = splitProps(props, modalPropKeys);
|
|
46
|
+
return <Modal {...local} dialog={<standardMessageDialogExt {...rest} />} />;
|
|
47
|
+
};
|