@decky/ui 4.8.0 → 4.8.2

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.
@@ -19,6 +19,6 @@ export const DialogBodyText = MappedDialogDivs.get('DialogBodyText');
19
19
  export const DialogBody = MappedDialogDivs.get('DialogBody');
20
20
  export const DialogControlsSection = MappedDialogDivs.get('DialogControlsSection');
21
21
  export const DialogControlsSectionHeader = MappedDialogDivs.get('DialogControlsSectionHeader');
22
- export const DialogButtonPrimary = Object.values(CommonUIModule).find((mod) => mod?.render?.toString()?.includes('"DialogButton","_DialogLayout","Primary"'));
23
- export const DialogButtonSecondary = Object.values(CommonUIModule).find((mod) => mod?.render?.toString()?.includes('"DialogButton","_DialogLayout","Secondary"'));
22
+ export const DialogButtonPrimary = Object.values(CommonUIModule).find((mod) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Primary"'));
23
+ export const DialogButtonSecondary = Object.values(CommonUIModule).find((mod) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Secondary"'));
24
24
  export const DialogButton = DialogButtonSecondary;
@@ -1,7 +1,8 @@
1
1
  import { findModuleExport } from '../webpack';
2
- export const DialogCheckbox = findModuleExport(e => e.prototype &&
2
+ export const DialogCheckbox = findModuleExport(e => e?.prototype &&
3
+ typeof e?.prototype == "object" &&
3
4
  "GetPanelElementProps" in e?.prototype &&
4
5
  "SetChecked" in e?.prototype &&
5
6
  "Toggle" in e?.prototype &&
6
- (e?.prototype?.render?.toString().includes('="DialogCheckbox"') || (e.contextType &&
7
- e.prototype?.render?.toString().includes('fallback:'))));
7
+ (e?.prototype?.render?.toString?.().includes('="DialogCheckbox"') || (e.contextType &&
8
+ e.prototype?.render?.toString?.().includes('fallback:'))));
@@ -1,2 +1,2 @@
1
1
  import { findModuleExport } from '../webpack';
2
- export const FocusRing = findModuleExport((e) => e?.toString()?.includes('.GetShowDebugFocusRing())'));
2
+ export const FocusRing = findModuleExport((e) => e?.toString?.()?.includes('.GetShowDebugFocusRing())'));
@@ -31,11 +31,11 @@ export declare enum GamepadButton {
31
31
  STEAM_QUICK_MENU = 28
32
32
  }
33
33
  export declare enum NavEntryPositionPreferences {
34
- FIRST,
35
- LAST,
36
- MAINTAIN_X,
37
- MAINTAIN_Y,
38
- PREFERRED_CHILD
34
+ FIRST = 0,
35
+ LAST = 1,
36
+ MAINTAIN_X = 2,
37
+ MAINTAIN_Y = 3,
38
+ PREFERRED_CHILD = 4
39
39
  }
40
40
  export interface GamepadEventDetail {
41
41
  button: number;
@@ -47,6 +47,8 @@ export declare type ActionDescriptionMap = {
47
47
  };
48
48
  export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
49
49
  export interface FooterLegendProps {
50
+ navEntryPreferPosition?: NavEntryPositionPreferences;
51
+ preferredFocus?: boolean;
50
52
  actionDescriptionMap?: ActionDescriptionMap;
51
53
  onOKActionDescription?: ReactNode;
52
54
  onCancelActionDescription?: ReactNode;
@@ -30,3 +30,11 @@ export var GamepadButton;
30
30
  GamepadButton[GamepadButton["STEAM_GUIDE"] = 27] = "STEAM_GUIDE";
31
31
  GamepadButton[GamepadButton["STEAM_QUICK_MENU"] = 28] = "STEAM_QUICK_MENU";
32
32
  })(GamepadButton || (GamepadButton = {}));
33
+ export var NavEntryPositionPreferences;
34
+ (function (NavEntryPositionPreferences) {
35
+ NavEntryPositionPreferences[NavEntryPositionPreferences["FIRST"] = 0] = "FIRST";
36
+ NavEntryPositionPreferences[NavEntryPositionPreferences["LAST"] = 1] = "LAST";
37
+ NavEntryPositionPreferences[NavEntryPositionPreferences["MAINTAIN_X"] = 2] = "MAINTAIN_X";
38
+ NavEntryPositionPreferences[NavEntryPositionPreferences["MAINTAIN_Y"] = 3] = "MAINTAIN_Y";
39
+ NavEntryPositionPreferences[NavEntryPositionPreferences["PREFERRED_CHILD"] = 4] = "PREFERRED_CHILD";
40
+ })(NavEntryPositionPreferences || (NavEntryPositionPreferences = {}));
@@ -3,5 +3,5 @@ export const showContextMenu = findModuleExport((e) => typeof e === 'function' &
3
3
  && e.toString().includes('.CreateContextMenuInstance('));
4
4
  export const Menu = findModuleExport((e) => e?.prototype?.HideIfSubmenu && e?.prototype?.HideMenu);
5
5
  const MenuGoupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`));
6
- export const MenuGroup = MenuGoupModule && Object.values(MenuGoupModule).find((e) => typeof e == "function" && e?.toString()?.includes("bInGamepadUI:"));
7
- export const MenuItem = findModuleExport((e) => e?.render?.toString()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter));
6
+ export const MenuGroup = MenuGoupModule && Object.values(MenuGoupModule).find((e) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
7
+ export const MenuItem = findModuleExport((e) => e?.render?.toString?.()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter));
@@ -19,7 +19,7 @@ export const ModalRoot = Object.values(findModule((m) => {
19
19
  }
20
20
  }
21
21
  return false;
22
- }) || {})?.find((x) => x?.type?.toString()?.includes('((function(){'));
22
+ }) || {})?.find((x) => x?.type?.toString?.()?.includes('((function(){'));
23
23
  const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e) => e?.toString().includes('.ModalPosition'), 5);
24
24
  const ModalModuleProps = ModalModule ? Object.values(ModalModule) : [];
25
25
  export const SimpleModal = ModalModuleProps.find((prop) => {
@@ -1,4 +1,4 @@
1
1
  import { findModuleDetailsByExport } from '../webpack';
2
2
  const [mod, panelSection] = findModuleDetailsByExport((e) => e.toString()?.includes('.PanelSection'));
3
3
  export const PanelSection = panelSection;
4
- export const PanelSectionRow = Object.values(mod).filter((exp) => !exp?.toString()?.includes('.PanelSection'))[0];
4
+ export const PanelSectionRow = Object.values(mod).filter((exp) => !exp?.toString?.()?.includes('.PanelSection'))[0];
@@ -1,6 +1,6 @@
1
1
  import { findModuleExport } from '../webpack';
2
2
  import { createPropListRegex } from '../utils';
3
- export const ProgressBar = findModuleExport((e) => e?.toString()?.includes('.ProgressBar,"standard"=='));
4
- export const ProgressBarWithInfo = findModuleExport((e) => e?.toString()?.includes('.ProgressBarFieldStatus},'));
3
+ export const ProgressBar = findModuleExport((e) => e?.toString?.()?.includes('.ProgressBar,"standard"=='));
4
+ export const ProgressBarWithInfo = findModuleExport((e) => e?.toString?.()?.includes('.ProgressBarFieldStatus},'));
5
5
  const progressBarItemRegex = createPropListRegex(["indeterminate", "nTransitionSec", "nProgress"]);
6
6
  export const ProgressBarItem = findModuleExport((e) => e?.toString && progressBarItemRegex.test(e.toString()));
@@ -1,2 +1,2 @@
1
1
  import { CommonUIModule } from '../webpack';
2
- export const SliderField = Object.values(CommonUIModule).find((mod) => mod?.toString()?.includes('SliderField,fallback') || mod?.toString()?.includes("SliderField\","));
2
+ export const SliderField = Object.values(CommonUIModule).find((mod) => mod?.toString?.()?.includes('SliderField,fallback') || mod?.toString?.()?.includes("SliderField\","));
@@ -1,3 +1,3 @@
1
1
  import { findModuleByExport } from '../webpack';
2
- const tabsModule = findModuleByExport(e => e?.toString()?.includes(".TabRowTabs") && e?.toString()?.includes("activeTab:"));
3
- export const Tabs = tabsModule && Object.values(tabsModule).find((e) => e?.type?.toString()?.includes("((function()"));
2
+ const tabsModule = findModuleByExport(e => e?.toString?.()?.includes(".TabRowTabs") && e?.toString?.()?.includes("activeTab:"));
3
+ export const Tabs = tabsModule && Object.values(tabsModule).find((e) => e?.type?.toString?.()?.includes("((function()"));
@@ -1,2 +1,2 @@
1
1
  import { CommonUIModule } from '../webpack';
2
- export const Toggle = Object.values(CommonUIModule).find((mod) => mod?.render?.toString()?.includes('.ToggleOff)'));
2
+ export const Toggle = Object.values(CommonUIModule).find((mod) => mod?.render?.toString?.()?.includes('.ToggleOff)'));
@@ -1,2 +1,2 @@
1
1
  import { CommonUIModule } from '../webpack';
2
- export const ToggleField = Object.values(CommonUIModule).find((mod) => mod?.render?.toString()?.includes('ToggleField,fallback') || mod?.render?.toString()?.includes("ToggleField\","));
2
+ export const ToggleField = Object.values(CommonUIModule).find((mod) => mod?.render?.toString?.()?.includes('ToggleField,fallback') || mod?.render?.toString?.()?.includes("ToggleField\","));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decky/ui",
3
- "version": "4.8.0",
3
+ "version": "4.8.2",
4
4
  "description": "A library for interacting with the Steam frontend in Decky plugins and elsewhere.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -78,11 +78,11 @@ export const DialogControlsSection = MappedDialogDivs.get('DialogControlsSection
78
78
  export const DialogControlsSectionHeader = MappedDialogDivs.get('DialogControlsSectionHeader') as FC<DialogCommonProps>;
79
79
 
80
80
  export const DialogButtonPrimary = Object.values(CommonUIModule).find(
81
- (mod: any) => mod?.render?.toString()?.includes('"DialogButton","_DialogLayout","Primary"'),
81
+ (mod: any) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Primary"'),
82
82
  ) as FC<DialogButtonProps>;
83
83
 
84
84
  export const DialogButtonSecondary = Object.values(CommonUIModule).find(
85
- (mod: any) => mod?.render?.toString()?.includes('"DialogButton","_DialogLayout","Secondary"')
85
+ (mod: any) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Secondary"')
86
86
  ) as FC<DialogButtonProps>;
87
87
 
88
88
  // This is the "main" button. The Primary can act as a submit button,
@@ -20,13 +20,14 @@ export interface DialogCheckboxProps extends DialogCommonProps, FooterLegendProp
20
20
 
21
21
  // Do not access KeyDown, SetChecked, Toggle here as they are getters and accessing them outside of a render breaks them globally
22
22
  export const DialogCheckbox = findModuleExport(e =>
23
- e.prototype &&
23
+ e?.prototype &&
24
+ typeof e?.prototype == "object" &&
24
25
  "GetPanelElementProps" in e?.prototype &&
25
26
  "SetChecked" in e?.prototype &&
26
27
  "Toggle" in e?.prototype &&
27
28
  // beta || stable as of oct 2 2024
28
- (e?.prototype?.render?.toString().includes('="DialogCheckbox"') || (
29
+ (e?.prototype?.render?.toString?.().includes('="DialogCheckbox"') || (
29
30
  e.contextType &&
30
- e.prototype?.render?.toString().includes('fallback:')
31
+ e.prototype?.render?.toString?.().includes('fallback:')
31
32
  ))
32
33
  ) as FC<DialogCheckboxProps>;
@@ -11,5 +11,5 @@ export interface FocusRingProps {
11
11
  }
12
12
 
13
13
  export const FocusRing = findModuleExport((e: Export) =>
14
- e?.toString()?.includes('.GetShowDebugFocusRing())'),
14
+ e?.toString?.()?.includes('.GetShowDebugFocusRing())'),
15
15
  ) as FC<FocusRingProps>;
@@ -31,11 +31,42 @@ export enum GamepadButton {
31
31
  STEAM_GUIDE,
32
32
  STEAM_QUICK_MENU,
33
33
  }
34
- export declare enum NavEntryPositionPreferences {
34
+ export enum NavEntryPositionPreferences {
35
+ /**
36
+ * Always give focus to the first child element.
37
+ */
35
38
  FIRST,
39
+
40
+ /**
41
+ * Always give focus to the last child element.
42
+ */
36
43
  LAST,
44
+
45
+ /**
46
+ * Give focus to the child element that would maintain the flow in the X axis.
47
+ *
48
+ * Imagine you have a calculator window with 9 standard buttons.
49
+ * You have 3 rows of buttons, with 3 buttons per row.
50
+ * If you select button with number 8 and navigate down, the buttons
51
+ * will be navigated in the following order 8->5->3.
52
+ * The flow is maintained for the X axis while you're navigating the Y axis.
53
+ */
37
54
  MAINTAIN_X,
55
+
56
+ /**
57
+ * Give focus to the child element that would maintain the flow in the Y axis.
58
+ *
59
+ * Imagine you have a calculator window with 9 standard buttons.
60
+ * You have 3 columns of buttons, with 3 buttons per column.
61
+ * If you select button with number 4 and navigate right, the buttons
62
+ * will be navigated in the following order 4->5->6.
63
+ * The flow is maintained for the Y axis while you're navigating the X axis.
64
+ */
38
65
  MAINTAIN_Y,
66
+
67
+ /**
68
+ * Give focus to the first child element with `preferredFocus == true` prop.
69
+ */
39
70
  PREFERRED_CHILD,
40
71
  }
41
72
  export interface GamepadEventDetail {
@@ -48,6 +79,25 @@ export declare type ActionDescriptionMap = {
48
79
  };
49
80
  export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
50
81
  export interface FooterLegendProps {
82
+ /**
83
+ * Navigation entry strategy to be used when gaining focus during navigation.
84
+ *
85
+ * This is meant to be used on a parent container that has children. Once the
86
+ * container (e.g. Focusable) is navigated to and has children in it, the children
87
+ * is then navigated to (focused) using the provided strategy.
88
+ *
89
+ * If no strategy is provided, it seems that the `NavEntryPositionPreferences.FIRST`
90
+ * is used initialy, but for the next time the parent remembers previously focused
91
+ * child and focused back on it instead.
92
+ */
93
+ navEntryPreferPosition?: NavEntryPositionPreferences;
94
+
95
+ /**
96
+ * Mark the element as the preferred child (to be focused) whenever the parent uses the
97
+ * `NavEntryPositionPreferences.PREFERRED_CHILD` navigation strategy.
98
+ */
99
+ preferredFocus?: boolean;
100
+
51
101
  actionDescriptionMap?: ActionDescriptionMap;
52
102
  onOKActionDescription?: ReactNode;
53
103
  onCancelActionDescription?: ReactNode;
@@ -26,7 +26,7 @@ export interface MenuGroupProps {
26
26
  }
27
27
 
28
28
  const MenuGoupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`));
