@decky/ui 4.0.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.
Files changed (150) hide show
  1. package/LICENSE +504 -0
  2. package/README.md +27 -0
  3. package/dist/class-mapper.d.ts +7 -0
  4. package/dist/class-mapper.js +26 -0
  5. package/dist/components/Button.d.ts +5 -0
  6. package/dist/components/Button.js +2 -0
  7. package/dist/components/ButtonItem.d.ts +7 -0
  8. package/dist/components/ButtonItem.js +3 -0
  9. package/dist/components/Carousel.d.ts +19 -0
  10. package/dist/components/Carousel.js +2 -0
  11. package/dist/components/ControlsList.d.ts +6 -0
  12. package/dist/components/ControlsList.js +2 -0
  13. package/dist/components/Dialog.d.ts +32 -0
  14. package/dist/components/Dialog.js +19 -0
  15. package/dist/components/DialogCheckbox.d.ts +17 -0
  16. package/dist/components/DialogCheckbox.js +14 -0
  17. package/dist/components/Dropdown.d.ts +34 -0
  18. package/dist/components/Dropdown.js +3 -0
  19. package/dist/components/Field.d.ts +22 -0
  20. package/dist/components/Field.js +2 -0
  21. package/dist/components/FocusRing.d.ts +9 -0
  22. package/dist/components/FocusRing.js +2 -0
  23. package/dist/components/Focusable.d.ts +12 -0
  24. package/dist/components/Focusable.js +2 -0
  25. package/dist/components/FooterLegend.d.ts +66 -0
  26. package/dist/components/FooterLegend.js +32 -0
  27. package/dist/components/Item.d.ts +11 -0
  28. package/dist/components/Item.js +1 -0
  29. package/dist/components/Marquee.d.ts +14 -0
  30. package/dist/components/Marquee.js +2 -0
  31. package/dist/components/Menu.d.ts +29 -0
  32. package/dist/components/Menu.js +8 -0
  33. package/dist/components/Modal.d.ts +52 -0
  34. package/dist/components/Modal.js +29 -0
  35. package/dist/components/Panel.d.ts +11 -0
  36. package/dist/components/Panel.js +4 -0
  37. package/dist/components/ProgressBar.d.ts +21 -0
  38. package/dist/components/ProgressBar.js +4 -0
  39. package/dist/components/Scroll.d.ts +7 -0
  40. package/dist/components/Scroll.js +5 -0
  41. package/dist/components/SidebarNavigation.d.ts +21 -0
  42. package/dist/components/SidebarNavigation.js +2 -0
  43. package/dist/components/SliderField.d.ts +26 -0
  44. package/dist/components/SliderField.js +2 -0
  45. package/dist/components/Spinner.d.ts +2 -0
  46. package/dist/components/Spinner.js +2 -0
  47. package/dist/components/SteamSpinner.d.ts +2 -0
  48. package/dist/components/SteamSpinner.js +2 -0
  49. package/dist/components/Tabs.d.ts +16 -0
  50. package/dist/components/Tabs.js +48 -0
  51. package/dist/components/TextField.d.ts +22 -0
  52. package/dist/components/TextField.js +2 -0
  53. package/dist/components/Toggle.d.ts +8 -0
  54. package/dist/components/Toggle.js +2 -0
  55. package/dist/components/ToggleField.d.ts +9 -0
  56. package/dist/components/ToggleField.js +2 -0
  57. package/dist/components/index.d.ts +25 -0
  58. package/dist/components/index.js +25 -0
  59. package/dist/custom-components/ColorPickerModal.d.ts +12 -0
  60. package/dist/custom-components/ColorPickerModal.js +87 -0
  61. package/dist/custom-components/ReorderableList.d.ts +26 -0
  62. package/dist/custom-components/ReorderableList.js +84 -0
  63. package/dist/custom-components/SuspensefulImage.d.ts +7 -0
  64. package/dist/custom-components/SuspensefulImage.js +27 -0
  65. package/dist/custom-components/index.d.ts +3 -0
  66. package/dist/custom-components/index.js +3 -0
  67. package/dist/custom-hooks/index.d.ts +1 -0
  68. package/dist/custom-hooks/index.js +1 -0
  69. package/dist/custom-hooks/useQuickAccessVisible.d.ts +1 -0
  70. package/dist/custom-hooks/useQuickAccessVisible.js +22 -0
  71. package/dist/deck-hooks/index.d.ts +1 -0
  72. package/dist/deck-hooks/index.js +1 -0
  73. package/dist/deck-hooks/useParams.d.ts +1 -0
  74. package/dist/deck-hooks/useParams.js +2 -0
  75. package/dist/globals/SteamClient.d.ts +307 -0
  76. package/dist/globals/SteamClient.js +1 -0
  77. package/dist/globals/index.d.ts +2 -0
  78. package/dist/globals/index.js +2 -0
  79. package/dist/globals/stores.d.ts +50 -0
  80. package/dist/globals/stores.js +1 -0
  81. package/dist/index.d.ts +10 -0
  82. package/dist/index.js +10 -0
  83. package/dist/logger.d.ts +17 -0
  84. package/dist/logger.js +46 -0
  85. package/dist/modules/Router.d.ts +110 -0
  86. package/dist/modules/Router.js +102 -0
  87. package/dist/modules/index.d.ts +1 -0
  88. package/dist/modules/index.js +1 -0
  89. package/dist/plugin.d.ts +68 -0
  90. package/dist/plugin.js +5 -0
  91. package/dist/utils/index.d.ts +12 -0
  92. package/dist/utils/index.js +23 -0
  93. package/dist/utils/patcher.d.ts +18 -0
  94. package/dist/utils/patcher.js +103 -0
  95. package/dist/utils/react.d.ts +18 -0
  96. package/dist/utils/react.js +74 -0
  97. package/dist/utils/static-classes.d.ts +52 -0
  98. package/dist/utils/static-classes.js +28 -0
  99. package/dist/webpack.d.ts +21 -0
  100. package/dist/webpack.js +102 -0
  101. package/package.json +82 -0
  102. package/src/class-mapper.ts +34 -0
  103. package/src/components/Button.tsx +8 -0
  104. package/src/components/ButtonItem.tsx +14 -0
  105. package/src/components/Carousel.ts +25 -0
  106. package/src/components/ControlsList.tsx +13 -0
  107. package/src/components/Dialog.tsx +86 -0
  108. package/src/components/DialogCheckbox.tsx +36 -0
  109. package/src/components/Dropdown.tsx +49 -0
  110. package/src/components/Field.tsx +28 -0
  111. package/src/components/FocusRing.ts +15 -0
  112. package/src/components/Focusable.tsx +18 -0
  113. package/src/components/FooterLegend.ts +67 -0
  114. package/src/components/Item.tsx +12 -0
  115. package/src/components/Marquee.tsx +20 -0
  116. package/src/components/Menu.tsx +57 -0
  117. package/src/components/Modal.tsx +119 -0
  118. package/src/components/Panel.tsx +26 -0
  119. package/src/components/ProgressBar.tsx +35 -0
  120. package/src/components/Scroll.tsx +15 -0
  121. package/src/components/SidebarNavigation.tsx +28 -0
  122. package/src/components/SliderField.tsx +33 -0
  123. package/src/components/Spinner.tsx +8 -0
  124. package/src/components/SteamSpinner.tsx +7 -0
  125. package/src/components/Tabs.tsx +127 -0
  126. package/src/components/TextField.tsx +28 -0
  127. package/src/components/Toggle.tsx +14 -0
  128. package/src/components/ToggleField.tsx +15 -0
  129. package/src/components/index.ts +25 -0
  130. package/src/custom-components/ColorPickerModal.tsx +132 -0
  131. package/src/custom-components/ReorderableList.tsx +183 -0
  132. package/src/custom-components/SuspensefulImage.tsx +44 -0
  133. package/src/custom-components/index.ts +3 -0
  134. package/src/custom-hooks/index.ts +1 -0
  135. package/src/custom-hooks/useQuickAccessVisible.tsx +63 -0
  136. package/src/deck-hooks/index.ts +1 -0
  137. package/src/deck-hooks/useParams.ts +15 -0
  138. package/src/globals/SteamClient.ts +321 -0
  139. package/src/globals/index.ts +2 -0
  140. package/src/globals/stores.ts +50 -0
  141. package/src/index.ts +11 -0
  142. package/src/logger.ts +77 -0
  143. package/src/modules/Router.tsx +174 -0
  144. package/src/modules/index.ts +1 -0
  145. package/src/plugin.tsx +96 -0
  146. package/src/utils/index.ts +43 -0
  147. package/src/utils/patcher.ts +160 -0
  148. package/src/utils/react.ts +119 -0
  149. package/src/utils/static-classes.ts +1104 -0
  150. package/src/webpack.ts +136 -0
