koota 0.0.3 → 0.0.5
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 +133 -2
- package/dist/index.cjs +6 -5
- package/dist/index.js +6 -5
- package/dist/react.cjs +24 -3
- package/dist/react.d.cts +5 -3
- package/dist/react.d.ts +5 -3
- package/dist/react.js +23 -3
- package/package.json +12 -5
- package/react/index.cjs +132 -0
- package/react/index.d.cts +21 -0
- package/react/index.d.ts +21 -0
- package/react/index.js +102 -0
package/README.md
CHANGED
|
@@ -318,15 +318,22 @@ const time = world.get(Time);
|
|
|
318
318
|
world.set(Time, { current: performance.now() });
|
|
319
319
|
```
|
|
320
320
|
|
|
321
|
+
### Select traits on queries for updates
|
|
322
|
+
Query filters entity results and `select` is used to choose what traits are fetched for `updateEach` and `useStore`.
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
// Add example when I get the energy
|
|
326
|
+
```
|
|
327
|
+
|
|
321
328
|
### Modifying trait stores direclty
|
|
322
329
|
|
|
323
330
|
For performance-critical operations, you can modify trait stores directly using the useStore hook. This approach bypasses some of the safety checks and event triggers, so use it with caution. All stores are structure of arrays for performance purposes.
|
|
324
331
|
|
|
325
332
|
```js
|
|
326
333
|
// Returns the SoA stores
|
|
327
|
-
world.query(Position, Velocity).useStore(([position,
|
|
334
|
+
world.query(Position, Velocity).useStore(([position, velocity], entities) => {
|
|
328
335
|
// Write our own loop over the stores
|
|
329
|
-
for (let i = 0; i
|
|
336
|
+
for (let i = 0; i < entities.length; i++) {
|
|
330
337
|
// Get the entity ID to use as the array index
|
|
331
338
|
const eid = entities[i].id();
|
|
332
339
|
// Write to each array in the store
|
|
@@ -335,3 +342,127 @@ world.query(Position, Velocity).useStore(([position, store], entities) => {
|
|
|
335
342
|
}
|
|
336
343
|
});
|
|
337
344
|
```
|
|
345
|
+
|
|
346
|
+
## APIs in detail until I make docs
|
|
347
|
+
|
|
348
|
+
These are more like notes for docs. Take a look around, ask questions. Eventually this will become proper docs.
|
|
349
|
+
|
|
350
|
+
### World
|
|
351
|
+
|
|
352
|
+
This is where all data is stored. We have methods on entities but this is a bit of a trick, entities don't actually store any data and instead it is operating on the connected world. Each world has its own set of entities that do not overlap with another. Typically you only need one world.
|
|
353
|
+
|
|
354
|
+
Worlds can have traits, which is our version of a singleton. Use these for global resources like a clock. Each world gets its own entity used for world traits. This entity is no queryable but will show up in the list of active entities making the only way to retrieve a world trait with its API.
|
|
355
|
+
|
|
356
|
+
```js
|
|
357
|
+
// Spawns an entity
|
|
358
|
+
// Can pass any number of traits
|
|
359
|
+
// Return Entity
|
|
360
|
+
const entity = world.spawn()
|
|
361
|
+
|
|
362
|
+
// Checks if the world has the entity
|
|
363
|
+
// Return boolean
|
|
364
|
+
const result = world.has(entity)
|
|
365
|
+
|
|
366
|
+
// Get all entities that match the query parameters
|
|
367
|
+
// Return QueryResult (which is Entity[] with extras)
|
|
368
|
+
const entities = world.query(Position)
|
|
369
|
+
|
|
370
|
+
// Return the first entity that matches the query
|
|
371
|
+
// Return Entity
|
|
372
|
+
const entity = world.queryFirst(Position)
|
|
373
|
+
|
|
374
|
+
// The trait API is identical to entity's
|
|
375
|
+
|
|
376
|
+
// Add a trait to the world
|
|
377
|
+
world.add(Time)
|
|
378
|
+
|
|
379
|
+
// Remove a trait from the world
|
|
380
|
+
world.remove(Time)
|
|
381
|
+
|
|
382
|
+
// Check if the world has a trait
|
|
383
|
+
// Return boolean
|
|
384
|
+
const result = world.has(Time)
|
|
385
|
+
|
|
386
|
+
// Gets a snapshot instance of the trait
|
|
387
|
+
// Return TraitInstance
|
|
388
|
+
const time = world.get(Time)
|
|
389
|
+
|
|
390
|
+
// Sets the trait and triggers a change event
|
|
391
|
+
world.set(Time, { current: performance.now() })
|
|
392
|
+
|
|
393
|
+
// Subscribe to add, remove or change events for a set of query parameters
|
|
394
|
+
// Anything you can put in a query is legal
|
|
395
|
+
// Return unsub function
|
|
396
|
+
const unsub = world.onAdd([Position], (entity) => {})
|
|
397
|
+
const unsub = world.onRemove([Position], (entity) => {})
|
|
398
|
+
const unsub = world.onChange([Position], (entity) => {})
|
|
399
|
+
|
|
400
|
+
// An array of all entities alive in the world
|
|
401
|
+
// This is a copy so editing it won't do anything!
|
|
402
|
+
// Entity[]
|
|
403
|
+
world.entities
|
|
404
|
+
|
|
405
|
+
// Returns the world's unique ID
|
|
406
|
+
// Return number
|
|
407
|
+
const id = world.id()
|
|
408
|
+
|
|
409
|
+
// Resets the world as if it were just created
|
|
410
|
+
world.reset()
|
|
411
|
+
|
|
412
|
+
// Nukes the world and releases its ID
|
|
413
|
+
world.destroy()
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Entity
|
|
417
|
+
|
|
418
|
+
An entity is a number encoded with a world, generation and ID. Every entity is unique even if they have the same ID since they will have different generations. This makes automatic-recycling possible without reference errors. Because of this, the number of an entity won't give you its ID but will have to instaed be decoded with `entity.id()`.
|
|
419
|
+
|
|
420
|
+
```js
|
|
421
|
+
// Add a trait to the entity
|
|
422
|
+
entity.add(Position)
|
|
423
|
+
|
|
424
|
+
// Remove a trait from the entity
|
|
425
|
+
entity.remove(Position)
|
|
426
|
+
|
|
427
|
+
// Checks if the entity has the trait
|
|
428
|
+
// Return boolean
|
|
429
|
+
const result = enttiy.has(Position)
|
|
430
|
+
|
|
431
|
+
// Gets a snapshot instance of the trait
|
|
432
|
+
// Return TraitInstance
|
|
433
|
+
const position = entity.get(Position)
|
|
434
|
+
|
|
435
|
+
// Sets the trait and triggers a change event
|
|
436
|
+
entity.set(Position, { x: 10, y: 10 })
|
|
437
|
+
|
|
438
|
+
// Get the targets for a relationship
|
|
439
|
+
// Return Entity[]
|
|
440
|
+
const targets = entity.targetsFor(Contains)
|
|
441
|
+
|
|
442
|
+
// Get the first target for a relationship
|
|
443
|
+
// Return Entity
|
|
444
|
+
const target = entity.targetFor(Contains)
|
|
445
|
+
|
|
446
|
+
// Get the entity ID
|
|
447
|
+
// Return number
|
|
448
|
+
const id = entity.id()
|
|
449
|
+
|
|
450
|
+
// Destroys the entity making its number no longer valid
|
|
451
|
+
entity.destroy()
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### React
|
|
455
|
+
|
|
456
|
+
`useEntityRef` is a safe way to spawn an entity per React primitive and add traits. It is usually used for adding traits that capture the ref to the entity. The entity will be stable for the lifetime of the React component, except in cases like HMR.
|
|
457
|
+
|
|
458
|
+
```js
|
|
459
|
+
const Ref = trait({ value: null! })
|
|
460
|
+
|
|
461
|
+
function Rocket() {
|
|
462
|
+
const entityRef = useEntityRef((node, entity) => {
|
|
463
|
+
entity.add(Ref({ value: node }))
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
return <div ref={entityRef}>🚀</div>
|
|
467
|
+
}
|
|
468
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -297,10 +297,12 @@ function addTrait(world, entity, ...traits) {
|
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
|
-
const defaults =
|
|
301
|
-
for (const key in
|
|
302
|
-
if (typeof
|
|
303
|
-
defaults[key] =
|
|
300
|
+
const defaults = {};
|
|
301
|
+
for (const key in data.schema) {
|
|
302
|
+
if (typeof data.schema[key] === "function") {
|
|
303
|
+
defaults[key] = data.schema[key]();
|
|
304
|
+
} else {
|
|
305
|
+
defaults[key] = data.schema[key];
|
|
304
306
|
}
|
|
305
307
|
}
|
|
306
308
|
entity.set(trait2, { ...defaults, ...params }, false);
|
|
@@ -350,7 +352,6 @@ function hasTrait(world, entity, trait2) {
|
|
|
350
352
|
}
|
|
351
353
|
function getStore(world, trait2) {
|
|
352
354
|
const ctx = world[$internal];
|
|
353
|
-
if (!ctx.traitData.has(trait2)) registerTrait(world, trait2);
|
|
354
355
|
const data = ctx.traitData.get(trait2);
|
|
355
356
|
const store = data.store;
|
|
356
357
|
return store;
|
package/dist/index.js
CHANGED
|
@@ -258,10 +258,12 @@ function addTrait(world, entity, ...traits) {
|
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
|
-
const defaults =
|
|
262
|
-
for (const key in
|
|
263
|
-
if (typeof
|
|
264
|
-
defaults[key] =
|
|
261
|
+
const defaults = {};
|
|
262
|
+
for (const key in data.schema) {
|
|
263
|
+
if (typeof data.schema[key] === "function") {
|
|
264
|
+
defaults[key] = data.schema[key]();
|
|
265
|
+
} else {
|
|
266
|
+
defaults[key] = data.schema[key];
|
|
265
267
|
}
|
|
266
268
|
}
|
|
267
269
|
entity.set(trait2, { ...defaults, ...params }, false);
|
|
@@ -311,7 +313,6 @@ function hasTrait(world, entity, trait2) {
|
|
|
311
313
|
}
|
|
312
314
|
function getStore(world, trait2) {
|
|
313
315
|
const ctx = world[$internal];
|
|
314
|
-
if (!ctx.traitData.has(trait2)) registerTrait(world, trait2);
|
|
315
316
|
const data = ctx.traitData.get(trait2);
|
|
316
317
|
const store = data.store;
|
|
317
318
|
return store;
|
package/dist/react.cjs
CHANGED
|
@@ -22,13 +22,14 @@ var react_exports = {};
|
|
|
22
22
|
__export(react_exports, {
|
|
23
23
|
WorldProvider: () => WorldProvider,
|
|
24
24
|
createActions: () => createActions,
|
|
25
|
+
useEntityRef: () => useEntityRef,
|
|
25
26
|
useObserve: () => useObserve,
|
|
26
27
|
useQuery: () => useQuery,
|
|
27
28
|
useWorld: () => useWorld
|
|
28
29
|
});
|
|
29
30
|
module.exports = __toCommonJS(react_exports);
|
|
30
31
|
|
|
31
|
-
// ../react/src/
|
|
32
|
+
// ../react/src/hooks/use-query.ts
|
|
32
33
|
var import_react3 = require("react");
|
|
33
34
|
|
|
34
35
|
// ../react/src/world/use-world.ts
|
|
@@ -45,7 +46,7 @@ function useWorld() {
|
|
|
45
46
|
return world;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
// ../react/src/
|
|
49
|
+
// ../react/src/hooks/use-query.ts
|
|
49
50
|
function useQuery(...parameters) {
|
|
50
51
|
const world = useWorld();
|
|
51
52
|
const [entities, setEntities] = (0, import_react3.useState)([]);
|
|
@@ -83,7 +84,7 @@ function createActions(actionSet) {
|
|
|
83
84
|
);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
// ../react/src/
|
|
87
|
+
// ../react/src/hooks/use-observe.ts
|
|
87
88
|
var import_react4 = require("react");
|
|
88
89
|
function useObserve(entity, trait) {
|
|
89
90
|
const world = useWorld();
|
|
@@ -101,10 +102,30 @@ function useObserve(entity, trait) {
|
|
|
101
102
|
}, [entity, trait]);
|
|
102
103
|
return value;
|
|
103
104
|
}
|
|
105
|
+
|
|
106
|
+
// ../react/src/hooks/use-entity-ref.ts
|
|
107
|
+
var import_react5 = require("react");
|
|
108
|
+
function useEntityRef(callback) {
|
|
109
|
+
const world = useWorld();
|
|
110
|
+
const entityRef = (0, import_react5.useRef)(null);
|
|
111
|
+
return (0, import_react5.useCallback)(
|
|
112
|
+
(node) => {
|
|
113
|
+
if (node) {
|
|
114
|
+
if (entityRef.current) entityRef.current.destroy();
|
|
115
|
+
entityRef.current = world.spawn();
|
|
116
|
+
callback(node, entityRef.current);
|
|
117
|
+
} else if (entityRef.current) {
|
|
118
|
+
entityRef.current.destroy();
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[world]
|
|
122
|
+
);
|
|
123
|
+
}
|
|
104
124
|
// Annotate the CommonJS export names for ESM import in node:
|
|
105
125
|
0 && (module.exports = {
|
|
106
126
|
WorldProvider,
|
|
107
127
|
createActions,
|
|
128
|
+
useEntityRef,
|
|
108
129
|
useObserve,
|
|
109
130
|
useQuery,
|
|
110
131
|
useWorld
|
package/dist/react.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as QueryParameter,
|
|
1
|
+
import { Q as QueryParameter, j as Entity, W as World, T as Trait, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.cjs';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
-
declare function useQuery(...parameters: QueryParameter[]):
|
|
4
|
+
declare function useQuery(...parameters: QueryParameter[]): Entity[];
|
|
5
5
|
|
|
6
6
|
declare function WorldProvider({ children, world }: {
|
|
7
7
|
children: React.ReactNode;
|
|
@@ -16,4 +16,6 @@ declare function createActions<T extends Record<string, (...args: any[]) => any>
|
|
|
16
16
|
|
|
17
17
|
declare function useObserve<T extends Trait>(entity: Entity, trait: T): TraitInstanceFromSchema<ExtractSchema<T>> | undefined;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
declare function useEntityRef<T = any>(callback: (node: T, entity: Entity) => void): (node: T) => void;
|
|
20
|
+
|
|
21
|
+
export { WorldProvider, createActions, useEntityRef, useObserve, useQuery, useWorld };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Q as QueryParameter,
|
|
1
|
+
import { Q as QueryParameter, j as Entity, W as World, T as Trait, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.js';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
|
-
declare function useQuery(...parameters: QueryParameter[]):
|
|
4
|
+
declare function useQuery(...parameters: QueryParameter[]): Entity[];
|
|
5
5
|
|
|
6
6
|
declare function WorldProvider({ children, world }: {
|
|
7
7
|
children: React.ReactNode;
|
|
@@ -16,4 +16,6 @@ declare function createActions<T extends Record<string, (...args: any[]) => any>
|
|
|
16
16
|
|
|
17
17
|
declare function useObserve<T extends Trait>(entity: Entity, trait: T): TraitInstanceFromSchema<ExtractSchema<T>> | undefined;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
declare function useEntityRef<T = any>(callback: (node: T, entity: Entity) => void): (node: T) => void;
|
|
20
|
+
|
|
21
|
+
export { WorldProvider, createActions, useEntityRef, useObserve, useQuery, useWorld };
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./chunk-AQ5VUG5P.js";
|
|
2
2
|
|
|
3
|
-
// ../react/src/
|
|
3
|
+
// ../react/src/hooks/use-query.ts
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
5
|
|
|
6
6
|
// ../react/src/world/use-world.ts
|
|
@@ -17,7 +17,7 @@ function useWorld() {
|
|
|
17
17
|
return world;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// ../react/src/
|
|
20
|
+
// ../react/src/hooks/use-query.ts
|
|
21
21
|
function useQuery(...parameters) {
|
|
22
22
|
const world = useWorld();
|
|
23
23
|
const [entities, setEntities] = useState([]);
|
|
@@ -55,7 +55,7 @@ function createActions(actionSet) {
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
// ../react/src/
|
|
58
|
+
// ../react/src/hooks/use-observe.ts
|
|
59
59
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
60
60
|
function useObserve(entity, trait) {
|
|
61
61
|
const world = useWorld();
|
|
@@ -73,9 +73,29 @@ function useObserve(entity, trait) {
|
|
|
73
73
|
}, [entity, trait]);
|
|
74
74
|
return value;
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
// ../react/src/hooks/use-entity-ref.ts
|
|
78
|
+
import { useCallback, useRef } from "react";
|
|
79
|
+
function useEntityRef(callback) {
|
|
80
|
+
const world = useWorld();
|
|
81
|
+
const entityRef = useRef(null);
|
|
82
|
+
return useCallback(
|
|
83
|
+
(node) => {
|
|
84
|
+
if (node) {
|
|
85
|
+
if (entityRef.current) entityRef.current.destroy();
|
|
86
|
+
entityRef.current = world.spawn();
|
|
87
|
+
callback(node, entityRef.current);
|
|
88
|
+
} else if (entityRef.current) {
|
|
89
|
+
entityRef.current.destroy();
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
[world]
|
|
93
|
+
);
|
|
94
|
+
}
|
|
76
95
|
export {
|
|
77
96
|
WorldProvider,
|
|
78
97
|
createActions,
|
|
98
|
+
useEntityRef,
|
|
79
99
|
useObserve,
|
|
80
100
|
useQuery,
|
|
81
101
|
useWorld
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koota",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "🌎 Performant data-oriented state management for React and TypeScript.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -9,18 +9,25 @@
|
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"types":
|
|
12
|
+
"types": {
|
|
13
|
+
"import": "./dist/index.d.ts",
|
|
14
|
+
"require": "./dist/index.d.cts"
|
|
15
|
+
},
|
|
13
16
|
"import": "./dist/index.js",
|
|
14
17
|
"require": "./dist/index.cjs"
|
|
15
18
|
},
|
|
16
19
|
"./react": {
|
|
17
|
-
"types":
|
|
20
|
+
"types": {
|
|
21
|
+
"import": "./dist/react.d.ts",
|
|
22
|
+
"require": "./dist/react.d.cts"
|
|
23
|
+
},
|
|
18
24
|
"import": "./dist/react.js",
|
|
19
25
|
"require": "./dist/react.cjs"
|
|
20
26
|
}
|
|
21
27
|
},
|
|
22
28
|
"files": [
|
|
23
29
|
"dist",
|
|
30
|
+
"react",
|
|
24
31
|
"README.md",
|
|
25
32
|
"LICENSE"
|
|
26
33
|
],
|
|
@@ -31,8 +38,8 @@
|
|
|
31
38
|
"react": "^18.3.1",
|
|
32
39
|
"react-dom": "^18.3.1",
|
|
33
40
|
"tsup": "^8.3.0",
|
|
34
|
-
"@koota/react": "0.0.1",
|
|
35
41
|
"@koota/core": "0.0.1",
|
|
42
|
+
"@koota/react": "0.0.1",
|
|
36
43
|
"tsconfig": "0.1.0"
|
|
37
44
|
},
|
|
38
45
|
"peerDependencies": {
|
|
@@ -53,7 +60,7 @@
|
|
|
53
60
|
}
|
|
54
61
|
},
|
|
55
62
|
"scripts": {
|
|
56
|
-
"build": "tsup src/index.ts src/react.ts --format esm,cjs --dts --dts-resolve && tsx scripts/copy-readme.ts",
|
|
63
|
+
"build": "tsup src/index.ts src/react.ts --format esm,cjs --dts --dts-resolve && tsx scripts/copy-readme.ts && tsx scripts/copy-react-files.ts",
|
|
57
64
|
"test": "vitest --environment=jsdom"
|
|
58
65
|
}
|
|
59
66
|
}
|
package/react/index.cjs
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react.ts
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
WorldProvider: () => WorldProvider,
|
|
24
|
+
createActions: () => createActions,
|
|
25
|
+
useEntityRef: () => useEntityRef,
|
|
26
|
+
useObserve: () => useObserve,
|
|
27
|
+
useQuery: () => useQuery,
|
|
28
|
+
useWorld: () => useWorld
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(react_exports);
|
|
31
|
+
|
|
32
|
+
// ../react/src/hooks/use-query.ts
|
|
33
|
+
var import_react3 = require("react");
|
|
34
|
+
|
|
35
|
+
// ../react/src/world/use-world.ts
|
|
36
|
+
var import_react2 = require("react");
|
|
37
|
+
|
|
38
|
+
// ../react/src/world/world-context.ts
|
|
39
|
+
var import_react = require("react");
|
|
40
|
+
var WorldContext = (0, import_react.createContext)(null);
|
|
41
|
+
|
|
42
|
+
// ../react/src/world/use-world.ts
|
|
43
|
+
function useWorld() {
|
|
44
|
+
const world = (0, import_react2.useContext)(WorldContext);
|
|
45
|
+
if (!world) throw new Error("Koota ECS: Hooks can only be used within the World component!");
|
|
46
|
+
return world;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ../react/src/hooks/use-query.ts
|
|
50
|
+
function useQuery(...parameters) {
|
|
51
|
+
const world = useWorld();
|
|
52
|
+
const [entities, setEntities] = (0, import_react3.useState)([]);
|
|
53
|
+
(0, import_react3.useEffect)(() => {
|
|
54
|
+
const unsubAdd = world.onAdd(parameters, (entity) => {
|
|
55
|
+
setEntities((v) => [...v, entity]);
|
|
56
|
+
});
|
|
57
|
+
const unsubRemove = world.onRemove(parameters, (entity) => {
|
|
58
|
+
setEntities((v) => v.filter((e) => e !== entity));
|
|
59
|
+
});
|
|
60
|
+
return () => {
|
|
61
|
+
unsubAdd();
|
|
62
|
+
unsubRemove();
|
|
63
|
+
};
|
|
64
|
+
}, [world, parameters]);
|
|
65
|
+
return entities;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ../react/src/world/world-provider.tsx
|
|
69
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
70
|
+
function WorldProvider({ children, world }) {
|
|
71
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorldContext.Provider, { value: world, children });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ../react/src/actions/create-actions.ts
|
|
75
|
+
function createActions(actionSet) {
|
|
76
|
+
return Object.assign(
|
|
77
|
+
() => {
|
|
78
|
+
const world = useWorld();
|
|
79
|
+
return actionSet(world);
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
get: (world) => actionSet(world)
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ../react/src/hooks/use-observe.ts
|
|
88
|
+
var import_react4 = require("react");
|
|
89
|
+
function useObserve(entity, trait) {
|
|
90
|
+
const world = useWorld();
|
|
91
|
+
const [value, setValue] = (0, import_react4.useState)(() => {
|
|
92
|
+
if (entity.has(trait)) return entity.get(trait);
|
|
93
|
+
return void 0;
|
|
94
|
+
});
|
|
95
|
+
(0, import_react4.useEffect)(() => {
|
|
96
|
+
const unsub = world.onChange(trait, (e) => {
|
|
97
|
+
if (e === entity) setValue(e.get(trait));
|
|
98
|
+
});
|
|
99
|
+
return () => {
|
|
100
|
+
unsub();
|
|
101
|
+
};
|
|
102
|
+
}, [entity, trait]);
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ../react/src/hooks/use-entity-ref.ts
|
|
107
|
+
var import_react5 = require("react");
|
|
108
|
+
function useEntityRef(callback) {
|
|
109
|
+
const world = useWorld();
|
|
110
|
+
const entityRef = (0, import_react5.useRef)(null);
|
|
111
|
+
return (0, import_react5.useCallback)(
|
|
112
|
+
(node) => {
|
|
113
|
+
if (node) {
|
|
114
|
+
if (entityRef.current) entityRef.current.destroy();
|
|
115
|
+
entityRef.current = world.spawn();
|
|
116
|
+
callback(node, entityRef.current);
|
|
117
|
+
} else if (entityRef.current) {
|
|
118
|
+
entityRef.current.destroy();
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[world]
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
125
|
+
0 && (module.exports = {
|
|
126
|
+
WorldProvider,
|
|
127
|
+
createActions,
|
|
128
|
+
useEntityRef,
|
|
129
|
+
useObserve,
|
|
130
|
+
useQuery,
|
|
131
|
+
useWorld
|
|
132
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Q as QueryParameter, j as Entity, W as World, T as Trait, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.cjs';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
declare function useQuery(...parameters: QueryParameter[]): Entity[];
|
|
5
|
+
|
|
6
|
+
declare function WorldProvider({ children, world }: {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
world: World;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
declare function useWorld(): World;
|
|
12
|
+
|
|
13
|
+
declare function createActions<T extends Record<string, (...args: any[]) => any>>(actionSet: (world: World) => T): (() => T) & {
|
|
14
|
+
get: (world: World) => T;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
declare function useObserve<T extends Trait>(entity: Entity, trait: T): TraitInstanceFromSchema<ExtractSchema<T>> | undefined;
|
|
18
|
+
|
|
19
|
+
declare function useEntityRef<T = any>(callback: (node: T, entity: Entity) => void): (node: T) => void;
|
|
20
|
+
|
|
21
|
+
export { WorldProvider, createActions, useEntityRef, useObserve, useQuery, useWorld };
|
package/react/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Q as QueryParameter, j as Entity, W as World, T as Trait, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.js';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
declare function useQuery(...parameters: QueryParameter[]): Entity[];
|
|
5
|
+
|
|
6
|
+
declare function WorldProvider({ children, world }: {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
world: World;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
declare function useWorld(): World;
|
|
12
|
+
|
|
13
|
+
declare function createActions<T extends Record<string, (...args: any[]) => any>>(actionSet: (world: World) => T): (() => T) & {
|
|
14
|
+
get: (world: World) => T;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
declare function useObserve<T extends Trait>(entity: Entity, trait: T): TraitInstanceFromSchema<ExtractSchema<T>> | undefined;
|
|
18
|
+
|
|
19
|
+
declare function useEntityRef<T = any>(callback: (node: T, entity: Entity) => void): (node: T) => void;
|
|
20
|
+
|
|
21
|
+
export { WorldProvider, createActions, useEntityRef, useObserve, useQuery, useWorld };
|
package/react/index.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import "./chunk-AQ5VUG5P.js";
|
|
2
|
+
|
|
3
|
+
// ../react/src/hooks/use-query.ts
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
|
|
6
|
+
// ../react/src/world/use-world.ts
|
|
7
|
+
import { useContext } from "react";
|
|
8
|
+
|
|
9
|
+
// ../react/src/world/world-context.ts
|
|
10
|
+
import { createContext } from "react";
|
|
11
|
+
var WorldContext = createContext(null);
|
|
12
|
+
|
|
13
|
+
// ../react/src/world/use-world.ts
|
|
14
|
+
function useWorld() {
|
|
15
|
+
const world = useContext(WorldContext);
|
|
16
|
+
if (!world) throw new Error("Koota ECS: Hooks can only be used within the World component!");
|
|
17
|
+
return world;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ../react/src/hooks/use-query.ts
|
|
21
|
+
function useQuery(...parameters) {
|
|
22
|
+
const world = useWorld();
|
|
23
|
+
const [entities, setEntities] = useState([]);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const unsubAdd = world.onAdd(parameters, (entity) => {
|
|
26
|
+
setEntities((v) => [...v, entity]);
|
|
27
|
+
});
|
|
28
|
+
const unsubRemove = world.onRemove(parameters, (entity) => {
|
|
29
|
+
setEntities((v) => v.filter((e) => e !== entity));
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
unsubAdd();
|
|
33
|
+
unsubRemove();
|
|
34
|
+
};
|
|
35
|
+
}, [world, parameters]);
|
|
36
|
+
return entities;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ../react/src/world/world-provider.tsx
|
|
40
|
+
import { jsx } from "react/jsx-runtime";
|
|
41
|
+
function WorldProvider({ children, world }) {
|
|
42
|
+
return /* @__PURE__ */ jsx(WorldContext.Provider, { value: world, children });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ../react/src/actions/create-actions.ts
|
|
46
|
+
function createActions(actionSet) {
|
|
47
|
+
return Object.assign(
|
|
48
|
+
() => {
|
|
49
|
+
const world = useWorld();
|
|
50
|
+
return actionSet(world);
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
get: (world) => actionSet(world)
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ../react/src/hooks/use-observe.ts
|
|
59
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
60
|
+
function useObserve(entity, trait) {
|
|
61
|
+
const world = useWorld();
|
|
62
|
+
const [value, setValue] = useState2(() => {
|
|
63
|
+
if (entity.has(trait)) return entity.get(trait);
|
|
64
|
+
return void 0;
|
|
65
|
+
});
|
|
66
|
+
useEffect2(() => {
|
|
67
|
+
const unsub = world.onChange(trait, (e) => {
|
|
68
|
+
if (e === entity) setValue(e.get(trait));
|
|
69
|
+
});
|
|
70
|
+
return () => {
|
|
71
|
+
unsub();
|
|
72
|
+
};
|
|
73
|
+
}, [entity, trait]);
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ../react/src/hooks/use-entity-ref.ts
|
|
78
|
+
import { useCallback, useRef } from "react";
|
|
79
|
+
function useEntityRef(callback) {
|
|
80
|
+
const world = useWorld();
|
|
81
|
+
const entityRef = useRef(null);
|
|
82
|
+
return useCallback(
|
|
83
|
+
(node) => {
|
|
84
|
+
if (node) {
|
|
85
|
+
if (entityRef.current) entityRef.current.destroy();
|
|
86
|
+
entityRef.current = world.spawn();
|
|
87
|
+
callback(node, entityRef.current);
|
|
88
|
+
} else if (entityRef.current) {
|
|
89
|
+
entityRef.current.destroy();
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
[world]
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
WorldProvider,
|
|
97
|
+
createActions,
|
|
98
|
+
useEntityRef,
|
|
99
|
+
useObserve,
|
|
100
|
+
useQuery,
|
|
101
|
+
useWorld
|
|
102
|
+
};
|