Skip to content

Commit 0e7632c

Browse files
committed
Implemented handle placement property to replace overlayHandle property to allow 3 different placements of the resize handle and re added inner space element
1 parent c53b5f6 commit 0e7632c

File tree

6 files changed

+64
-41
lines changed

6 files changed

+64
-41
lines changed

src/components/Space.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ISpaceProps, CenterType } from "../core-types";
1+
import { ISpaceProps, CenterType, ResizeHandlePlacement, AnchorType } from "../core-types";
22
import { useSpace, ParentContext, LayerContext, DOMRectContext } from "../core-react";
33
import * as React from "react";
44
import { Centered } from "./Centered";
@@ -64,9 +64,25 @@ const SpaceInner: React.FC<ISpaceProps & { wrapperInstance: Space }> = (props) =
6464

6565
const userClasses = className ? className.split(" ").map((c) => c.trim()) : [];
6666

67-
const outerClasses = [...["spaces-space", space.children.find((s) => s.resizing) ? "spaces-resizing" : undefined], ...userClasses].filter(
68-
(c) => c,
69-
);
67+
const outerClasses = [
68+
...["spaces-space", space.children.find((s) => s.resizing) ? "spaces-resizing" : undefined],
69+
...userClasses.map((c) => `${c}-container`),
70+
].filter((c) => c);
71+
72+
const innerClasses = [...["spaces-space-inner"], ...userClasses];
73+
74+
let innerStyle = style;
75+
if (space.handlePlacement === ResizeHandlePlacement.Inside) {
76+
innerStyle = {
77+
...style,
78+
...{
79+
left: space.anchor === AnchorType.Right ? space.handleSize : undefined,
80+
right: space.anchor === AnchorType.Left ? space.handleSize : undefined,
81+
top: space.anchor === AnchorType.Bottom ? space.handleSize : undefined,
82+
bottom: space.anchor === AnchorType.Top ? space.handleSize : undefined,
83+
},
84+
};
85+
}
7086

7187
const centeredContent = applyCentering(children, props.centerContent);
7288

@@ -85,17 +101,16 @@ const SpaceInner: React.FC<ISpaceProps & { wrapperInstance: Space }> = (props) =
85101
id: space.id,
86102
ref: elementRef,
87103
className: outerClasses.join(" "),
88-
style: style,
89104
},
90105
...events,
91106
},
92-
<>
107+
<div className={innerClasses.join(" ")} style={innerStyle}>
93108
<ParentContext.Provider value={space.id}>
94109
<LayerContext.Provider value={undefined}>
95110
<DOMRectContext.Provider value={domRect}>{centeredContent}</DOMRectContext.Provider>
96111
</LayerContext.Provider>
97112
</ParentContext.Provider>
98-
</>,
113+
</div>,
99114
)}
100115
</>
101116
);

