@onerjs/shared-ui-components 8.48.3 → 8.48.5
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/buttonLine.js +2 -1
- package/fluent/hoc/buttonLine.js.map +1 -1
- package/fluent/primitives/contextMenu.js.map +1 -1
- package/fluent/primitives/popover.js.map +1 -1
- package/modularTool/components/errorBoundary.d.ts +31 -0
- package/modularTool/components/errorBoundary.js +91 -0
- package/modularTool/components/errorBoundary.js.map +1 -0
- package/modularTool/components/extensibleAccordion.d.ts +67 -0
- package/modularTool/components/extensibleAccordion.js +148 -0
- package/modularTool/components/extensibleAccordion.js.map +1 -0
- package/modularTool/components/pane.d.ts +4 -0
- package/modularTool/components/pane.js +20 -0
- package/modularTool/components/pane.js.map +1 -0
- package/modularTool/components/teachingMoment.d.ts +20 -0
- package/modularTool/components/teachingMoment.js +17 -0
- package/modularTool/components/teachingMoment.js.map +1 -0
- package/modularTool/components/theme.d.ts +10 -0
- package/modularTool/components/theme.js +24 -0
- package/modularTool/components/theme.js.map +1 -0
- package/modularTool/components/uxContextProvider.d.ts +2 -0
- package/modularTool/components/uxContextProvider.js +19 -0
- package/modularTool/components/uxContextProvider.js.map +1 -0
- package/modularTool/contexts/extensionManagerContext.d.ts +6 -0
- package/modularTool/contexts/extensionManagerContext.js +6 -0
- package/modularTool/contexts/extensionManagerContext.js.map +1 -0
- package/modularTool/contexts/settingsContext.d.ts +3 -0
- package/modularTool/contexts/settingsContext.js +6 -0
- package/modularTool/contexts/settingsContext.js.map +1 -0
- package/modularTool/extensibility/builtInsExtensionFeed.d.ts +21 -0
- package/modularTool/extensibility/builtInsExtensionFeed.js +26 -0
- package/modularTool/extensibility/builtInsExtensionFeed.js.map +1 -0
- package/modularTool/extensibility/extensionFeed.d.ts +113 -0
- package/modularTool/extensibility/extensionFeed.js +2 -0
- package/modularTool/extensibility/extensionFeed.js.map +1 -0
- package/modularTool/extensibility/extensionManager.d.ts +111 -0
- package/modularTool/extensibility/extensionManager.js +277 -0
- package/modularTool/extensibility/extensionManager.js.map +1 -0
- package/modularTool/hooks/observableHooks.d.ts +35 -0
- package/modularTool/hooks/observableHooks.js +84 -0
- package/modularTool/hooks/observableHooks.js.map +1 -0
- package/modularTool/hooks/resourceHooks.d.ts +20 -0
- package/modularTool/hooks/resourceHooks.js +101 -0
- package/modularTool/hooks/resourceHooks.js.map +1 -0
- package/modularTool/hooks/settingsHooks.d.ts +8 -0
- package/modularTool/hooks/settingsHooks.js +40 -0
- package/modularTool/hooks/settingsHooks.js.map +1 -0
- package/modularTool/hooks/teachingMomentHooks.d.ts +34 -0
- package/modularTool/hooks/teachingMomentHooks.js +89 -0
- package/modularTool/hooks/teachingMomentHooks.js.map +1 -0
- package/modularTool/hooks/themeHooks.d.ts +17 -0
- package/modularTool/hooks/themeHooks.js +38 -0
- package/modularTool/hooks/themeHooks.js.map +1 -0
- package/modularTool/hooks/useResizeHandle.d.ts +35 -0
- package/modularTool/hooks/useResizeHandle.js +75 -0
- package/modularTool/hooks/useResizeHandle.js.map +1 -0
- package/modularTool/misc/assert.d.ts +5 -0
- package/modularTool/misc/assert.js +10 -0
- package/modularTool/misc/assert.js.map +1 -0
- package/modularTool/misc/graphUtils.d.ts +44 -0
- package/modularTool/misc/graphUtils.js +90 -0
- package/modularTool/misc/graphUtils.js.map +1 -0
- package/modularTool/misc/observableCollection.d.ts +23 -0
- package/modularTool/misc/observableCollection.js +43 -0
- package/modularTool/misc/observableCollection.js.map +1 -0
- package/modularTool/modularTool.d.ts +42 -0
- package/modularTool/modularTool.js +223 -0
- package/modularTool/modularTool.js.map +1 -0
- package/modularTool/modularity/serviceContainer.d.ts +64 -0
- package/modularTool/modularity/serviceContainer.js +181 -0
- package/modularTool/modularity/serviceContainer.js.map +1 -0
- package/modularTool/modularity/serviceDefinition.d.ts +64 -0
- package/modularTool/modularity/serviceDefinition.js +11 -0
- package/modularTool/modularity/serviceDefinition.js.map +1 -0
- package/modularTool/services/extensionsListService.d.ts +3 -0
- package/modularTool/services/extensionsListService.js +202 -0
- package/modularTool/services/extensionsListService.js.map +1 -0
- package/modularTool/services/globalSettings.d.ts +3 -0
- package/modularTool/services/globalSettings.js +9 -0
- package/modularTool/services/globalSettings.js.map +1 -0
- package/modularTool/services/reactContextService.d.ts +18 -0
- package/modularTool/services/reactContextService.js +5 -0
- package/modularTool/services/reactContextService.js.map +1 -0
- package/modularTool/services/settingsService.d.ts +24 -0
- package/modularTool/services/settingsService.js +41 -0
- package/modularTool/services/settingsService.js.map +1 -0
- package/modularTool/services/settingsStore.d.ts +55 -0
- package/modularTool/services/settingsStore.js +35 -0
- package/modularTool/services/settingsStore.js.map +1 -0
- package/modularTool/services/shellService.d.ts +256 -0
- package/modularTool/services/shellService.js +729 -0
- package/modularTool/services/shellService.js.map +1 -0
- package/modularTool/services/shellSettingsService.d.ts +3 -0
- package/modularTool/services/shellSettingsService.js +35 -0
- package/modularTool/services/shellSettingsService.js.map +1 -0
- package/modularTool/services/themeSelectorService.d.ts +3 -0
- package/modularTool/services/themeSelectorService.js +42 -0
- package/modularTool/services/themeSelectorService.js.map +1 -0
- package/modularTool/services/themeService.d.ts +60 -0
- package/modularTool/services/themeService.js +69 -0
- package/modularTool/services/themeService.js.map +1 -0
- package/modularTool/themes/babylonTheme.d.ts +3 -0
- package/modularTool/themes/babylonTheme.js +36 -0
- package/modularTool/themes/babylonTheme.js.map +1 -0
- package/package.json +1 -1
package/fluent/hoc/buttonLine.js
CHANGED
|
@@ -8,6 +8,7 @@ import { Button } from "../primitives/button.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export const ButtonLine = (props) => {
|
|
10
10
|
ButtonLine.displayName = "ButtonLine";
|
|
11
|
-
|
|
11
|
+
const { uniqueId, ...buttonProps } = props;
|
|
12
|
+
return (_jsx(LineContainer, { uniqueId: uniqueId ?? props.label, children: _jsx(Button, { ...buttonProps }) }));
|
|
12
13
|
};
|
|
13
14
|
//# sourceMappingURL=buttonLine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buttonLine.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/hoc/buttonLine.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAoB,MAAM,sBAAsB,CAAC;AAOhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAuC,CAAC,KAAK,EAAE,EAAE;IACpE,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC;IAEtC,OAAO,CACH,KAAC,aAAa,IAAC,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"buttonLine.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/hoc/buttonLine.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,MAAM,EAAoB,MAAM,sBAAsB,CAAC;AAOhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAuC,CAAC,KAAK,EAAE,EAAE;IACpE,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC;IAEtC,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC;IAE3C,OAAO,CACH,KAAC,aAAa,IAAC,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,KAAK,YAC5C,KAAC,MAAM,OAAK,WAAW,GAAI,GACf,CACnB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { LineContainer } from \"./propertyLines/propertyLine\";\r\nimport { type FunctionComponent } from \"react\";\r\nimport { Button, type ButtonProps } from \"../primitives/button\";\r\n\r\ntype ButtonLineProps = Omit<ButtonProps, \"label\"> & {\r\n label: string; // Require a label when button is the entire line (by default, label is optional on a button)\r\n uniqueId?: string; // The ID of the property line to be used when the label cannot be used as a persistent ID.\r\n};\r\n\r\n/**\r\n * Wraps a button with a label in a line container\r\n * @param props Button props plus a label\r\n * @returns A button inside a line\r\n */\r\nexport const ButtonLine: FunctionComponent<ButtonLineProps> = (props) => {\r\n ButtonLine.displayName = \"ButtonLine\";\r\n\r\n const { uniqueId, ...buttonProps } = props;\r\n\r\n return (\r\n <LineContainer uniqueId={uniqueId ?? props.label}>\r\n <Button {...buttonProps} />\r\n </LineContainer>\r\n );\r\n};\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/contextMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAqC,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAChF,OAAO,EACH,IAAI,EACJ,WAAW,EACX,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,SAAS,EACT,eAAe,EACf,UAAU,EACV,MAAM,GAET,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,MAAM,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"contextMenu.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/contextMenu.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type ReactElement, type ReactNode, forwardRef, useState } from \"react\";\r\nimport {\r\n Menu,\r\n MenuTrigger,\r\n MenuPopover,\r\n MenuList,\r\n MenuItem,\r\n MenuDivider,\r\n MenuGroup,\r\n MenuGroupHeader,\r\n makeStyles,\r\n tokens,\r\n type MenuProps as FluentMenuProps,\r\n} from \"@fluentui/react-components\";\r\nimport { type FluentIcon } from \"@fluentui/react-icons\";\r\nimport { Button } from \"./button\";\r\nimport { type BasePrimitiveProps } from \"./primitive\";\r\n\r\nconst useStyles = makeStyles({\r\n menuPopover: {\r\n minWidth: \"160px\",\r\n },\r\n menuItem: {\r\n cursor: \"pointer\",\r\n },\r\n menuItemIcon: {\r\n color: tokens.colorNeutralForeground2,\r\n },\r\n});\r\n\r\n/**\r\n * Represents a single menu item in the context menu.\r\n */\r\nexport type ContextMenuItemProps = {\r\n /**\r\n * Unique key for the menu item.\r\n */\r\n key: string;\r\n /**\r\n * The text label displayed for the menu item.\r\n */\r\n label: string;\r\n /**\r\n * Optional icon to display alongside the menu item.\r\n */\r\n icon?: FluentIcon;\r\n /**\r\n * Called when the menu item is clicked.\r\n */\r\n onClick?: () => void;\r\n /**\r\n * Whether the menu item is disabled.\r\n */\r\n disabled?: boolean;\r\n /**\r\n * Optional secondary text displayed alongside the label.\r\n */\r\n secondaryContent?: string;\r\n};\r\n\r\n/**\r\n * Represents a divider in the context menu.\r\n */\r\nexport type ContextMenuDividerProps = {\r\n /**\r\n * Unique key for the divider.\r\n */\r\n key: string;\r\n /**\r\n * Indicates this is a divider item.\r\n */\r\n type: \"divider\";\r\n};\r\n\r\n/**\r\n * Represents a group of menu items with an optional header.\r\n */\r\nexport type ContextMenuGroupProps = {\r\n /**\r\n * Unique key for the group.\r\n */\r\n key: string;\r\n /**\r\n * Indicates this is a group item.\r\n */\r\n type: \"group\";\r\n /**\r\n * Optional header text for the group.\r\n */\r\n header?: string;\r\n /**\r\n * The menu items within the group.\r\n */\r\n items: ContextMenuItem[];\r\n};\r\n\r\n/**\r\n * Union type representing all possible menu items.\r\n */\r\nexport type ContextMenuItem = ContextMenuItemProps | ContextMenuDividerProps | ContextMenuGroupProps;\r\n\r\ntype ContextMenuWithIconProps = {\r\n /**\r\n * Icon to use as the trigger button.\r\n */\r\n icon: FluentIcon;\r\n trigger?: never;\r\n};\r\n\r\ntype ContextMenuWithTriggerProps = {\r\n icon?: never;\r\n /**\r\n * Custom trigger element for opening the menu.\r\n */\r\n trigger: ReactElement;\r\n};\r\n\r\nexport type ContextMenuProps = BasePrimitiveProps &\r\n (ContextMenuWithIconProps | ContextMenuWithTriggerProps) & {\r\n /**\r\n * Array of menu items to display.\r\n */\r\n items: ContextMenuItem[];\r\n /**\r\n * Positioning of the menu relative to the trigger.\r\n */\r\n positioning?: FluentMenuProps[\"positioning\"];\r\n /**\r\n * Called when the menu open state changes.\r\n */\r\n onOpenChange?: (open: boolean) => void;\r\n };\r\n\r\nconst IsDivider = (item: ContextMenuItem): item is ContextMenuDividerProps => {\r\n return \"type\" in item && item.type === \"divider\";\r\n};\r\n\r\nconst IsGroup = (item: ContextMenuItem): item is ContextMenuGroupProps => {\r\n return \"type\" in item && item.type === \"group\";\r\n};\r\n\r\nconst RenderMenuItem = (item: ContextMenuItemProps, classes: ReturnType<typeof useStyles>) => {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const Icon = item.icon;\r\n return (\r\n <MenuItem\r\n key={item.key}\r\n className={classes.menuItem}\r\n icon={Icon ? <Icon className={classes.menuItemIcon} /> : undefined}\r\n onClick={item.onClick}\r\n disabled={item.disabled}\r\n secondaryContent={item.secondaryContent}\r\n >\r\n {item.label}\r\n </MenuItem>\r\n );\r\n};\r\n\r\nconst RenderMenuItems = (items: ContextMenuItem[], classes: ReturnType<typeof useStyles>): ReactNode[] => {\r\n return items.map((item) => {\r\n if (IsDivider(item)) {\r\n return <MenuDivider key={item.key} />;\r\n }\r\n\r\n if (IsGroup(item)) {\r\n return (\r\n <MenuGroup key={item.key}>\r\n {item.header && <MenuGroupHeader>{item.header}</MenuGroupHeader>}\r\n {RenderMenuItems(item.items, classes)}\r\n </MenuGroup>\r\n );\r\n }\r\n\r\n return RenderMenuItem(item, classes);\r\n });\r\n};\r\n\r\n/**\r\n * A wrapper around Fluent UI's Menu component providing a simplified API for context menus.\r\n * Supports menu items with icons, dividers, and grouped items.\r\n */\r\nexport const ContextMenu = forwardRef<HTMLButtonElement, ContextMenuProps>((props, ref) => {\r\n const { items, onOpenChange, disabled } = props;\r\n const [open, setOpen] = useState(false);\r\n const classes = useStyles();\r\n\r\n const handleOpenChange = (_: unknown, data: { open: boolean }) => {\r\n setOpen(data.open);\r\n onOpenChange?.(data.open);\r\n };\r\n\r\n return (\r\n <Menu openOnContext open={open} onOpenChange={handleOpenChange}>\r\n <MenuTrigger disableButtonEnhancement>\r\n {props.trigger ?? (\r\n <Button\r\n ref={ref}\r\n icon={props.icon}\r\n onClick={(e) => {\r\n e?.stopPropagation();\r\n setOpen(true);\r\n }}\r\n disabled={disabled}\r\n />\r\n )}\r\n </MenuTrigger>\r\n <MenuPopover className={classes.menuPopover}>\r\n <MenuList>{RenderMenuItems(items, classes)}</MenuList>\r\n </MenuPopover>\r\n </Menu>\r\n );\r\n});\r\n\r\nContextMenu.displayName = \"ContextMenu\";\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/popover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAA6C,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAA6B,MAAM,4BAA4B,CAAC;AAErJ,OAAO,EAAE,MAAM,EAAE,MAAM
|
|
1
|
+
{"version":3,"file":"popover.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/popover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAA6C,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAA6B,MAAM,4BAA4B,CAAC;AAErJ,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,OAAO,EAAE;QACL,QAAQ,EAAE,OAAO;KACpB;IACD,OAAO,EAAE;QACL,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,GAAG,EAAE,MAAM,CAAC,gBAAgB;QAC5B,OAAO,EAAE,MAAM,CAAC,kBAAkB;QAClC,QAAQ,EAAE,OAAO;KACpB;CACJ,CAAC,CAAC;AAyBH,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAqD,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACjG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAC9F,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,MAAM,YAAY,GAAG,cAAc,KAAK,SAAS,CAAC;IAClD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC;IAEjE,MAAM,gBAAgB,GAAG,CAAC,CAAU,EAAE,IAAuB,EAAE,EAAE;QAC7D,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,OAAO,CACH,MAAC,aAAa,IACV,IAAI,EAAE,WAAW,EACjB,YAAY,EAAE,gBAAgB,EAC9B,WAAW,EACP,WAAW,IAAI;YACX,KAAK,EAAE,OAAO;YACd,gBAAgB,EAAE,QAAQ,CAAC,IAAI;YAC/B,QAAQ,EAAE,IAAI;SACjB,aAGL,KAAC,cAAc,IAAC,wBAAwB,kBACnC,KAAK,CAAC,OAAO,IAAI,KAAC,MAAM,IAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAI,GAClG,EACjB,KAAC,cAAc,IAAC,SAAS,EAAE,gBAAgB,IAAI,OAAO,CAAC,OAAO,YAC1D,cAAK,SAAS,EAAE,OAAO,CAAC,OAAO,YAAG,QAAQ,GAAO,GACpC,IACL,CACnB,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC","sourcesContent":["import { type PropsWithChildren, type ReactElement, forwardRef, useState } from \"react\";\r\nimport { Popover as FluentPopover, PopoverTrigger, PopoverSurface, makeStyles, tokens, type PositioningShorthand } from \"@fluentui/react-components\";\r\nimport { type FluentIcon } from \"@fluentui/react-icons\";\r\nimport { Button } from \"./button\";\r\n\r\nconst useStyles = makeStyles({\r\n surface: {\r\n maxWidth: \"400px\",\r\n },\r\n content: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: tokens.spacingVerticalM,\r\n padding: tokens.spacingHorizontalL,\r\n minWidth: \"300px\",\r\n },\r\n});\r\n\r\ntype PopoverWithIconProps = {\r\n icon: FluentIcon;\r\n trigger?: never;\r\n};\r\n\r\ntype PopoverWithTriggerProps = {\r\n icon?: never;\r\n trigger: ReactElement;\r\n};\r\n\r\ntype PopoverBaseProps = {\r\n /** Controlled open state */\r\n open?: boolean;\r\n /** Callback when open state changes */\r\n onOpenChange?: (open: boolean) => void;\r\n /** Positioning of the popover */\r\n positioning?: PositioningShorthand;\r\n /** Custom class for the surface */\r\n surfaceClassName?: string;\r\n};\r\n\r\ntype PopoverProps = PopoverBaseProps & (PopoverWithIconProps | PopoverWithTriggerProps);\r\n\r\nexport const Popover = forwardRef<HTMLButtonElement, PropsWithChildren<PopoverProps>>((props, ref) => {\r\n const { children, open: controlledOpen, onOpenChange, positioning, surfaceClassName } = props;\r\n const [internalOpen, setInternalOpen] = useState(false);\r\n const classes = useStyles();\r\n\r\n const isControlled = controlledOpen !== undefined;\r\n const popoverOpen = isControlled ? controlledOpen : internalOpen;\r\n\r\n const handleOpenChange = (_: unknown, data: { open: boolean }) => {\r\n if (!isControlled) {\r\n setInternalOpen(data.open);\r\n }\r\n onOpenChange?.(data.open);\r\n };\r\n\r\n return (\r\n <FluentPopover\r\n open={popoverOpen}\r\n onOpenChange={handleOpenChange}\r\n positioning={\r\n positioning ?? {\r\n align: \"start\",\r\n overflowBoundary: document.body,\r\n autoSize: true,\r\n }\r\n }\r\n >\r\n <PopoverTrigger disableButtonEnhancement>\r\n {props.trigger ?? <Button ref={ref} icon={props.icon} onClick={() => handleOpenChange(null, { open: true })} />}\r\n </PopoverTrigger>\r\n <PopoverSurface className={surfaceClassName ?? classes.surface}>\r\n <div className={classes.content}>{children}</div>\r\n </PopoverSurface>\r\n </FluentPopover>\r\n );\r\n});\r\n\r\nPopover.displayName = \"Popover\";\r\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ErrorInfo, type ReactNode, Component } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Props for the {@link ErrorBoundary} component.
|
|
4
|
+
*/
|
|
5
|
+
type ErrorBoundaryProps = {
|
|
6
|
+
/** Child components to render */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** Optional fallback UI to show on error */
|
|
9
|
+
fallback?: ReactNode;
|
|
10
|
+
/** Optional callback when an error occurs */
|
|
11
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
12
|
+
/** Optional name for identifying this boundary in logs */
|
|
13
|
+
name?: string;
|
|
14
|
+
};
|
|
15
|
+
type ErrorBoundaryState = {
|
|
16
|
+
hasError: boolean;
|
|
17
|
+
error: Error | null;
|
|
18
|
+
errorInfo: ErrorInfo | null;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Error boundary component that catches JavaScript errors in child components
|
|
22
|
+
* and displays a fallback UI instead of crashing the entire application.
|
|
23
|
+
*/
|
|
24
|
+
export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
25
|
+
constructor(props: ErrorBoundaryProps);
|
|
26
|
+
static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState>;
|
|
27
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
28
|
+
private _handleRetry;
|
|
29
|
+
render(): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Component } from "react";
|
|
3
|
+
import { makeStyles, tokens } from "@fluentui/react-components";
|
|
4
|
+
import { ErrorCircleRegular } from "@fluentui/react-icons";
|
|
5
|
+
import { Button } from "../../fluent/primitives/button.js";
|
|
6
|
+
import { TokenMap } from "../../fluent/primitives/utils.js";
|
|
7
|
+
const useStyles = makeStyles({
|
|
8
|
+
root: {
|
|
9
|
+
display: "flex",
|
|
10
|
+
flexDirection: "column",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "center",
|
|
13
|
+
padding: TokenMap.px20,
|
|
14
|
+
backgroundColor: tokens.colorNeutralBackground1,
|
|
15
|
+
color: tokens.colorNeutralForeground1,
|
|
16
|
+
height: "100%",
|
|
17
|
+
minHeight: "100px",
|
|
18
|
+
},
|
|
19
|
+
icon: {
|
|
20
|
+
fontSize: "48px",
|
|
21
|
+
color: tokens.colorPaletteRedForeground1,
|
|
22
|
+
marginBottom: TokenMap.px12,
|
|
23
|
+
},
|
|
24
|
+
title: {
|
|
25
|
+
fontSize: TokenMap.px16,
|
|
26
|
+
fontWeight: "600",
|
|
27
|
+
marginBottom: TokenMap.px8,
|
|
28
|
+
},
|
|
29
|
+
message: {
|
|
30
|
+
fontSize: TokenMap.px12,
|
|
31
|
+
color: tokens.colorNeutralForeground2,
|
|
32
|
+
marginBottom: TokenMap.px16,
|
|
33
|
+
textAlign: "center",
|
|
34
|
+
maxWidth: "300px",
|
|
35
|
+
},
|
|
36
|
+
details: {
|
|
37
|
+
fontSize: TokenMap.px10,
|
|
38
|
+
color: tokens.colorNeutralForeground3,
|
|
39
|
+
fontFamily: "monospace",
|
|
40
|
+
whiteSpace: "pre-wrap",
|
|
41
|
+
maxHeight: "100px",
|
|
42
|
+
overflow: "auto",
|
|
43
|
+
padding: TokenMap.px8,
|
|
44
|
+
backgroundColor: tokens.colorNeutralBackground3,
|
|
45
|
+
borderRadius: TokenMap.px4,
|
|
46
|
+
marginTop: TokenMap.px8,
|
|
47
|
+
maxWidth: "100%",
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Error boundary component that catches JavaScript errors in child components
|
|
52
|
+
* and displays a fallback UI instead of crashing the entire application.
|
|
53
|
+
*/
|
|
54
|
+
export class ErrorBoundary extends Component {
|
|
55
|
+
constructor(props) {
|
|
56
|
+
super(props);
|
|
57
|
+
this._handleRetry = () => {
|
|
58
|
+
this.setState({ hasError: false, error: null, errorInfo: null });
|
|
59
|
+
};
|
|
60
|
+
this.state = { hasError: false, error: null, errorInfo: null };
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
63
|
+
static getDerivedStateFromError(error) {
|
|
64
|
+
return { hasError: true, error };
|
|
65
|
+
}
|
|
66
|
+
componentDidCatch(error, errorInfo) {
|
|
67
|
+
this.setState({ errorInfo });
|
|
68
|
+
// Log the error
|
|
69
|
+
const boundaryName = this.props.name || "ErrorBoundary";
|
|
70
|
+
// eslint-disable-next-line no-console
|
|
71
|
+
console.error(`[${boundaryName}] Error caught:`, error, errorInfo);
|
|
72
|
+
// Call optional error callback
|
|
73
|
+
this.props.onError?.(error, errorInfo);
|
|
74
|
+
}
|
|
75
|
+
render() {
|
|
76
|
+
if (this.state.hasError) {
|
|
77
|
+
// If a custom fallback is provided, use it
|
|
78
|
+
if (this.props.fallback) {
|
|
79
|
+
return this.props.fallback;
|
|
80
|
+
}
|
|
81
|
+
// Default fallback UI
|
|
82
|
+
return _jsx(ErrorFallback, { error: this.state.error, onRetry: this._handleRetry });
|
|
83
|
+
}
|
|
84
|
+
return this.props.children;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function ErrorFallback({ error, onRetry }) {
|
|
88
|
+
const styles = useStyles();
|
|
89
|
+
return (_jsxs("div", { className: styles.root, children: [_jsx(ErrorCircleRegular, { className: styles.icon }), _jsx("div", { className: styles.title, children: "Something went wrong" }), _jsx("div", { className: styles.message, children: "An error occurred in this component. You can try again or continue using other parts of the tool." }), _jsx(Button, { label: "Try Again", appearance: "primary", onClick: onRetry }), error && _jsx("div", { className: styles.details, children: error.message })] }));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=errorBoundary.js.map
|
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type ComponentType, type PropsWithChildren, type Ref } from "react";
|
|
2
|
+
import { type AccordionProps } from "../../fluent/primitives/accordion.js";
|
|
3
|
+
/**
|
|
4
|
+
* Describes a section within a dynamic accordion that can be added at runtime.
|
|
5
|
+
*/
|
|
6
|
+
export type DynamicAccordionSection = Readonly<{
|
|
7
|
+
/**
|
|
8
|
+
* A unique identity for the section, which can be referenced by section content.
|
|
9
|
+
*/
|
|
10
|
+
identity: string;
|
|
11
|
+
/**
|
|
12
|
+
* An optional order for the section, relative to other sections.
|
|
13
|
+
* Defaults to 0.
|
|
14
|
+
*/
|
|
15
|
+
order?: number;
|
|
16
|
+
/**
|
|
17
|
+
* An optional flag indicating whether the section should be collapsed by default.
|
|
18
|
+
* Defaults to false.
|
|
19
|
+
*/
|
|
20
|
+
collapseByDefault?: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* Describes content that belongs to a section within a dynamic accordion.
|
|
24
|
+
*/
|
|
25
|
+
export type DynamicAccordionSectionContent<ContextT> = Readonly<{
|
|
26
|
+
/**
|
|
27
|
+
* A unique key for the the content.
|
|
28
|
+
*/
|
|
29
|
+
key: string;
|
|
30
|
+
/**
|
|
31
|
+
* The section this content belongs to.
|
|
32
|
+
*/
|
|
33
|
+
section: string;
|
|
34
|
+
/**
|
|
35
|
+
* An optional order for the content within the section.
|
|
36
|
+
* Defaults to 0.
|
|
37
|
+
*/
|
|
38
|
+
order?: number;
|
|
39
|
+
/**
|
|
40
|
+
* The React component that will be rendered for this content.
|
|
41
|
+
*/
|
|
42
|
+
component: ComponentType<{
|
|
43
|
+
context: ContextT;
|
|
44
|
+
}>;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Imperative handle for controlling section highlights on the extensible accordion.
|
|
48
|
+
*/
|
|
49
|
+
export type SectionsImperativeRef = {
|
|
50
|
+
/**
|
|
51
|
+
* Highlights the specified sections, collapsing all others until the context changes.
|
|
52
|
+
* @param sections The identity strings of the sections to highlight.
|
|
53
|
+
*/
|
|
54
|
+
highlightSections: (sections: readonly string[]) => void;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* An accordion component that supports dynamically adding sections and section content at runtime.
|
|
58
|
+
* Combines statically defined children sections with dynamically registered sections and content.
|
|
59
|
+
* @param props The accordion props including sections, section content, context, and an optional imperative ref.
|
|
60
|
+
* @returns The extensible accordion component.
|
|
61
|
+
*/
|
|
62
|
+
export declare function ExtensibleAccordion<ContextT = unknown>(props: PropsWithChildren<{
|
|
63
|
+
sections: readonly DynamicAccordionSection[];
|
|
64
|
+
sectionContent: readonly DynamicAccordionSectionContent<ContextT>[];
|
|
65
|
+
context: ContextT;
|
|
66
|
+
sectionsRef?: Ref<SectionsImperativeRef>;
|
|
67
|
+
} & AccordionProps>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Children, isValidElement, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { Accordion, AccordionSection } from "../../fluent/primitives/accordion.js";
|
|
4
|
+
import { makeStyles } from "@fluentui/react-components";
|
|
5
|
+
import { UXContextProvider } from "./uxContextProvider.js";
|
|
6
|
+
function AsReadonlyArray(array) {
|
|
7
|
+
return array;
|
|
8
|
+
}
|
|
9
|
+
const useStyles = makeStyles({
|
|
10
|
+
rootDiv: {
|
|
11
|
+
flex: 1,
|
|
12
|
+
overflow: "hidden",
|
|
13
|
+
display: "flex",
|
|
14
|
+
flexDirection: "column",
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* An accordion component that supports dynamically adding sections and section content at runtime.
|
|
19
|
+
* Combines statically defined children sections with dynamically registered sections and content.
|
|
20
|
+
* @param props The accordion props including sections, section content, context, and an optional imperative ref.
|
|
21
|
+
* @returns The extensible accordion component.
|
|
22
|
+
*/
|
|
23
|
+
export function ExtensibleAccordion(props) {
|
|
24
|
+
const classes = useStyles();
|
|
25
|
+
const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;
|
|
26
|
+
const defaultSections = useMemo(() => {
|
|
27
|
+
const defaultSections = [];
|
|
28
|
+
if (children) {
|
|
29
|
+
Children.forEach(children, (child) => {
|
|
30
|
+
if (isValidElement(child)) {
|
|
31
|
+
const childProps = child.props;
|
|
32
|
+
defaultSections.push({
|
|
33
|
+
identity: childProps.title,
|
|
34
|
+
collapseByDefault: childProps.collapseByDefault,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return AsReadonlyArray(defaultSections);
|
|
40
|
+
}, [children]);
|
|
41
|
+
// Cache stable component wrappers for static (children-based) sections so that
|
|
42
|
+
// React does not unmount/remount them on every re-render. The components read
|
|
43
|
+
// the latest child element from `elements` so they always render fresh content.
|
|
44
|
+
const staticComponentCacheRef = useRef({ elements: new Map(), components: new Map() });
|
|
45
|
+
const defaultSectionContent = useMemo(() => {
|
|
46
|
+
const cache = staticComponentCacheRef.current;
|
|
47
|
+
cache.elements.clear();
|
|
48
|
+
const defaultSectionContent = [];
|
|
49
|
+
if (children) {
|
|
50
|
+
Children.forEach(children, (child, index) => {
|
|
51
|
+
if (isValidElement(child)) {
|
|
52
|
+
const childProps = child.props;
|
|
53
|
+
const key = child.key ?? childProps.title;
|
|
54
|
+
// Update the element so the stable component renders the latest content.
|
|
55
|
+
cache.elements.set(key, child);
|
|
56
|
+
// Create a stable component wrapper only once per key.
|
|
57
|
+
if (!cache.components.has(key)) {
|
|
58
|
+
const capturedKey = key;
|
|
59
|
+
cache.components.set(capturedKey, () => _jsx(_Fragment, { children: cache.elements.get(capturedKey) }));
|
|
60
|
+
}
|
|
61
|
+
defaultSectionContent.push({
|
|
62
|
+
key,
|
|
63
|
+
section: defaultSections[index].identity,
|
|
64
|
+
component: cache.components.get(key),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return AsReadonlyArray(defaultSectionContent);
|
|
70
|
+
}, [children, defaultSections]);
|
|
71
|
+
const mergedSectionContent = useMemo(() => {
|
|
72
|
+
return AsReadonlyArray([...defaultSectionContent, ...sectionContent].map((content, index) => {
|
|
73
|
+
return {
|
|
74
|
+
...content,
|
|
75
|
+
key: `${content.key}-${index}`,
|
|
76
|
+
order: content.order ?? index,
|
|
77
|
+
};
|
|
78
|
+
}));
|
|
79
|
+
}, [defaultSectionContent, sectionContent]);
|
|
80
|
+
const mergedSections = useMemo(() => {
|
|
81
|
+
const mergedSections = [...defaultSections.map((s) => ({ ...s, isDefault: true })), ...sections.map((s) => ({ ...s, isDefault: false }))];
|
|
82
|
+
// Check for implicit sections (e.g. sections that were not explicitly defined, but referenced by content).
|
|
83
|
+
const implicitSections = [];
|
|
84
|
+
for (const sectionContent of mergedSectionContent) {
|
|
85
|
+
if (!mergedSections.some((s) => s.identity === sectionContent.section) && !implicitSections.some((s) => s.identity === sectionContent.section)) {
|
|
86
|
+
implicitSections.push({ identity: sectionContent.section });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return AsReadonlyArray([...implicitSections.map((s) => ({ ...s, isDefault: false })), ...mergedSections].map((section, index) => {
|
|
90
|
+
return {
|
|
91
|
+
...section,
|
|
92
|
+
order: section.order ?? index,
|
|
93
|
+
collapseByDefault: section.collapseByDefault ?? false,
|
|
94
|
+
};
|
|
95
|
+
}));
|
|
96
|
+
}, [defaultSections, sections, mergedSectionContent]);
|
|
97
|
+
const visibleSections = useMemo(() => {
|
|
98
|
+
if (!context) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const sortedSections = [...mergedSections].sort((a, b) => {
|
|
102
|
+
// Default sections always come before non-default sections.
|
|
103
|
+
if (a.isDefault !== b.isDefault) {
|
|
104
|
+
return a.isDefault ? -1 : 1;
|
|
105
|
+
}
|
|
106
|
+
return a.order - b.order;
|
|
107
|
+
});
|
|
108
|
+
return sortedSections
|
|
109
|
+
.map((section) => {
|
|
110
|
+
// Get a flat list of the section content, preserving the key so it can be used when each component for each section is rendered.
|
|
111
|
+
const contentForSection = mergedSectionContent.filter((content) => content.section === section.identity);
|
|
112
|
+
// If there is no content for this section, we skip it.
|
|
113
|
+
if (contentForSection.length === 0) {
|
|
114
|
+
return null; // No content for this section
|
|
115
|
+
}
|
|
116
|
+
// Sort the content for this section by order, defaulting to 0 if not specified.
|
|
117
|
+
contentForSection.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
118
|
+
// Return the section with its identity, collapseByDefault flag, and the content components to render.
|
|
119
|
+
return {
|
|
120
|
+
identity: section.identity,
|
|
121
|
+
collapseByDefault: section.collapseByDefault ?? false,
|
|
122
|
+
components: contentForSection.map((content) => _jsx(content.component, { context: context }, content.key)),
|
|
123
|
+
};
|
|
124
|
+
})
|
|
125
|
+
.filter((section) => section !== null);
|
|
126
|
+
}, [mergedSections, mergedSectionContent, context]);
|
|
127
|
+
const [highlightSections, setHighlightSections] = useState();
|
|
128
|
+
// When the context changes, clear any existing highlights.
|
|
129
|
+
useLayoutEffect(() => {
|
|
130
|
+
setHighlightSections(undefined);
|
|
131
|
+
}, [context]);
|
|
132
|
+
// This just assigns the returned object to any type of React ref, whether it is
|
|
133
|
+
// a mutable ref with a 'current' property or whether it is a callback, useImperativeHandle
|
|
134
|
+
// will deal with it.
|
|
135
|
+
useImperativeHandle(sectionsRef, () => {
|
|
136
|
+
return {
|
|
137
|
+
highlightSections: (sectionsToHighlight) => {
|
|
138
|
+
if (sectionsToHighlight.length > 0) {
|
|
139
|
+
setHighlightSections(sectionsToHighlight);
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}, []);
|
|
144
|
+
return (_jsx("div", { className: classes.rootDiv, children: visibleSections.length > -1 && (_jsx(UXContextProvider, { children: _jsxs(Accordion, { highlightSections: highlightSections, ...rest, children: [...visibleSections.map((section) => {
|
|
145
|
+
return (_jsx(AccordionSection, { title: section.identity, collapseByDefault: section.collapseByDefault, children: section.components }, section.identity));
|
|
146
|
+
})] }) })) }));
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=extensibleAccordion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensibleAccordion.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/extensibleAccordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type ComponentType, type PropsWithChildren, type Ref, Children, isValidElement, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from \"react\";\r\n\r\nimport { type AccordionProps, type AccordionSectionProps, Accordion, AccordionSection } from \"shared-ui-components/fluent/primitives/accordion\";\r\n\r\nimport { makeStyles } from \"@fluentui/react-components\";\r\n\r\nimport { UXContextProvider } from \"./uxContextProvider\";\r\n\r\nfunction AsReadonlyArray<T>(array: T[]): readonly T[] {\r\n return array;\r\n}\r\n\r\n/**\r\n * Describes a section within a dynamic accordion that can be added at runtime.\r\n */\r\nexport type DynamicAccordionSection = Readonly<{\r\n /**\r\n * A unique identity for the section, which can be referenced by section content.\r\n */\r\n identity: string;\r\n\r\n /**\r\n * An optional order for the section, relative to other sections.\r\n * Defaults to 0.\r\n */\r\n order?: number;\r\n\r\n /**\r\n * An optional flag indicating whether the section should be collapsed by default.\r\n * Defaults to false.\r\n */\r\n collapseByDefault?: boolean;\r\n}>;\r\n\r\n/**\r\n * Describes content that belongs to a section within a dynamic accordion.\r\n */\r\nexport type DynamicAccordionSectionContent<ContextT> = Readonly<{\r\n /**\r\n * A unique key for the the content.\r\n */\r\n key: string;\r\n\r\n /**\r\n * The section this content belongs to.\r\n */\r\n section: string;\r\n\r\n /**\r\n * An optional order for the content within the section.\r\n * Defaults to 0.\r\n */\r\n order?: number;\r\n\r\n /**\r\n * The React component that will be rendered for this content.\r\n */\r\n component: ComponentType<{ context: ContextT }>;\r\n}>;\r\n\r\nconst useStyles = makeStyles({\r\n rootDiv: {\r\n flex: 1,\r\n overflow: \"hidden\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n },\r\n});\r\n\r\n/**\r\n * Imperative handle for controlling section highlights on the extensible accordion.\r\n */\r\nexport type SectionsImperativeRef = {\r\n /**\r\n * Highlights the specified sections, collapsing all others until the context changes.\r\n * @param sections The identity strings of the sections to highlight.\r\n */\r\n highlightSections: (sections: readonly string[]) => void;\r\n};\r\n\r\n/**\r\n * An accordion component that supports dynamically adding sections and section content at runtime.\r\n * Combines statically defined children sections with dynamically registered sections and content.\r\n * @param props The accordion props including sections, section content, context, and an optional imperative ref.\r\n * @returns The extensible accordion component.\r\n */\r\nexport function ExtensibleAccordion<ContextT = unknown>(\r\n props: PropsWithChildren<\r\n {\r\n sections: readonly DynamicAccordionSection[];\r\n sectionContent: readonly DynamicAccordionSectionContent<ContextT>[];\r\n context: ContextT;\r\n sectionsRef?: Ref<SectionsImperativeRef>;\r\n } & AccordionProps\r\n >\r\n) {\r\n const classes = useStyles();\r\n\r\n const { children, sections, sectionContent, context, sectionsRef, ...rest } = props;\r\n\r\n const defaultSections = useMemo(() => {\r\n const defaultSections: DynamicAccordionSection[] = [];\r\n if (children) {\r\n Children.forEach(children, (child) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as AccordionSectionProps;\r\n defaultSections.push({\r\n identity: childProps.title,\r\n collapseByDefault: childProps.collapseByDefault,\r\n });\r\n }\r\n });\r\n }\r\n return AsReadonlyArray(defaultSections);\r\n }, [children]);\r\n\r\n // Cache stable component wrappers for static (children-based) sections so that\r\n // React does not unmount/remount them on every re-render. The components read\r\n // the latest child element from `elements` so they always render fresh content.\r\n const staticComponentCacheRef = useRef<{\r\n elements: Map<string, React.ReactNode>;\r\n components: Map<string, ComponentType<{ context: ContextT }>>;\r\n }>({ elements: new Map(), components: new Map() });\r\n\r\n const defaultSectionContent = useMemo(() => {\r\n const cache = staticComponentCacheRef.current;\r\n cache.elements.clear();\r\n const defaultSectionContent: DynamicAccordionSectionContent<ContextT>[] = [];\r\n if (children) {\r\n Children.forEach(children, (child, index) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as AccordionSectionProps;\r\n const key = child.key ?? childProps.title;\r\n\r\n // Update the element so the stable component renders the latest content.\r\n cache.elements.set(key, child);\r\n\r\n // Create a stable component wrapper only once per key.\r\n if (!cache.components.has(key)) {\r\n const capturedKey = key;\r\n cache.components.set(capturedKey, () => <>{cache.elements.get(capturedKey)}</>);\r\n }\r\n\r\n defaultSectionContent.push({\r\n key,\r\n section: defaultSections[index].identity,\r\n component: cache.components.get(key)!,\r\n });\r\n }\r\n });\r\n }\r\n return AsReadonlyArray(defaultSectionContent);\r\n }, [children, defaultSections]);\r\n\r\n const mergedSectionContent = useMemo(() => {\r\n return AsReadonlyArray(\r\n [...defaultSectionContent, ...sectionContent].map((content, index) => {\r\n return {\r\n ...content,\r\n key: `${content.key}-${index}`,\r\n order: content.order ?? index,\r\n } as const;\r\n })\r\n );\r\n }, [defaultSectionContent, sectionContent]);\r\n\r\n const mergedSections = useMemo(() => {\r\n const mergedSections = [...defaultSections.map((s) => ({ ...s, isDefault: true as const })), ...sections.map((s) => ({ ...s, isDefault: false as const }))];\r\n\r\n // Check for implicit sections (e.g. sections that were not explicitly defined, but referenced by content).\r\n const implicitSections: DynamicAccordionSection[] = [];\r\n for (const sectionContent of mergedSectionContent) {\r\n if (!mergedSections.some((s) => s.identity === sectionContent.section) && !implicitSections.some((s) => s.identity === sectionContent.section)) {\r\n implicitSections.push({ identity: sectionContent.section });\r\n }\r\n }\r\n\r\n return AsReadonlyArray(\r\n [...implicitSections.map((s) => ({ ...s, isDefault: false as const })), ...mergedSections].map((section, index) => {\r\n return {\r\n ...section,\r\n order: section.order ?? index,\r\n collapseByDefault: section.collapseByDefault ?? false,\r\n } as const;\r\n })\r\n );\r\n }, [defaultSections, sections, mergedSectionContent]);\r\n\r\n const visibleSections = useMemo(() => {\r\n if (!context) {\r\n return [];\r\n }\r\n\r\n const sortedSections = [...mergedSections].sort((a, b) => {\r\n // Default sections always come before non-default sections.\r\n if (a.isDefault !== b.isDefault) {\r\n return a.isDefault ? -1 : 1;\r\n }\r\n return a.order - b.order;\r\n });\r\n\r\n return sortedSections\r\n .map((section) => {\r\n // Get a flat list of the section content, preserving the key so it can be used when each component for each section is rendered.\r\n const contentForSection = mergedSectionContent.filter((content) => content.section === section.identity);\r\n\r\n // If there is no content for this section, we skip it.\r\n if (contentForSection.length === 0) {\r\n return null; // No content for this section\r\n }\r\n\r\n // Sort the content for this section by order, defaulting to 0 if not specified.\r\n contentForSection.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\r\n\r\n // Return the section with its identity, collapseByDefault flag, and the content components to render.\r\n return {\r\n identity: section.identity,\r\n collapseByDefault: section.collapseByDefault ?? false,\r\n components: contentForSection.map((content) => <content.component key={content.key} context={context} />),\r\n };\r\n })\r\n .filter((section) => section !== null);\r\n }, [mergedSections, mergedSectionContent, context]);\r\n\r\n const [highlightSections, setHighlightSections] = useState<readonly string[]>();\r\n\r\n // When the context changes, clear any existing highlights.\r\n useLayoutEffect(() => {\r\n setHighlightSections(undefined);\r\n }, [context]);\r\n\r\n // This just assigns the returned object to any type of React ref, whether it is\r\n // a mutable ref with a 'current' property or whether it is a callback, useImperativeHandle\r\n // will deal with it.\r\n useImperativeHandle(sectionsRef, () => {\r\n return {\r\n highlightSections: (sectionsToHighlight: readonly string[]) => {\r\n if (sectionsToHighlight.length > 0) {\r\n setHighlightSections(sectionsToHighlight);\r\n }\r\n },\r\n };\r\n }, []);\r\n\r\n return (\r\n <div className={classes.rootDiv}>\r\n {visibleSections.length > -1 && (\r\n <UXContextProvider>\r\n <Accordion highlightSections={highlightSections} {...rest}>\r\n {...visibleSections.map((section) => {\r\n return (\r\n <AccordionSection key={section.identity} title={section.identity} collapseByDefault={section.collapseByDefault}>\r\n {section.components}\r\n </AccordionSection>\r\n );\r\n })}\r\n </Accordion>\r\n </UXContextProvider>\r\n )}\r\n </div>\r\n );\r\n}\r\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Used to apply common styles to panes.
|
|
3
|
+
*/
|
|
4
|
+
export declare const SidePaneContainer: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { makeStyles, mergeClasses, tokens } from "@fluentui/react-components";
|
|
4
|
+
const useStyles = makeStyles({
|
|
5
|
+
paneRootDiv: {
|
|
6
|
+
display: "flex",
|
|
7
|
+
flex: 1,
|
|
8
|
+
flexDirection: "column",
|
|
9
|
+
padding: `0 ${tokens.spacingHorizontalM}`,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Used to apply common styles to panes.
|
|
14
|
+
*/
|
|
15
|
+
export const SidePaneContainer = forwardRef((props, ref) => {
|
|
16
|
+
const { className, ...rest } = props;
|
|
17
|
+
const classes = useStyles();
|
|
18
|
+
return (_jsx("div", { className: mergeClasses(classes.paneRootDiv, className), ref: ref, ...rest, children: props.children }));
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=pane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pane.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/pane.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAuB,UAAU,EAAE,MAAM,OAAO,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAE9E,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,WAAW,EAAE;QACT,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,CAAC;QACP,aAAa,EAAE,QAAQ;QACvB,OAAO,EAAE,KAAK,MAAM,CAAC,kBAAkB,EAAE;KAC5C;CACJ,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAwC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9F,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACrC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,OAAO,CACH,cAAK,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,KAAM,IAAI,YAC3E,KAAK,CAAC,QAAQ,GACb,CACT,CAAC;AACN,CAAC,CAAC,CAAC","sourcesContent":["import { type ComponentProps, forwardRef } from \"react\";\r\n\r\nimport { makeStyles, mergeClasses, tokens } from \"@fluentui/react-components\";\r\n\r\nconst useStyles = makeStyles({\r\n paneRootDiv: {\r\n display: \"flex\",\r\n flex: 1,\r\n flexDirection: \"column\",\r\n padding: `0 ${tokens.spacingHorizontalM}`,\r\n },\r\n});\r\n\r\n/**\r\n * Used to apply common styles to panes.\r\n */\r\nexport const SidePaneContainer = forwardRef<HTMLDivElement, ComponentProps<\"div\">>((props, ref) => {\r\n const { className, ...rest } = props;\r\n const classes = useStyles();\r\n\r\n return (\r\n <div className={mergeClasses(classes.paneRootDiv, className)} ref={ref} {...rest}>\r\n {props.children}\r\n </div>\r\n );\r\n});\r\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type FunctionComponent } from "react";
|
|
2
|
+
import { type MakePopoverTeachingMoment } from "../hooks/teachingMomentHooks.js";
|
|
3
|
+
/**
|
|
4
|
+
* The state returned by the teaching moment hook.
|
|
5
|
+
*/
|
|
6
|
+
type TeachingMomentState = ReturnType<ReturnType<typeof MakePopoverTeachingMoment>>;
|
|
7
|
+
/**
|
|
8
|
+
* Props for the {@link TeachingMoment} component.
|
|
9
|
+
*/
|
|
10
|
+
type TeachingMomentProps = Pick<TeachingMomentState, "shouldDisplay" | "positioningRef" | "onOpenChange"> & {
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A component that displays a teaching moment popover.
|
|
16
|
+
* @param props Props for the teaching moment popover.
|
|
17
|
+
* @returns The teaching moment popover.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TeachingMoment: FunctionComponent<TeachingMomentProps>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { makeStyles, TeachingPopover, TeachingPopoverBody, TeachingPopoverHeader, TeachingPopoverSurface } from "@fluentui/react-components";
|
|
3
|
+
const useStyles = makeStyles({
|
|
4
|
+
extensionTeachingPopover: {
|
|
5
|
+
maxWidth: "320px",
|
|
6
|
+
},
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* A component that displays a teaching moment popover.
|
|
10
|
+
* @param props Props for the teaching moment popover.
|
|
11
|
+
* @returns The teaching moment popover.
|
|
12
|
+
*/
|
|
13
|
+
export const TeachingMoment = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {
|
|
14
|
+
const classes = useStyles();
|
|
15
|
+
return (_jsx(TeachingPopover, { appearance: "brand", open: shouldDisplay, positioning: { positioningRef }, onOpenChange: onOpenChange, children: _jsxs(TeachingPopoverSurface, { className: classes.extensionTeachingPopover, children: [_jsx(TeachingPopoverHeader, { children: title }), _jsx(TeachingPopoverBody, { children: description })] }) }));
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=teachingMoment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teachingMoment.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/teachingMoment.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAE7I,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,wBAAwB,EAAE;QACtB,QAAQ,EAAE,OAAO;KACpB;CACJ,CAAC,CAAC;AAeH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2C,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;IAC1I,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,OAAO,CACH,KAAC,eAAe,IAAC,UAAU,EAAC,OAAO,EAAC,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,EAAE,cAAc,EAAE,EAAE,YAAY,EAAE,YAAY,YAChH,MAAC,sBAAsB,IAAC,SAAS,EAAE,OAAO,CAAC,wBAAwB,aAC/D,KAAC,qBAAqB,cAAE,KAAK,GAAyB,EACtD,KAAC,mBAAmB,cAAE,WAAW,GAAuB,IACnC,GACX,CACrB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { type FunctionComponent } from \"react\";\r\nimport { type MakePopoverTeachingMoment } from \"../hooks/teachingMomentHooks\";\r\n\r\nimport { makeStyles, TeachingPopover, TeachingPopoverBody, TeachingPopoverHeader, TeachingPopoverSurface } from \"@fluentui/react-components\";\r\n\r\nconst useStyles = makeStyles({\r\n extensionTeachingPopover: {\r\n maxWidth: \"320px\",\r\n },\r\n});\r\n\r\n/**\r\n * The state returned by the teaching moment hook.\r\n */\r\ntype TeachingMomentState = ReturnType<ReturnType<typeof MakePopoverTeachingMoment>>;\r\n\r\n/**\r\n * Props for the {@link TeachingMoment} component.\r\n */\r\ntype TeachingMomentProps = Pick<TeachingMomentState, \"shouldDisplay\" | \"positioningRef\" | \"onOpenChange\"> & {\r\n title: string;\r\n description: string;\r\n};\r\n\r\n/**\r\n * A component that displays a teaching moment popover.\r\n * @param props Props for the teaching moment popover.\r\n * @returns The teaching moment popover.\r\n */\r\nexport const TeachingMoment: FunctionComponent<TeachingMomentProps> = ({ shouldDisplay, positioningRef, onOpenChange, title, description }) => {\r\n const classes = useStyles();\r\n\r\n return (\r\n <TeachingPopover appearance=\"brand\" open={shouldDisplay} positioning={{ positioningRef }} onOpenChange={onOpenChange}>\r\n <TeachingPopoverSurface className={classes.extensionTeachingPopover}>\r\n <TeachingPopoverHeader>{title}</TeachingPopoverHeader>\r\n <TeachingPopoverBody>{description}</TeachingPopoverBody>\r\n </TeachingPopoverSurface>\r\n </TeachingPopover>\r\n );\r\n};\r\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type FluentProviderProps } from "@fluentui/react-components";
|
|
2
|
+
import { type FunctionComponent } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* A themed Fluent UI provider that applies the current theme mode (light or dark).
|
|
5
|
+
* @param props Fluent provider props, plus an optional `invert` flag to swap the theme.
|
|
6
|
+
* @returns The themed Fluent UI provider component.
|
|
7
|
+
*/
|
|
8
|
+
export declare const Theme: FunctionComponent<FluentProviderProps & {
|
|
9
|
+
invert?: boolean;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { FluentProvider, makeStyles, mergeClasses, tokens } from "@fluentui/react-components";
|
|
3
|
+
import { useTheme } from "../hooks/themeHooks.js";
|
|
4
|
+
// Fluent doesn't apply styling to scrollbars by default, so provide our own reasonable default.
|
|
5
|
+
const useStyles = makeStyles({
|
|
6
|
+
root: {
|
|
7
|
+
scrollbarColor: `${tokens.colorNeutralForeground3} ${tokens.colorTransparentBackground}`,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* A themed Fluent UI provider that applies the current theme mode (light or dark).
|
|
12
|
+
* @param props Fluent provider props, plus an optional `invert` flag to swap the theme.
|
|
13
|
+
* @returns The themed Fluent UI provider component.
|
|
14
|
+
*/
|
|
15
|
+
export const Theme = (props) => {
|
|
16
|
+
// NOTE: We do not want to applyStylesToPortals by default. It makes classes flow into portals
|
|
17
|
+
// (like popovers), and if those styles do things like disable overflow, they can completely
|
|
18
|
+
// break any UI within the portal. Therefore, default to false.
|
|
19
|
+
const { invert = false, applyStylesToPortals = false, className, ...rest } = props;
|
|
20
|
+
const theme = useTheme(invert);
|
|
21
|
+
const classes = useStyles();
|
|
22
|
+
return (_jsx(FluentProvider, { theme: theme, className: mergeClasses(classes.root, className), applyStylesToPortals: applyStylesToPortals, ...rest, children: props.children }));
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/modularTool/components/theme.tsx"],"names":[],"mappings":";AAAA,OAAO,EAA4B,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGxH,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;;;;GAIG;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,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACnF,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,OAAO,CACH,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,oBAAoB,EAAE,oBAAoB,KAAM,IAAI,YAC/H,KAAK,CAAC,QAAQ,GACF,CACpB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { type FluentProviderProps, FluentProvider, makeStyles, mergeClasses, tokens } from \"@fluentui/react-components\";\r\nimport { type FunctionComponent } 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 * @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, ...rest } = props;\r\n const theme = useTheme(invert);\r\n const classes = useStyles();\r\n\r\n return (\r\n <FluentProvider theme={theme} className={mergeClasses(classes.root, className)} applyStylesToPortals={applyStylesToPortals} {...rest}>\r\n {props.children}\r\n </FluentProvider>\r\n );\r\n};\r\n"]}
|