@alekstar79/draggable-resizable-container 1.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.
- package/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +265 -0
- package/dist/core/ContainerManager.d.ts +298 -0
- package/dist/core/types.d.ts +130 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.es.js +970 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +9 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/package.json +89 -0
- package/dist/plugins/EdgeDockingPlugin.d.ts +112 -0
- package/dist/plugins/LoggingPlugin.d.ts +53 -0
- package/dist/plugins/SnappingPlugin.d.ts +70 -0
- package/dist/plugins/StatePersistencePlugin.d.ts +159 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/utils/BoundaryTracker.d.ts +155 -0
- package/dist/utils/ContainerInitializer.d.ts +9 -0
- package/dist/utils/ContentCreator.d.ts +22 -0
- package/dist/utils/Notifications.d.ts +29 -0
- package/dist/utils/StatsManager.d.ts +51 -0
- package/dist/utils/TemplateLoader.d.ts +24 -0
- package/dist/utils/helpers.d.ts +31 -0
- package/dist/utils/index.d.ts +13 -0
- package/package.json +89 -0
package/dist/index.es.js
ADDED
|
@@ -0,0 +1,970 @@
|
|
|
1
|
+
import './index.css';var z = Object.defineProperty;
|
|
2
|
+
var S = (o, t, e) => t in o ? z(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
|
+
var a = (o, t, e) => S(o, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import f, { reactive as b, computed as x, effect as p } from "@alekstar79/reactive-event-system";
|
|
5
|
+
import { clamp as m, deepMerge as M } from "@alekstar79/utility";
|
|
6
|
+
class R {
|
|
7
|
+
constructor(t) {
|
|
8
|
+
a(this, "container");
|
|
9
|
+
this.container = t || this.createContainer();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create notifications container
|
|
13
|
+
*/
|
|
14
|
+
createContainer() {
|
|
15
|
+
const t = document.querySelector(".notifications");
|
|
16
|
+
if (t)
|
|
17
|
+
return t;
|
|
18
|
+
const e = document.createElement("div");
|
|
19
|
+
return e.className = "notifications", document.body.appendChild(e), e;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Show notification toast
|
|
23
|
+
*/
|
|
24
|
+
show(t, e = "info") {
|
|
25
|
+
const i = document.createElement("li"), s = this.removeToast.bind(this, i);
|
|
26
|
+
i.innerHTML = this.getToastHTML(t, e), i.className = `toast ${e}`, i.timeoutId = window.setTimeout(s, 4e3);
|
|
27
|
+
const r = i.querySelector(".icon");
|
|
28
|
+
r && r.addEventListener("click", s), this.container.appendChild(i);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate toast HTML based on type
|
|
32
|
+
*/
|
|
33
|
+
getToastHTML(t, e) {
|
|
34
|
+
return `
|
|
35
|
+
<div class="column">
|
|
36
|
+
<i class="fa-solid ${{
|
|
37
|
+
success: "fa-circle-check",
|
|
38
|
+
error: "fa-circle-xmark",
|
|
39
|
+
warning: "fa-triangle-exclamation",
|
|
40
|
+
info: "fa-circle-info"
|
|
41
|
+
}[e]}"></i>
|
|
42
|
+
<span>${t}</span>
|
|
43
|
+
</div>
|
|
44
|
+
<i class="icon fa-solid fa-xmark"></i>
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Remove toast with animation
|
|
49
|
+
*/
|
|
50
|
+
removeToast(t) {
|
|
51
|
+
t.classList.add("hide"), t.timeoutId && clearTimeout(t.timeoutId), setTimeout(() => {
|
|
52
|
+
t.parentNode && t.parentNode.removeChild(t);
|
|
53
|
+
}, 300);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear all notifications
|
|
57
|
+
*/
|
|
58
|
+
clear() {
|
|
59
|
+
for (; this.container.firstChild; )
|
|
60
|
+
this.container.removeChild(this.container.firstChild);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
new R();
|
|
64
|
+
class I {
|
|
65
|
+
/**
|
|
66
|
+
* Create container element with proper initialization
|
|
67
|
+
*/
|
|
68
|
+
static createContainerElement(t, e, i, s, r) {
|
|
69
|
+
const n = document.createElement("div");
|
|
70
|
+
return n.className = "container advanced-container new", n.style.position = "absolute", n.style.width = `${t}px`, n.style.height = `${e}px`, i !== void 0 && (n.style.left = `${i}px`), s !== void 0 && (n.style.top = `${s}px`), r && (n.style.borderColor = r), n;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
class k {
|
|
74
|
+
constructor(t) {
|
|
75
|
+
a(this, "templateLoader");
|
|
76
|
+
this.templateLoader = t;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create content from various sources
|
|
80
|
+
* @param content - String, HTMLElement, or template name
|
|
81
|
+
* @param container - Container element to append content to
|
|
82
|
+
*/
|
|
83
|
+
async createContent(t, e) {
|
|
84
|
+
try {
|
|
85
|
+
const i = e.classList.contains("container-content");
|
|
86
|
+
let s;
|
|
87
|
+
if (i ? s = e : (s = e.querySelector(".container-content"), s || (s = document.createElement("div"), s.className = "container-content", e.appendChild(s))), s.innerHTML = "", typeof t == "string")
|
|
88
|
+
s.innerHTML = t;
|
|
89
|
+
else if (t instanceof HTMLElement)
|
|
90
|
+
s.appendChild(t);
|
|
91
|
+
else if (t.template)
|
|
92
|
+
try {
|
|
93
|
+
s.innerHTML = await this.templateLoader.loadTemplate(t.template);
|
|
94
|
+
} catch (r) {
|
|
95
|
+
console.error(`[ContentCreator] Failed to load template: ${t.template}`, r), s.innerHTML = `<div class="template-error">Failed to load template: ${t.template}</div>`;
|
|
96
|
+
}
|
|
97
|
+
return s;
|
|
98
|
+
} catch (i) {
|
|
99
|
+
throw console.error("[ContentCreator] Error creating content:", i), i;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Set template loader instance
|
|
104
|
+
*/
|
|
105
|
+
setTemplateLoader(t) {
|
|
106
|
+
this.templateLoader = t;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
var T = Object.defineProperty, H = (o, t, e) => t in o ? T(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e, d = (o, t, e) => H(o, typeof t != "symbol" ? t + "" : t, e);
|
|
110
|
+
class C {
|
|
111
|
+
constructor() {
|
|
112
|
+
d(this, "templates", /* @__PURE__ */ new Map()), d(this, "lastUpdated", /* @__PURE__ */ new Map());
|
|
113
|
+
}
|
|
114
|
+
register(t) {
|
|
115
|
+
if (!t.name.trim()) throw new Error("Template name cannot be empty");
|
|
116
|
+
this.templates.set(t.name, t), this.lastUpdated.set(t.name, Date.now());
|
|
117
|
+
}
|
|
118
|
+
async registerBulk(t) {
|
|
119
|
+
for (const [e, i] of Object.entries(t)) this.register({ name: e, source: i });
|
|
120
|
+
}
|
|
121
|
+
get(t) {
|
|
122
|
+
return this.templates.get(t);
|
|
123
|
+
}
|
|
124
|
+
has(t) {
|
|
125
|
+
return this.templates.has(t);
|
|
126
|
+
}
|
|
127
|
+
remove(t) {
|
|
128
|
+
this.templates.delete(t), this.lastUpdated.delete(t);
|
|
129
|
+
}
|
|
130
|
+
list() {
|
|
131
|
+
return Array.from(this.templates.keys());
|
|
132
|
+
}
|
|
133
|
+
clear() {
|
|
134
|
+
this.templates.clear(), this.lastUpdated.clear();
|
|
135
|
+
}
|
|
136
|
+
getMetadata(t) {
|
|
137
|
+
var e;
|
|
138
|
+
return (e = this.templates.get(t)) == null ? void 0 : e.metadata;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
class L {
|
|
142
|
+
constructor(t = 36e5) {
|
|
143
|
+
d(this, "cache", /* @__PURE__ */ new Map()), d(this, "ttl"), this.ttl = t;
|
|
144
|
+
}
|
|
145
|
+
set(t, e) {
|
|
146
|
+
this.cache.set(t, { content: e, timestamp: Date.now() });
|
|
147
|
+
}
|
|
148
|
+
get(t) {
|
|
149
|
+
const e = this.cache.get(t);
|
|
150
|
+
return e ? this.ttl <= 0 || Date.now() - e.timestamp > this.ttl ? (this.cache.delete(t), null) : e.content : null;
|
|
151
|
+
}
|
|
152
|
+
has(t) {
|
|
153
|
+
return this.get(t) !== null;
|
|
154
|
+
}
|
|
155
|
+
clear() {
|
|
156
|
+
this.cache.clear();
|
|
157
|
+
}
|
|
158
|
+
size() {
|
|
159
|
+
return this.cache.size;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
class A {
|
|
163
|
+
constructor(t, e = {}) {
|
|
164
|
+
d(this, "cache"), d(this, "config"), d(this, "metrics"), d(this, "retryQueue", /* @__PURE__ */ new Map()), d(this, "registry"), this.registry = t ?? new C(), this.cache = new L(e == null ? void 0 : e.cacheTTL), this.config = this.normalizeConfig(e), this.metrics = { totalLoads: 0, totalHits: 0, totalMisses: 0, totalErrors: 0, averageLoadTime: 0, cacheHitRate: 0 };
|
|
165
|
+
}
|
|
166
|
+
normalizeConfig(t = {}) {
|
|
167
|
+
var i;
|
|
168
|
+
const e = t || {};
|
|
169
|
+
return { environment: e.environment === "auto" ? typeof process < "u" && ((i = process.env) == null ? void 0 : i.NODE_ENV) === "production" ? "production" : "development" : e.environment ?? "development", cache: e.cache ?? !0, cacheTTL: e.cacheTTL ?? 36e5, enableMetrics: e.enableMetrics ?? !0, onError: e.onError ?? (() => {
|
|
170
|
+
}), onWarn: e.onWarn ?? (() => {
|
|
171
|
+
}), fallbackTemplate: e.fallbackTemplate ?? '<div class="template-error">Template load failed</div>' };
|
|
172
|
+
}
|
|
173
|
+
async loadTemplate(t, e = 2) {
|
|
174
|
+
const i = performance.now(), s = this.retryQueue.get(t) ?? 0;
|
|
175
|
+
if (this.metrics.totalLoads++, this.config.cache) {
|
|
176
|
+
const n = this.cache.get(t);
|
|
177
|
+
if (n) return this.metrics.totalHits++, this.updateCacheHitRate(), n;
|
|
178
|
+
}
|
|
179
|
+
this.metrics.totalMisses++;
|
|
180
|
+
const r = this.registry.get(t);
|
|
181
|
+
if (!r) {
|
|
182
|
+
const n = this.createError(`Template "${t}" not found. Available: ${this.registry.list().join(", ")}`, t, s);
|
|
183
|
+
return this.metrics.totalErrors++, this.config.onError(n), this.config.fallbackTemplate;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
let n = typeof r.source == "function" ? await r.source() : r.source;
|
|
187
|
+
if (typeof n != "string") {
|
|
188
|
+
const h = this.createError("Template source must return a string, got " + typeof n, t, s);
|
|
189
|
+
return this.metrics.totalErrors++, this.config.onError(h), this.config.fallbackTemplate;
|
|
190
|
+
}
|
|
191
|
+
return this.config.cache && this.cache.set(t, n), this.retryQueue.delete(t), this.recordLoadTime(i), n;
|
|
192
|
+
} catch (n) {
|
|
193
|
+
const h = n instanceof Error ? n : new Error(String(n));
|
|
194
|
+
if (s < e) return this.retryQueue.set(t, s + 1), this.config.onWarn(`Retrying template "${t}" (attempt ${s + 1}/${e})`), await new Promise((u) => setTimeout(u, 100 * Math.pow(2, s))), this.loadTemplate(t, e);
|
|
195
|
+
const l = this.createError(`Failed to load template "${t}": ${h.message}`, t, s);
|
|
196
|
+
return this.metrics.totalErrors++, this.config.onError(l), this.retryQueue.delete(t), this.config.fallbackTemplate;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async loadTemplates(t) {
|
|
200
|
+
const e = {};
|
|
201
|
+
return await Promise.all(t.map(async (i) => {
|
|
202
|
+
e[i] = await this.loadTemplate(i);
|
|
203
|
+
})), e;
|
|
204
|
+
}
|
|
205
|
+
getMetrics() {
|
|
206
|
+
return { ...this.metrics };
|
|
207
|
+
}
|
|
208
|
+
clearCache() {
|
|
209
|
+
this.cache.clear();
|
|
210
|
+
}
|
|
211
|
+
resetMetrics() {
|
|
212
|
+
this.metrics = { totalLoads: 0, totalHits: 0, totalMisses: 0, totalErrors: 0, averageLoadTime: 0, cacheHitRate: 0 };
|
|
213
|
+
}
|
|
214
|
+
has(t) {
|
|
215
|
+
return this.registry.has(t);
|
|
216
|
+
}
|
|
217
|
+
list() {
|
|
218
|
+
return this.registry.list();
|
|
219
|
+
}
|
|
220
|
+
info(t) {
|
|
221
|
+
return this.registry.get(t);
|
|
222
|
+
}
|
|
223
|
+
createError(t, e, i) {
|
|
224
|
+
return Object.assign(new Error(t), { name: "TemplateLoadError", templateName: e, timestamp: /* @__PURE__ */ new Date(), retryCount: i });
|
|
225
|
+
}
|
|
226
|
+
recordLoadTime(t) {
|
|
227
|
+
if (this.config.enableMetrics) {
|
|
228
|
+
const e = performance.now() - t, i = this.metrics.averageLoadTime * (this.metrics.totalLoads - 1) + e;
|
|
229
|
+
this.metrics.averageLoadTime = i / this.metrics.totalLoads;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
updateCacheHitRate() {
|
|
233
|
+
this.config.enableMetrics && (this.metrics.cacheHitRate = this.metrics.totalHits / this.metrics.totalLoads);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const c = class c {
|
|
237
|
+
constructor() {
|
|
238
|
+
a(this, "draggable", []);
|
|
239
|
+
}
|
|
240
|
+
zIndex(t) {
|
|
241
|
+
return `${c.highestZIndex + this.draggable.findIndex((e) => e === t)}`;
|
|
242
|
+
}
|
|
243
|
+
push(t) {
|
|
244
|
+
return this.draggable = [.../* @__PURE__ */ new Set([...this.draggable, t])], this;
|
|
245
|
+
}
|
|
246
|
+
remove(t) {
|
|
247
|
+
return this.draggable = this.draggable.filter((e) => e !== t), this;
|
|
248
|
+
}
|
|
249
|
+
sort(t) {
|
|
250
|
+
return this.draggable.sort((e, i) => e === t ? 1 : i === t ? -1 : 0), this;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
a(c, "inatance"), a(c, "highestZIndex", 1e3), a(c, "init", () => c.inatance ?? (c.inatance = new c()));
|
|
254
|
+
let v = c;
|
|
255
|
+
function w() {
|
|
256
|
+
return {
|
|
257
|
+
width: window.innerWidth || document.documentElement.clientWidth,
|
|
258
|
+
height: window.innerHeight || document.documentElement.clientHeight
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function D() {
|
|
262
|
+
return v.init();
|
|
263
|
+
}
|
|
264
|
+
const g = class g {
|
|
265
|
+
/**
|
|
266
|
+
* Create a new container manager instance with reactive state management
|
|
267
|
+
* @param container - HTML element to manage
|
|
268
|
+
* @param config - Configuration options
|
|
269
|
+
*/
|
|
270
|
+
constructor(t, e = {}) {
|
|
271
|
+
// Streams for reactive event handling
|
|
272
|
+
a(this, "dragStream");
|
|
273
|
+
a(this, "resizeStream");
|
|
274
|
+
a(this, "stateChangeStream");
|
|
275
|
+
a(this, "eventEmitter");
|
|
276
|
+
a(this, "pluginEventEmitter");
|
|
277
|
+
a(this, "config");
|
|
278
|
+
a(this, "container");
|
|
279
|
+
a(this, "dragHandle");
|
|
280
|
+
a(this, "resizeHandles", /* @__PURE__ */ new Map());
|
|
281
|
+
a(this, "installedPlugins", /* @__PURE__ */ new Set());
|
|
282
|
+
a(this, "reactiveEffects", []);
|
|
283
|
+
a(this, "isDragging", !1);
|
|
284
|
+
a(this, "isResizing", !1);
|
|
285
|
+
a(this, "resizeDirection", null);
|
|
286
|
+
a(this, "startX", 0);
|
|
287
|
+
a(this, "startY", 0);
|
|
288
|
+
a(this, "startState");
|
|
289
|
+
a(this, "resizeObserver", null);
|
|
290
|
+
a(this, "parentResizeObserver", null);
|
|
291
|
+
a(this, "zIndexState");
|
|
292
|
+
a(this, "reactiveState", b({
|
|
293
|
+
x: 0,
|
|
294
|
+
y: 0,
|
|
295
|
+
width: 0,
|
|
296
|
+
height: 0,
|
|
297
|
+
mode: "smooth",
|
|
298
|
+
draggingDirection: "all"
|
|
299
|
+
}));
|
|
300
|
+
// Computed state with applied constraints
|
|
301
|
+
a(this, "constrainedState", x(() => {
|
|
302
|
+
var s;
|
|
303
|
+
const t = this.reactiveState;
|
|
304
|
+
if (!this.config) return { ...t };
|
|
305
|
+
let e = { ...t };
|
|
306
|
+
const { boundaries: i } = this.config;
|
|
307
|
+
if (e.width = m(
|
|
308
|
+
t.width,
|
|
309
|
+
i.minWidth || g.MINWIDTH,
|
|
310
|
+
i.maxWidth || 1 / 0
|
|
311
|
+
), e.height = m(
|
|
312
|
+
t.height,
|
|
313
|
+
i.minHeight || g.MINHEIGHT,
|
|
314
|
+
i.maxHeight || 1 / 0
|
|
315
|
+
), this.shouldConstrainToViewport()) {
|
|
316
|
+
const r = w();
|
|
317
|
+
e.x = m(t.x, 0, r.width - e.width), e.y = m(t.y, 0, r.height - e.height);
|
|
318
|
+
}
|
|
319
|
+
return (s = this.config) != null && s.constrainToParent && (e = this.constrainToParent(e)), e;
|
|
320
|
+
}));
|
|
321
|
+
// Automatic DOM updates with reactive effect
|
|
322
|
+
a(this, "domUpdateEffect", p(() => {
|
|
323
|
+
var e;
|
|
324
|
+
const t = this.constrainedState.value;
|
|
325
|
+
this.container && (this.container.style.left = `${t.x}px`, this.container.style.top = `${t.y}px`, this.container.style.width = `${t.width}px`, this.container.style.height = `${t.height}px`, (e = this.eventEmitter) == null || e.emit("stateChange", {
|
|
326
|
+
type: "stateChange",
|
|
327
|
+
state: { ...t },
|
|
328
|
+
mode: this.reactiveState.mode,
|
|
329
|
+
element: this.container
|
|
330
|
+
}));
|
|
331
|
+
}));
|
|
332
|
+
this.config = M({
|
|
333
|
+
_uid: "",
|
|
334
|
+
mode: "smooth",
|
|
335
|
+
constrainToViewport: !1,
|
|
336
|
+
draggingDirection: "all",
|
|
337
|
+
constrainToParent: !1,
|
|
338
|
+
boundaries: {
|
|
339
|
+
minWidth: g.MINWIDTH,
|
|
340
|
+
minHeight: g.MINHEIGHT
|
|
341
|
+
},
|
|
342
|
+
autoAdjust: {
|
|
343
|
+
enabled: !1,
|
|
344
|
+
width: !1,
|
|
345
|
+
height: !1
|
|
346
|
+
},
|
|
347
|
+
resize: {
|
|
348
|
+
enabled: !0,
|
|
349
|
+
directions: ["se"]
|
|
350
|
+
}
|
|
351
|
+
}, e), this.container = t, this.zIndexState = D();
|
|
352
|
+
const i = this.getCurrentState();
|
|
353
|
+
this.reactiveState.x = i.x, this.reactiveState.y = i.y, this.reactiveState.width = i.width, this.reactiveState.height = i.height, this.reactiveState.mode = this.config.mode, this.reactiveState.draggingDirection = this.config.draggingDirection, this.eventEmitter = new f({ enableMetrics: !0 }), this.pluginEventEmitter = new f({ enableMetrics: !0 }), this.stateChangeStream = this.eventEmitter.stream("stateChange"), this.dragStream = this.eventEmitter.stream("drag"), this.resizeStream = this.eventEmitter.stream("resize"), this.startState = this.getState(), this.setupEventMiddleware(), this.initializeHandles(), this.bindEvents(), this.setupResizeObservers(), this.setupReactiveMonitoring();
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Set up ResizeObserver to track viewport and parent size changes
|
|
357
|
+
*/
|
|
358
|
+
setupResizeObservers() {
|
|
359
|
+
var t;
|
|
360
|
+
this.shouldConstrainToViewport() && this.setupViewportResizeObserver(), (t = this.config.autoAdjust) != null && t.enabled && this.setupParentResizeObserver();
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Determine if viewport constraints should be applied
|
|
364
|
+
*/
|
|
365
|
+
shouldConstrainToViewport() {
|
|
366
|
+
return !this.config.constrainToParent || this.config.constrainToViewport;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Set up ResizeObserver to track viewport size changes
|
|
370
|
+
*/
|
|
371
|
+
setupViewportResizeObserver() {
|
|
372
|
+
let t = null;
|
|
373
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
374
|
+
t && cancelAnimationFrame(t), t = requestAnimationFrame(() => {
|
|
375
|
+
this.handleViewportResize();
|
|
376
|
+
});
|
|
377
|
+
}), this.resizeObserver.observe(document.body);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Handle viewport resize event with reactive state updates
|
|
381
|
+
*/
|
|
382
|
+
handleViewportResize() {
|
|
383
|
+
if (!this.shouldConstrainToViewport()) return;
|
|
384
|
+
const t = w(), i = { ...this.getState() };
|
|
385
|
+
let s = !1;
|
|
386
|
+
i.x + i.width > t.width && (i.x = Math.max(0, t.width - i.width), s = !0), i.y + i.height > t.height && (i.y = Math.max(0, t.height - i.height), s = !0), i.x < 0 && (i.x = 0, s = !0), i.y < 0 && (i.y = 0, s = !0), s && (this.setState(i), this.eventEmitter.emit("viewportResize", {
|
|
387
|
+
type: "viewportResize",
|
|
388
|
+
state: this.getState(),
|
|
389
|
+
mode: this.reactiveState.mode,
|
|
390
|
+
element: this.container
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Set up ResizeObserver for parent element auto-adjustment
|
|
395
|
+
*/
|
|
396
|
+
setupParentResizeObserver() {
|
|
397
|
+
const t = this.container.parentElement;
|
|
398
|
+
t && (this.parentResizeObserver = new ResizeObserver((e) => {
|
|
399
|
+
for (const i of e)
|
|
400
|
+
this.handleParentResize(i);
|
|
401
|
+
}), this.parentResizeObserver.observe(t));
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Handle parent element resize for auto-adjustment with reactive updates
|
|
405
|
+
*/
|
|
406
|
+
handleParentResize(t) {
|
|
407
|
+
const { autoAdjust: e } = this.config;
|
|
408
|
+
if (!(e != null && e.enabled)) return;
|
|
409
|
+
const i = t.contentRect, r = { ...this.getState() };
|
|
410
|
+
let n = !1;
|
|
411
|
+
if (e.width) {
|
|
412
|
+
const h = this.getMaxWidthConstraint(), l = Math.min(i.width, h);
|
|
413
|
+
Math.abs(r.width - l) > 1 && (r.width = l, n = !0);
|
|
414
|
+
}
|
|
415
|
+
if (e.height) {
|
|
416
|
+
const h = this.getMaxHeightConstraint(), l = Math.min(i.height, h);
|
|
417
|
+
Math.abs(r.height - l) > 1 && (r.height = l, n = !0);
|
|
418
|
+
}
|
|
419
|
+
n && (this.setState(r), this.eventEmitter.emit("autoAdjust", {
|
|
420
|
+
type: "autoAdjust",
|
|
421
|
+
state: this.getState(),
|
|
422
|
+
mode: this.reactiveState.mode,
|
|
423
|
+
element: this.container
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Initialize drag and resize handles based on configuration
|
|
428
|
+
*/
|
|
429
|
+
initializeHandles() {
|
|
430
|
+
var t;
|
|
431
|
+
this.initializeDragHandle(), (t = this.config.resize) != null && t.enabled && this.initializeResizeHandles();
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Initialize drag handle
|
|
435
|
+
*/
|
|
436
|
+
initializeDragHandle() {
|
|
437
|
+
this.dragHandle = this.container.querySelector("[data-drag-handle]"), this.dragHandle ? this.dragHandle.setAttribute("oncontextmenu", "return false") : (this.dragHandle = document.createElement("div"), this.dragHandle.className = "drag-handle", this.dragHandle.setAttribute("data-drag-handle", "true"), this.dragHandle.setAttribute("oncontextmenu", "return false"), this.container.prepend(this.dragHandle));
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Initialize resize handles for all configured directions
|
|
441
|
+
*/
|
|
442
|
+
initializeResizeHandles() {
|
|
443
|
+
var e;
|
|
444
|
+
(((e = this.config.resize) == null ? void 0 : e.directions) || ["se"]).forEach((i) => {
|
|
445
|
+
const s = this.createResizeHandle(i);
|
|
446
|
+
this.resizeHandles.set(i, s), this.container.appendChild(s);
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Create individual resize handle for specific direction
|
|
451
|
+
*/
|
|
452
|
+
createResizeHandle(t) {
|
|
453
|
+
const e = document.createElement("div");
|
|
454
|
+
return e.className = `resize-handle resize-${t}`, e.setAttribute("data-resize-handle", t), e.setAttribute("data-resize-direction", t), e.addEventListener("contextmenu", this.onContextMenu), this.applyResizeHandleStyles(e, t), e;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Apply styles and cursor for resize handle based on direction
|
|
458
|
+
*/
|
|
459
|
+
applyResizeHandleStyles(t, e) {
|
|
460
|
+
const i = {
|
|
461
|
+
n: "ns-resize",
|
|
462
|
+
s: "ns-resize",
|
|
463
|
+
e: "ew-resize",
|
|
464
|
+
w: "ew-resize",
|
|
465
|
+
ne: "nesw-resize",
|
|
466
|
+
nw: "nwse-resize",
|
|
467
|
+
se: "nwse-resize",
|
|
468
|
+
sw: "nesw-resize"
|
|
469
|
+
};
|
|
470
|
+
t.style.position = "absolute", t.style.cursor = i[e], this.positionResizeHandle(t, e);
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Position resize handle based on direction
|
|
474
|
+
*/
|
|
475
|
+
positionResizeHandle(t, e) {
|
|
476
|
+
switch (e) {
|
|
477
|
+
case "n":
|
|
478
|
+
t.style.top = "0", t.style.left = "0", t.style.right = "0", t.style.height = "12px";
|
|
479
|
+
break;
|
|
480
|
+
case "s":
|
|
481
|
+
t.style.bottom = "0", t.style.left = "0", t.style.right = "0", t.style.height = "12px";
|
|
482
|
+
break;
|
|
483
|
+
case "e":
|
|
484
|
+
t.style.right = "0", t.style.top = "0", t.style.bottom = "0", t.style.width = "12px";
|
|
485
|
+
break;
|
|
486
|
+
case "w":
|
|
487
|
+
t.style.left = "0", t.style.top = "0", t.style.bottom = "0", t.style.width = "12px";
|
|
488
|
+
break;
|
|
489
|
+
case "ne":
|
|
490
|
+
t.style.top = "0", t.style.right = "0", t.style.width = "12px", t.style.height = "12px";
|
|
491
|
+
break;
|
|
492
|
+
case "nw":
|
|
493
|
+
t.style.top = "0", t.style.left = "0", t.style.width = "12px", t.style.height = "12px";
|
|
494
|
+
break;
|
|
495
|
+
case "se":
|
|
496
|
+
t.style.bottom = "0", t.style.right = "0", t.style.width = "12px", t.style.height = "12px";
|
|
497
|
+
break;
|
|
498
|
+
case "sw":
|
|
499
|
+
t.style.bottom = "0", t.style.left = "0", t.style.width = "12px", t.style.height = "12px";
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Bind event listeners to handles
|
|
505
|
+
*/
|
|
506
|
+
bindEvents() {
|
|
507
|
+
var t;
|
|
508
|
+
this.onDragStart = this.onDragStart.bind(this), this.onDragMove = this.onDragMove.bind(this), this.onDragEnd = this.onDragEnd.bind(this), this.onResizeStart = this.onResizeStart.bind(this), this.onResizeMove = this.onResizeMove.bind(this), this.onResizeEnd = this.onResizeEnd.bind(this), this.onContextMenu = this.onContextMenu.bind(this), this.hasPluginByName("SnappingPlugin") || (this.dragHandle.addEventListener("mousedown", this.onDragStart), this.dragHandle.addEventListener("touchstart", this.onDragStart)), (t = this.config.resize) != null && t.enabled && this.resizeHandles.forEach((e, i) => {
|
|
509
|
+
e.addEventListener("mousedown", (s) => this.onResizeStart(s, i)), e.addEventListener("touchstart", (s) => this.onResizeStart(s, i));
|
|
510
|
+
}), this.dragHandle.addEventListener("contextmenu", this.onContextMenu);
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Apply movement mode to coordinates
|
|
514
|
+
*/
|
|
515
|
+
applyMovementMode(t, e) {
|
|
516
|
+
const i = { ...this.startState };
|
|
517
|
+
return this.reactiveState.mode === "smooth" && (i.x = this.startState.x + t, i.y = this.startState.y + e), i;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Calculate new state based on resize direction and deltas
|
|
521
|
+
*/
|
|
522
|
+
calculateResizeState(t, e, i) {
|
|
523
|
+
const s = { ...this.startState };
|
|
524
|
+
switch (i) {
|
|
525
|
+
case "e":
|
|
526
|
+
s.width = this.startState.width + t;
|
|
527
|
+
break;
|
|
528
|
+
case "w":
|
|
529
|
+
s.width = this.startState.width - t, s.x = this.startState.x + t;
|
|
530
|
+
break;
|
|
531
|
+
case "n":
|
|
532
|
+
s.height = this.startState.height - e, s.y = this.startState.y + e;
|
|
533
|
+
break;
|
|
534
|
+
case "s":
|
|
535
|
+
s.height = this.startState.height + e;
|
|
536
|
+
break;
|
|
537
|
+
case "ne":
|
|
538
|
+
s.width = this.startState.width + t, s.height = this.startState.height - e, s.y = this.startState.y + e;
|
|
539
|
+
break;
|
|
540
|
+
case "nw":
|
|
541
|
+
s.width = this.startState.width - t, s.height = this.startState.height - e, s.x = this.startState.x + t, s.y = this.startState.y + e;
|
|
542
|
+
break;
|
|
543
|
+
case "se":
|
|
544
|
+
s.width = this.startState.width + t, s.height = this.startState.height + e;
|
|
545
|
+
break;
|
|
546
|
+
case "sw":
|
|
547
|
+
s.width = this.startState.width - t, s.height = this.startState.height + e, s.x = this.startState.x + t;
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
return s;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Constrain container to parent element boundaries (both position and size)
|
|
554
|
+
*/
|
|
555
|
+
constrainToParent(t) {
|
|
556
|
+
const e = this.container.parentElement;
|
|
557
|
+
if (!e) return t;
|
|
558
|
+
const i = e.getBoundingClientRect();
|
|
559
|
+
if (i.width === 0 || i.height === 0)
|
|
560
|
+
return t;
|
|
561
|
+
const s = Math.max(0, i.width - t.width), r = Math.max(0, i.height - t.height), n = i.width - t.x, h = i.height - t.y;
|
|
562
|
+
return {
|
|
563
|
+
x: m(t.x, 0, s),
|
|
564
|
+
y: m(t.y, 0, r),
|
|
565
|
+
width: m(t.width, 0, n),
|
|
566
|
+
height: m(t.height, 0, h)
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Get maximum width constraint considering parent and boundaries
|
|
571
|
+
*/
|
|
572
|
+
getMaxWidthConstraint() {
|
|
573
|
+
const { boundaries: t } = this.config;
|
|
574
|
+
let e = t.maxWidth || 1 / 0;
|
|
575
|
+
if (this.config.constrainToParent && this.container.parentElement) {
|
|
576
|
+
const i = this.container.parentElement.getBoundingClientRect().width;
|
|
577
|
+
e = Math.min(e, i);
|
|
578
|
+
}
|
|
579
|
+
return e;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Get maximum height constraint considering parent and boundaries
|
|
583
|
+
*/
|
|
584
|
+
getMaxHeightConstraint() {
|
|
585
|
+
const { boundaries: t } = this.config;
|
|
586
|
+
let e = t.maxHeight || 1 / 0;
|
|
587
|
+
if (this.config.constrainToParent && this.container.parentElement) {
|
|
588
|
+
const i = this.container.parentElement.getBoundingClientRect().height;
|
|
589
|
+
e = Math.min(e, i);
|
|
590
|
+
}
|
|
591
|
+
return e;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Handle context menu event on drag handle
|
|
595
|
+
*/
|
|
596
|
+
onContextMenu(t) {
|
|
597
|
+
t.preventDefault(), t.stopPropagation();
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Check if snapping plugin is installed
|
|
601
|
+
*/
|
|
602
|
+
hasPluginByName(t) {
|
|
603
|
+
return Array.from(this.installedPlugins).some((e) => e.constructor.name === t);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Get current container state from DOM
|
|
607
|
+
*/
|
|
608
|
+
getCurrentState() {
|
|
609
|
+
const t = this.container.getBoundingClientRect(), e = window.getComputedStyle(this.container), i = parseFloat(e.width) || t.width, s = parseFloat(e.height) || t.height;
|
|
610
|
+
return {
|
|
611
|
+
x: t.left,
|
|
612
|
+
y: t.top,
|
|
613
|
+
width: i,
|
|
614
|
+
height: s
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Setup event middleware for enhanced event processing
|
|
619
|
+
*/
|
|
620
|
+
setupEventMiddleware() {
|
|
621
|
+
this.eventEmitter.use("*", (t, e) => (typeof window < "u" && window.DEBUG_CONTAINER_MANAGER && console.log(`[ContainerManager] ${e}:`, t), t)), this.eventEmitter.use("dragStart", (t, e) => {
|
|
622
|
+
if (this.reactiveState.mode === "pinned")
|
|
623
|
+
throw new Error("Cannot drag in pinned mode");
|
|
624
|
+
return t;
|
|
625
|
+
}), this.eventEmitter.use("drag", (t, e) => t);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Setup reactive monitoring for container metrics
|
|
629
|
+
*/
|
|
630
|
+
setupReactiveMonitoring() {
|
|
631
|
+
const t = p(() => {
|
|
632
|
+
const { state: i } = this.stateChangeStream;
|
|
633
|
+
});
|
|
634
|
+
this.reactiveEffects.push(t);
|
|
635
|
+
const e = p(() => {
|
|
636
|
+
const i = this.eventEmitter.getMetrics();
|
|
637
|
+
i.state.errorCount > 10 && console.warn("[ContainerManager] High error count in event system:", i.state.errorCount);
|
|
638
|
+
});
|
|
639
|
+
this.reactiveEffects.push(e);
|
|
640
|
+
}
|
|
641
|
+
// Public API Implementation
|
|
642
|
+
/**
|
|
643
|
+
* Subscribe to container events
|
|
644
|
+
* @param event - Event name
|
|
645
|
+
* @param callback - Callback function
|
|
646
|
+
*/
|
|
647
|
+
on(t, e) {
|
|
648
|
+
this.eventEmitter.on(t, e);
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Unsubscribe from container events
|
|
652
|
+
* @param event - Event name
|
|
653
|
+
* @param callback - Callback function
|
|
654
|
+
*/
|
|
655
|
+
off(t, e) {
|
|
656
|
+
this.eventEmitter.off(t, e);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Wait for specific container event
|
|
660
|
+
* @example
|
|
661
|
+
* // Wait for drag to complete
|
|
662
|
+
* const dragResult = await manager.waitFor('dragEnd')
|
|
663
|
+
* console.log('Drag completed:', dragResult.state)
|
|
664
|
+
*/
|
|
665
|
+
waitFor(t, e) {
|
|
666
|
+
return this.eventEmitter.waitFor(t, e);
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Get reactive stream for specific event type
|
|
670
|
+
* @example
|
|
671
|
+
* // Get state change stream
|
|
672
|
+
* const stateStream = manager.getStream('stateChange')
|
|
673
|
+
* stateStream.subscribe((data) => {
|
|
674
|
+
* console.log('State changed:', data.state)
|
|
675
|
+
* })
|
|
676
|
+
*/
|
|
677
|
+
getStream(t) {
|
|
678
|
+
return this.eventEmitter.stream(t);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Pipe container events to another emitter
|
|
682
|
+
* @example
|
|
683
|
+
* // Pipe all events to analytics emitter
|
|
684
|
+
* manager.pipe('*', analyticsEmitter)
|
|
685
|
+
*/
|
|
686
|
+
pipe(t, e, i) {
|
|
687
|
+
return this.eventEmitter.pipe(t, e, i);
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Get event system metrics for monitoring
|
|
691
|
+
*/
|
|
692
|
+
getEventMetrics() {
|
|
693
|
+
return this.eventEmitter.getMetrics();
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Plugin-specific event emission
|
|
697
|
+
*/
|
|
698
|
+
emitPluginEvent(t, e) {
|
|
699
|
+
this.pluginEventEmitter.emit(t, e);
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Listen to plugin-specific events
|
|
703
|
+
*/
|
|
704
|
+
onPluginEvent(t, e) {
|
|
705
|
+
this.pluginEventEmitter.on(t, e);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Remove plugin event listener
|
|
709
|
+
*/
|
|
710
|
+
offPluginEvent(t, e) {
|
|
711
|
+
this.pluginEventEmitter.off(t, e);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Add middleware for plugin events
|
|
715
|
+
*/
|
|
716
|
+
usePluginMiddleware(t, e) {
|
|
717
|
+
return this.pluginEventEmitter.use(t, e);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Handle drag start event
|
|
721
|
+
*/
|
|
722
|
+
onDragStart(t) {
|
|
723
|
+
if (this.reactiveState.mode === "pinned") return;
|
|
724
|
+
t.preventDefault(), this.bringToFront(), this.isDragging = !0;
|
|
725
|
+
const e = t instanceof MouseEvent ? t.clientX : t.touches[0].clientX, i = t instanceof MouseEvent ? t.clientY : t.touches[0].clientY;
|
|
726
|
+
this.startX = e, this.startY = i, this.startState = this.getState(), this.eventEmitter.emit("dragStart", {
|
|
727
|
+
type: "drag",
|
|
728
|
+
state: this.getState(),
|
|
729
|
+
mode: this.reactiveState.mode,
|
|
730
|
+
element: this.container
|
|
731
|
+
}), document.addEventListener("mousemove", this.onDragMove), document.addEventListener("mouseup", this.onDragEnd), document.addEventListener("touchmove", this.onDragMove), document.addEventListener("touchend", this.onDragEnd);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Handle drag movement with reactive state updates
|
|
735
|
+
*/
|
|
736
|
+
onDragMove(t) {
|
|
737
|
+
if (!this.isDragging) return;
|
|
738
|
+
const { clientX: e, clientY: i } = this.directionResolver(
|
|
739
|
+
t instanceof MouseEvent ? t.clientX : t.touches[0].clientX,
|
|
740
|
+
t instanceof MouseEvent ? t.clientY : t.touches[0].clientY
|
|
741
|
+
), s = e - this.startX, r = i - this.startY, n = this.applyMovementMode(s, r);
|
|
742
|
+
this.setState(n), this.eventEmitter.emit("drag", {
|
|
743
|
+
type: "drag",
|
|
744
|
+
state: this.getState(),
|
|
745
|
+
mode: this.reactiveState.mode,
|
|
746
|
+
element: this.container
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Handle drag end event
|
|
751
|
+
*/
|
|
752
|
+
onDragEnd() {
|
|
753
|
+
this.isDragging = !1, document.removeEventListener("mousemove", this.onDragMove), document.removeEventListener("mouseup", this.onDragEnd), document.removeEventListener("touchmove", this.onDragMove), document.removeEventListener("touchend", this.onDragEnd), this.eventEmitter.emit("dragEnd", {
|
|
754
|
+
type: "drag",
|
|
755
|
+
state: this.getState(),
|
|
756
|
+
mode: this.reactiveState.mode,
|
|
757
|
+
element: this.container
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Handle resize start event with direction
|
|
762
|
+
*/
|
|
763
|
+
onResizeStart(t, e) {
|
|
764
|
+
t.preventDefault(), t.stopPropagation(), this.bringToFront(), this.isResizing = !0, this.resizeDirection = e;
|
|
765
|
+
const i = t instanceof MouseEvent ? t.clientX : t.touches[0].clientX, s = t instanceof MouseEvent ? t.clientY : t.touches[0].clientY;
|
|
766
|
+
this.startX = i, this.startY = s, this.startState = this.getState(), document.addEventListener("mousemove", this.onResizeMove), document.addEventListener("mouseup", this.onResizeEnd), document.addEventListener("touchmove", this.onResizeMove), document.addEventListener("touchend", this.onResizeEnd), this.eventEmitter.emit("resizeStart", {
|
|
767
|
+
type: "resize",
|
|
768
|
+
state: this.getState(),
|
|
769
|
+
mode: this.reactiveState.mode,
|
|
770
|
+
element: this.container,
|
|
771
|
+
direction: e
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Handle resize movement with multi-direction support and reactive updates
|
|
776
|
+
*/
|
|
777
|
+
onResizeMove(t) {
|
|
778
|
+
if (!this.isResizing || !this.resizeDirection) return;
|
|
779
|
+
const e = t instanceof MouseEvent ? t.clientX : t.touches[0].clientX, i = t instanceof MouseEvent ? t.clientY : t.touches[0].clientY, s = e - this.startX, r = i - this.startY, n = this.calculateResizeState(s, r, this.resizeDirection);
|
|
780
|
+
this.setState(n), this.eventEmitter.emit("resize", {
|
|
781
|
+
type: "resize",
|
|
782
|
+
state: this.getState(),
|
|
783
|
+
mode: this.reactiveState.mode,
|
|
784
|
+
direction: this.resizeDirection,
|
|
785
|
+
element: this.container
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Handle resize end event
|
|
790
|
+
*/
|
|
791
|
+
onResizeEnd() {
|
|
792
|
+
this.isResizing = !1, this.resizeDirection = null, document.removeEventListener("mousemove", this.onResizeMove), document.removeEventListener("mouseup", this.onResizeEnd), document.removeEventListener("touchmove", this.onResizeMove), document.removeEventListener("touchend", this.onResizeEnd), this.eventEmitter.emit("resizeEnd", {
|
|
793
|
+
type: "resize",
|
|
794
|
+
state: this.getState(),
|
|
795
|
+
mode: this.reactiveState.mode,
|
|
796
|
+
element: this.container
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Set movement direction
|
|
801
|
+
*/
|
|
802
|
+
setDirection(t) {
|
|
803
|
+
this.reactiveState.draggingDirection = t, this.emitPluginEvent("directionChanged", { direction: t });
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Get current movement direction
|
|
807
|
+
*/
|
|
808
|
+
getDirection() {
|
|
809
|
+
return this.reactiveState.draggingDirection;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Resolve coordinates based on current direction mode
|
|
813
|
+
*/
|
|
814
|
+
directionResolver(t, e) {
|
|
815
|
+
const i = this.reactiveState.draggingDirection, s = i === "vertical", r = i === "horizontal";
|
|
816
|
+
return {
|
|
817
|
+
clientX: s ? this.startX : t,
|
|
818
|
+
clientY: r ? this.startY : e
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
/**
|
|
822
|
+
* Get current movement mode
|
|
823
|
+
*/
|
|
824
|
+
getMode() {
|
|
825
|
+
return this.reactiveState.mode;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Set movement mode with reactive update
|
|
829
|
+
*/
|
|
830
|
+
setMode(t) {
|
|
831
|
+
this.reactiveState.mode = t, this.eventEmitter.emit("modeChange", {
|
|
832
|
+
type: "modeChange",
|
|
833
|
+
state: this.getState(),
|
|
834
|
+
mode: this.reactiveState.mode,
|
|
835
|
+
element: this.container
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Update container boundaries
|
|
840
|
+
*/
|
|
841
|
+
setBoundaries(t) {
|
|
842
|
+
this.config.boundaries = { ...this.config.boundaries, ...t };
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Get current container state (reactive)
|
|
846
|
+
*/
|
|
847
|
+
getState() {
|
|
848
|
+
return {
|
|
849
|
+
x: this.reactiveState.x,
|
|
850
|
+
y: this.reactiveState.y,
|
|
851
|
+
width: this.reactiveState.width,
|
|
852
|
+
height: this.reactiveState.height
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Update container position and size with reactive state
|
|
857
|
+
*/
|
|
858
|
+
setState(t) {
|
|
859
|
+
t.height !== void 0 && (this.reactiveState.height = t.height), t.width !== void 0 && (this.reactiveState.width = t.width), t.x !== void 0 && (this.reactiveState.x = t.x), t.y !== void 0 && (this.reactiveState.y = t.y), this.applyStateToDOM();
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Apply current state to DOM immediately for synchronization
|
|
863
|
+
*/
|
|
864
|
+
applyStateToDOM() {
|
|
865
|
+
const t = this.getState();
|
|
866
|
+
this.container.style.left = `${t.x}px`, this.container.style.top = `${t.y}px`, this.container.style.width = `${t.width}px`, this.container.style.height = `${t.height}px`;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Bring container to front programmatically
|
|
870
|
+
*/
|
|
871
|
+
bringToFront() {
|
|
872
|
+
const { _uid: t } = this.config;
|
|
873
|
+
this.container.style.zIndex = this.zIndexState.sort(t).zIndex(t);
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Get container DOM element
|
|
877
|
+
*/
|
|
878
|
+
getContainer() {
|
|
879
|
+
return this.container;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Update auto-adjust configuration
|
|
883
|
+
*/
|
|
884
|
+
setAutoAdjust(t) {
|
|
885
|
+
var e;
|
|
886
|
+
this.config.autoAdjust = { ...this.config.autoAdjust, ...t }, this.parentResizeObserver && (this.parentResizeObserver.disconnect(), this.parentResizeObserver = null), (e = this.config.autoAdjust) != null && e.enabled && this.setupParentResizeObserver();
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Update resize configuration
|
|
890
|
+
*/
|
|
891
|
+
setResizeConfig(t) {
|
|
892
|
+
var e;
|
|
893
|
+
this.config.resize = { ...this.config.resize, ...t }, this.resizeHandles.forEach((i) => i.remove()), this.resizeHandles.clear(), (e = this.config.resize) != null && e.enabled && (this.initializeResizeHandles(), this.bindEvents());
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Set constrain to parent configuration
|
|
897
|
+
*/
|
|
898
|
+
setConstrainToParent(t) {
|
|
899
|
+
this.config.constrainToParent = t, this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.shouldConstrainToViewport() && this.setupViewportResizeObserver();
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Set constrain to viewport configuration
|
|
903
|
+
*/
|
|
904
|
+
setConstrainToViewport(t) {
|
|
905
|
+
this.config.constrainToViewport = t, this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.shouldConstrainToViewport() && this.setupViewportResizeObserver();
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Recalculate container state relative to parent element
|
|
909
|
+
*/
|
|
910
|
+
recalculateForParent() {
|
|
911
|
+
if (!this.config.constrainToParent || !this.container.parentElement)
|
|
912
|
+
return;
|
|
913
|
+
const t = this.container.parentElement.getBoundingClientRect(), e = this.getState();
|
|
914
|
+
if (t.width === 0 || t.height === 0)
|
|
915
|
+
return;
|
|
916
|
+
const i = e.width, s = e.height, r = Math.min(i, t.width), n = Math.min(s, t.height), h = e.x, l = e.y, u = Math.min(h, t.width - r), y = Math.min(l, t.height - n);
|
|
917
|
+
this.setState({
|
|
918
|
+
x: u,
|
|
919
|
+
y,
|
|
920
|
+
width: r,
|
|
921
|
+
height: n
|
|
922
|
+
}), this.eventEmitter.emit("parentRecalculated", {
|
|
923
|
+
type: "parentRecalculated",
|
|
924
|
+
state: this.getState(),
|
|
925
|
+
mode: this.reactiveState.mode,
|
|
926
|
+
element: this.container
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Install plugin on this container manager instance
|
|
931
|
+
*/
|
|
932
|
+
use(t, e) {
|
|
933
|
+
if (this.installedPlugins.has(t)) return this;
|
|
934
|
+
try {
|
|
935
|
+
t.install(this, e), this.installedPlugins.add(t);
|
|
936
|
+
} catch (i) {
|
|
937
|
+
console.error("[ContainerManager] Failed to install plugin:", i);
|
|
938
|
+
}
|
|
939
|
+
return this;
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Check if plugin is installed on this instance
|
|
943
|
+
*/
|
|
944
|
+
hasPlugin(t) {
|
|
945
|
+
return this.installedPlugins.has(t);
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Get all installed plugins on this instance
|
|
949
|
+
*/
|
|
950
|
+
getInstalledPlugins() {
|
|
951
|
+
return Array.from(this.installedPlugins);
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Destroy container manager with proper cleanup
|
|
955
|
+
*/
|
|
956
|
+
destroy() {
|
|
957
|
+
this.reactiveEffects.forEach((t) => t()), this.reactiveEffects = [], this.stateChangeStream.destroy(), this.dragStream.destroy(), this.resizeStream.destroy(), this.eventEmitter.destroy(), this.pluginEventEmitter.destroy(), this.domUpdateEffect(), this.dragHandle.removeEventListener("mousedown", this.onDragStart), this.dragHandle.removeEventListener("touchstart", this.onDragStart), this.dragHandle.removeEventListener("contextmenu", this.onContextMenu), this.resizeHandles.forEach((t, e) => {
|
|
958
|
+
t.removeEventListener("mousedown", (i) => this.onResizeStart(i, e)), t.removeEventListener("touchstart", (i) => this.onResizeStart(i, e));
|
|
959
|
+
}), this.resizeObserver && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.parentResizeObserver && (this.parentResizeObserver.disconnect(), this.parentResizeObserver = null), this.installedPlugins.clear(), this.zIndexState.remove(this.config._uid);
|
|
960
|
+
}
|
|
961
|
+
};
|
|
962
|
+
a(g, "MINWIDTH", 200), a(g, "MINHEIGHT", 45);
|
|
963
|
+
let E = g;
|
|
964
|
+
export {
|
|
965
|
+
I as ContainerInitializer,
|
|
966
|
+
E as ContainerManager,
|
|
967
|
+
k as ContentCreator,
|
|
968
|
+
A as TemplateLoader
|
|
969
|
+
};
|
|
970
|
+
//# sourceMappingURL=index.es.js.map
|