@cocreate/position 1.14.0 → 2.0.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.
@@ -0,0 +1,64 @@
1
+ import observer from "@cocreate/observer";
2
+ import Position from "./draggable/engine.js";
3
+
4
+ const selector = "[draggable]";
5
+
6
+ export function initElement(element, options = {}) {
7
+ if (!element?.matches) return;
8
+ const draggable = options.draggable ?? element.matches(selector);
9
+ const previous = element.position;
10
+ const dragScope = options.dragScope || null;
11
+
12
+ if (!previous?._positionController) {
13
+ const position = new Position(element, element.parentElement, {
14
+ draggable,
15
+ dragScope,
16
+ delegated: options.delegated
17
+ });
18
+ if (previous?.place) position.place = previous.place;
19
+ if (previous?.unplace) position.unplace = previous.unplace;
20
+ position._positionController = true;
21
+ element.position = position;
22
+ } else {
23
+ previous.options.draggable = draggable;
24
+ previous.options.dragScope = dragScope;
25
+ if (draggable && !options.delegated && previous.options.delegated) {
26
+ previous.options.delegated = false;
27
+ previous._initEvent();
28
+ }
29
+ }
30
+ return element.position;
31
+ }
32
+
33
+ export function initElements(elements) {
34
+ for (const element of elements) initElement(element);
35
+ }
36
+
37
+ function refresh(node) {
38
+ if (node.nodeType !== 1) return;
39
+ if (node.matches(selector)) initElement(node);
40
+ initElements(node.querySelectorAll(selector));
41
+ }
42
+
43
+ export function init() {
44
+ initElements(document.querySelectorAll(selector));
45
+ }
46
+
47
+ observer.init({
48
+ name: "positionDraggableAddedNodes",
49
+ types: ["addedNodes"],
50
+ selector,
51
+ callback: mutation => refresh(mutation.target)
52
+ });
53
+
54
+ observer.init({
55
+ name: "positionDraggableAttributes",
56
+ types: ["attributes"],
57
+ attributeFilter: ["draggable"],
58
+ selector,
59
+ callback: mutation => initElement(mutation.target)
60
+ });
61
+
62
+ init();
63
+
64
+ export default { init, initElement, initElements };
@@ -0,0 +1,15 @@
1
+ import { getValueFromObject } from "@cocreate/utils";
2
+
3
+ export function resolveEventOperator(query, event) {
4
+ if (typeof query !== "string" || !query.startsWith("event."))
5
+ return { handled: false, value: undefined, selector: null };
6
+
7
+ const [, path, remaining = ""] = query.match(/^event\.([^\s]+)(?:\s+([\s\S]*))?$/) || [];
8
+ if (!path) return { handled: true, value: undefined, selector: null };
9
+
10
+ return {
11
+ handled: true,
12
+ value: getValueFromObject(event, path),
13
+ selector: remaining.trim() || "$this"
14
+ };
15
+ }
@@ -0,0 +1,34 @@
1
+ export function normalizeEvent(event) {
2
+ const detail = event?.detail && typeof event.detail === "object" ? event.detail : {};
3
+ const originalEvent = detail.originalEvent || event;
4
+ const target = detail.target ?? originalEvent?.target ?? event?.target ?? null;
5
+ const cursor = detail.cursor || {};
6
+ return {
7
+ type: originalEvent?.type || event?.type || "",
8
+ target,
9
+ relatedTarget: detail.relatedTarget ?? originalEvent?.relatedTarget ?? event?.relatedTarget ?? null,
10
+ document: detail.document ?? originalEvent?.view?.document ?? target?.ownerDocument ?? null,
11
+ clientX: cursor.x ?? originalEvent?.clientX ?? event?.clientX,
12
+ clientY: cursor.y ?? originalEvent?.clientY ?? event?.clientY,
13
+ which: originalEvent?.which ?? event?.which,
14
+ button: originalEvent?.button ?? event?.button,
15
+ touches: originalEvent?.touches ?? event?.touches,
16
+ changedTouches: originalEvent?.changedTouches ?? event?.changedTouches,
17
+ originalEvent,
18
+ detail: event?.detail,
19
+ preventDefault() {
20
+ originalEvent?.preventDefault?.();
21
+ if (event !== originalEvent) event?.preventDefault?.();
22
+ }
23
+ };
24
+ }
25
+
26
+ export function dispatch(element, name, detail = {}) {
27
+ const EventConstructor = element?.ownerDocument?.defaultView?.CustomEvent;
28
+ if (!EventConstructor) return;
29
+ const event = new EventConstructor(name, {
30
+ detail: { element, instance: element.position, ...detail }
31
+ });
32
+ element.dispatchEvent(event);
33
+ return event;
34
+ }
package/src/index.css CHANGED
@@ -20,3 +20,22 @@
20
20
  [drag-area] {
21
21
  cursor: move;
22
22
  }
