rc-dock

repository·master·Indexed 21 days ago

https://github.com/ticlo/rc-dock

A React component for creating complex, dockable window layouts similar to IDE interfaces. It supports docking, floating panels, and tabbed interfaces through a hierarchical structure of LayoutData, BoxData, PanelData, and TabData. Version 4.0.0-alpha.2 provides both controlled and uncontrolled modes, an imperative API for programmatic layout manipulation (including saveLayout, loadLayout, and dockMove), and customizable tab loading/saving behaviors.

Tokens
4.8K
Snippets
20
Records
30
Agent score
73%

What's inside rc-dock

  1. How DockLayout, BoxData, PanelData, and TabData work together

    master

    The layout is structured as a hierarchy of nested objects:

    • LayoutData: The root object containing a dockbox (the main layout area) and an optional floatbox (for floating elements).
    • BoxData: A structural element that contains other boxes or panels. It defines the layout orientation using mode ('horizontal', 'vertical', or 'float') and holds children.
    • PanelData: A visual container that holds a set of tabs. It includes a tabs array and an optional panelLock to prevent removal or floating.
    • TabData: The individual leaf nodes containing the actual content. Each tab requires a unique id, a title, and content (a React element or a function returning one).
  2. Install and use rc-dock in a React application

    master

    To use rc-dock, import the DockLayout component and its required CSS file. You can manage the layout in two ways:

    1. Uncontrolled Layout: Provide the initial layout configuration via the defaultLayout prop.
    2. Controlled Layout: Manage the layout state yourself and provide it via the layout prop.

    Ensure the DockLayout component has a defined size (e.g., via absolute positioning) so it is visible.

    import DockLayout from 'rc-dock'
    import "rc-dock/dist/rc-dock.css";
    
    const defaultLayout = {
      dockbox: {
        mode: 'horizontal',
        children: [
          {
            tabs: [
              {id: 'tab1', title: 'tab1', content: <div>Hello World</div>}
            ]
          }
        ]
      }
    };
    
    // In your component render:
    <DockLayout
      defaultLayout={defaultLayout}
      style={{
        position: "absolute",
        left: 10,
        top: 10,
        right: 10,
        bottom: 10,
      }}
    />
  3. Understand the LayoutData structure

    master

    The LayoutData object is the top-level configuration for the entire dock system. It is composed of several specialized boxes:

    • dockbox: The main layout container (BoxData).
    • floatbox: Contains floating panels (PanelData).
    • windowbox: Contains panels that have been moved to native windows (PanelData).
    • maxbox: Contains the single panel currently in maximized mode (PanelData).
  4. Use controlled mode with DockLayout

    master

    To treat DockLayout as a fully controlled component, pass the current layout state to the layout prop and use the onLayoutChange callback to update your state. This is necessary if you want to manage the layout state externally (e.g., in a Redux store or parent component state).

    const [layout, setLayout] = useState<LayoutBase>(initialLayout);
    
    <DockLayout
      layout={layout}
      onLayoutChange={(newLayout) => setLayout(newLayout)}
    />
  5. Use the DockLayout imperative API

    master

    To perform programmatic actions like saving layouts, moving tabs, or finding items, you must obtain a ref to the DockLayout component.

    Available methods:

    • saveLayout(): Returns a SavedLayout object representing the current state.
    • loadLayout(savedLayout: SavedLayout): Restores the layout from a previously saved object.
    • dockMove(source, target, direction): Moves a tab or panel to a new location or container.
    • find(id | predicate): Locates a PanelData or TabData by its ID or a search function.
    • updateTab(id, newTab): Updates an existing tab with new data. Returns false if the tab is not found.
  6. Configure drop mode for panel dragging

    master

    The dropMode prop determines how the UI responds when dragging a panel:

    • 'default': Shows 4 to 9 squares to help the user pick a drop area.
    • 'edge': Uses the distance between the mouse and the panel border to pick the drop area. In this mode, dragging a float panel's header will not bring the panel back to the dock layer.
  7. Customize tab loading and saving

    master

    You can intercept how tabs and panels are serialized and deserialized using these props:

    • saveTab(tab: TabData): TabBase: Override this to customize how a tab is saved. It must return an object with at least a unique id.
    • loadTab(tab: TabBase): TabData: Override this to customize how a tab is loaded.
      • If loadTab is defined, defaultLayout only needs to contain IDs and custom data for tabs.
      • If loadTab is NOT defined, defaultLayout must contain full title and content for all tabs.
    • afterPanelSaved(savedPanel: PanelBase, panel: PanelData): void: Modify the panel data before it is saved (e.g., to add extra metadata).
    • afterPanelLoaded(savedPanel: PanelBase, loadedPanel: PanelData): void: Modify the panel data after it is loaded. You can add data or replace tabs (ensure you provide full title and content when replacing tabs).
  8. Use maximizeTo to specify a portal for maximized panels

    master

    By default, a maximized panel renders within the DockLayout hierarchy. If you provide the maximizeTo prop, the maximized panel will be rendered into a React Portal at the specified location.

    • Pass a string representing the id of a DOM element.
    • Pass an HTMLElement directly.
    // Using an element ID
    <DockLayout maximizeTo="my-portal-container" ... />
    
    // Using a DOM element
    const container = document.getElementById('overlay');
    <DockLayout maximizeTo={container} ... />
  9. Configure TabGroup behavior and styles

    master

    A TabGroup defines how tabs within a panel behave and how the panel header is rendered. You can define custom groups in your layout to control features like floating, maximizing, and locking. Use the panelExtra property to inject custom React elements (like buttons or listeners) into the right side of the panel's tab bar.

    const myGroups = {
      specialGroup: {
        floatable: 'singleTab',
        maximizable: true,
        tabLocked: true,
        panelExtra: (panel: PanelData) => (
          <button onClick={() => console.log('Panel extra clicked')}>Action</button>
        ),
      }
    };
  10. Reference: BoxData configuration

    master

    A box is a layout element that contains other boxes or panels.

    PropertyTypeCommentsDefault
    mode'horizontal''vertical''float'
    children(BoxData | PanelData)[]children boxes or panelsrequired
    {
      "mode": "horizontal",
      "children": []
    }
  11. Reference: LayoutData structure

    master

    The root layout object structure.

    PropertyTypeCommentsDefault
    dockboxBoxDatamain dock boxempty BoxData
    floatboxBoxDatamain float box, children can only be PanelDataempty BoxData
    {
      "dockbox": { ... },
      "floatbox": { ... }
    }
  12. Reference: PanelData configuration

    master

    A panel is a visual container with a tabs button in the title bar.

    PropertyTypeCommentsDefault
    tabsTabData[]children tabsrequired
    panelLockPanelLockprevents the panel from being removed when empty or being moved to float layer
    {
      "tabs": [],
      "panelLock": undefined
    }