Compare commits

...

26 Commits

Author SHA1 Message Date
semantic-release-bot
af2d3a29e2 chore(release): 0.7.2 [CI SKIP] 2022-06-08 22:30:10 +00:00
AAGaming
e5e561edd6 fix(package): fix pnpm peer dependencies errors 2022-06-08 18:29:27 -04:00
semantic-release-bot
7111d18667 chore(release): 0.7.1 [CI SKIP] 2022-06-08 21:55:07 +00:00
AAGaming
24244f6e91 fix(spinners): add SVG props 2022-06-08 17:54:20 -04:00
AAGaming
dd5c42c57d fix(Router): add NavigateToStore to interface 2022-06-08 17:53:49 -04:00
semantic-release-bot
09ab2fed4b chore(release): 0.7.0 [CI SKIP] 2022-06-08 17:25:30 +00:00
Jonas Dellinger
4328385391 feat(components): added shared item-props, progressbar, and more types for slider 2022-06-08 19:24:53 +02:00
semantic-release-bot
3fe986aaba chore(release): 0.6.0 [CI SKIP] 2022-06-08 08:00:06 +00:00
Jonas Dellinger
bc2bec4b83 fix(husky): wrong script for husky caused problems when installing 2022-06-08 09:59:20 +02:00
Jonas Dellinger
a99fb4a22d feat(dropdown): add dropdown 2022-06-08 09:59:20 +02:00
Jonas Dellinger
d8794ef4d3 feat(sidebar-navigation): add sidebar navigation component 2022-06-08 09:59:20 +02:00
Jonas Dellinger
23ed5dd157 chore(textfield): remove console.log 2022-06-08 09:59:20 +02:00
semantic-release-bot
210b0389f7 chore(release): 0.5.1 [CI SKIP] 2022-06-06 21:33:48 +00:00
AAGaming
198f96abb5 Merge branch 'main' of github.com:steamdeckhomebrew/decky-frontend-lib 2022-06-06 17:33:08 -04:00
AAGaming
244ae128da fix(classes): switch static-classes to findModule 2022-06-06 17:33:05 -04:00
semantic-release-bot
377d7adde8 chore(release): 0.5.0 [CI SKIP] 2022-06-06 21:28:39 +00:00
AAGaming
f34b9de97f feat(utils): add joinClassNames util 2022-06-06 17:27:56 -04:00
semantic-release-bot
b5192cf590 chore(release): 0.4.2 [CI SKIP] 2022-06-06 21:21:44 +00:00
AAGaming
2e7b4b664a fix(classes): add gamepadDialogClasses and quickAccessControlsClasses 2022-06-06 17:20:55 -04:00
semantic-release-bot
b92e6a5b9d chore(release): 0.4.1 [CI SKIP] 2022-06-05 13:11:12 +00:00
Jonas Dellinger
32c355f2a7 fix(textfield): correct type for onChange callback 2022-06-05 15:10:23 +02:00
semantic-release-bot
747d70dcca chore(release): 0.4.0 [CI SKIP] 2022-06-05 13:08:53 +00:00
Jonas Dellinger
7f9dfc5910 fix(typings): export all prop types 2022-06-05 15:07:47 +02:00
Jonas Dellinger
a3c1a7c7b7 feat(textfield): extract TextField component 2022-06-05 15:06:06 +02:00
semantic-release-bot
fccfdd6f11 chore(release): 0.3.0 [CI SKIP] 2022-06-04 17:43:17 +00:00
AAGaming
f124480af8 feat(typings): add Navigate to router typings 2022-06-04 13:42:23 -04:00
20 changed files with 378 additions and 36 deletions

View File

