From d53e055a42374e85bd2f9482bd56f2350f41b986 Mon Sep 17 00:00:00 2001 From: Alexiz Hernandez Date: Tue, 25 Jun 2024 17:54:46 -0700 Subject: [PATCH] added grid gap prop to support adding any gaps to width/height --- README.md | 5 +++ src/index.tsx | 13 +++++-- stories/grid.stories.tsx | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 stories/grid.stories.tsx diff --git a/README.md b/README.md index 65d80b2a..1e1f5fe1 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,11 @@ The `maxHeight` property is used to set the maximum height of a resizable compon The `grid` property is used to specify the increments that resizing should snap to. Defaults to `[1, 1]`. +#### `gridGap?: [number, number];` + +The `gridGap` property is used to specify any gaps between your grid cells that should be accounted for when resizing. Defaults to `[0, 0]`. +The value provided for each axis will always add the grid gap amount times grid cells spanned minus one. + #### `snap?: { x?: Array, y?: Array };` The `snap` property is used to specify absolute pixel values that resizing should snap to. `x` and `y` are both optional, allowing you to only include the axis you want to define. Defaults to `null`. diff --git a/src/index.tsx b/src/index.tsx index f58fb1ca..9c581d88 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -82,6 +82,7 @@ export interface ResizableProps { style?: React.CSSProperties; className?: string; grid?: [number, number]; + gridGap?: [number, number]; snap?: { x?: number[]; y?: number[]; @@ -129,7 +130,11 @@ interface State { } const clamp = (n: number, min: number, max: number): number => Math.max(Math.min(n, max), min); -const snap = (n: number, size: number): number => Math.round(n / size) * size; +const snap = (n: number, size: number, gridGap: number): number => { + const v = Math.round(n / size); + + return v * size + gridGap * (v - 1); +}; const hasDirection = (dir: 'top' | 'right' | 'bottom' | 'left', target: string): boolean => new RegExp(dir, 'i').test(target); @@ -242,6 +247,7 @@ const definedProps = [ 'style', 'className', 'grid', + 'gridGap', 'snap', 'bounds', 'boundsByDirection', @@ -373,6 +379,7 @@ export class Resizable extends React.PureComponent { }, style: {}, grid: [1, 1], + gridGap: [0, 0], lockAspectRatio: false, lockAspectRatioExtraWidth: 0, lockAspectRatioExtraHeight: 0, @@ -801,8 +808,8 @@ export class Resizable extends React.PureComponent { newHeight = newSize.newHeight; if (this.props.grid) { - const newGridWidth = snap(newWidth, this.props.grid[0]); - const newGridHeight = snap(newHeight, this.props.grid[1]); + const newGridWidth = snap(newWidth, this.props.grid[0], this.props.gridGap ? this.props.gridGap[0] : 0); + const newGridHeight = snap(newHeight, this.props.grid[1], this.props.gridGap ? this.props.gridGap[1] : 0); const gap = this.props.snapGap || 0; const w = gap === 0 || Math.abs(newGridWidth - newWidth) <= gap ? newGridWidth : newWidth; const h = gap === 0 || Math.abs(newGridHeight - newHeight) <= gap ? newGridHeight : newHeight; diff --git a/stories/grid.stories.tsx b/stories/grid.stories.tsx new file mode 100644 index 00000000..ecf3de91 --- /dev/null +++ b/stories/grid.stories.tsx @@ -0,0 +1,82 @@ +import * as React from 'react'; +import { Resizable } from '../src'; +import { storiesOf } from '@storybook/react'; +import { style } from './style'; + +const cell: React.CSSProperties = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '100px', + height: '50px', + backgroundColor: '#f8f8f8', + border: '1px solid #f0f0f0', + boxSizing: 'border-box', +}; + +const container: React.CSSProperties = { + display: 'flex', + gap: '3px', +}; + +const verticalContainer: React.CSSProperties = { + display: 'flex', + flexDirection: 'column', + gap: '3px', +}; + +storiesOf('grid', module) + .add('default', () => ( + { + console.log(a); + }} + > + 001 + + )) + .add('grid gap', () => ( +
+
+
+ {Array.from({ length: 3 }, (_, idx) => ( +
h: 50px
+ ))} +
+
+
+ {Array.from({ length: 3 }, (_, idx) => ( +
+ w: 100px +
+ ))} +
+ { + console.log(a); + }} + > + 001 + +
+
+ ));