@decky/ui 4.11.6 → 4.12.1

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.
@@ -1,2 +1,2 @@
1
1
  import { findModuleExport } from '../webpack';
2
- export const ControlsList = findModuleExport((e) => e?.toString && e.toString().includes('().ControlsListChild') && e.toString().includes('().ControlsListOuterPanel'));
2
+ export const ControlsList = findModuleExport((e) => e?.toString && e.toString?.().includes('().ControlsListChild') && e.toString?.().includes('().ControlsListOuterPanel'));
@@ -1,2 +1,2 @@
1
1
  import { findModuleExport } from '../webpack';
2
- export const Field = findModuleExport((e) => (e?.toString()?.includes('().Field') && e?.toString()?.includes('"shift-children-below"')) || e?.render?.toString()?.includes('"shift-children-below"'));
2
+ export const Field = findModuleExport((e) => (e?.toString?.()?.includes('().Field') && e?.toString?.()?.includes('"shift-children-below"')) || e?.render?.toString()?.includes('"shift-children-below"'));
@@ -1,4 +1,4 @@
1
1
  import { findModuleExport } from '../webpack';
2
2
  import { createPropListRegex } from '../utils';
3
3
  const focusableRegex = createPropListRegex(["flow-children", "onActivate", "onCancel", "focusClassName", "focusWithinClassName"]);
4
- export const Focusable = findModuleExport((e) => (typeof e == 'function' && e?.toString && focusableRegex.test(e.toString())) || (e?.render?.toString && focusableRegex.test(e.render.toString())));
4
+ export const Focusable = findModuleExport((e) => (typeof e == 'function' && e?.toString && focusableRegex.test(e.toString?.())) || (e?.render?.toString && focusableRegex.test(e.render.toString())));
@@ -1,2 +1,2 @@
1
1
  import { findModuleExport } from '../webpack';
2
- export const Marquee = findModuleExport((e) => e?.toString && e.toString().includes('.Marquee') && e.toString().includes('--fade-length'));
2
+ export const Marquee = findModuleExport((e) => e?.toString && e.toString?.().includes('.Marquee') && e.toString?.().includes('--fade-length'));
@@ -1,11 +1,11 @@
1
1
  import { findModuleByExport, findModuleDetailsByExport, findModuleExport } from '../webpack';
2
2
  export const showContextMenu = findModuleExport((e) => typeof e === 'function' &&
3
- e.toString().includes('GetContextMenuManagerFromWindow(') &&
4
- e.toString().includes('.CreateContextMenuInstance('));
3
+ e.toString?.().includes('GetContextMenuManagerFromWindow(') &&
4
+ e.toString?.().includes('.CreateContextMenuInstance('));
5
5
  const MenuModule = findModuleDetailsByExport((e) => e?.render?.toString()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter));
6
6
  export const Menu = findModuleExport((e) => e?.prototype?.HideIfSubmenu && e?.prototype?.HideMenu) ||