src/components/stories/Utils.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const StandardProps = () => (
8888
/>
8989
<Prop
9090
name="centerContent"
91-
type="CenterType.Vertical or CenterType.HorizontalVertical or 'vertical' or 'horizontalVertical'"
91+
type="CenterType.Vertical ('vertical'), CenterType.HorizontalVertical ('horizontalVertical')"
9292
description="Apply centering to children."
9393
/>
9494
<Prop name="className" type="string" description="A class name to apply to the space element." />
@@ -141,10 +141,10 @@ export const ResizableProps = () => (
141141
<PropsHeader>Resizable properties</PropsHeader>
142142
<Prop name="handleSize" type="number" default="5" description="Size of the resize handle in pixels." />
143143
<Prop
144-
name="overlayHandle"
145-
type="boolean"
146-
default="true"
147-
description="Determines method of placement of the resize handle. By default the handle is placed over the space. When set to false, the space resize handle sits next to the space reducing the size of the space."
144+
name="handlePlacement"
145+
type="ResizeHandlePlacement.OverlayInside ('overlay-inside'), ResizeHandlePlacement.Inside ('inside'), ResizeHandlePlacement.OverlayBoundary ('overlay-boundary')"
146+
default="overlay-inside"
147+
description="Determines method of placement of the resize handle. By default the handle is placed overlays content inside the space ('overlay'). Other options are to take up space within the space ('inside') or to be overlayed in the middle of the boundary of the space and neighbouring spaces ('overlay-boundary')"
148148
/>
149149
<Prop name="minimumSize" type="number" description="Constrains resizing of the space to a minimum size." />
150150
<Prop name="maximumSize" type="number" description="Constrains resizing of the space to a maximum size." />

src/core-react.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ export function useSpace(props: ISpaceProps) {
131131
interface IResizeHandleProps {
132132
id?: string;
133133
key: string | number;
134-
style: CSSProperties;
135134
className?: string;
136135
onMouseDown: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
137136
onTouchStart: (e: React.TouchEvent<HTMLElement>) => void;
@@ -140,22 +139,18 @@ interface IResizeHandleProps {
140139
export function useSpaceResizeHandles(store: ISpaceStore, space: ISpaceDefinition, position: IPositionalProps | undefined) {
141140
const mouseHandles: IResizeHandleProps[] = [];
142141
const touchHandles: IResizeHandleProps[] = [];
143-
const handleSize = space.handleSize;
144-
const touchHandleSize = space.touchHandleSize;
145142

146143
if (position && position.rightResizable) {
147144
mouseHandles.push({
148145
id: `${space.id}-m`,
149146
key: "right",
150-
style: { width: handleSize },
151147
className: `spaces-resize-handle resize-right`,
152148
onMouseDown: (event) => store.startMouseResize(ResizeType.Right, space, space.width, event),
153149
onTouchStart: (event) => store.startTouchResize(ResizeType.Right, space, space.width, event),
154150
});
155151
touchHandles.push({
156152
id: `${space.id}-t`,
157153
key: "right",
158-
style: { width: touchHandleSize },
159154
className: `spaces-touch-handle resize-right`,
160155
onMouseDown: (event) => event.preventDefault(),
161156
onTouchStart: (event) => store.startTouchResize(ResizeType.Right, space, space.width, event),
@@ -166,15 +161,13 @@ export function useSpaceResizeHandles(store: ISpaceStore, space: ISpaceDefinitio
166161
mouseHandles.push({
167162
id: `${space.id}-m`,
168163
key: "left",
169-
style: { width: handleSize },
170164
className: `spaces-resize-handle resize-left`,
171165
onMouseDown: (event) => store.startMouseResize(ResizeType.Left, space, space.width, event),
172166
onTouchStart: (event) => store.startTouchResize(ResizeType.Left, space, space.width, event),
173167
});
174168
touchHandles.push({
175169
id: `${space.id}-t`,
176170
key: "left",
177-
style: { width: touchHandleSize },
178171
className: `spaces-touch-handle resize-left`,
179172
onMouseDown: (event) => event.preventDefault(),
180173
onTouchStart: (event) => store.startTouchResize(ResizeType.Left, space, space.width, event),
@@ -185,15 +178,13 @@ export function useSpaceResizeHandles(store: ISpaceStore, space: ISpaceDefinitio
185178
mouseHandles.push({
186179
id: `${space.id}-m`,
187180
key: "top",
188-
style: { height: handleSize },
189181
className: `spaces-resize-handle resize-top`,
190182
onMouseDown: (event) => store.startMouseResize(ResizeType.Top, space, space.height, event),
191183
onTouchStart: (event) => store.startTouchResize(ResizeType.Top, space, space.height, event),
192184
});
193185
touchHandles.push({
194186
id: `${space.id}-t`,
195187
key: "top",
196-
style: { height: touchHandleSize },
197188
className: `spaces-touch-handle resize-top`,
198189
onMouseDown: (event) => event.preventDefault(),
199190
onTouchStart: (event) => store.startTouchResize(ResizeType.Top, space, space.height, event),
@@ -205,14 +196,12 @@ export function useSpaceResizeHandles(store: ISpaceStore, space: ISpaceDefinitio
205196
id: `${space.id}-m`,
206197
key: "bottom",
207198
className: `spaces-resize-handle resize-bottom`,
208-
style: { height: handleSize },
209199
onMouseDown: (event) => store.startMouseResize(ResizeType.Bottom, space, space.height, event),
210200
onTouchStart: (event) => store.startTouchResize(ResizeType.Bottom, space, space.height, event),
211201
});
212202
touchHandles.push({
213203
id: `${space.id}-t`,
214204
key: "bottom",
215-
style: { height: touchHandleSize },
216205
className: `spaces-touch-handle resize-bottom`,
217206
onMouseDown: (event) => event.preventDefault(),
218207
onTouchStart: (event) => store.startTouchResize(ResizeType.Bottom, space, space.height, event),

src/core-types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ export enum ResizeType {
3232
SE = "resize-se",
3333
}
3434

35+
export enum ResizeHandlePlacement {
36+
OverlayInside = "overlay-inside",
37+
Inside = "inside",
38+
OverlayBoundary = "overlay-boundary"
39+
}
40+
3541
export enum CenterType {
3642
None = "none",
3743
Vertical = "vertical",
@@ -66,8 +72,8 @@ export interface ISpaceProps extends ICommonProps {
6672
anchor?: AnchorType | undefined;
6773
order?: number | undefined;
6874
position?: IPositionalProps | undefined;
69-
overlayHandle?: boolean | undefined;
7075
handleSize?: number | undefined;
76+
handlePlacement?: ResizeHandlePlacement;
7177
touchHandleSize?: number | undefined;
7278
minimumSize?: number | undefined;
7379
maximumSize?: number | undefined;
@@ -145,7 +151,7 @@ export interface ISpaceDefinition {
145151
maximumSize?: number;
146152
handleSize: number;
147153
touchHandleSize: number;
148-
overlayHandle: boolean;
154+
handlePlacement: ResizeHandlePlacement;
149155
canResizeTop: boolean;
150156
canResizeLeft: boolean;
151157
canResizeRight: boolean;

src/core-utils.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ISpaceDefinition, SizeUnit, ISize } from "./core-types";
1+
import { ISpaceDefinition, SizeUnit, ISize, ResizeHandlePlacement } from "./core-types";
22

33
export function shortuuid() {
44
let firstPart = (Math.random() * 46656) | 0;
@@ -124,27 +124,40 @@ export function styleDefinition(space: ISpaceDefinition) {
124124
cssElements.push(`#${space.id} { ${cssString.join(" ")} }`);
125125
}
126126

127-
const handleSize = space.handleSize / 2;
128-
const touchHandleSize = space.touchHandleSize / 2;
127+
let handleOffset = 0;
128+
let touchHandleOffset = 0;
129+
130+
switch (space.handlePlacement)
131+
{
132+
case ResizeHandlePlacement.Inside:
133+
case ResizeHandlePlacement.OverlayInside:
134+
handleOffset = space.handleSize;
135+
touchHandleOffset = space.touchHandleSize;
136+
break;
137+
case ResizeHandlePlacement.OverlayBoundary:
138+
handleOffset = space.handleSize / 2;
139+
touchHandleOffset = space.touchHandleSize / 2;
140+
break;
141+
}
129142

130143
if (space.canResizeLeft) {
131-
cssElements.push(`#${space.id}-t { left: calc(${css(space.left, true)} + ${css(space.width, true)} - ${touchHandleSize}px); }`);
132-
cssElements.push(`#${space.id}-m { left: calc(${css(space.left, true)} + ${css(space.width, true)} - ${handleSize}px); }`);
144+
cssElements.push(`#${space.id}-t { left: calc(${css(space.left, true)} + ${css(space.width, true)} - ${touchHandleOffset}px); width: ${space.touchHandleSize}px; }`);
145+
cssElements.push(`#${space.id}-m { left: calc(${css(space.left, true)} + ${css(space.width, true)} - ${handleOffset}px); width: ${space.handleSize}px; }`);
133146
}
134147

135148
if (space.canResizeTop) {
136-
cssElements.push(`#${space.id}-t { top: calc(${css(space.top, true)} + ${css(space.height, true)} - ${touchHandleSize}px); }`);
137-
cssElements.push(`#${space.id}-m { top: calc(${css(space.top, true)} + ${css(space.height, true)} - ${handleSize}px); }`);
149+
cssElements.push(`#${space.id}-t { top: calc(${css(space.top, true)} + ${css(space.height, true)} - ${touchHandleOffset}px); height: ${space.touchHandleSize}px; }`);
150+
cssElements.push(`#${space.id}-m { top: calc(${css(space.top, true)} + ${css(space.height, true)} - ${handleOffset}px); height: ${space.handleSize}px; }`);
138151
}
139152

140153
if (space.canResizeRight) {
141-
cssElements.push(`#${space.id}-t { right: calc(${css(space.right, true)} + ${css(space.width, true)} - ${touchHandleSize}px); }`);
142-
cssElements.push(`#${space.id}-m { right: calc(${css(space.right, true)} + ${css(space.width, true)} - ${handleSize}px); }`);
154+
cssElements.push(`#${space.id}-t { right: calc(${css(space.right, true)} + ${css(space.width, true)} - ${touchHandleOffset}px); width: ${space.touchHandleSize}px; }`);
155+
cssElements.push(`#${space.id}-m { right: calc(${css(space.right, true)} + ${css(space.width, true)} - ${handleOffset}px); width: ${space.handleSize}px; }`);
143156
}
144157

145158
if (space.canResizeBottom) {
146-
cssElements.push(`#${space.id}-t { bottom: calc(${css(space.bottom, true)} + ${css(space.height, true)} - ${touchHandleSize}px); }`);
147-
cssElements.push(`#${space.id}-m { bottom: calc(${css(space.bottom, true)} + ${css(space.height, true)} - ${handleSize}px); }`);
159+
cssElements.push(`#${space.id}-t { bottom: calc(${css(space.bottom, true)} + ${css(space.height, true)} - ${touchHandleOffset}px); height: ${space.touchHandleSize}px; }`);
160+
cssElements.push(`#${space.id}-m { bottom: calc(${css(space.bottom, true)} + ${css(space.height, true)} - ${handleOffset}px); height: ${space.handleSize}px; }`);
148161
}
149162

150163
return cssElements.join(" ");

src/core.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ISpaceDefinition, SizeUnit, AnchorType, Type, Orientation, ISpaceStore, ISpaceProps, CenterType } from "./core-types";
1+
import { ISpaceDefinition, SizeUnit, AnchorType, Type, Orientation, ISpaceStore, ISpaceProps, CenterType, ResizeHandlePlacement } from "./core-types";
22
import { EndEvent, MoveEvent, createResize } from "./core-resizing";
33
import { updateStyleDefinition, removeStyleDefinition, coalesce, adjustmentsEqual } from "./core-utils";
44

@@ -12,7 +12,7 @@ const spaceDefaults: Partial<ISpaceDefinition> = {
1212
dimension: { left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0, x: 0, y: 0, toJSON: () => "" },
1313
handleSize: 5,
1414
touchHandleSize: 30,
15-
overlayHandle: true,
15+
handlePlacement: ResizeHandlePlacement.OverlayInside,
1616
adjustLeft: () => false,
1717
adjustRight: () => false,
1818
adjustTop: () => false,
@@ -191,7 +191,7 @@ export function createStore(): ISpaceStore {
191191
maximumSize,
192192
handleSize,
193193
touchHandleSize,
194-
overlayHandle,
194+
handlePlacement
195195
} = props;
196196
const canResizeLeft = (position && position.rightResizable) || false;
197197
const canResizeRight = (position && position.leftResizable) || false;
@@ -300,8 +300,8 @@ export function createStore(): ISpaceStore {
300300
changed = true;
301301
}
302302

303-
if (space.overlayHandle !== overlayHandle) {
304-
space.overlayHandle = overlayHandle || spaceDefaults.overlayHandle!;
303+
if (space.handlePlacement !== handlePlacement) {
304+
space.handlePlacement = handlePlacement || spaceDefaults.handlePlacement!;
305305
changed = true;
306306
}
307307

0 commit comments

Comments
 (0)