Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
alexreardon committed Jun 12, 2018
1 parent d9b9157 commit ffc440a
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 103 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"dependencies": {
"babel-runtime": "^6.26.0",
"css-box-model": "^0.0.13",
"css-box-model": "^0.0.14",
"memoize-one": "^3.1.1",
"prop-types": "^15.6.1",
"raf-schd": "^2.1.2",
Expand Down
32 changes: 32 additions & 0 deletions src/state/box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @flow
import memoizeOne from 'memoize-one';
import type { Spacing, Box } from 'css-box-model';
import type { BoxSpacing, BoxSizing } from '../types';

export const withBoxSpacing = memoizeOne((box: Spacing): BoxSpacing => ({
paddingTop: box.padding.top,
paddingRight: box.padding.right,
paddingBottom: box.padding.bottom,
paddingLeft: box.padding.left,
marginTop: box.margin.top,
marginRight: box.margin.right,
marginBottom: box.margin.bottom,
marginLeft: box.margin.left,
borderTopWidth: box.border.top,
borderRightWidth: box.border.right,
borderBottomWidth: box.border.bottom,
borderLeftWidth: box.border.left,
}));

type WidthAndHeight = {|
width: number,
height: number,
|}

export const getBoxSizingHeightAndWidth = memoizeOne((box: Box, boxSizing: BoxSizing): WidthAndHeight => {
const isBorderBox: boolean = boxSizing === 'border-box';
const width: number = isBorderBox ? box.borderBox.width : box.contentBox.width;
const height: number = isBorderBox ? box.borderBox.height : box.contentBox.height;

return { width, height };
});
20 changes: 19 additions & 1 deletion src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,33 @@ export type HorizontalAxis = {|

export type Axis = VerticalAxis | HorizontalAxis

export type BoxSpacing = {|
marginTop: number,
marginRight: number,
marginBottom: number,
marginLeft: number,
paddingTop: number,
paddingRight: number,
paddingBottom: number,
paddingLeft: number,
borderTopWidth: number,
borderRightWidth: number,
borderBottomWidth: number,
borderLeftWidth: number,
|}

export type BoxSizing = 'border-box' | 'content-box';

export type Placeholder = {|
client: BoxModel,
tagName: string,
display: string,
boxSizing: string,
boxSizing: BoxSizing,
|}

export type DraggableDimension = {|
descriptor: DraggableDescriptor,
boxSizing: BoxSizing,
// the placeholder for the draggable
placeholder: Placeholder,
// relative to the viewport when the drag started
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,32 @@
// @flow
import { Component, type Node } from 'react';
import type { Position } from 'css-box-model';
import PropTypes from 'prop-types';
import memoizeOne from 'memoize-one';
import invariant from 'tiny-invariant';
import { calculateBox, withScroll, type BoxModel, getBox } from 'css-box-model';
import { calculateBox, withScroll, getBox, offset, type BoxModel, type Position } from 'css-box-model';
import { negate, subtract } from '../../state/position';
import { dimensionMarshalKey } from '../context-keys';
import type {
DraggableDescriptor,
DraggableDimension,
Placeholder,
DraggableId,
DroppableId,
BoxSizing,
} from '../../types';
import type { DimensionMarshal } from '../../state/dimension-marshal/dimension-marshal-types';

type Props = {|
draggableId: DraggableId,
droppableId: DroppableId,
index: number,
isDragging: boolean,
offset: Position,
getDraggableRef: () => ?HTMLElement,
getPlaceholderRef: () => ?HTMLElement,
children: Node,
|}

type PositionStyleToggle = {|
capture: () => void,
clear: () => void,
restore: () => void,
|}

const style = document.createElement('style');
style.innerHTML = `
.alex-test {
/* shifted draggables */
transform: none !important;
/* dragging item */
position: inherit !important;
top: inherit !important;
left: inherit !important;
}
`;
const head = document.querySelector('head');
head.appendChild(style);

export default class DraggableDimensionPublisher extends Component<Props> {
/* eslint-disable react/sort-comp */
static contextTypes = {
Expand Down Expand Up @@ -110,49 +93,68 @@ export default class DraggableDimensionPublisher extends Component<Props> {

getDimension = (windowScroll: Position): DraggableDimension => {
const targetRef: ?HTMLElement = this.props.getDraggableRef();
const placeholderRef: ?HTMLElement = this.props.getPlaceholderRef();
// const placeholderRef: ?HTMLElement = this.props.getPlaceholderRef();
const descriptor: ?DraggableDescriptor = this.publishedDescriptor;

invariant(targetRef, 'DraggableDimensionPublisher cannot calculate a dimension when not attached to the DOM');
invariant(descriptor, 'Cannot get dimension for unpublished draggable');

const ref: HTMLElement = placeholderRef || targetRef;
// We need to fast forward any transforms so that the collection will be correct
// given the current offset.
// When there is no transition the value will be empty string ("")
const previousTransition: ?string = targetRef.style.transition;
if (previousTransition) {
targetRef.style.transition = 'none';
}

// Record values from the DOM
const computedStyles: CSSStyleDeclaration = window.getComputedStyle(targetRef);
const borderBox: ClientRect = targetRef.getBoundingClientRect();

if (ref === placeholderRef) {
console.log('using placeholder ref for', descriptor.id);
// Reapply inline style transition if there was one
if (previousTransition) {
targetRef.style.transition = previousTransition;
}
// TODO: rather than toggling these properties (yuck) - force offset with current offset

const previous = {
transition: ref.style.transition,
transform: ref.style.transform,
};
ref.style.transition = 'none';
ref.style.transform = 'none';
const change: Position = (() => {
const { isDragging, offset: shift } = this.props;
const transform: Position = negate(shift);
console.log('transform', transform);
if (!isDragging) {
return transform;
}

// When dragging, position: fixed will avoid any client changes based on scroll.
// We are manually undoing that
return subtract(transform, windowScroll);
})();

const computedStyles: CSSStyleDeclaration = window.getComputedStyle(ref);
const borderBox: ClientRect = ref.getBoundingClientRect();
// Object.assign(ref.style, previous);

Object.assign(ref.style, previous);
const client: BoxModel = offset(calculateBox(borderBox, computedStyles), change);

const client: BoxModel = calculateBox(borderBox, computedStyles);
console.log(descriptor.id, 'client', client, 'box sizing', computedStyles.boxSizing);
const page: BoxModel = withScroll(client, windowScroll);

console.warn(descriptor.id, 'collected pageBorderBoxCenter', page.borderBox.center, 'height', client.borderBox.height);
if (placeholderRef) {
const box = getBox(targetRef);
console.warn(descriptor.id, 'targetRef (not placeholder) pageBorderBoxCenter', box.borderBox.center, 'height', box.borderBox.height);
}
// if (placeholderRef) {
// const box = getBox(targetRef);
// console.warn(descriptor.id, 'targetRef (not placeholder)
// pageBorderBoxCenter', box.borderBox.center, 'height', box.borderBox.height);
// }

const boxSizing: BoxSizing = computedStyles.boxSizing === 'border-box' ? 'border-box' : 'content-box';

const placeholder: Placeholder = {
client,
tagName: ref.tagName.toLowerCase(),
tagName: targetRef.tagName.toLowerCase(),
display: computedStyles.display,
boxSizing: computedStyles.boxSizing,
boxSizing,
};

const dimension: DraggableDimension = {
descriptor,
boxSizing,
placeholder,
client,
page,
Expand Down
10 changes: 5 additions & 5 deletions src/view/draggable/draggable-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import type {
DraggableDimension,
ZIndex,
State,
BoxSpacing,
BoxSizing,
} from '../../types';
import {
lift,
Expand All @@ -16,6 +18,7 @@ import {
moveDown,
moveRight,
moveLeft,

drop,
dropAnimationFinished,
} from '../../state/action-creators';
Expand All @@ -39,7 +42,6 @@ export type DraggingStyle = {|
// used `box-sizing: content-box` or `box-sizing: border-box`
// Because we are setting the width and height directly we want to ensure that
// these are the actual values applied
boxSizing: 'border-box',

// We initially position the element in the same *visual spot* as when it started.
// This means that these values *exclude* the original margins so that element remains
Expand All @@ -52,10 +54,8 @@ export type DraggingStyle = {|
// the element positioned with the top/left position (which is margin aware).
// We also clear the margin right / bottom. This has no positioning impact,
// but it is cleanest to just remove all the margins rather than only the top and left.
marginTop: number,
marginRight: number,
marginBottom: number,
marginLeft: number,
boxSizing: BoxSizing,
...BoxSpacing,

// We need to opt out of the shared global style that is being applied to
// all draggables. The movement of moving draggables is either not animated
Expand Down
17 changes: 8 additions & 9 deletions src/view/draggable/draggable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
ZIndexOptions,
} from './draggable-types';
import getWindowScroll from '../window/get-window-scroll';
import { withBoxSpacing, getBoxSizingHeightAndWidth } from '../../state/box';
import type { Speed, Style as MovementStyle } from '../moveable/moveable-types';

export const zIndexOptions: ZIndexOptions = {
Expand Down Expand Up @@ -210,17 +211,14 @@ export default class Draggable extends Component<Props> {

// const { width, height, top, left } = dimension.client.borderBox;
// For an explanation of properties see `draggable-types`.
const { width, height } = getBoxSizingHeightAndWidth(box, dimension.boxSizing);

const style: DraggingStyle = {
// ## Sizing
// Applying the correct border-box sizing
boxSizing: 'border-box',
width: box.borderBox.width,
height: box.borderBox.height,
// Apply margin so that dimension recapturing will get the same marginBox
marginTop: dimension.client.margin.top,
marginRight: dimension.client.margin.right,
marginBottom: dimension.client.margin.bottom,
marginLeft: dimension.client.margin.left,
boxSizing: dimension.boxSizing,
width,
height,
...withBoxSpacing(box),
// ## Placement
// As we are applying the margins we need to align to the start of the marginBox
top: box.marginBox.top,
Expand Down Expand Up @@ -381,6 +379,7 @@ export default class Draggable extends Component<Props> {
draggableId={draggableId}
droppableId={droppableId}
index={index}
offset={offset}
getDraggableRef={this.getDraggableRef}
getPlaceholderRef={this.getPlaceholderRef}
>
Expand Down
44 changes: 3 additions & 41 deletions src/view/placeholder/placeholder.jsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,13 @@
// @flow
import React, { PureComponent } from 'react';
import type { Spacing } from 'css-box-model';
import { withBoxSpacing, getBoxSizingHeightAndWidth } from '../../state/box';
import type { Placeholder as PlaceholderType } from '../../types';

type Props = {|
placeholder: PlaceholderType,
innerRef: (ref: ?HTMLElement) => void,
|}

type SpacingMap = {|
top: string,
right: string,
bottom: string,
left: string,
|}

const fromSpacing = (map: SpacingMap) => (spacing: Spacing) => ({
[map.top]: spacing.top,
[map.right]: spacing.right,
[map.bottom]: spacing.bottom,
[map.left]: spacing.left,
});

const withMargin = fromSpacing({
top: 'marginTop',
right: 'marginRight',
bottom: 'marginBottom',
left: 'marginLeft',
});

const withPadding = fromSpacing({
top: 'paddingTop',
right: 'paddingRight',
bottom: 'paddingBottom',
left: 'paddingLeft',
});

const withBorder = fromSpacing({
top: 'borderTopWidth',
right: 'borderRightWidth',
bottom: 'borderBottomWidth',
left: 'borderLeftWidth',
});

export default class Placeholder extends PureComponent<Props> {
// eslint-disable-next-line react/sort-comp
ref: ?HTMLElement = null
Expand Down Expand Up @@ -73,17 +38,14 @@ export default class Placeholder extends PureComponent<Props> {
const placeholder: PlaceholderType = this.props.placeholder;
const { client, display, tagName, boxSizing } = placeholder;

const width: number = boxSizing === 'borderBox' ? client.borderBox.width : client.contentBox.width;
const height: number = boxSizing === 'borderBox' ? client.borderBox.height : client.contentBox.height;
const { width, height } = getBoxSizingHeightAndWidth(client, boxSizing);

const style = {
display,
boxSizing,
width,
height,
...withMargin(client.margin),
...withPadding(client.padding),
...withBorder(client.border),
...withBoxSpacing(client),
borderStyle: 'solid',
borderColor: 'transparent',

Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2734,9 +2734,9 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"

css-box-model@^0.0.13:
version "0.0.13"
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-0.0.13.tgz#e9c2a3b25e48ac786f38b7153eeef785c6658000"
css-box-model@^0.0.14:
version "0.0.14"
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-0.0.14.tgz#bb10ba311bd07d72c7ed4ce260d3035ecb5b5c57"

css-color-keywords@^1.0.0:
version "1.0.0"
Expand Down

0 comments on commit ffc440a

Please sign in to comment.