@babylonjs/shared-ui-components 9.9.1 → 9.10.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/fluent/hoc/childWindow.js +45 -130
- package/fluent/hoc/childWindow.js.map +1 -1
- package/fluent/hoc/popupWindow.d.ts +75 -0
- package/fluent/hoc/popupWindow.js +156 -0
- package/fluent/hoc/popupWindow.js.map +1 -0
- package/fluent/primitives/button.d.ts +12 -0
- package/fluent/primitives/button.js +2 -2
- package/fluent/primitives/button.js.map +1 -1
- package/fluent/primitives/dialog.js +1 -1
- package/fluent/primitives/dialog.js.map +1 -1
- package/fluent/primitives/toggleButton.d.ts +2 -0
- package/fluent/primitives/toggleButton.js +2 -2
- package/fluent/primitives/toggleButton.js.map +1 -1
- package/fluent/primitives/tooltip.d.ts +8 -0
- package/fluent/primitives/tooltip.js +2 -2
- package/fluent/primitives/tooltip.js.map +1 -1
- package/modularTool/components/errorBoundary.js +3 -0
- package/modularTool/components/errorBoundary.js.map +1 -1
- package/modularTool/components/theme.d.ts +5 -0
- package/modularTool/components/theme.js +27 -3
- package/modularTool/components/theme.js.map +1 -1
- package/modularTool/contexts/dialogContext.d.ts +14 -0
- package/modularTool/contexts/dialogContext.js +13 -0
- package/modularTool/contexts/dialogContext.js.map +1 -0
- package/modularTool/modularTool.js +64 -3
- package/modularTool/modularTool.js.map +1 -1
- package/modularTool/services/dialogService.d.ts +22 -0
- package/modularTool/services/dialogService.js +5 -0
- package/modularTool/services/dialogService.js.map +1 -0
- package/modularTool/services/shellService.js +15 -0
- package/modularTool/services/shellService.js.map +1 -1
- package/nodeGraphSystem/graphCanvas.d.ts +5 -1
- package/nodeGraphSystem/graphCanvas.js +6 -2
- package/nodeGraphSystem/graphCanvas.js.map +1 -1
- package/nodeGraphSystem/graphNode.d.ts +5 -1
- package/nodeGraphSystem/graphNode.js +13 -5
- package/nodeGraphSystem/graphNode.js.map +1 -1
- package/nodeGraphSystem/nodeLink.d.ts +6 -1
- package/nodeGraphSystem/nodeLink.js +9 -2
- package/nodeGraphSystem/nodeLink.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACzJ,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AA8BlC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,MAAM,GAAoB,CAAC,KAAK,EAAE,EAAE;IAC7C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAE5D,OAAO,CACH,KAAC,YAAY,IACT,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,OAAO,EACjB,YAAY,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;YACtB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC1B,SAAS,EAAE,CAAC;YAChB,CAAC;QACL,CAAC,YAED,KAAC,aAAa,cACV,MAAC,UAAU,eACP,KAAC,WAAW,IACR,MAAM,EACF,SAAS,CAAC,CAAC,CAAC,CACR,KAAC,aAAa,IAAC,MAAM,EAAC,OAAO,YACzB,KAAC,MAAM,IAAC,UAAU,EAAC,QAAQ,
|
|
1
|
+
{"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACzJ,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AA8BlC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,MAAM,GAAoB,CAAC,KAAK,EAAE,EAAE;IAC7C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAE5D,OAAO,CACH,KAAC,YAAY,IACT,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,OAAO,EACjB,YAAY,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;YACtB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC1B,SAAS,EAAE,CAAC;YAChB,CAAC;QACL,CAAC,YAED,KAAC,aAAa,cACV,MAAC,UAAU,eACP,KAAC,WAAW,IACR,MAAM,EACF,SAAS,CAAC,CAAC,CAAC,CACR,KAAC,aAAa,IAAC,MAAM,EAAC,OAAO,YACzB,KAAC,MAAM,IAAC,UAAU,EAAC,QAAQ,EAAC,SAAS,EAAC,OAAO,EAAC,IAAI,EAAE,cAAc,GAAI,GAC1D,CACnB,CAAC,CAAC,CAAC,SAAS,YAGhB,KAAK,GACI,EACd,KAAC,aAAa,cAAE,QAAQ,GAAiB,EACxC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAC9B,KAAC,aAAa,cACT,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5B,KAAC,MAAM,IAAa,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAjG,KAAK,CAAgG,CACrH,CAAC,GACU,CACnB,IACQ,GACD,GACL,CAClB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { Dialog as FluentDialog, DialogSurface, DialogBody, DialogTitle, DialogContent, DialogActions, DialogTrigger } from \"@fluentui/react-components\";\nimport { DismissRegular } from \"@fluentui/react-icons\";\nimport { type ReactNode, type FC } from \"react\";\nimport { Button } from \"./button\";\n\n/**\n * Props for an action button in the dialog footer.\n */\nexport type DialogActionProps = {\n /** Button label text. */\n label: string;\n /** Click handler. */\n onClick: () => void;\n /** Button appearance. Defaults to \"secondary\". */\n appearance?: \"primary\" | \"secondary\";\n};\n\n/**\n * Props for the shared Dialog primitive.\n */\nexport type DialogProps = {\n /** Whether the dialog is open. */\n open: boolean;\n /** Dialog title. */\n title: string;\n /** Dialog content (body). */\n children: ReactNode;\n /** Action buttons rendered in the footer. */\n actions?: DialogActionProps[];\n /** Called when the dialog is dismissed via the close button. */\n onDismiss?: () => void;\n};\n\n/**\n * A shared dialog component wrapping Fluent UI Dialog with Babylon conventions.\n *\n * @example\n * ```tsx\n * <Dialog\n * open={isOpen}\n * title=\"Confirm Action\"\n * onDismiss={() => setIsOpen(false)}\n * actions={[\n * { label: \"Cancel\", onClick: () => setIsOpen(false) },\n * { label: \"Confirm\", onClick: handleConfirm, appearance: \"primary\" },\n * ]}\n * >\n * <Text>Are you sure you want to proceed?</Text>\n * </Dialog>\n * ```\n *\n * @param props - The dialog props.\n * @returns The dialog element.\n */\nexport const Dialog: FC<DialogProps> = (props) => {\n const { open, title, children, actions, onDismiss } = props;\n\n return (\n <FluentDialog\n open={open}\n modalType=\"modal\"\n onOpenChange={(_, data) => {\n if (!data.open && onDismiss) {\n onDismiss();\n }\n }}\n >\n <DialogSurface>\n <DialogBody>\n <DialogTitle\n action={\n onDismiss ? (\n <DialogTrigger action=\"close\">\n <Button appearance=\"subtle\" ariaLabel=\"close\" icon={DismissRegular} />\n </DialogTrigger>\n ) : undefined\n }\n >\n {title}\n </DialogTitle>\n <DialogContent>{children}</DialogContent>\n {actions && actions.length > 0 && (\n <DialogActions>\n {actions.map((action, index) => (\n <Button key={index} appearance={action.appearance ?? \"secondary\"} onClick={action.onClick} label={action.label} />\n ))}\n </DialogActions>\n )}\n </DialogBody>\n </DialogSurface>\n </FluentDialog>\n );\n};\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TooltipProps } from "@fluentui/react-components";
|
|
1
2
|
import { type ButtonProps } from "./button.js";
|
|
2
3
|
import { type FunctionComponent } from "react";
|
|
3
4
|
import { type FluentIcon } from "@fluentui/react-icons";
|
|
@@ -6,6 +7,7 @@ type ToggleButtonProps = Omit<ButtonProps, "icon" | "onClick"> & {
|
|
|
6
7
|
checkedIcon: FluentIcon;
|
|
7
8
|
uncheckedIcon?: FluentIcon;
|
|
8
9
|
onChange: (checked: boolean) => void;
|
|
10
|
+
titlePositioning?: TooltipProps["positioning"];
|
|
9
11
|
};
|
|
10
12
|
/**
|
|
11
13
|
* Toggles between two states using a button with icons.
|
|
@@ -19,7 +19,7 @@ const useStyles = makeStyles({
|
|
|
19
19
|
*/
|
|
20
20
|
export const ToggleButton = (props) => {
|
|
21
21
|
ToggleButton.displayName = "ToggleButton";
|
|
22
|
-
const { value, onChange, title, appearance = "subtle" } = props;
|
|
22
|
+
const { value, onChange, title, appearance = "subtle", ariaLabel } = props;
|
|
23
23
|
const { size } = useContext(ToolContext);
|
|
24
24
|
const classes = useStyles();
|
|
25
25
|
const [checked, setChecked] = useState(value);
|
|
@@ -33,6 +33,6 @@ export const ToggleButton = (props) => {
|
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
setChecked(props.value);
|
|
35
35
|
}, [props.value]);
|
|
36
|
-
return (_jsx(Tooltip, { content: title ?? "", children: _jsx(FluentToggleButton, { className: classes.button, size: size, icon: checked ? _jsx(props.checkedIcon, {}) : props.uncheckedIcon ? _jsx(props.uncheckedIcon, {}) : _jsx(props.checkedIcon, {}), appearance: appearance, checked: checked, onClick: toggle }) }));
|
|
36
|
+
return (_jsx(Tooltip, { content: title ?? "", positioning: props.titlePositioning, children: _jsx(FluentToggleButton, { className: classes.button, size: size, "aria-label": ariaLabel ?? title, icon: checked ? _jsx(props.checkedIcon, {}) : props.uncheckedIcon ? _jsx(props.uncheckedIcon, {}) : _jsx(props.checkedIcon, {}), appearance: appearance, checked: checked, onClick: toggle }) }));
|
|
37
37
|
};
|
|
38
38
|
//# sourceMappingURL=toggleButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggleButton.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/toggleButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"toggleButton.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/toggleButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,UAAU,EAAqB,MAAM,4BAA4B,CAAC;AAE/G,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAA0B,MAAM,OAAO,CAAC;AAE7F,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,MAAM,EAAE;QACJ,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;KAC3B;CACJ,CAAC,CAAC;AAUH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAyC,CAAC,KAAK,EAAE,EAAE;IACxE,YAAY,CAAC,WAAW,GAAG,cAAc,CAAC;IAC1C,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAC3E,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,UAAU,CAAC,CAAC,WAAW,EAAE,EAAE;YACvB,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC;YAC7B,QAAQ,CAAC,OAAO,CAAC,CAAC;YAClB,OAAO,OAAO,CAAC;QACnB,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,SAAS,CAAC,GAAG,EAAE;QACX,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElB,OAAO,CACH,KAAC,OAAO,IAAC,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,gBAAgB,YAC9D,KAAC,kBAAkB,IACf,SAAS,EAAE,OAAO,CAAC,MAAM,EACzB,IAAI,EAAE,IAAI,gBACE,SAAS,IAAI,KAAK,EAC9B,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,WAAW,KAAG,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,aAAa,KAAG,CAAC,CAAC,CAAC,KAAC,KAAK,CAAC,WAAW,KAAG,EAC7G,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACjB,GACI,CACb,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { ToggleButton as FluentToggleButton, makeStyles, type TooltipProps } from \"@fluentui/react-components\";\r\nimport { type ButtonProps } from \"./button\";\r\nimport { useCallback, useContext, useEffect, useState, type FunctionComponent } from \"react\";\r\nimport { type FluentIcon } from \"@fluentui/react-icons\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { Tooltip } from \"./tooltip\";\r\n\r\nconst useStyles = makeStyles({\r\n button: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n },\r\n});\r\n\r\ntype ToggleButtonProps = Omit<ButtonProps, \"icon\" | \"onClick\"> & {\r\n value: boolean;\r\n checkedIcon: FluentIcon;\r\n uncheckedIcon?: FluentIcon;\r\n onChange: (checked: boolean) => void;\r\n titlePositioning?: TooltipProps[\"positioning\"];\r\n};\r\n\r\n/**\r\n * Toggles between two states using a button with icons.\r\n * If no disabledIcon is provided, the button will toggle between visual enabled/disabled states without an icon change\r\n *\r\n * @param props\r\n * @returns\r\n */\r\nexport const ToggleButton: FunctionComponent<ToggleButtonProps> = (props) => {\r\n ToggleButton.displayName = \"ToggleButton\";\r\n const { value, onChange, title, appearance = \"subtle\", ariaLabel } = props;\r\n const { size } = useContext(ToolContext);\r\n const classes = useStyles();\r\n const [checked, setChecked] = useState(value);\r\n const toggle = useCallback(() => {\r\n setChecked((prevChecked) => {\r\n const enabled = !prevChecked;\r\n onChange(enabled);\r\n return enabled;\r\n });\r\n }, [onChange]);\r\n\r\n useEffect(() => {\r\n setChecked(props.value);\r\n }, [props.value]);\r\n\r\n return (\r\n <Tooltip content={title ?? \"\"} positioning={props.titlePositioning}>\r\n <FluentToggleButton\r\n className={classes.button}\r\n size={size}\r\n aria-label={ariaLabel ?? title}\r\n icon={checked ? <props.checkedIcon /> : props.uncheckedIcon ? <props.uncheckedIcon /> : <props.checkedIcon />}\r\n appearance={appearance}\r\n checked={checked}\r\n onClick={toggle}\r\n />\r\n </Tooltip>\r\n );\r\n};\r\n"]}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { type Nullable } from "@babylonjs/core/index.js";
|
|
2
2
|
import { type ReactElement } from "react";
|
|
3
|
+
import { type TooltipProps as FluentTooltipProps } from "@fluentui/react-components";
|
|
4
|
+
/**
|
|
5
|
+
* Props for the Tooltip primitive.
|
|
6
|
+
*/
|
|
3
7
|
export type TooltipProps = {
|
|
8
|
+
/** The tooltip content. If null/empty, the tooltip is not rendered. */
|
|
4
9
|
content?: Nullable<string | ReactElement>;
|
|
10
|
+
/** Optional positioning passed through to the underlying FluentTooltip. */
|
|
11
|
+
positioning?: FluentTooltipProps["positioning"];
|
|
12
|
+
/** The element that the tooltip is attached to. */
|
|
5
13
|
children: ReactElement;
|
|
6
14
|
};
|
|
7
15
|
export declare const Tooltip: import("react").ForwardRefExoticComponent<TooltipProps & import("react").RefAttributes<HTMLElement>>;
|
|
@@ -4,11 +4,11 @@ import { Tooltip as FluentTooltip } from "@fluentui/react-components";
|
|
|
4
4
|
// forwardRef wrapper to avoid "function components cannot be given refs" warning
|
|
5
5
|
// FluentTooltip handles ref forwarding to children internally via applyTriggerPropsToChildren
|
|
6
6
|
export const Tooltip = forwardRef((props, _ref) => {
|
|
7
|
-
const { content, children } = props;
|
|
7
|
+
const { content, positioning, children } = props;
|
|
8
8
|
if (!content) {
|
|
9
9
|
return children;
|
|
10
10
|
}
|
|
11
|
-
return (_jsx(FluentTooltip, { relationship: "description", content: content, children: children }));
|
|
11
|
+
return (_jsx(FluentTooltip, { relationship: "description", content: content, positioning: positioning, children: children }));
|
|
12
12
|
});
|
|
13
13
|
Tooltip.displayName = "Tooltip";
|
|
14
14
|
//# sourceMappingURL=tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/tooltip.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAqB,UAAU,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAE,OAAO,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/tooltip.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAqB,UAAU,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAE,OAAO,IAAI,aAAa,EAA2C,MAAM,4BAA4B,CAAC;AAc/G,iFAAiF;AACjF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAA4B,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACzE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,OAAO,CACH,KAAC,aAAa,IAAC,YAAY,EAAC,aAAa,EAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,YAC/E,QAAQ,GACG,CACnB,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC","sourcesContent":["import { type Nullable } from \"core/index\";\r\n\r\nimport { type ReactElement, forwardRef } from \"react\";\r\n\r\nimport { Tooltip as FluentTooltip, type TooltipProps as FluentTooltipProps } from \"@fluentui/react-components\";\r\n\r\n/**\r\n * Props for the Tooltip primitive.\r\n */\r\nexport type TooltipProps = {\r\n /** The tooltip content. If null/empty, the tooltip is not rendered. */\r\n content?: Nullable<string | ReactElement>;\r\n /** Optional positioning passed through to the underlying FluentTooltip. */\r\n positioning?: FluentTooltipProps[\"positioning\"];\r\n /** The element that the tooltip is attached to. */\r\n children: ReactElement;\r\n};\r\n\r\n// forwardRef wrapper to avoid \"function components cannot be given refs\" warning\r\n// FluentTooltip handles ref forwarding to children internally via applyTriggerPropsToChildren\r\nexport const Tooltip = forwardRef<HTMLElement, TooltipProps>((props, _ref) => {\r\n const { content, positioning, children } = props;\r\n\r\n if (!content) {\r\n return children;\r\n }\r\n\r\n return (\r\n <FluentTooltip relationship=\"description\" content={content} positioning={positioning}>\r\n {children}\r\n </FluentTooltip>\r\n );\r\n});\r\n\r\nTooltip.displayName = \"Tooltip\";\r\n"]}
|
|
@@ -13,6 +13,9 @@ const useStyles = makeStyles({
|
|
|
13
13
|
padding: TokenMap.px20,
|
|
14
14
|
backgroundColor: tokens.colorNeutralBackground1,
|
|
15
15
|
color: tokens.colorNeutralForeground1,
|
|
16
|
+
// Claim the full row of the flex parent (e.g. shellService's central-content row)
|
|
17
|
+
// so the centered children sit in the middle of the available area, not at the left edge.
|
|
18
|
+
flex: 1,
|
|
16
19
|
height: "100%",
|
|
17
20
|
minHeight: "100px",
|
|
18
21
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorBoundary.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/errorBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type ErrorInfo, type ReactNode, Component } from \"react\";\r\n\r\nimport { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { ErrorCircleRegular } from \"@fluentui/react-icons\";\r\nimport { Button } from \"shared-ui-components/fluent/primitives/button\";\r\nimport { TokenMap } from \"shared-ui-components/fluent/primitives/utils\";\r\n\r\nconst useStyles = makeStyles({\r\n root: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n padding: TokenMap.px20,\r\n backgroundColor: tokens.colorNeutralBackground1,\r\n color: tokens.colorNeutralForeground1,\r\n height: \"100%\",\r\n minHeight: \"100px\",\r\n },\r\n icon: {\r\n fontSize: \"48px\",\r\n color: tokens.colorPaletteRedForeground1,\r\n marginBottom: TokenMap.px12,\r\n },\r\n title: {\r\n fontSize: TokenMap.px16,\r\n fontWeight: \"600\",\r\n marginBottom: TokenMap.px8,\r\n },\r\n message: {\r\n fontSize: TokenMap.px12,\r\n color: tokens.colorNeutralForeground2,\r\n marginBottom: TokenMap.px16,\r\n textAlign: \"center\",\r\n maxWidth: \"300px\",\r\n },\r\n details: {\r\n fontSize: TokenMap.px10,\r\n color: tokens.colorNeutralForeground3,\r\n fontFamily: \"monospace\",\r\n whiteSpace: \"pre-wrap\",\r\n maxHeight: \"100px\",\r\n overflow: \"auto\",\r\n padding: TokenMap.px8,\r\n backgroundColor: tokens.colorNeutralBackground3,\r\n borderRadius: TokenMap.px4,\r\n marginTop: TokenMap.px8,\r\n maxWidth: \"100%\",\r\n },\r\n});\r\n\r\n/**\r\n * Props for the {@link ErrorBoundary} component.\r\n */\r\ntype ErrorBoundaryProps = {\r\n /** Child components to render */\r\n children: ReactNode;\r\n /** Optional fallback UI to show on error */\r\n fallback?: ReactNode;\r\n /** Optional callback when an error occurs */\r\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\r\n /** Optional name for identifying this boundary in logs */\r\n name?: string;\r\n};\r\n\r\ntype ErrorBoundaryState = {\r\n hasError: boolean;\r\n error: Error | null;\r\n errorInfo: ErrorInfo | null;\r\n};\r\n\r\n/**\r\n * Error boundary component that catches JavaScript errors in child components\r\n * and displays a fallback UI instead of crashing the entire application.\r\n */\r\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\r\n constructor(props: ErrorBoundaryProps) {\r\n super(props);\r\n this.state = { hasError: false, error: null, errorInfo: null };\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\r\n return { hasError: true, error };\r\n }\r\n\r\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n this.setState({ errorInfo });\r\n\r\n // Log the error\r\n const boundaryName = this.props.name || \"ErrorBoundary\";\r\n // eslint-disable-next-line no-console\r\n console.error(`[${boundaryName}] Error caught:`, error, errorInfo);\r\n\r\n // Call optional error callback\r\n this.props.onError?.(error, errorInfo);\r\n }\r\n\r\n private _handleRetry = () => {\r\n this.setState({ hasError: false, error: null, errorInfo: null });\r\n };\r\n\r\n override render() {\r\n if (this.state.hasError) {\r\n // If a custom fallback is provided, use it\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n\r\n // Default fallback UI\r\n return <ErrorFallback error={this.state.error} onRetry={this._handleRetry} />;\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\ntype ErrorFallbackProps = {\r\n error: Error | null;\r\n onRetry: () => void;\r\n};\r\n\r\nfunction ErrorFallback({ error, onRetry }: ErrorFallbackProps) {\r\n const styles = useStyles();\r\n\r\n return (\r\n <div className={styles.root}>\r\n <ErrorCircleRegular className={styles.icon} />\r\n <div className={styles.title}>Something went wrong</div>\r\n <div className={styles.message}>An error occurred in this component. You can try again or continue using other parts of the tool.</div>\r\n <Button label=\"Try Again\" appearance=\"primary\" onClick={onRetry} />\r\n {error && <div className={styles.details}>{error.message}</div>}\r\n </div>\r\n );\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"errorBoundary.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/errorBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type ErrorInfo, type ReactNode, Component } from \"react\";\r\n\r\nimport { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { ErrorCircleRegular } from \"@fluentui/react-icons\";\r\nimport { Button } from \"shared-ui-components/fluent/primitives/button\";\r\nimport { TokenMap } from \"shared-ui-components/fluent/primitives/utils\";\r\n\r\nconst useStyles = makeStyles({\r\n root: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n padding: TokenMap.px20,\r\n backgroundColor: tokens.colorNeutralBackground1,\r\n color: tokens.colorNeutralForeground1,\r\n // Claim the full row of the flex parent (e.g. shellService's central-content row)\r\n // so the centered children sit in the middle of the available area, not at the left edge.\r\n flex: 1,\r\n height: \"100%\",\r\n minHeight: \"100px\",\r\n },\r\n icon: {\r\n fontSize: \"48px\",\r\n color: tokens.colorPaletteRedForeground1,\r\n marginBottom: TokenMap.px12,\r\n },\r\n title: {\r\n fontSize: TokenMap.px16,\r\n fontWeight: \"600\",\r\n marginBottom: TokenMap.px8,\r\n },\r\n message: {\r\n fontSize: TokenMap.px12,\r\n color: tokens.colorNeutralForeground2,\r\n marginBottom: TokenMap.px16,\r\n textAlign: \"center\",\r\n maxWidth: \"300px\",\r\n },\r\n details: {\r\n fontSize: TokenMap.px10,\r\n color: tokens.colorNeutralForeground3,\r\n fontFamily: \"monospace\",\r\n whiteSpace: \"pre-wrap\",\r\n maxHeight: \"100px\",\r\n overflow: \"auto\",\r\n padding: TokenMap.px8,\r\n backgroundColor: tokens.colorNeutralBackground3,\r\n borderRadius: TokenMap.px4,\r\n marginTop: TokenMap.px8,\r\n maxWidth: \"100%\",\r\n },\r\n});\r\n\r\n/**\r\n * Props for the {@link ErrorBoundary} component.\r\n */\r\ntype ErrorBoundaryProps = {\r\n /** Child components to render */\r\n children: ReactNode;\r\n /** Optional fallback UI to show on error */\r\n fallback?: ReactNode;\r\n /** Optional callback when an error occurs */\r\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\r\n /** Optional name for identifying this boundary in logs */\r\n name?: string;\r\n};\r\n\r\ntype ErrorBoundaryState = {\r\n hasError: boolean;\r\n error: Error | null;\r\n errorInfo: ErrorInfo | null;\r\n};\r\n\r\n/**\r\n * Error boundary component that catches JavaScript errors in child components\r\n * and displays a fallback UI instead of crashing the entire application.\r\n */\r\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\r\n constructor(props: ErrorBoundaryProps) {\r\n super(props);\r\n this.state = { hasError: false, error: null, errorInfo: null };\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\r\n return { hasError: true, error };\r\n }\r\n\r\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n this.setState({ errorInfo });\r\n\r\n // Log the error\r\n const boundaryName = this.props.name || \"ErrorBoundary\";\r\n // eslint-disable-next-line no-console\r\n console.error(`[${boundaryName}] Error caught:`, error, errorInfo);\r\n\r\n // Call optional error callback\r\n this.props.onError?.(error, errorInfo);\r\n }\r\n\r\n private _handleRetry = () => {\r\n this.setState({ hasError: false, error: null, errorInfo: null });\r\n };\r\n\r\n override render() {\r\n if (this.state.hasError) {\r\n // If a custom fallback is provided, use it\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n\r\n // Default fallback UI\r\n return <ErrorFallback error={this.state.error} onRetry={this._handleRetry} />;\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\ntype ErrorFallbackProps = {\r\n error: Error | null;\r\n onRetry: () => void;\r\n};\r\n\r\nfunction ErrorFallback({ error, onRetry }: ErrorFallbackProps) {\r\n const styles = useStyles();\r\n\r\n return (\r\n <div className={styles.root}>\r\n <ErrorCircleRegular className={styles.icon} />\r\n <div className={styles.title}>Something went wrong</div>\r\n <div className={styles.message}>An error occurred in this component. You can try again or continue using other parts of the tool.</div>\r\n <Button label=\"Try Again\" appearance=\"primary\" onClick={onRetry} />\r\n {error && <div className={styles.details}>{error.message}</div>}\r\n </div>\r\n );\r\n}\r\n"]}
|
|
@@ -3,6 +3,11 @@ import { type FunctionComponent } from "react";
|
|
|
3
3
|
/**
|
|
4
4
|
* A themed Fluent UI provider that applies the current theme mode (light or dark).
|
|
5
5
|
* @param props Fluent provider props, plus an optional `invert` flag to swap the theme.
|
|
6
|
+
* When `targetDocument` is provided and differs from the inherited Fluent
|
|
7
|
+
* document (e.g. when rendering into a popup window), a Griffel renderer
|
|
8
|
+
* scoped to that document is created so styles are injected into it.
|
|
9
|
+
* When omitted, `targetDocument` is inherited from the ambient Fluent
|
|
10
|
+
* context so nested Theme components do not lose cross-window targeting.
|
|
6
11
|
* @returns The themed Fluent UI provider component.
|
|
7
12
|
*/
|
|
8
13
|
export declare const Theme: FunctionComponent<FluentProviderProps & {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { FluentProvider, makeStyles, mergeClasses, tokens } from "@fluentui/react-components";
|
|
2
|
+
import { FluentProvider, RendererProvider, createDOMRenderer, makeStyles, mergeClasses, tokens, useFluent, } from "@fluentui/react-components";
|
|
3
|
+
import { useMemo } from "react";
|
|
3
4
|
import { useTheme } from "../hooks/themeHooks.js";
|
|
4
5
|
// Fluent doesn't apply styling to scrollbars by default, so provide our own reasonable default.
|
|
5
6
|
const useStyles = makeStyles({
|
|
@@ -10,15 +11,38 @@ const useStyles = makeStyles({
|
|
|
10
11
|
/**
|
|
11
12
|
* A themed Fluent UI provider that applies the current theme mode (light or dark).
|
|
12
13
|
* @param props Fluent provider props, plus an optional `invert` flag to swap the theme.
|
|
14
|
+
* When `targetDocument` is provided and differs from the inherited Fluent
|
|
15
|
+
* document (e.g. when rendering into a popup window), a Griffel renderer
|
|
16
|
+
* scoped to that document is created so styles are injected into it.
|
|
17
|
+
* When omitted, `targetDocument` is inherited from the ambient Fluent
|
|
18
|
+
* context so nested Theme components do not lose cross-window targeting.
|
|
13
19
|
* @returns The themed Fluent UI provider component.
|
|
14
20
|
*/
|
|
15
21
|
export const Theme = (props) => {
|
|
16
22
|
// NOTE: We do not want to applyStylesToPortals by default. It makes classes flow into portals
|
|
17
23
|
// (like popovers), and if those styles do things like disable overflow, they can completely
|
|
18
24
|
// break any UI within the portal. Therefore, default to false.
|
|
19
|
-
const { invert = false, applyStylesToPortals = false, className, ...rest } = props;
|
|
25
|
+
const { invert = false, applyStylesToPortals = false, className, targetDocument: explicitTargetDocument, ...rest } = props;
|
|
20
26
|
const theme = useTheme(invert);
|
|
21
27
|
const classes = useStyles();
|
|
22
|
-
|
|
28
|
+
// Resolve the target document from the explicit prop or fall back to the ambient Fluent context.
|
|
29
|
+
// This makes nested <Theme> components automatically inherit cross-window targeting from a
|
|
30
|
+
// top-level <Theme targetDocument={popupDocument}> wrapper.
|
|
31
|
+
const inheritedTargetDocument = useFluent().targetDocument;
|
|
32
|
+
const resolvedTargetDocument = explicitTargetDocument ?? inheritedTargetDocument;
|
|
33
|
+
// Only create a new Griffel renderer when the resolved document differs from the inherited
|
|
34
|
+
// one. In the common (main-window, no nesting) case, this leaves Fluent's default renderer
|
|
35
|
+
// and renderer provider in place — matching the original behaviour exactly.
|
|
36
|
+
const renderer = useMemo(() => {
|
|
37
|
+
if (resolvedTargetDocument && resolvedTargetDocument !== inheritedTargetDocument) {
|
|
38
|
+
return createDOMRenderer(resolvedTargetDocument);
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}, [resolvedTargetDocument, inheritedTargetDocument]);
|
|
42
|
+
const fluent = (_jsx(FluentProvider, { theme: theme, className: mergeClasses(classes.root, className), applyStylesToPortals: applyStylesToPortals, targetDocument: resolvedTargetDocument, ...rest, children: props.children }));
|
|
43
|
+
if (renderer && resolvedTargetDocument) {
|
|
44
|
+
return (_jsx(RendererProvider, { renderer: renderer, targetDocument: resolvedTargetDocument, children: fluent }));
|
|
45
|
+
}
|
|
46
|
+
return fluent;
|
|
23
47
|
};
|
|
24
48
|
//# sourceMappingURL=theme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/theme.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/theme.tsx"],"names":[],"mappings":";AAAA,OAAO,EAGH,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,MAAM,EACN,SAAS,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAA0B,OAAO,EAAE,MAAM,OAAO,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,gGAAgG;AAChG,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,IAAI,EAAE;QACF,cAAc,EAAE,GAAG,MAAM,CAAC,uBAAuB,IAAI,MAAM,CAAC,0BAA0B,EAAE;KAC3F;CACJ,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAkE,CAAC,KAAK,EAAE,EAAE;IAC1F,8FAA8F;IAC9F,4FAA4F;IAC5F,+DAA+D;IAC/D,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,oBAAoB,GAAG,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAC3H,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,iGAAiG;IACjG,2FAA2F;IAC3F,4DAA4D;IAC5D,MAAM,uBAAuB,GAAG,SAAS,EAAE,CAAC,cAAc,CAAC;IAC3D,MAAM,sBAAsB,GAAG,sBAAsB,IAAI,uBAAuB,CAAC;IAEjF,2FAA2F;IAC3F,2FAA2F;IAC3F,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,OAAO,CAA8B,GAAG,EAAE;QACvD,IAAI,sBAAsB,IAAI,sBAAsB,KAAK,uBAAuB,EAAE,CAAC;YAC/E,OAAO,iBAAiB,CAAC,sBAAsB,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC,EAAE,CAAC,sBAAsB,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,CACX,KAAC,cAAc,IACX,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,EAChD,oBAAoB,EAAE,oBAAoB,EAC1C,cAAc,EAAE,sBAAsB,KAClC,IAAI,YAEP,KAAK,CAAC,QAAQ,GACF,CACpB,CAAC;IAEF,IAAI,QAAQ,IAAI,sBAAsB,EAAE,CAAC;QACrC,OAAO,CACH,KAAC,gBAAgB,IAAC,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,sBAAsB,YACvE,MAAM,GACQ,CACtB,CAAC;IACN,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC","sourcesContent":["import {\r\n type FluentProviderProps,\r\n type GriffelRenderer,\r\n FluentProvider,\r\n RendererProvider,\r\n createDOMRenderer,\r\n makeStyles,\r\n mergeClasses,\r\n tokens,\r\n useFluent,\r\n} from \"@fluentui/react-components\";\r\nimport { type FunctionComponent, useMemo } from \"react\";\r\n\r\nimport { useTheme } from \"../hooks/themeHooks\";\r\n\r\n// Fluent doesn't apply styling to scrollbars by default, so provide our own reasonable default.\r\nconst useStyles = makeStyles({\r\n root: {\r\n scrollbarColor: `${tokens.colorNeutralForeground3} ${tokens.colorTransparentBackground}`,\r\n },\r\n});\r\n\r\n/**\r\n * A themed Fluent UI provider that applies the current theme mode (light or dark).\r\n * @param props Fluent provider props, plus an optional `invert` flag to swap the theme.\r\n * When `targetDocument` is provided and differs from the inherited Fluent\r\n * document (e.g. when rendering into a popup window), a Griffel renderer\r\n * scoped to that document is created so styles are injected into it.\r\n * When omitted, `targetDocument` is inherited from the ambient Fluent\r\n * context so nested Theme components do not lose cross-window targeting.\r\n * @returns The themed Fluent UI provider component.\r\n */\r\nexport const Theme: FunctionComponent<FluentProviderProps & { invert?: boolean }> = (props) => {\r\n // NOTE: We do not want to applyStylesToPortals by default. It makes classes flow into portals\r\n // (like popovers), and if those styles do things like disable overflow, they can completely\r\n // break any UI within the portal. Therefore, default to false.\r\n const { invert = false, applyStylesToPortals = false, className, targetDocument: explicitTargetDocument, ...rest } = props;\r\n const theme = useTheme(invert);\r\n const classes = useStyles();\r\n\r\n // Resolve the target document from the explicit prop or fall back to the ambient Fluent context.\r\n // This makes nested <Theme> components automatically inherit cross-window targeting from a\r\n // top-level <Theme targetDocument={popupDocument}> wrapper.\r\n const inheritedTargetDocument = useFluent().targetDocument;\r\n const resolvedTargetDocument = explicitTargetDocument ?? inheritedTargetDocument;\r\n\r\n // Only create a new Griffel renderer when the resolved document differs from the inherited\r\n // one. In the common (main-window, no nesting) case, this leaves Fluent's default renderer\r\n // and renderer provider in place — matching the original behaviour exactly.\r\n const renderer = useMemo<GriffelRenderer | undefined>(() => {\r\n if (resolvedTargetDocument && resolvedTargetDocument !== inheritedTargetDocument) {\r\n return createDOMRenderer(resolvedTargetDocument);\r\n }\r\n return undefined;\r\n }, [resolvedTargetDocument, inheritedTargetDocument]);\r\n\r\n const fluent = (\r\n <FluentProvider\r\n theme={theme}\r\n className={mergeClasses(classes.root, className)}\r\n applyStylesToPortals={applyStylesToPortals}\r\n targetDocument={resolvedTargetDocument}\r\n {...rest}\r\n >\r\n {props.children}\r\n </FluentProvider>\r\n );\r\n\r\n if (renderer && resolvedTargetDocument) {\r\n return (\r\n <RendererProvider renderer={renderer} targetDocument={resolvedTargetDocument}>\r\n {fluent}\r\n </RendererProvider>\r\n );\r\n }\r\n\r\n return fluent;\r\n};\r\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type DialogOptions } from "../services/dialogService.js";
|
|
2
|
+
type DialogContext = {
|
|
3
|
+
showDialog: (options: DialogOptions) => void;
|
|
4
|
+
};
|
|
5
|
+
export declare const DialogContext: import("react").Context<DialogContext>;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the showDialog function provided by the surrounding modular tool framework.
|
|
8
|
+
* If called outside of a DialogContext provider, falls back to the default context
|
|
9
|
+
* value, whose showDialog implementation invokes the browser's blocking `alert` with
|
|
10
|
+
* the dialog title.
|
|
11
|
+
* @returns A function that displays a dialog when called.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useDialog(): DialogContext;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
export const DialogContext = createContext({ showDialog: (options) => alert(options.title) });
|
|
3
|
+
/**
|
|
4
|
+
* Returns the showDialog function provided by the surrounding modular tool framework.
|
|
5
|
+
* If called outside of a DialogContext provider, falls back to the default context
|
|
6
|
+
* value, whose showDialog implementation invokes the browser's blocking `alert` with
|
|
7
|
+
* the dialog title.
|
|
8
|
+
* @returns A function that displays a dialog when called.
|
|
9
|
+
*/
|
|
10
|
+
export function useDialog() {
|
|
11
|
+
return useContext(DialogContext);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=dialogContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialogContext.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/contexts/dialogContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAQlD,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAgB,EAAE,UAAU,EAAE,CAAC,OAAsB,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE5H;;;;;;GAMG;AACH,MAAM,UAAU,SAAS;IACrB,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { createContext, useContext } from \"react\";\r\n\r\nimport { type DialogOptions } from \"../services/dialogService\";\r\n\r\ntype DialogContext = {\r\n showDialog: (options: DialogOptions) => void;\r\n};\r\n\r\nexport const DialogContext = createContext<DialogContext>({ showDialog: (options: DialogOptions) => alert(options.title) });\r\n\r\n/**\r\n * Returns the showDialog function provided by the surrounding modular tool framework.\r\n * If called outside of a DialogContext provider, falls back to the default context\r\n * value, whose showDialog implementation invokes the browser's blocking `alert` with\r\n * the dialog title.\r\n * @returns A function that displays a dialog when called.\r\n */\r\nexport function useDialog(): DialogContext {\r\n return useContext(DialogContext);\r\n}\r\n"]}
|
|
@@ -6,13 +6,15 @@ import { SettingsStore, SettingsStoreIdentity } from "./services/settingsStore.j
|
|
|
6
6
|
import { MakeShellServiceDefinition, RootComponentServiceIdentity } from "./services/shellService.js";
|
|
7
7
|
import { ThemeModeSettingDescriptor, ThemeServiceDefinition } from "./services/themeService.js";
|
|
8
8
|
import { Body1, Button, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, List, ListItem, makeStyles, Spinner, tokens, } from "@fluentui/react-components";
|
|
9
|
-
import { ErrorCircleRegular } from "@fluentui/react-icons";
|
|
9
|
+
import { CheckmarkCircleRegular, ErrorCircleRegular, InfoRegular, WarningRegular } from "@fluentui/react-icons";
|
|
10
10
|
import { createRoot } from "react-dom/client";
|
|
11
11
|
import { Deferred } from "@babylonjs/core/Misc/deferred.js";
|
|
12
12
|
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
|
13
13
|
import { ToastProvider } from "../fluent/primitives/toast.js";
|
|
14
|
+
import { DialogServiceIdentity } from "./services/dialogService.js";
|
|
14
15
|
import { ToastServiceIdentity } from "./services/toastService.js";
|
|
15
16
|
import { Theme } from "./components/theme.js";
|
|
17
|
+
import { DialogContext } from "./contexts/dialogContext.js";
|
|
16
18
|
import { ExtensionManagerContext } from "./contexts/extensionManagerContext.js";
|
|
17
19
|
import { SettingsStoreContext } from "./contexts/settingsContext.js";
|
|
18
20
|
import { ReactContextServiceIdentity } from "./services/reactContextService.js";
|
|
@@ -42,6 +44,24 @@ const useStyles = makeStyles({
|
|
|
42
44
|
extensionErrorIcon: {
|
|
43
45
|
color: tokens.colorPaletteRedForeground1,
|
|
44
46
|
},
|
|
47
|
+
dialogTitle: {
|
|
48
|
+
display: "flex",
|
|
49
|
+
flexDirection: "row",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
gap: tokens.spacingHorizontalS,
|
|
52
|
+
},
|
|
53
|
+
dialogIconSuccess: {
|
|
54
|
+
color: tokens.colorStatusSuccessForeground1,
|
|
55
|
+
},
|
|
56
|
+
dialogIconError: {
|
|
57
|
+
color: tokens.colorStatusDangerForeground1,
|
|
58
|
+
},
|
|
59
|
+
dialogIconWarning: {
|
|
60
|
+
color: tokens.colorStatusWarningForeground1,
|
|
61
|
+
},
|
|
62
|
+
dialogIconInfo: {
|
|
63
|
+
color: tokens.colorBrandForeground1,
|
|
64
|
+
},
|
|
45
65
|
});
|
|
46
66
|
const ReactContextsWrapper = ({ contexts, children }) => {
|
|
47
67
|
return _jsx(_Fragment, { children: contexts.reduceRight((acc, entry) => createElement(entry.provider, { value: entry.value }, acc), children) });
|
|
@@ -77,6 +97,21 @@ export function MakeModularTool(options) {
|
|
|
77
97
|
setToastQueue([]);
|
|
78
98
|
}
|
|
79
99
|
}, [toastHandle, toastQueue]);
|
|
100
|
+
// Queue of dialogs to display. We show one at a time (the one at the head of the queue).
|
|
101
|
+
const [dialogQueue, dispatchDialogQueue] = useReducer((state, action) => {
|
|
102
|
+
switch (action.type) {
|
|
103
|
+
case "enqueue":
|
|
104
|
+
return [...state, action.options];
|
|
105
|
+
case "dequeue":
|
|
106
|
+
return state.slice(1);
|
|
107
|
+
}
|
|
108
|
+
}, []);
|
|
109
|
+
const showDialog = useCallback((dialogOptions) => {
|
|
110
|
+
dispatchDialogQueue({ type: "enqueue", options: dialogOptions });
|
|
111
|
+
}, []);
|
|
112
|
+
const onDismissDialog = useCallback(() => {
|
|
113
|
+
dispatchDialogQueue({ type: "dequeue" });
|
|
114
|
+
}, []);
|
|
80
115
|
const [rootComponentService, setRootComponentService] = useState();
|
|
81
116
|
const [contexts, updateContexts] = useReducer((state, action) => {
|
|
82
117
|
switch (action.type) {
|
|
@@ -127,6 +162,12 @@ export function MakeModularTool(options) {
|
|
|
127
162
|
},
|
|
128
163
|
}),
|
|
129
164
|
});
|
|
165
|
+
// Expose the dialog service so non-React code (e.g. Observable callbacks) can show dialogs.
|
|
166
|
+
serviceContainer.addService({
|
|
167
|
+
friendlyName: "Dialog Service",
|
|
168
|
+
produces: [DialogServiceIdentity],
|
|
169
|
+
factory: () => ({ showDialog }),
|
|
170
|
+
});
|
|
130
171
|
// Register the shell service (top level toolbar/side pane UI layout).
|
|
131
172
|
serviceContainer.addService(MakeShellServiceDefinition(options));
|
|
132
173
|
// Register a service that simply consumes the services we need before first render.
|
|
@@ -216,16 +257,36 @@ export function MakeModularTool(options) {
|
|
|
216
257
|
const onAcknowledgedExtensionInstallError = useCallback(() => {
|
|
217
258
|
setExtensionInstallError(undefined);
|
|
218
259
|
}, [setExtensionInstallError]);
|
|
260
|
+
// The dialog at the head of the queue, if any, is the one currently being displayed.
|
|
261
|
+
const currentDialog = dialogQueue[0];
|
|
262
|
+
const currentDialogIcon = (() => {
|
|
263
|
+
switch (currentDialog?.intent) {
|
|
264
|
+
case "success":
|
|
265
|
+
return _jsx(CheckmarkCircleRegular, { className: classes.dialogIconSuccess });
|
|
266
|
+
case "error":
|
|
267
|
+
return _jsx(ErrorCircleRegular, { className: classes.dialogIconError });
|
|
268
|
+
case "warning":
|
|
269
|
+
return _jsx(WarningRegular, { className: classes.dialogIconWarning });
|
|
270
|
+
case "info":
|
|
271
|
+
case undefined:
|
|
272
|
+
return _jsx(InfoRegular, { className: classes.dialogIconInfo });
|
|
273
|
+
}
|
|
274
|
+
})();
|
|
219
275
|
// Show a spinner until a main view has been set.
|
|
220
276
|
if (!rootComponentService) {
|
|
221
|
-
return (_jsx(ReactContextsWrapper, { contexts: contexts, children: _jsx(SettingsStoreContext.Provider, { value: settingsStore, children: _jsx(Theme, { className: classes.app, children: _jsx(Spinner, { className: classes.spinner }) }) }) }));
|
|
277
|
+
return (_jsx(ReactContextsWrapper, { contexts: contexts, children: _jsx(SettingsStoreContext.Provider, { value: settingsStore, children: _jsx(Theme, { className: classes.app, targetDocument: targetDocument, children: _jsx(Spinner, { className: classes.spinner }) }) }) }));
|
|
222
278
|
}
|
|
223
279
|
else {
|
|
224
280
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
225
281
|
const Content = rootComponentService.rootComponent;
|
|
226
|
-
return (_jsx(ReactContextsWrapper, { contexts: contexts, children: _jsx(SettingsStoreContext.Provider, { value: settingsStore, children: _jsx(ExtensionManagerContext.Provider, { value: extensionManagerContext, children: _jsx(Theme, { className: classes.app, children: _jsxs(ToastProvider, { imperativeRef: setToastHandle, children: [_jsx(Dialog, { open: !!requiredExtensions, modalType: "alert", children: _jsx(DialogSurface, { children: _jsxs(DialogBody, { children: [_jsx(DialogTitle, { children: "Required Extensions" }), _jsxs(DialogContent, { children: ["Opening this URL requires the following extensions to be installed and enabled:", _jsx("ul", { children: requiredExtensions?.map((name) => (_jsx("li", { children: name }, name))) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { appearance: "primary", onClick: onAcceptRequiredExtensions, children: "Install & Enable" }), _jsx(Button, { appearance: "secondary", onClick: onRejectRequiredExtensions, children: "No Thanks" })] })] }) }) }), _jsx(Dialog, { open: !!extensionInstallError, modalType: "alert", children: _jsx(DialogSurface, { children: _jsxs(DialogBody, { children: [_jsx(DialogTitle, { children: _jsxs("div", { className: classes.extensionErrorTitleDiv, children: ["Extension Install Error", _jsx(ErrorCircleRegular, { className: classes.extensionErrorIcon })] }) }), _jsx(DialogContent, { children: _jsxs(List, { children: [_jsx(ListItem, { children: _jsx(Body1, { children: `Extension "${extensionInstallError?.extension.name}" failed to install and was removed.` }) }), _jsx(ListItem, { children: _jsx(Body1, { children: `${extensionInstallError?.error}` }) })] }) }), _jsx(DialogActions, { children: _jsx(Button, { appearance: "primary", onClick: onAcknowledgedExtensionInstallError, children: "Close" }) })] }) }) }), _jsx(Suspense, { fallback: _jsx(Spinner, { className: classes.spinner }), children: _jsx(Content, {}) })] }) }) }) }) }));
|
|
282
|
+
return (_jsx(ReactContextsWrapper, { contexts: contexts, children: _jsx(SettingsStoreContext.Provider, { value: settingsStore, children: _jsx(ExtensionManagerContext.Provider, { value: extensionManagerContext, children: _jsx(Theme, { className: classes.app, targetDocument: targetDocument, children: _jsxs(ToastProvider, { imperativeRef: setToastHandle, children: [_jsx(Dialog, { open: !!requiredExtensions, modalType: "alert", children: _jsx(DialogSurface, { children: _jsxs(DialogBody, { children: [_jsx(DialogTitle, { children: "Required Extensions" }), _jsxs(DialogContent, { children: ["Opening this URL requires the following extensions to be installed and enabled:", _jsx("ul", { children: requiredExtensions?.map((name) => (_jsx("li", { children: name }, name))) })] }), _jsxs(DialogActions, { children: [_jsx(Button, { appearance: "primary", onClick: onAcceptRequiredExtensions, children: "Install & Enable" }), _jsx(Button, { appearance: "secondary", onClick: onRejectRequiredExtensions, children: "No Thanks" })] })] }) }) }), _jsx(Dialog, { open: !!extensionInstallError, modalType: "alert", children: _jsx(DialogSurface, { children: _jsxs(DialogBody, { children: [_jsx(DialogTitle, { children: _jsxs("div", { className: classes.extensionErrorTitleDiv, children: ["Extension Install Error", _jsx(ErrorCircleRegular, { className: classes.extensionErrorIcon })] }) }), _jsx(DialogContent, { children: _jsxs(List, { children: [_jsx(ListItem, { children: _jsx(Body1, { children: `Extension "${extensionInstallError?.extension.name}" failed to install and was removed.` }) }), _jsx(ListItem, { children: _jsx(Body1, { children: `${extensionInstallError?.error}` }) })] }) }), _jsx(DialogActions, { children: _jsx(Button, { appearance: "primary", onClick: onAcknowledgedExtensionInstallError, children: "Close" }) })] }) }) }), _jsx(Dialog, { open: !!currentDialog, modalType: "alert", children: _jsx(DialogSurface, { children: _jsxs(DialogBody, { children: [_jsx(DialogTitle, { children: _jsxs("div", { className: classes.dialogTitle, children: [currentDialogIcon, currentDialog?.title] }) }), currentDialog?.content && _jsx(DialogContent, { children: currentDialog.content }), _jsx(DialogActions, { children: _jsx(Button, { appearance: "primary", onClick: onDismissDialog, children: "OK" }) })] }) }) }), _jsx(Suspense, { fallback: _jsx(Spinner, { className: classes.spinner }), children: _jsx(DialogContext.Provider, { value: { showDialog }, children: _jsx(Content, {}) }) })] }) }) }) }) }));
|
|
227
283
|
}
|
|
228
284
|
};
|
|
285
|
+
// Derive the target document from the container element. When the container is in a popup
|
|
286
|
+
// window (or other document distinct from the main one), this is what makes Fluent inject
|
|
287
|
+
// styles and render portals into the correct document.
|
|
288
|
+
const containerOwnerDocument = containerElement.ownerDocument;
|
|
289
|
+
const targetDocument = containerOwnerDocument && containerOwnerDocument !== document ? containerOwnerDocument : undefined;
|
|
229
290
|
// Set the container element to be a flex container so that the tool can be displayed properly.
|
|
230
291
|
const originalContainerElementDisplay = containerElement.style.display;
|
|
231
292
|
containerElement.style.display = "flex";
|