@@ -0,0 +1,183 @@
1
+ import { Fragment, JSXElementConstructor, ReactElement, ReactNode, useEffect, useState } from 'react';
2
+
3
+ import { Field, FieldProps, Focusable, GamepadButton } from '../components';
4
+
5
+ /**
6
+ * A ReorderableList entry of type <T>.
7
+ * @param label The name of this entry in the list.
8
+ * @param data Optional data to connect to this entry.
9
+ * @param position The position of this entry in the list.
10
+ */
11
+ export type ReorderableEntry<T> = {
12
+ label: ReactNode;
13
+ data?: T;
14
+ position: number;
15
+ };
16
+
17
+ /**
18
+ * Properties for a ReorderableList component of type <T>.
19
+ *
20
+ * @param animate If the list should animate. @default true
21
+ */
22
+ export type ReorderableListProps<T> = {
23
+ entries: ReorderableEntry<T>[];
24
+ onSave: (entries: ReorderableEntry<T>[]) => void;
25
+ interactables?: JSXElementConstructor<{ entry: ReorderableEntry<T> }>;
26
+ fieldProps?: FieldProps;
27
+ animate?: boolean;
28
+ };
29
+
30
+ /**
31
+ * A component for creating reorderable lists.
32
+ *
33
+ * See an example implementation {@linkplain https://github.com/Tormak9970/Component-Testing-Plugin/blob/main/src/testing-window/ReorderableListTest.tsx here}.
34
+ */
35
+ export function ReorderableList<T>(props: ReorderableListProps<T>) {
36
+ if (props.animate === undefined) props.animate = true;
37
+ const [entryList, setEntryList] = useState<ReorderableEntry<T>[]>(
38
+ props.entries.sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position),
39
+ );
40
+ const [reorderEnabled, setReorderEnabled] = useState<boolean>(false);
41
+
42
+ useEffect(() => {
43
+ setEntryList(props.entries.sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position));
44
+ }, [props.entries]);
45
+
46
+ function toggleReorderEnabled(): void {
47
+ let newReorderValue = !reorderEnabled;
48
+ setReorderEnabled(newReorderValue);
49
+
50
+ if (!newReorderValue) {
51
+ props.onSave(entryList);
52
+ }
53
+ }
54
+
55
+ function saveOnBackout(e: Event) {
56
+ const event = e as CustomEvent;
57
+ if (event.detail.button == GamepadButton.CANCEL && reorderEnabled) {
58
+ setReorderEnabled(!reorderEnabled);
59
+ props.onSave(entryList);
60
+ }
61
+ }
62
+
63
+ return (
64
+ <Fragment>
65
+ <div
66
+ style={{
67
+ width: 'inherit',
68
+ height: 'inherit',
69
+ flex: '1 1 1px',
70
+ scrollPadding: '48px 0px',
71
+ display: 'flex',
72
+ flexDirection: 'column',
73
+ justifyContent: 'flex-start',
74
+ alignContent: 'stretch',
75
+ }}
76
+ >
77
+ <Focusable
78
+ onSecondaryButton={toggleReorderEnabled}
79
+ onSecondaryActionDescription={reorderEnabled ? 'Save Order' : 'Reorder'}
80
+ onClick={toggleReorderEnabled}
81
+ onButtonDown={saveOnBackout}
82
+ >
83
+ {entryList.map((entry: ReorderableEntry<T>) => (
84
+ <ReorderableItem
85
+ animate={props.animate!}
86
+ listData={entryList}
87
+ entryData={entry}
88
+ reorderEntryFunc={setEntryList}
89
+ reorderEnabled={reorderEnabled}
90
+ fieldProps={props.fieldProps}
91
+ >
92
+ {props.interactables ? <props.interactables entry={entry} /> : null}
93
+ </ReorderableItem>
94
+ ))}
95
+ </Focusable>
96
+ </div>
97
+ </Fragment>
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Properties for a ReorderableItem component of type <T>
103
+ */
104
+ export type ReorderableListEntryProps<T> = {
105
+ fieldProps?: FieldProps;
106
+ listData: ReorderableEntry<T>[];
107
+ entryData: ReorderableEntry<T>;
108
+ reorderEntryFunc: CallableFunction;
109
+ reorderEnabled: boolean;
110
+ animate: boolean;
111
+ children: ReactElement | null;
112
+ };
113
+
114
+ function ReorderableItem<T>(props: ReorderableListEntryProps<T>) {
115
+ const [isSelected, _setIsSelected] = useState<boolean>(false);
116
+ const [isSelectedLastFrame, setIsSelectedLastFrame] = useState<boolean>(false);
117
+ const listEntries = props.listData;
118
+
119
+ function onReorder(e: Event): void {
120
+ if (!props.reorderEnabled) return;
121
+
122
+ const event = e as CustomEvent;
123
+ const currentIdx = listEntries.findIndex((entryData: ReorderableEntry<T>) => entryData === props.entryData);
124
+ const currentIdxValue = listEntries[currentIdx];
125
+ if (currentIdx < 0) return;
126
+
127
+ let targetPosition: number = -1;
128
+ if (event.detail.button == GamepadButton.DIR_DOWN) {
129
+ targetPosition = currentIdxValue.position + 1;
130
+ } else if (event.detail.button == GamepadButton.DIR_UP) {
131
+ targetPosition = currentIdxValue.position - 1;
132
+ }
133
+
134
+ if (targetPosition >= listEntries.length || targetPosition < 0) return;
135
+
136
+ let otherToUpdate = listEntries.find((entryData: ReorderableEntry<T>) => entryData.position === targetPosition);
137
+ if (!otherToUpdate) return;
138
+
139
+ let currentPosition = currentIdxValue.position;
140
+
141
+ currentIdxValue.position = otherToUpdate.position;
142
+ otherToUpdate.position = currentPosition;
143
+
144
+ props.reorderEntryFunc(
145
+ [...listEntries].sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position),
146
+ );
147
+ }
148
+
149
+ async function setIsSelected(val: boolean) {
150
+ _setIsSelected(val);
151
+ // Wait 3 frames, then set. I have no idea why, but if you dont wait long enough it doesn't work.
152
+ for (let i = 0; i < 3; i++) await new Promise((res) => requestAnimationFrame(res));
153
+ setIsSelectedLastFrame(val);
154
+ }
155
+
156
+ return (
157
+ <div
158
+ style={
159
+ props.animate
160
+ ? {
161
+ transition:
162
+ isSelected || isSelectedLastFrame
163
+ ? ''
164
+ : 'transform 0.3s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1)', // easeOutQuart https://easings.net/#easeOutQuart
165
+ transform: !props.reorderEnabled || isSelected ? 'scale(1)' : 'scale(0.9)',
166
+ opacity: !props.reorderEnabled || isSelected ? 1 : 0.7,
167
+ }
168
+ : {}
169
+ }
170
+ >
171
+ <Field
172
+ label={props.entryData.label}
173
+ {...props.fieldProps}
174
+ focusable={!props.children}
175
+ onButtonDown={onReorder}
176
+ onGamepadBlur={() => setIsSelected(false)}
177
+ onGamepadFocus={() => setIsSelected(true)}
178
+ >
179
+ <Focusable style={{ display: 'flex', width: '100%', position: 'relative' }}>{props.children}</Focusable>
180
+ </Field>
181
+ </div>
182
+ );
183
+ }
@@ -0,0 +1,44 @@
1
+ import { useEffect } from 'react';
2
+ import { FC, ImgHTMLAttributes, useState } from 'react';
3
+
4
+ import { Spinner } from '../components';
5
+
6
+ interface SuspensefulImageProps extends ImgHTMLAttributes<HTMLImageElement> {
7
+ suspenseWidth?: string | number;
8
+ suspenseHeight?: string | number;
9
+ }
10
+
11
+ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
12
+ const [loading, setLoading] = useState(true);
13
+ const [error, setError] = useState(false);
14
+
15
+ useEffect(() => {
16
+ setLoading(true);
17
+ setError(false);
18
+ const img = new Image();
19
+ img.src = props.src || '';
20
+ img.addEventListener('load', () => {
21
+ setLoading(false);
22
+ });
23
+ img.addEventListener('error', () => {
24
+ setError(true);
25
+ });
26
+ }, [props.src]);
27
+
28
+ return loading ? (
29
+ <div
30
+ style={{
31
+ width: props.suspenseWidth || props.style?.width,
32
+ height: props.suspenseHeight || props.style?.height,
33
+ background: 'rgba(255, 255, 255, 0.2)',
34
+ display: 'flex',
35
+ alignItems: 'center',
36
+ justifyContent: 'center',
37
+ }}
38
+ >
39
+ {error ? 'Missing image' : <Spinner style={{ height: '48px' }} />}
40
+ </div>
41
+ ) : (
42
+ <img {...props} />
43
+ );
44
+ };
@@ -0,0 +1,3 @@
1
+ export * from './SuspensefulImage';
2
+ export * from './ColorPickerModal';
3
+ export * from './ReorderableList';
@@ -0,0 +1 @@
1
+ export * from './useQuickAccessVisible';
@@ -0,0 +1,63 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import { getGamepadNavigationTrees } from '../utils';
4
+
5
+ function getQuickAccessWindow(): Window | null {
6
+ const navTrees = getGamepadNavigationTrees();
7
+ return (
8
+ navTrees.find((tree: any) => tree?.id === 'QuickAccess-NA')?.m_Root?.m_element?.ownerDocument.defaultView ?? null
9
+ );
10
+ }
11
+
12
+ /**
13
+ * Returns state indicating the visibility of quick access menu.
14
+ *
15
+ * @returns `true` if quick access menu is visible and `false` otherwise.
16
+ *
17
+ * @example
18
+ * import { VFC, useEffect } from "react";
19
+ * import { useQuickAccessVisible } from "decky-frontend-lib";
20
+ *
21
+ * export const PluginPanelView: VFC<{}> = ({ }) => {
22
+ * const isVisible = useQuickAccessVisible();
23
+ *
24
+ * useEffect(() => {
25
+ * if (!isVisible) {
26
+ * return;
27
+ * }
28
+ *
29
+ * const interval = setInterval(() => console.log("Hello world!"), 1000);
30
+ * return () => {
31
+ * clearInterval(interval);
32
+ * }
33
+ * }, [isVisible])
34
+ *
35
+ * return (
36
+ * <div>
37
+ * {isVisible ? "VISIBLE" : "INVISIBLE"}
38
+ * </div>
39
+ * );
40
+ * };
41
+ */
42
+ export function useQuickAccessVisible(): boolean {
43
+ // By default we say that document is not hidden, unless we know otherwise.
44
+ // This would cover the cases when Valve breaks something and the quick access window
45
+ // cannot be accessed anymore - the plugins that use this would continue working somewhat.
46
+ const [isHidden, setIsHidden] = useState(getQuickAccessWindow()?.document.hidden ?? false);
47
+
48
+ useEffect(() => {
49
+ const quickAccessWindow = getQuickAccessWindow();
50
+ if (quickAccessWindow === null) {
51
+ console.error('Could not get window of QuickAccess menu!');
52
+ return;
53
+ }
54
+
55
+ const onVisibilityChange = () => setIsHidden(quickAccessWindow.document.hidden);
56
+ quickAccessWindow.addEventListener('visibilitychange', onVisibilityChange);
57
+ return () => {
58
+ quickAccessWindow.removeEventListener('visibilitychange', onVisibilityChange);
59
+ };
60
+ }, []);
61
+
62
+ return !isHidden;
63
+ }
@@ -0,0 +1 @@
1
+ export * from './useParams';
@@ -0,0 +1,15 @@
1
+ import { ReactRouter } from '../webpack';
2
+
3
+ /**
4
+ * Get the current params from ReactRouter
5
+ *
6
+ * @returns an object with the current ReactRouter params
7
+ *
8
+ * @example
9
+ * import { useParams } from "decky-frontend-lib";
10
+ *
11
+ * const { appid } = useParams<{ appid: string }>()
12
+ */
13
+ export const useParams = Object.values(ReactRouter).find((val) => /return (\w)\?\1\.params:{}/.test(`${val}`)) as <
14
+ T,
15
+ >() => T;
@@ -0,0 +1,321 @@
1
+ declare global {
2
+ var SteamClient: SteamClient;
3
+ }
4
+
5
+ export interface Apps {
6
+ RegisterForAppOverviewChanges: any;
7
+ RegisterForAppDetails: any;
8
+ RegisterForLocalizationChanges: any;
9
+ RegisterForWorkshopChanges: any;
10
+ RegisterForWorkshopItemDownloads: any;
11
+ GetLibraryBootstrapData: any;
12
+ RegisterForAchievementChanges: any;
13
+ GetFriendAchievementsForApp: any;
14
+ GetMyAchievementsForApp: any;
15
+ AddUserTagToApps: any;
16
+ RemoveUserTagFromApps: any;
17
+ ClearUserTagsOnApps: any;
18
+ ClearAndSetUserTagsOnApp: any;
19
+ SetAppHidden: any;
20
+ ResetHiddenState: any;
21
+ SetAppLaunchOptions: any;
22
+ SetAppResolutionOverride: any;
23
+ SetAppCurrentLanguage: any;
24
+ SetAppAutoUpdateBehavior: any;
25
+ SetAppBackgroundDownloadsBehavior: any;
26
+ ToggleAppFamilyBlockedState: any;
27
+ ToggleAppSteamCloudEnabled: any;
28
+ ToggleAppSteamCloudSyncOnSuspendEnabled: any;
29
+ ToggleOverrideResolutionForInternalDisplay: any;
30
+ ToggleEnableSteamOverlayForApp: any;
31
+ ToggleEnableDesktopTheatreForApp: any;
32
+ BrowseLocalFilesForApp: any;
33
+ BrowseScreenshotsForApp: any;
34
+ BrowseScreenshotForApp: any;
35
+ BackupFilesForApp: any;
36
+ VerifyFilesForApp: any;
37
+ CreateDesktopShortcutForApp: any;
38
+ JoinAppContentBeta: any;
39
+ JoinAppContentBetaByPassword: any;
40
+ GetAchievementsInTimeRange: any;
41
+ GetSubscribedWorkshopItems: any;
42
+ SubscribeWorkshopItem: any;
43
+ GetDownloadedWorkshopItems: any;
44
+ DownloadWorkshopItem: any;
45
+ SetLocalScreenshotCaption: any;
46
+ SetLocalScreenshotSpoiler: any;
47
+ GetDetailsForScreenshotUpload: any;
48
+ UploadLocalScreenshot: any;
49
+ DeleteLocalScreenshot: any;
50
+ GetScreenshotsInTimeRange: any;
51
+ GetFriendsWhoPlay: any;
52
+ RequestLegacyCDKeysForApp: any;
53
+ GetSoundtrackDetails: any;
54
+ GetStoreTagLocalization: any;
55
+ GetLaunchOptionsForApp: any;
56
+ GetResolutionOverrideForApp: any;
57
+ ScanForShortcuts: any;
58
+ GetAllShortcuts: any;
59
+ GetShortcutData: any;
60
+ AddShortcut: any;
61
+ RemoveShortcut: any;
62
+ InstallFlatpakAppAndCreateShortcut: any;
63
+ ListFlatpakApps: any;
64
+ UninstallFlatpakApp: any;
65
+ ShowControllerConfigurator: any;
66
+ SetThirdPartyControllerConfiguration: any;
67
+ ToggleAllowDesktopConfiguration: any;
68
+ SetControllerRumblePreference: any;
69
+ GetCachedAppDetails: any;
70
+ SetCachedAppDetails: any;
71
+ ReportLibraryAssetCacheMiss: any;
72
+ SaveAchievementProgressCache: any;
73
+ SetStreamingClientForApp: any;
74
+ SetCustomArtworkForApp: any;
75
+ ClearCustomArtworkForApp: any;
76
+ SetCustomLogoPositionForApp: any;
77
+ ClearCustomLogoPositionForApp: any;
78
+ RequestIconDataForApp: any;
79
+ SpecifyCompatTool: any;
80
+ GetAvailableCompatTools: any;
81
+ SetShortcutName: any;
82
+ SetShortcutExe: any;
83
+ SetShortcutStartDir: any;
84
+ SetShortcutLaunchOptions: any;
85
+ SetShortcutIsVR: any;
86
+ PromptToChangeShortcut: any;
87
+ PromptToSelectShortcutIcon: any;
88
+ InstallApp: any;
89
+ RunGame: any;
90
+ VerifyApp: any;
91
+ StreamGame: any;
92
+ CancelLaunch: any;
93
+ TerminateApp: any;
94
+ UninstallApps: any;
95
+ ShowStore: any;
96
+ SetDLCEnabled: any;
97
+ ContinueGameAction: any;
98
+ CancelGameAction: any;
99
+ GetActiveGameActions: any;
100
+ GetGameActionDetails: any;
101
+ GetGameActionForApp: any;
102
+ SkipShaderProcessing: any;
103
+ MarkEulaAccepted: any;
104
+ MarkEulaRejected: any;
105
+ LoadEula: any;
106
+ GetConflictingFileTimestamps: any;
107
+ GetCloudPendingRemoteOperations: any;
108
+ ClearProton: any;
109
+ RegisterForMarketingMessages: any;
110
+ FetchMarketingMessages: any;
111
+ MarkMarketingMessageSeen: any;
112
+ ReportMarketingMessageSeen: any;
113
+ RegisterForGameActionStart: any;
114
+ RegisterForGameActionEnd: any;
115
+ RegisterForGameActionTaskChange: any;
116
+ RegisterForGameActionUserRequest: any;
117
+ RegisterForGameActionShowError: any;
118
+ RegisterForGameActionShowUI: any;
119
+ OpenAppSettingsDialog: any;
120
+ }
121
+
122
+ export interface Window {
123
+ RegisterForExternalDisplayChanged: any;
124
+ SetManualDisplayScaleFactor: any;
125
+ SetAutoDisplayScale: any;
126
+ Minimize: any;
127
+ ProcessShuttingDown: any;
128
+ ToggleMaximize: any;
129
+ MoveTo: any;
130
+ ResizeTo: any;
131
+ SetMinSize: any;
132
+ SetResizeGrip: any;
133
+ SetComposition: any;
134
+ GamescopeBlur: any;
135
+ BringToFront: any;
136
+ SetForegroundWindow: any;
137
+ SetKeyFocus: any;
138
+ FlashWindow: any;
139
+ StopFlashWindow: any;
140
+ ShowWindow: any;
141
+ HideWindow: any;
142
+ SetWindowIcon: any;
143
+ GetWindowDimensions: any;
144
+ GetWindowRestoreDetails: any;
145
+ PositionWindowRelative: any;
146
+ GetMousePositionDetails: any;
147
+ IsWindowMinimized: any;
148
+ GetBrowserID: any;
149
+ }
150
+
151
+ export interface SteamClient {
152
+ Apps: Apps;
153
+ Browser: any;
154
+ BrowserView: any;
155
+ ClientNotifications: any;
156
+ Cloud: any;
157
+ Console: any;
158
+ Downloads: any;
159
+ FamilySharing: any;
160
+ FriendSettings: any;
161
+ Friends: any;
162
+ GameSessions: any;
163
+ Input: any;
164
+ InstallFolder: any;
165
+ Installs: any;
166
+ MachineStorage: any;
167
+ Messaging: any;
168
+ Notifications: any;
169
+ OpenVR: any;
170
+ Overlay: any;
171
+ Parental: any;
172
+ RegisterIFrameNavigatedCallback: any;
173
+ RemotePlay: any;
174
+ RoamingStorage: any;
175
+ Screenshots: any;
176
+ Settings: any;
177
+ SharedConnection: any;
178
+ Stats: any;
179
+ Storage: any;
180
+ Streaming: any;
181
+ System: any;
182
+ UI: any;
183
+ URL: any;
184
+ Updates: any;
185
+ User: any;
186
+ WebChat: any;
187
+ Window: Window;
188
+ }
189
+
190
+ export interface SteamShortcut {
191
+ appid: number;
192
+ data: {
193
+ bIsApplication: boolean;
194
+ strAppName: string;
195
+ strExePath: string;
196
+ strArguments: string;
197
+ strShortcutPath: string;
198
+ strSortAs: string;
199
+ };
200
+ }
201
+
202
+ /**
203
+ * @prop unAppID is not properly set by Steam for non-steam game shortcuts, so it defaults to 0 for them
204
+ */
205
+ export interface LifetimeNotification {
206
+ unAppID: number;
207
+ nInstanceID: number;
208
+ bRunning: boolean;
209
+ }
210
+
211
+ export type AppAchievements = {
212
+ nAchieved: number;
213
+ nTotal: number;
214
+ vecAchievedHidden: any[];
215
+ vecHighlight: any[];
216
+ vecUnachieved: any[];
217
+ };
218
+
219
+ export type AppLanguages = {
220
+ strDisplayName: string;
221
+ strShortName: string;
222
+ };
223
+
224
+ export type LogoPinPositions = 'BottomLeft' | 'UpperLeft' | 'CenterCenter' | 'UpperCenter' | 'BottomCenter';
225
+
226
+ export interface LogoPosition {
227
+ pinnedPosition: LogoPinPositions;
228
+ nWidthPct: number;
229
+ nHeightPct: number;
230
+ }
231
+
232
+ export interface AppDetails {
233
+ achievements: AppAchievements;
234
+ bCanMoveInstallFolder: boolean;
235
+ bCloudAvailable: boolean;
236
+ bCloudEnabledForAccount: boolean;
237
+ bCloudEnabledForApp: boolean;
238
+ bCloudSyncOnSuspendAvailable: boolean;
239
+ bCloudSyncOnSuspendEnabled: boolean;
240
+ bCommunityMarketPresence: boolean;
241
+ bEnableAllowDesktopConfiguration: boolean;
242
+ bFreeRemovableLicense: boolean;
243
+ bHasAllLegacyCDKeys: boolean;
244
+ bHasAnyLocalContent: boolean;
245
+ bHasLockedPrivateBetas: boolean;
246
+ bIsExcludedFromSharing: boolean;
247
+ bIsSubscribedTo: boolean;
248
+ bOverlayEnabled: boolean;
249
+ bOverrideInternalResolution: boolean;
250
+ bRequiresLegacyCDKey: boolean;
251
+ bShortcutIsVR: boolean;
252
+ bShowCDKeyInMenus: boolean;
253
+ bShowControllerConfig: boolean;
254
+ bSupportsCDKeyCopyToClipboard: boolean;
255
+ bVRGameTheatreEnabled: boolean;
256
+ bWorkshopVisible: boolean;
257
+ eAppOwnershipFlags: number;
258
+ eAutoUpdateValue: number;
259
+ eBackgroundDownloads: number;
260
+ eCloudSync: number;
261
+ eControllerRumblePreference: number;
262
+ eDisplayStatus: number;
263
+ eEnableThirdPartyControllerConfiguration: number;
264
+ eSteamInputControllerMask: number;
265
+ iInstallFolder: number;
266
+ lDiskUsageBytes: number;
267
+ lDlcUsageBytes: number;
268
+ nBuildID: number;
269
+ nCompatToolPriority: number;
270
+ nPlaytimeForever: number;
271
+ nScreenshots: number;
272
+ rtLastTimePlayed: number;
273
+ rtLastUpdated: number;
274
+ rtPurchased: number;
275
+ selectedLanguage: {
276
+ strDisplayName: string;
277
+ strShortName: string;
278
+ };
279
+ strCloudBytesAvailable: string;
280
+ strCloudBytesUsed: string;
281
+ strCompatToolDisplayName: string;
282
+ strCompatToolName: string;
283
+ strDeveloperName: string;
284
+ strDeveloperURL: string;
285
+ strDisplayName: string;
286
+ strExternalSubscriptionURL: string;
287
+ strFlatpakAppID: string;
288
+ strHomepageURL: string;
289
+ strLaunchOptions: string;
290
+ strManualURL: string;
291
+ strOwnerSteamID: string;
292
+ strResolutionOverride: string;
293
+ strSelectedBeta: string;
294
+ strShortcutExe: string;
295
+ strShortcutLaunchOptions: string;
296
+ strShortcutStartDir: string;
297
+ strSteamDeckBlogURL: string;
298
+ unAppID: number;
299
+ vecBetas: any[];
300
+ vecDLC: any[];
301
+ vecDeckCompatTestResults: any[];
302
+ vecLanguages: AppLanguages[];
303
+ vecLegacyCDKeys: any[];
304
+ vecMusicAlbums: any[];
305
+ vecPlatforms: string[];
306
+ vecScreenShots: any[];
307
+ libraryAssets?: {
308
+ logoPosition?: LogoPosition;
309
+ };
310
+ }
311
+
312
+ export interface SteamAppOverview {
313
+ display_name: string;
314
+ gameid: string;
315
+ appid: number;
316
+ icon_hash: string;
317
+ third_party_mod?: boolean;
318
+ selected_clientid?: string;
319
+ BIsModOrShortcut: () => boolean;
320
+ BIsShortcut: () => boolean;
321
+ }
@@ -0,0 +1,2 @@
1
+ export * from './SteamClient';
2
+ export * from './stores';
@@ -0,0 +1,50 @@
1
+ import { AppDetails, LogoPosition, SteamAppOverview } from './SteamClient';
2
+ declare global {
3
+ interface Window {
4
+ LocalizationManager: {
5
+ m_mapTokens: Map<string, string>;
6
+ m_mapFallbackTokens: Map<string, string>;
7
+ m_rgLocalesToUse: string[];
8
+ };
9
+ App: {
10
+ m_CurrentUser: {
11
+ bIsLimited: boolean;
12
+ bIsOfflineMode: boolean;
13
+ bSupportAlertActive: boolean;
14
+ bCanInviteFriends: boolean;
15
+ NotificationCounts: {
16
+ comments: number;
17
+ inventory_items: number;
18
+ invites: number;
19
+ gifts: number;
20
+ offline_messages: number;
21
+ trade_offers: number;
22
+ async_game_updates: number;
23
+ moderator_messages: number;
24
+ help_request_replies: number;
25
+ };
26
+ strAccountBalance: string;
27
+ strAccountName: string;
28
+ strSteamID: string;
29
+ };
30
+ };
31
+ appStore: {
32
+ GetAppOverviewByAppID: (appId: number) => SteamAppOverview | null;
33
+ GetCustomVerticalCapsuleURLs: (app: SteamAppOverview) => string[];
34
+ GetCustomLandcapeImageURLs: (app: SteamAppOverview) => string[];
35
+ GetCustomHeroImageURLs: (app: SteamAppOverview) => string[];
36
+ GetCustomLogoImageURLs: (app: SteamAppOverview) => string[];
37
+ GetLandscapeImageURLForApp: (app: SteamAppOverview) => string;
38
+ GetVerticalCapsuleURLForApp: (app: SteamAppOverview) => string;
39
+ GetCachedLandscapeImageURLForApp: (app: SteamAppOverview) => string;
40
+ GetCachedVerticalImageURLForApp: (app: SteamAppOverview) => string;
41
+ GetPregeneratedVerticalCapsuleForApp: (app: SteamAppOverview) => string;
42
+ GetIconURLForApp: (app: SteamAppOverview) => string;
43
+ };
44
+ appDetailsStore: {
45
+ GetAppDetails: (appId: number) => AppDetails | null;
46
+ GetCustomLogoPosition: (app: SteamAppOverview) => LogoPosition | null;
47
+ SaveCustomLogoPosition: (app: SteamAppOverview, logoPositions: LogoPosition) => any;
48
+ };
49
+ }
50
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ // export * from './deck-libs';
2
+ export * from './custom-components';
3
+ export * from './custom-hooks';
4
+ export * from './components';
5
+ export * from './deck-hooks';
6
+ export * from './modules';
7
+ export * from './globals';
8
+ export * from './plugin';
9
+ export * from './webpack';
10
+ export * from './utils';
11
+ export * from './class-mapper';