@studiometa/js-toolkit 2.4.6 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,19 +41,27 @@ var import_utils2 = require("../utils.cjs");
41
41
  var import_AbstractManager = __toESM(require("./AbstractManager.cjs"), 1);
42
42
  var import_RefsManager = require("./RefsManager.cjs");
43
43
  var names = /* @__PURE__ */ new Map();
44
+ var normalizeRegex1 = /[A-Z]([A-Z].*)/g;
45
+ var normalizeRegex2 = /[^a-zA-Z\d\s:]/g;
46
+ var normalizeRegex3 = /(^\w|\s+\w)/g;
44
47
  function normalizeName(name) {
45
48
  if (!names.has(name)) {
46
49
  names.set(
47
50
  name,
48
- name.replace(/[A-Z]([A-Z].*)/g, (c) => c.toLowerCase()).replace(/[^a-zA-Z\d\s:]/g, " ").replace(/(^\w|\s+\w)/g, (c) => c.trim().toUpperCase()).trim()
51
+ name.replace(normalizeRegex1, (c) => c.toLowerCase()).replace(normalizeRegex2, " ").replace(normalizeRegex3, (c) => c.trim().toUpperCase()).trim()
49
52
  );
50
53
  }
51
54
  return names.get(name);
52
55
  }
53
56
  var eventNames = /* @__PURE__ */ new Map();
