tinybase 4.3.23 → 4.4.0-beta.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.
Files changed (41) hide show
  1. package/lib/cjs/store.cjs +1 -1
  2. package/lib/cjs/store.cjs.gz +0 -0
  3. package/lib/cjs/tinybase.cjs +1 -1
  4. package/lib/cjs/tinybase.cjs.gz +0 -0
  5. package/lib/cjs/ui-react-dom-debug.cjs +1 -1
  6. package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
  7. package/lib/cjs-es6/store.cjs +1 -1
  8. package/lib/cjs-es6/store.cjs.gz +0 -0
  9. package/lib/cjs-es6/tinybase.cjs +1 -1
  10. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  11. package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
  12. package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
  13. package/lib/debug/store.js +112 -25
  14. package/lib/debug/tinybase.js +112 -25
  15. package/lib/debug/ui-react-dom.js +112 -25
  16. package/lib/es6/store.js +1 -1
  17. package/lib/es6/store.js.gz +0 -0
  18. package/lib/es6/tinybase.js +1 -1
  19. package/lib/es6/tinybase.js.gz +0 -0
  20. package/lib/es6/ui-react-dom-debug.js +1 -1
  21. package/lib/es6/ui-react-dom-debug.js.gz +0 -0
  22. package/lib/store.js +1 -1
  23. package/lib/store.js.gz +0 -0
  24. package/lib/tinybase.js +1 -1
  25. package/lib/tinybase.js.gz +0 -0
  26. package/lib/types/store.d.ts +911 -31
  27. package/lib/types/with-schemas/store.d.ts +1179 -35
  28. package/lib/umd/store.js +1 -1
  29. package/lib/umd/store.js.gz +0 -0
  30. package/lib/umd/tinybase.js +1 -1
  31. package/lib/umd/tinybase.js.gz +0 -0
  32. package/lib/umd/ui-react-dom-debug.js +1 -1
  33. package/lib/umd/ui-react-dom-debug.js.gz +0 -0
  34. package/lib/umd-es6/store.js +1 -1
  35. package/lib/umd-es6/store.js.gz +0 -0
  36. package/lib/umd-es6/tinybase.js +1 -1
  37. package/lib/umd-es6/tinybase.js.gz +0 -0
  38. package/lib/umd-es6/ui-react-dom-debug.js +1 -1
  39. package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
  40. package/package.json +4 -4
  41. package/readme.md +13 -13
@@ -846,9 +846,35 @@ export type TransactionListener<Schemas extends OptionalSchemas> = (
846
846
  getTransactionLog: GetTransactionLog<Schemas>,
847
847
  ) => void;
848
848
 