@@ -1,3 +1,85 @@
## [0.7.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.7.1...v0.7.2) (2022-06-08)
### Bug Fixes
* **package:** fix pnpm peer dependencies errors ([e5e561e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e5e561edd67994b8c55f99c1228e47d77b1c2ee2))
## [0.7.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.7.0...v0.7.1) (2022-06-08)
### Bug Fixes
* **Router:** add NavigateToStore to interface ([dd5c42c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/dd5c42c57d9ce6266f56237607bf37d8b5bd3b4c))
* **spinners:** add SVG props ([24244f6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/24244f6e91e39a11bb964ee2779662084dcd0fd0))
# [0.7.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.6.0...v0.7.0) (2022-06-08)
### Features
* **components:** added shared item-props, progressbar, and more types for slider ([4328385](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/43283853916f3993d92f6841b12f7ee47667e75b))
# [0.6.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.5.1...v0.6.0) (2022-06-08)
### Bug Fixes
* **husky:** wrong script for husky caused problems when installing ([bc2bec4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bc2bec4b839d691e20beb090327a359c9e93f1cc))
### Features
* **dropdown:** add dropdown ([a99fb4a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a99fb4a22dcea3b6cd2a52f0dbd274d9a10f2e35))
* **sidebar-navigation:** add sidebar navigation component ([d8794ef](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d8794ef4d36b25e600123d41696b0d5cc10dc2af))
## [0.5.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.5.0...v0.5.1) (2022-06-06)
### Bug Fixes
* **classes:** switch static-classes to findModule ([244ae12](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/244ae128da03e0687f1ba0b0e5b5b548b581277a))
# [0.5.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.4.2...v0.5.0) (2022-06-06)
### Features
* **utils:** add joinClassNames util ([f34b9de](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/f34b9de97f61eb5b075d6adedfcacfa5e097943b))
## [0.4.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.4.1...v0.4.2) (2022-06-06)
### Bug Fixes
* **classes:** add gamepadDialogClasses and quickAccessControlsClasses ([2e7b4b6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2e7b4b664a673b46b402b995fb58f0ce8ffbafac))
## [0.4.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.4.0...v0.4.1) (2022-06-05)
### Bug Fixes
* **textfield:** correct type for onChange callback ([32c355f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/32c355f2a7e0b6ca6592b956e8174d217766bc5c))
# [0.4.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.3.0...v0.4.0) (2022-06-05)
### Bug Fixes
* **typings:** export all prop types ([7f9dfc5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7f9dfc5910dfc172ba161d9b63763e85eb289a43))
### Features
* **textfield:** extract TextField component ([a3c1a7c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a3c1a7c7b73eae475574a13b6ff9c75ff78cbcb6))
# [0.3.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.2.0...v0.3.0) (2022-06-04)
### Features
* **typings:** add Navigate to router typings ([f124480](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/f124480af8082d24730ed03fdf88742f76abc026))
# [0.2.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v0.1.0...v0.2.0) (2022-06-04)

View File