57
+ var normalizeEventRegex1 = /[A-Z]/g;
58
+ var normalizeEventRegex2 = /^-/;
54
59
  function normalizeEventName(name) {
55
60
  if (!eventNames.has(name)) {
56
- eventNames.set(name, name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`).replace(/^-/, ""));
61
+ eventNames.set(
62
+ name,
63
+ name.replace(normalizeEventRegex1, (c) => `-${c.toLowerCase()}`).replace(normalizeEventRegex2, "")
64
+ );
57
65
  }
58
66
  return eventNames.get(name);
59
67
  }
@@ -100,13 +108,29 @@ function manageChild(that, name, instance, mode = "add") {
100
108
  instance[action](event, that.__childrenHandler);
101
109
  });
102
110
  }
111
+ var isDocumentRegex = /^onDocument[A-Z][a-z]+/;
112
+ var isWindowRegex = /^onWindow[A-Z][a-z]+/;
113
+ var methodIsDocument = (method) => isDocumentRegex.test(method);
114
+ var methodIsWindow = (method) => isWindowRegex.test(method);
115
+ var methodIsGlobal = (method) => methodIsWindow(method) || methodIsDocument(method);
116
+ var getGlobalEventTarget = (method) => methodIsDocument(method) ? document : window;
103
117
  function manageRootElement(that, mode = "add") {
104
118
  const modeMethod = `${mode}EventListener`;
105
119
  const methods = getEventMethodsByName(that);
106
120
  const { __base: base, __config: config } = that;
107
- methods.map((method) => getEventNameByMethod(method)).filter((event) => (0, import_utils2.eventIsDefinedInConfig)(event, config) || (0, import_utils2.eventIsNative)(event, base.$el)).forEach((event) => {
108
- const target = (0, import_utils2.getEventTarget)(base, event, config);
109
- target[modeMethod](event, that.__rootElementHandler);
121
+ methods.forEach((method) => {
122
+ let event = getEventNameByMethod(method);
123
+ if ((0, import_utils2.eventIsDefinedInConfig)(event, config) || (0, import_utils2.eventIsNative)(event, base.$el)) {
124
+ const target = (0, import_utils2.getEventTarget)(base, event, config);
125
+ target[modeMethod](event, that.__rootElementHandler);
126
+ } else if (methodIsGlobal(method)) {
127
+ event = getEventNameByMethod(method, methodIsDocument(method) ? "document" : "window");
128
+ const target = getGlobalEventTarget(method);
129
+ target[modeMethod](
130
+ event,
131
+ methodIsDocument(method) ? that.__documentHandler : that.__windowHandler
132
+ );
133
+ }
110
134
  });
111
135
  }
112
136
  var EventsManager = class extends import_AbstractManager.default {
@@ -124,6 +148,20 @@ var EventsManager = class extends import_AbstractManager.default {
124
148
  }
125
149
  }
126
150
  });
151
+ __publicField(this, "__documentHandler", {
152
+ handleEvent: (event) => {
153
+ const normalizedEventName = normalizeName(event.type);
154
+ const method = `onDocument${normalizedEventName}`;
155
+ this.__base[method](event);
156
+ }
157
+ });
158
+ __publicField(this, "__windowHandler", {
159
+ handleEvent: (event) => {
160
+ const normalizedEventName = normalizeName(event.type);
161
+ const method = `onWindow${normalizedEventName}`;
162
+ this.__base[method](event);
163
+ }
164
+ });
127
165
  __publicField(this, "__refsHandler", {
128
166
  handleEvent: (event) => {
129
167
  const ref = event.currentTarget;
@@ -159,7 +197,9 @@ var EventsManager = class extends import_AbstractManager.default {
159
197
  "__methodsCache",
160
198
  "__rootElementHandler",
161
199
  "__refsHandler",
162
- "__childrenHandler"
200
+ "__childrenHandler",
201
+ "__documentHandler",
202
+ "__windowHandler"
163
203
  ]);
164
204
  }
165
205
  bindRef(name, elements) {
@@ -39,6 +39,30 @@ export default class EventsManager extends AbstractManager {
39
39
  * Event listener object for the root element.
40
40
  */
41
41
  __rootElementHandler: EventListenerObject;
42
+ /**
43
+ * Event listener object for the root element.
44
+ *
45
+ * @type {EventListenerObject}
46
+ */
47
+ __documentHandler: {
48
+ /**
49
+ * @param {Event|CustomEvent} event
50
+ * @returns {void}
51
+ */
52
+ handleEvent: (event: any) => void;
53
+ };
54
+ /**
55
+ * Event listener object for the root element.
56
+ *
57
+ * @type {EventListenerObject}
58
+ */
59
+ __windowHandler: {
60
+ /**
61
+ * @param {Event|CustomEvent} event
62
+ * @returns {void}
63
+ */
64
+ handleEvent: (event: any) => void;
65
+ };
42
66
  /**
43
67
  * Event listener object for the refs.
44
68
  */
@@ -10,19 +10,27 @@ import { getEventTarget, eventIsNative, eventIsDefinedInConfig } from "../utils.
10
10
  import AbstractManager from "./AbstractManager.js";
11
11
  import { normalizeRefName } from "./RefsManager.js";
12
12
  const names = /* @__PURE__ */ new Map();
13
+ const normalizeRegex1 = /[A-Z]([A-Z].*)/g;
14
+ const normalizeRegex2 = /[^a-zA-Z\d\s:]/g;
15
+ const normalizeRegex3 = /(^\w|\s+\w)/g;
13
16
  function normalizeName(name) {
14
17
  if (!names.has(name)) {
15
18
  names.set(
16
19
  name,
17
- name.replace(/[A-Z]([A-Z].*)/g, (c) => c.toLowerCase()).replace(/[^a-zA-Z\d\s:]/g, " ").replace(/(^\w|\s+\w)/g, (c) => c.trim().toUpperCase()).trim()
20
+ name.replace(normalizeRegex1, (c) => c.toLowerCase()).replace(normalizeRegex2, " ").replace(normalizeRegex3, (c) => c.trim().toUpperCase()).trim()
18
21
  );
19
22
  }
20
23
  return names.get(name);
21
24
  }
22
25
  const eventNames = /* @__PURE__ */ new Map();
26
+ const normalizeEventRegex1 = /[A-Z]/g;
27
+ const normalizeEventRegex2 = /^-/;
23
28
  function normalizeEventName(name) {
24
29
  if (!eventNames.has(name)) {
25
- eventNames.set(name, name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`).replace(/^-/, ""));
30
+ eventNames.set(
31
+ name,
32
+ name.replace(normalizeEventRegex1, (c) => `-${c.toLowerCase()}`).replace(normalizeEventRegex2, "")
33
+ );
26
34
  }
27
35
  return eventNames.get(name);
28
36
  }
@@ -69,13 +77,29 @@ function manageChild(that, name, instance, mode = "add") {
69
77
  instance[action](event, that.__childrenHandler);
70
78
  });
71
79
  }
