@babylonjs/inspector 8.33.2-preview → 8.33.3-preview

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/lib/index.d.ts CHANGED
@@ -5,7 +5,6 @@ import { IDisposable as IDisposable$1, Nullable as Nullable$1, IReadonlyObservab
5
5
  import { IReadonlyObservable as IReadonlyObservable$1 } from '@babylonjs/core/Misc/observable.js';
6
6
  import { Nullable as Nullable$2 } from '@babylonjs/core/types.js';
7
7
  import { PositioningImperativeRef, OnOpenChangeData, SpinnerProps } from '@fluentui/react-components';
8
- export { Link } from '@fluentui/react-components';
9
8
  import { Color3 as Color3$1, Color4 as Color4$1 } from '@babylonjs/core/Maths/math.color.js';
10
9
  import { Vector3 as Vector3$1, Quaternion as Quaternion$1 } from '@babylonjs/core/Maths/math.vector.js';
11
10
  import { IDisposable as IDisposable$2, Scene as Scene$2 } from '@babylonjs/core/scene.js';
@@ -76,6 +75,10 @@ type BasePrimitiveProps = {
76
75
  * Optional class name to apply custom styles to the component.
77
76
  */
78
77
  className?: string;
78
+ /**
79
+ * Optional style object to apply custom inline styles to the top-level HTML element.
80
+ */
81
+ style?: React.CSSProperties;
79
82
  /**
80
83
  * Optional title for the component, used for tooltips or accessibility.
81
84
  */
@@ -21357,6 +21360,10 @@ declare class ParticleSystem extends ThinParticleSystem {
21357
21360
  * The current active Sub-systems, this property is used by the root particle system only.
21358
21361
  */
21359
21362
  activeSubSystems: Array<ParticleSystem>;
21363
+ /**
21364
+ * Specifies if the particle system should be serialized
21365
+ */
21366
+ doNotSerialize: boolean;
21360
21367
  /**
21361
21368
  * Creates a Point Emitter for the particle system (emits directly from the emitter position)
21362
21369
  * @param direction1 Particles are emitted between the direction1 and direction2 from within the box
@@ -22058,6 +22065,10 @@ interface IParticleSystem {
22058
22065
  * Returns true if the particle system was generated by a node particle system set
22059
22066
  */
22060
22067
  isNodeGenerated: boolean;
22068
+ /**
22069
+ * Specifies if the particle system should be serialized
22070
+ */
22071
+ doNotSerialize?: boolean;
22061
22072
  /**
22062
22073
  * Gets the maximum number of particles active at the same time.
22063
22074
  * @returns The max number of active particles.
@@ -48137,6 +48148,19 @@ declare class KeyboardInfoPre extends KeyboardInfo {
48137
48148
  event: IKeyboardEvent);
48138
48149
  }
48139
48150
 
48151
+ /**
48152
+ * Description of a custom block to be used in the node render graph editor
48153
+ */
48154
+ interface INodeRenderGraphCustomBlockDescription {
48155
+ /** Block name. It will be used as the block name in the left menu of the editor. Spaces must be replaced by underscores in the name. */
48156
+ name: string;
48157
+ /** Description (tooltip) of the block. */
48158
+ description: string;
48159
+ /** Category of the block. Spaces must be replaced by underscores in the category name. */
48160
+ menu: string;
48161
+ /** Factory function to create the block. */
48162
+ factory: (frameGraph: FrameGraph, scene: Scene) => NodeRenderGraphBlock;
48163
+ }
48140
48164
  /**
48141
48165
  * Interface used to configure the node render graph editor
48142
48166
  */
@@ -48147,6 +48171,7 @@ interface INodeRenderGraphEditorOptions {
48147
48171
  nodeRenderGraphEditorConfig?: {
48148
48172
  backgroundColor?: Color4;
48149
48173
  hostScene?: Scene;
48174
+ customBlockDescriptions?: INodeRenderGraphCustomBlockDescription[];
48150
48175
  };
48151
48176
  }
48152
48177
  /**
@@ -49365,6 +49390,8 @@ declare class NodeRenderGraph {
49365
49390
  static EditorURL: string;
49366
49391
  /** Define the Url to load snippets */
49367
49392
  static SnippetUrl: string;
49393
+ /** Description of custom blocks to use in the node render graph editor */
49394
+ static CustomBlockDescriptions: INodeRenderGraphCustomBlockDescription[];
49368
49395
  private BJSNODERENDERGRAPHEDITOR;
49369
49396
  /** @returns the inspector from bundle or global */
49370
49397
  private _getGlobalNodeRenderGraphEditor;
@@ -71410,6 +71437,22 @@ type LazyComponentProps = {
71410
71437
  */
71411
71438
  declare function MakeLazyComponent<ComponentT extends ComponentType<any>>(getComponentAsync: () => Promise<ComponentT>, defaultProps?: LazyComponentProps): react.ForwardRefExoticComponent<react.PropsWithoutRef<ComponentProps<ComponentT> & LazyComponentProps> & react.RefAttributes<ElementRef<ComponentT | _fluentui_react_utilities.ForwardRefComponent<SpinnerProps>>>>;
71412
71439
 
71440
+ type LinkProps = ImmutablePrimitiveProps<string> & {
71441
+ /**
71442
+ * Used if you want to handle the link click yourself
71443
+ */
71444
+ onLink?: () => void;
71445
+ /**
71446
+ * The URL the link points to
71447
+ */
71448
+ url?: string;
71449
+ /**
71450
+ * Defines whether to open the link in current tab or new tab. Default is new
71451
+ */
71452
+ target?: "current" | "new";
71453
+ };
71454
+ declare const Link: FunctionComponent<PropsWithChildren<LinkProps>>;
71455
+
71413
71456
  /**
71414
71457
  * Represents an item in a list
71415
71458
  */
@@ -71627,10 +71670,6 @@ declare const NumberInputPropertyLine: FunctionComponent<NumberInputPropertyLine
71627
71670
  */
71628
71671
  declare const HexPropertyLine: FunctionComponent<NumberInputPropertyLineProps>;
71629
71672
 
71630
- type LinkProps = ImmutablePrimitiveProps<string> & {
71631
- onLink?: () => void;
71632
- url?: string;
71633
- };
71634
71673
  /**
71635
71674
  * Wraps a link in a property line
71636
71675
  * @param props - PropertyLineProps and LinkProps
@@ -71730,5 +71769,5 @@ declare const Vector2PropertyLine: FunctionComponent<TensorPropertyLineProps<Vec
71730
71769
  declare const Vector3PropertyLine: FunctionComponent<TensorPropertyLineProps<Vector3>>;
71731
71770
  declare const Vector4PropertyLine: FunctionComponent<TensorPropertyLineProps<Vector4>>;
71732
71771
 
71733
- export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useCompactMode, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useSidePaneDockOverrides, useVector3Property };
71734
- export type { AcceptedDropdownValue, AccordionSectionProps, BasePrimitiveProps, BoundPropertyProps, BuiltInExtension, ButtonProps, CentralContentDefinition, ColorPickerProps, ColorPropertyLineProps, ComboBoxProps, DraggableLineProps, DropdownOption, DropdownProps, DynamicAccordionSection, DynamicAccordionSectionContent, EntityBase, EntityDisplayInfo, ExtensionMetadata, ExtensionModule, FunctionHooks, IDebugService, IExtensionFeed, IExtensionMetadataQuery, IPropertiesService, ISceneContext, ISceneExplorerService, ISelectionService, IService, ISettingsContext, ISettingsService, IShellService, IStatsService, IToolsService, ImmutablePrimitiveProps, InfoLabelParentProps, InfoLabelProps, InputHexProps, ListItem, NumberInputPropertyLineProps, PaneProps, PrimitiveProps, PropertyHooks, PropertyLineProps, SceneExplorerCommand, SceneExplorerCommandProvider, SceneExplorerSection, ServiceDefinition, ServiceFactory, SidePaneDefinition, SpinButtonProps, SwitchProps, SyncedSliderProps, TensorPropertyLineProps, TextInputProps, TextareaProps, ToolbarItemDefinition };
71772
+ export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, Link, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useCompactMode, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useSidePaneDockOverrides, useVector3Property };
71773
+ export type { AcceptedDropdownValue, AccordionSectionProps, BasePrimitiveProps, BoundPropertyProps, BuiltInExtension, ButtonProps, CentralContentDefinition, ColorPickerProps, ColorPropertyLineProps, ComboBoxProps, DraggableLineProps, DropdownOption, DropdownProps, DynamicAccordionSection, DynamicAccordionSectionContent, EntityBase, EntityDisplayInfo, ExtensionMetadata, ExtensionModule, FunctionHooks, IDebugService, IExtensionFeed, IExtensionMetadataQuery, IPropertiesService, ISceneContext, ISceneExplorerService, ISelectionService, IService, ISettingsContext, ISettingsService, IShellService, IStatsService, IToolsService, ImmutablePrimitiveProps, InfoLabelParentProps, InfoLabelProps, InputHexProps, LinkProps, ListItem, NumberInputPropertyLineProps, PaneProps, PrimitiveProps, PropertyHooks, PropertyLineProps, SceneExplorerCommand, SceneExplorerCommandProvider, SceneExplorerSection, ServiceDefinition, ServiceFactory, SidePaneDefinition, SpinButtonProps, SwitchProps, SyncedSliderProps, TensorPropertyLineProps, TextInputProps, TextareaProps, ToolbarItemDefinition };
package/lib/index.js CHANGED
@@ -3,10 +3,9 @@ import { useMemo, useEffect, useState, useRef, useCallback, forwardRef, createCo
3
3
  import { Color3, Color4 } from '@babylonjs/core/Maths/math.color.js';
4
4
  import { Vector3, Quaternion, Matrix, Vector2, Vector4, TmpVectors } from '@babylonjs/core/Maths/math.vector.js';
5
5
  import { Observable } from '@babylonjs/core/Misc/observable.js';
6
- import { makeStyles, ToggleButton as ToggleButton$1, Button as Button$1, tokens, Link, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, mergeClasses, Body1, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Portal, Toolbar as Toolbar$1, Tooltip, ToolbarRadioButton, Menu, MenuTrigger, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, treeItemLevelToken, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, TabList, Tab, DialogContent, SplitButton, MenuItemRadio, DialogActions, List as List$1, ListItem, Badge, useId, Input, SpinButton as SpinButton$1, Slider, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, ToolbarButton, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
7
- export { Link } from '@fluentui/react-components';
8
- import { ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, Copy20Regular, PanelLeftExpandRegular, PanelLeftContractRegular, PanelRightExpandRegular, PanelRightContractRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, DocumentTextRegular, createFluentIcon, FilterRegular, GlobeRegular, ArrowExpandAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, MyLocationRegular, CameraRegular, LightbulbRegular, BorderOutsideRegular, BorderNoneRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, DeleteFilled } from '@fluentui/react-icons';
9
- import { Collapse as Collapse$1 } from '@fluentui/react-motion-components-preview';
6
+ import { makeStyles, Link as Link$1, Body1, ToggleButton as ToggleButton$1, Button as Button$1, tokens, InfoLabel as InfoLabel$1, Body1Strong, Checkbox as Checkbox$1, mergeClasses, Accordion as Accordion$1, AccordionItem, AccordionHeader, Subtitle2Stronger, AccordionPanel, Divider, TeachingPopover, TeachingPopoverSurface, TeachingPopoverHeader, TeachingPopoverBody, createLightTheme, createDarkTheme, FluentProvider, Tooltip, Menu, MenuTrigger, SplitButton, MenuPopover, MenuList, MenuItem, Toolbar as Toolbar$1, Portal, RendererProvider, ToolbarRadioButton, createDOMRenderer, MenuGroup, MenuGroupHeader, SearchBox as SearchBox$1, FlatTree, FlatTreeItem, TreeItemLayout, treeItemLevelToken, Switch as Switch$1, PresenceBadge, Spinner, Dialog, DialogTrigger, DialogSurface, DialogBody, DialogTitle, TabList, Tab, DialogContent, MenuItemRadio, DialogActions, List as List$1, ListItem, Badge, useId, Input, SpinButton as SpinButton$1, Slider, MessageBar as MessageBar$1, MessageBarBody, MessageBarTitle, Dropdown as Dropdown$1, Option, Popover, PopoverTrigger, ColorSwatch, PopoverSurface, ColorPicker, ColorArea, ColorSlider, AlphaSlider, Textarea as Textarea$1, ToolbarButton, useComboboxFilter, Combobox, Field } from '@fluentui/react-components';
7
+ import { ChevronCircleRight16Regular, ChevronCircleRight20Regular, ChevronCircleDown16Regular, ChevronCircleDown20Regular, Copy16Regular, Copy20Regular, PanelLeftExpandRegular, PanelRightExpandRegular, PanelLeftContractRegular, PanelRightContractRegular, PictureInPictureEnterRegular, MoreHorizontalRegular, LayoutColumnTwoFocusLeftFilled, LayoutColumnTwoSplitLeftFocusTopLeftFilled, LayoutColumnTwoSplitLeftFocusBottomLeftFilled, LayoutColumnTwoFocusRightFilled, LayoutColumnTwoSplitRightFocusTopRightFilled, LayoutColumnTwoSplitRightFocusBottomRightFilled, DocumentTextRegular, createFluentIcon, FilterRegular, GlobeRegular, ArrowExpandAllRegular, CubeTreeRegular, BugRegular, SettingsRegular, ArrowUploadRegular, DataBarHorizontalRegular, WrenchRegular, AppsAddInRegular, DismissRegular, WeatherSunnyRegular, WeatherMoonRegular, ErrorCircleRegular, ArrowRotateClockwiseRegular, ArrowExpandRegular, SelectObjectRegular, CubeRegular, SaveRegular, ArrowUndoRegular, BracesRegular, BracesDismiss16Regular, CopyRegular, DeleteRegular, EyeOffFilled, EyeFilled, ArrowMoveFilled, StopFilled, PlayFilled, StackRegular, FilmstripRegular, PauseFilled, WeatherSunnyLowFilled, LayerRegular, FrameRegular, PlayRegular, AppGenericRegular, MyLocationRegular, CameraRegular, LightbulbRegular, BorderOutsideRegular, BorderNoneRegular, EyeRegular, EyeOffRegular, VideoFilled, VideoRegular, FlashlightRegular, FlashlightOffRegular, DropRegular, BlurRegular, PipelineRegular, PersonWalkingRegular, DataLineRegular, PersonSquareRegular, LayerDiagonalPersonRegular, ImageEditRegular, ImageRegular, TargetRegular, PersonFeedbackRegular, DeleteFilled } from '@fluentui/react-icons';
8
+ import { Collapse as Collapse$1, Fade } from '@fluentui/react-motion-components-preview';
10
9
  import '@babylonjs/core/Misc/typeStore.js';
11
10
  import { useLocalStorage, useTernaryDarkMode } from 'usehooks-ts';
12
11
  import { AsyncLock } from '@babylonjs/core/Misc/asyncLock.js';
@@ -638,6 +637,11 @@ function copyCommandToClipboard(strCommand) {
638
637
 
639
638
  const ToolContext = createContext({ useFluent: false, disableCopy: false, toolName: "", size: undefined });
640
639
 
640
+ const Link = (props) => {
641
+ const { target, url, onLink, ...rest } = props;
642
+ return (jsxs(Link$1, { inline: true, target: target === "current" ? "_self" : "_blank", rel: "noopener noreferrer", href: url, onClick: onLink ?? undefined, ...rest, children: [props.children, jsx(Body1, { children: props.value })] }));
643
+ };
644
+
641
645
  /**
642
646
  * Toggles between two states using a button with icons.
643
647
  * If no disabledIcon is provided, the button will toggle between visual enabled/disabled states without an icon change
@@ -793,7 +797,7 @@ const PropertyLine = forwardRef((props, ref) => {
793
797
  const { label, onCopy, expandedContent, children, nullable, ignoreNullable } = props;
794
798
  const [expanded, setExpanded] = useState("expandByDefault" in props ? props.expandByDefault : false);
795
799
  const cachedVal = useRef(nullable ? props.value : null);
796
- const description = props.docLink ? jsx(Link, { href: props.docLink, children: props.description ?? "Docs" }) : props.description;
800
+ const description = props.docLink ? jsx(Link, { url: props.docLink, value: props.description ?? "Docs" }) : props.description;
797
801
  // Process children to handle nullable state -- creating component in disabled state with default value in lieu of null value
798
802
  const processedChildren = (nullable || ignoreNullable) && isValidElement(children)
799
803
  ? cloneElement(children, {
@@ -848,7 +852,7 @@ const PlaceholderPropertyLine = (props) => {
848
852
  */
849
853
  const LinkPropertyLine = (props) => {
850
854
  LinkPropertyLine.displayName = "LinkPropertyLine";
851
- return (jsx(PropertyLine, { ...props, children: jsx(Link, { inline: true, onClick: () => props.onLink?.(), href: props.url, title: props.title, children: jsx(Body1, { children: props.value }) }) }));
855
+ return (jsx(PropertyLine, { ...props, children: jsx(Link, { ...props }) }));
852
856
  };
853
857
 
854
858
  /**
@@ -1604,11 +1608,15 @@ const useStyles$d = makeStyles({
1604
1608
  flexDirection: "row",
1605
1609
  },
1606
1610
  paneCollapseButton: {
1607
- margin: `0 ${tokens.spacingHorizontalSNudge}`,
1611
+ margin: `0 0 0 ${tokens.spacingHorizontalXS}`,
1612
+ },
1613
+ collapseMenuPopover: {
1614
+ minWidth: 0,
1608
1615
  },
1609
1616
  pane: {
1610
1617
  backgroundColor: tokens.colorNeutralBackground2,
1611
1618
  display: "flex",
1619
+ flex: 1,
1612
1620
  alignItems: "stretch",
1613
1621
  overflow: "hidden",
1614
1622
  },
@@ -1630,6 +1638,9 @@ const useStyles$d = makeStyles({
1630
1638
  flexDirection: "column",
1631
1639
  overflow: "hidden",
1632
1640
  },
1641
+ unselectedPane: {
1642
+ display: "none",
1643
+ },
1633
1644
  paneHeaderDiv: {
1634
1645
  display: "flex",
1635
1646
  flexDirection: "row",
@@ -1690,6 +1701,16 @@ const useStyles$d = makeStyles({
1690
1701
  display: "flex",
1691
1702
  overflow: "hidden",
1692
1703
  },
1704
+ expandButtonContainer: {
1705
+ position: "absolute",
1706
+ },
1707
+ expandButtonContainerLeft: {
1708
+ left: 0,
1709
+ },
1710
+ expandButtonContainerRight: {
1711
+ right: 0,
1712
+ },
1713
+ expandButton: {},
1693
1714
  });
1694
1715
  const DockMenu = (props) => {
1695
1716
  const { openOnContext, sidePaneId, dockOptions, children } = props;
@@ -1738,14 +1759,15 @@ const SidePaneTab = (props) => {
1738
1759
  // This hook provides a side pane container and the tab list.
1739
1760
  // In "compact" mode, the tab list is integrated into the pane itself.
1740
1761
  // In "full" mode, the returned tab list is later injected into the toolbar.
1741
- function usePane(location, defaultWidth, minWidth, sidePanes, topPaneContainerRef, bottomPaneContainerRef, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems) {
1762
+ function usePane(location, defaultWidth, minWidth, sidePanes, onSelectSidePane, dockOperations, toolbarMode, topBarItems, bottomBarItems) {
1742
1763
  const classes = useStyles$d();
1743
1764
  const [topSelectedTab, setTopSelectedTab] = useState();
1744
1765
  const [bottomSelectedTab, setBottomSelectedTab] = useState();
1745
1766
  const [collapsed, setCollapsed] = useState(false);
1767
+ const [undocked, setUndocked] = useState(false);
1746
1768
  const onExpandCollapseClick = useCallback(() => {
1747
1769
  setCollapsed((collapsed) => !collapsed);
1748
- }, [collapsed]);
1770
+ }, []);
1749
1771
  const widthStorageKey = `Babylon/Settings/${location}Pane/WidthAdjust`;
1750
1772
  const heightStorageKey = `Babylon/Settings/${location}Pane/HeightAdjust`;
1751
1773
  const currentSidePanes = useMemo(() => sidePanes.filter((entry) => entry.horizontalLocation === location), [sidePanes, location]);
@@ -1799,14 +1821,10 @@ function usePane(location, defaultWidth, minWidth, sidePanes, topPaneContainerRe
1799
1821
  });
1800
1822
  return () => observer.remove();
1801
1823
  }, [topPanes, bottomPanes, onSelectSidePane]);
1802
- const expandCollapseIcon = useMemo(() => {
1803
- if (location === "left") {
1804
- return collapsed ? jsx(PanelLeftExpandRegular, {}) : jsx(PanelLeftContractRegular, {});
1805
- }
1806
- else {
1807
- return collapsed ? jsx(PanelRightExpandRegular, {}) : jsx(PanelRightContractRegular, {});
1808
- }
1809
- }, [collapsed, location]);
1824
+ const expandCollapseButton = useMemo(() => {
1825
+ const expandCollapseIcon = location === "left" ? collapsed ? jsx(PanelLeftExpandRegular, {}) : jsx(PanelLeftContractRegular, {}) : collapsed ? jsx(PanelRightExpandRegular, {}) : jsx(PanelRightContractRegular, {});
1826
+ return (jsxs(Menu, { positioning: "below-end", children: [jsx(MenuTrigger, { disableButtonEnhancement: true, children: (triggerProps) => (jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", relationship: "label", children: jsx(SplitButton, { className: classes.paneCollapseButton, menuButton: triggerProps, primaryActionButton: { onClick: onExpandCollapseClick }, size: "small", appearance: "transparent", icon: expandCollapseIcon }) })) }), jsx(MenuPopover, { className: classes.collapseMenuPopover, children: jsx(MenuList, { children: jsx(MenuItem, { icon: jsx(PictureInPictureEnterRegular, {}), onClick: () => setUndocked(true), children: "Undock" }) }) })] }));
1827
+ }, [collapsed, onExpandCollapseClick, location]);
1810
1828
  const createPaneTabList = useCallback((paneComponents, toolbarMode, selectedTab, setSelectedTab, dockOptions) => {
1811
1829
  return (jsx(Fragment, { children: paneComponents.length > 0 && (jsxs("div", { className: `${classes.paneTabListDiv} ${location === "left" || toolbarMode === "compact" ? classes.paneTabListDivLeft : classes.paneTabListDivRight}`, children: [paneComponents.length > 1 && (jsx(Fragment, { children: jsx(Toolbar$1, { className: classes.tabToolbar, checkedValues: { selectedTab: [selectedTab?.key ?? ""] }, onCheckedValueChange: (event, data) => {
1812
1830
  const tab = paneComponents.find((entry) => entry.key === data.checkedItems[0]);
@@ -1815,8 +1833,8 @@ function usePane(location, defaultWidth, minWidth, sidePanes, topPaneContainerRe
1815
1833
  }, children: paneComponents.map((entry) => {
1816
1834
  const isSelected = selectedTab?.key === entry.key;
1817
1835
  return (jsx(SidePaneTab, { location: location, id: entry.key, title: entry.title, icon: entry.icon, suppressTeachingMoment: entry.suppressTeachingMoment, isSelected: isSelected && !collapsed, dockOptions: dockOptions }, entry.key));
1818
- }) }) })), toolbarMode === "full" && (jsxs(Fragment, { children: [paneComponents.length > 1 && (jsxs(Fragment, { children: [jsx(Divider, { vertical: true, inset: true, style: { minHeight: 0 } }), " "] })), jsx(Tooltip, { content: collapsed ? "Show Side Pane" : "Hide Side Pane", relationship: "label", children: jsx(Button$1, { className: classes.paneCollapseButton, appearance: "subtle", icon: expandCollapseIcon, onClick: onExpandCollapseClick }) })] }))] })) }));
1819
- }, [location, collapsed]);
1836
+ }) }) })), toolbarMode === "full" && (jsxs(Fragment, { children: [paneComponents.length > 1 && (jsxs(Fragment, { children: [jsx(Divider, { vertical: true, inset: true, style: { minHeight: 0 } }), " "] })), jsx(Collapse, { visible: !undocked, orientation: "horizontal", children: expandCollapseButton })] }))] })) }));
1837
+ }, [location, collapsed, undocked, expandCollapseButton]);
1820
1838
  // This memos the TabList to make it easy for the JSX to be inserted at the top of the pane (in "compact" mode) or returned to the caller to be used in the toolbar (in "full" mode).
1821
1839
  const topPaneTabList = useMemo(() => createPaneTabList(topPanes, toolbarMode, topSelectedTab, setTopSelectedTab, validTopDockOptions), [createPaneTabList, topPanes, toolbarMode, topSelectedTab]);
1822
1840
  const bottomPaneTabList = useMemo(() => createPaneTabList(bottomPanes, "compact", bottomSelectedTab, setBottomSelectedTab, validBottomDockOptions), [createPaneTabList, bottomPanes, bottomSelectedTab]);
@@ -1852,9 +1870,78 @@ function usePane(location, defaultWidth, minWidth, sidePanes, topPaneContainerRe
1852
1870
  setPaneHeightAdjust(Number.parseInt(storedPaneHeightAdjust));
1853
1871
  }
1854
1872
  }, []);
1873
+ const paneContainerRef = useRef(null);
1874
+ const [windowState, setWindowState] = useState();
1875
+ useEffect(() => {
1876
+ const disposeActions = [];
1877
+ if (undocked) {
1878
+ const paneContainer = paneContainerRef.current;
1879
+ if (!paneContainer) {
1880
+ // It shouldn't be possible to get here and have this ref be null, but just in case,
1881
+ // bail out of the undock operation.
1882
+ setUndocked(false);
1883
+ }
1884
+ else {
1885
+ // This is the extra buffer needed on top of minWidth to account for window chrome to avoid a horizontal scrollbar.
1886
+ const widthBuffer = 4;
1887
+ // This offsets the window's top position to account for window chrome/title bar.
1888
+ const topOffset = 100;
1889
+ // Create the child window with approximately the same location and size as the side pane.
1890
+ const bounds = paneContainer.getBoundingClientRect();
1891
+ const top = bounds.top + window.screenY + topOffset;
1892
+ const left = bounds.left + window.screenX;
1893
+ const width = Math.max(bounds.width, minWidth + widthBuffer);
1894
+ const height = bounds.height - topOffset;
1895
+ const childWindow = window.open("", "", `width=${width},height=${height},left=${left},top=${top},location=no`);
1896
+ if (childWindow) {
1897
+ const body = childWindow.document.body;
1898
+ body.style.width = "100%";
1899
+ body.style.height = "100%";
1900
+ body.style.margin = "0";
1901
+ body.style.padding = "0";
1902
+ body.style.display = "flex";
1903
+ body.style.overflowY = "hidden";
1904
+ body.style.overflowX = "auto";
1905
+ childWindow.document.title = location === "left" ? "Left" : "Right";
1906
+ const applyWindowState = () => {
1907
+ // Setup the window state, including creating a Fluent/Griffel "renderer" for managing runtime styles/classes in the child window.
1908
+ setWindowState({ window: childWindow, mountNode: body, renderer: createDOMRenderer(childWindow.document) });
1909
+ };
1910
+ // Once the child window document is ready, setup the window state which will trigger another effect that renders into the child window.
1911
+ if (childWindow.document.readyState === "complete") {
1912
+ applyWindowState();
1913
+ }
1914
+ else {
1915
+ const onChildWindowLoad = () => {
1916
+ applyWindowState();
1917
+ };
1918
+ childWindow.addEventListener("load", onChildWindowLoad, { once: true });
1919
+ disposeActions.push(() => childWindow.removeEventListener("load", onChildWindowLoad));
1920
+ }
1921
+ // When the child window is closed for any reason, transition back to a docked state.
1922
+ childWindow.addEventListener("unload", () => {
1923
+ setWindowState(undefined);
1924
+ setUndocked(false);
1925
+ }, { once: true });
1926
+ // If the main window closes, close any undocked child windows as well (don't leave them orphaned).
1927
+ const onParentWindowUnload = () => childWindow.close();
1928
+ window.addEventListener("unload", onParentWindowUnload);
1929
+ disposeActions.push(() => window.removeEventListener("unload", onParentWindowUnload));
1930
+ }
1931
+ disposeActions.push(() => childWindow?.close());
1932
+ }
1933
+ }
1934
+ return () => disposeActions.reverse().forEach((dispose) => dispose());
1935
+ }, [undocked]);
1936
+ // This effect closes the window if all panes have been removed.
1937
+ useEffect(() => {
1938
+ if (windowState && topPanes.length === 0 && bottomPanes.length === 0) {
1939
+ windowState.window.close();
1940
+ }
1941
+ }, [windowState, topPanes, bottomPanes]);
1855
1942
  // This memoizes the pane itself, which may or may not include the tab list, depending on the toolbar mode.
1856
- const pane = useMemo(() => {
1857
- return (jsx(Fragment, { children: (topPanes.length > 0 || bottomPanes.length > 0) && (jsxs("div", { className: `${classes.pane} ${location === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsxs("div", { ref: paneHorizontalResizeElementRef, className: classes.paneContainer, style: { width: `clamp(${minWidth}px, calc(${defaultWidth}px + var(${paneWidthAdjustCSSVar}, 0px)), 1000px)` }, children: [toolbarMode === "compact" && (topPanes.length > 1 || topBarItems.length > 0) && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [topPaneTabList, jsx(Toolbar, { location: "top", components: topBarItems })] }) })), topPanes.length > 0 && (jsx("div", { className: classes.paneContent, children: topSelectedTab && (jsxs(Fragment, { children: [jsx(PaneHeader, { id: topSelectedTab.key, title: topSelectedTab.title, dockOptions: validTopDockOptions }), jsx("div", { ref: topPaneContainerRef, className: classes.paneContent })] })) })), topPanes.length > 0 && bottomPanes.length > 0 && jsx(Divider, { ref: paneVerticalResizeHandleRef, className: classes.paneDivider }), bottomPanes.length > 1 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: bottomPaneTabList }) })), bottomPanes.length > 0 && (jsx("div", { ref: paneVerticalResizeElementRef, className: classes.paneContent, style: { height: `clamp(200px, calc(45% + var(${paneHeightAdjustCSSVar}, 0px)), 100% - 300px)`, flex: "0 0 auto" }, children: bottomSelectedTab && (jsxs(Fragment, { children: [jsx(PaneHeader, { id: bottomSelectedTab.key, title: bottomSelectedTab.title, dockOptions: validBottomDockOptions }), jsx("div", { ref: bottomPaneContainerRef, className: classes.paneContent })] })) })), toolbarMode === "compact" && bottomBarItems.length > 0 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarItems }) }) }))] }) }), jsx("div", { ref: paneHorizontalResizeHandleRef, className: `${classes.resizer} ${location === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` } })] })) }));
1943
+ const corePane = useMemo(() => {
1944
+ return (jsxs(Fragment, { children: [toolbarMode === "compact" && (topPanes.length > 1 || topBarItems.length > 0) && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [!undocked && location === "left" && expandCollapseButton, topPaneTabList, jsx(Toolbar, { location: "top", components: topBarItems }), !undocked && location === "right" && expandCollapseButton] }) })), topPanes.length > 0 && (jsx("div", { className: classes.paneContent, children: topSelectedTab && (jsxs(Fragment, { children: [jsx(PaneHeader, { id: topSelectedTab.key, title: topSelectedTab.title, dockOptions: validTopDockOptions }), topPanes.map((pane) => (jsx("div", { className: mergeClasses(classes.paneContent, pane.key !== topSelectedTab.key ? classes.unselectedPane : undefined), children: jsx(pane.content, {}) }, pane.key)))] })) })), topPanes.length > 0 && bottomPanes.length > 0 && jsx(Divider, { ref: paneVerticalResizeHandleRef, className: classes.paneDivider }), bottomPanes.length > 1 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: bottomPaneTabList }) })), bottomPanes.length > 0 && (jsx("div", { ref: paneVerticalResizeElementRef, className: classes.paneContent, style: { height: `clamp(200px, calc(45% + var(${paneHeightAdjustCSSVar}, 0px)), 100% - 300px)`, flex: "0 0 auto" }, children: bottomSelectedTab && (jsxs(Fragment, { children: [jsx(PaneHeader, { id: bottomSelectedTab.key, title: bottomSelectedTab.title, dockOptions: validBottomDockOptions }), bottomPanes.map((pane) => (jsx("div", { className: mergeClasses(classes.paneContent, pane.key !== bottomSelectedTab.key ? classes.unselectedPane : undefined), children: jsx(pane.content, {}) }, pane.key)))] })) })), toolbarMode === "compact" && bottomBarItems.length > 0 && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomBarItems }) }) }))] }));
1858
1945
  }, [
1859
1946
  topPanes,
1860
1947
  topSelectedTab,
@@ -1866,9 +1953,23 @@ function usePane(location, defaultWidth, minWidth, sidePanes, topPaneContainerRe
1866
1953
  bottomBarItems,
1867
1954
  topPaneTabList,
1868
1955
  bottomPaneTabList,
1869
- collapsed,
1956
+ undocked,
1870
1957
  ]);
1871
- return [topPaneTabList, pane, topSelectedTab, bottomSelectedTab];
1958
+ // This deals with docked vs undocked state, where undocked is rendered into a separate window via a portal.
1959
+ const pane = useMemo(() => {
1960
+ if (!windowState) {
1961
+ // If there is no window state, then we are docked, so render the resizable div and the collapse container.
1962
+ return (jsx("div", { ref: paneContainerRef, className: classes.paneContainer, children: (topPanes.length > 0 || bottomPanes.length > 0) && (jsxs("div", { className: `${classes.pane} ${location === "left" ? classes.paneLeft : classes.paneRight}`, children: [jsx(Collapse, { orientation: "horizontal", visible: !collapsed, children: jsx("div", { ref: paneHorizontalResizeElementRef, className: classes.paneContainer, style: { width: `clamp(${minWidth}px, calc(${defaultWidth}px + var(${paneWidthAdjustCSSVar}, 0px)), 1000px)` }, children: corePane }) }), jsx("div", { ref: paneHorizontalResizeHandleRef, className: `${classes.resizer} ${location === "left" ? classes.resizerLeft : classes.resizerRight}`, style: { pointerEvents: `${collapsed ? "none" : "auto"}` } })] })) }));
1963
+ }
1964
+ else {
1965
+ // Otherwise we are undocked, so render into the portal that targets the body of the child window.
1966
+ const { mountNode, renderer } = windowState;
1967
+ return (
1968
+ // Portal targets the body of the child window.
1969
+ jsx(Portal, { mountNode: mountNode, children: jsx(RendererProvider, { renderer: renderer, targetDocument: mountNode.ownerDocument, children: jsx(Theme, { className: classes.paneContent, style: { minWidth }, targetDocument: mountNode.ownerDocument, children: corePane }) }) }));
1970
+ }
1971
+ }, [collapsed, corePane, windowState]);
1972
+ return [topPaneTabList, pane, collapsed, setCollapsed];
1872
1973
  }
1873
1974
  function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWidth = 350, rightPaneDefaultWidth = 350, rightPaneMinWidth = 350, toolbarMode = "full", sidePaneRemapper = undefined, } = {}) {
1874
1975
  return {
@@ -1898,37 +1999,29 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
1898
1999
  const coercedSidePanes = useMemo(() => {
1899
2000
  // First pass - apply overrides and respect the side pane mode.
1900
2001
  const coercedSidePanes = sidePanes.map((sidePaneDefinition) => {
1901
- let sidePaneEntry = coercedSidePaneCache.current.get(sidePaneDefinition.key);
1902
- if (!sidePaneEntry) {
1903
- // Manually create html element containers outside the React tree to prevent unmounting/mounting
1904
- // when panes are re-docked or the selected tabs change. This preserves state within the side panes.
1905
- // This is combined with the usage of React portals to make it all work.
1906
- const sidePaneContainer = document.createElement("div");
1907
- sidePaneContainer.style.display = "flex";
1908
- sidePaneContainer.style.flex = "1";
1909
- sidePaneContainer.style.flexDirection = "column";
1910
- sidePaneContainer.style.overflow = "hidden";
1911
- sidePaneEntry = { ...sidePaneDefinition, container: sidePaneContainer };
1912
- coercedSidePaneCache.current.set(sidePaneDefinition.key, sidePaneEntry);
2002
+ let coercedSidePane = coercedSidePaneCache.current.get(sidePaneDefinition.key);
2003
+ if (!coercedSidePane) {
2004
+ coercedSidePane = { ...sidePaneDefinition };
2005
+ coercedSidePaneCache.current.set(sidePaneDefinition.key, coercedSidePane);
1913
2006
  }
1914
2007
  const override = sidePaneDockOverrides[sidePaneDefinition.key];
1915
2008
  if (override) {
1916
2009
  // Override (user manually re-docked) has the highest priority.
1917
- sidePaneEntry.horizontalLocation = override.horizontalLocation;
1918
- sidePaneEntry.verticalLocation = override.verticalLocation;
2010
+ coercedSidePane.horizontalLocation = override.horizontalLocation;
2011
+ coercedSidePane.verticalLocation = override.verticalLocation;
1919
2012
  }
1920
2013
  else if (sidePaneRemapper) {
1921
2014
  // A side pane remapper has the next highest priority.
1922
2015
  const { horizontalLocation, verticalLocation } = sidePaneRemapper(sidePaneDefinition);
1923
- sidePaneEntry.horizontalLocation = horizontalLocation;
1924
- sidePaneEntry.verticalLocation = verticalLocation;
2016
+ coercedSidePane.horizontalLocation = horizontalLocation;
2017
+ coercedSidePane.verticalLocation = verticalLocation;
1925
2018
  }
1926
2019
  else {
1927
2020
  // Otherwise use the default defined location.
1928
- sidePaneEntry.horizontalLocation = sidePaneDefinition.horizontalLocation;
1929
- sidePaneEntry.verticalLocation = sidePaneDefinition.verticalLocation;
2021
+ coercedSidePane.horizontalLocation = sidePaneDefinition.horizontalLocation;
2022
+ coercedSidePane.verticalLocation = sidePaneDefinition.verticalLocation;
1930
2023
  }
1931
- return sidePaneEntry;
2024
+ return coercedSidePane;
1932
2025
  });
1933
2026
  // Second pass - correct any invalid state, specifically if there are only bottom panes, force them to be top panes.
1934
2027
  for (const side of ["left", "right"]) {
@@ -2005,31 +2098,9 @@ function MakeShellServiceDefinition({ leftPaneDefaultWidth = 350, leftPaneMinWid
2005
2098
  const bottomBarLeftItems = useMemo(() => bottomToolBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "left"), [bottomToolBarItems, coerceToolBarItemHorizontalLocation]);
2006
2099
  const bottomBarRightItems = useMemo(() => bottomToolBarItems.filter((entry) => coerceToolBarItemHorizontalLocation(entry) === "right"), [bottomToolBarItems, coerceToolBarItemHorizontalLocation]);
2007
2100
  const centralContents = useOrderedObservableCollection(centralContentCollection);
2008
- const [topLeftPaneContainer, setTopLeftPaneContainer] = useState(null);
2009
- const [bottomLeftPaneContainer, setBottomLeftPaneContainer] = useState(null);
2010
- const [topRightPaneContainer, setTopRightPaneContainer] = useState(null);
2011
- const [bottomRightPaneContainer, setBottomRightPaneContainer] = useState(null);
2012
- const [leftPaneTabList, leftPane, topLeftSelectedPane, bottomLeftSelectedPane] = usePane("left", leftPaneDefaultWidth, leftPaneMinWidth, coercedSidePanes, setTopLeftPaneContainer, setBottomLeftPaneContainer, onSelectSidePane, sidePaneDockOperations, toolbarMode, topBarLeftItems, bottomBarLeftItems);
2013
- const [rightPaneTabList, rightPane, topRightSelectedPane, bottomRightSelectedPane] = usePane("right", rightPaneDefaultWidth, rightPaneMinWidth, coercedSidePanes, setTopRightPaneContainer, setBottomRightPaneContainer, onSelectSidePane, sidePaneDockOperations, toolbarMode, topBarRightItems, bottomBarRightItems);
2014
- // Update the content of the top left pane container.
2015
- useEffect(() => {
2016
- topLeftPaneContainer?.replaceChildren(...(topLeftSelectedPane ? [topLeftSelectedPane.container] : []));
2017
- }, [topLeftPaneContainer, topLeftSelectedPane]);
2018
- // Update the content of the bottom left pane container.
2019
- useEffect(() => {
2020
- bottomLeftPaneContainer?.replaceChildren(...(bottomLeftSelectedPane ? [bottomLeftSelectedPane.container] : []));
2021
- }, [bottomLeftPaneContainer, bottomLeftSelectedPane]);
2022
- // Update the content of the top right pane container.
2023
- useEffect(() => {
2024
- topRightPaneContainer?.replaceChildren(...(topRightSelectedPane ? [topRightSelectedPane.container] : []));
2025
- }, [topRightPaneContainer, topRightSelectedPane]);
2026
- // Update the content of the bottom right pane container.
2027
- useEffect(() => {
2028
- bottomRightPaneContainer?.replaceChildren(...(bottomRightSelectedPane ? [bottomRightSelectedPane.container] : []));
2029
- }, [bottomRightPaneContainer, bottomRightSelectedPane]);
2030
- return (jsxs("div", { className: classes.mainView, children: [toolbarMode === "full" && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [leftPaneTabList, jsx(Toolbar, { location: "top", components: topToolBarItems }), rightPaneTabList] }) })), jsxs("div", { className: classes.verticallyCentralContent, children: [leftPane, jsx("div", { className: classes.centralContent, children: centralContents.map((entry) => (jsx(entry.component, {}, entry.key))) }), rightPane] }), toolbarMode === "full" && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomToolBarItems }) }) })), coercedSidePanes.map((sidePaneDefinition) => {
2031
- return (jsx(Portal, { mountNode: sidePaneDefinition.container, children: jsx(sidePaneDefinition.content, {}) }, sidePaneDefinition.key));
2032
- })] }));
2101
+ const [leftPaneTabList, leftPane, leftPaneCollapsed, setLeftPaneCollapsed] = usePane("left", leftPaneDefaultWidth, leftPaneMinWidth, coercedSidePanes, onSelectSidePane, sidePaneDockOperations, toolbarMode, topBarLeftItems, bottomBarLeftItems);
2102
+ const [rightPaneTabList, rightPane, rightPaneCollapsed, setRightPaneCollapsed] = usePane("right", rightPaneDefaultWidth, rightPaneMinWidth, coercedSidePanes, onSelectSidePane, sidePaneDockOperations, toolbarMode, topBarRightItems, bottomBarRightItems);
2103
+ return (jsxs("div", { className: classes.mainView, children: [toolbarMode === "full" && (jsx(Fragment, { children: jsxs("div", { className: classes.barDiv, children: [leftPaneTabList, jsx(Toolbar, { location: "top", components: topToolBarItems }), rightPaneTabList] }) })), jsxs("div", { className: classes.verticallyCentralContent, children: [leftPane, jsxs("div", { className: classes.centralContent, children: [centralContents.map((entry) => (jsx(entry.component, {}, entry.key))), toolbarMode === "compact" && (jsxs(Fragment, { children: [jsx(Fade, { visible: leftPaneCollapsed, delay: 50, children: jsx("div", { className: mergeClasses(classes.expandButtonContainer, classes.expandButtonContainerLeft), children: jsx(Tooltip, { content: "Show Side Pane", relationship: "label", children: jsx(Button$1, { className: classes.expandButton, icon: jsx(PanelLeftExpandRegular, {}), onClick: () => setLeftPaneCollapsed(false) }) }) }) }), jsx(Fade, { visible: rightPaneCollapsed, delay: 50, children: jsx("div", { className: mergeClasses(classes.expandButtonContainer, classes.expandButtonContainerRight), children: jsx(Tooltip, { content: "Show Side Pane", relationship: "label", children: jsx(Button$1, { className: classes.expandButton, icon: jsx(PanelRightExpandRegular, {}), onClick: () => setRightPaneCollapsed(false) }) }) }) })] }))] }), rightPane] }), toolbarMode === "full" && (jsx(Fragment, { children: jsx("div", { className: classes.barDiv, children: jsx(Toolbar, { location: "bottom", components: bottomToolBarItems }) }) }))] }));
2033
2104
  };
2034
2105
  rootComponent.displayName = "Shell Service Root";
2035
2106
  return {
@@ -2594,26 +2665,37 @@ const SceneExplorer = (props) => {
2594
2665
  for (let treeItem = allTreeItems.get(entity.uniqueId); treeItem; treeItem = treeItem?.type === "entity" ? treeItem.parent : undefined) {
2595
2666
  parentStack.push(treeItem.type === "entity" ? treeItem.entity.uniqueId : treeItem.sectionName);
2596
2667
  }
2668
+ // The first item will be the entity itself, so just remove it.
2669
+ parentStack.shift();
2597
2670
  return parentStack;
2598
2671
  }, [allTreeItems]);
2599
- const [isScrollToPending, setIsScrollToPending] = useState(false);
2600
- useEffect(() => {
2601
- if (selectedEntity && selectedEntity !== previousSelectedEntity.current) {
2602
- const entity = selectedEntity;
2603
- if (entity.uniqueId != undefined) {
2604
- const parentStack = getParentStack(entity);
2605
- if (parentStack.length > 0) {
2606
- const newOpenItems = new Set(openItems);
2607
- for (const parent of parentStack) {
2608
- newOpenItems.add(parent);
2609
- }
2610
- setOpenItems(newOpenItems);
2611
- setIsScrollToPending(true);
2672
+ const selectEntity = useCallback((selectedEntity) => {
2673
+ const entity = selectedEntity;
2674
+ if (entity && entity.uniqueId != undefined) {
2675
+ const parentStack = getParentStack(entity);
2676
+ if (parentStack.length > 0) {
2677
+ const newOpenItems = new Set(openItems);
2678
+ for (const parent of parentStack) {
2679
+ newOpenItems.add(parent);
2612
2680
  }
2681
+ setOpenItems(newOpenItems);
2682
+ setIsScrollToPending(true);
2613
2683
  }
2614
2684
  }
2615
2685
  previousSelectedEntity.current = selectedEntity;
2616
- }, [selectedEntity]);
2686
+ }, [getParentStack, openItems]);
2687
+ const [isScrollToPending, setIsScrollToPending] = useState(false);
2688
+ useEffect(() => {
2689
+ if (selectedEntity && selectedEntity !== previousSelectedEntity.current) {
2690
+ selectEntity(selectedEntity);
2691
+ }
2692
+ }, [selectedEntity, selectEntity]);
2693
+ useEffect(() => {
2694
+ // If there are no open items, then it should mean scene explorer has only just mounted, so we should select the already selected entity.
2695
+ if (openItems.size === 0) {
2696
+ selectEntity(selectedEntity);
2697
+ }
2698
+ }, [openItems, selectEntity, selectedEntity]);
2617
2699
  // We need to wait for a render to complete before we can scroll to the item, hence the isScrollToPending.
2618
2700
  useEffect(() => {
2619
2701
  if (isScrollToPending) {
@@ -3916,7 +3998,7 @@ const ExtensionListServiceDefinition = {
3916
3998
 
3917
3999
  const useStyles$9 = makeStyles({
3918
4000
  themeButton: {
3919
- margin: `${tokens.spacingVerticalXXS} 0`,
4001
+ margin: 0,
3920
4002
  },
3921
4003
  themeMenuPopover: {
3922
4004
  minWidth: 0,
@@ -4192,7 +4274,7 @@ const MaterialIcon = createFluentIcon("Material", "16", '<path d="M14.74,6.3c-.0
4192
4274
 
4193
4275
  const useStyles$7 = makeStyles({
4194
4276
  coordinatesModeButton: {
4195
- margin: `0 ${tokens.spacingVerticalXS}`,
4277
+ margin: `0 0 0 ${tokens.spacingHorizontalXS}`,
4196
4278
  },
4197
4279
  coordinatesModeMenu: {
4198
4280
  minWidth: 0,
@@ -4617,7 +4699,7 @@ const MessageBar = (props) => {
4617
4699
  MessageBar.displayName = "MessageBar";
4618
4700
  const { message, title: header, intent, docLink } = props;
4619
4701
  const classes = useClasses();
4620
- return (jsx("div", { className: classes.container, children: jsx(MessageBar$1, { intent: intent, layout: "multiline", children: jsxs(MessageBarBody, { children: [jsx(MessageBarTitle, { children: header }), message, docLink && (jsxs(Fragment, { children: [" - ", jsx(Link, { href: docLink, target: "_blank", rel: "noopener noreferrer", children: "Learn More" })] }))] }) }) }));
4702
+ return (jsx("div", { className: classes.container, children: jsx(MessageBar$1, { intent: intent, layout: "multiline", children: jsxs(MessageBarBody, { children: [jsx(MessageBarTitle, { children: header }), message, docLink && (jsxs(Fragment, { children: [" - ", jsx(Link, { url: docLink, value: "Learn More" })] }))] }) }) }));
4621
4703
  };
4622
4704
 
4623
4705
  const AnimationsProperties = (props) => {
@@ -4917,7 +4999,7 @@ const InputHexField = (props) => {
4917
4999
  info: !props.linearHex ? undefined : !isLinearMode ? ( // If representing a linear hex but we are in gammaMode, simple message explaining why linearHex is disabled
4918
5000
  jsx(Fragment, { children: " This color picker is attached to an entity whose color is stored in gamma space, so we are showing linear hex in disabled view " })) : (
4919
5001
  // If representing a linear hex and we are in linearMode, give information about how to use these hex values
4920
- jsxs(Fragment, { children: ["This color picker is attached to an entity whose color is stored in linear space (ex: PBR Material), and Babylon converts the color to gamma space before rendering on screen because the human eye is best at processing colors in gamma space. We thus also want to display the color picker in gamma space so that the color chosen here will match the color seen in your entity.", jsx("br", {}), "If you want to copy/paste the HEX into your code, you can either use", jsx(Body1Strong, { children: "Color3.FromHexString(LINEAR_HEX)" }), jsx("br", {}), "or", jsx("br", {}), jsx(Body1Strong, { children: "Color3.FromHexString(GAMMA_HEX).toLinearSpace()" }), jsx("br", {}), jsx("br", {}), jsx(Link, { href: "https://doc.babylonjs.com/preparingArtForBabylon/controllingColorSpace/", children: " Read more in our docs! " })] })),
5002
+ jsxs(Fragment, { children: ["This color picker is attached to an entity whose color is stored in linear space (ex: PBR Material), and Babylon converts the color to gamma space before rendering on screen because the human eye is best at processing colors in gamma space. We thus also want to display the color picker in gamma space so that the color chosen here will match the color seen in your entity.", jsx("br", {}), "If you want to copy/paste the HEX into your code, you can either use", jsx(Body1Strong, { children: "Color3.FromHexString(LINEAR_HEX)" }), jsx("br", {}), "or", jsx("br", {}), jsx(Body1Strong, { children: "Color3.FromHexString(GAMMA_HEX).toLinearSpace()" }), jsx("br", {}), jsx("br", {}), jsx(Link, { url: "https://doc.babylonjs.com/preparingArtForBabylon/controllingColorSpace/", value: "Read more in our docs!" })] })),
4921
5003
  }
4922
5004
  : undefined }));
4923
5005
  };
@@ -9659,5 +9741,5 @@ const TextAreaPropertyLine = (props) => {
9659
9741
  return (jsx(PropertyLine, { ...props, children: jsx(Textarea, { ...props }) }));
9660
9742
  };
9661
9743
 
9662
- export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useCompactMode, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useSidePaneDockOverrides, useVector3Property };
9744
+ export { Accordion, AccordionSection, BooleanBadgePropertyLine, BoundProperty, BuiltInsExtensionFeed, Button, ButtonLine, Checkbox, CheckboxPropertyLine, Collapse, Color3GradientComponent, Color3GradientList, Color3PropertyLine, Color4GradientComponent, Color4GradientList, Color4PropertyLine, ColorPickerPopup, ColorStepGradientComponent, ComboBox, ConstructorFactory, DebugServiceIdentity, DraggableLine, Dropdown, ExtensibleAccordion, FactorGradientComponent, FactorGradientList, FileUploadLine, GetPropertyDescriptor, HexPropertyLine, HideInspector, InfoLabel, InputHexField, InputHsvField, Inspector, InterceptFunction, InterceptProperty, IsInspectorVisible, IsPropertyReadonly, LineContainer, Link, LinkPropertyLine, LinkToEntityPropertyLine, List, MakeDialogTeachingMoment, MakeLazyComponent, MakePopoverTeachingMoment, MakePropertyHook, MakeTeachingMoment, MessageBar, NumberDropdown, NumberDropdownPropertyLine, NumberInputPropertyLine, ObservableCollection, Pane, PlaceholderPropertyLine, PositionedPopover, PropertiesServiceIdentity, PropertyLine, QuaternionPropertyLine, RotationVectorPropertyLine, SceneContextIdentity, SceneExplorerServiceIdentity, SearchBar, SearchBox, SelectionServiceDefinition, SelectionServiceIdentity, SettingsContextIdentity, SettingsServiceIdentity, ShellServiceIdentity, ShowInspector, SidePaneContainer, SpinButton, SpinButtonPropertyLine, StatsServiceIdentity, StringDropdown, StringDropdownPropertyLine, StringifiedPropertyLine, Switch, SwitchPropertyLine, SyncedSliderInput, SyncedSliderPropertyLine, TeachingMoment, TextAreaPropertyLine, TextInput, TextInputPropertyLine, TextPropertyLine, Textarea, ToggleButton, ToolsServiceIdentity, Vector2PropertyLine, Vector3PropertyLine, Vector4PropertyLine, useAngleConverters, useAsyncResource, useColor3Property, useColor4Property, useCompactMode, useEventfulState, useInterceptObservable, useObservableCollection, useObservableState, useOrderedObservableCollection, usePollingObservable, useProperty, useQuaternionProperty, useResource, useSidePaneDockOverrides, useVector3Property };
9663
9745
  //# sourceMappingURL=index.js.map