7
- Object.values(MenuModule?.[0] ?? {}).find((e) => e?.toString()?.includes?.(`useId`) && e?.toString()?.includes?.(`labelId`));
8
- const MenuGoupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`));
9
- export const MenuGroup = MenuGoupModule && Object.values(MenuGoupModule).find((e) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
7
+ Object.values(MenuModule?.[0] ?? {}).find((e) => e?.toString?.()?.includes?.(`useId`) && e?.toString?.()?.includes?.(`labelId`));
8
+ const MenuGroupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && (e?.prototype?.render?.toString().includes?.(`this.props.tone=="emphasis"`) || e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`)));
9
+ export const MenuGroup = MenuGroupModule && Object.values(MenuGroupModule).find((e) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
10
10
  export const MenuItem = MenuModule?.[1];
11
- export const MenuSeparator = findModuleExport((e) => typeof e === 'function' && /className:.+?\.ContextMenuSeparator/.test(e.toString()));
11
+ export const MenuSeparator = findModuleExport((e) => typeof e === 'function' && /className:.+?\.ContextMenuSeparator/.test(e.toString?.()));
@@ -1,6 +1,6 @@
1
1
  import { findSP } from '../utils';
2
2
  import { findModule, findModuleDetailsByExport, findModuleExport } from '../webpack';
3
- const showModalRaw = findModuleExport((e) => typeof e === 'function' && e.toString().includes('props.bDisableBackgroundDismiss') && !e?.prototype?.Cancel);
3
+ const showModalRaw = findModuleExport((e) => typeof e === 'function' && e.toString?.().includes('props.bDisableBackgroundDismiss') && !e?.prototype?.Cancel);
4
4
  export const showModal = (modal, parent, props = {
5
5
  strTitle: 'Decky Dialog',
6
6
  bHideMainWindowForPopouts: false,
@@ -9,8 +9,8 @@ export const showModal = (modal, parent, props = {
9
9
  bHideActions: props.bHideActionIcons,
10
10
  });
11
11
  };
12
- export const ConfirmModal = findModuleExport((e) => e?.toString()?.includes('bUpdateDisabled') && e?.toString()?.includes('closeModal') && e?.toString()?.includes('onGamepadCancel'));
13
- export const ModalRoot = findModuleExport((e) => typeof e === 'function' && e.toString().includes('Either closeModal or onCancel should be passed to GenericDialog. Classes: ')) ||
12
+ export const ConfirmModal = findModuleExport((e) => e?.toString?.()?.includes('bUpdateDisabled') && e?.toString?.()?.includes('closeModal') && e?.toString?.()?.includes('onGamepadCancel'));
13
+ export const ModalRoot = findModuleExport((e) => typeof e === 'function' && e.toString?.().includes('Either closeModal or onCancel should be passed to GenericDialog. Classes: ')) ||
14
14
  Object.values(findModule((m) => {
15
15
  if (typeof m !== 'object')
16
16
  return false;
@@ -21,7 +21,7 @@ export const ModalRoot = findModuleExport((e) => typeof e === 'function' && e.to
21
21
  }
22
22
  return false;
23
23
  }) || {})?.find((x) => x?.type?.toString?.()?.includes('((function(){'));
24
- const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e) => e?.toString().includes('.ModalPosition'), 5);
24
+ const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e) => e?.toString?.().includes('.ModalPosition'), 5);
25
25
  const ModalModuleProps = ModalModule ? Object.values(ModalModule) : [];
26
26
  export const SimpleModal = ModalModuleProps.find((prop) => {
27
27
  const string = prop?.toString();
@@ -1,4 +1,4 @@
1
1
  import { findModuleDetailsByExport } from '../webpack';
2
- const [mod, panelSection] = findModuleDetailsByExport((e) => e.toString()?.includes('.PanelSection'));
2
+ const [mod, panelSection] = findModuleDetailsByExport((e) => e.toString?.()?.includes('.PanelSection'));
3
3
  export const PanelSection = panelSection;
4
4
  export const PanelSectionRow = Object.values(mod).filter((exp) => !exp?.toString?.()?.includes('.PanelSection'))[0];
@@ -1,6 +1,6 @@
1
1
  import { findModuleExport } from '../webpack';
2
2
  import { createPropListRegex } from '../utils';
3
- export const ProgressBar = findModuleExport((e) => e?.toString?.()?.includes('.ProgressBar,"standard"=='));
3
+ export const ProgressBar = findModuleExport((e) => e?.toString && /\.ProgressBar,(?:\w*==)?"standard"(?:==)?/.test(e.toString?.()));
4
4
  export const ProgressBarWithInfo = findModuleExport((e) => e?.toString?.()?.includes('.ProgressBarFieldStatus,children') || e?.toString?.()?.includes('.ProgressBarFieldStatus},'));
5
5
  const progressBarItemRegex = createPropListRegex(["indeterminate", "nTransitionSec", "nProgress"]);
6
- export const ProgressBarItem = findModuleExport((e) => e?.toString && progressBarItemRegex.test(e.toString()));
6
+ export const ProgressBarItem = findModuleExport((e) => e?.toString && progressBarItemRegex.test(e.toString?.()));
@@ -1,4 +1,4 @@
1
1
  import { findModuleExport } from '../webpack';
2
2
  import { createPropListRegex } from '../utils';
3
3
  const sidebarNavigationRegex = createPropListRegex(["pages", "fnSetNavigateToPage", "disableRouteReporting"]);
4
- export const SidebarNavigation = findModuleExport((e) => e?.toString && sidebarNavigationRegex.test(e.toString()));
4
+ export const SidebarNavigation = findModuleExport((e) => e?.toString && sidebarNavigationRegex.test(e.toString?.()));
@@ -13,6 +13,7 @@ export type ReorderableListProps<T> = {
13
13
  }>;
14
14
  fieldProps?: FieldProps;
15
15
  animate?: boolean;
16
+ disableReordering?: boolean;
16
17
  };
17
18
  export declare function ReorderableList<T>(props: ReorderableListProps<T>): import("react/jsx-runtime").JSX.Element;
18
19
  export type ReorderableListEntryProps<T> = {
@@ -9,7 +9,15 @@ export function ReorderableList(props) {
9
9
  useEffect(() => {
10
10
  setEntryList([...props.entries].sort((a, b) => a.position - b.position));
11
11
  }, [props.entries]);
12
+ useEffect(() => {
13
+ if (props.disableReordering && reorderEnabled) {
14
+ setReorderEnabled(false);
15
+ props.onSave(entryList);
16
+ }
17
+ }, [props.disableReordering, reorderEnabled, entryList]);
12
18
  function toggleReorderEnabled() {
19
+ if (props.disableReordering)
20
+ return;
13
21
  let newReorderValue = !reorderEnabled;
14
22
  setReorderEnabled(newReorderValue);
15
23
  if (!newReorderValue) {
@@ -32,7 +40,7 @@ export function ReorderableList(props) {
32
40
  flexDirection: 'column',
33
41
  justifyContent: 'flex-start',
34
42
  alignContent: 'stretch',
35
- }, children: _jsx(Focusable, { onSecondaryButton: toggleReorderEnabled, onSecondaryActionDescription: reorderEnabled ? 'Save Order' : 'Reorder', onClick: toggleReorderEnabled, onButtonDown: saveOnBackout, children: entryList.map((entry) => (_jsx(ReorderableItem, { animate: props.animate, listData: entryList, entryData: entry, reorderEntryFunc: setEntryList, reorderEnabled: reorderEnabled, fieldProps: props.fieldProps, children: props.interactables ? _jsx(props.interactables, { entry: entry }) : null }))) }) }) }));
43
+ }, children: _jsx(Focusable, { onSecondaryButton: props.disableReordering ? undefined : toggleReorderEnabled, onSecondaryActionDescription: props.disableReordering ? undefined : reorderEnabled ? 'Save Order' : 'Reorder', onClick: props.disableReordering ? undefined : toggleReorderEnabled, onButtonDown: saveOnBackout, children: entryList.map((entry) => (_jsx(ReorderableItem, { animate: props.animate, listData: entryList, entryData: entry, reorderEntryFunc: setEntryList, reorderEnabled: reorderEnabled, fieldProps: props.fieldProps, children: props.interactables ? _jsx(props.interactables, { entry: entry }) : null }))) }) }) }));
36
44
  }