80
+ const isDocumentRegex = /^onDocument[A-Z][a-z]+/;
81
+ const isWindowRegex = /^onWindow[A-Z][a-z]+/;
82
+ const methodIsDocument = (method) => isDocumentRegex.test(method);
83
+ const methodIsWindow = (method) => isWindowRegex.test(method);
84
+ const methodIsGlobal = (method) => methodIsWindow(method) || methodIsDocument(method);
85
+ const getGlobalEventTarget = (method) => methodIsDocument(method) ? document : window;
72
86
  function manageRootElement(that, mode = "add") {
73
87
  const modeMethod = `${mode}EventListener`;
74
88
  const methods = getEventMethodsByName(that);
75
89
  const { __base: base, __config: config } = that;
76
- methods.map((method) => getEventNameByMethod(method)).filter((event) => eventIsDefinedInConfig(event, config) || eventIsNative(event, base.$el)).forEach((event) => {
77
- const target = getEventTarget(base, event, config);
78
- target[modeMethod](event, that.__rootElementHandler);
90
+ methods.forEach((method) => {
91
+ let event = getEventNameByMethod(method);
92
+ if (eventIsDefinedInConfig(event, config) || eventIsNative(event, base.$el)) {
93
+ const target = getEventTarget(base, event, config);
94
+ target[modeMethod](event, that.__rootElementHandler);
95
+ } else if (methodIsGlobal(method)) {
96
+ event = getEventNameByMethod(method, methodIsDocument(method) ? "document" : "window");
97
+ const target = getGlobalEventTarget(method);
98
+ target[modeMethod](
99
+ event,
100
+ methodIsDocument(method) ? that.__documentHandler : that.__windowHandler
101
+ );
102
+ }
79
103
  });
80
104
  }
81
105
  class EventsManager extends AbstractManager {
@@ -93,6 +117,20 @@ class EventsManager extends AbstractManager {
93
117
  }
94
118
  }
95
119
  });
120
+ __publicField(this, "__documentHandler", {
121
+ handleEvent: (event) => {
122
+ const normalizedEventName = normalizeName(event.type);
123
+ const method = `onDocument${normalizedEventName}`;
124
+ this.__base[method](event);
125
+ }
126
+ });
127
+ __publicField(this, "__windowHandler", {
128
+ handleEvent: (event) => {
129
+ const normalizedEventName = normalizeName(event.type);
130
+ const method = `onWindow${normalizedEventName}`;
131
+ this.__base[method](event);
132
+ }
133
+ });
96
134
  __publicField(this, "__refsHandler", {
97
135
  handleEvent: (event) => {
98
136
  const ref = event.currentTarget;
@@ -128,7 +166,9 @@ class EventsManager extends AbstractManager {
128
166
  "__methodsCache",
129
167
  "__rootElementHandler",
130
168
  "__refsHandler",
131
- "__childrenHandler"
169
+ "__childrenHandler",
170
+ "__documentHandler",
171
+ "__windowHandler"
132
172
  ]);
133
173
  }
134
174
  bindRef(name, elements) {
@@ -0,0 +1,48 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
21
+ mod
22
+ ));
23
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
24
+
25
+ // packages/js-toolkit/helpers/getClosestParent.ts
26
+ var getClosestParent_exports = {};
27
+ __export(getClosestParent_exports, {
28
+ default: () => getClosestParent
29
+ });
30
+ module.exports = __toCommonJS(getClosestParent_exports);
31
+ var import_getInstanceFromElement = __toESM(require("./getInstanceFromElement.cjs"), 1);
32
+ function walkAncestorsWhile(element, condition, limit = 1e3) {
33
+ let parent = element.parentElement;
34
+ let count = 0;
35
+ while (parent && condition(parent) && count < limit) {
36
+ parent = parent.parentElement;
37
+ count += 1;
38
+ }
39
+ return parent;
40
+ }
41
+ function getClosestParent(childInstance, ParentConstructor) {
42
+ const parentEl = walkAncestorsWhile(
43
+ childInstance.$el,
44
+ (element) => !(0, import_getInstanceFromElement.default)(element, ParentConstructor)
45
+ );
46
+ return parentEl ? (0, import_getInstanceFromElement.default)(parentEl, ParentConstructor) : null;
47
+ }
48
+ if (module.exports.default) module.exports = module.exports.default;
@@ -0,0 +1,5 @@
1
+ import type { Base, BaseConstructor } from '../Base/index.js';
2
+ /**
3
+ * Get the closest parent of a component.
4
+ */
5
+ export default function getClosestParent<T extends BaseConstructor>(childInstance: Base, ParentConstructor: T): InstanceType<T>;
@@ -0,0 +1,20 @@
1
+ import getInstanceFromElement from "./getInstanceFromElement.js";
2
+ function walkAncestorsWhile(element, condition, limit = 1e3) {
3
+ let parent = element.parentElement;
4
+ let count = 0;
5
+ while (parent && condition(parent) && count < limit) {
6
+ parent = parent.parentElement;
7
+ count += 1;
8
+ }
9
+ return parent;
10
+ }
11
+ function getClosestParent(childInstance, ParentConstructor) {
12
+ const parentEl = walkAncestorsWhile(
13
+ childInstance.$el,
14
+ (element) => !getInstanceFromElement(element, ParentConstructor)
15
+ );
16
+ return parentEl ? getInstanceFromElement(parentEl, ParentConstructor) : null;
17
+ }
18
+ export {
19
+ getClosestParent as default
20
+ };
package/helpers/index.cjs CHANGED
@@ -27,14 +27,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
27
27
  var helpers_exports = {};
