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 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, store], entities) => {
334
+ world.query(Position, Velocity).useStore(([position, velocity], entities) => {
328
335
  // Write our own loop over the stores
329
- for (let i = 0; i > entities.length; 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 = data.schema;
301
- for (const key in defaults) {
302
- if (typeof defaults[key] === "function") {
303
- defaults[key] = 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 = data.schema;
262
- for (const key in defaults) {
263
- if (typeof defaults[key] === "function") {
264
- defaults[key] = 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/query/use-query.ts
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/query/use-query.ts
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/trait/use-observe.tsx
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, W as World, T as Trait, j as Entity, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.cjs';
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[]): number[];
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
- export { WorldProvider, createActions, useObserve, useQuery, useWorld };
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, W as World, T as Trait, j as Entity, d as TraitInstanceFromSchema, E as ExtractSchema } from './world-BRz2NI5_.js';
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[]): number[];
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
- export { WorldProvider, createActions, useObserve, useQuery, useWorld };
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/query/use-query.ts
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/query/use-query.ts
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/trait/use-observe.tsx
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",
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": "./dist/index.d.ts",
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": "./dist/react.d.ts",
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
  }
@@ -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 };
@@ -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
+ };