@react-shimeji/core 0.2.1 → 0.2.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/dist/index.cjs +34 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -6
- package/dist/index.d.ts +4 -6
- package/dist/index.js +34 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -219,7 +219,7 @@ interface ShimejiEngineOptions {
|
|
|
219
219
|
gravity?: number;
|
|
220
220
|
/** Maximum elapsed time applied to one animation update. Defaults to 100 ms. */
|
|
221
221
|
maxDeltaTime?: number;
|
|
222
|
-
/**
|
|
222
|
+
/** @deprecated There is no shared work area; retained for source compatibility. */
|
|
223
223
|
workAreaClassName?: string;
|
|
224
224
|
/** CSS class added to each generated mascot element. */
|
|
225
225
|
mascotClassName?: string;
|
|
@@ -326,8 +326,6 @@ declare class ShimejiEngine {
|
|
|
326
326
|
private readonly disposers;
|
|
327
327
|
private readonly intervals;
|
|
328
328
|
private readonly options;
|
|
329
|
-
private readonly originalContainerPosition;
|
|
330
|
-
private readonly adjustedContainerPosition;
|
|
331
329
|
private pointer;
|
|
332
330
|
private animationFrame;
|
|
333
331
|
private lastFrameTime;
|
|
@@ -464,7 +462,7 @@ interface PlatformRectangle extends Rectangle {
|
|
|
464
462
|
}
|
|
465
463
|
/** Resolves a platform option into DOM elements, excluding engine-owned nodes. */
|
|
466
464
|
declare function resolvePlatformElements(source: string | readonly HTMLElement[], document: Document, excludedRoot?: HTMLElement): HTMLElement[];
|
|
467
|
-
/** Reads platform bounds once and converts viewport coordinates to
|
|
465
|
+
/** Reads platform bounds once and converts viewport coordinates to the supplied origin. */
|
|
468
466
|
declare function readPlatformRectangles(elements: readonly HTMLElement[], workAreaRectangle: Pick<DOMRect, "left" | "top">): PlatformRectangle[];
|
|
469
467
|
|
|
470
468
|
/** A resolved image and optional atlas crop for one sprite frame. */
|
|
@@ -496,9 +494,9 @@ declare function isIndividualSprite(sprite: SpriteRectangle | IndividualSprite |
|
|
|
496
494
|
|
|
497
495
|
/** DOM nodes and resources owned by one mascot. */
|
|
498
496
|
interface MascotDomHandle {
|
|
499
|
-
/**
|
|
497
|
+
/** Fixed, pointer-transparent mascot wrapper. */
|
|
500
498
|
element: HTMLDivElement;
|
|
501
|
-
/**
|
|
499
|
+
/** Pointer-interactive child element on which sprite images are painted. */
|
|
502
500
|
spriteElement: HTMLDivElement;
|
|
503
501
|
/** Per-mascot spritesheet URL lease. */
|
|
504
502
|
spriteLease: SpriteLease;
|
package/dist/index.d.ts
CHANGED
|
@@ -219,7 +219,7 @@ interface ShimejiEngineOptions {
|
|
|
219
219
|
gravity?: number;
|
|
220
220
|
/** Maximum elapsed time applied to one animation update. Defaults to 100 ms. */
|
|
221
221
|
maxDeltaTime?: number;
|
|
222
|
-
/**
|
|
222
|
+
/** @deprecated There is no shared work area; retained for source compatibility. */
|
|
223
223
|
workAreaClassName?: string;
|
|
224
224
|
/** CSS class added to each generated mascot element. */
|
|
225
225
|
mascotClassName?: string;
|
|
@@ -326,8 +326,6 @@ declare class ShimejiEngine {
|
|
|
326
326
|
private readonly disposers;
|
|
327
327
|
private readonly intervals;
|
|
328
328
|
private readonly options;
|
|
329
|
-
private readonly originalContainerPosition;
|
|
330
|
-
private readonly adjustedContainerPosition;
|
|
331
329
|
private pointer;
|
|
332
330
|
private animationFrame;
|
|
333
331
|
private lastFrameTime;
|
|
@@ -464,7 +462,7 @@ interface PlatformRectangle extends Rectangle {
|
|
|
464
462
|
}
|
|
465
463
|
/** Resolves a platform option into DOM elements, excluding engine-owned nodes. */
|
|
466
464
|
declare function resolvePlatformElements(source: string | readonly HTMLElement[], document: Document, excludedRoot?: HTMLElement): HTMLElement[];
|
|
467
|
-
/** Reads platform bounds once and converts viewport coordinates to
|
|
465
|
+
/** Reads platform bounds once and converts viewport coordinates to the supplied origin. */
|
|
468
466
|
declare function readPlatformRectangles(elements: readonly HTMLElement[], workAreaRectangle: Pick<DOMRect, "left" | "top">): PlatformRectangle[];
|
|
469
467
|
|
|
470
468
|
/** A resolved image and optional atlas crop for one sprite frame. */
|
|
@@ -496,9 +494,9 @@ declare function isIndividualSprite(sprite: SpriteRectangle | IndividualSprite |
|
|
|
496
494
|
|
|
497
495
|
/** DOM nodes and resources owned by one mascot. */
|
|
498
496
|
interface MascotDomHandle {
|
|
499
|
-
/**
|
|
497
|
+
/** Fixed, pointer-transparent mascot wrapper. */
|
|
500
498
|
element: HTMLDivElement;
|
|
501
|
-
/**
|
|
499
|
+
/** Pointer-interactive child element on which sprite images are painted. */
|
|
502
500
|
spriteElement: HTMLDivElement;
|
|
503
501
|
/** Per-mascot spritesheet URL lease. */
|
|
504
502
|
spriteLease: SpriteLease;
|
package/dist/index.js
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
1
|
// src/dom.ts
|
|
2
2
|
var DomManager = class {
|
|
3
|
-
/**
|
|
4
|
-
constructor(container, sprites
|
|
3
|
+
/** Uses the supplied element only as a mount point for independent mascots. */
|
|
4
|
+
constructor(container, sprites) {
|
|
5
5
|
this.container = container;
|
|
6
6
|
this.sprites = sprites;
|
|
7
|
-
const workArea = document.createElement("div");
|
|
8
|
-
workArea.dataset.reactShimejiWorkArea = "true";
|
|
9
|
-
if (workAreaClassName) workArea.className = workAreaClassName;
|
|
10
|
-
Object.assign(workArea.style, {
|
|
11
|
-
position: "absolute",
|
|
12
|
-
inset: "0",
|
|
13
|
-
width: "100%",
|
|
14
|
-
height: "100%",
|
|
15
|
-
overflow: "hidden",
|
|
16
|
-
pointerEvents: "none",
|
|
17
|
-
zIndex: "2147483643"
|
|
18
|
-
});
|
|
19
|
-
this.workArea = workArea;
|
|
20
|
-
this.ensureMounted();
|
|
21
7
|
}
|
|
22
8
|
container;
|
|
23
9
|
sprites;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/** Reattaches the work area if application code temporarily removed it. */
|
|
10
|
+
handles = /* @__PURE__ */ new Set();
|
|
11
|
+
/** Reattaches mascot elements if application code temporarily removed them. */
|
|
27
12
|
ensureMounted() {
|
|
28
|
-
|
|
13
|
+
const target = this.container.ownerDocument.body;
|
|
14
|
+
for (const handle of this.handles) {
|
|
15
|
+
if (handle.element.parentElement !== target) target.appendChild(handle.element);
|
|
16
|
+
}
|
|
29
17
|
}
|
|
30
|
-
/** Returns
|
|
18
|
+
/** Returns viewport bounds because fixed mascots use viewport coordinates. */
|
|
31
19
|
getBounds() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/** Converts a previously-read work-area client rectangle into local bounds. */
|
|
35
|
-
getBoundsFromClientRectangle(rectangle) {
|
|
36
|
-
const width = rectangle.width || this.container.clientWidth || window.innerWidth;
|
|
37
|
-
const height = rectangle.height || this.container.clientHeight || window.innerHeight;
|
|
38
|
-
return { x: 0, y: 0, width, height };
|
|
20
|
+
const view = this.container.ownerDocument.defaultView ?? window;
|
|
21
|
+
return { x: 0, y: 0, width: view.innerWidth, height: view.innerHeight };
|
|
39
22
|
}
|
|
40
23
|
/** Creates a mascot node and acquires its spritesheet resource. */
|
|
41
24
|
createMascot(spec, mascotId, mascotClassName) {
|
|
@@ -43,12 +26,14 @@ var DomManager = class {
|
|
|
43
26
|
const element = document.createElement("div");
|
|
44
27
|
element.dataset.shimejiId = mascotId;
|
|
45
28
|
if (mascotClassName) element.className = mascotClassName;
|
|
46
|
-
Object.assign(element.style, { position: "
|
|
29
|
+
Object.assign(element.style, { position: "fixed", left: "0", top: "0", width: "0", height: "0", pointerEvents: "none", zIndex: "9999", userSelect: "none", willChange: "transform" });
|
|
47
30
|
const spriteElement = document.createElement("div");
|
|
48
|
-
Object.assign(spriteElement.style, { position: "absolute", left: "0", top: "0", backgroundRepeat: "no-repeat", transformOrigin: "center center", pointerEvents: "none" });
|
|
31
|
+
Object.assign(spriteElement.style, { position: "absolute", left: "0", top: "0", backgroundRepeat: "no-repeat", transformOrigin: "center center", pointerEvents: "auto", touchAction: "none", userSelect: "none" });
|
|
49
32
|
element.appendChild(spriteElement);
|
|
50
|
-
|
|
51
|
-
|
|
33
|
+
const handle = { element, spriteElement, spriteLease };
|
|
34
|
+
this.handles.add(handle);
|
|
35
|
+
this.container.ownerDocument.body.appendChild(element);
|
|
36
|
+
return handle;
|
|
52
37
|
}
|
|
53
38
|
/** Paints one mascot state into its existing DOM nodes. */
|
|
54
39
|
render(handle, spec, state) {
|
|
@@ -80,12 +65,18 @@ var DomManager = class {
|
|
|
80
65
|
}
|
|
81
66
|
/** Removes one mascot node and releases its temporary image URL. */
|
|
82
67
|
removeMascot(handle) {
|
|
68
|
+
if (!this.handles.delete(handle)) return;
|
|
83
69
|
handle.element.remove();
|
|
84
70
|
handle.spriteLease.release();
|
|
85
71
|
}
|
|
86
|
-
/**
|
|
72
|
+
/** Returns whether an element belongs to one of this manager's mascots. */
|
|
73
|
+
owns(element) {
|
|
74
|
+
for (const handle of this.handles) if (handle.element === element || handle.element.contains(element)) return true;
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
/** Removes every mascot element and releases its temporary image URL. */
|
|
87
78
|
destroy() {
|
|
88
|
-
this.
|
|
79
|
+
for (const handle of [...this.handles]) this.removeMascot(handle);
|
|
89
80
|
}
|
|
90
81
|
};
|
|
91
82
|
|
|
@@ -1102,7 +1093,7 @@ var Mascot = class {
|
|
|
1102
1093
|
return nearby;
|
|
1103
1094
|
}
|
|
1104
1095
|
installPointerHandlers() {
|
|
1105
|
-
const element = this.domHandle.
|
|
1096
|
+
const element = this.domHandle.spriteElement;
|
|
1106
1097
|
const listen = (target, type, listener) => {
|
|
1107
1098
|
target.addEventListener(type, listener);
|
|
1108
1099
|
this.disposers.push(() => target.removeEventListener(type, listener));
|
|
@@ -1111,8 +1102,7 @@ var Mascot = class {
|
|
|
1111
1102
|
const pointerEvent = event;
|
|
1112
1103
|
if (pointerEvent.button !== 0) return;
|
|
1113
1104
|
event.preventDefault();
|
|
1114
|
-
const
|
|
1115
|
-
const point = { x: pointerEvent.clientX - bounds.left, y: pointerEvent.clientY - bounds.top };
|
|
1105
|
+
const point = { x: pointerEvent.clientX, y: pointerEvent.clientY };
|
|
1116
1106
|
this.pointerId = pointerEvent.pointerId;
|
|
1117
1107
|
this.pointerDown = point;
|
|
1118
1108
|
this.lastPointer = point;
|
|
@@ -1126,8 +1116,7 @@ var Mascot = class {
|
|
|
1126
1116
|
listen(document, "pointermove", (event) => {
|
|
1127
1117
|
const pointerEvent = event;
|
|
1128
1118
|
if (!this.state.dragging || pointerEvent.pointerId !== this.pointerId) return;
|
|
1129
|
-
const
|
|
1130
|
-
const point = { x: pointerEvent.clientX - bounds.left, y: pointerEvent.clientY - bounds.top };
|
|
1119
|
+
const point = { x: pointerEvent.clientX, y: pointerEvent.clientY };
|
|
1131
1120
|
const previous = this.lastPointer ?? point;
|
|
1132
1121
|
this.state.vx = (point.x - previous.x) * 0.8;
|
|
1133
1122
|
this.state.vy = (point.y - previous.y) * 0.8;
|
|
@@ -1275,10 +1264,7 @@ var ShimejiEngine = class {
|
|
|
1275
1264
|
if (!container) throw new TypeError("ShimejiEngine requires a container element");
|
|
1276
1265
|
this.options = { ...defaults, ...options, random: options.random };
|
|
1277
1266
|
this.platformSource = this.options.platforms;
|
|
1278
|
-
this.
|
|
1279
|
-
this.adjustedContainerPosition = getComputedStyle(container).position === "static";
|
|
1280
|
-
if (this.adjustedContainerPosition) container.style.position = "relative";
|
|
1281
|
-
this.dom = new DomManager(container, this.sprites, this.options.workAreaClassName || void 0);
|
|
1267
|
+
this.dom = new DomManager(container, this.sprites);
|
|
1282
1268
|
this.initialize();
|
|
1283
1269
|
}
|
|
1284
1270
|
container;
|
|
@@ -1290,8 +1276,6 @@ var ShimejiEngine = class {
|
|
|
1290
1276
|
disposers = [];
|
|
1291
1277
|
intervals = /* @__PURE__ */ new Set();
|
|
1292
1278
|
options;
|
|
1293
|
-
originalContainerPosition;
|
|
1294
|
-
adjustedContainerPosition;
|
|
1295
1279
|
pointer = { x: 0, y: 0, dx: 0, dy: 0 };
|
|
1296
1280
|
animationFrame;
|
|
1297
1281
|
lastFrameTime;
|
|
@@ -1306,9 +1290,8 @@ var ShimejiEngine = class {
|
|
|
1306
1290
|
this.initialized = true;
|
|
1307
1291
|
this.listen(document, "pointermove", (event) => {
|
|
1308
1292
|
const pointerEvent = event;
|
|
1309
|
-
const
|
|
1310
|
-
const
|
|
1311
|
-
const y = pointerEvent.clientY - rectangle.top;
|
|
1293
|
+
const x = pointerEvent.clientX;
|
|
1294
|
+
const y = pointerEvent.clientY;
|
|
1312
1295
|
this.pointer = { x, y, dx: x - this.pointer.x, dy: y - this.pointer.y };
|
|
1313
1296
|
});
|
|
1314
1297
|
this.listen(window, "resize", () => this.renderAll());
|
|
@@ -1412,7 +1395,6 @@ var ShimejiEngine = class {
|
|
|
1412
1395
|
this.sprites.destroy();
|
|
1413
1396
|
this.specs.clear();
|
|
1414
1397
|
this.events.clear();
|
|
1415
|
-
if (this.adjustedContainerPosition && this.container.style.position === "relative") this.container.style.position = this.originalContainerPosition;
|
|
1416
1398
|
this.destroyed = true;
|
|
1417
1399
|
this.initialized = false;
|
|
1418
1400
|
}
|
|
@@ -1435,10 +1417,9 @@ var ShimejiEngine = class {
|
|
|
1435
1417
|
for (const mascot of this.mascots.values()) mascot.tick(0, bounds, platforms);
|
|
1436
1418
|
}
|
|
1437
1419
|
readFrameGeometry() {
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
return { bounds, platforms: readPlatformRectangles(elements, workAreaRectangle) };
|
|
1420
|
+
const bounds = this.dom.getBounds();
|
|
1421
|
+
const elements = resolvePlatformElements(this.platformSource, this.container.ownerDocument).filter((element) => !this.dom.owns(element));
|
|
1422
|
+
return { bounds, platforms: readPlatformRectangles(elements, { left: 0, top: 0 }) };
|
|
1442
1423
|
}
|
|
1443
1424
|
emitState() {
|
|
1444
1425
|
this.events.emit("statechange", this.getState());
|