cotomy 0.3.1 → 0.3.3
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/README.md +4 -1
- package/dist/browser/cotomy.js +56 -11
- package/dist/browser/cotomy.js.map +1 -1
- package/dist/browser/cotomy.min.js +1 -1
- package/dist/browser/cotomy.min.js.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/view.js +56 -11
- package/dist/esm/view.js.map +1 -1
- package/dist/types/view.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ The View layer provides thin wrappers around DOM elements and window events.
|
|
|
43
43
|
- Static helpers
|
|
44
44
|
- `CotomyElement.encodeHtml(text)`
|
|
45
45
|
- `CotomyElement.first(selector, type?)`
|
|
46
|
+
- `CotomyElement.last(selector, type?)`
|
|
46
47
|
- `CotomyElement.find(selector, type?)`
|
|
47
48
|
- `CotomyElement.contains(selector)` / `CotomyElement.containsById(id)`
|
|
48
49
|
- `CotomyElement.byId(id, type?)`
|
|
@@ -71,7 +72,7 @@ The View layer provides thin wrappers around DOM elements and window events.
|
|
|
71
72
|
- `firstChild(selector = "*", type?)`
|
|
72
73
|
- `lastChild(selector = "*", type?)`
|
|
73
74
|
- `closest(selector, type?)`
|
|
74
|
-
- `find(selector, type?)` / `first(selector = "*", type?)` / `contains(selector)`
|
|
75
|
+
- `find(selector, type?)` / `first(selector = "*", type?)` / `last(selector = "*", type?)` / `contains(selector)`
|
|
75
76
|
- `append(child): this` / `prepend(child): this` / `appendAll(children): this`
|
|
76
77
|
- `insertBefore(sibling): this` / `insertAfter(sibling): this`
|
|
77
78
|
- `appendTo(target): this` / `prependTo(target): this`
|
|
@@ -99,6 +100,8 @@ The View layer provides thin wrappers around DOM elements and window events.
|
|
|
99
100
|
- Focus: `focus`, `blur`, `focusin`, `focusout`
|
|
100
101
|
- Viewport: `inview`, `outview` (uses `IntersectionObserver`)
|
|
101
102
|
- Layout (custom): `resize`, `scroll`, `changelayout` — requires `listenLayoutEvents()` on the element
|
|
103
|
+
- Move lifecycle: `cotomy:transitstart`, `cotomy:transitend` — emitted automatically by `append`, `prepend`, `insertBefore/After`, `appendTo`, and `prependTo`. While moving, the element (and its descendants) receive a temporary `data-cotomy-moving` attribute so removal observers know the node is still in transit.
|
|
104
|
+
- Removal: `removed` — fired when an element actually leaves the DOM (MutationObserver-backed). Because `cotomy:transitstart`/`transitend` manage the `data-cotomy-moving` flag, `removed` only runs for true detachments, making it safe for cleanup.
|
|
102
105
|
- File: `filedrop(handler: (files: File[]) => void)`
|
|
103
106
|
|
|
104
107
|
Example (scoped CSS and events):
|
package/dist/browser/cotomy.js
CHANGED
|
@@ -892,6 +892,10 @@ class CotomyElement {
|
|
|
892
892
|
const ctor = (type ?? CotomyElement);
|
|
893
893
|
return new ctor(element);
|
|
894
894
|
}
|
|
895
|
+
static last(selector, type) {
|
|
896
|
+
const elements = this.find(selector, type);
|
|
897
|
+
return elements.pop();
|
|
898
|
+
}
|
|
895
899
|
static find(selector, type) {
|
|
896
900
|
const elements = document.querySelectorAll(selector);
|
|
897
901
|
const ctor = (type ?? CotomyElement);
|
|
@@ -939,10 +943,24 @@ class CotomyElement {
|
|
|
939
943
|
}
|
|
940
944
|
}
|
|
941
945
|
}
|
|
942
|
-
this.
|
|
943
|
-
this.
|
|
944
|
-
|
|
945
|
-
|
|
946
|
+
if (!this.instanceId) {
|
|
947
|
+
this.attribute("data-cotomy-instance", `__cotomy_instance_${cuid_default()()}`);
|
|
948
|
+
this.removed(() => {
|
|
949
|
+
this._element = CotomyElement.createHTMLElement(`<div data-cotomy-invalidated style="display: none;"></div>`);
|
|
950
|
+
EventRegistry.instance.clear(this);
|
|
951
|
+
});
|
|
952
|
+
this.on("cotomy:transitstart", () => {
|
|
953
|
+
this.attribute("data-cotomy-moving", "");
|
|
954
|
+
this.find("[data-cotomy-instance]").forEach(e => e.attribute("data-cotomy-moving", ""));
|
|
955
|
+
});
|
|
956
|
+
this.on("cotomy:transitend", () => {
|
|
957
|
+
this.attribute("data-cotomy-moving", null);
|
|
958
|
+
this.find("[data-cotomy-instance]").forEach(e => e.attribute("data-cotomy-moving", null));
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
get instanceId() {
|
|
963
|
+
return this.attribute("data-cotomy-instance");
|
|
946
964
|
}
|
|
947
965
|
get scopeId() {
|
|
948
966
|
if (!this._scopeId) {
|
|
@@ -1389,15 +1407,32 @@ class CotomyElement {
|
|
|
1389
1407
|
const elements = this.find(selector, type);
|
|
1390
1408
|
return elements.shift() ?? undefined;
|
|
1391
1409
|
}
|
|
1410
|
+
last(selector = "*", type) {
|
|
1411
|
+
const elements = this.find(selector, type);
|
|
1412
|
+
return elements.pop() ?? undefined;
|
|
1413
|
+
}
|
|
1392
1414
|
contains(selector) {
|
|
1393
1415
|
return this.find(selector).length > 0;
|
|
1394
1416
|
}
|
|
1417
|
+
static runWithMoveEvents(target, operation) {
|
|
1418
|
+
target.trigger("cotomy:transitstart");
|
|
1419
|
+
try {
|
|
1420
|
+
operation();
|
|
1421
|
+
}
|
|
1422
|
+
finally {
|
|
1423
|
+
target.trigger("cotomy:transitend");
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1395
1426
|
prepend(prepend) {
|
|
1396
|
-
|
|
1427
|
+
CotomyElement.runWithMoveEvents(prepend, () => {
|
|
1428
|
+
this.element.prepend(prepend.element);
|
|
1429
|
+
});
|
|
1397
1430
|
return this;
|
|
1398
1431
|
}
|
|
1399
1432
|
append(target) {
|
|
1400
|
-
|
|
1433
|
+
CotomyElement.runWithMoveEvents(target, () => {
|
|
1434
|
+
this.element.append(target.element);
|
|
1435
|
+
});
|
|
1401
1436
|
return this;
|
|
1402
1437
|
}
|
|
1403
1438
|
appendAll(targets) {
|
|
@@ -1405,19 +1440,27 @@ class CotomyElement {
|
|
|
1405
1440
|
return this;
|
|
1406
1441
|
}
|
|
1407
1442
|
insertBefore(append) {
|
|
1408
|
-
|
|
1443
|
+
CotomyElement.runWithMoveEvents(append, () => {
|
|
1444
|
+
this.element.before(append.element);
|
|
1445
|
+
});
|
|
1409
1446
|
return this;
|
|
1410
1447
|
}
|
|
1411
1448
|
insertAfter(append) {
|
|
1412
|
-
|
|
1449
|
+
CotomyElement.runWithMoveEvents(append, () => {
|
|
1450
|
+
this.element.after(append.element);
|
|
1451
|
+
});
|
|
1413
1452
|
return this;
|
|
1414
1453
|
}
|
|
1415
1454
|
appendTo(target) {
|
|
1416
|
-
|
|
1455
|
+
CotomyElement.runWithMoveEvents(this, () => {
|
|
1456
|
+
target.element.append(this.element);
|
|
1457
|
+
});
|
|
1417
1458
|
return this;
|
|
1418
1459
|
}
|
|
1419
1460
|
prependTo(target) {
|
|
1420
|
-
|
|
1461
|
+
CotomyElement.runWithMoveEvents(this, () => {
|
|
1462
|
+
target.element.prepend(this.element);
|
|
1463
|
+
});
|
|
1421
1464
|
return this;
|
|
1422
1465
|
}
|
|
1423
1466
|
trigger(event, e) {
|
|
@@ -1815,7 +1858,9 @@ class CotomyWindow {
|
|
|
1815
1858
|
mutation.removedNodes.forEach(node => {
|
|
1816
1859
|
if (typeof HTMLElement !== "undefined" && node instanceof HTMLElement) {
|
|
1817
1860
|
const element = new CotomyElement(node);
|
|
1818
|
-
element.
|
|
1861
|
+
if (!element.hasAttribute("data-cotomy-moving") && !element.attached) {
|
|
1862
|
+
element.trigger("removed");
|
|
1863
|
+
}
|
|
1819
1864
|
}
|
|
1820
1865
|
});
|
|
1821
1866
|
});
|