29
- export const MenuGroup: FC<MenuGroupProps> = MenuGoupModule && Object.values(MenuGoupModule).find((e: Export) => typeof e == "function" && e?.toString()?.includes("bInGamepadUI:"));
29
+ export const MenuGroup: FC<MenuGroupProps> = MenuGoupModule && Object.values(MenuGoupModule).find((e: Export) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
30
30
  export interface MenuItemProps extends FooterLegendProps {
31
31
  bInteractableItem?: boolean;
32
32
  onClick?(evt: Event): void;
@@ -42,7 +42,7 @@ export interface MenuItemProps extends FooterLegendProps {
42
42
 
43
43
  export const MenuItem: FC<MenuItemProps> = findModuleExport(
44
44
  (e: Export) =>
45
- e?.render?.toString()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter),
45
+ e?.render?.toString?.()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter),
46
46
  );
47
47
 
48
48
  /*
@@ -98,7 +98,7 @@ export const ModalRoot = Object.values(
98
98
 
99
99
  return false;
100
100
  }) || {},
101
- )?.find((x: any) => x?.type?.toString()?.includes('((function(){')) as FC<ModalRootProps>;
101
+ )?.find((x: any) => x?.type?.toString?.()?.includes('((function(){')) as FC<ModalRootProps>;
102
102
 
103
103
  interface SimpleModalProps {
104
104
  active?: boolean;
@@ -22,5 +22,5 @@ export interface PanelSectionRowProps {
22
22
  children?: ReactNode;
23
23
  }
24
24
  export const PanelSectionRow = Object.values(mod).filter(
25
- (exp: any) => !exp?.toString()?.includes('.PanelSection'),
25
+ (exp: any) => !exp?.toString?.()?.includes('.PanelSection'),
26
26
  )[0] as FC<PanelSectionRowProps>;
@@ -24,11 +24,11 @@ export interface ProgressBarWithInfoProps extends ProgressBarItemProps {
24
24
  }
25
25
 
26
26
  export const ProgressBar = findModuleExport((e: Export) =>
27
- e?.toString()?.includes('.ProgressBar,"standard"=='),
27
+ e?.toString?.()?.includes('.ProgressBar,"standard"=='),
28
28
  ) as FC<ProgressBarProps>;
29
29
 
30
30
  export const ProgressBarWithInfo = findModuleExport((e: Export) =>
31
- e?.toString()?.includes('.ProgressBarFieldStatus},'),
31
+ e?.toString?.()?.includes('.ProgressBarFieldStatus},'),
32
32
  ) as FC<ProgressBarWithInfoProps>;
33
33
 
34
34
  const progressBarItemRegex = createPropListRegex(["indeterminate", "nTransitionSec", "nProgress"]);
@@ -30,5 +30,5 @@ export interface SliderFieldProps extends ItemProps {
30
30
 
31
31
  export const SliderField = Object.values(CommonUIModule).find((mod: any) =>
32
32
  // stable || beta as of oct 2 2024
33
- mod?.toString()?.includes('SliderField,fallback') || mod?.toString()?.includes("SliderField\",")
33
+ mod?.toString?.()?.includes('SliderField,fallback') || mod?.toString?.()?.includes("SliderField\",")
34
34
  ) as FC<SliderFieldProps>;
@@ -62,9 +62,9 @@ export interface TabsProps {
62
62
  autoFocusContents?: boolean;
63
63
  }
64
64
 
65
- const tabsModule = findModuleByExport(e => e?.toString()?.includes(".TabRowTabs") && e?.toString()?.includes("activeTab:"));
65
+ const tabsModule = findModuleByExport(e => e?.toString?.()?.includes(".TabRowTabs") && e?.toString?.()?.includes("activeTab:"));
66
66
 
67
67
  /**
68
68
  * Tabs component as used in the library and media tabs. See {@link TabsProps}.
69
69
  */
70
- export const Tabs = tabsModule && Object.values(tabsModule).find((e: any) => e?.type?.toString()?.includes("((function()")) as FC<TabsProps>;
70
+ export const Tabs = tabsModule && Object.values(tabsModule).find((e: any) => e?.type?.toString?.()?.includes("((function()")) as FC<TabsProps>;
@@ -10,5 +10,5 @@ export interface ToggleProps {
10
10
  }
11
11
 
12
12
  export const Toggle = Object.values(CommonUIModule).find((mod: any) =>
13
- mod?.render?.toString()?.includes('.ToggleOff)'),
13
+ mod?.render?.toString?.()?.includes('.ToggleOff)'),
14
14
  ) as FC<ToggleProps>;
@@ -12,5 +12,5 @@ export interface ToggleFieldProps extends ItemProps {
12
12
 
13
13
  export const ToggleField = Object.values(CommonUIModule).find((mod: any) =>
14
14
  // stable || beta as of oct 2 2024
15
- mod?.render?.toString()?.includes('ToggleField,fallback') || mod?.render?.toString()?.includes("ToggleField\",")
15
+ mod?.render?.toString?.()?.includes('ToggleField,fallback') || mod?.render?.toString?.()?.includes("ToggleField\",")
16
16
  ) as FC<ToggleFieldProps>;