37
45
  function ReorderableItem(props) {
38
46
  const [isSelected, _setIsSelected] = useState(false);
@@ -1,2 +1,2 @@
1
1
  import { ReactRouter } from '../webpack';
2
- export const useParams = Object.values(ReactRouter).find((val) => /return (\w)\?\1\.params:{}/.test(`${val}`));
2
+ export const useParams = Object.values(ReactRouter).find((val) => /return (\w*)\?\1\.params:{}/.test(`${val}`));
package/dist/webpack.js CHANGED
@@ -59,7 +59,7 @@ export const findModuleDetailsByExport = (filter, minExports) => {
59
59
  }
60
60
  }
61
61
  catch (e) {
62
- logger.warn("Webpack filter threw exception: ", e);
62
+ logger.warn("Webpack filter threw exception: ", e, "Filter: ", filter);
63
63
  }
64
64
  }
65
65
  }
@@ -117,5 +117,5 @@ export const CommonUIModule = findModule((m) => {
117
117
  }
118
118
  return false;
119
119
  });
120
- export const IconsModule = findModuleByExport((e) => e?.toString && /Spinner\),children:\[\(0,\w+\.jsx\)\("path",\{d:"M18 /.test(e.toString()) || /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(e.toString()));
120
+ export const IconsModule = findModuleByExport((e) => e?.toString && /Spinner\),children:\[\(0,\w+\.jsx\)\("path",\{d:"M18 /.test(e.toString?.()) || /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(e.toString?.()));
121
121
  export const ReactRouter = findModuleByExport((e) => e.computeRootMatch);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decky/ui",
3
- "version": "4.11.6",
3
+ "version": "4.12.1",
4
4
  "description": "A library for interacting with the Steam frontend in Decky plugins and elsewhere.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,5 +10,5 @@ export interface ControlsListProps {
10
10
 
11
11
  export const ControlsList: FC<ControlsListProps> = findModuleExport(
12
12
  (e: Export) =>
13
- e?.toString && e.toString().includes('().ControlsListChild') && e.toString().includes('().ControlsListOuterPanel'),
13
+ e?.toString && e.toString?.().includes('().ControlsListChild') && e.toString?.().includes('().ControlsListOuterPanel'),
14
14
  );
@@ -25,6 +25,6 @@ export interface FieldProps extends FooterLegendProps {
25
25
  }
26
26
 
27
27
  // new || old
28
- export const Field = findModuleExport((e: Export) => (e?.toString()?.includes('().Field') && e?.toString()?.includes('"shift-children-below"')) || e?.render?.toString()?.includes('"shift-children-below"')) as FC<
28
+ export const Field = findModuleExport((e: Export) => (e?.toString?.()?.includes('().Field') && e?.toString?.()?.includes('"shift-children-below"')) || e?.render?.toString()?.includes('"shift-children-below"')) as FC<
29
29
  FieldProps & RefAttributes<HTMLDivElement>
30
30
  >;
@@ -17,5 +17,5 @@ export interface FocusableProps extends HTMLAttributes<HTMLDivElement>, FooterLe
17
17
  const focusableRegex = createPropListRegex(["flow-children", "onActivate", "onCancel", "focusClassName", "focusWithinClassName"]);
18
18
 
19
19
  export const Focusable = findModuleExport((e: Export) =>
20
- (typeof e == 'function' && e?.toString && focusableRegex.test(e.toString())) || (e?.render?.toString && focusableRegex.test(e.render.toString()))
20
+ (typeof e == 'function' && e?.toString && focusableRegex.test(e.toString?.())) || (e?.render?.toString && focusableRegex.test(e.render.toString()))
21
21
  ) as FC<FocusableProps & RefAttributes<HTMLDivElement>>;
@@ -16,5 +16,5 @@ export interface MarqueeProps {
16
16
  }
17
17
 
18
18
  export const Marquee: FC<MarqueeProps> = findModuleExport(
19
- (e: Export) => e?.toString && e.toString().includes('.Marquee') && e.toString().includes('--fade-length'),
19
+ (e: Export) => e?.toString && e.toString?.().includes('.Marquee') && e.toString?.().includes('--fade-length'),
20
20
  );
@@ -123,8 +123,8 @@ export const showContextMenu: (
123
123
  ) => ContextMenuInstance = findModuleExport(
124
124
  (e: Export) =>
125
125
  typeof e === 'function' &&
126
- e.toString().includes('GetContextMenuManagerFromWindow(') &&
127
- e.toString().includes('.CreateContextMenuInstance('),
126
+ e.toString?.().includes('GetContextMenuManagerFromWindow(') &&
127
+ e.toString?.().includes('.CreateContextMenuInstance('),
128
128
  );
129
129
 
130
130
  export interface MenuProps extends FooterLegendProps {
@@ -138,7 +138,7 @@ const MenuModule = findModuleDetailsByExport((e: Export) => e?.render?.toString(
138
138
 
139
139
  export const Menu: FC<MenuProps> =
140
140
  findModuleExport((e: Export) => e?.prototype?.HideIfSubmenu && e?.prototype?.HideMenu) || // Legacy Menu
141
- (Object.values(MenuModule?.[0] ?? {}).find((e) => e?.toString()?.includes?.(`useId`) && e?.toString()?.includes?.(`labelId`)) as FC<MenuProps>); // New Menu 6/15/2025
141
+ (Object.values(MenuModule?.[0] ?? {}).find((e) => e?.toString?.()?.includes?.(`useId`) && e?.toString?.()?.includes?.(`labelId`)) as FC<MenuProps>); // New Menu 6/15/2025
142
142
 
143
143
  export interface MenuGroupProps {
144
144
  label: string;
@@ -146,8 +146,9 @@ export interface MenuGroupProps {
146
146
  children?: ReactNode;
147
147
  }
148
148
 
149
- const MenuGoupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`));
150
- export const MenuGroup: FC<MenuGroupProps> = MenuGoupModule && Object.values(MenuGoupModule).find((e: Export) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
149
+ // New || Old 9/14/2026
150
+ const MenuGroupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && (e?.prototype?.render?.toString().includes?.(`this.props.tone=="emphasis"`) || e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`)));
151
+ export const MenuGroup: FC<MenuGroupProps> = MenuGroupModule && Object.values(MenuGroupModule).find((e: Export) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
151
152
  export interface MenuItemProps extends FooterLegendProps {
152
153
  bInteractableItem?: boolean;
153
154
  onClick?(evt: Event): void;
@@ -164,7 +165,7 @@ export interface MenuItemProps extends FooterLegendProps {
164
165
  export const MenuItem: FC<MenuItemProps> = MenuModule?.[1];
165
166
 
166
167
  export const MenuSeparator: FC = findModuleExport(
167
- (e: Export) => typeof e === 'function' && /className:.+?\.ContextMenuSeparator/.test(e.toString()),
168
+ (e: Export) => typeof e === 'function' && /className:.+?\.ContextMenuSeparator/.test(e.toString?.()),
168
169
  );
169
170
 
170
171
  /*
@@ -39,7 +39,7 @@ const showModalRaw: (
39
39
  modalManager?: unknown,
40
40
  ) => ShowModalResult = findModuleExport(
41
41
  (e: Export) =>
42
- typeof e === 'function' && e.toString().includes('props.bDisableBackgroundDismiss') && !e?.prototype?.Cancel,
42
+ typeof e === 'function' && e.toString?.().includes('props.bDisableBackgroundDismiss') && !e?.prototype?.Cancel,
43
43
  );
44
44
 
45
45
  export const showModal = (
@@ -83,12 +83,12 @@ export interface ConfirmModalProps extends ModalRootProps {
83
83
  }
84
84
 
85
85
  export const ConfirmModal = findModuleExport(
86
- (e: Export) => e?.toString()?.includes('bUpdateDisabled') && e?.toString()?.includes('closeModal') && e?.toString()?.includes('onGamepadCancel'),
86
+ (e: Export) => e?.toString?.()?.includes('bUpdateDisabled') && e?.toString?.()?.includes('closeModal') && e?.toString?.()?.includes('onGamepadCancel'),
87
87
  ) as FC<ConfirmModalProps>;
88
88
 
89
89
  export const ModalRoot =
90
90
  // new
91
- findModuleExport((e: Export) => typeof e === 'function' && e.toString().includes('Either closeModal or onCancel should be passed to GenericDialog. Classes: ')) ||
91
+ findModuleExport((e: Export) => typeof e === 'function' && e.toString?.().includes('Either closeModal or onCancel should be passed to GenericDialog. Classes: ')) ||
92
92
  // old
93
93
  Object.values(
94
94
  findModule((m: any) => {
@@ -109,7 +109,7 @@ interface SimpleModalProps {
109
109
  children: ReactNode;
110
110
  }
111
111
 
112
- const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e: Export) => e?.toString().includes('.ModalPosition'), 5)
112
+ const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e: Export) => e?.toString?.().includes('.ModalPosition'), 5)
113
113
 
114
114
  const ModalModuleProps = ModalModule ? Object.values(ModalModule) : [];
115
115
 
@@ -14,7 +14,7 @@ export interface PanelSectionProps {
14
14
  children?: ReactNode;
15
15
  }
16
16
 
17
- const [mod, panelSection] = findModuleDetailsByExport((e: Export) => e.toString()?.includes('.PanelSection'));
17
+ const [mod, panelSection] = findModuleDetailsByExport((e: Export) => e.toString?.()?.includes('.PanelSection'));
18
18
 
19
19
  export const PanelSection = panelSection as FC<PanelSectionProps>;
20
20
 
@@ -24,7 +24,7 @@ export interface ProgressBarWithInfoProps extends ProgressBarItemProps {
24
24
  }
25
25
 
26
26
  export const ProgressBar = findModuleExport((e: Export) =>
27
- e?.toString?.()?.includes('.ProgressBar,"standard"=='),
27
+ e?.toString && /\.ProgressBar,(?:\w*==)?"standard"(?:==)?/.test(e.toString?.()),
28
28
  ) as FC<ProgressBarProps>;
29
29
 
30
30
  export const ProgressBarWithInfo = findModuleExport((e: Export) =>
@@ -34,5 +34,5 @@ export const ProgressBarWithInfo = findModuleExport((e: Export) =>
34
34
 
35
35
  const progressBarItemRegex = createPropListRegex(["indeterminate", "nTransitionSec", "nProgress"]);
36
36
  export const ProgressBarItem = findModuleExport((e: Export) =>
37
- e?.toString && progressBarItemRegex.test(e.toString()),
37
+ e?.toString && progressBarItemRegex.test(e.toString?.()),
38
38
  ) as FC<ProgressBarItemProps>;
@@ -26,5 +26,5 @@ export interface SidebarNavigationProps {
26
26
 
27
27
  const sidebarNavigationRegex = createPropListRegex(["pages", "fnSetNavigateToPage", "disableRouteReporting"]);
28
28
  export const SidebarNavigation = findModuleExport((e: Export) =>
29
- e?.toString && sidebarNavigationRegex.test(e.toString()),
29
+ e?.toString && sidebarNavigationRegex.test(e.toString?.()),
30
30
  ) as FC<SidebarNavigationProps>;
@@ -18,6 +18,7 @@ export type ReorderableEntry<T> = {
18
18
  * Properties for a ReorderableList component of type <T>.
19
19
  *
20
20
  * @param animate If the list should animate. @default true
21
+ * @param disableReordering If true, prevents entering reordering mode and hides reorder instructions. @default false
21
22
  */
22
23
  export type ReorderableListProps<T> = {
23
24
  entries: ReorderableEntry<T>[];
@@ -25,6 +26,7 @@ export type ReorderableListProps<T> = {
25
26
  interactables?: JSXElementConstructor<{ entry: ReorderableEntry<T> }>;
26
27
  fieldProps?: FieldProps;
27
28
  animate?: boolean;
29
+ disableReordering?: boolean;
28
30
  };
29
31
 
30
32
  /**
@@ -43,7 +45,16 @@ export function ReorderableList<T>(props: ReorderableListProps<T>) {
43
45
  setEntryList([...props.entries].sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position));
44
46
  }, [props.entries]);
45
47
 
48
+ useEffect(() => {
49
+ if (props.disableReordering && reorderEnabled) {
50
+ setReorderEnabled(false);
51
+ props.onSave(entryList);
52
+ }
53
+ }, [props.disableReordering, reorderEnabled, entryList]);
54
+
46
55
  function toggleReorderEnabled(): void {
56
+ if (props.disableReordering) return;
57
+
47
58
  let newReorderValue = !reorderEnabled;
48
59
  setReorderEnabled(newReorderValue);
49
60
 
@@ -75,9 +86,9 @@ export function ReorderableList<T>(props: ReorderableListProps<T>) {
75
86
  }}
76
87
  >
77
88
  <Focusable
78
- onSecondaryButton={toggleReorderEnabled}
79
- onSecondaryActionDescription={reorderEnabled ? 'Save Order' : 'Reorder'}
80
- onClick={toggleReorderEnabled}
89
+ onSecondaryButton={props.disableReordering ? undefined : toggleReorderEnabled}
90
+ onSecondaryActionDescription={props.disableReordering ? undefined : reorderEnabled ? 'Save Order' : 'Reorder'}
91
+ onClick={props.disableReordering ? undefined : toggleReorderEnabled}
81
92
  onButtonDown={saveOnBackout}
82
93
  >
83
94
  {entryList.map((entry: ReorderableEntry<T>) => (
@@ -10,6 +10,6 @@ import { ReactRouter } from '../webpack';
10
10
  *
11
11
  * const { appid } = useParams<{ appid: string }>()
12
12
  */
13
- export const useParams = Object.values(ReactRouter).find((val) => /return (\w)\?\1\.params:{}/.test(`${val}`)) as <
13
+ export const useParams = Object.values(ReactRouter).find((val) => /return (\w*)\?\1\.params:{}/.test(`${val}`)) as <
14
14
  T,
15
15
  >() => T;
package/src/webpack.ts CHANGED
@@ -85,7 +85,7 @@ export const findModuleDetailsByExport = (
85
85
  continue;
86
86
  }
87
87
  } catch (e) {
88
- logger.warn("Webpack filter threw exception: ", e);
88
+ logger.warn("Webpack filter threw exception: ", e, "Filter: ", filter);
89
89
  }
90
90
  }
91
91
  }
@@ -154,7 +154,7 @@ export const CommonUIModule = findModule((m: Module) => {
154
154
  });
155
155
 
156
156
  export const IconsModule = findModuleByExport(
157
- (e) => e?.toString && /Spinner\),children:\[\(0,\w+\.jsx\)\("path",\{d:"M18 /.test(e.toString()) || /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(e.toString()),
157
+ (e) => e?.toString && /Spinner\),children:\[\(0,\w+\.jsx\)\("path",\{d:"M18 /.test(e.toString?.()) || /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(e.toString?.()),
158
158
  );
159
159
 
160
160
  export const ReactRouter = findModuleByExport((e) => e.computeRootMatch);