@@ -1,6 +1,6 @@
{
"name": "decky-frontend-lib",
"version": "0.2.0",
"version": "0.7.2",
"description": "A library for building decky plugins",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
"dev": "tsc -b -w",
"prepack": "npm run build",
"test": "echo 'No tests for now!'",
"postinstall": "husky install",
"prepare": "husky install",
"commit": "git-cz"
},
"files": [
@@ -58,6 +58,14 @@
"ts-jest": "^27.1.4",
"typescript": "^4.6.3"
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"react",
"react-dom"
]
}
},
"importSort": {
".js, .jsx, .ts, .tsx": {
"style": "module",

View File

@@ -2,7 +2,7 @@ import { FC } from 'react';
import { CommonUIModule } from '../webpack';
interface ButtonProps {
export interface ButtonProps {
className?: string;
noFocusRing?: boolean;
disabled?: boolean;

View File

@@ -1,15 +1,11 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
import { ItemProps } from './Item';
interface ButtonItemProps {
label?: string;
description?: string;
layout?: 'below';
icon?: JSX.Element;
export interface ButtonItemProps extends ItemProps {
onClick?(e: MouseEvent): void;
disabled?: boolean;
bottomSeparator?: boolean;
}
export const ButtonItem = Object.values(CommonUIModule).find((mod: any) =>

View File

@@ -0,0 +1,44 @@
import { ReactNode, VFC } from 'react';
import { CommonUIModule } from '../webpack';
import { ItemProps } from './Item';
export interface SingleDropdownOption {
data: number;
label: string;
options?: never;
}
export interface MultiDropdownOption {
label: string;
options: DropdownOption[];
data?: never;
}
export type DropdownOption = SingleDropdownOption | MultiDropdownOption;
export interface DropdownProps {
rgOptions: DropdownOption[];
selectedOption: number | null;
disabled?: boolean;
onMenuWillOpen?(showMenu: () => void): void;
onMenuOpened?(): void;
onChange?(data: SingleDropdownOption): void;
contextMenuPositionOptions?: any;
menuLabel?: string;
strDefaultLabel?: string;
renderButtonValue?(element: ReactNode): ReactNode;
focusable?: boolean;
}
export const Dropdown = Object.values(CommonUIModule).find(
(mod: any) => mod?.prototype?.SetSelectedOption && mod?.prototype?.BuildMenu,
) as VFC<DropdownProps>;
export interface DropdownItemProps extends DropdownProps, ItemProps {}
export const DropdownItem = Object.values(CommonUIModule).find((mod: any) =>
mod?.toString()?.includes('"dropDownControlRef","description"'),
) as VFC<DropdownItemProps>;

View File

@@ -0,0 +1,11 @@
import { ReactNode } from 'react';
export interface ItemProps {
label?: string;
description?: string;
layout?: 'below' | 'inline';
icon?: ReactNode;
bottomSeparator?: boolean;
indentLevel?: number;
tooltip?: string;
}

View File

@@ -11,7 +11,7 @@ export const showContextMenu: (children: ReactNode, parent?: EventTarget) => voi
}
});
interface MenuProps {
export interface MenuProps {
label: string;
onCancel?(): void;
cancelText?: string;
@@ -27,7 +27,7 @@ export const Menu: FC<MenuProps> = findModuleChild((m) => {
}
});
interface MenuItemProps {
export interface MenuItemProps {
onSelected?(): void;
}

View File

@@ -1,4 +1,5 @@
import { FC, ReactNode } from 'react';
import { findModuleChild } from '../webpack';
// TODO: there is another argument, figure out what it does
@@ -11,18 +12,18 @@ export const showModal: (children: ReactNode, parent?: EventTarget) => void = fi
}
});
interface ModalRootProps {
onMiddleButton?(): void,
export interface ModalRootProps {
onMiddleButton?(): void;
onCancel?(): void;
onOK?(): void;
bAllowFullSize?: boolean;
}
export const ModalRoot = findModuleChild(m => {
if (typeof m !== "object") return undefined;
export const ModalRoot = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (!m[prop]?.prototype?.OK && m[prop]?.prototype?.Cancel && m[prop]?.prototype?.render) {
return m[prop];
}
}
}) as FC<ModalRootProps>;
}) as FC<ModalRootProps>;

View File

@@ -2,7 +2,7 @@ import { FC } from 'react';
import { findModuleChild } from '../webpack';
interface PanelSectionProps {
export interface PanelSectionProps {
title?: string;
spinner?: boolean;
}

View File

@@ -0,0 +1,18 @@
import { VFC } from 'react';
import { findModuleChild } from '../webpack';
import { ItemProps } from './Item';
export interface ProgressBarItem extends ItemProps {
indeterminate?: boolean;
nTransitionSec?: number;
nProgress?: number;
focusable?: boolean;
}
export const ProgressBarItem = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.toString()?.includes('"indeterminate","nTransitionSec"')) return m[prop];
}
}) as VFC<ProgressBarItem>;

View File