28
28
  __export(helpers_exports, {
29
29
  createApp: () => import_createApp.default,
30
+ getClosestParent: () => import_getClosestParent.default,
30
31
  getInstanceFromElement: () => import_getInstanceFromElement.default,
31
32
  importOnInteraction: () => import_importOnInteraction.default,
32
33
  importWhenIdle: () => import_importWhenIdle.default,
33
34
  importWhenVisible: () => import_importWhenVisible.default
34
35
  });
35
36
  module.exports = __toCommonJS(helpers_exports);
36
- var import_createApp = __toESM(require("./createApp.cjs"), 1);
37
37
  __reExport(helpers_exports, require("./getDirectChildren.cjs"), module.exports);
38
+ var import_createApp = __toESM(require("./createApp.cjs"), 1);
39
+ var import_getClosestParent = __toESM(require("./getClosestParent.cjs"), 1);
38
40
  var import_getInstanceFromElement = __toESM(require("./getInstanceFromElement.cjs"), 1);
39
41
  var import_importOnInteraction = __toESM(require("./importOnInteraction.cjs"), 1);
40
42
  var import_importWhenIdle = __toESM(require("./importWhenIdle.cjs"), 1);
@@ -1,5 +1,6 @@
1
- export { default as createApp } from './createApp.js';
2
1
  export * from './getDirectChildren.js';
2
+ export { default as createApp } from './createApp.js';
3
+ export { default as getClosestParent } from './getClosestParent.js';
3
4
  export { default as getInstanceFromElement } from './getInstanceFromElement.js';
4
5
  export { default as importOnInteraction } from './importOnInteraction.js';
5
6
  export { default as importWhenIdle } from './importWhenIdle.js';
package/helpers/index.js CHANGED
@@ -1,13 +1,15 @@
1
- import { default as default2 } from "./createApp.js";
2
1
  export * from "./getDirectChildren.js";
3
- import { default as default3 } from "./getInstanceFromElement.js";
4
- import { default as default4 } from "./importOnInteraction.js";
5
- import { default as default5 } from "./importWhenIdle.js";
6
- import { default as default6 } from "./importWhenVisible.js";
2
+ import { default as default2 } from "./createApp.js";
3
+ import { default as default3 } from "./getClosestParent.js";
4
+ import { default as default4 } from "./getInstanceFromElement.js";
5
+ import { default as default5 } from "./importOnInteraction.js";
6
+ import { default as default6 } from "./importWhenIdle.js";
7
+ import { default as default7 } from "./importWhenVisible.js";
7
8
  export {
8
9
  default2 as createApp,
9
- default3 as getInstanceFromElement,
10
- default4 as importOnInteraction,
11
- default5 as importWhenIdle,
12
- default6 as importWhenVisible
10
+ default3 as getClosestParent,
11
+ default4 as getInstanceFromElement,
12
+ default5 as importOnInteraction,
13
+ default6 as importWhenIdle,
14
+ default7 as importWhenVisible
13
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/js-toolkit",
3
- "version": "2.4.6",
3
+ "version": "2.5.0",
4
4
  "description": "A set of useful little bits of JavaScript to boost your project! 🚀",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -24,12 +24,14 @@
24
24
  ".": {
25
25
  "import": "./index.js",
26
26
  "require": "./index.cjs",
27
- "types": "./index.d.ts"
27
+ "types": "./index.d.ts",
28
+ "default": "./index.js"
28
29
  },
29
30
  "./utils": {
30
31
  "import": "./utils/index.js",
31
32
  "require": "./utils/index.cjs",
32
- "types": "./utils/index.d.ts"
33
+ "types": "./utils/index.d.ts",
34
+ "default": "./utils/index.js"
33
35
  }
34
36
  },
