@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,106 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IGroupProps } from "./group.props";
|
|
5
|
+
import type { FontValue, HorizAlign, ResType, VertAlign } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Properties for the ScrollingLabel node.
|
|
9
|
+
*
|
|
10
|
+
* ScrollingLabel displays a string of text that automatically scrolls horizontally
|
|
11
|
+
* if the text length exceeds the specified maximum width.
|
|
12
|
+
*
|
|
13
|
+
* **Scrolling Behavior:**
|
|
14
|
+
* - If the text fits within `maxWidth`, it is simply drawn without scrolling
|
|
15
|
+
* - If the text exceeds `maxWidth`, it is initially drawn with an ellipsis (...),
|
|
16
|
+
* then transitions to the full string and scrolls left to right, returning
|
|
17
|
+
* to the ellipsized state after scrolling completes
|
|
18
|
+
*
|
|
19
|
+
* @extends Group
|
|
20
|
+
* @see {@link https://developer.roku.com/dev/docs/scrollinglabel}
|
|
21
|
+
*/
|
|
22
|
+
export interface IScrollingLabelProps extends IGroupProps {
|
|
23
|
+
/**
|
|
24
|
+
* Specifies the text string to be displayed.
|
|
25
|
+
*
|
|
26
|
+
* @default ""
|
|
27
|
+
*/
|
|
28
|
+
text?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Specifies the text color as a hex value (e.g., `0xRRGGBBAA`).
|
|
32
|
+
*
|
|
33
|
+
* @default 0xddddddff
|
|
34
|
+
*/
|
|
35
|
+
color?: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Specifies the Font node to use for rendering the text.
|
|
39
|
+
* Can be a system font enum value or a custom font URI string.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Using system font
|
|
43
|
+
* font={SystemFont.Medium}
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Using custom font URI
|
|
47
|
+
* font="pkg:/fonts/custom.ttf"
|
|
48
|
+
*
|
|
49
|
+
* @default system default font
|
|
50
|
+
*/
|
|
51
|
+
font?: FontValue;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Specifies the maximum width of the rendered text in local coordinates.
|
|
55
|
+
* If the rendered text width exceeds this value, the scrolling behavior
|
|
56
|
+
* is automatically triggered.
|
|
57
|
+
*
|
|
58
|
+
* @default 500
|
|
59
|
+
*/
|
|
60
|
+
maxWidth?: ResType<number>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Specifies the height of the label in local coordinates.
|
|
64
|
+
* If set to 0, the actual height is determined by the font metrics.
|
|
65
|
+
*
|
|
66
|
+
* @default 0
|
|
67
|
+
*/
|
|
68
|
+
height?: ResType<number>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Specifies the horizontal scrolling speed in pixels per second.
|
|
72
|
+
*
|
|
73
|
+
* @default 100
|
|
74
|
+
*/
|
|
75
|
+
scrollSpeed?: number;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Controls the scrolling repeat behavior:
|
|
79
|
+
* - `-1`: Scrolls continuously (default)
|
|
80
|
+
* - `0`: Text remains ellipsized and never scrolls
|
|
81
|
+
* - `> 0`: Scrolls the specified number of times, then shows ellipsis
|
|
82
|
+
*
|
|
83
|
+
* @default -1
|
|
84
|
+
*/
|
|
85
|
+
repeatCount?: number;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Specifies the horizontal alignment of the text within the label bounds.
|
|
89
|
+
* - `"left"`: Left edge of the text is drawn at the 0 x-coordinate
|
|
90
|
+
* - `"center"`: Horizontal center of the text is drawn at half the computed width
|
|
91
|
+
* - `"right"`: Right edge of the text is drawn at the computed width
|
|
92
|
+
*
|
|
93
|
+
* @default "left"
|
|
94
|
+
*/
|
|
95
|
+
horizAlign?: HorizAlign;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Specifies the vertical alignment of the text within the label bounds.
|
|
99
|
+
* - `"top"`: Top edge of the text is drawn at the 0 y-coordinate
|
|
100
|
+
* - `"center"`: Vertical center of the text is drawn at half the computed height
|
|
101
|
+
* - `"bottom"`: Bottom edge of the text is drawn at the computed height
|
|
102
|
+
*
|
|
103
|
+
* @default "top"
|
|
104
|
+
*/
|
|
105
|
+
vertAlign?: VertAlign;
|
|
106
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IScrollingLabelProps } from "./scrolling-label.props";
|
|
5
|
+
import { Component } from "./types";
|
|
6
|
+
export type { IScrollingLabelProps } from "./scrolling-label.props";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ScrollingLabel component for displaying horizontally scrolling text.
|
|
10
|
+
*
|
|
11
|
+
* Use ScrollingLabel when you need to display text that may exceed a fixed width
|
|
12
|
+
* and should scroll to reveal the full content. This is commonly used for titles,
|
|
13
|
+
* descriptions, or any text that may be truncated.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { SystemFont } from "@roku-sdk/components";
|
|
18
|
+
*
|
|
19
|
+
* <scrollingLabel
|
|
20
|
+
* text="This is a long text that will scroll if it exceeds maxWidth"
|
|
21
|
+
* maxWidth={400}
|
|
22
|
+
* scrollSpeed={80}
|
|
23
|
+
* font={SystemFont.Medium}
|
|
24
|
+
* color="0xFFFFFFFF"
|
|
25
|
+
* />
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* // Scroll only 3 times then show ellipsis
|
|
31
|
+
* <scrollingLabel
|
|
32
|
+
* text="Limited scroll text"
|
|
33
|
+
* maxWidth={200}
|
|
34
|
+
* repeatCount={3}
|
|
35
|
+
* />
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @see {@link https://developer.roku.com/dev/docs/scrollinglabel}
|
|
39
|
+
*/
|
|
40
|
+
export const ScrollingLabel: Component<IScrollingLabelProps> = props => {
|
|
41
|
+
return <scrollingLabel {...props}></scrollingLabel>;
|
|
42
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { IGroupProps } from "./group.props";
|
|
5
|
+
import type { HorizAlign } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Horizontal origin options for SimpleLabel positioning.
|
|
9
|
+
* Controls the x=0 position of the SimpleLabel node's local coordinate system.
|
|
10
|
+
*/
|
|
11
|
+
export type HorizOrigin = HorizAlign;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Vertical origin options for SimpleLabel positioning.
|
|
15
|
+
* Controls the y=0 position of the SimpleLabel node's local coordinate system.
|
|
16
|
+
*
|
|
17
|
+
* - `"top"`: Top edge of the text is at the 0 y-coordinate
|
|
18
|
+
* - `"center"`: Vertical center of the text is at the 0 y-coordinate
|
|
19
|
+
* - `"baseline"`: Baseline of the text is at the 0 y-coordinate
|
|
20
|
+
* - `"bottom"`: Bottom edge of the text is at the 0 y-coordinate
|
|
21
|
+
*/
|
|
22
|
+
export type VertOrigin = "top" | "center" | "baseline" | "bottom";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Font URI options for SimpleLabel.
|
|
26
|
+
*
|
|
27
|
+
* Can be either:
|
|
28
|
+
* - A path to a TrueType or OpenType font file (e.g., `pkg:/fonts/MyFont.ttf`)
|
|
29
|
+
* - A built-in system font name using the `font:` prefix
|
|
30
|
+
*
|
|
31
|
+
* **Built-in System Fonts (Fixed Size):**
|
|
32
|
+
* - `font:SmallestSystemFont`
|
|
33
|
+
* - `font:SmallSystemFont`
|
|
34
|
+
* - `font:MediumSystemFont`
|
|
35
|
+
* - `font:LargeSystemFont`
|
|
36
|
+
* - `font:SmallestBoldSystemFont`
|
|
37
|
+
* - `font:SmallBoldSystemFont`
|
|
38
|
+
* - `font:MediumBoldSystemFont`
|
|
39
|
+
* - `font:LargeBoldSystemFont`
|
|
40
|
+
*
|
|
41
|
+
* **Built-in System Fonts (Variable Size - respects fontSize):**
|
|
42
|
+
* - `font:SystemFontFile`
|
|
43
|
+
* - `font:BoldSystemFontFile`
|
|
44
|
+
*/
|
|
45
|
+
export type SimpleLabelFontUri = string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Properties for the SimpleLabel node.
|
|
49
|
+
*
|
|
50
|
+
* SimpleLabel is a lightweight component for displaying a single line of text.
|
|
51
|
+
* It is more memory efficient than the Label node and supports simplified font
|
|
52
|
+
* style specification.
|
|
53
|
+
*
|
|
54
|
+
* **Features:**
|
|
55
|
+
* - Built-in system fonts or TrueType/OpenType font files
|
|
56
|
+
* - Customizable text color
|
|
57
|
+
* - Flexible horizontal and vertical origin positioning
|
|
58
|
+
* - Rotation support (center of rotation determined by origin point)
|
|
59
|
+
*
|
|
60
|
+
* @extends Group
|
|
61
|
+
* @see {@link https://developer.roku.com/dev/docs/simplelabel}
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* <SimpleLabel
|
|
65
|
+
* text="Hello World"
|
|
66
|
+
* fontUri="font:MediumBoldSystemFont"
|
|
67
|
+
* color="#FFFFFFFF"
|
|
68
|
+
* horizOrigin="center"
|
|
69
|
+
* vertOrigin="baseline"
|
|
70
|
+
* />
|
|
71
|
+
*/
|
|
72
|
+
export interface ISimpleLabelProps extends IGroupProps {
|
|
73
|
+
/**
|
|
74
|
+
* Specifies the text string to be displayed.
|
|
75
|
+
*
|
|
76
|
+
* @default ""
|
|
77
|
+
*/
|
|
78
|
+
text?: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Specifies the text color as a hex value (e.g., `0xRRGGBBAA` or `#RRGGBBAA`).
|
|
82
|
+
*
|
|
83
|
+
* @default 0xddddddff
|
|
84
|
+
*/
|
|
85
|
+
color?: string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Specifies either a path to a TrueType/OpenType font file or a built-in
|
|
89
|
+
* system font name.
|
|
90
|
+
*
|
|
91
|
+
* For TrueType or OpenType font files, the file must be included with the
|
|
92
|
+
* application (e.g., `pkg:/fonts/SomeFontFile.ttf`). If no fontUri is
|
|
93
|
+
* specified, the System Default font is used.
|
|
94
|
+
*
|
|
95
|
+
* **Fixed Size System Fonts** (fontSize field is ignored):
|
|
96
|
+
* - `font:SmallestSystemFont`
|
|
97
|
+
* - `font:SmallSystemFont`
|
|
98
|
+
* - `font:MediumSystemFont`
|
|
99
|
+
* - `font:LargeSystemFont`
|
|
100
|
+
* - `font:SmallestBoldSystemFont`
|
|
101
|
+
* - `font:SmallBoldSystemFont`
|
|
102
|
+
* - `font:MediumBoldSystemFont`
|
|
103
|
+
* - `font:LargeBoldSystemFont`
|
|
104
|
+
*
|
|
105
|
+
* **Variable Size System Fonts** (fontSize field is respected):
|
|
106
|
+
* - `font:SystemFontFile`
|
|
107
|
+
* - `font:BoldSystemFontFile`
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // Using a built-in system font
|
|
111
|
+
* fontUri="font:MediumBoldSystemFont"
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Using a custom TrueType font
|
|
115
|
+
* fontUri="pkg:/fonts/CustomFont.ttf"
|
|
116
|
+
*
|
|
117
|
+
* @default system default
|
|
118
|
+
*/
|
|
119
|
+
fontUri?: SimpleLabelFontUri;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Specifies the size of the font in points.
|
|
123
|
+
*
|
|
124
|
+
* **Note:** This field is only respected when using variable size system fonts
|
|
125
|
+
* (`font:SystemFontFile` or `font:BoldSystemFontFile`) or custom font files.
|
|
126
|
+
* Fixed size system fonts ignore this value.
|
|
127
|
+
*
|
|
128
|
+
* @default system default
|
|
129
|
+
*/
|
|
130
|
+
fontSize?: number;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Controls the horizontal origin (x=0 position) of the SimpleLabel's local
|
|
134
|
+
* coordinate system.
|
|
135
|
+
*
|
|
136
|
+
* - `"left"`: Left edge of text is at x=0
|
|
137
|
+
* - `"center"`: Horizontal center of text is at x=0
|
|
138
|
+
* - `"right"`: Right edge of text is at x=0
|
|
139
|
+
*
|
|
140
|
+
* @default "left"
|
|
141
|
+
*/
|
|
142
|
+
horizOrigin?: HorizOrigin;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Controls the vertical origin (y=0 position) of the SimpleLabel's local
|
|
146
|
+
* coordinate system.
|
|
147
|
+
*
|
|
148
|
+
* - `"top"`: Top edge of text is at y=0
|
|
149
|
+
* - `"center"`: Vertical center of text is at y=0
|
|
150
|
+
* - `"baseline"`: Text baseline is at y=0
|
|
151
|
+
* - `"bottom"`: Bottom edge of text is at y=0
|
|
152
|
+
*
|
|
153
|
+
* @default "top"
|
|
154
|
+
*/
|
|
155
|
+
vertOrigin?: VertOrigin;
|
|
156
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { ISimpleLabelProps } from "./simple-label.props";
|
|
5
|
+
import { Component } from "./types";
|
|
6
|
+
export type { HorizOrigin, VertOrigin, SimpleLabelFontUri, ISimpleLabelProps } from "./simple-label.props";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* SimpleLabel component for displaying a single line of text.
|
|
10
|
+
*
|
|
11
|
+
* SimpleLabel is a lightweight complement to the Label node. It supports simplified
|
|
12
|
+
* font style specification and is more memory efficient than the Label node.
|
|
13
|
+
*
|
|
14
|
+
* Use SimpleLabel when you need basic text rendering without the advanced features
|
|
15
|
+
* of the Label node (such as multi-line text, wrapping, or truncation).
|
|
16
|
+
*
|
|
17
|
+
* **Origin-based Positioning:**
|
|
18
|
+
* Unlike most nodes where translation moves the top-left corner, SimpleLabel uses
|
|
19
|
+
* origin-based positioning. The `horizOrigin` and `vertOrigin` fields determine
|
|
20
|
+
* which part of the text is positioned at the translation point.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* // Basic usage with system font
|
|
25
|
+
* <simpleLabel
|
|
26
|
+
* text="Hello World"
|
|
27
|
+
* fontUri="font:MediumBoldSystemFont"
|
|
28
|
+
* translation={[100, 100]}
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // Centered text at a specific position
|
|
35
|
+
* <simpleLabel
|
|
36
|
+
* text="Centered Text"
|
|
37
|
+
* fontUri="font:LargeSystemFont"
|
|
38
|
+
* horizOrigin="center"
|
|
39
|
+
* vertOrigin="center"
|
|
40
|
+
* translation={[960, 540]}
|
|
41
|
+
* />
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* // Custom font with specific size
|
|
47
|
+
* <simpleLabel
|
|
48
|
+
* text="Custom Font"
|
|
49
|
+
* fontUri="font:SystemFontFile"
|
|
50
|
+
* fontSize={24}
|
|
51
|
+
* color="#FF6B6BFF"
|
|
52
|
+
* />
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @see {@link https://developer.roku.com/dev/docs/simplelabel}
|
|
56
|
+
*/
|
|
57
|
+
export const SimpleLabel: Component<ISimpleLabelProps> = props => {
|
|
58
|
+
return <simpleLabel {...props}></simpleLabel>;
|
|
59
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import type { ComponentRef } from "@roku-sdk/interfaces";
|
|
5
|
+
|
|
6
|
+
import type { INodeProps } from "./node";
|
|
7
|
+
import type { EventHandler } from "./types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Control values for the SoundEffect `control` field.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
13
|
+
*/
|
|
14
|
+
export enum SoundEffectControl {
|
|
15
|
+
None = "none",
|
|
16
|
+
Play = "play",
|
|
17
|
+
Stop = "stop"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Playback state values reported by the SoundEffect `state` field.
|
|
22
|
+
*
|
|
23
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
24
|
+
*/
|
|
25
|
+
export enum SoundEffectState {
|
|
26
|
+
None = "none",
|
|
27
|
+
Playing = "playing",
|
|
28
|
+
Stopped = "stopped",
|
|
29
|
+
Finished = "finished",
|
|
30
|
+
TooManySounds = "toomanysounds",
|
|
31
|
+
NotReady = "notready"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Load status values reported by the SoundEffect `loadStatus` field.
|
|
36
|
+
*
|
|
37
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
38
|
+
*/
|
|
39
|
+
export enum SoundEffectLoadStatus {
|
|
40
|
+
None = "none",
|
|
41
|
+
Loading = "loading",
|
|
42
|
+
Ready = "ready",
|
|
43
|
+
Failed = "failed",
|
|
44
|
+
Flushed = "flushed"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Properties for the SoundEffect node.
|
|
49
|
+
*
|
|
50
|
+
* The SoundEffect node plays short audio sound effects triggered from UI events.
|
|
51
|
+
* Up to four simultaneous sounds can play at any time, in addition to audio from
|
|
52
|
+
* streaming content and TextToSpeech audio. All files must be WAV (PCM) format.
|
|
53
|
+
*
|
|
54
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
55
|
+
*/
|
|
56
|
+
export interface ISoundEffectProps extends INodeProps {
|
|
57
|
+
/**
|
|
58
|
+
* Specifies the URI of the WAV file. Sounds included as part of the application
|
|
59
|
+
* package can be referenced using the `pkg:/sounds` prefix. This may also specify
|
|
60
|
+
* the location of a WAV file on a remote server.
|
|
61
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect | SoundEffect Fields}
|
|
62
|
+
*/
|
|
63
|
+
uri?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Controls the audio playback. Getting the value returns the most recent value set,
|
|
66
|
+
* or `"none"` if no value has been set.
|
|
67
|
+
*
|
|
68
|
+
* - `"none"` -- No effect.
|
|
69
|
+
* - `"play"` -- Start playing the audio. Restarts if already playing. If `loadStatus`
|
|
70
|
+
* is not `"ready"`, the sound will not play and `state` becomes `"notready"`.
|
|
71
|
+
* - `"stop"` -- Stop playing the audio if it is currently playing.
|
|
72
|
+
*
|
|
73
|
+
* @default "none"
|
|
74
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect | SoundEffect Fields}
|
|
75
|
+
*/
|
|
76
|
+
control?: SoundEffectControl;
|
|
77
|
+
/**
|
|
78
|
+
* The volume as a percentage of full volume (0--100). Use 50 for normal volume.
|
|
79
|
+
* @default 50
|
|
80
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect | SoundEffect Fields}
|
|
81
|
+
*/
|
|
82
|
+
volume?: number;
|
|
83
|
+
/**
|
|
84
|
+
* Fired when the playback state changes.
|
|
85
|
+
*
|
|
86
|
+
* Possible values: `"none"`, `"playing"`, `"stopped"`, `"finished"`,
|
|
87
|
+
* `"toomanysounds"`, `"notready"`.
|
|
88
|
+
*/
|
|
89
|
+
onState?: EventHandler<SoundEffectState>;
|
|
90
|
+
/**
|
|
91
|
+
* Fired when the load status of the sound file changes.
|
|
92
|
+
*
|
|
93
|
+
* Possible values: `"none"`, `"loading"`, `"ready"`, `"failed"`, `"flushed"`.
|
|
94
|
+
*/
|
|
95
|
+
onLoadStatus?: EventHandler<SoundEffectLoadStatus>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Handle for imperative control of a {@link SoundEffect} component, obtained via the `ref` prop.
|
|
100
|
+
*
|
|
101
|
+
* Extends {@link ComponentRef} with convenience methods that map to
|
|
102
|
+
* {@link SoundEffectControl} values, so you can drive playback without manually
|
|
103
|
+
* setting the `control` prop.
|
|
104
|
+
*
|
|
105
|
+
* Unlike {@link import("./video").VideoRef | VideoRef} and
|
|
106
|
+
* {@link import("./audio").AudioRef | AudioRef}, SoundEffect only supports
|
|
107
|
+
* `play` and `stop` — there is no pause, resume, or skip.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```tsx
|
|
111
|
+
* import { SoundEffect, SoundEffectRef, Button } from "@roku-sdk/components";
|
|
112
|
+
*
|
|
113
|
+
* const ClickSound = () => {
|
|
114
|
+
* let sfxRef!: SoundEffectRef;
|
|
115
|
+
*
|
|
116
|
+
* return (
|
|
117
|
+
* <>
|
|
118
|
+
* <Button text="Play" onButtonSelected={() => sfxRef.play()} />
|
|
119
|
+
* <SoundEffect ref={sfxRef} uri="pkg:/sounds/click.wav" volume={50} />
|
|
120
|
+
* </>
|
|
121
|
+
* );
|
|
122
|
+
* };
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
126
|
+
*/
|
|
127
|
+
export interface SoundEffectRef extends ComponentRef<ISoundEffectProps> {
|
|
128
|
+
play: () => void;
|
|
129
|
+
stop: () => void;
|
|
130
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright (c) 2026 Roku, Inc.
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
import { registerImperativeMethods, setPropMethod } from "@roku-sdk/solid";
|
|
5
|
+
|
|
6
|
+
import type { ISoundEffectProps } from "./sound-effect.props";
|
|
7
|
+
export { SoundEffectControl, SoundEffectState, SoundEffectLoadStatus } from "./sound-effect.props";
|
|
8
|
+
|
|
9
|
+
export type { ISoundEffectProps, SoundEffectRef } from "./sound-effect.props";
|
|
10
|
+
|
|
11
|
+
import { Component } from "./types";
|
|
12
|
+
|
|
13
|
+
registerImperativeMethods("soundEffect", {
|
|
14
|
+
play: setPropMethod("control", "play"),
|
|
15
|
+
stop: setPropMethod("control", "stop")
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* SoundEffect plays short audio sound effects that can be triggered from UI events.
|
|
20
|
+
* Files can be installed locally as part of the package or dynamically downloaded from
|
|
21
|
+
* the network. All files must be WAV (PCM) format. Up to four simultaneous sounds can
|
|
22
|
+
* play at any time.
|
|
23
|
+
*
|
|
24
|
+
* For local files, the convention is to include WAV files in a directory named `sounds`.
|
|
25
|
+
* For downloaded files, a least-recently-used (LRU) mechanism keeps the most recently
|
|
26
|
+
* played sounds in temporary storage on the device.
|
|
27
|
+
*
|
|
28
|
+
* Playback can be controlled declaratively via the `control` prop or imperatively
|
|
29
|
+
* via a {@link SoundEffectRef} obtained through the `ref` prop.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* // Declarative control via the control prop
|
|
34
|
+
* <soundEffect
|
|
35
|
+
* uri="pkg:/sounds/click.wav"
|
|
36
|
+
* control={SoundEffectControl.Play}
|
|
37
|
+
* volume={50}
|
|
38
|
+
* onState={(state) => console.log("SoundEffect state:", state)}
|
|
39
|
+
* />
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* // Imperative control via ref
|
|
45
|
+
* let sfxRef!: SoundEffectRef;
|
|
46
|
+
* <soundEffect ref={sfxRef} uri="pkg:/sounds/click.wav" volume={50} />
|
|
47
|
+
* // Then trigger playback: sfxRef.play()
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* // Network-hosted sound with load status monitoring
|
|
53
|
+
* <soundEffect
|
|
54
|
+
* uri="https://example.com/sounds/alert.wav"
|
|
55
|
+
* onLoadStatus={(status) => {
|
|
56
|
+
* if (status === SoundEffectLoadStatus.Ready) console.log("Sound ready to play");
|
|
57
|
+
* }}
|
|
58
|
+
* />
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see {@link https://developer.roku.com/dev/docs/soundeffect}
|
|
62
|
+
*/
|
|
63
|
+
export const SoundEffect: Component<ISoundEffectProps> = props => {
|
|
64
|
+
return <soundEffect {...props} />;
|
|
65
|
+
};
|