mirror of
https://github.com/SteamDeckHomebrew/decky-frontend-lib.git
synced 2026-05-22 19:08:46 +02:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b76ccd91a | ||
|
|
99ad7543a9 | ||
|
|
b5dc08a977 | ||
|
|
40871af853 | ||
|
|
c910dbde79 | ||
|
|
4cbb30c21c | ||
|
|
54a1ef6201 | ||
|
|
ed0be5e87e | ||
|
|
a064163b49 | ||
|
|
0b4fcb8d49 | ||
|
|
4233128c7e | ||
|
|
43cb2726d8 | ||
|
|
5d9c506fe7 | ||
|
|
35a061759a | ||
|
|
1fbe55aa54 | ||
|
|
66eb0cbbf3 | ||
|
|
6996e5424f | ||
|
|
ad643836f0 | ||
|
|
b39ba26b28 | ||
|
|
130dfa24c5 | ||
|
|
71babc82c8 |
49
CHANGELOG.md
49
CHANGELOG.md
@@ -1,3 +1,52 @@
|
|||||||
|
## [3.3.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.2...v3.3.3) (2022-10-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **modal:** make children optional ([#34](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/34)) ([99ad754](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/99ad7543a9966b8ff3f4ec01e6f05c94e5242c93))
|
||||||
|
|
||||||
|
## [3.3.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.1...v3.3.2) (2022-10-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **modal:** allow children ([40871af](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/40871af8539858f435c83123a56d4b31b63d627d))
|
||||||
|
|
||||||
|
## [3.3.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.0...v3.3.1) (2022-10-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **SidebarNavigation:** add more props ([#29](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/29)) ([ed0be5e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ed0be5e87e964ed57cc99b40ff55fe35a2f518b2))
|
||||||
|
|
||||||
|
# [3.3.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.2...v3.3.0) (2022-10-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **Menu:** add nested menu groups + more props ([#30](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/30)) ([4233128](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4233128c7ee8c6e5ab4ee74385c7b1b911d507a6))
|
||||||
|
|
||||||
|
## [3.2.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.1...v3.2.2) (2022-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **modal:** extend props for modals ([#32](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/32)) ([1fbe55a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/1fbe55aa544c9e84e2b3e2d6af9950db2fe7546c))
|
||||||
|
|
||||||
|
## [3.2.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.0...v3.2.1) (2022-09-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **modal:** update showModal types ([#27](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/27)) ([6996e54](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/6996e5424f33467ef5bb93f47614058c127cb3ee))
|
||||||
|
|
||||||
|
# [3.2.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.1.4...v3.2.0) (2022-09-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **FooterLegend:** add GamepadEvent ([130dfa2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/130dfa24c51c3a670cca9ebc38e4891618532bef))
|
||||||
|
|
||||||
## [3.1.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.1.3...v3.1.4) (2022-09-19)
|
## [3.1.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.1.3...v3.1.4) (2022-09-19)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
LICENSE
20
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE (DECKY-FRONTEND-LIB v1)
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
Version 2.1, February 1999
|
Version 2.1, February 1999
|
||||||
|
|
||||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
@@ -457,24 +457,6 @@ DAMAGES.
|
|||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
EXCEPTION NOTICE
|
|
||||||
|
|
||||||
1. The exception is that you may use, copy, link, modify and distribute
|
|
||||||
under your own terms, binary object code versions of works based on the
|
|
||||||
Library.
|
|
||||||
|
|
||||||
2. If you copy code from files distributed under the terms of the GNU
|
|
||||||
General Public Licence or the GNU Library General Public Licence into a
|
|
||||||
copy of this library, as this licence permits, the exception does not apply
|
|
||||||
to the code that you add in this way. To avoid misleading anyone as to the
|
|
||||||
status of such modified files, you must delete this exception notice from
|
|
||||||
such code and/or adjust the licensing conditions notice accordingly.
|
|
||||||
|
|
||||||
3. If you write modifications of your own for this library, it is your
|
|
||||||
choice whether to permit this exception to apply to your modifications. If
|
|
||||||
you do not wish that, you must delete the exception notice from such code
|
|
||||||
and/or adjust the licensing conditions notice accordingly.
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Libraries
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
If you develop a new library, and you want it to be of the greatest
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "decky-frontend-lib",
|
"name": "decky-frontend-lib",
|
||||||
"version": "3.1.4",
|
"version": "3.3.3",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "decky-frontend-lib",
|
"name": "decky-frontend-lib",
|
||||||
"version": "3.1.4",
|
"version": "3.3.3",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": "^1.2.6"
|
"minimist": "^1.2.6"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "decky-frontend-lib",
|
"name": "decky-frontend-lib",
|
||||||
"version": "3.1.4",
|
"version": "3.3.3",
|
||||||
"description": "A library for building decky plugins",
|
"description": "A library for building decky plugins",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"components"
|
"components"
|
||||||
],
|
],
|
||||||
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
||||||
"license": "LGPL-2.1-with-decky-exceptions",
|
"license": "LGPL-2.1",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues"
|
"url": "https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export * from './SuspensefulImage';
|
export * from './SuspensefulImage';
|
||||||
|
export * from './ColorPickerModal';
|
||||||
|
|||||||
1
src/custom-hooks/index.ts
Normal file
1
src/custom-hooks/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './usequickaccessvisible';
|
||||||
67
src/custom-hooks/usequickaccessvisible.tsx
Normal file
67
src/custom-hooks/usequickaccessvisible.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var FocusNavController: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns state indicating the visibility of quick access menu.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* During development it is possible to open the quick access menu without giving it
|
||||||
|
* focus in some cases. In such cases, the quick access menu state is invisible.
|
||||||
|
*
|
||||||
|
* This seems to be impossible to replicate when running the deck normally. Even in
|
||||||
|
* the edge cases it always seems to have a focus.
|
||||||
|
*
|
||||||
|
* @returns `true` if quick access menu is visible (focused) and `false` otherwise.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import { VFC, useEffect } from "react";
|
||||||
|
* import { useQuickAccessVisible } from "decky-frontend-lib";
|
||||||
|
*
|
||||||
|
* export const PluginPanelView: VFC<{}> = ({ }) => {
|
||||||
|
* const isVisible = useQuickAccessVisible();
|
||||||
|
*
|
||||||
|
* useEffect(() => {
|
||||||
|
* if (!isVisible) {
|
||||||
|
* return;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const interval = setInterval(() => console.log("Hello world!"), 1000);
|
||||||
|
* return () => {
|
||||||
|
* clearInterval(interval);
|
||||||
|
* }
|
||||||
|
* }, [isVisible])
|
||||||
|
*
|
||||||
|
* return (
|
||||||
|
* <div>
|
||||||
|
* {isVisible ? "VISIBLE" : "INVISIBLE"}
|
||||||
|
* </div>
|
||||||
|
* );
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
export function useQuickAccessVisible(): boolean {
|
||||||
|
// Assuming that the component is rendered in QAM already, so true by default...
|
||||||
|
const [isVisible, setIsVisible] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const quickAccessWindow: Window | null = FocusNavController?.GetGamepadNavTreeByID("QuickAccess-NA")?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
|
||||||
|
if (quickAccessWindow === null) {
|
||||||
|
console.error("Could not get window of QuickAccess menu!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onBlur = () => setIsVisible(false);
|
||||||
|
const onFocus = () => setIsVisible(true);
|
||||||
|
|
||||||
|
quickAccessWindow.addEventListener("blur", onBlur);
|
||||||
|
quickAccessWindow.addEventListener("focus", onFocus);
|
||||||
|
return () => {
|
||||||
|
quickAccessWindow.removeEventListener("blur", onBlur);
|
||||||
|
quickAccessWindow.removeEventListener("focus", onFocus);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return isVisible;
|
||||||
|
}
|
||||||
@@ -1,21 +1,8 @@
|
|||||||
import { CSSProperties, FC, RefAttributes } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { DialogButton, DialogButtonProps } from "./Dialog";
|
||||||
|
|
||||||
import { CommonUIModule } from '../webpack';
|
export interface ButtonProps extends DialogButtonProps {
|
||||||
|
|
||||||
export interface DialogButtonProps extends RefAttributes<HTMLDivElement> {
|
|
||||||
label?: string;
|
|
||||||
style?: CSSProperties;
|
|
||||||
className?: string;
|
|
||||||
noFocusRing?: boolean;
|
|
||||||
description?: string;
|
|
||||||
layout?: 'below';
|
|
||||||
onClick?(e: MouseEvent): void;
|
|
||||||
disabled?: boolean;
|
|
||||||
bottomSeparator?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DialogButton = Object.values(CommonUIModule).find(
|
// Button isn't exported, so call DialogButton to grab it
|
||||||
(mod: any) =>
|
export const Button = (DialogButton as any)?.render({}).type as FC<ButtonProps>;
|
||||||
mod?.render?.toString()?.includes('Object.assign({type:"button"') &&
|
|
||||||
mod?.render?.toString()?.includes('DialogButton'),
|
|
||||||
) as FC<DialogButtonProps>;
|
|
||||||
|
|||||||
63
src/deck-components/Dialog.tsx
Normal file
63
src/deck-components/Dialog.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { CommonUIModule } from "../webpack";
|
||||||
|
import { CSSProperties, FC, RefAttributes } from "react";
|
||||||
|
import { FooterLegendProps } from './FooterLegend';
|
||||||
|
|
||||||
|
export interface DialogCommonProps extends RefAttributes<HTMLDivElement> {
|
||||||
|
style?: CSSProperties;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogButtonProps extends DialogCommonProps, FooterLegendProps {
|
||||||
|
noFocusRing?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
onClick?(e: MouseEvent): void;
|
||||||
|
onPointerDown?(e: PointerEvent): void;
|
||||||
|
onPointerUp?(e: PointerEvent): void;
|
||||||
|
onPointerCancel?(e: PointerEvent): void;
|
||||||
|
onMouseDown?(e: MouseEvent): void;
|
||||||
|
onMouseUp?(e: MouseEvent): void;
|
||||||
|
onTouchStart?(e: TouchEvent): void;
|
||||||
|
onTouchEnd?(e: TouchEvent): void;
|
||||||
|
onTouchCancel?(e: TouchEvent): void;
|
||||||
|
onSubmit?(e: SubmitEvent): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CommonDialogDivs = Object.values(CommonUIModule).filter((m: any) => typeof m === "object" && m?.render?.toString().includes('"div",Object.assign({},'));
|
||||||
|
const MappedDialogDivs = new Map(Object.values(CommonDialogDivs).map((m: any) => {
|
||||||
|
const renderedDiv = m.render({});
|
||||||
|
// Take only the first class name segment as it identifies the element we want
|
||||||
|
return [renderedDiv.props.className.split(" ")[0], m]
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const DialogHeader = MappedDialogDivs.get("DialogHeader") as FC<DialogCommonProps>;
|
||||||
|
export const DialogSubHeader = MappedDialogDivs.get("DialogSubHeader") as FC<DialogCommonProps>;
|
||||||
|
export const DialogFooter = MappedDialogDivs.get("DialogFooter") as FC<DialogCommonProps>;
|
||||||
|
export const DialogLabel = MappedDialogDivs.get("DialogLabel") as FC<DialogCommonProps>;
|
||||||
|
export const DialogBodyText = MappedDialogDivs.get("DialogBodyText") as FC<DialogCommonProps>;
|
||||||
|
export const DialogBody = MappedDialogDivs.get("DialogBody") as FC<DialogCommonProps>;
|
||||||
|
export const DialogControlsSection = MappedDialogDivs.get("DialogControlsSection") as FC<DialogCommonProps>;
|
||||||
|
export const DialogControlsSectionHeader = MappedDialogDivs.get("DialogControlsSectionHeader") as FC<DialogCommonProps>;
|
||||||
|
|
||||||
|
export const DialogButtonPrimary = Object.values(CommonUIModule).find(
|
||||||
|
(mod: any) =>
|
||||||
|
mod?.render?.toString()?.includes('DialogButton') &&
|
||||||
|
mod?.render?.toString()?.includes('Primary')
|
||||||
|
) as FC<DialogButtonProps>;
|
||||||
|
|
||||||
|
export const DialogButtonSecondary = Object.values(CommonUIModule).find(
|
||||||
|
(mod: any) =>
|
||||||
|
mod?.render?.toString()?.includes('Object.assign({type:"button"') &&
|
||||||
|
mod?.render?.toString()?.includes('DialogButton') &&
|
||||||
|
mod?.render?.toString()?.includes('Secondary')
|
||||||
|
) as FC<DialogButtonProps>;
|
||||||
|
|
||||||
|
export const DialogButtonSmall = Object.values(CommonUIModule).find(
|
||||||
|
(mod: any) =>
|
||||||
|
mod?.render?.toString()?.includes('Object.assign({type:"button"') &&
|
||||||
|
mod?.render?.toString()?.includes('DialogButton') &&
|
||||||
|
mod?.render?.toString()?.includes('Small')
|
||||||
|
) as FC<DialogButtonProps>;
|
||||||
|
|
||||||
|
// This is the "main" button. The Primary can act as a submit button,
|
||||||
|
// therefore secondary is chosen (also for backwards comp. reasons)
|
||||||
|
export const DialogButton = DialogButtonSecondary;
|
||||||
@@ -1,3 +1,51 @@
|
|||||||
|
export enum GamepadButton {
|
||||||
|
INVALID,
|
||||||
|
OK,
|
||||||
|
CANCEL,
|
||||||
|
SECONDARY,
|
||||||
|
OPTIONS,
|
||||||
|
BUMPER_LEFT,
|
||||||
|
BUMPER_RIGHT,
|
||||||
|
TRIGGER_LEFT,
|
||||||
|
TRIGGER_RIGHT,
|
||||||
|
DIR_UP,
|
||||||
|
DIR_DOWN,
|
||||||
|
DIR_LEFT,
|
||||||
|
DIR_RIGHT,
|
||||||
|
SELECT,
|
||||||
|
START,
|
||||||
|
LSTICK_CLICK,
|
||||||
|
RSTICK_CLICK,
|
||||||
|
LSTICK_TOUCH,
|
||||||
|
RSTICK_TOUCH,
|
||||||
|
LPAD_TOUCH,
|
||||||
|
LPAD_CLICK,
|
||||||
|
RPAD_TOUCH,
|
||||||
|
RPAD_CLICK,
|
||||||
|
REAR_LEFT_UPPER,
|
||||||
|
REAR_LEFT_LOWER,
|
||||||
|
REAR_RIGHT_UPPER,
|
||||||
|
REAR_RIGHT_LOWER,
|
||||||
|
STEAM_GUIDE,
|
||||||
|
STEAM_QUICK_MENU
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum NavEntryPositionPreferences {
|
||||||
|
FIRST,
|
||||||
|
LAST,
|
||||||
|
MAINTAIN_X,
|
||||||
|
MAINTAIN_Y,
|
||||||
|
PREFERRED_CHILD
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GamepadEventDetail {
|
||||||
|
button: number;
|
||||||
|
is_repeat?: boolean;
|
||||||
|
source: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GamepadEvent = CustomEvent<GamepadEventDetail>
|
||||||
|
|
||||||
export interface FooterLegendProps {
|
export interface FooterLegendProps {
|
||||||
actionDescriptionMap?: unknown;
|
actionDescriptionMap?: unknown;
|
||||||
onOKActionDescription?: string;
|
onOKActionDescription?: string;
|
||||||
@@ -5,14 +53,14 @@ export interface FooterLegendProps {
|
|||||||
onSecondaryActionDescription?: string;
|
onSecondaryActionDescription?: string;
|
||||||
onOptionsActionDescription?: string;
|
onOptionsActionDescription?: string;
|
||||||
onMenuActionDescription?: string;
|
onMenuActionDescription?: string;
|
||||||
onButtonDown?: () => void;
|
onButtonDown?: (evt: GamepadEvent) => void;
|
||||||
onButtonUp?: () => void;
|
onButtonUp?: (evt: GamepadEvent) => void;
|
||||||
onOKButton?: () => void;
|
onOKButton?: (evt: GamepadEvent) => void;
|
||||||
onCancelButton?: () => void;
|
onCancelButton?: (evt: GamepadEvent) => void;
|
||||||
onSecondaryButton?: () => void;
|
onSecondaryButton?: (evt: GamepadEvent) => void;
|
||||||
onOptionsButton?: () => void;
|
onOptionsButton?: (evt: GamepadEvent) => void;
|
||||||
onGamepadDirection?: () => void;
|
onGamepadDirection?: (evt: GamepadEvent) => void;
|
||||||
onGamepadFocus?: () => void;
|
onGamepadFocus?: (evt: GamepadEvent) => void;
|
||||||
onGamepadBlur?: () => void;
|
onGamepadBlur?: (evt: GamepadEvent) => void;
|
||||||
onMenuButton?: () => void;
|
onMenuButton?: (evt: GamepadEvent) => void;
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ export interface MenuProps {
|
|||||||
label: string;
|
label: string;
|
||||||
onCancel?(): void;
|
onCancel?(): void;
|
||||||
cancelText?: string;
|
cancelText?: string;
|
||||||
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Menu: FC<MenuProps> = findModuleChild((m) => {
|
export const Menu: FC<MenuProps> = findModuleChild((m) => {
|
||||||
@@ -27,8 +28,26 @@ export const Menu: FC<MenuProps> = findModuleChild((m) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export interface MenuGroupProps {
|
||||||
|
label: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MenuGroup: FC<MenuGroupProps> = findModuleChild((m) => {
|
||||||
|
if (typeof m !== 'object') return undefined;
|
||||||
|
|
||||||
|
for (let prop in m) {
|
||||||
|
if (m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu) {
|
||||||
|
return m[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export interface MenuItemProps {
|
export interface MenuItemProps {
|
||||||
onSelected?(): void;
|
onSelected?(): void;
|
||||||
|
disabled?: boolean;
|
||||||
|
children?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
|
export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
|
||||||
|
|||||||
@@ -1,9 +1,33 @@
|
|||||||
import { FC, ReactNode } from 'react';
|
import { FC, ReactNode } from 'react';
|
||||||
|
|
||||||
import { findModuleChild } from '../webpack';
|
import { findModuleChild } from '../webpack';
|
||||||
|
|
||||||
// TODO: there is another argument, figure out what it does
|
// All of the popout options + strTitle are related. Proper usage is not yet known...
|
||||||
export const showModal: (children: ReactNode, parent?: EventTarget) => void = findModuleChild((m) => {
|
export interface ShowModalProps {
|
||||||
|
browserContext?: unknown; // This is another Deck Object that is yet to be found
|
||||||
|
bForcePopOut?: boolean;
|
||||||
|
bHideActionIcons?: boolean;
|
||||||
|
bHideMainWindowForPopouts?: boolean;
|
||||||
|
bNeverPopOut?: boolean;
|
||||||
|
fnOnClose?: () => void; // Seems to be the same as "closeModal" callback, but only when the modal is a popout. Will no longer work after "Update" invocation!
|
||||||
|
popupHeight?: number;
|
||||||
|
popupWidth?: number;
|
||||||
|
promiseRenderComplete?: Promise<void>; // Invoked once the render is complete. Currently, it seems to be used as image loading success/error callback...
|
||||||
|
strTitle?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShowModalResult {
|
||||||
|
// This method will not invoke any of the variations of "closeModal" callbacks!
|
||||||
|
Close: () => void;
|
||||||
|
|
||||||
|
// This method will replace the modal element completely and will not update the callback chains,
|
||||||
|
// meaning that "closeModal" and etc. will not automatically close the modal anymore (also "fnOnClose"
|
||||||
|
// will not be even called upon close anymore)! You have to manually call the "Close" method when, for example,
|
||||||
|
// the "closeModal" is invoked in the newly updated modal:
|
||||||
|
// <ModalRoot closeModal={() => { console.log("ABOUT TO CLOSE"); showModalRes.Close(); }} />
|
||||||
|
Update: (modal: ReactNode) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showModal: (modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => Promise<ShowModalResult> = findModuleChild((m) => {
|
||||||
if (typeof m !== 'object') return undefined;
|
if (typeof m !== 'object') return undefined;
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
|
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
|
||||||
@@ -13,6 +37,7 @@ export const showModal: (children: ReactNode, parent?: EventTarget) => void = fi
|
|||||||
});
|
});
|
||||||
|
|
||||||
export interface ModalRootProps {
|
export interface ModalRootProps {
|
||||||
|
children?: ReactNode;
|
||||||
onCancel?(): void;
|
onCancel?(): void;
|
||||||
closeModal?(): void;
|
closeModal?(): void;
|
||||||
onOK?(): void;
|
onOK?(): void;
|
||||||
@@ -24,10 +49,18 @@ export interface ModalRootProps {
|
|||||||
bDisableBackgroundDismiss?: boolean;
|
bDisableBackgroundDismiss?: boolean;
|
||||||
bHideCloseIcon?: boolean;
|
bHideCloseIcon?: boolean;
|
||||||
bOKDisabled?: boolean;
|
bOKDisabled?: boolean;
|
||||||
|
bCancelDisabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfirmModalProps extends ModalRootProps {
|
export interface ConfirmModalProps extends ModalRootProps {
|
||||||
onMiddleButton?(): void;
|
onMiddleButton?(): void; // setting this prop will enable the middle button
|
||||||
|
strTitle?: ReactNode;
|
||||||
|
strDescription?: ReactNode;
|
||||||
|
strOKButtonText?: ReactNode;
|
||||||
|
strCancelButtonText?: ReactNode;
|
||||||
|
strMiddleButtonText?: ReactNode;
|
||||||
|
bAlertDialog?: boolean; // This will open a modal with only OK button enabled
|
||||||
|
bMiddleDisabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConfirmModal = findModuleChild((m) => {
|
export const ConfirmModal = findModuleChild((m) => {
|
||||||
@@ -46,4 +79,4 @@ export const ModalRoot = findModuleChild((m) => {
|
|||||||
return m[prop];
|
return m[prop];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) as FC<ModalRootProps>;
|
}) as FC<ModalRootProps>;
|
||||||
|
|||||||
@@ -4,8 +4,14 @@ import { Module, findModuleChild } from '../webpack';
|
|||||||
|
|
||||||
export interface SidebarNavigationPages {
|
export interface SidebarNavigationPages {
|
||||||
title: string;
|
title: string;
|
||||||
route: string;
|
|
||||||
content: ReactNode;
|
content: ReactNode;
|
||||||
|
icon?: ReactNode;
|
||||||
|
visible?: boolean;
|
||||||
|
hideTitle?: boolean;
|
||||||
|
identifier?: string;
|
||||||
|
route?: string;
|
||||||
|
link?: string;
|
||||||
|
padding?: "none" | "compact";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SidebarNavigationProps {
|
export interface SidebarNavigationProps {
|
||||||
@@ -13,6 +19,8 @@ export interface SidebarNavigationProps {
|
|||||||
pages: SidebarNavigationPages[];
|
pages: SidebarNavigationPages[];
|
||||||
showTitle?: boolean;
|
showTitle?: boolean;
|
||||||
disableRouteReporting?: boolean;
|
disableRouteReporting?: boolean;
|
||||||
|
page?: string;
|
||||||
|
onPageRequested?: (page: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SidebarNavigation = findModuleChild((mod: Module) => {
|
export const SidebarNavigation = findModuleChild((mod: Module) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './Button';
|
export * from './Button';
|
||||||
export * from './ButtonItem';
|
export * from './ButtonItem';
|
||||||
export * from './Carousel';
|
export * from './Carousel';
|
||||||
|
export * from './Dialog';
|
||||||
export * from './Dropdown';
|
export * from './Dropdown';
|
||||||
export * from './Field';
|
export * from './Field';
|
||||||
export * from './Focusable';
|
export * from './Focusable';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { findModule } from '../webpack';
|
import { findModule } from '../webpack';
|
||||||
|
|
||||||
type StaticClasses = Record<
|
type QuickAccessMenuClasses = Record<
|
||||||
| 'ActiveTab'
|
| 'ActiveTab'
|
||||||
| 'AllTabContents'
|
| 'AllTabContents'
|
||||||
| 'BatteryDetailsLabels'
|
| 'BatteryDetailsLabels'
|
||||||
@@ -63,7 +63,7 @@ type StaticClasses = Record<
|
|||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type ScrollClasses = Record<
|
type ScrollPanelClasses = Record<
|
||||||
| 'ScrollBoth'
|
| 'ScrollBoth'
|
||||||
| 'ScrollPanel'
|
| 'ScrollPanel'
|
||||||
| 'ScrollX'
|
| 'ScrollX'
|
||||||
@@ -355,10 +355,18 @@ type GamepadSliderClasses = Record<
|
|||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const staticClasses: StaticClasses = findModule((mod) => typeof mod === 'object' && mod.TransitionMenuDelay);
|
export const quickAccessMenuClasses: QuickAccessMenuClasses = findModule((mod) => typeof mod === 'object' && mod?.Title?.includes('quickaccessmenu'));
|
||||||
export const scrollClasses: ScrollClasses = findModule((mod) => typeof mod === 'object' && mod.ScrollPanel && mod.ScrollY);
|
/**
|
||||||
export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => typeof mod === 'object' && mod.WithFirstRow);
|
* @depreciated please use quickAccessMenuClasses instead
|
||||||
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => typeof mod === 'object' && mod.PanelSectionRow);
|
*/
|
||||||
export const updaterFieldClasses: UpdaterFieldClasses = findModule((mod) => typeof mod === 'object' && mod.PatchNotes && mod.PostedTime);
|
export const staticClasses = quickAccessMenuClasses;
|
||||||
export const playSectionClasses: PlaySectionClasses = findModule((mod) => typeof mod === 'object' && mod.MenuButton && mod.MenuActive);
|
export const scrollPanelClasses: ScrollPanelClasses = findModule((mod) => typeof mod === 'object' && mod?.ScrollPanel?.includes('scrollpanel'));
|
||||||
export const gamepadSliderClasses: GamepadSliderClasses = findModule((mod) => typeof mod === 'object' && mod.SliderTrack && mod.SliderHasNotches);
|
/**
|
||||||
|
* @depreciated please use scrollPanelClasses instead
|
||||||
|
*/
|
||||||
|
export const scrollClasses = scrollPanelClasses;
|
||||||
|
export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => typeof mod === 'object' && mod?.GamepadDialogContent?.includes('gamepaddialog'));
|
||||||
|
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => typeof mod === 'object' && mod?.PanelSection?.includes('quickaccesscontrols'));
|
||||||
|
export const updaterFieldClasses: UpdaterFieldClasses = findModule((mod) => typeof mod === 'object' && mod?.OOBEUpdateStatusContainer?.includes('updaterfield'));
|
||||||
|
export const playSectionClasses: PlaySectionClasses = findModule((mod) => typeof mod === 'object' && mod?.Container?.includes('appdetailsplaysection'));
|
||||||
|
export const gamepadSliderClasses: GamepadSliderClasses = findModule((mod) => typeof mod === 'object' && mod?.SliderControlPanelGroup?.includes('gamepadslider'));
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// export * from './deck-libs';
|
// export * from './deck-libs';
|
||||||
export * from './custom-components';
|
export * from './custom-components';
|
||||||
|
export * from './custom-hooks';
|
||||||
export * from './deck-components';
|
export * from './deck-components';
|
||||||
export * from './plugin';
|
export * from './plugin';
|
||||||
export * from './webpack';
|
export * from './webpack';
|
||||||
|
|||||||
Reference in New Issue
Block a user