849
+ /**
850
+ * The HasTablesListener type describes a function that is used to listen to
851
+ * Tables as a whole being added to or removed from the Store.
852
+ *
853
+ * This has schema-based typing. The following is a simplified representation:
854
+ *
855
+ * ```ts override
856
+ * (store: Store, hasTables: boolean) => void;
857
+ * ```
858
+ *
859
+ * A HasTablesListener is provided when using the addHasTablesListener method.
860
+ * See that method for specific examples.
861
+ *
862
+ * When called, a HasTablesListener is given a reference to the Store. It is
863
+ * also given a flag to indicate whether Tables now exist (having not done
864
+ * previously), or do not (having done so previously).
865
+ * @param store A reference to the Store that changed.
866
+ * @param hasTables Whether Tables now exist or not.
867
+ * @category Listener
868
+ * @since v4.4.0
869
+ */
870
+ export type HasTablesListener<Schemas extends OptionalSchemas> = (
871
+ store: Store<Schemas>,
872
+ hasTables: boolean,
873
+ ) => void;
874
+
849
875
  /**
850
876
  * The TablesListener type describes a function that is used to listen to
851
- * changes to the whole Store.
877
+ * changes to the tabular part of the Store.
852
878
  *
853
879
  * This has schema-based typing. The following is a simplified representation:
854
880
  *
@@ -909,6 +935,44 @@ export type TableIdsListener<Schemas extends OptionalSchemas> = (
909
935
  getIdChanges: GetIdChanges<TableIdFromSchema<Schemas[0]>> | undefined,
910
936
  ) => void;
911
937
 
938
+ /**
939
+ * The HasTableListener type describes a function that is used to listen to a
940
+ * Table being added to or removed from the Store.
941
+ *
942
+ * This has schema-based typing. The following is a simplified representation:
943
+ *
944
+ * ```ts override
945
+ * (
946
+ * store: Store,
947
+ * tableId: Id,
948
+ * hasTable: boolean,
949
+ * ) => void;
950
+ * ```
951
+ *
952
+ * A HasTableListener is provided when using the addHasTableListener method. See
953
+ * that method for specific examples.
954
+ *
955
+ * When called, a HasTableListener is given a reference to the Store, and the Id
956
+ * of the Table that changed. It is also given a flag to indicate whether the
957
+ * Table now exists (having not done previously), or does not (having done so
958
+ * previously).
959
+ * @param store A reference to the Store that changed.
960
+ * @param tableId The Id of the Table that changed.
961
+ * @param hasTable Whether the Table now exists or not.
962
+ * @category Listener
963
+ * @since v4.4.0
964
+ */
965
+ export type HasTableListener<
966
+ Schemas extends OptionalSchemas,
967
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
968
+ > = (
969
+ store: Store<Schemas>,
970
+ tableId: TableIdOrNull extends null
971
+ ? TableIdFromSchema<Schemas[0]>
972
+ : TableIdOrNull,
973
+ hasTable: boolean,
974
+ ) => void;
975
+
912
976
  /**
913
977
  * The TableListener type describes a function that is used to listen to changes
914
978
  * to a Table.
@@ -1000,6 +1064,75 @@ export type TableCellIdsListener<
1000
1064
  : // | ((...params: Params1) => void)
1001
1065
  never;
1002
1066
 
1067
+ /**
1068
+ * The HasTableCellListener type describes a function that is used to listen to
1069
+ * a Cell being added to or removed from a Table as a whole.
1070
+ *
1071
+ * This has schema-based typing. The following is a simplified representation:
1072
+ *
1073
+ * ```ts override
1074
+ * (
1075
+ * store: Store,
1076
+ * tableId: Id,
1077
+ * cellId: Id,
1078
+ * hasTableCell: boolean,
1079
+ * ) => void;
1080
+ * ```
1081
+ *
1082
+ * A HasTableCellListener is provided when using the addHasTableCellListener
1083
+ * method. See that method for specific examples.
1084
+ *
1085
+ * When called, a HasTableCellListener is given a reference to the Store, the Id
1086
+ * of the Table that changed, and the Id of the Cell that changed. It is also
1087
+ * given a flag to indicate whether the Cell now exists anywhere in the Table
1088
+ * (having not done previously), or does not (having done so previously).
1089
+ * @param store A reference to the Store that changed.
1090
+ * @param tableId The Id of the Table that changed.
1091
+ * @param cellId The Id of the Table Cell that changed.
1092
+ * @param hasTableCell Whether the Cell now exists anywhere in the Table or not.
1093
+ * @category Listener
1094
+ * @since v4.4.0
1095
+ */
1096
+ export type HasTableCellListener<
1097
+ Schemas extends OptionalSchemas,
1098
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
1099
+ CellIdOrNull extends
1100
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
1101
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
1102
+ : AllCellIdFromSchema<Schemas[0]>)
1103
+ | null,
1104
+ Params extends any[] = (
1105
+ TableIdOrNull extends null ? TableIdFromSchema<Schemas[0]> : TableIdOrNull
1106
+ ) extends infer TableId
1107
+ ? TableId extends TableIdFromSchema<Schemas[0]>
1108
+ ? (
1109
+ CellIdOrNull extends null
1110
+ ? CellIdFromSchema<Schemas[0], TableId>
1111
+ : CellIdOrNull
1112
+ ) extends infer CellId
1113
+ ? CellId extends CellIdFromSchema<Schemas[0], TableId>
1114
+ ? [
1115
+ store: Store<Schemas>,
1116
+ tableId: TableId,
1117
+ cellId: CellId,
1118
+ hasTableCell: boolean,
1119
+ ]
1120
+ : never
1121
+ : never
1122
+ : never
1123
+ : never,
1124
+ Params4 extends any[] =
1125
+ | Params
1126
+ | [store: never, tableId: never, cellId: never, hasTableCell: never],
1127
+ Params3 extends any[] = Truncate<Params4>,
1128
+ // Params2 extends any[] = Truncate<Params3>,
1129
+ // Params1 extends any[] = Truncate<Params2>,
1130
+ > = Params extends any
1131
+ ? ((...params: Params4) => void) | ((...params: Params3) => void)
1132
+ : // | ((...params: Params2) => void)
1133
+ // | ((...params: Params1) => void)
1134
+ never;
1135
+
1003
1136
  /**
1004
1137
  * The RowCountListener type describes a function that is used to listen to
1005
1138
  * changes to the number of Row objects in a Table.
@@ -1129,6 +1262,48 @@ export type SortedRowIdsListener<
1129
1262
  sortedRowIds: Ids,
1130
1263
  ) => void;
1131
1264
 
1265
+ /**
1266
+ * The HasRowListener type describes a function that is used to listen to a Row
1267
+ * being added to or removed from the Store.
1268
+ *
1269
+ * This has schema-based typing. The following is a simplified representation:
1270
+ *
1271
+ * ```ts override
1272
+ * (
1273
+ * store: Store,
1274
+ * tableId: Id,
1275
+ * rowId: Id,
1276
+ * hasRow: boolean,
1277
+ * ) => void;
1278
+ * ```
1279
+ *
1280
+ * A HasRowListener is provided when using the addHasRowListener method. See
1281
+ * that method for specific examples.
1282
+ *
1283
+ * When called, a HasRowListener is given a reference to the Store, the Id of
1284
+ * the Table that changed, and the Id of the Row that changed. It is also given
1285
+ * a flag to indicate whether the Row now exists (having not done previously),
1286
+ * or does not (having done so previously).
1287
+ * @param store A reference to the Store that changed.
1288
+ * @param tableId The Id of the Table that changed.
1289
+ * @param rowId The Id of the Row that changed.
1290
+ * @param hasRow Whether the Row now exists or not.
1291
+ * @category Listener
1292
+ * @since v4.4.0
1293
+ */
1294
+ export type HasRowListener<
1295
+ Schemas extends OptionalSchemas,
1296
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
1297
+ RowIdOrNull extends IdOrNull,
1298
+ > = (
1299
+ store: Store<Schemas>,
1300
+ tableId: TableIdOrNull extends null
1301
+ ? TableIdFromSchema<Schemas[0]>
1302
+ : TableIdOrNull,
1303
+ rowId: RowIdOrNull extends null ? Id : RowIdOrNull,
1304
+ hasRow: boolean,
1305
+ ) => void;
1306
+
1132
1307
  /**
1133
1308
  * The RowListener type describes a function that is used to listen to changes
1134
1309
  * to a Row.
@@ -1233,6 +1408,89 @@ export type CellIdsListener<
1233
1408
  // | ((...params: Params1) => void)
1234
1409
  never;
1235
1410
 
1411
+ /**
1412
+ * The HasCellListener type describes a function that is used to listen to a
1413
+ * Cell being added to or removed from the Store.
1414
+ *
1415
+ * This has schema-based typing. The following is a simplified representation:
1416
+ *
1417
+ * ```ts override
1418
+ * (
1419
+ * store: Store,
1420
+ * tableId: Id,
1421
+ * rowId: Id,
1422
+ * cellId: Id,
1423
+ * hasCell: boolean,
1424
+ * ) => void;
1425
+ * ```
1426
+ *
1427
+ * A HasCellListener is provided when using the addHasCellListener method. See
1428
+ * that method for specific examples.
1429
+ *
1430
+ * When called, a HasCellListener is given a reference to the Store, the Id of
1431
+ * the Table that changed, the Id of the Row that changed, and the Id of Cell
1432
+ * that changed. It is also given a flag to indicate whether the Cell now exists
1433
+ * (having not done previously), or does not (having done so previously).
1434
+ * @param store A reference to the Store that changed.
1435
+ * @param tableId The Id of the Table that changed.
1436
+ * @param rowId The Id of the Row that changed.
1437
+ * @param cellId The Id of the Cell that changed.
1438
+ * @param hasCell Whether the Cell now exists or not.
1439
+ * @category Listener
1440
+ * @since v4.4.0
1441
+ */
1442
+ export type HasCellListener<
1443
+ Schemas extends OptionalSchemas,
1444
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
1445
+ RowIdOrNull extends IdOrNull,
1446
+ CellIdOrNull extends
1447
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
1448
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
1449
+ : AllCellIdFromSchema<Schemas[0]>)
1450
+ | null,
1451
+ Params extends any[] = (
1452
+ TableIdOrNull extends null ? TableIdFromSchema<Schemas[0]> : TableIdOrNull
1453
+ ) extends infer TableId
1454
+ ? TableId extends TableIdFromSchema<Schemas[0]>
1455
+ ? (
1456
+ CellIdOrNull extends null
1457
+ ? CellIdFromSchema<Schemas[0], TableId>
1458
+ : CellIdOrNull
1459
+ ) extends infer CellId
1460
+ ? CellId extends CellIdFromSchema<Schemas[0], TableId>
1461
+ ? [
1462
+ store: Store<Schemas>,
1463
+ tableId: TableId,
1464
+ rowId: RowIdOrNull extends null ? Id : RowIdOrNull,
1465
+ cellId: CellId,
1466
+ hasCell: boolean,
1467
+ ]
1468
+ : never
1469
+ : never
1470
+ : never
1471
+ : never,
1472
+ Params5 extends any[] =
1473
+ | Params
1474
+ | [
1475
+ store: never,
1476
+ tableId: never,
1477
+ rowId: never,
1478
+ cellId: never,
1479
+ hasCell: boolean,
1480
+ ],
1481
+ Params4 extends any[] = Truncate<Params5>,
1482
+ // Params3 extends any[] = Truncate<Params4>,
1483
+ // Params2 extends any[] = Truncate<Params3>,
1484
+ // Params1 extends any[] = Truncate<Params2>,
1485
+ > = Params extends any
1486
+ ? ((...params: Params5) => void) | ((...params: Params4) => void)
1487
+ : // | ((...params: Params3) => void)
1488
+ // | ((...params: Params2) => void)
1489
+ // | ((...params: Params1) => void)
1490
+ // The unions may no longer be discriminatory with fewer parameters, and
1491
+ // TypeScript fails to resolve callback signatures in some cases.
1492
+ never;
1493
+
1236
1494
  /**
1237
1495
  * The CellListener type describes a function that is used to listen to changes
1238
1496
  * to a Cell.
@@ -1336,6 +1594,32 @@ export type CellListener<
1336
1594
  // | ((...params: Params1) => void)
1337
1595
  never;
1338
1596
 
1597
+ /**
1598
+ * The HasValuesListener type describes a function that is used to listen to
1599
+ * Values as a whole being added to or removed from the Store.
1600
+ *
1601
+ * This has schema-based typing. The following is a simplified representation:
1602
+ *
1603
+ * ```ts override
1604
+ * (store: Store, hasValues: boolean) => void;
1605
+ * ```
1606
+ *
1607
+ * A HasValuesListener is provided when using the addHasValuesListener method.
1608
+ * See that method for specific examples.
1609
+ *
1610
+ * When called, a HasValuesListener is given a reference to the Store. It is
1611
+ * also given a flag to indicate whether Values now exist (having not done
1612
+ * previously), or do not (having done so previously).
1613
+ * @param store A reference to the Store that changed.
1614
+ * @param hasValues Whether Values now exist or not.
1615
+ * @category Listener
1616
+ * @since v4.4.0
1617
+ */
1618
+ export type HasValuesListener<Schemas extends OptionalSchemas> = (
1619
+ store: Store<Schemas>,
1620
+ hasValues: boolean,
1621
+ ) => void;
1622
+
1339
1623
  /**
1340
1624
  * The ValuesListener type describes a function that is used to listen to
1341
1625
  * changes to all the Values in a Store.
@@ -1399,6 +1683,44 @@ export type ValueIdsListener<Schemas extends OptionalSchemas> = (
1399
1683
  getIdChanges: GetIdChanges<ValueIdFromSchema<Schemas[1]>> | undefined,
1400
1684
  ) => void;
1401
1685
 
1686
+ /**
1687
+ * The HasValueListener type describes a function that is used to listen to a
1688
+ * Value being added to or removed from the Store.
1689
+ *
1690
+ * This has schema-based typing. The following is a simplified representation:
1691
+ *
1692
+ * ```ts override
1693
+ * (
1694
+ * store: Store,
1695
+ * valueId: Id,
1696
+ * hasValue: boolean,
1697
+ * ) => void;
1698
+ * ```
1699
+ *
1700
+ * A HasValueListener is provided when using the addHasValueListener method. See
1701
+ * that method for specific examples.
1702
+ *
1703
+ * When called, a HasValueListener is given a reference to the Store and the Id
1704
+ * of Value that changed. It is also given a flag to indicate whether the Value
1705
+ * now exists (having not done previously), or does not (having done so
1706
+ * previously).
1707
+ * @param store A reference to the Store that changed.
1708
+ * @param valueId The Id of the Value that changed.
1709
+ * @param hasValue Whether the Value now exists or not.
1710
+ * @category Listener
1711
+ * @since v4.4.0
1712
+ */
1713
+ export type HasValueListener<
1714
+ Schemas extends OptionalSchemas,
1715
+ ValueIdOrNull extends ValueIdFromSchema<Schemas[1]> | null,
1716
+ > = (
1717
+ store: Store<Schemas>,
1718
+ valueId: ValueIdOrNull extends null
1719
+ ? ValueIdFromSchema<Schemas[1]>
1720
+ : ValueIdOrNull,
1721
+ hasValue: boolean,
1722
+ ) => void;
1723
+
1402
1724
  /**
1403
1725
  * The ValueListener type describes a function that is used to listen to changes
1404
1726
  * to a Value.
@@ -1982,6 +2304,11 @@ export type GetTransactionLog<Schemas extends OptionalSchemas> =
1982
2304
  * @category Development
1983
2305
  */