23
+
24
+ .position-moving:not(.position-cloning) {
25
+ position: fixed !important;
26
+ width: var(--position-moving-width) !important;
27
+ height: var(--position-moving-height) !important;
28
+ min-width: var(--position-moving-width) !important;
29
+ min-height: var(--position-moving-height) !important;
30
+ max-width: var(--position-moving-width) !important;
31
+ max-height: var(--position-moving-height) !important;
32
+ box-sizing: border-box !important;
33
+ }
34
+
35
+ .position-cloning {
36
+ opacity: 0.6;
37
+ }
38
+
39
+ .position-moving-preview {
40
+ pointer-events: none;
41
+ }
package/src/index.js CHANGED
@@ -1,38 +1,232 @@
1
- import observer from "@cocreate/observer";
2
- import position from "./position";
3
- import "./index.css";
4
-
5
- function init() {
6
- let elements = document.querySelectorAll("[moveable], [positionable]");
7
- initElements(elements);
8
- }
9
-
10
- function initElements(elements) {
11
- for (let element of elements) initElement(element);
12
- }
13
-
14
- function initElement(element) {
15
- element.position = new position(element, element.parentElement);
16
- }
17
-
18
- observer.init({
19
- name: "positionAddedNodes",
20
- types: ["addedNodes"],
21
- selector: "[moveable], [positionable]",
22
- callback: (mutation) => {
23
- initElement(mutation.target);
24
- }
25
- });
26
-
27
- observer.init({
28
- name: "positionAttributes",
29
- types: ["attributes"],
30
- attributeFilter: ["moveable", "positionable"],
31
- callback: (mutation) => {
32
- initElement(mutation.target);
33
- }
34
- });
35
-
36
- init();
37
-
38
- export default position;
1
+ import observer from "@cocreate/observer";
2
+ import "./index.css";
3
+
4
+ const draggableSelector = "[draggable], [draggable-query], [clonable-query]";
5
+ const snappableSelector = "[droppable-query], [snappable-query], [position-reference]";
6
+ const placementSelector = "[position-query], [position-element], [position-events], [position-box]";
7
+
8
+ let draggablePromise;
9
+ let snappablePromise;
10
+ let placementPromise;
11
+
12
+ function load(getPromise, setPromise, importer) {
13
+ let promise = getPromise();
14
+ if (!promise) {
15
+ promise = importer()
16
+ .then(module => {
17
+ module.init?.();
18
+ return module.default || module;
19
+ })
20
+ .catch(error => {
21
+ setPromise(undefined);
22
+ throw error;
23
+ });
24
+ }
25
+ setPromise(promise);
26
+ return promise;
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @public
32
+ * @environment client
33
+ */
34
+ function loadDraggable() {
35
+ return load(() => draggablePromise, value => { draggablePromise = value; },
36
+ () => import(/* webpackChunkName: "position-draggable" */ "./draggable.js"));
37
+ }
38
+
39
+ /**
40
+ *
41
+ * @public
42
+ * @environment client
43
+ */
44
+ function loadSnappable() {
45
+ return load(() => snappablePromise, value => { snappablePromise = value; },
46
+ () => import(/* webpackChunkName: "position-snappable" */ "./snappable.js"));
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @public
52
+ * @environment client
53
+ */
54
+ function loadPlacement() {
55
+ return load(() => placementPromise, value => { placementPromise = value; },
56
+ () => import(/* webpackChunkName: "position-placement" */ "./position.js"));
57
+ }
58
+
59
+ function reportError(element, error, feature) {
60
+ const EventConstructor = element?.ownerDocument?.defaultView?.CustomEvent || CustomEvent;
61
+ element?.dispatchEvent(new EventConstructor("position-error", {
62
+ bubbles: true,
63
+ detail: { error, feature }
64
+ }));
65
+ }
66
+
67
+ function loadForMutation({ target, attributeName }) {
68
+ if (target?.matches?.(draggableSelector) || attributeName === "draggable")
69
+ loadDraggable().catch(error => reportError(target, error, "draggable"));
70
+ if (target?.matches?.(snappableSelector) || ["draggable-query", "clonable-query", "droppable-query", "snappable-query", "position-reference"].includes(attributeName))
71
+ loadSnappable().catch(error => reportError(target, error, "snappable"));
72
+ if (target?.matches?.(placementSelector) || ["position-query", "position-element", "position-events", "position-box"].includes(attributeName))
73
+ loadPlacement().catch(error => reportError(target, error, "placement"));
74
+ }
75
+
76
+ observer.init([
77
+ {
78
+ name: "CoCreatePositionLoaderAddedNodes",
79
+ types: ["addedNodes"],
80
+ selector: [draggableSelector, snappableSelector, placementSelector].join(", "),
81
+ callback: loadForMutation
82
+ },
83
+ {
84
+ name: "CoCreatePositionLoaderAttributes",
85
+ types: ["attributes"],
86
+ attributeFilter: ["draggable", "draggable-query", "clonable-query", "droppable-query", "snappable-query", "position-reference", "position-query", "position-element", "position-events", "position-box"],
87
+ selector: [draggableSelector, snappableSelector, placementSelector].join(", "),
88
+ callback: loadForMutation
89
+ }
90
+ ]);
91
+
92
+ function start() {
93
+ if (document.querySelector(draggableSelector)) loadDraggable().catch(() => {});
94
+ if (document.querySelector(snappableSelector)) loadSnappable().catch(() => {});
95
+ if (document.querySelector(placementSelector)) loadPlacement().catch(() => {});
96
+ }
97
+
98
+ start();
99
+
100
+ /** Load and initialize the requested position feature modules. * @public
101
+ * @environment client
102
+ */
103
+ export function init() {
104
+ start();
105
+ return Promise.all([draggablePromise, snappablePromise, placementPromise].filter(Boolean));
106
+ }
107
+
108
+ /**
109
+ *
110
+ * @public
111
+ * @environment client
112
+ */
113
+ export function initElement(element, options) {
114
+ return loadDraggable().then(module => module.initElement(element, options));
115
+ }
116
+
117
+ /**
118
+ *
119
+ * @public
120
+ * @environment client
121
+ */
122
+ export function initElements(elements) {
123
+ return loadDraggable().then(module => module.initElements(elements));
124
+ }
125
+
126
+ export { loadDraggable, loadSnappable, loadPlacement };
127
+
128
+ export default { init, initElement, initElements, loadDraggable, loadSnappable, loadPlacement };
129
+
130
+ /**
131
+ *
132
+ * @name clonable-query
133
+ * @kind member
134
+ * @attribute
135
+ * @environment client
136
+ */
137
+
138
+ /**
139
+ *
140
+ * @name draggable
141
+ * @kind member
142
+ * @attribute
143
+ * @environment client
144
+ */
145
+
146
+ /**
147
+ *
148
+ * @name draggable-query
149
+ * @kind member
150
+ * @attribute
151
+ * @environment client
152
+ */
153
+
154
+ /**
155
+ *
156
+ * @name droppable-query
157
+ * @kind member
158
+ * @attribute
159
+ * @environment client
160
+ */
161
+
162
+ /**
163
+ *
164
+ * @name position-box
165
+ * @kind member
166
+ * @attribute
167
+ * @environment client
168
+ */
169
+
170
+ /**
171
+ *
172
+ * @name position-element
173
+ * @kind member
174
+ * @attribute
175
+ * @environment client
176
+ */
177
+
178
+ /**
179
+ *
180
+ * @name position-events
181
+ * @kind member
182
+ * @attribute
183
+ * @environment client
184
+ */
185
+
186
+ /**
187
+ *
188
+ * @name position-query
189
+ * @kind member
190
+ * @attribute
191
+ * @environment client
192
+ */
193
+
194
+ /**
195
+ *
196
+ * @name position-reference
197
+ * @kind member
198
+ * @attribute
199
+ * @environment client
200
+ */
201
+
202
+ /**
203
+ *
204
+ * @name snappable-query
205
+ * @kind member
206
+ * @attribute
207
+ * @environment client
208
+ */
209
+
210
+ /**
211
+ * Declarative DOM positioning, dragging, snapping, and drag-and-drop for web interfaces.
212
+ *
213
+ * @module position
214
+ * @environment client
215
+ */
216
+
217
+ /**
218
+ * Declarative selectors recognized by this module.
219
+ *
220
+ * @name declarative-selectors
221
+ * @kind member
222
+ * @selectors
223
+ * @environment client
224
+ * @example
225
+ * ```json
226
+ * [
227
+ * "[draggable], [draggable-query], [clonable-query]",
228
+ * "[droppable-query], [snappable-query], [position-reference]",
229
+ * "[position-query], [position-element], [position-events], [position-box]"
230
+ * ]
231
+ * ```
232
+ */