35
37
  "keywords": [
package/services/drag.cjs CHANGED
@@ -29,9 +29,9 @@ __export(drag_exports, {
29
29
  });
30
30
  module.exports = __toCommonJS(drag_exports);
31
31
  var import_service = require("./service.cjs");
32
- var import_pointer = __toESM(require("./pointer.cjs"), 1);
33
32
  var import_raf = __toESM(require("./raf.cjs"), 1);
34
33
  var import_inertiaFinalValue = __toESM(require("../utils/math/inertiaFinalValue.cjs"), 1);
34
+ var import_utils = require("../utils/index.cjs");
35
35
  var MODES = {
36
36
  START: "start",
37
37
  DRAG: "drag",
@@ -40,13 +40,26 @@ var MODES = {
40
40
  STOP: "stop"
41
41
  };
42
42
  var count = 0;
43
+ var events = ["pointerdown", "pointerup"];
44
+ var passiveEventOptions = { passive: true };
45
+ function getEventPosition(event) {
46
+ const eventOrTouch = (0, import_utils.isDefined)(event.touches) ? event.touches[0] : event;
47
+ return {
48
+ x: eventOrTouch.clientX,
49
+ y: eventOrTouch.clientY
50
+ };
51
+ }
43
52
  function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}) {
44
53
  count += 1;
45
54
  const id = `drag-${count}`;
55
+ let previousEvent;
46
56
  function shouldPreventClick() {
47
57
  return Math.abs(props.distance.x) > dragTreshold || Math.abs(props.distance.y) > dragTreshold;
48
58
  }
49
59
  function start(x, y) {
60
+ if (props.isGrabbing) {
61
+ return;
62
+ }
50
63
  props.x = x;
51
64
  props.y = y;
52
65
  props.origin.x = x;
@@ -60,8 +73,12 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
60
73
  props.mode = MODES.START;
61
74
  props.isGrabbing = true;
62
75
  trigger(props);
76
+ document.addEventListener("touchmove", handleEvent, passiveEventOptions);
77
+ document.addEventListener("mousemove", handleEvent, passiveEventOptions);
63
78
  }
64
79
  function drop() {
80
+ document.removeEventListener("touchmove", handleEvent);
81
+ document.removeEventListener("mousemove", handleEvent);
65
82
  props.isGrabbing = false;
66
83
  props.mode = MODES.DROP;
67
84
  props.hasInertia = true;
@@ -76,6 +93,7 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
76
93
  }
77
94
  function stop() {
78
95
  (0, import_raf.default)().remove(id);
96
+ props.isGrabbing = false;
79
97
  props.hasInertia = false;
80
98
  props.mode = MODES.STOP;
81
99
  trigger(props);
@@ -97,41 +115,51 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
97
115
  }
98
116
  }
99
117
  }
