@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.
- package/LICENSE +504 -0
- package/README.md +27 -0
- package/dist/class-mapper.d.ts +7 -0
- package/dist/class-mapper.js +26 -0
- package/dist/components/Button.d.ts +5 -0
- package/dist/components/Button.js +2 -0
- package/dist/components/ButtonItem.d.ts +7 -0
- package/dist/components/ButtonItem.js +3 -0
- package/dist/components/Carousel.d.ts +19 -0
- package/dist/components/Carousel.js +2 -0
- package/dist/components/ControlsList.d.ts +6 -0
- package/dist/components/ControlsList.js +2 -0
- package/dist/components/Dialog.d.ts +32 -0
- package/dist/components/Dialog.js +19 -0
- package/dist/components/DialogCheckbox.d.ts +17 -0
- package/dist/components/DialogCheckbox.js +14 -0
- package/dist/components/Dropdown.d.ts +34 -0
- package/dist/components/Dropdown.js +3 -0
- package/dist/components/Field.d.ts +22 -0
- package/dist/components/Field.js +2 -0
- package/dist/components/FocusRing.d.ts +9 -0
- package/dist/components/FocusRing.js +2 -0
- package/dist/components/Focusable.d.ts +12 -0
- package/dist/components/Focusable.js +2 -0
- package/dist/components/FooterLegend.d.ts +66 -0
- package/dist/components/FooterLegend.js +32 -0
- package/dist/components/Item.d.ts +11 -0
- package/dist/components/Item.js +1 -0
- package/dist/components/Marquee.d.ts +14 -0
- package/dist/components/Marquee.js +2 -0
- package/dist/components/Menu.d.ts +29 -0
- package/dist/components/Menu.js +8 -0
- package/dist/components/Modal.d.ts +52 -0
- package/dist/components/Modal.js +29 -0
- package/dist/components/Panel.d.ts +11 -0
- package/dist/components/Panel.js +4 -0
- package/dist/components/ProgressBar.d.ts +21 -0
- package/dist/components/ProgressBar.js +4 -0
- package/dist/components/Scroll.d.ts +7 -0
- package/dist/components/Scroll.js +5 -0
- package/dist/components/SidebarNavigation.d.ts +21 -0
- package/dist/components/SidebarNavigation.js +2 -0
- package/dist/components/SliderField.d.ts +26 -0
- package/dist/components/SliderField.js +2 -0
- package/dist/components/Spinner.d.ts +2 -0
- package/dist/components/Spinner.js +2 -0
- package/dist/components/SteamSpinner.d.ts +2 -0
- package/dist/components/SteamSpinner.js +2 -0
- package/dist/components/Tabs.d.ts +16 -0
- package/dist/components/Tabs.js +48 -0
- package/dist/components/TextField.d.ts +22 -0
- package/dist/components/TextField.js +2 -0
- package/dist/components/Toggle.d.ts +8 -0
- package/dist/components/Toggle.js +2 -0
- package/dist/components/ToggleField.d.ts +9 -0
- package/dist/components/ToggleField.js +2 -0
- package/dist/components/index.d.ts +25 -0
- package/dist/components/index.js +25 -0
- package/dist/custom-components/ColorPickerModal.d.ts +12 -0
- package/dist/custom-components/ColorPickerModal.js +87 -0
- package/dist/custom-components/ReorderableList.d.ts +26 -0
- package/dist/custom-components/ReorderableList.js +84 -0
- package/dist/custom-components/SuspensefulImage.d.ts +7 -0
- package/dist/custom-components/SuspensefulImage.js +27 -0
- package/dist/custom-components/index.d.ts +3 -0
- package/dist/custom-components/index.js +3 -0
- package/dist/custom-hooks/index.d.ts +1 -0
- package/dist/custom-hooks/index.js +1 -0
- package/dist/custom-hooks/useQuickAccessVisible.d.ts +1 -0
- package/dist/custom-hooks/useQuickAccessVisible.js +22 -0
- package/dist/deck-hooks/index.d.ts +1 -0
- package/dist/deck-hooks/index.js +1 -0
- package/dist/deck-hooks/useParams.d.ts +1 -0
- package/dist/deck-hooks/useParams.js +2 -0
- package/dist/globals/SteamClient.d.ts +307 -0
- package/dist/globals/SteamClient.js +1 -0
- package/dist/globals/index.d.ts +2 -0
- package/dist/globals/index.js +2 -0
- package/dist/globals/stores.d.ts +50 -0
- package/dist/globals/stores.js +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.js +46 -0
- package/dist/modules/Router.d.ts +110 -0
- package/dist/modules/Router.js +102 -0
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/plugin.d.ts +68 -0
- package/dist/plugin.js +5 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/patcher.d.ts +18 -0
- package/dist/utils/patcher.js +103 -0
- package/dist/utils/react.d.ts +18 -0
- package/dist/utils/react.js +74 -0
- package/dist/utils/static-classes.d.ts +52 -0
- package/dist/utils/static-classes.js +28 -0
- package/dist/webpack.d.ts +21 -0
- package/dist/webpack.js +102 -0
- package/package.json +82 -0
- package/src/class-mapper.ts +34 -0
- package/src/components/Button.tsx +8 -0
- package/src/components/ButtonItem.tsx +14 -0
- package/src/components/Carousel.ts +25 -0
- package/src/components/ControlsList.tsx +13 -0
- package/src/components/Dialog.tsx +86 -0
- package/src/components/DialogCheckbox.tsx +36 -0
- package/src/components/Dropdown.tsx +49 -0
- package/src/components/Field.tsx +28 -0
- package/src/components/FocusRing.ts +15 -0
- package/src/components/Focusable.tsx +18 -0
- package/src/components/FooterLegend.ts +67 -0
- package/src/components/Item.tsx +12 -0
- package/src/components/Marquee.tsx +20 -0
- package/src/components/Menu.tsx +57 -0
- package/src/components/Modal.tsx +119 -0
- package/src/components/Panel.tsx +26 -0
- package/src/components/ProgressBar.tsx +35 -0
- package/src/components/Scroll.tsx +15 -0
- package/src/components/SidebarNavigation.tsx +28 -0
- package/src/components/SliderField.tsx +33 -0
- package/src/components/Spinner.tsx +8 -0
- package/src/components/SteamSpinner.tsx +7 -0
- package/src/components/Tabs.tsx +127 -0
- package/src/components/TextField.tsx +28 -0
- package/src/components/Toggle.tsx +14 -0
- package/src/components/ToggleField.tsx +15 -0
- package/src/components/index.ts +25 -0
- package/src/custom-components/ColorPickerModal.tsx +132 -0
- package/src/custom-components/ReorderableList.tsx +183 -0
- package/src/custom-components/SuspensefulImage.tsx +44 -0
- package/src/custom-components/index.ts +3 -0
- package/src/custom-hooks/index.ts +1 -0
- package/src/custom-hooks/useQuickAccessVisible.tsx +63 -0
- package/src/deck-hooks/index.ts +1 -0
- package/src/deck-hooks/useParams.ts +15 -0
- package/src/globals/SteamClient.ts +321 -0
- package/src/globals/index.ts +2 -0
- package/src/globals/stores.ts +50 -0
- package/src/index.ts +11 -0
- package/src/logger.ts +77 -0
- package/src/modules/Router.tsx +174 -0
- package/src/modules/index.ts +1 -0
- package/src/plugin.tsx +96 -0
- package/src/utils/index.ts +43 -0
- package/src/utils/patcher.ts +160 -0
- package/src/utils/react.ts +119 -0
- package/src/utils/static-classes.ts +1104 -0
- 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 @@
|
|
|
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,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';
|