@@ -17,11 +17,13 @@ export enum QuickAccessTab {
Decky,
}
interface Router {
export interface Router {
CloseSideMenus(): void;
OpenQuickAccessMenu(quickAccessTab: QuickAccessTab): void;
GetQuickAccessTab(): QuickAccessTab;
Navigate(path: string): void;
NavigateToExternalWeb(url: string): void;
NavigateToStore(): void;
ToggleSideMenu(sideMenu: SideMenu): void;
CloseSideMenus(): void;
OpenSideMenu(sideMenu: SideMenu): void;

View File

@@ -0,0 +1,25 @@
import { ReactNode, VFC } from 'react';
import { Module, findModuleChild } from '../webpack';
export interface SidebarNavigationPages {
title: string;
route: string;
content: ReactNode;
}
export interface SidebarNavigationProps {
title?: string;
pages: SidebarNavigationPages[];
showTitle?: boolean;
disableRouteReporting?: boolean;
}
export const SidebarNavigation = findModuleChild((mod: Module) => {
for (let prop in mod) {
if (mod[prop]?.toString()?.includes('"disableRouteReporting"')) {
return mod[prop];
}
}
return null;
}) as VFC<SidebarNavigationProps>;

View File

@@ -1,26 +1,32 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
import { ItemProps } from './Item';
interface NotchLabel {
export interface NotchLabel {
notchIndex: number;
label: string;
value: number;
value?: number;
}
interface SliderProps {
label?: string;
export interface SliderProps extends ItemProps {
value: number;
layout?: 'below';
icon?: JSX.Element;
min?: number;
max?: number;
step?: number;
notchCount?: number;
notchLabels?: NotchLabel[];
notchTicksVisible?: boolean;
showValue?: boolean;
resetValue?: number;
disabled?: boolean;
editableValue?: boolean;
validValues?: 'steps' | 'range' | ((value: number) => boolean);
valueSuffix?: string;
minimumDpadGranularity?: number;
onChange?(value: number): void;
}
export const Slider = Object.values(CommonUIModule).find((mod: any) =>
mod?.render?.toString()?.includes('SliderField,fallback'),
mod?.toString()?.includes('SliderField,fallback'),
) as FC<SliderProps>;

View File

@@ -1,8 +1,8 @@
import { FC } from 'react';
import { FC, SVGAttributes } from 'react';
import { IconsModule } from '../webpack';
// TODO type this and other icons?
export const Spinner = Object.values(IconsModule).find((mod: any) =>
mod?.toString && /Spinner\)}\),.\.createElement\(\"path\",{d:\"M18 /.test(mod.toString())
) as FC<{}>;
) as FC<SVGAttributes<SVGElement>>;

View File

@@ -1,4 +1,4 @@
import { FC } from 'react';
import { FC, SVGAttributes } from 'react';
import { findModuleChild } from '../webpack';
export const SteamSpinner = findModuleChild((m) => {
@@ -6,4 +6,4 @@ export const SteamSpinner = findModuleChild((m) => {
for (let prop in m) {
if (m[prop]?.toString()?.includes("Steam Spinner") && m[prop].toString().includes("PreloadThrobber")) return m[prop]
}
}) as FC<{}>;
}) as FC<SVGAttributes<SVGElement>>;

View File

@@ -0,0 +1,27 @@
import { ChangeEventHandler, ReactNode, VFC } from 'react';
import { CommonUIModule, Module } from '../webpack';
export interface TextFieldProps {
label?: ReactNode;
requiredLabel?: ReactNode;
description?: ReactNode;
bShowCopyAction?: boolean;
bShowClearAction?: boolean;
bAlwaysShowClearAction?: boolean;
bIsPassword?: boolean;
rangeMin?: number;
rangeMax?: number;
mustBeNumeric?: boolean;
mustBeURL?: boolean;
mustBeEmail?: boolean;
focusOnMount?: boolean;
tooltip?: string;
inlineControls?: ReactNode;
onChange?: ChangeEventHandler<HTMLInputElement>;
value?: string;
}
export const TextField = Object.values(CommonUIModule).find(
(mod: Module) => mod?.validateUrl && mod?.validateEmail,
) as VFC<TextFieldProps>;

View File

@@ -1,12 +1,10 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
import { ItemProps } from './Item';
interface ToggleProps {
label?: string;
description?: string;
export interface ToggleProps extends ItemProps {
checked: boolean;
icon?: JSX.Element;
disabled?: boolean;
onChange?(checked: boolean): void;
}

View File

@@ -1,11 +1,15 @@
export * from './Button';
export * from './ButtonItem';
export * from './Dropdown';
export * from './Menu';
export * from './Modal';
export * from './Panel';
export * from './ProgressBar';
export * from './Router';
export * from './SidebarNavigation';
export * from './Slider';
export * from './Spinner';
export * from './static-classes';
export * from './SteamSpinner';
export * from './TextField';
export * from './Toggle';

View File

@@ -1,4 +1,4 @@
import { findModuleChild } from '../webpack';
import { findModule } from '../webpack';
type StaticClasses = Record<
| 'ActiveTab'
@@ -63,10 +63,126 @@ type StaticClasses = Record<
string
>;
export const staticClasses: StaticClasses = findModuleChild((mod) => {
type GamepadDialogClasses = Record<
| 'duration-app-launch'
| 'GamepadDialogContent'
| 'GamepadDialogContent_InnerWidth'
| 'Field'
| 'Button'
| 'NoMinWidth'
| 'ActiveAndUnfocused'
| 'StandaloneFieldSeparator'
| 'StandardPadding'
| 'CompactPadding'
| 'WithDescription'
| 'WithBottomSeparatorStandard'
| 'WithBottomSeparatorThick'
| 'HighlightOnFocus'
| 'ItemFocusAnim-darkerGrey'
| 'ItemFocusAnim-darkGrey'
| 'WithBottomSeparator'
| 'Disabled'
| 'Clickable'
| 'FieldClickTarget'
| 'FieldChildren'
| 'FieldLeadIcon'
| 'FieldLabelRow'
| 'VerticalAlignCenter'
| 'InlineWrapShiftsChildrenBelow'
| 'ExtraPaddingOnChildrenBelow'
| 'ChildrenWidthFixed'
| 'ChildrenWidthGrow'
| 'WithFirstRow'
| 'WithChildrenBelow'
| 'FieldLabel'
| 'FieldLabelValue'
| 'FieldDescription'
| 'ModalPosition'
| 'WithStandardPadding'
| 'slideInAnimation'
| 'BasicTextInput'
| 'Toggle'
| 'ToggleRail'
| 'On'
| 'ToggleSwitch'
| 'LabelFieldValue'
| 'DropDownControlButtonContents'
| 'Spacer'
| 'ControlsListOuterPanel'
| 'StandardSpacing'
| 'ExtraSpacing'
| 'AlignRight'
| 'AlignLeft'
| 'AlignCenter'
| 'ControlsListChild'
| 'QuickAccess-Menu'
| 'BigButtons'
| 'BottomButtons'
| 'ItemFocusAnim-darkerGrey-nocolor'
| 'ItemFocusAnim-grey'
| 'ItemFocusAnimBorder-darkGrey'
| 'ItemFocusAnim-green'
| 'focusAnimation'
| 'hoverAnimation',
string
>;
type QuickAccessControlsClasses = Record<
| 'duration-app-launch'
| 'PanelSection'
| 'PanelSectionTitle'
| 'Text'
| 'PanelSectionRow'
| 'Label'
| 'ComingSoon'
| 'LowBattery'
| 'ReallyLow'
| 'LowBatteryGauge'
| 'Remaining'
| 'EmptyNotifications'
| 'BatterySectionContainer'
| 'BatteryIcon'
| 'BatteryPercentageLabel'
| 'BatteryDetailsLabels'
| 'BatteryProjectedValue'
| 'BatteryProjectedLabel'
| 'ItemFocusAnim-darkerGrey-nocolor'
| 'ItemFocusAnim-darkerGrey'
| 'ItemFocusAnim-darkGrey'
| 'ItemFocusAnim-grey'
| 'ItemFocusAnimBorder-darkGrey'
| 'ItemFocusAnim-green'
| 'focusAnimation'
| 'hoverAnimation',
string
>;
export const staticClasses: StaticClasses = findModule((mod) => {
if (typeof mod !== 'object') return false;
if (mod.TransitionMenuDelay) {
return mod;
return true;
}
return false;
});
export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => {
if (typeof mod !== 'object') return false;
if (mod.WithFirstRow) {
return true;
}
return false;
});
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => {
if (typeof mod !== 'object') return false;
if (mod.PanelSectionRow) {
return true;
}
return false;
});

View File

@@ -85,3 +85,7 @@ export function unpatch(obj: any, name: any): void {
export function getReactInstance(o: HTMLElement | Element | Node) {
return o[Object.keys(o).find(k => k.startsWith('__reactInternalInstance')) as string]
}
export function joinClassNames(...classes: string[]): string {
return classes.join(" ");
}