@react-shimeji/core 0.2.1 → 0.2.2
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 +33 -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 +33 -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,23 @@
|
|
|
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
|
+
for (const handle of this.handles) {
|
|
14
|
+
if (handle.element.parentElement !== this.container) this.container.appendChild(handle.element);
|
|
15
|
+
}
|
|
29
16
|
}
|
|
30
|
-
/** Returns
|
|
17
|
+
/** Returns viewport bounds because fixed mascots use viewport coordinates. */
|
|
31
18
|
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 };
|
|
19
|
+
const view = this.container.ownerDocument.defaultView ?? window;
|
|
20
|
+
return { x: 0, y: 0, width: view.innerWidth, height: view.innerHeight };
|
|
39
21
|
}
|
|
40
22
|
/** Creates a mascot node and acquires its spritesheet resource. */
|
|
41
23
|
createMascot(spec, mascotId, mascotClassName) {
|
|
@@ -43,12 +25,14 @@ var DomManager = class {
|
|
|
43
25
|
const element = document.createElement("div");
|
|
44
26
|
element.dataset.shimejiId = mascotId;
|
|
45
27
|
if (mascotClassName) element.className = mascotClassName;
|
|
46
|
-
Object.assign(element.style, { position: "
|
|
28
|
+
Object.assign(element.style, { position: "fixed", left: "0", top: "0", width: "0", height: "0", pointerEvents: "none", zIndex: "9999", userSelect: "none", willChange: "transform" });
|
|
47
29
|
const spriteElement = document.createElement("div");
|
|
48
|
-
Object.assign(spriteElement.style, { position: "absolute", left: "0", top: "0", backgroundRepeat: "no-repeat", transformOrigin: "center center", pointerEvents: "none" });
|
|
30
|
+
Object.assign(spriteElement.style, { position: "absolute", left: "0", top: "0", backgroundRepeat: "no-repeat", transformOrigin: "center center", pointerEvents: "auto", touchAction: "none", userSelect: "none" });
|
|
49
31
|
element.appendChild(spriteElement);
|
|
50
|
-
|
|
51
|
-
|
|
32
|
+
const handle = { element, spriteElement, spriteLease };
|
|
33
|
+
this.handles.add(handle);
|
|
34
|
+
this.container.appendChild(element);
|
|
35
|
+
return handle;
|
|
52
36
|
}
|
|
53
37
|
/** Paints one mascot state into its existing DOM nodes. */
|
|
54
38
|
render(handle, spec, state) {
|
|
@@ -80,12 +64,18 @@ var DomManager = class {
|
|
|
80
64
|
}
|
|
81
65
|
/** Removes one mascot node and releases its temporary image URL. */
|
|
82
66
|
removeMascot(handle) {
|
|
67
|
+
if (!this.handles.delete(handle)) return;
|
|
83
68
|
handle.element.remove();
|
|
84
69
|
handle.spriteLease.release();
|
|
85
70
|
}
|
|
86
|
-
/**
|
|
71
|
+
/** Returns whether an element belongs to one of this manager's mascots. */
|
|
72
|
+
owns(element) {
|
|
73
|
+
for (const handle of this.handles) if (handle.element === element || handle.element.contains(element)) return true;
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
/** Removes every mascot element and releases its temporary image URL. */
|
|
87
77
|
destroy() {
|
|
88
|
-
this.
|
|
78
|
+
for (const handle of [...this.handles]) this.removeMascot(handle);
|
|
89
79
|
}
|
|
90
80
|
};
|
|
91
81
|
|
|
@@ -1102,7 +1092,7 @@ var Mascot = class {
|
|
|
1102
1092
|
return nearby;
|
|
1103
1093
|
}
|
|
1104
1094
|
installPointerHandlers() {
|
|
1105
|
-
const element = this.domHandle.
|
|
1095
|
+
const element = this.domHandle.spriteElement;
|
|
1106
1096
|
const listen = (target, type, listener) => {
|
|
1107
1097
|
target.addEventListener(type, listener);
|
|
1108
1098
|
this.disposers.push(() => target.removeEventListener(type, listener));
|
|
@@ -1111,8 +1101,7 @@ var Mascot = class {
|
|
|
1111
1101
|
const pointerEvent = event;
|
|
1112
1102
|
if (pointerEvent.button !== 0) return;
|
|
1113
1103
|
event.preventDefault();
|
|
1114
|
-
const
|
|
1115
|
-
const point = { x: pointerEvent.clientX - bounds.left, y: pointerEvent.clientY - bounds.top };
|
|
1104
|
+
const point = { x: pointerEvent.clientX, y: pointerEvent.clientY };
|
|
1116
1105
|
this.pointerId = pointerEvent.pointerId;
|
|
1117
1106
|
this.pointerDown = point;
|
|
1118
1107
|
this.lastPointer = point;
|
|
@@ -1126,8 +1115,7 @@ var Mascot = class {
|
|
|
1126
1115
|
listen(document, "pointermove", (event) => {
|
|
1127
1116
|
const pointerEvent = event;
|
|
1128
1117
|
if (!this.state.dragging || pointerEvent.pointerId !== this.pointerId) return;
|
|
1129
|
-
const
|
|
1130
|
-
const point = { x: pointerEvent.clientX - bounds.left, y: pointerEvent.clientY - bounds.top };
|
|
1118
|
+
const point = { x: pointerEvent.clientX, y: pointerEvent.clientY };
|
|
1131
1119
|
const previous = this.lastPointer ?? point;
|
|
1132
1120
|
this.state.vx = (point.x - previous.x) * 0.8;
|
|
1133
1121
|
this.state.vy = (point.y - previous.y) * 0.8;
|
|
@@ -1275,10 +1263,7 @@ var ShimejiEngine = class {
|
|
|
1275
1263
|
if (!container) throw new TypeError("ShimejiEngine requires a container element");
|
|
1276
1264
|
this.options = { ...defaults, ...options, random: options.random };
|
|
1277
1265
|
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);
|
|
1266
|
+
this.dom = new DomManager(container, this.sprites);
|
|
1282
1267
|
this.initialize();
|
|
1283
1268
|
}
|
|
1284
1269
|
container;
|
|
@@ -1290,8 +1275,6 @@ var ShimejiEngine = class {
|
|
|
1290
1275
|
disposers = [];
|
|
1291
1276
|
intervals = /* @__PURE__ */ new Set();
|
|
1292
1277
|
options;
|
|
1293
|
-
originalContainerPosition;
|
|
1294
|
-
adjustedContainerPosition;
|
|
1295
1278
|
pointer = { x: 0, y: 0, dx: 0, dy: 0 };
|
|
1296
1279
|
animationFrame;
|
|
1297
1280
|
lastFrameTime;
|
|
@@ -1306,9 +1289,8 @@ var ShimejiEngine = class {
|
|
|
1306
1289
|
this.initialized = true;
|
|
1307
1290
|
this.listen(document, "pointermove", (event) => {
|
|
1308
1291
|
const pointerEvent = event;
|
|
1309
|
-
const
|
|
1310
|
-
const
|
|
1311
|
-
const y = pointerEvent.clientY - rectangle.top;
|
|
1292
|
+
const x = pointerEvent.clientX;
|
|
1293
|
+
const y = pointerEvent.clientY;
|
|
1312
1294
|
this.pointer = { x, y, dx: x - this.pointer.x, dy: y - this.pointer.y };
|
|
1313
1295
|
});
|
|
1314
1296
|
this.listen(window, "resize", () => this.renderAll());
|
|
@@ -1412,7 +1394,6 @@ var ShimejiEngine = class {
|
|
|
1412
1394
|
this.sprites.destroy();
|
|
1413
1395
|
this.specs.clear();
|
|
1414
1396
|
this.events.clear();
|
|
1415
|
-
if (this.adjustedContainerPosition && this.container.style.position === "relative") this.container.style.position = this.originalContainerPosition;
|
|
1416
1397
|
this.destroyed = true;
|
|
1417
1398
|
this.initialized = false;
|
|
1418
1399
|
}
|
|
@@ -1435,10 +1416,9 @@ var ShimejiEngine = class {
|
|
|
1435
1416
|
for (const mascot of this.mascots.values()) mascot.tick(0, bounds, platforms);
|
|
1436
1417
|
}
|
|
1437
1418
|
readFrameGeometry() {
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1440
|
-
|
|
1441
|
-
return { bounds, platforms: readPlatformRectangles(elements, workAreaRectangle) };
|
|
1419
|
+
const bounds = this.dom.getBounds();
|
|
1420
|
+
const elements = resolvePlatformElements(this.platformSource, this.container.ownerDocument).filter((element) => !this.dom.owns(element));
|
|
1421
|
+
return { bounds, platforms: readPlatformRectangles(elements, { left: 0, top: 0 }) };
|
|
1442
1422
|
}
|
|
1443
1423
|
emitState() {
|
|
1444
1424
|
this.events.emit("statechange", this.getState());
|