1984
2306
  export type StoreListenerStats = {
2307
+ /**
2308
+ * The number of HasTablesListener functions registered with the Store, since
2309
+ * v4.4.
2310
+ */
2311
+ hasTables?: number;
1985
2312
  /**
1986
2313
  * The number of TablesListener functions registered with the Store.
1987
2314
  */
@@ -1990,6 +2317,11 @@ export type StoreListenerStats = {
1990
2317
  * The number of TableIdsListener functions registered with the Store.
1991
2318
  */
1992
2319
  tableIds?: number;
2320
+ /**
2321
+ * The number of HasTableListener functions registered with the Store, since
2322
+ * v4.4.
2323
+ */
2324
+ hasTable?: number;
1993
2325
  /**
1994
2326
  * The number of TableListener functions registered with the Store.
1995
2327
  */
@@ -1999,6 +2331,11 @@ export type StoreListenerStats = {
1999
2331
  * since v3.3.
2000
2332
  */
2001
2333
  tableCellIds?: number;
2334
+ /**
2335
+ * The number of HasTableCellListener functions registered with the Store,
2336
+ * since v4.4.
2337
+ */
2338
+ hasTableCell?: number;
2002
2339
  /**
2003
2340
  * The number of RowCountListener functions registered with the Store, since
2004
2341
  * v4.1.0
@@ -2012,6 +2349,11 @@ export type StoreListenerStats = {
2012
2349
  * The number of SortedRowIdsListener functions registered with the Store.
2013
2350
  */
2014
2351
  sortedRowIds?: number;
2352
+ /**
2353
+ * The number of HasRowListener functions registered with the Store, since
2354
+ * v4.4.
2355
+ */
2356
+ hasRow?: number;
2015
2357
  /**
2016
2358
  * The number of RowListener functions registered with the Store.
2017
2359
  */
@@ -2020,6 +2362,11 @@ export type StoreListenerStats = {
2020
2362
  * The number of CellIdsListener functions registered with the Store.
2021
2363
  */
2022
2364
  cellIds?: number;
2365
+ /**
2366
+ * The number of HasCellListener functions registered with the Store, since
2367
+ * v4.4.
2368
+ */
2369
+ hasCell?: number;
2023
2370
  /**
2024
2371
  * The number of CellListener functions registered with the Store.
2025
2372
  */
@@ -2028,6 +2375,11 @@ export type StoreListenerStats = {
2028
2375
  * The number of InvalidCellListener functions registered with the Store.
2029
2376
  */
2030
2377
  invalidCell?: number;
2378
+ /**
2379
+ * The number of HasValuesListener functions registered with the Store, since
2380
+ * v4.4.
2381
+ */
2382
+ hasValues?: number;
2031
2383
  /**
2032
2384
  * The number of ValuesListener functions registered with the Store, since
2033
2385
  * v3.0.
@@ -2038,6 +2390,11 @@ export type StoreListenerStats = {
2038
2390
  * v3.0.
2039
2391
  */
2040
2392
  valueIds?: number;
2393
+ /**
2394
+ * The number of HasValueListener functions registered with the Store, since
2395
+ * v4.4.
2396
+ */
2397
+ hasValue?: number;
2041
2398
  /**
2042
2399
  * The number of ValueListener functions registered with the Store, since
2043
2400
  * v3.0.
@@ -2203,6 +2560,10 @@ export type StoreListenerStats = {
2203
2560
  * |Row|hasRow|forEachRow|
2204
2561
  * |Cell|hasCell|forEachCell|
2205
2562
  *
2563
+ * Since v4.3.23, you can add listeners for the change of existence of part of a
2564
+ * Store. For example, the addHasValueListener method lets you listen for a
2565
+ * Value being added or removed.
2566
+ *
2206
2567
  * Finally, the getListenerStats method describes the current state of the
2207
2568
  * Store's listeners for debugging purposes.
2208
2569
  * @example
@@ -5064,18 +5425,20 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5064
5425
  forEachValue(valueCallback: ValueCallback<Schemas[1]>): void;
5065
5426
 
5066
5427
  /**
5067
- * The addTablesListener method registers a listener function with the Store
5068
- * that will be called whenever data in the Store changes.
5428
+ * The addHasTablesListener method registers a listener function with the
5429
+ * Store that will be called when Tables as a whole are added to or removed
5430
+ * from the Store.
5069
5431
  *
5070
5432
  * This has schema-based typing. The following is a simplified representation:
5071
5433
  *
5072
5434
  * ```ts override
5073
- * addTablesListener(listener: TablesListener, mutator?: boolean): Id;
5435
+ * addHasTablesListener(listener: HasTablesListener, mutator?: boolean): Id;
5074
5436
  * ```
5075
5437
  *
5076
- * The provided listener is a TablesListener function, and will be called with
5077
- * a reference to the Store and a GetCellChange function in case you need to
5078
- * inspect any changes that occurred.
5438
+ * The provided listener is a HasTablesListener function, and will be called
5439
+ * with a reference to the Store. It is also given a flag to indicate whether
5440
+ * Tables now exist (having not done previously), or do not (having done so
5441
+ * previously).
5079
5442
  *
5080
5443
  * Use the optional mutator parameter to indicate that there is code in the
5081
5444
  * listener that will mutate Store data. If set to `false` (or omitted), such
@@ -5084,26 +5447,98 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5084
5447
  * (since the latter may become relevant due to changes made in the former).
5085
5448
  * The changes made by mutator listeners do not fire other mutating listeners,
5086
5449
  * though they will fire non-mutator listeners.
5087
- * @param listener The function that will be called whenever data in the Store
5088
- * changes.
5450
+ * @param listener The function that will be called whenever Tables as a whole
5451
+ * are added or removed.
5089
5452
  * @param mutator An optional boolean that indicates that the listener mutates
5090
5453
  * Store data.
5091
5454
  * @returns A unique Id for the listener that can later be used to call it
5092
5455
  * explicitly, or to remove it.
5093
5456
  * @example
5094
- * This example registers a listener that responds to any changes to the whole
5095
- * Store.
5457
+ * This example registers a listener that responds to Tables being added or
5458
+ * removed.
5096
5459
  *
5097
5460
  * ```js
5098
5461
  * const store = createStore().setTables({
5099
5462
  * pets: {fido: {species: 'dog', color: 'brown'}},
5100
5463
  * });
5101
- * const listenerId = store.addTablesListener((store, getCellChange) => {
5102
- * console.log('Tables changed');
5103
- * console.log(getCellChange('pets', 'fido', 'color'));
5464
+ * const listenerId = store.addHasTablesListener((store, hasTables) => {
5465
+ * console.log('Tables ' + (hasTables ? 'added' : 'removed'));
5104
5466
  * });
5105
5467
  *
5106
- * store.setCell('pets', 'fido', 'color', 'walnut');
5468
+ * store.delTables();
5469
+ * // -> 'Tables removed'
5470
+ *
5471
+ * store.setTables({species: {dog: {price: 5}}});
5472
+ * // -> 'Tables added'
5473
+ *
5474
+ * store.delListener(listenerId);
5475
+ * ```
5476
+ * @example
5477
+ * This example registers a listener that responds to Tables being added or
5478
+ * removed, and which also mutates the Store itself.
5479
+ *
5480
+ * ```js
5481
+ * const store = createStore();
5482
+ * const listenerId = store.addHasTablesListener(
5483
+ * (store, hasTables) => store.setValue('hasTables', hasTables),
5484
+ * true,
5485
+ * );
5486
+ *
5487
+ * store.setTables({species: {dog: {price: 5}}});
5488
+ * console.log(store.getValues());
5489
+ * // -> {hasTables: true}
5490
+ *
5491
+ * store.delListener(listenerId);
5492
+ * ```
5493
+ * @category Listener
5494
+ * @since v4.4.0
5495
+ */
5496
+ addHasTablesListener(
5497
+ listener: HasTablesListener<Schemas>,
5498
+ mutator?: boolean,
5499
+ ): Id;
5500
+
5501
+ /**
5502
+ * The addTablesListener method registers a listener function with the Store
5503
+ * that will be called whenever data in the Store changes.
5504
+ *
5505
+ * This has schema-based typing. The following is a simplified representation:
5506
+ *
5507
+ * ```ts override
5508
+ * addTablesListener(listener: TablesListener, mutator?: boolean): Id;
5509
+ * ```
5510
+ *
5511
+ * The provided listener is a TablesListener function, and will be called with
5512
+ * a reference to the Store and a GetCellChange function in case you need to
5513
+ * inspect any changes that occurred.
5514
+ *
5515
+ * Use the optional mutator parameter to indicate that there is code in the
5516
+ * listener that will mutate Store data. If set to `false` (or omitted), such
5517
+ * mutations will be silently ignored. All relevant mutator listeners (with
5518
+ * this flag set to `true`) are called _before_ any non-mutator listeners
5519
+ * (since the latter may become relevant due to changes made in the former).
5520
+ * The changes made by mutator listeners do not fire other mutating listeners,
5521
+ * though they will fire non-mutator listeners.
5522
+ * @param listener The function that will be called whenever data in the Store
5523
+ * changes.
5524
+ * @param mutator An optional boolean that indicates that the listener mutates
5525
+ * Store data.
5526
+ * @returns A unique Id for the listener that can later be used to call it
5527
+ * explicitly, or to remove it.
5528
+ * @example
5529
+ * This example registers a listener that responds to any changes to the whole
5530
+ * Store.
5531
+ *
5532
+ * ```js
5533
+ * const store = createStore().setTables({
5534
+ * pets: {fido: {species: 'dog', color: 'brown'}},
5535
+ * });
5536
+ * const listenerId = store.addTablesListener((store, getCellChange) => {
5537
+ * console.log('Tables changed');
5538
+ * console.log(getCellChange('pets', 'fido', 'color'));
5539
+ * });
5540
+ *
5541
+ * store.setCell('pets', 'fido', 'color', 'walnut');
5107
5542
  * // -> 'Tables changed'
5108
5543
  * // -> [true, 'brown', 'walnut']
5109
5544
  *
@@ -5203,6 +5638,119 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5203
5638
  mutator?: boolean,
5204
5639
  ): Id;
5205
5640
 
5641
+ /**
5642
+ * The addHasTableListener method registers a listener function with the Store
5643
+ * that will be called when a Table is added to or removed from the Store.
5644
+ *
5645
+ * This has schema-based typing. The following is a simplified representation:
5646
+ *
5647
+ * ```ts override
5648
+ * addHasTableListener(
5649
+ * tableId: IdOrNull,
5650
+ * listener: HasTableListener,
5651
+ * mutator?: boolean,
5652
+ * ): Id;
5653
+ * ```
5654
+ *
5655
+ * The provided listener is a HasTableListener function, and will be called
5656
+ * with a reference to the Store and the Id of the Table that changed. It is
5657
+ * also given a flag to indicate whether the Table now exists (having not done
5658
+ * previously), or does not (having done so previously).
5659
+ *
5660
+ * You can either listen to a single Table being added or removed (by
5661
+ * specifying the Table Id as the method's first parameter) or changes to any
5662
+ * Table (by providing a `null` wildcard).
5663
+ *
5664
+ * Use the optional mutator parameter to indicate that there is code in the
5665
+ * listener that will mutate Store data. If set to `false` (or omitted), such
5666
+ * mutations will be silently ignored. All relevant mutator listeners (with
5667
+ * this flag set to `true`) are called _before_ any non-mutator listeners
5668
+ * (since the latter may become relevant due to changes made in the former).
5669
+ * The changes made by mutator listeners do not fire other mutating listeners,
5670
+ * though they will fire non-mutator listeners.
5671
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
5672
+ * @param listener The function that will be called whenever the matching
5673
+ * Table is added or removed.
5674
+ * @param mutator An optional boolean that indicates that the listener mutates
5675
+ * Store data.
5676
+ * @returns A unique Id for the listener that can later be used to call it
5677
+ * explicitly, or to remove it.
5678
+ * @example
5679
+ * This example registers a listener that responds to a specific Table being
5680
+ * added or removed.
5681
+ *
5682
+ * ```js
5683
+ * const store = createStore().setTables({
5684
+ * pets: {fido: {species: 'dog', color: 'brown'}},
5685
+ * });
5686
+ * const listenerId = store.addHasTableListener(
5687
+ * 'pets',
5688
+ * (store, tableId, hasTable) => {
5689
+ * console.log('pets table ' + (hasTable ? 'added' : 'removed'));
5690
+ * },
5691
+ * );
5692
+ *
5693
+ * store.delTable('pets');
5694
+ * // -> 'pets table removed'
5695
+ *
5696
+ * store.setTable('pets', {fido: {species: 'dog', color: 'brown'}});
5697
+ * // -> 'pets table added'
5698
+ *
5699
+ * store.delListener(listenerId);
5700
+ * ```
5701
+ * @example
5702
+ * This example registers a listener that responds to any Table being added or
5703
+ * removed.
5704
+ *
5705
+ * ```js
5706
+ * const store = createStore().setTables({
5707
+ * pets: {fido: {species: 'dog', color: 'brown'}},
5708
+ * });
5709
+ * const listenerId = store.addHasTableListener(
5710
+ * null,
5711
+ * (store, tableId, hasTable) => {
5712
+ * console.log(`${tableId} table ` + (hasTable ? 'added' : 'removed'));
5713
+ * },
5714
+ * );
5715
+ *
5716
+ * store.delTable('pets');
5717
+ * // -> 'pets table removed'
5718
+ * store.setTable('species', {dog: {price: 5}});
5719
+ * // -> 'species table added'
5720
+ *
5721
+ * store.delListener(listenerId);
5722
+ * ```
5723
+ * @example
5724
+ * This example registers a listener that responds to a specific Table being
5725
+ * added or removed, and which also mutates the Store itself.
5726
+ *
5727
+ * ```js
5728
+ * const store = createStore().setTables({
5729
+ * pets: {fido: {species: 'dog', color: 'brown'}},
5730
+ * });
5731
+ * const listenerId = store.addHasTableListener(
5732
+ * 'pets',
5733
+ * (store, tableId) => store.setCell('meta', 'update', tableId, true),
5734
+ * true,
5735
+ * );
5736
+ *
5737
+ * store.delTable('pets', 'fido');
5738
+ * console.log(store.getTable('meta'));
5739
+ * // -> {update: {pets: true}}
5740
+ *
5741
+ * store.delListener(listenerId);
5742
+ * ```
5743
+ * @category Listener
5744
+ * @since v4.4.0
5745
+ */
5746
+ addHasTableListener<
5747
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
5748
+ >(
5749
+ tableId: TableIdOrNull,
5750
+ listener: HasTableListener<Schemas, TableIdOrNull>,
5751
+ mutator?: boolean,
5752
+ ): Id;
5753
+
5206
5754
  /**
5207
5755
  * The addTableListener method registers a listener function with the Store
5208
5756
  * that will be called whenever data in a Table changes.
@@ -5425,6 +5973,143 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5425
5973
  mutator?: boolean,
5426
5974
  ): Id;
5427
5975
 
5976
+ /**
5977
+ * The addHasTableCellListener method registers a listener function with the
5978
+ * Store that will be called when a Cell is added to or removed from anywhere
5979
+ * in a Table as a whole.
5980
+ *
5981
+ * This has schema-based typing. The following is a simplified representation:
5982
+ *
5983
+ * ```ts override
5984
+ * addHasTableCellListener(
5985
+ * tableId: IdOrNull,
5986
+ * cellId: IdOrNull,
5987
+ * listener: HasTableCellListener,
5988
+ * mutator?: boolean,
5989
+ * ): Id;
5990
+ * ```
5991
+ *
5992
+ * The provided listener is a HasTableCellListener function, and will be
5993
+ * called with a reference to the Store, the Id of the Table that changed, and
5994
+ * the Id of the Table Cell that changed. It is also given a flag to indicate
5995
+ * whether the Cell now exists anywhere in the Table (having not done
5996
+ * previously), or does not (having done so previously).
5997
+ *
5998
+ * You can either listen to a single Table Cell being added or removed (by
5999
+ * specifying the Table Id and Cell Id, as the method's first two parameters)
6000
+ * or changes to any Table Cell (by providing `null` wildcards).
6001
+ *
6002
+ * Both, either, or neither of the `tableId` and `cellId` parameters can be
6003
+ * wildcarded with `null`. You can listen to a specific Row in a specific
6004
+ * Table, any Row in a specific Table, a specific Row in any Table, or any Row
6005
+ * in any Table.
6006
+ *
6007
+ * Use the optional mutator parameter to indicate that there is code in the
6008
+ * listener that will mutate Store data. If set to `false` (or omitted), such
6009
+ * mutations will be silently ignored. All relevant mutator listeners (with
6010
+ * this flag set to `true`) are called _before_ any non-mutator listeners
6011
+ * (since the latter may become relevant due to changes made in the former).
6012
+ * The changes made by mutator listeners do not fire other mutating listeners,
6013
+ * though they will fire non-mutator listeners.
6014
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
6015
+ * @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
6016
+ * @param listener The function that will be called whenever the matching Cell
6017
+ * is added to or removed from anywhere in the Table.
6018
+ * @param mutator An optional boolean that indicates that the listener mutates
6019
+ * Store data.
6020
+ * @returns A unique Id for the listener that can later be used to call it
6021
+ * explicitly, or to remove it.
6022
+ * @example
6023
+ * This example registers a listener that responds to a specific Cell being
6024
+ * added to or removed from the Table as a whole.
6025
+ *
6026
+ * ```js
6027
+ * const store = createStore().setTables({
6028
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6029
+ * });
6030
+ * const listenerId = store.addHasTableCellListener(
6031
+ * 'pets',
6032
+ * 'color',
6033
+ * (store, tableId, cellId, hasTableCell) => {
6034
+ * console.log(
6035
+ * 'color cell in pets table ' + (hasTableCell ? 'added' : 'removed'),
6036
+ * );
6037
+ * },
6038
+ * );
6039
+ *
6040
+ * store.delCell('pets', 'fido', 'color');
6041
+ * // -> 'color cell in pets table removed'
6042
+ *
6043
+ * store.setRow('pets', 'felix', {species: 'cat', color: 'brown'});
6044
+ * // -> 'color cell in pets table added'
6045
+ *
6046
+ * store.delListener(listenerId);
6047
+ * ```
6048
+ * @example
6049
+ * This example registers a listener that responds to any Cell being
6050
+ * added to or removed from the Table as a whole.
6051
+ *
6052
+ * ```js
6053
+ * const store = createStore().setTables({
6054
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6055
+ * });
6056
+ * const listenerId = store.addHasTableCellListener(
6057
+ * null,
6058
+ * null,
6059
+ * (store, tableId, cellId, hasTableCell) => {
6060
+ * console.log(
6061
+ * `${cellId} cell in ${tableId} table ` +
6062
+ * (hasTableCell ? 'added' : 'removed'),
6063
+ * );
6064
+ * },
6065
+ * );
6066
+ *
6067
+ * store.delCell('pets', 'fido', 'color');
6068
+ * // -> 'color cell in pets table removed'
6069
+ * store.setTable('species', {dog: {price: 5}});
6070
+ * // -> 'price cell in species table added'
6071
+ *
6072
+ * store.delListener(listenerId);
6073
+ * ```
6074
+ * @example
6075
+ * This example registers a listener that responds to a specific Cell being
6076
+ * added or removed, and which also mutates the Store itself.
6077
+ *
6078
+ * ```js
6079
+ * const store = createStore().setTables({
6080
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6081
+ * });
6082
+ * const listenerId = store.addHasTableCellListener(
6083
+ * 'pets',
6084
+ * 'color',
6085
+ * (store, tableId, cellId) =>
6086
+ * store.setCell('meta', 'update', `${tableId}_${cellId}`, true),
6087
+ * true,
6088
+ * );
6089
+ *
6090
+ * store.delRow('pets', 'fido');
6091
+ * console.log(store.getTable('meta'));
6092
+ * // -> {update: {pets_color: true}}
6093
+ *
6094
+ * store.delListener(listenerId);
6095
+ * ```
6096
+ * @category Listener
6097
+ * @since v4.4.0
6098
+ */
6099
+ addHasTableCellListener<
6100
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
6101
+ CellIdOrNull extends
6102
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
6103
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
6104
+ : AllCellIdFromSchema<Schemas[0]>)
6105
+ | null,
6106
+ >(
6107
+ tableId: TableIdOrNull,
6108
+ cellId: CellIdOrNull,
6109
+ listener: HasTableCellListener<Schemas, TableIdOrNull, CellIdOrNull>,
6110
+ mutator?: boolean,
6111
+ ): Id;
6112
+
5428
6113
  /**
5429
6114
  * The addRowCountListener method registers a listener function with the Store
5430
6115
  * that will be called whenever the count of Row objects in a Table change.
@@ -5884,28 +6569,29 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5884
6569
  ): Id;
5885
6570
 
5886
6571
  /**
5887
- * The addRowListener method registers a listener function with the Store that
5888
- * will be called whenever data in a Row changes.
6572
+ * The addHasRowListener method registers a listener function with the Store
6573
+ * that will be called when a Row is added to or removed from the Store.
5889
6574
  *
5890
6575
  * This has schema-based typing. The following is a simplified representation:
5891
6576
  *
5892
6577
  * ```ts override
5893
- * addRowListener(
6578
+ * addHasRowListener(
5894
6579
  * tableId: IdOrNull,
5895
6580
  * rowId: IdOrNull,
5896
- * listener: RowListener,
6581
+ * listener: HasRowListener,
5897
6582
  * mutator?: boolean,
5898
6583
  * ): Id;
5899
6584
  * ```
5900
6585
  *
5901
- * The provided listener is a RowListener function, and will be called with a
5902
- * reference to the Store, the Id of the Table that changed, the Id of the Row
5903
- * that changed, and a GetCellChange function in case you need to inspect any
5904
- * changes that occurred.
6586
+ * The provided listener is a HasRowListener function, and will be called with
6587
+ * a reference to the Store, the Id of the Table that changed, and the Id of
6588
+ * the Row that changed. It is also given a flag to indicate whether the Row
6589
+ * now exists (having not done previously), or does not (having done so
6590
+ * previously).
5905
6591
  *
5906
- * You can either listen to a single Row (by specifying the Table Id and Row
5907
- * Id as the method's first two parameters) or changes to any Row (by
5908
- * providing `null` wildcards).
6592
+ * You can either listen to a single Row being added or removed (by specifying
6593
+ * the Table Id and Row Id, as the method's first two parameters) or changes
6594
+ * to any Row (by providing `null` wildcards).
5909
6595
  *
5910
6596
  * Both, either, or neither of the `tableId` and `rowId` parameters can be
5911
6597
  * wildcarded with `null`. You can listen to a specific Row in a specific
@@ -5921,27 +6607,157 @@ export interface Store<in out Schemas extends OptionalSchemas> {
5921
6607
  * though they will fire non-mutator listeners.
5922
6608
  * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
5923
6609
  * @param rowId The Id of the Row to listen to, or `null` as a wildcard.
5924
- * @param listener The function that will be called whenever data in the
5925
- * matching Row changes.
6610
+ * @param listener The function that will be called whenever the matching Row
6611
+ * is added or removed.
5926
6612
  * @param mutator An optional boolean that indicates that the listener mutates
5927
6613
  * Store data.
5928
6614
  * @returns A unique Id for the listener that can later be used to call it
5929
6615
  * explicitly, or to remove it.
5930
6616
  * @example
5931
- * This example registers a listener that responds to any changes to a
5932
- * specific Row.
6617
+ * This example registers a listener that responds to a specific Row being
6618
+ * added or removed.
5933
6619
  *
5934
6620
  * ```js
5935
6621
  * const store = createStore().setTables({
5936
6622
  * pets: {fido: {species: 'dog', color: 'brown'}},
5937
6623
  * });
5938
- * const listenerId = store.addRowListener(
6624
+ * const listenerId = store.addHasRowListener(
5939
6625
  * 'pets',
5940
6626
  * 'fido',
5941
- * (store, tableId, rowId, getCellChange) => {
5942
- * console.log('fido row in pets table changed');
5943
- * console.log(getCellChange('pets', 'fido', 'color'));
5944
- * },
6627
+ * (store, tableId, rowId, hasRow) => {
6628
+ * console.log(
6629
+ * 'fido row in pets table ' + (hasRow ? 'added' : 'removed'),
6630
+ * );
6631
+ * },
6632
+ * );
6633
+ *
6634
+ * store.delRow('pets', 'fido');
6635
+ * // -> 'fido row in pets table removed'
6636
+ *
6637
+ * store.setRow('pets', 'fido', {species: 'dog', color: 'brown'});
6638
+ * // -> 'fido row in pets table added'
6639
+ *
6640
+ * store.delListener(listenerId);
6641
+ * ```
6642
+ * @example
6643
+ * This example registers a listener that responds to any Row being added or
6644
+ * removed.
6645
+ *
6646
+ * ```js
6647
+ * const store = createStore().setTables({
6648
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6649
+ * });
6650
+ * const listenerId = store.addHasRowListener(
6651
+ * null,
6652
+ * null,
6653
+ * (store, tableId, rowId, hasRow) => {
6654
+ * console.log(
6655
+ * `${rowId} row in ${tableId} table ` + (hasRow ? 'added' : 'removed'),
6656
+ * );
6657
+ * },
6658
+ * );
6659
+ *
6660
+ * store.delRow('pets', 'fido');
6661
+ * // -> 'fido row in pets table removed'
6662
+ * store.setTable('species', {dog: {price: 5}});
6663
+ * // -> 'dog row in species table added'
6664
+ *
6665
+ * store.delListener(listenerId);
6666
+ * ```
6667
+ * @example
6668
+ * This example registers a listener that responds to a specific Row being
6669
+ * added or removed, and which also mutates the Store itself.
6670
+ *
6671
+ * ```js
6672
+ * const store = createStore().setTables({
6673
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6674
+ * });
6675
+ * const listenerId = store.addHasRowListener(
6676
+ * 'pets',
6677
+ * 'fido',
6678
+ * (store, tableId, rowId) =>
6679
+ * store.setCell('meta', 'update', `${tableId}_${rowId}`, true),
6680
+ * true,
6681
+ * );
6682
+ *
6683
+ * store.delRow('pets', 'fido');
6684
+ * console.log(store.getTable('meta'));
6685
+ * // -> {update: {pets_fido: true}}
6686
+ *
6687
+ * store.delListener(listenerId);
6688
+ * ```
6689
+ * @category Listener
6690
+ * @since v4.4.0
6691
+ */
6692
+ addHasRowListener<
6693
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
6694
+ RowIdOrNull extends IdOrNull,
6695
+ >(
6696
+ tableId: TableIdOrNull,
6697
+ rowId: RowIdOrNull,
6698
+ listener: HasRowListener<Schemas, TableIdOrNull, RowIdOrNull>,
6699
+ mutator?: boolean,
6700
+ ): Id;
6701
+
6702
+ /**
6703
+ * The addRowListener method registers a listener function with the Store that
6704
+ * will be called whenever data in a Row changes.
6705
+ *
6706
+ * This has schema-based typing. The following is a simplified representation:
6707
+ *
6708
+ * ```ts override
6709
+ * addRowListener(
6710
+ * tableId: IdOrNull,
6711
+ * rowId: IdOrNull,
6712
+ * listener: RowListener,
6713
+ * mutator?: boolean,
6714
+ * ): Id;
6715
+ * ```
6716
+ *
6717
+ * The provided listener is a RowListener function, and will be called with a
6718
+ * reference to the Store, the Id of the Table that changed, the Id of the Row
6719
+ * that changed, and a GetCellChange function in case you need to inspect any
6720
+ * changes that occurred.
6721
+ *
6722
+ * You can either listen to a single Row (by specifying the Table Id and Row
6723
+ * Id as the method's first two parameters) or changes to any Row (by
6724
+ * providing `null` wildcards).
6725
+ *
6726
+ * Both, either, or neither of the `tableId` and `rowId` parameters can be
6727
+ * wildcarded with `null`. You can listen to a specific Row in a specific
6728
+ * Table, any Row in a specific Table, a specific Row in any Table, or any Row
6729
+ * in any Table.
6730
+ *
6731
+ * Use the optional mutator parameter to indicate that there is code in the
6732
+ * listener that will mutate Store data. If set to `false` (or omitted), such
6733
+ * mutations will be silently ignored. All relevant mutator listeners (with
6734
+ * this flag set to `true`) are called _before_ any non-mutator listeners
6735
+ * (since the latter may become relevant due to changes made in the former).
6736
+ * The changes made by mutator listeners do not fire other mutating listeners,
6737
+ * though they will fire non-mutator listeners.
6738
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
6739
+ * @param rowId The Id of the Row to listen to, or `null` as a wildcard.
6740
+ * @param listener The function that will be called whenever data in the
6741
+ * matching Row changes.
6742
+ * @param mutator An optional boolean that indicates that the listener mutates
6743
+ * Store data.
6744
+ * @returns A unique Id for the listener that can later be used to call it
6745
+ * explicitly, or to remove it.
6746
+ * @example
6747
+ * This example registers a listener that responds to any changes to a
6748
+ * specific Row.
6749
+ *
6750
+ * ```js
6751
+ * const store = createStore().setTables({
6752
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6753
+ * });
6754
+ * const listenerId = store.addRowListener(
6755
+ * 'pets',
6756
+ * 'fido',
6757
+ * (store, tableId, rowId, getCellChange) => {
6758
+ * console.log('fido row in pets table changed');
6759
+ * console.log(getCellChange('pets', 'fido', 'color'));
6760
+ * },
5945
6761
  * );
5946
6762
  *
5947
6763
  * store.setCell('pets', 'fido', 'color', 'walnut');
@@ -6125,6 +6941,155 @@ export interface Store<in out Schemas extends OptionalSchemas> {
6125
6941
  mutator?: boolean,
6126
6942
  ): Id;
6127
6943
 
6944
+ /**
6945
+ * The addHasCellListener method registers a listener function with the Store
6946
+ * that will be called when a Cell is added to or removed from the Store.
6947
+ *
6948
+ * This has schema-based typing. The following is a simplified representation:
6949
+ *
6950
+ * ```ts override
6951
+ * addHasCellListener(
6952
+ * tableId: IdOrNull,
6953
+ * rowId: IdOrNull,
6954
+ * cellId: IdOrNull,
6955
+ * listener: HasCellListener,
6956
+ * mutator?: boolean,
6957
+ * ): Id;
6958
+ * ```
6959
+ *
6960
+ * The provided listener is a HasCellListener function, and will be called
6961
+ * with a reference to the Store, the Id of the Table that changed, the Id of
6962
+ * the Row that changed, and the Id of the Cell that changed. It is also given
6963
+ * a flag to indicate whether the Cell now exists (having not done
6964
+ * previously), or does not (having done so previously).
6965
+ *
6966
+ * You can either listen to a single Cell being added or removed (by
6967
+ * specifying the Table Id, Row Id, and Cell Id as the method's first three
6968
+ * parameters) or changes to any Cell (by providing `null` wildcards).
6969
+ *
6970
+ * All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can
6971
+ * be wildcarded with `null`. You can listen to a specific Cell in a specific
6972
+ * Row in a specific Table, any Cell in any Row in any Table, for example - or
6973
+ * every other combination of wildcards.
6974
+ *
6975
+ * Use the optional mutator parameter to indicate that there is code in the
6976
+ * listener that will mutate Store data. If set to `false` (or omitted), such
6977
+ * mutations will be silently ignored. All relevant mutator listeners (with
6978
+ * this flag set to `true`) are called _before_ any non-mutator listeners
6979
+ * (since the latter may become relevant due to changes made in the former).
6980
+ * The changes made by mutator listeners do not fire other mutating listeners,
6981
+ * though they will fire non-mutator listeners.
6982
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
6983
+ * @param rowId The Id of the Row to listen to, or `null` as a wildcard.
6984
+ * @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
6985
+ * @param listener The function that will be called whenever the matching Cell
6986
+ * is added or removed.
6987
+ * @param mutator An optional boolean that indicates that the listener mutates
6988
+ * Store data.
6989
+ * @returns A unique Id for the listener that can later be used to call it
6990
+ * explicitly, or to remove it.
6991
+ * @example
6992
+ * This example registers a listener that responds to a specific Cell being
6993
+ * added or removed.
6994
+ *
6995
+ * ```js
6996
+ * const store = createStore().setTables({
6997
+ * pets: {fido: {species: 'dog', color: 'brown'}},
6998
+ * });
6999
+ * const listenerId = store.addHasCellListener(
7000
+ * 'pets',
7001
+ * 'fido',
7002
+ * 'color',
7003
+ * (store, tableId, rowId, cellId, hasCell) => {
7004
+ * console.log(
7005
+ * 'color cell in fido row in pets table ' +
7006
+ * (hasCell ? 'added' : 'removed'),
7007
+ * );
7008
+ * },
7009
+ * );
7010
+ *
7011
+ * store.delCell('pets', 'fido', 'color');
7012
+ * // -> 'color cell in fido row in pets table removed'
7013
+ *
7014
+ * store.setCell('pets', 'fido', 'color', 'walnut');
7015
+ * // -> 'color cell in fido row in pets table added'
7016
+ *
7017
+ * store.delListener(listenerId);
7018
+ * ```
7019
+ * @example
7020
+ * This example registers a listener that responds to any Cell being added or
7021
+ * removed.
7022
+ *
7023
+ * ```js
7024
+ * const store = createStore().setTables({
7025
+ * pets: {fido: {species: 'dog', color: 'brown'}},
7026
+ * });
7027
+ * const listenerId = store.addHasCellListener(
7028
+ * null,
7029
+ * null,
7030
+ * null,
7031
+ * (store, tableId, rowId, cellId, hasCell) => {
7032
+ * console.log(
7033
+ * `${cellId} cell in ${rowId} row in ${tableId} table ` +
7034
+ * (hasCell ? 'added' : 'removed'),
7035
+ * );
7036
+ * },
7037
+ * );
7038
+ *
7039
+ * store.delCell('pets', 'fido', 'color');
7040
+ * // -> 'color cell in fido row in pets table removed'
7041
+ * store.setTable('species', {dog: {price: 5}});
7042
+ * // -> 'price cell in dog row in species table added'
7043
+ *
7044
+ * store.delListener(listenerId);
7045
+ * ```
7046
+ * @example
7047
+ * This example registers a listener that responds to a specific Cell being
7048
+ * added or removed, and which also mutates the Store itself.
7049
+ *
7050
+ * ```js
7051
+ * const store = createStore().setTables({
7052
+ * pets: {fido: {species: 'dog', color: 'brown'}},
7053
+ * });
7054
+ * const listenerId = store.addHasCellListener(
7055
+ * 'pets',
7056
+ * 'fido',
7057
+ * 'color',
7058
+ * (store, tableId, rowId, cellId) =>
7059
+ * store.setCell('meta', 'update', `${tableId}_${rowId}_${cellId}`, true),
7060
+ * true,
7061
+ * );
7062
+ *
7063
+ * store.delCell('pets', 'fido', 'color');
7064
+ * console.log(store.getTable('meta'));
7065
+ * // -> {update: {pets_fido_color: true}}
7066
+ *
7067
+ * store.delListener(listenerId);
7068
+ * ```
7069
+ * @category Listener
7070
+ * @since v4.4.0
7071
+ */
7072
+ addHasCellListener<
7073
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
7074
+ RowIdOrNull extends IdOrNull,
7075
+ CellIdOrNull extends
7076
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
7077
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
7078
+ : AllCellIdFromSchema<Schemas[0]>)
7079
+ | null,
7080
+ >(
7081
+ tableId: TableIdOrNull,
7082
+ rowId: RowIdOrNull,
7083
+ cellId: CellIdOrNull,
7084
+ listener: HasCellListener<
7085
+ Schemas,
7086
+ TableIdOrNull,
7087
+ RowIdOrNull,
7088
+ CellIdOrNull
7089
+ >,
7090
+ mutator?: boolean,
7091
+ ): Id;
7092
+
6128
7093
  /**
6129
7094
  * The addCellListener method registers a listener function with the Store
6130
7095
  * that will be called whenever data in a Cell changes.
@@ -6264,6 +7229,78 @@ export interface Store<in out Schemas extends OptionalSchemas> {
6264
7229
  mutator?: boolean,
6265
7230
  ): Id;
6266
7231
 
7232
+ /**
7233
+ * The addHasValuesListener method registers a listener function with the
7234
+ * Store that will be called when Values as a whole are added to or removed
7235
+ * from the Store.
7236
+ *
7237
+ * This has schema-based typing. The following is a simplified representation:
7238
+ *
7239
+ * ```ts override
7240
+ * addHasValuesListener(listener: HasValuesListener, mutator?: boolean): Id;
7241
+ * ```
7242
+ *
7243
+ * The provided listener is a HasValuesListener function, and will be called
7244
+ * with a reference to the Store. It is also given a flag to indicate whether
7245
+ * Values now exist (having not done previously), or do not (having done so
7246
+ * previously).
7247
+ *
7248
+ * Use the optional mutator parameter to indicate that there is code in the
7249
+ * listener that will mutate Store data. If set to `false` (or omitted), such
7250
+ * mutations will be silently ignored. All relevant mutator listeners (with
7251
+ * this flag set to `true`) are called _before_ any non-mutator listeners
7252
+ * (since the latter may become relevant due to changes made in the former).
7253
+ * The changes made by mutator listeners do not fire other mutating listeners,
7254
+ * though they will fire non-mutator listeners.
7255
+ * @param listener The function that will be called whenever Values as a whole
7256
+ * are added or removed.
7257
+ * @param mutator An optional boolean that indicates that the listener mutates
7258
+ * Store data.
7259
+ * @returns A unique Id for the listener that can later be used to call it
7260
+ * explicitly, or to remove it.
7261
+ * @example
7262
+ * This example registers a listener that responds to Values being added or
7263
+ * removed.
7264
+ *
7265
+ * ```js
7266
+ * const store = createStore().setValues({open: true, employees: 3});
7267
+ * const listenerId = store.addHasValuesListener((store, hasValues) => {
7268
+ * console.log('Values ' + (hasValues ? 'added' : 'removed'));
7269
+ * });
7270
+ *
7271
+ * store.delValues();
7272
+ * // -> 'Values removed'
7273
+ *
7274
+ * store.setValue('employees', 4);
7275
+ * // -> 'Values added'
7276
+ *
7277
+ * store.delListener(listenerId);
7278
+ * ```
7279
+ * @example
7280
+ * This example registers a listener that responds to Values being added or
7281
+ * removed, and which also mutates the Store itself.
7282
+ *
7283
+ * ```js
7284
+ * const store = createStore();
7285
+ * const listenerId = store.addHasValuesListener(
7286
+ * (store, hasValues) => store.setValue('hasValues', hasValues),
7287
+ * true,
7288
+ * );
7289
+ *
7290
+ * store.setValue('employees', 4);
7291
+ * console.log(store.getValues());
7292
+ * // -> {employees: 4, hasValues: true}
7293
+ *
7294
+ * store.delListener(listenerId);
7295
+ * ```
7296
+ * @category Listener
7297
+ * @since v4.4.0
7298
+ */
7299
+ addHasValuesListener(
7300
+ listener: HasValuesListener<Schemas>,
7301
+ mutator?: boolean,
7302
+ ): Id;
7303
+
6267
7304
  /**
6268
7305
  * The addValuesListener method registers a listener function with the Store
6269
7306
  * that will be called whenever the Values change.
@@ -6402,6 +7439,113 @@ export interface Store<in out Schemas extends OptionalSchemas> {
6402
7439
  mutator?: boolean,
6403
7440
  ): Id;
6404
7441
 
7442
+ /**
7443
+ * The addHasValueListener method registers a listener function with the Store
7444
+ * that will be called when a Value is added to or removed from the Store.
7445
+ *
7446
+ * This has schema-based typing. The following is a simplified representation:
7447
+ *
7448
+ * ```ts override
7449
+ * addHasValueListener(
7450
+ * valueId: IdOrNull,
7451
+ * listener: HasValueListener,
7452
+ * mutator?: boolean,
7453
+ * ): Id;
7454
+ * ```
7455
+ *
7456
+ * The provided listener is a HasValueListener function, and will be called
7457
+ * with a reference to the Store and the Id of Value that changed. It is also
7458
+ * given a flag to indicate whether the Value now exists (having not done
7459
+ * previously), or does not (having done so previously).
7460
+ *
7461
+ * You can either listen to a single Value being added or removed (by
7462
+ * specifying the Value Id) or any Value being added or removed (by providing
7463
+ * a `null` wildcard).
7464
+ *
7465
+ * Use the optional mutator parameter to indicate that there is code in the
7466
+ * listener that will mutate Store data. If set to `false` (or omitted), such
7467
+ * mutations will be silently ignored. All relevant mutator listeners (with
7468
+ * this flag set to `true`) are called _before_ any non-mutator listeners
7469
+ * (since the latter may become relevant due to changes made in the former).
7470
+ * The changes made by mutator listeners do not fire other mutating listeners,
7471
+ * though they will fire non-mutator listeners.
7472
+ * @param valueId The Id of the Value to listen to, or `null` as a wildcard.
7473
+ * @param listener The function that will be called whenever the matching
7474
+ * Value is added or removed.
7475
+ * @param mutator An optional boolean that indicates that the listener mutates
7476
+ * Store data.
7477
+ * @returns A unique Id for the listener that can later be used to call it
7478
+ * explicitly, or to remove it.
7479
+ * @example
7480
+ * This example registers a listener that responds to a specific Value being
7481
+ * added or removed.
7482
+ *
7483
+ * ```js
7484
+ * const store = createStore().setValues({open: true, employees: 3});
7485
+ * const listenerId = store.addHasValueListener(
7486
+ * 'employees',
7487
+ * (store, valueId, hasValue) => {
7488
+ * console.log('employee value ' + (hasValue ? 'added' : 'removed'));
7489
+ * },
7490
+ * );
7491
+ *
7492
+ * store.delValue('employees');
7493
+ * // -> 'employee value removed'
7494
+ *
7495
+ * store.setValue('employees', 4);
7496
+ * // -> 'employee value added'
7497
+ *
7498
+ * store.delListener(listenerId);
7499
+ * ```
7500
+ * @example
7501
+ * This example registers a listener that responds to any Value being added or
7502
+ * removed.
7503
+ *
7504
+ * ```js
7505
+ * const store = createStore().setValues({open: true, employees: 3});
7506
+ * const listenerId = store.addHasValueListener(
7507
+ * null,
7508
+ * (store, valueId, hasValue) => {
7509
+ * console.log(valueId + ' value ' + (hasValue ? 'added' : 'removed'));
7510
+ * },
7511
+ * );
7512
+ *
7513
+ * store.delValue('employees');
7514
+ * // -> 'employees value removed'
7515
+ * store.setValue('website', 'https://pets.com');
7516
+ * // -> 'website value added'
7517
+ *
7518
+ * store.delListener(listenerId);
7519
+ * ```
7520
+ * @example
7521
+ * This example registers a listener that responds to a specific Value being
7522
+ * added or removed, and which also mutates the Store itself.
7523
+ *
7524
+ * ```js
7525
+ * const store = createStore().setValues({open: true, employees: 3});
7526
+ * const listenerId = store.addHasValueListener(
7527
+ * 'employees',
7528
+ * (store, valueId) => store.setValue('updated', true),
7529
+ * true,
7530
+ * );
7531
+ *
7532
+ * store.delValue('employees');
7533
+ * console.log(store.getValues());
7534
+ * // -> {open: true, updated: true}
7535
+ *
7536
+ * store.delListener(listenerId);
7537
+ * ```
7538
+ * @category Listener
7539
+ * @since v4.4.0
7540
+ */
7541
+ addHasValueListener<
7542
+ ValueIdOrNull extends ValueIdFromSchema<Schemas[1]> | null,
7543
+ >(
7544
+ valueId: ValueIdOrNull,
7545
+ listener: HasValueListener<Schemas, ValueIdOrNull>,
7546
+ mutator?: boolean,
7547
+ ): Id;
7548
+
6405
7549
  /**
6406
7550
  * The addValueListener method registers a listener function with the Store
6407
7551
  * that will be called whenever data in a Value changes.