100
- function pointerHandler(pointerProps) {
118
+ function drag(event) {
101
119
  if (props.isGrabbing) {
102
- props.x = pointerProps.x;
103
- props.y = pointerProps.y;
104
- props.delta.x = pointerProps.delta.x;
105
- props.delta.y = pointerProps.delta.y;
106
- props.final.x = pointerProps.x;
107
- props.final.y = pointerProps.y;
120
+ const position = getEventPosition(event);
121
+ props.x = position.x;
122
+ props.y = position.y;
123
+ if (previousEvent) {
124
+ const previousPosition = getEventPosition(previousEvent);
125
+ props.delta.x = position.x - previousPosition.x;
126
+ props.delta.y = position.y - previousPosition.y;
127
+ }
128
+ props.final.x = position.x;
129
+ props.final.y = position.y;
108
130
  props.distance.x = props.x - props.origin.x;
109
131
  props.distance.y = props.y - props.origin.y;
110
132
  if (props.mode !== MODES.DRAG) {
111
133
  props.mode = MODES.DRAG;
112
134
  }
113
135
  trigger(props);
114
- if (!pointerProps.isDown) {
115
- drop();
116
- }
136
+ previousEvent = event;
117
137
  }
118
138
  }
119
139
  function handleEvent(event) {
120
- if (event.type === "dragstart") {
121
- event.preventDefault();
122
- return;
123
- }
124
- if (event.type === "click") {
125
- if (shouldPreventClick()) {
126
- event.stopImmediatePropagation();
127
- event.stopPropagation();
140
+ switch (event.type) {
141
+ case "dragstart":
128
142
  event.preventDefault();
129
- }
130
- return;
143
+ break;
144
+ case "click":
145
+ if (shouldPreventClick()) {
146
+ event.stopImmediatePropagation();
147
+ event.stopPropagation();
148
+ event.preventDefault();
149
+ }
150
+ break;
151
+ case "pointerup":
152
+ drop();
153
+ break;
154
+ case "touchmove":
155
+ case "mousemove":
156
+ drag(event);
157
+ break;
158
+ default:
159
+ if (event.button === 0) {
160
+ start(event.x, event.y);
161
+ }
131
162
  }
132
- const x = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
133
- const y = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY;
134
- start(x, y);
135
163
  }
136
164
  const { add, remove, has, trigger, props } = (0, import_service.useService)({
137
165
  props: {
@@ -159,21 +187,18 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
159
187
  }
160
188
  },
161
189
  init() {
162
- const options = { passive: true };
163
- props.target.addEventListener("mousedown", handleEvent, options);
164
- props.target.addEventListener("touchstart", handleEvent, options);
165
- props.target.addEventListener("dragstart", handleEvent, { capture: true });
166
- props.target.addEventListener("click", handleEvent, { capture: true });
167
- const pointer = (0, import_pointer.default)();
168
- pointer.add(id, pointerHandler);
190
+ events.forEach((event) => {
191
+ target.addEventListener(event, handleEvent, passiveEventOptions);
192
+ });
193
+ target.addEventListener("dragstart", handleEvent, { capture: true });
194
+ target.addEventListener("click", handleEvent, { capture: true });
169
195
  },
170
196
  kill() {
171
- props.target.removeEventListener("mousedown", handleEvent);
172
- props.target.removeEventListener("touchstart", handleEvent);
173
- props.target.removeEventListener("dragstart", handleEvent);
174
- props.target.removeEventListener("click", handleEvent);
175
- const pointer = (0, import_pointer.default)();
176
- pointer.remove(id);
197
+ events.forEach((event) => {
198
+ target.removeEventListener(event, handleEvent);
199
+ });
200
+ target.removeEventListener("dragstart", handleEvent);
201
+ target.removeEventListener("click", handleEvent);
177
202
  }
178
203
  });
179
204
  return {
package/services/drag.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useService } from "./service.js";
2
- import usePointer from "./pointer.js";
3
2
  import useRaf from "./raf.js";
4
3
  import inertiaFinalValue from "../utils/math/inertiaFinalValue.js";
4
+ import { isDefined } from "../utils/index.js";
5
5
  const MODES = {
6
6
  START: "start",
7
7
  DRAG: "drag",
@@ -10,13 +10,26 @@ const MODES = {
10
10
  STOP: "stop"
11
11
  };
12
12
  let count = 0;
13
+ const events = ["pointerdown", "pointerup"];
14
+ const passiveEventOptions = { passive: true };
15
+ function getEventPosition(event) {
16
+ const eventOrTouch = isDefined(event.touches) ? event.touches[0] : event;
17
+ return {
18
+ x: eventOrTouch.clientX,
19
+ y: eventOrTouch.clientY
20
+ };
21
+ }
13
22
  function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}) {
14
23
  count += 1;
15
24
  const id = `drag-${count}`;
25
+ let previousEvent;
16
26
  function shouldPreventClick() {
17
27
  return Math.abs(props.distance.x) > dragTreshold || Math.abs(props.distance.y) > dragTreshold;
18
28
  }
19
29
  function start(x, y) {
30
+ if (props.isGrabbing) {
31
+ return;
32
+ }
20
33
  props.x = x;
21
34
  props.y = y;
22
35
  props.origin.x = x;
@@ -30,8 +43,12 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
30
43
  props.mode = MODES.START;
31
44
  props.isGrabbing = true;
32
45
  trigger(props);
46
+ document.addEventListener("touchmove", handleEvent, passiveEventOptions);
47
+ document.addEventListener("mousemove", handleEvent, passiveEventOptions);
33
48
  }
34
49
  function drop() {
50
+ document.removeEventListener("touchmove", handleEvent);
51
+ document.removeEventListener("mousemove", handleEvent);
35
52
  props.isGrabbing = false;
36
53
  props.mode = MODES.DROP;
37
54
  props.hasInertia = true;
@@ -46,6 +63,7 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
46
63
  }
47
64
  function stop() {
48
65
  useRaf().remove(id);
66
+ props.isGrabbing = false;
49
67
  props.hasInertia = false;
50
68
  props.mode = MODES.STOP;
51
69
  trigger(props);
@@ -67,41 +85,51 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
67
85
  }
68
86
  }
