-
Notifications
You must be signed in to change notification settings - Fork 39
Conversation
We should support pointer events as part of this provider and it should not need to deal with touch/mouse events then. |
7db2806
to
ddc825d
Compare
/** | ||
* The movement of pointer during the duration of the drag state | ||
*/ | ||
delta: Position; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should we declare the interface before we use it? (I thought it was an from an import)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was favouring alphabetisation over use before declaration... one form of clarity causes another issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess so.
src/meta/Drag.ts
Outdated
|
||
/** | ||
* Return the delta position between two positions | ||
* @param start The first posistion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
posistion -> position
|
||
private _getData(target: HTMLElement): { state: NodeData, target: HTMLElement } | undefined { | ||
if (this._nodeMap.has(target)) { | ||
return { state: this._nodeMap.get(target)!, target }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be so good if TS could know that we are in a block narrowed by this._nodeMap.has(target)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not surprised there’s an issue. That would be nice.
} | ||
} | ||
|
||
private _onDragStart = (e: PointerEvent) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason why private _onDragStart = (e: PointerEvent) => {
over private _onDragStart(e: PointerEvent) {
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could we have event
over e
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the lambda, is because the handler needs to be bound to the instance. When used as a handler, the this
scope is the window
I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha re scope. Over having a separate variable that binds scope to the method (we have used both patterns)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... I like this better for class methods where it effects the code readability less, IMO. Using the bound variable makes a bit of indirection when reading the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, for private methods.
} | ||
|
||
constructor() { | ||
const win: Window = global.window; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
window
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't want to mask the global. We have tended to now do that, using doc
or win
when using a reference to a potential global.
src/meta/Drag.ts
Outdated
// first time we see a node, we will initialize its state | ||
if (!_nodeMap.has(node)) { | ||
_nodeMap.set(node, { | ||
dragResults: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use emptyResults
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apart from it being frozen... could we just deep assign the emptyResults
when we return them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, empty results is valid here, I will use that
src/meta/Drag.ts
Outdated
|
||
const controller = new DragController(); | ||
|
||
export default class Drag extends Base { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally we do a named export and a default export across widget-core.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no problem
src/meta/Drag.ts
Outdated
const controller = new DragController(); | ||
|
||
export default class Drag extends Base { | ||
private boundInvalidate = this.invalidate.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_boundInvalidate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
src/meta/Drag.ts
Outdated
|
||
/** | ||
* Return the x/y position for an event | ||
* @param e The MouseEvent or TouchEvent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now the PointerEvent
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor stuff
const controller = new DragController(); | ||
|
||
export class Drag extends Base { | ||
private _boundInvalidate: () => void = this.invalidate.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should already be a bound version that comes from WidgetBase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is its own .invalidate
which isn't auto bound I believe... because this doesn't come from WidgetBase
. I will double check though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the properties passed in at creation provides a bound invalidate, that is a private property on base and the public invalidate()
calls that private property that is copied out, therefore when called from event handlers, the Base.invalidate()
loses its context and needs to be statically bound. This is likely undesirable, and we should consider ensuring that Base.invalidate()
will always call the right invalidate, but for now, this needs to stay this way to work. I will open an issue to consider the change to Base
.
|
||
class DragController { | ||
private _nodeMap = new WeakMap<HTMLElement, NodeData>(); | ||
private _dragging: HTMLElement | undefined = undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be private _dragging?: HTMLElement;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be, but considering I was explicitly assigning undefined
, the property will always be on the instance. Felt more accurate to not be optional.
tests/unit/meta/Drag.ts
Outdated
key: 'child1' | ||
}), | ||
v('div', { | ||
innerHTML: 'Hello Wolrd', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that it matters, but a typo :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
tests/unit/meta/Drag.ts
Outdated
document.body.removeChild(div); | ||
}, | ||
|
||
'non draggable node'() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth naming this differently. I was thinking non-draggable meant something marked as non-draggable by CSS or attributes and got confused - but this is testing that a node where drag events haven't been requested doesn't generate drag events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename it to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non listening node?
Type: Feature
The following has been addressed in the PR:
Description:
This is a proof of concept meta provider which provides drag information to a widget instance. The provider provides a
DragResults
every time it is called. Those drag results provide if the node is being currently draggedisDragging
and any change in position from the last time the provider was called.An example of how this would look in a real world implementation would be something like this:
Because the DragController tracks the events from the window level, but is able to attribute it back to a particular node, tracking of the events keeps the drag state accurate. Here is an example of it in action:
Fixes: #571 (in part)