Online demo: https://gridstack-react.pages.dev/
The code in this repository will be manually copied to the react folder of the gridstack.js main repository.
- Add Widgets
- Add Sub Grid
- Nested Sub Grid
- Remove Widget
- Copy(Duplicate) Widget
- Custom handle
- Drag between two grid stacks
Welcome to give any suggestions and ideas, you can submit an issue or contact me by email. :)
Simple
Render item with widget id selector.
function App() {
const [uncontrolledInitialOptions] = useState<GridStackOptions>({
// ...
children: [
{ id: "item1", h: 2, w: 2, x: 0, y: 0 },
{ id: "item2", h: 2, w: 2, x: 2, y: 0 },
],
});
return (
<GridStackProvider initialOptions={uncontrolledInitialOptions}>
<Toolbar />
<GridStackRender>
<GridStackItem id="item1">
<div>hello</div>
</GridStackItem>
<GridStackItem id="item2">
<div>grid</div>
</GridStackItem>
</GridStackRender>
</GridStackProvider>
);
}
Advanced
Render item with widget map component info.
ComponentInfoMap is just an example, you can use any way you want to store and retrieve component information.
function App() {
const [uncontrolledInitialOptions] = useState<GridStackOptions>({
// ...
children: [
{ id: "item1", h: 2, w: 2, x: 0, y: 0 },
{ id: "item2", h: 2, w: 2, x: 2, y: 0 },
],
});
const [initialComponentInfoMap] = useState<Record<string, ComponentInfo>>(
() => ({
item1: { component: "Text", serializableProps: { content: "Text" } },
item2: {
component: "ComplexCard",
serializableProps: { title: "Complex Card", color: "red" },
},
})
);
return (
<ComponentInfoMapProvider initialComponentInfoMap={initialComponentInfoMap}>
<GridStackProvider initialOptions={uncontrolledInitialOptions}>
<Toolbar />
<GridStackRender>
<DynamicGridStackItems />
</GridStackRender>
</GridStackProvider>
</ComponentInfoMapProvider>
);
}
export function DynamicGridStackItems() {
const { componentInfoMap } = useComponentInfoMap();
return (
<>
{Array.from(componentInfoMap.entries()).map(
([widgetId, componentInfo]) => {
const Component = COMPONENT_MAP[componentInfo.component];
if (!Component) {
throw new Error(`Component ${componentInfo.component} not found`);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const props = componentInfo.serializableProps as any;
if (componentInfo.component === "ComplexCard") {
return (
<GridStackItem key={widgetId} id={widgetId}>
<ComplexCardEditableWrapper
key={`complex-card-editable-wrapper-${widgetId}`}
serializableProps={componentInfo.serializableProps}
>
<Component {...props} key={`component-${widgetId}`} />
</ComplexCardEditableWrapper>
</GridStackItem>
);
}
return (
<GridStackItem key={widgetId} id={widgetId}>
<Component {...props} key={`component-${widgetId}`} />
</GridStackItem>
);
}
)}
</>
);
}
Experimental
Render item with custom handle.
<GridStackItem id="xxx">
<GridStackHandleReInitializer>
<button className={CUSTOM_DRAGGABLE_HANDLE_CLASSNAME}>
Handle ONLY HERE
</button>
</GridStackHandleReInitializer>
</GridStackItem>
Top-level component that provides GridStack context.
type GridStackProviderProps = {
initialOptions: GridStackOptions; // GridStack initialization options
children: React.ReactNode;
};
Render GridStack root container component.
type GridStackRenderProps = {
children: React.ReactNode;
};
Component representing a single grid item.
type GridStackItemProps = {
id: string; // Grid item unique identifier
children: React.ReactNode;
};
Experimental component for reinitializing the drag handle of a grid item.
type GridStackHandleReInitializerProps = {
children: React.ReactNode;
};
Provide GridStack core functionality context.
interface GridStackContextType {
initialOptions: GridStackOptions;
addWidget: (widget: GridStackWidget) => void;
removeWidget: (el: GridStackElement) => void;
saveOptions: () => ReturnType<GridStack["save"]> | undefined;
_gridStack: {
value: GridStack | null;
set: React.Dispatch<React.SetStateAction<GridStack | null>>;
};
}
Provide single grid item functionality context.
type GridStackItemContextType = {
id: string;
remove: () => void;
getBounds: () => {
current: { x?: number; y?: number; w?: number; h?: number };
original: { x?: number; y?: number; w?: number; h?: number };
} | null;
setSize: (size: { w: number; h: number }) => void;
};
Provide rendering related functionality context.
type GridStackRenderContextType = {
getWidgetContainer: (widgetId: string) => HTMLElement | null;
};
Get GridStack context.
function useGridStackContext(): GridStackContextType;
Get grid item context.
function useGridStackItemContext(): GridStackItemContextType;
Get rendering context.
function useGridStackRenderContext(): GridStackRenderContextType;
export type {
GridStackContextType,
GridStackProviderProps,
GridStackRenderContextType,
GridStackRenderProps,
GridStackItemProps,
GridStackItemContextType,
GridStackHandleReInitializerProps,
};