69
87
  }
70
- function pointerHandler(pointerProps) {
88
+ function drag(event) {
71
89
  if (props.isGrabbing) {
72
- props.x = pointerProps.x;
73
- props.y = pointerProps.y;
74
- props.delta.x = pointerProps.delta.x;
75
- props.delta.y = pointerProps.delta.y;
76
- props.final.x = pointerProps.x;
77
- props.final.y = pointerProps.y;
90
+ const position = getEventPosition(event);
91
+ props.x = position.x;
92
+ props.y = position.y;
93
+ if (previousEvent) {
94
+ const previousPosition = getEventPosition(previousEvent);
95
+ props.delta.x = position.x - previousPosition.x;
96
+ props.delta.y = position.y - previousPosition.y;
97
+ }
98
+ props.final.x = position.x;
99
+ props.final.y = position.y;
78
100
  props.distance.x = props.x - props.origin.x;
79
101
  props.distance.y = props.y - props.origin.y;
80
102
  if (props.mode !== MODES.DRAG) {
81
103
  props.mode = MODES.DRAG;
82
104
  }
83
105
  trigger(props);
84
- if (!pointerProps.isDown) {
85
- drop();
86
- }
106
+ previousEvent = event;
87
107
  }
88
108
  }
89
109
  function handleEvent(event) {
90
- if (event.type === "dragstart") {
91
- event.preventDefault();
92
- return;
93
- }
94
- if (event.type === "click") {
95
- if (shouldPreventClick()) {
96
- event.stopImmediatePropagation();
97
- event.stopPropagation();
110
+ switch (event.type) {
111
+ case "dragstart":
98
112
  event.preventDefault();
99
- }
100
- return;
113
+ break;
114
+ case "click":
115
+ if (shouldPreventClick()) {
116
+ event.stopImmediatePropagation();
117
+ event.stopPropagation();
118
+ event.preventDefault();
119
+ }
120
+ break;
121
+ case "pointerup":
122
+ drop();
123
+ break;
124
+ case "touchmove":
125
+ case "mousemove":
126
+ drag(event);
127
+ break;
128
+ default:
129
+ if (event.button === 0) {
130
+ start(event.x, event.y);
131
+ }
101
132
  }
102
- const x = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
103
- const y = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY;
104
- start(x, y);
105
133
  }
106
134
  const { add, remove, has, trigger, props } = useService({
107
135
  props: {
@@ -129,21 +157,18 @@ function createDragService(target, { dampFactor = 0.85, dragTreshold = 10 } = {}
129
157
  }
130
158
  },
131
159
  init() {
132
- const options = { passive: true };
133
- props.target.addEventListener("mousedown", handleEvent, options);
134
- props.target.addEventListener("touchstart", handleEvent, options);
135
- props.target.addEventListener("dragstart", handleEvent, { capture: true });
136
- props.target.addEventListener("click", handleEvent, { capture: true });
137
- const pointer = usePointer();
138
- pointer.add(id, pointerHandler);
160
+ events.forEach((event) => {
161
+ target.addEventListener(event, handleEvent, passiveEventOptions);
162
+ });
163
+ target.addEventListener("dragstart", handleEvent, { capture: true });
164
+ target.addEventListener("click", handleEvent, { capture: true });
139
165
  },
140
166
  kill() {
141
- props.target.removeEventListener("mousedown", handleEvent);
142
- props.target.removeEventListener("touchstart", handleEvent);
143
- props.target.removeEventListener("dragstart", handleEvent);
144
- props.target.removeEventListener("click", handleEvent);
145
- const pointer = usePointer();
146
- pointer.remove(id);
167
+ events.forEach((event) => {
168
+ target.removeEventListener(event, handleEvent);
169
+ });
170
+ target.removeEventListener("dragstart", handleEvent);
171
+ target.removeEventListener("click", handleEvent);
147
172
  }
148
173
  });
149
174
  return {