koota 0.2.3 → 0.3.1

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/react.cjs CHANGED
@@ -3,10 +3,6 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __typeError = (msg) => {
7
- throw TypeError(msg);
8
- };
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
6
  var __export = (target, all) => {
11
7
  for (var name in all)
12
8
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -20,25 +16,11 @@ var __copyProps = (to, from, except, desc) => {
20
16
  return to;
21
17
  };
22
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
24
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
25
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
26
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
27
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
28
- var __privateWrapper = (obj, member, setter, getter) => ({
29
- set _(value) {
30
- __privateSet(obj, member, value, setter);
31
- },
32
- get _() {
33
- return __privateGet(obj, member, getter);
34
- }
35
- });
36
19
 
37
20
  // src/react.ts
38
21
  var react_exports = {};
39
22
  __export(react_exports, {
40
23
  WorldProvider: () => WorldProvider,
41
- getDefaultWorld: () => getDefaultWorld,
42
24
  useActions: () => useActions,
43
25
  useQuery: () => useQuery,
44
26
  useQueryFirst: () => useQueryFirst,
@@ -103,7 +85,7 @@ var universe = {
103
85
  cachedQueries: /* @__PURE__ */ new Map(),
104
86
  worldIndex: createWorldIndex(),
105
87
  reset: () => {
106
- universe.worlds = new Array(WORLD_ID_BITS ** 2);
88
+ universe.worlds = new Array(WORLD_ID_BITS ** 2).fill(null);
107
89
  universe.cachedQueries = /* @__PURE__ */ new Map();
108
90
  universe.worldIndex = createWorldIndex();
109
91
  }
@@ -115,9 +97,9 @@ var ModifierData = class {
115
97
  this.type = type;
116
98
  this.id = id;
117
99
  this.traits = traits;
118
- __publicField(this, "traitIds");
119
100
  this.traitIds = traits.map((trait2) => trait2[$internal].id);
120
101
  }
102
+ traitIds;
121
103
  };
122
104
 
123
105
  // ../core/src/query/utils/tracking-cursor.ts
@@ -198,8 +180,9 @@ function getRelationTrait(relation2, traitFactory, pairsMap, target) {
198
180
  }
199
181
  var getRelationTargets = (world, relation2, entity) => {
200
182
  const ctx = world[$internal];
201
- const traits = ctx.entityTraits.get(entity) || [];
183
+ const traits = ctx.entityTraits.get(entity);
202
184
  const targets = [];
185
+ if (!traits) return targets;
203
186
  for (const trait2 of traits) {
204
187
  const traitCtx = trait2[$internal];
205
188
  if (traitCtx.relation === relation2 && traitCtx.pairTarget !== Wildcard) {
@@ -231,15 +214,15 @@ var incrementWorldBitflag = (world) => {
231
214
 
232
215
  // ../core/src/trait/trait-data.ts
233
216
  var TraitData = class {
217
+ generationId;
218
+ bitflag;
219
+ trait;
220
+ store;
221
+ queries;
222
+ notQueries;
223
+ schema;
224
+ changedSubscriptions;
234
225
  constructor(world, trait2) {
235
- __publicField(this, "generationId");
236
- __publicField(this, "bitflag");
237
- __publicField(this, "trait");
238
- __publicField(this, "store");
239
- __publicField(this, "queries");
240
- __publicField(this, "notQueries");
241
- __publicField(this, "schema");
242
- __publicField(this, "changedSubscriptions");
243
226
  const ctx = world[$internal];
244
227
  const traitCtx = trait2[$internal];
245
228
  this.generationId = ctx.entityMasks.length - 1;
@@ -572,47 +555,47 @@ var getAliveEntities = (index) => {
572
555
  // ../core/src/entity/entity-methods-patch.ts
573
556
  Number.prototype.add = function(...traits) {
574
557
  const worldId = this >>> WORLD_ID_SHIFT;
575
- const world = universe.worlds[worldId];
558
+ const world = universe.worlds[worldId].deref();
576
559
  return addTrait(world, this, ...traits);
577
560
  };
578
561
  Number.prototype.remove = function(...traits) {
579
562
  const worldId = this >>> WORLD_ID_SHIFT;
580
- const world = universe.worlds[worldId];
563
+ const world = universe.worlds[worldId].deref();
581
564
  return removeTrait(world, this, ...traits);
582
565
  };
583
566
  Number.prototype.has = function(trait2) {
584
567
  const worldId = this >>> WORLD_ID_SHIFT;
585
- const world = universe.worlds[worldId];
568
+ const world = universe.worlds[worldId].deref();
586
569
  return hasTrait(world, this, trait2);
587
570
  };
588
571
  Number.prototype.destroy = function() {
589
572
  const worldId = this >>> WORLD_ID_SHIFT;
590
- const world = universe.worlds[worldId];
573
+ const world = universe.worlds[worldId].deref();
591
574
  return destroyEntity(world, this);
592
575
  };
593
576
  Number.prototype.changed = function(trait2) {
594
577
  const worldId = this >>> WORLD_ID_SHIFT;
595
- const world = universe.worlds[worldId];
578
+ const world = universe.worlds[worldId].deref();
596
579
  return setChanged(world, this, trait2);
597
580
  };
598
581
  Number.prototype.get = function(trait2) {
599
582
  const worldId = this >>> WORLD_ID_SHIFT;
600
- const world = universe.worlds[worldId];
583
+ const world = universe.worlds[worldId].deref();
601
584
  return getTrait(world, this, trait2);
602
585
  };
603
586
  Number.prototype.set = function(trait2, value, triggerChanged = true) {
604
587
  const worldId = this >>> WORLD_ID_SHIFT;
605
- const world = universe.worlds[worldId];
588
+ const world = universe.worlds[worldId].deref();
606
589
  setTrait(world, this, trait2, value, triggerChanged);
607
590
  };
608
591
  Number.prototype.targetsFor = function(relation2) {
609
592
  const worldId = this >>> WORLD_ID_SHIFT;
610
- const world = universe.worlds[worldId];
593
+ const world = universe.worlds[worldId].deref();
611
594
  return getRelationTargets(world, relation2, this);
612
595
  };
613
596
  Number.prototype.targetFor = function(relation2) {
614
597
  const worldId = this >>> WORLD_ID_SHIFT;
615
- const world = universe.worlds[worldId];
598
+ const world = universe.worlds[worldId].deref();
616
599
  return getRelationTargets(world, relation2, this)[0];
617
600
  };
618
601
  Number.prototype.id = function() {
@@ -621,7 +604,7 @@ Number.prototype.id = function() {
621
604
  };
622
605
  Number.prototype.isAlive = function() {
623
606
  const worldId = this >>> WORLD_ID_SHIFT;
624
- const world = universe.worlds[worldId];
607
+ const world = universe.worlds[worldId].deref();
625
608
  return isEntityAlive(world[$internal].entityIndex, this);
626
609
  };
627
610
 
@@ -687,57 +670,51 @@ function destroyEntity(world, entity) {
687
670
  }
688
671
 
689
672
  // ../core/src/utils/sparse-set.ts
690
- var _dense, _sparse, _cursor;
691
673
  var SparseSet = class {
692
- constructor() {
693
- __privateAdd(this, _dense, []);
694
- __privateAdd(this, _sparse, []);
695
- __privateAdd(this, _cursor, 0);
696
- }
674
+ #dense = [];
675
+ #sparse = [];
676
+ #cursor = 0;
697
677
  has(val) {
698
- const index = __privateGet(this, _sparse)[val];
699
- return index < __privateGet(this, _cursor) && __privateGet(this, _dense)[index] === val;
678
+ const index = this.#sparse[val];
679
+ return index < this.#cursor && this.#dense[index] === val;
700
680
  }
701
681
  add(val) {
702
682
  if (this.has(val)) return;
703
- __privateGet(this, _sparse)[val] = __privateGet(this, _cursor);
704
- __privateGet(this, _dense)[__privateWrapper(this, _cursor)._++] = val;
683
+ this.#sparse[val] = this.#cursor;
684
+ this.#dense[this.#cursor++] = val;
705
685
  }
706
686
  remove(val) {
707
687
  if (!this.has(val)) return;
708
- const index = __privateGet(this, _sparse)[val];
709
- __privateWrapper(this, _cursor)._--;
710
- const swapped = __privateGet(this, _dense)[__privateGet(this, _cursor)];
688
+ const index = this.#sparse[val];
689
+ this.#cursor--;
690
+ const swapped = this.#dense[this.#cursor];
711
691
  if (swapped !== val) {
712
- __privateGet(this, _dense)[index] = swapped;
713
- __privateGet(this, _sparse)[swapped] = index;
692
+ this.#dense[index] = swapped;
693
+ this.#sparse[swapped] = index;
714
694
  }
715
695
  }
716
696
  clear() {
717
- for (let i = 0; i < __privateGet(this, _cursor); i++) {
718
- __privateGet(this, _sparse)[__privateGet(this, _dense)[i]] = 0;
697
+ for (let i = 0; i < this.#cursor; i++) {
698
+ this.#sparse[this.#dense[i]] = 0;
719
699
  }
720
- __privateSet(this, _cursor, 0);
700
+ this.#cursor = 0;
721
701
  }
722
702
  sort() {
723
- __privateGet(this, _dense).sort((a, b) => a - b);
724
- for (let i = 0; i < __privateGet(this, _dense).length; i++) {
725
- __privateGet(this, _sparse)[__privateGet(this, _dense)[i]] = i;
703
+ this.#dense.sort((a, b) => a - b);
704
+ for (let i = 0; i < this.#dense.length; i++) {
705
+ this.#sparse[this.#dense[i]] = i;
726
706
  }
727
707
  }
728
708
  getIndex(val) {
729
- return __privateGet(this, _sparse)[val];
709
+ return this.#sparse[val];
730
710
  }
731
711
  get dense() {
732
- return __privateGet(this, _dense).slice(0, __privateGet(this, _cursor));
712
+ return this.#dense.slice(0, this.#cursor);
733
713
  }
734
714
  get sparse() {
735
- return __privateGet(this, _sparse);
715
+ return this.#sparse;
736
716
  }
737
717
  };
738
- _dense = new WeakMap();
739
- _sparse = new WeakMap();
740
- _cursor = new WeakMap();
741
718
 
742
719
  // ../core/src/query/utils/create-query-hash.ts
743
720
  var sortedIDs = new Float32Array(1024);
@@ -767,22 +744,22 @@ var createQueryHash = (parameters) => {
767
744
  // ../core/src/query/query.ts
768
745
  var IsExcluded = trait();
769
746
  var Query = class {
747
+ version = 0;
748
+ world;
749
+ parameters;
750
+ hash;
751
+ traits = [];
752
+ traitData = { required: [], forbidden: [], or: [], added: [], removed: [], changed: [], all: [] };
753
+ bitmasks = [];
754
+ generations;
755
+ entities = new SparseSet();
756
+ isTracking = false;
757
+ hasChangedModifiers = false;
758
+ changedTraits = /* @__PURE__ */ new Set();
759
+ toRemove = new SparseSet();
760
+ addSubscriptions = /* @__PURE__ */ new Set();
761
+ removeSubscriptions = /* @__PURE__ */ new Set();
770
762
  constructor(world, parameters = []) {
771
- __publicField(this, "version", 0);
772
- __publicField(this, "world");
773
- __publicField(this, "parameters");
774
- __publicField(this, "hash");
775
- __publicField(this, "traits", []);
776
- __publicField(this, "traitData", { required: [], forbidden: [], or: [], added: [], removed: [], changed: [], all: [] });
777
- __publicField(this, "bitmasks", []);
778
- __publicField(this, "generations");
779
- __publicField(this, "entities", new SparseSet());
780
- __publicField(this, "isTracking", false);
781
- __publicField(this, "hasChangedModifiers", false);
782
- __publicField(this, "changedTraits", /* @__PURE__ */ new Set());
783
- __publicField(this, "toRemove", new SparseSet());
784
- __publicField(this, "addSubscriptions", /* @__PURE__ */ new Set());
785
- __publicField(this, "removeSubscriptions", /* @__PURE__ */ new Set());
786
763
  this.world = world;
787
764
  this.parameters = parameters;
788
765
  const ctx = world[$internal];
@@ -1192,6 +1169,10 @@ function createQueryResult(query, world, params) {
1192
1169
  stores.length = 0;
1193
1170
  getQueryStores(params2, traits, stores, world);
1194
1171
  return results;
1172
+ },
1173
+ sort(callback = (a, b) => getEntityId(a) - getEntityId(b)) {
1174
+ Array.prototype.sort.call(entities, callback);
1175
+ return results;
1195
1176
  }
1196
1177
  });
1197
1178
  return results;
@@ -1216,50 +1197,50 @@ function getQueryStores(params, traits, stores, world) {
1216
1197
  }
1217
1198
 
1218
1199
  // ../core/src/world/world.ts
1219
- var _a, _id, _isInitialized;
1220
- _a = $internal;
1221
1200
  var World = class {
1222
- constructor(...traits) {
1223
- __privateAdd(this, _id, allocateWorldId(universe.worldIndex));
1224
- __publicField(this, _a, {
1225
- entityIndex: createEntityIndex(__privateGet(this, _id)),
1226
- entityMasks: [[]],
1227
- entityTraits: /* @__PURE__ */ new Map(),
1228
- bitflag: 1,
1229
- traitData: /* @__PURE__ */ new Map(),
1230
- queries: /* @__PURE__ */ new Set(),
1231
- queriesHashMap: /* @__PURE__ */ new Map(),
1232
- notQueries: /* @__PURE__ */ new Set(),
1233
- dirtyQueries: /* @__PURE__ */ new Set(),
1234
- relationTargetEntities: /* @__PURE__ */ new Set(),
1235
- dirtyMasks: /* @__PURE__ */ new Map(),
1236
- trackingSnapshots: /* @__PURE__ */ new Map(),
1237
- changedMasks: /* @__PURE__ */ new Map(),
1238
- worldEntity: null,
1239
- trackedTraits: /* @__PURE__ */ new Set()
1240
- });
1241
- __privateAdd(this, _isInitialized, false);
1242
- __publicField(this, "traits", /* @__PURE__ */ new Set());
1243
- this.init(...traits);
1244
- }
1201
+ #id = allocateWorldId(universe.worldIndex);
1202
+ [$internal] = {
1203
+ entityIndex: createEntityIndex(this.#id),
1204
+ entityMasks: [[]],
1205
+ entityTraits: /* @__PURE__ */ new Map(),
1206
+ bitflag: 1,
1207
+ traitData: /* @__PURE__ */ new Map(),
1208
+ queries: /* @__PURE__ */ new Set(),
1209
+ queriesHashMap: /* @__PURE__ */ new Map(),
1210
+ notQueries: /* @__PURE__ */ new Set(),
1211
+ dirtyQueries: /* @__PURE__ */ new Set(),
1212
+ relationTargetEntities: /* @__PURE__ */ new Set(),
1213
+ dirtyMasks: /* @__PURE__ */ new Map(),
1214
+ trackingSnapshots: /* @__PURE__ */ new Map(),
1215
+ changedMasks: /* @__PURE__ */ new Map(),
1216
+ worldEntity: null,
1217
+ trackedTraits: /* @__PURE__ */ new Set(),
1218
+ resetSubscriptions: /* @__PURE__ */ new Set()
1219
+ };
1245
1220
  get id() {
1246
- return __privateGet(this, _id);
1221
+ return this.#id;
1247
1222
  }
1223
+ #isInitialized = false;
1248
1224
  get isInitialized() {
1249
- return __privateGet(this, _isInitialized);
1225
+ return this.#isInitialized;
1250
1226
  }
1251
1227
  get entities() {
1252
1228
  return getAliveEntities(this[$internal].entityIndex);
1253
1229
  }
1230
+ traits = /* @__PURE__ */ new Set();
1231
+ constructor(...traits) {
1232
+ this.init(...traits);
1233
+ }
1254
1234
  init(...traits) {
1255
1235
  const ctx = this[$internal];
1256
- if (__privateGet(this, _isInitialized)) return;
1257
- __privateSet(this, _isInitialized, true);
1258
- universe.worlds[__privateGet(this, _id)] = this;
1236
+ if (this.#isInitialized) return;
1237
+ this.#isInitialized = true;
1238
+ universe.worlds[this.#id] = new WeakRef(this);
1259
1239
  const cursor2 = getTrackingCursor();
1260
1240
  for (let i = 0; i < cursor2; i++) {
1261
1241
  setTrackingMasks(this, i);
1262
1242
  }
1243
+ if (!ctx.traitData.has(IsExcluded)) registerTrait(this, IsExcluded);
1263
1244
  for (const [hash, parameters] of universe.cachedQueries) {
1264
1245
  const query = new Query(this, parameters);
1265
1246
  ctx.queriesHashMap.set(hash, query);
@@ -1289,15 +1270,15 @@ var World = class {
1289
1270
  this[$internal].worldEntity = null;
1290
1271
  this.entities.forEach((entity) => destroyEntity(this, entity));
1291
1272
  this.reset();
1292
- __privateSet(this, _isInitialized, false);
1293
- releaseWorldId(universe.worldIndex, __privateGet(this, _id));
1294
- universe.worlds.splice(universe.worlds.indexOf(this), 1);
1273
+ this.#isInitialized = false;
1274
+ releaseWorldId(universe.worldIndex, this.#id);
1275
+ universe.worlds[this.#id] = null;
1295
1276
  }
1296
1277
  reset() {
1297
1278
  const ctx = this[$internal];
1298
- ctx.entityIndex = createEntityIndex(__privateGet(this, _id));
1279
+ this.entities.forEach((entity) => destroyEntity(this, entity));
1280
+ ctx.entityIndex = createEntityIndex(this.#id);
1299
1281
  ctx.entityTraits.clear();
1300
- ctx.notQueries.clear();
1301
1282
  ctx.entityMasks = [[]];
1302
1283
  ctx.bitflag = 1;
1303
1284
  ctx.traitData.clear();
@@ -1305,12 +1286,16 @@ var World = class {
1305
1286
  ctx.queries.clear();
1306
1287
  ctx.queriesHashMap.clear();
1307
1288
  ctx.dirtyQueries.clear();
1289
+ ctx.notQueries.clear();
1308
1290
  ctx.relationTargetEntities.clear();
1309
1291
  ctx.trackingSnapshots.clear();
1310
1292
  ctx.dirtyMasks.clear();
1311
1293
  ctx.changedMasks.clear();
1312
1294
  ctx.trackedTraits.clear();
1313
1295
  ctx.worldEntity = createEntity(this, IsExcluded);
1296
+ for (const sub of ctx.resetSubscriptions) {
1297
+ sub(this);
1298
+ }
1314
1299
  }
1315
1300
  query(...args) {
1316
1301
  const ctx = this[$internal];
@@ -1362,21 +1347,21 @@ var World = class {
1362
1347
  ctx.trackedTraits.add(trait2);
1363
1348
  return () => {
1364
1349
  data.changedSubscriptions.delete(callback);
1365
- ctx.trackedTraits.delete(trait2);
1350
+ if (data.changedSubscriptions.size === 0) ctx.trackedTraits.delete(trait2);
1366
1351
  };
1367
1352
  }
1368
1353
  };
1369
- _id = new WeakMap();
1370
- _isInitialized = new WeakMap();
1371
- function createWorld(...traits) {
1372
- return new World(...traits);
1373
- }
1354
+ var worldFinalizer = new FinalizationRegistry((worldId) => {
1355
+ universe.worlds[worldId] = null;
1356
+ releaseWorldId(universe.worldIndex, worldId);
1357
+ });
1374
1358
 
1375
1359
  // ../core/src/query/utils/cache-query.ts
1376
1360
  function cacheQuery(...parameters) {
1377
1361
  const hash = createQueryHash(parameters);
1378
- for (const world of universe.worlds) {
1379
- if (!world) continue;
1362
+ for (const worldRef of universe.worlds) {
1363
+ if (!worldRef) continue;
1364
+ const world = worldRef.deref();
1380
1365
  const ctx = world[$internal];
1381
1366
  if (!ctx.queriesHashMap.has(hash)) {
1382
1367
  const query = new Query(world, parameters);
@@ -1387,6 +1372,9 @@ function cacheQuery(...parameters) {
1387
1372
  return hash;
1388
1373
  }
1389
1374
 
1375
+ // ../core/src/query/types.ts
1376
+ var $parameters = Symbol();
1377
+
1390
1378
  // ../react/src/hooks/use-query.ts
1391
1379
  var import_react3 = require("react");
1392
1380
 
@@ -1397,41 +1385,48 @@ var import_react2 = require("react");
1397
1385
  var import_react = require("react");
1398
1386
  var WorldContext = (0, import_react.createContext)(null);
1399
1387
 
1400
- // ../react/src/world/default-world.ts
1401
- var defaultWorld = createWorld();
1402
- var getDefaultWorld = () => defaultWorld;
1403
-
1404
1388
  // ../react/src/world/use-world.ts
1405
1389
  function useWorld() {
1406
- const world = (0, import_react2.useContext)(WorldContext) ?? defaultWorld;
1390
+ const world = (0, import_react2.useContext)(WorldContext);
1391
+ if (!world) {
1392
+ throw new Error("Koota: useWorld must be used within a WorldProvider");
1393
+ }
1407
1394
  return world;
1408
1395
  }
1409
1396
 
1410
1397
  // ../react/src/hooks/use-query.ts
1411
1398
  function useQuery(...parameters) {
1412
1399
  const world = useWorld();
1413
- const [hash, initialVersion] = (0, import_react3.useMemo)(() => {
1400
+ const [version, setVersion] = (0, import_react3.useState)(0);
1401
+ const [hash, initialQueryVersion] = (0, import_react3.useMemo)(() => {
1414
1402
  const hash2 = cacheQuery(...parameters);
1415
1403
  const query = world[$internal].queriesHashMap.get(hash2);
1416
1404
  return [hash2, query.version];
1417
- }, [parameters]);
1418
- const [entities, setEntities] = (0, import_react3.useState)(() => world.query(hash));
1405
+ }, [parameters, world]);
1406
+ const [entities, setEntities] = (0, import_react3.useState)(() => world.query(hash).sort());
1419
1407
  (0, import_react3.useEffect)(() => {
1420
1408
  const unsubAdd = world.onAdd(parameters, () => {
1421
- setEntities(world.query(hash));
1409
+ setEntities(world.query(hash).sort());
1422
1410
  });
1423
1411
  const unsubRemove = world.onRemove(parameters, () => {
1424
- setEntities(world.query(hash));
1412
+ setEntities(world.query(hash).sort());
1425
1413
  });
1426
1414
  const query = world[$internal].queriesHashMap.get(hash);
1427
- if (query.version !== initialVersion) {
1428
- setEntities(world.query(hash));
1415
+ if (query.version !== initialQueryVersion) {
1416
+ setEntities(world.query(hash).sort());
1429
1417
  }
1430
1418
  return () => {
1431
1419
  unsubAdd();
1432
1420
  unsubRemove();
1433
1421
  };
1434
- }, [world, hash]);
1422
+ }, [world, hash, version]);
1423
+ (0, import_react3.useEffect)(() => {
1424
+ const handler = () => setVersion((v) => v + 1);
1425
+ world[$internal].resetSubscriptions.add(handler);
1426
+ return () => {
1427
+ world[$internal].resetSubscriptions.delete(handler);
1428
+ };
1429
+ }, [world]);
1435
1430
  return entities;
1436
1431
  }
1437
1432
 
@@ -1532,7 +1527,6 @@ function useTraitEffect(target, trait2, callback) {
1532
1527
  // Annotate the CommonJS export names for ESM import in node:
1533
1528
  0 && (module.exports = {
1534
1529
  WorldProvider,
1535
- getDefaultWorld,
1536
1530
  useActions,
1537
1531
  useQuery,
1538
1532
  useQueryFirst,
package/dist/react.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Q as QueryParameter, o as QueryResult, W as World, T as Trait, k as Entity, g as TraitInstance } from './world-CHO2npCL.cjs';
1
+ import { Q as QueryParameter, p as QueryResult, W as World, T as Trait, l as Entity, h as TraitInstance } from './world-BYe3z9dR.cjs';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
4
  declare function useQuery<T extends QueryParameter[]>(...parameters: T): QueryResult<T>;
@@ -18,6 +18,4 @@ declare function useQueryFirst<T extends QueryParameter[]>(...parameters: T): En
18
18
 
19
19
  declare function useTraitEffect<T extends Trait>(target: Entity | World, trait: T, callback: (value: TraitInstance<T> | undefined) => void): void;
20
20
 
21
- declare const getDefaultWorld: () => World;
22
-
23
- export { WorldProvider, getDefaultWorld, useActions, useQuery, useQueryFirst, useTrait, useTraitEffect, useWorld };
21
+ export { WorldProvider, useActions, useQuery, useQueryFirst, useTrait, useTraitEffect, useWorld };
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Q as QueryParameter, o as QueryResult, W as World, T as Trait, k as Entity, g as TraitInstance } from './world-CHO2npCL.js';
1
+ import { Q as QueryParameter, p as QueryResult, W as World, T as Trait, l as Entity, h as TraitInstance } from './world-BYe3z9dR.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
4
  declare function useQuery<T extends QueryParameter[]>(...parameters: T): QueryResult<T>;
@@ -18,6 +18,4 @@ declare function useQueryFirst<T extends QueryParameter[]>(...parameters: T): En
18
18
 
19
19
  declare function useTraitEffect<T extends Trait>(target: Entity | World, trait: T, callback: (value: TraitInstance<T> | undefined) => void): void;
20
20
 
21
- declare const getDefaultWorld: () => World;
22
-
23
- export { WorldProvider, getDefaultWorld, useActions, useQuery, useQueryFirst, useTrait, useTraitEffect, useWorld };
21
+ export { WorldProvider, useActions, useQuery, useQueryFirst, useTrait, useTraitEffect, useWorld };
package/dist/react.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  $internal,
3
- cacheQuery,
4
- createWorld
5
- } from "./chunk-ZHBGFPP2.js";
3
+ cacheQuery
4
+ } from "./chunk-OAPTAVXT.js";
6
5
 
7
6
  // ../react/src/hooks/use-query.ts
8
7
  import { useEffect, useMemo, useState } from "react";
@@ -14,41 +13,48 @@ import { useContext } from "react";
14
13
  import { createContext } from "react";
15
14
  var WorldContext = createContext(null);
16
15
 
17
- // ../react/src/world/default-world.ts
18
- var defaultWorld = createWorld();
19
- var getDefaultWorld = () => defaultWorld;
20
-
21
16
  // ../react/src/world/use-world.ts
22
17
  function useWorld() {
23
- const world = useContext(WorldContext) ?? defaultWorld;
18
+ const world = useContext(WorldContext);
19
+ if (!world) {
20
+ throw new Error("Koota: useWorld must be used within a WorldProvider");
21
+ }
24
22
  return world;
25
23
  }
26
24
 
27
25
  // ../react/src/hooks/use-query.ts
28
26
  function useQuery(...parameters) {
29
27
  const world = useWorld();
30
- const [hash, initialVersion] = useMemo(() => {
28
+ const [version, setVersion] = useState(0);
29
+ const [hash, initialQueryVersion] = useMemo(() => {
31
30
  const hash2 = cacheQuery(...parameters);
32
31
  const query = world[$internal].queriesHashMap.get(hash2);
33
32
  return [hash2, query.version];
34
- }, [parameters]);
35
- const [entities, setEntities] = useState(() => world.query(hash));
33
+ }, [parameters, world]);
34
+ const [entities, setEntities] = useState(() => world.query(hash).sort());
36
35
  useEffect(() => {
37
36
  const unsubAdd = world.onAdd(parameters, () => {
38
- setEntities(world.query(hash));
37
+ setEntities(world.query(hash).sort());
39
38
  });
40
39
  const unsubRemove = world.onRemove(parameters, () => {
41
- setEntities(world.query(hash));
40
+ setEntities(world.query(hash).sort());
42
41
  });
43
42
  const query = world[$internal].queriesHashMap.get(hash);
44
- if (query.version !== initialVersion) {
45
- setEntities(world.query(hash));
43
+ if (query.version !== initialQueryVersion) {
44
+ setEntities(world.query(hash).sort());
46
45
  }
47
46
  return () => {
48
47
  unsubAdd();
49
48
  unsubRemove();
50
49
  };
51
- }, [world, hash]);
50
+ }, [world, hash, version]);
51
+ useEffect(() => {
52
+ const handler = () => setVersion((v) => v + 1);
53
+ world[$internal].resetSubscriptions.add(handler);
54
+ return () => {
55
+ world[$internal].resetSubscriptions.delete(handler);
56
+ };
57
+ }, [world]);
52
58
  return entities;
53
59
  }
54
60
 
@@ -148,7 +154,6 @@ function useTraitEffect(target, trait, callback) {
148
154
  }
149
155
  export {
150
156
  WorldProvider,
151
- getDefaultWorld,
152
157
  useActions,
153
158
  useQuery,
154
159
  useQueryFirst,
@@ -138,6 +138,7 @@ type QueryResult<T extends QueryParameter[] = QueryParameter[]> = readonly Entit
138
138
  updateEach: (callback: (state: InstancesFromParameters<T>, entity: Entity, index: number) => void, options?: QueryResultOptions) => QueryResult<T>;
139
139
  useStores: (callback: (stores: StoresFromParameters<T>, entities: readonly Entity[]) => void) => QueryResult<T>;
140
140
  select<U extends QueryParameter[]>(...params: U): QueryResult<U>;
141
+ sort(callback?: (a: Entity, b: Entity) => number): QueryResult<T>;
141
142
  };
142
143
  type UnwrapModifierData<T> = T extends ModifierData<infer C> ? C : never;
143
144
  type StoresFromParameters<T extends QueryParameter[]> = T extends [infer First, ...infer Rest] ? [
@@ -152,6 +153,10 @@ type InstancesFromParameters<T extends QueryParameter[]> = T extends [
152
153
  ...(Rest extends QueryParameter[] ? InstancesFromParameters<Rest> : [])
153
154
  ] : [];
154
155
  type IsNotModifier<T> = T extends ModifierData<any, infer TType> ? TType extends 'not' ? true : false : false;
156
+ declare const $parameters: unique symbol;
157
+ type QueryHash<T extends QueryParameter[]> = string & {
158
+ readonly [$parameters]: T;
159
+ };
155
160
 
156
161
  declare class Query {
157
162
  version: number;
@@ -217,6 +222,7 @@ declare class World {
217
222
  changedMasks: Map<number, number[][]>;
218
223
  worldEntity: Entity;
219
224
  trackedTraits: Set<Trait>;
225
+ resetSubscriptions: Set<(world: World) => void>;
220
226
  };
221
227
  get id(): number;
222
228
  get isInitialized(): boolean;
@@ -233,7 +239,7 @@ declare class World {
233
239
  set<T extends Trait>(trait: T, value: TraitValue<ExtractSchema<T>>): void;
234
240
  destroy(): void;
235
241
  reset(): void;
236
- query<T extends QueryParameter[]>(key: string): QueryResult<T>;
242
+ query<T extends QueryParameter[]>(key: QueryHash<T>): QueryResult<T>;
237
243
  query<T extends QueryParameter[]>(...parameters: T): QueryResult<T>;
238
244
  queryFirst(key: string): Entity | undefined;
239
245
  queryFirst(...parameters: QueryParameter[]): Entity | undefined;
@@ -243,4 +249,4 @@ declare class World {
243
249
  }
244
250
  declare function createWorld(...traits: ConfigurableTrait[]): World;
245
251
 
246
- export { $internal as $, type AoSFactory as A, type ConfigurableTrait as C, type ExtractSchema as E, type IsTag as I, ModifierData as M, type Norm as N, type QueryParameter as Q, type Relation as R, type Schema as S, type Trait as T, World as W, type RelationTarget as a, type WildcardRelation as b, createWorld as c, type TraitType as d, type TraitValue as e, type TraitTuple as f, type TraitInstance as g, type Store as h, type ExtractStore as i, type ExtractIsTag as j, type Entity as k, type QueryModifier as l, type QuerySubscriber as m, type QueryResultOptions as n, type QueryResult as o, type StoresFromParameters as p, type InstancesFromParameters as q, type IsNotModifier as r };
252
+ export { $internal as $, type AoSFactory as A, type ConfigurableTrait as C, type ExtractSchema as E, type IsTag as I, ModifierData as M, type Norm as N, type QueryParameter as Q, type Relation as R, type Schema as S, type Trait as T, World as W, type QueryHash as a, type RelationTarget as b, type WildcardRelation as c, createWorld as d, type TraitType as e, type TraitValue as f, type TraitTuple as g, type TraitInstance as h, type Store as i, type ExtractStore as j, type ExtractIsTag as k, type Entity as l, type QueryModifier as m, type QuerySubscriber as n, type QueryResultOptions as o, type QueryResult as p, type StoresFromParameters as q, type InstancesFromParameters as r, type IsNotModifier as s };