fix(custom-widgets): stabilize commands and resolve dismissed confirmations
This commit is contained in:
1 parent
8f152f1929
commit
de75c5f29d
3 files changed
+22
-10
No files matched your search
@@ -77,6 +77,11 @@ Homarr provides React, Mantine, and `@homarr/widget-sdk` as shared host modules.
|
||||
from Homarr's installed version, which is recorded in the artifact lock. The reference packages show how to use the SDK for host dimensions, theme and locale, options, state, commands, data queries, and advanced
|
||||
views. Put additional dependencies in the package's dependency map rather than copying Homarr's internal source tree.
|
||||
|
||||
Use `WidgetScope` to compose components with independent state and command IDs. Commands registered through
|
||||
`useWidgetCommands` remain registered across unrelated host updates and are removed when their component unmounts.
|
||||
`useWidgetServices().confirm(...)` resolves to `true` on confirmation and `false` on cancellation or dismissal,
|
||||
including Escape, a backdrop click, or the close button.
|
||||
|
||||
## Convert an existing Custom JSX widget
|
||||
|
||||
Choose **Convert to a widget package** from a valid Custom JSX widget's list row or editor. Conversion uses its saved
|
||||
|
||||
@@ -53,6 +53,11 @@ export function WidgetScope({
|
||||
}>) {
|
||||
const runtime = useWidgetRuntime();
|
||||
const parent = runtime.services;
|
||||
const registerParentCommands = parent.registerCommands;
|
||||
const registerCommands = useCallback<WidgetHostServices["registerCommands"]>(
|
||||
(commands) => registerParentCommands(commands.map((command) => ({ ...command, id: `${name}:${command.id}` }))),
|
||||
[name, registerParentCommands],
|
||||
);
|
||||
const services = useMemo<WidgetHostServices>(() => {
|
||||
const operation = (input: Parameters<WidgetHostServices["transport"]["query"]>[0]) => ({
|
||||
...input,
|
||||
@@ -65,8 +70,7 @@ export function WidgetScope({
|
||||
set: (key, value) => parent.state.set(`${name}:${key}`, value),
|
||||
subscribe: parent.state.subscribe,
|
||||
},
|
||||
registerCommands: (commands) =>
|
||||
parent.registerCommands(commands.map((command) => ({ ...command, id: `${name}:${command.id}` }))),
|
||||
registerCommands,
|
||||
transport: {
|
||||
query: (input, signal) => parent.transport.query(operation(input), signal),
|
||||
action: (input) => parent.transport.action(operation(input)),
|
||||
@@ -75,7 +79,7 @@ export function WidgetScope({
|
||||
storageSet: (input) => parent.transport.storageSet({ ...input, key: `${name}:${input.key}` }),
|
||||
},
|
||||
};
|
||||
}, [handlerPrefix, name, parent]);
|
||||
}, [handlerPrefix, name, parent, registerCommands]);
|
||||
const scope = `${runtime.context.scope ?? ""}/${name}`;
|
||||
return (
|
||||
<WidgetContext.Provider
|
||||
|
||||
@@ -147,13 +147,16 @@ export function TrustedWidgetHost({
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
openConfirmModal({
|
||||
title,
|
||||
children: message,
|
||||
confirmProps: { color: destructive ? "red" : undefined },
|
||||
onConfirm: () => resolve(true),
|
||||
onCancel: () => resolve(false),
|
||||
});
|
||||
openConfirmModal(
|
||||
{
|
||||
title,
|
||||
children: message,
|
||||
confirmProps: { color: destructive ? "red" : undefined },
|
||||
onConfirm: () => resolve(true),
|
||||
onCancel: () => resolve(false),
|
||||
},
|
||||
{ onClose: () => resolve(false) },
|
||||
);
|
||||
}),
|
||||
}),
|
||||
[
|
||||
|
||||
Reference in new issue
Block a user