tinybase 4.4.0-beta.1 → 4.4.0

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 (71) 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/tools.cjs +1 -1
  6. package/lib/cjs/tools.cjs.gz +0 -0
  7. package/lib/cjs/ui-react-dom-debug.cjs +1 -1
  8. package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
  9. package/lib/cjs/ui-react.cjs +1 -1
  10. package/lib/cjs/ui-react.cjs.gz +0 -0
  11. package/lib/cjs-es6/store.cjs +1 -1
  12. package/lib/cjs-es6/store.cjs.gz +0 -0
  13. package/lib/cjs-es6/tinybase.cjs +1 -1
  14. package/lib/cjs-es6/tinybase.cjs.gz +0 -0
  15. package/lib/cjs-es6/tools.cjs +1 -1
  16. package/lib/cjs-es6/tools.cjs.gz +0 -0
  17. package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
  18. package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
  19. package/lib/cjs-es6/ui-react.cjs +1 -1
  20. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  21. package/lib/debug/store.js +1 -1
  22. package/lib/debug/tinybase.js +1 -1
  23. package/lib/debug/tools.js +355 -14
  24. package/lib/debug/ui-react-dom.js +1 -1
  25. package/lib/debug/ui-react.js +284 -71
  26. package/lib/es6/store.js +1 -1
  27. package/lib/es6/store.js.gz +0 -0
  28. package/lib/es6/tinybase.js +1 -1
  29. package/lib/es6/tinybase.js.gz +0 -0
  30. package/lib/es6/tools.js +1 -1
  31. package/lib/es6/tools.js.gz +0 -0
  32. package/lib/es6/ui-react-dom-debug.js +1 -1
  33. package/lib/es6/ui-react-dom-debug.js.gz +0 -0
  34. package/lib/es6/ui-react.js +1 -1
  35. package/lib/es6/ui-react.js.gz +0 -0
  36. package/lib/store.js +1 -1
  37. package/lib/store.js.gz +0 -0
  38. package/lib/tinybase.js +1 -1
  39. package/lib/tinybase.js.gz +0 -0
  40. package/lib/tools.js +1 -1
  41. package/lib/tools.js.gz +0 -0
  42. package/lib/types/store.d.ts +1 -1
  43. package/lib/types/tools.d.ts +2 -2
  44. package/lib/types/ui-react.d.ts +1163 -52
  45. package/lib/types/with-schemas/store.d.ts +1 -1
  46. package/lib/types/with-schemas/tools.d.ts +2 -2
  47. package/lib/types/with-schemas/ui-react.d.ts +1353 -65
  48. package/lib/ui-react.js +1 -1
  49. package/lib/ui-react.js.gz +0 -0
  50. package/lib/umd/store.js +1 -1
  51. package/lib/umd/store.js.gz +0 -0
  52. package/lib/umd/tinybase.js +1 -1
  53. package/lib/umd/tinybase.js.gz +0 -0
  54. package/lib/umd/tools.js +1 -1
  55. package/lib/umd/tools.js.gz +0 -0
  56. package/lib/umd/ui-react-dom-debug.js +1 -1
  57. package/lib/umd/ui-react-dom-debug.js.gz +0 -0
  58. package/lib/umd/ui-react.js +1 -1
  59. package/lib/umd/ui-react.js.gz +0 -0
  60. package/lib/umd-es6/store.js +1 -1
  61. package/lib/umd-es6/store.js.gz +0 -0
  62. package/lib/umd-es6/tinybase.js +1 -1
  63. package/lib/umd-es6/tinybase.js.gz +0 -0
  64. package/lib/umd-es6/tools.js +1 -1
  65. package/lib/umd-es6/tools.js.gz +0 -0
  66. package/lib/umd-es6/ui-react-dom-debug.js +1 -1
  67. package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
  68. package/lib/umd-es6/ui-react.js +1 -1
  69. package/lib/umd-es6/ui-react.js.gz +0 -0
  70. package/package.json +20 -20
  71. package/readme.md +13 -13
@@ -69,6 +69,13 @@ import {
69
69
  CellIdsListener,
70
70
  CellListener,
71
71
  CellOrUndefined,
72
+ HasCellListener,
73
+ HasRowListener,
74
+ HasTableCellListener,
75
+ HasTableListener,
76
+ HasTablesListener,
77
+ HasValueListener,
78
+ HasValuesListener,
72
79
  MapCell,
73
80
  MapValue,
74
81
  OptionalSchemas,
@@ -524,6 +531,90 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
524
531
  storeOrStoreId?: StoreOrStoreId<Schemas>,
525
532
  ) => Store<Schemas> | undefined;
526
533
 
534
+ /**
535
+ * The useHasTables hook returns a boolean indicating whether any Table objects
536
+ * exist in the Store, and registers a listener so that any changes to that
537
+ * result will cause a re-render.
538
+ *
539
+ * This has schema-based typing. The following is a simplified representation:
540
+ *
541
+ * ```ts override
542
+ * useHasTables(storeOrStoreId?: StoreOrStoreId): boolean;
543
+ * ```
544
+ *
545
+ * A Provider component is used to wrap part of an application in a context, and
546
+ * it can contain a default Store or a set of Store objects named by Id. The
547
+ * useHasTables hook lets you indicate which Store to get data for: omit the
548
+ * optional parameter for the default context Store, provide an Id for a named
549
+ * context Store, or provide a Store explicitly by reference.
550
+ *
551
+ * When first rendered, this hook will create a listener so that changes to the
552
+ * Tables will cause a re-render. When the component containing this hook is
553
+ * unmounted, the listener will be automatically removed.
554
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
555
+ * Store, provide an Id for a named context Store, or provide an explicit
556
+ * reference.
557
+ * @returns Whether any Tables exist.
558
+ * @example
559
+ * This example creates a Store outside the application, which is used in the
560
+ * useHasTables hook by reference. A change to the data in the Store re-renders
561
+ * the component.
562
+ *
563
+ * ```jsx
564
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
565
+ * const App = () => <span>{JSON.stringify(useHasTables(store))}</span>;
566
+ *
567
+ * const app = document.createElement('div');
568
+ * const root = ReactDOMClient.createRoot(app);
569
+ * root.render(<App />); // !act
570
+ * console.log(app.innerHTML);
571
+ * // -> '<span>true</span>'
572
+ *
573
+ * store.delTable('pets'); // !act
574
+ * console.log(app.innerHTML);
575
+ * // -> '<span>false</span>'
576
+ * ```
577
+ * @example
578
+ * This example creates a Provider context into which a default Store is
579
+ * provided. A component within it then uses the useHasTables hook.
580
+ *
581
+ * ```jsx
582
+ * const App = ({store}) => (
583
+ * <Provider store={store}>
584
+ * <Pane />
585
+ * </Provider>
586
+ * );
587
+ * const Pane = () => <span>{JSON.stringify(useHasTables())}</span>;
588
+ *
589
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
590
+ * const app = document.createElement('div');
591
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
592
+ * console.log(app.innerHTML);
593
+ * // -> '<span>true</span>'
594
+ * ```
595
+ * @example
596
+ * This example creates a Provider context into which a Store is provided, named
597
+ * by Id. A component within it then uses the useHasTables hook.
598
+ *
599
+ * ```jsx
600
+ * const App = ({store}) => (
601
+ * <Provider storesById={{petStore: store}}>
602
+ * <Pane />
603
+ * </Provider>
604
+ * );
605
+ * const Pane = () => <span>{JSON.stringify(useHasTables('petStore'))}</span>;
606
+ *
607
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
608
+ * const app = document.createElement('div');
609
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
610
+ * console.log(app.innerHTML);
611
+ * // -> '<span>true</span>'
612
+ * ```
613
+ * @category Store hooks
614
+ * @since v4.4.0
615
+ */
616
+ useHasTables: (storeOrStoreId?: StoreOrStoreId<Schemas>) => boolean;
617
+
527
618
  /**
528
619
  * The useTables hook returns a Tables object containing the tabular data of a
529
620
  * Store, and registers a listener so that any changes to that result will cause
@@ -690,6 +781,101 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
690
781
  storeOrStoreId?: StoreOrStoreId<Schemas>,
691
782
  ) => TableIdFromSchema<Schemas[0]>[];
692
783
 
784
+ /**
785
+ * The useHasTable hook returns a boolean indicating whether a given Table
786
+ * exists in the Store, and registers a listener so that any changes to that
787
+ * result will cause a re-render.
788
+ *
789
+ * This has schema-based typing. The following is a simplified representation:
790
+ *
791
+ * ```ts override
792
+ * useHasTable(
793
+ * tableId: Id,
794
+ * storeOrStoreId?: StoreOrStoreId,
795
+ * ): boolean;
796
+ * ```
797
+ *
798
+ * A Provider component is used to wrap part of an application in a context, and
799
+ * it can contain a default Store or a set of Store objects named by Id. The
800
+ * useHasTable hook lets you indicate which Store to get data for: omit the
801
+ * optional parameter for the default context Store, provide an Id for a named
802
+ * context Store, or provide a Store explicitly by reference.
803
+ *
804
+ * When first rendered, this hook will create a listener so that changes to the
805
+ * Table will cause a re-render. When the component containing this hook is
806
+ * unmounted, the listener will be automatically removed.
807
+ * @param tableId The Id of the Table in the Store.
808
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
809
+ * Store, provide an Id for a named context Store, or provide an explicit
810
+ * reference.
811
+ * @returns Whether a Table with that Id exists.
812
+ * @example
813
+ * This example creates a Store outside the application, which is used in the
814
+ * useHasTable hook by reference. A change to the data in the Store re-renders
815
+ * the component.
816
+ *
817
+ * ```jsx
818
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
819
+ * const App = () => (
820
+ * <span>{JSON.stringify(useHasTable('pets', store))}</span>
821
+ * );
822
+ *
823
+ * const app = document.createElement('div');
824
+ * const root = ReactDOMClient.createRoot(app);
825
+ * root.render(<App />); // !act
826
+ * console.log(app.innerHTML);
827
+ * // -> '<span>true</span>'
828
+ *
829
+ * store.delTable('pets'); // !act
830
+ * console.log(app.innerHTML);
831
+ * // -> '<span>false</span>'
832
+ * ```
833
+ * @example
834
+ * This example creates a Provider context into which a default Store is
835
+ * provided. A component within it then uses the useHasTable hook.
836
+ *
837
+ * ```jsx
838
+ * const App = ({store}) => (
839
+ * <Provider store={store}>
840
+ * <Pane />
841
+ * </Provider>
842
+ * );
843
+ * const Pane = () => <span>{JSON.stringify(useHasTable('pets'))}</span>;
844
+ *
845
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
846
+ * const app = document.createElement('div');
847
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
848
+ * console.log(app.innerHTML);
849
+ * // -> '<span>true</span>'
850
+ * ```
851
+ * @example
852
+ * This example creates a Provider context into which a Store is provided, named
853
+ * by Id. A component within it then uses the useHasTable hook.
854
+ *
855
+ * ```jsx
856
+ * const App = ({store}) => (
857
+ * <Provider storesById={{petStore: store}}>
858
+ * <Pane />
859
+ * </Provider>
860
+ * );
861
+ * const Pane = () => (
862
+ * <span>{JSON.stringify(useHasTable('pets', 'petStore'))}</span>
863
+ * );
864
+ *
865
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
866
+ * const app = document.createElement('div');
867
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
868
+ * console.log(app.innerHTML);
869
+ * // -> '<span>true</span>'
870
+ * ```
871
+ * @category Store hooks
872
+ * @since v4.4.0
873
+ */
874
+ useHasTable: <TableId extends TableIdFromSchema<Schemas[0]>>(
875
+ tableId: TableId,
876
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
877
+ ) => boolean;
878
+
693
879
  /**
694
880
  * The useTable hook returns an object containing the data of a single Table in
695
881
  * a Store, and registers a listener so that any changes to that result will
@@ -872,6 +1058,108 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
872
1058
  storeOrStoreId?: StoreOrStoreId<Schemas>,
873
1059
  ) => CellIdFromSchema<Schemas[0], TableId>[];
874
1060
 
1061
+ /**
1062
+ * The useHasTableCell hook returns a boolean indicating whether a given Cell
1063
+ * exists anywhere in a Table, not just in a specific Row, and registers a
1064
+ * listener so that any changes to that result will cause a re-render.
1065
+ *
1066
+ * This has schema-based typing. The following is a simplified representation:
1067
+ *
1068
+ * ```ts override
1069
+ * useHasTableCell(
1070
+ * tableId: Id,
1071
+ * cellId: Id,
1072
+ * storeOrStoreId?: StoreOrStoreId,
1073
+ * ): boolean;
1074
+ * ```
1075
+ *
1076
+ * A Provider component is used to wrap part of an application in a context, and
1077
+ * it can contain a default Store or a set of Store objects named by Id. The
1078
+ * useHasTableCell hook lets you indicate which Store to get data for: omit the
1079
+ * optional parameter for the default context Store, provide an Id for a named
1080
+ * context Store, or provide a Store explicitly by reference.
1081
+ *
1082
+ * When first rendered, this hook will create a listener so that changes to the
1083
+ * Table will cause a re-render. When the component containing this hook is
1084
+ * unmounted, the listener will be automatically removed.
1085
+ * @param tableId The Id of the Table in the Store.
1086
+ * @param cellId The Id of the Cell in the Table.
1087
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
1088
+ * Store, provide an Id for a named context Store, or provide an explicit
1089
+ * reference.
1090
+ * @returns Whether a Cell with that Id exists anywhere in that Table.
1091
+ * @example
1092
+ * This example creates a Store outside the application, which is used in the
1093
+ * useHasTableCell hook by reference. A change to the data in the Store
1094
+ * re-renders the component.
1095
+ *
1096
+ * ```jsx
1097
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1098
+ * const App = () => (
1099
+ * <span>{JSON.stringify(useHasTableCell('pets', 'legs', store))}</span>
1100
+ * );
1101
+ *
1102
+ * const app = document.createElement('div');
1103
+ * const root = ReactDOMClient.createRoot(app);
1104
+ * root.render(<App />); // !act
1105
+ * console.log(app.innerHTML);
1106
+ * // -> '<span>false</span>'
1107
+ *
1108
+ * store.setRow('pets', 'felix', {color: 'black', legs: 4}); // !act
1109
+ * console.log(app.innerHTML);
1110
+ * // -> '<span>true</span>'
1111
+ * ```
1112
+ * @example
1113
+ * This example creates a Provider context into which a default Store is
1114
+ * provided. A component within it then uses the useHasTableCell hook.
1115
+ *
1116
+ * ```jsx
1117
+ * const App = ({store}) => (
1118
+ * <Provider store={store}>
1119
+ * <Pane />
1120
+ * </Provider>
1121
+ * );
1122
+ * const Pane = () => (
1123
+ * <span>{JSON.stringify(useHasTableCell('pets', 'legs'))}</span>
1124
+ * );
1125
+ *
1126
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1127
+ * const app = document.createElement('div');
1128
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1129
+ * console.log(app.innerHTML);
1130
+ * // -> '<span>false</span>'
1131
+ * ```
1132
+ * @example
1133
+ * This example creates a Provider context into which a Store is provided, named
1134
+ * by Id. A component within it then uses the useHasTableCell hook.
1135
+ *
1136
+ * ```jsx
1137
+ * const App = ({store}) => (
1138
+ * <Provider storesById={{petStore: store}}>
1139
+ * <Pane />
1140
+ * </Provider>
1141
+ * );
1142
+ * const Pane = () => (
1143
+ * <span>
1144
+ * {JSON.stringify(useHasTableCell('pets', 'legs', 'petStore'))}
1145
+ * </span>
1146
+ * );
1147
+ *
1148
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1149
+ * const app = document.createElement('div');
1150
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1151
+ * console.log(app.innerHTML);
1152
+ * // -> '<span>false</span>'
1153
+ * ```
1154
+ * @category Store hooks
1155
+ * @since v4.4.0
1156
+ */
1157
+ useHasTableCell: <TableId extends TableIdFromSchema<Schemas[0]>>(
1158
+ tableId: TableId,
1159
+ cellId: CellIdFromSchema<Schemas[0], TableId>,
1160
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
1161
+ ) => boolean;
1162
+
875
1163
  /**
876
1164
  * The useRowCount hook returns the count of the Row objects in a given Table,
877
1165
  * and registers a listener so that any changes to that result will cause a
@@ -1184,25 +1472,25 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1184
1472
  ) => Ids;
1185
1473
 
1186
1474
  /**
1187
- * The useRow hook returns an object containing the data of a single Row in a
1188
- * given Table, and registers a listener so that any changes to that result will
1475
+ * The useHasRow hook returns a boolean indicating whether a given Row exists in
1476
+ * the Store, and registers a listener so that any changes to that result will
1189
1477
  * cause a re-render.
1190
1478
  *
1191
1479
  * This has schema-based typing. The following is a simplified representation:
1192
1480
  *
1193
1481
  * ```ts override
1194
- * useRow(
1482
+ * useHasRow(
1195
1483
  * tableId: Id,
1196
1484
  * rowId: Id,
1197
1485
  * storeOrStoreId?: StoreOrStoreId,
1198
- * ): Row;
1486
+ * ): boolean;
1199
1487
  * ```
1200
1488
  *
1201
1489
  * A Provider component is used to wrap part of an application in a context, and
1202
1490
  * it can contain a default Store or a set of Store objects named by Id. The
1203
- * useRow hook lets you indicate which Store to get data for: omit the final
1204
- * optional final parameter for the default context Store, provide an Id for a
1205
- * named context Store, or provide a Store explicitly by reference.
1491
+ * useHasRow hook lets you indicate which Store to get data for: omit the
1492
+ * optional parameter for the default context Store, provide an Id for a named
1493
+ * context Store, or provide a Store explicitly by reference.
1206
1494
  *
1207
1495
  * When first rendered, this hook will create a listener so that changes to the
1208
1496
  * Row will cause a re-render. When the component containing this hook is
@@ -1212,26 +1500,126 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1212
1500
  * @param storeOrStoreId The Store to be accessed: omit for the default context
1213
1501
  * Store, provide an Id for a named context Store, or provide an explicit
1214
1502
  * reference.
1215
- * @returns An object containing the entire data of the Row.
1503
+ * @returns Whether a Row with that Id exists in that Table.
1216
1504
  * @example
1217
1505
  * This example creates a Store outside the application, which is used in the
1218
- * useRow hook by reference. A change to the data in the Store re-renders the
1219
- * component.
1506
+ * useHasRow hook by reference. A change to the data in the Store re-renders
1507
+ * the component.
1220
1508
  *
1221
1509
  * ```jsx
1222
1510
  * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1223
1511
  * const App = () => (
1224
- * <span>{JSON.stringify(useRow('pets', 'fido', store))}</span>
1512
+ * <span>{JSON.stringify(useHasRow('pets', 'felix', store))}</span>
1225
1513
  * );
1226
1514
  *
1227
1515
  * const app = document.createElement('div');
1228
- * ReactDOMClient.createRoot(app).render(<App />); // !act
1516
+ * const root = ReactDOMClient.createRoot(app);
1517
+ * root.render(<App />); // !act
1229
1518
  * console.log(app.innerHTML);
1230
- * // -> '<span>{"color":"brown"}</span>'
1519
+ * // -> '<span>false</span>'
1231
1520
  *
1232
- * store.setCell('pets', 'fido', 'color', 'walnut'); // !act
1521
+ * store.setCell('pets', 'felix', 'color', 'black'); // !act
1233
1522
  * console.log(app.innerHTML);
1234
- * // -> '<span>{"color":"walnut"}</span>'
1523
+ * // -> '<span>true</span>'
1524
+ * ```
1525
+ * @example
1526
+ * This example creates a Provider context into which a default Store is
1527
+ * provided. A component within it then uses the useHasRow hook.
1528
+ *
1529
+ * ```jsx
1530
+ * const App = ({store}) => (
1531
+ * <Provider store={store}>
1532
+ * <Pane />
1533
+ * </Provider>
1534
+ * );
1535
+ * const Pane = () => (
1536
+ * <span>{JSON.stringify(useHasRow('pets', 'felix'))}</span>
1537
+ * );
1538
+ *
1539
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1540
+ * const app = document.createElement('div');
1541
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1542
+ * console.log(app.innerHTML);
1543
+ * // -> '<span>false</span>'
1544
+ * ```
1545
+ * @example
1546
+ * This example creates a Provider context into which a Store is provided, named
1547
+ * by Id. A component within it then uses the useHasRow hook.
1548
+ *
1549
+ * ```jsx
1550
+ * const App = ({store}) => (
1551
+ * <Provider storesById={{petStore: store}}>
1552
+ * <Pane />
1553
+ * </Provider>
1554
+ * );
1555
+ * const Pane = () => (
1556
+ * <span>{JSON.stringify(useHasRow('pets', 'felix', 'petStore'))}</span>
1557
+ * );
1558
+ *
1559
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1560
+ * const app = document.createElement('div');
1561
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1562
+ * console.log(app.innerHTML);
1563
+ * // -> '<span>false</span>'
1564
+ * ```
1565
+ * @category Store hooks
1566
+ * @since v4.4.0
1567
+ */
1568
+ useHasRow: <TableId extends TableIdFromSchema<Schemas[0]>>(
1569
+ tableId: TableId,
1570
+ rowId: Id,
1571
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
1572
+ ) => boolean;
1573
+
1574
+ /**
1575
+ * The useRow hook returns an object containing the data of a single Row in a
1576
+ * given Table, and registers a listener so that any changes to that result will
1577
+ * cause a re-render.
1578
+ *
1579
+ * This has schema-based typing. The following is a simplified representation:
1580
+ *
1581
+ * ```ts override
1582
+ * useRow(
1583
+ * tableId: Id,
1584
+ * rowId: Id,
1585
+ * storeOrStoreId?: StoreOrStoreId,
1586
+ * ): Row;
1587
+ * ```
1588
+ *
1589
+ * A Provider component is used to wrap part of an application in a context, and
1590
+ * it can contain a default Store or a set of Store objects named by Id. The
1591
+ * useRow hook lets you indicate which Store to get data for: omit the final
1592
+ * optional final parameter for the default context Store, provide an Id for a
1593
+ * named context Store, or provide a Store explicitly by reference.
1594
+ *
1595
+ * When first rendered, this hook will create a listener so that changes to the
1596
+ * Row will cause a re-render. When the component containing this hook is
1597
+ * unmounted, the listener will be automatically removed.
1598
+ * @param tableId The Id of the Table in the Store.
1599
+ * @param rowId The Id of the Row in the Table.
1600
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
1601
+ * Store, provide an Id for a named context Store, or provide an explicit
1602
+ * reference.
1603
+ * @returns An object containing the entire data of the Row.
1604
+ * @example
1605
+ * This example creates a Store outside the application, which is used in the
1606
+ * useRow hook by reference. A change to the data in the Store re-renders the
1607
+ * component.
1608
+ *
1609
+ * ```jsx
1610
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1611
+ * const App = () => (
1612
+ * <span>{JSON.stringify(useRow('pets', 'fido', store))}</span>
1613
+ * );
1614
+ *
1615
+ * const app = document.createElement('div');
1616
+ * ReactDOMClient.createRoot(app).render(<App />); // !act
1617
+ * console.log(app.innerHTML);
1618
+ * // -> '<span>{"color":"brown"}</span>'
1619
+ *
1620
+ * store.setCell('pets', 'fido', 'color', 'walnut'); // !act
1621
+ * console.log(app.innerHTML);
1622
+ * // -> '<span>{"color":"walnut"}</span>'
1235
1623
  * ```
1236
1624
  * @example
1237
1625
  * This example creates a Provider context into which a default Store is
@@ -1377,6 +1765,114 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1377
1765
  storeOrStoreId?: StoreOrStoreId<Schemas>,
1378
1766
  ) => CellIdFromSchema<Schemas[0], TableId>[];
1379
1767
 
1768
+ /**
1769
+ * The useHasCell hook returns a boolean indicating whether a given Cell exists
1770
+ * in a given Row in a given Table, and registers a listener so that any changes
1771
+ * to that result will cause a re-render.
1772
+ *
1773
+ * This has schema-based typing. The following is a simplified representation:
1774
+ *
1775
+ * ```ts override
1776
+ * useHasCell(
1777
+ * tableId: Id,
1778
+ * rowId: Id,
1779
+ * cellId: Id,
1780
+ * storeOrStoreId?: StoreOrStoreId,
1781
+ * ): boolean;
1782
+ * ```
1783
+ *
1784
+ * A Provider component is used to wrap part of an application in a context, and
1785
+ * it can contain a default Store or a set of Store objects named by Id. The
1786
+ * useHasCell hook lets you indicate which Store to get data for: omit the
1787
+ * optional parameter for the default context Store, provide an Id for a named
1788
+ * context Store, or provide a Store explicitly by reference.
1789
+ *
1790
+ * When first rendered, this hook will create a listener so that changes to the
1791
+ * Cell will cause a re-render. When the component containing this hook is
1792
+ * unmounted, the listener will be automatically removed.
1793
+ * @param tableId The Id of the Table in the Store.
1794
+ * @param rowId The Id of the Row in the Table.
1795
+ * @param cellId The Id of the Cell in the Row.
1796
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
1797
+ * Store, provide an Id for a named context Store, or provide an explicit
1798
+ * reference.
1799
+ * @returns Whether a Cell with that Id exists in that Row in that Table.
1800
+ * @example
1801
+ * This example creates a Store outside the application, which is used in the
1802
+ * useHasCell hook by reference. A change to the data in the Store re-renders
1803
+ * the component.
1804
+ *
1805
+ * ```jsx
1806
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1807
+ * const App = () => (
1808
+ * <span>{JSON.stringify(useHasCell('pets', 'fido', 'legs', store))}</span>
1809
+ * );
1810
+ *
1811
+ * const app = document.createElement('div');
1812
+ * const root = ReactDOMClient.createRoot(app);
1813
+ * root.render(<App />); // !act
1814
+ * console.log(app.innerHTML);
1815
+ * // -> '<span>false</span>'
1816
+ *
1817
+ * store.setCell('pets', 'fido', 'legs', 4); // !act
1818
+ * console.log(app.innerHTML);
1819
+ * // -> '<span>true</span>'
1820
+ * ```
1821
+ * @example
1822
+ * This example creates a Provider context into which a default Store is
1823
+ * provided. A component within it then uses the useHasCell hook.
1824
+ *
1825
+ * ```jsx
1826
+ * const App = ({store}) => (
1827
+ * <Provider store={store}>
1828
+ * <Pane />
1829
+ * </Provider>
1830
+ * );
1831
+ * const Pane = () => (
1832
+ * <span>{JSON.stringify(useHasCell('pets', 'fido', 'legs'))}</span>
1833
+ * );
1834
+ *
1835
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1836
+ * const app = document.createElement('div');
1837
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1838
+ * console.log(app.innerHTML);
1839
+ * // -> '<span>false</span>'
1840
+ * ```
1841
+ * @example
1842
+ * This example creates a Provider context into which a Store is provided, named
1843
+ * by Id. A component within it then uses the useHasCell hook.
1844
+ *
1845
+ * ```jsx
1846
+ * const App = ({store}) => (
1847
+ * <Provider storesById={{petStore: store}}>
1848
+ * <Pane />
1849
+ * </Provider>
1850
+ * );
1851
+ * const Pane = () => (
1852
+ * <span>
1853
+ * {JSON.stringify(useHasCell('pets', 'fido', 'legs', 'petStore'))}
1854
+ * </span>
1855
+ * );
1856
+ *
1857
+ * const store = createStore().setCell('pets', 'fido', 'color', 'brown');
1858
+ * const app = document.createElement('div');
1859
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
1860
+ * console.log(app.innerHTML);
1861
+ * // -> '<span>false</span>'
1862
+ * ```
1863
+ * @category Store hooks
1864
+ * @since v4.4.0
1865
+ */
1866
+ useHasCell: <
1867
+ TableId extends TableIdFromSchema<Schemas[0]>,
1868
+ CellId extends CellIdFromSchema<Schemas[0], TableId>,
1869
+ >(
1870
+ tableId: TableId,
1871
+ rowId: Id,
1872
+ cellId: CellId,
1873
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
1874
+ ) => boolean;
1875
+
1380
1876
  /**
1381
1877
  * The useCell hook returns an object containing the value of a single Cell in a
1382
1878
  * given Row, in a given Table, and registers a listener so that any changes to
@@ -1477,6 +1973,90 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1477
1973
  storeOrStoreId?: StoreOrStoreId<Schemas>,
1478
1974
  ) => NoInfer<CellOrUndefined<Schemas[0], TableId, CellId>>;
1479
1975
 
1976
+ /**
1977
+ * The useHasValues hook returns a boolean indicating whether any Values exist
1978
+ * in the Store, and registers a listener so that any changes to that result
1979
+ * will cause a re-render.
1980
+ *
1981
+ * This has schema-based typing. The following is a simplified representation:
1982
+ *
1983
+ * ```ts override
1984
+ * useHasValues(storeOrStoreId?: StoreOrStoreId): boolean;
1985
+ * ```
1986
+ *
1987
+ * A Provider component is used to wrap part of an application in a context, and
1988
+ * it can contain a default Store or a set of Store objects named by Id. The
1989
+ * useHasValues hook lets you indicate which Store to get data for: omit the
1990
+ * optional parameter for the default context Store, provide an Id for a named
1991
+ * context Store, or provide a Store explicitly by reference.
1992
+ *
1993
+ * When first rendered, this hook will create a listener so that changes to the
1994
+ * Values will cause a re-render. When the component containing this hook is
1995
+ * unmounted, the listener will be automatically removed.
1996
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
1997
+ * Store, provide an Id for a named context Store, or provide an explicit
1998
+ * reference.
1999
+ * @returns Whether any Values exist.
2000
+ * @example
2001
+ * This example creates a Store outside the application, which is used in the
2002
+ * useHasValues hook by reference. A change to the data in the Store re-renders
2003
+ * the component.
2004
+ *
2005
+ * ```jsx
2006
+ * const store = createStore().setValue('open', true);
2007
+ * const App = () => <span>{JSON.stringify(useHasValues(store))}</span>;
2008
+ *
2009
+ * const app = document.createElement('div');
2010
+ * const root = ReactDOMClient.createRoot(app);
2011
+ * root.render(<App />); // !act
2012
+ * console.log(app.innerHTML);
2013
+ * // -> '<span>true</span>'
2014
+ *
2015
+ * store.delValue('open'); // !act
2016
+ * console.log(app.innerHTML);
2017
+ * // -> '<span>false</span>'
2018
+ * ```
2019
+ * @example
2020
+ * This example creates a Provider context into which a default Store is
2021
+ * provided. A component within it then uses the useHasValues hook.
2022
+ *
2023
+ * ```jsx
2024
+ * const App = ({store}) => (
2025
+ * <Provider store={store}>
2026
+ * <Pane />
2027
+ * </Provider>
2028
+ * );
2029
+ * const Pane = () => <span>{JSON.stringify(useHasValues())}</span>;
2030
+ *
2031
+ * const store = createStore().setValue('open', true);
2032
+ * const app = document.createElement('div');
2033
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
2034
+ * console.log(app.innerHTML);
2035
+ * // -> '<span>true</span>'
2036
+ * ```
2037
+ * @example
2038
+ * This example creates a Provider context into which a Store is provided, named
2039
+ * by Id. A component within it then uses the useHasValues hook.
2040
+ *
2041
+ * ```jsx
2042
+ * const App = ({store}) => (
2043
+ * <Provider storesById={{petStore: store}}>
2044
+ * <Pane />
2045
+ * </Provider>
2046
+ * );
2047
+ * const Pane = () => <span>{JSON.stringify(useHasValues('petStore'))}</span>;
2048
+ *
2049
+ * const store = createStore().setValue('open', true);
2050
+ * const app = document.createElement('div');
2051
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
2052
+ * console.log(app.innerHTML);
2053
+ * // -> '<span>true</span>'
2054
+ * ```
2055
+ * @category Store hooks
2056
+ * @since v4.4.0
2057
+ */
2058
+ useHasValues: (storeOrStoreId?: StoreOrStoreId<Schemas>) => boolean;
2059
+
1480
2060
  /**
1481
2061
  * The useValues hook returns a Values object containing the keyed value data of
1482
2062
  * a Store, and registers a listener so that any changes to that result will
@@ -1644,6 +2224,101 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1644
2224
  storeOrStoreId?: StoreOrStoreId<Schemas>,
1645
2225
  ) => ValueIdFromSchema<Schemas[1]>[];
1646
2226
 
2227
+ /**
2228
+ * The useHasValue hook returns a boolean indicating whether a given Value
2229
+ * exists in the Store, and registers a listener so that any changes to that
2230
+ * result will cause a re-render.
2231
+ *
2232
+ * This has schema-based typing. The following is a simplified representation:
2233
+ *
2234
+ * ```ts override
2235
+ * useHasValue(
2236
+ * valueId: Id,
2237
+ * storeOrStoreId?: StoreOrStoreId,
2238
+ * ): boolean;
2239
+ * ```
2240
+ *
2241
+ * A Provider component is used to wrap part of an application in a context, and
2242
+ * it can contain a default Store or a set of Store objects named by Id. The
2243
+ * useHasValue hook lets you indicate which Store to get data for: omit the
2244
+ * optional parameter for the default context Store, provide an Id for a named
2245
+ * context Store, or provide a Store explicitly by reference.
2246
+ *
2247
+ * When first rendered, this hook will create a listener so that changes to the
2248
+ * Value will cause a re-render. When the component containing this hook is
2249
+ * unmounted, the listener will be automatically removed.
2250
+ * @param valueId The Id of the Value in the Store.
2251
+ * @param storeOrStoreId The Store to be accessed: omit for the default context
2252
+ * Store, provide an Id for a named context Store, or provide an explicit
2253
+ * reference.
2254
+ * @returns Whether a Value with that Id exists in the Store.
2255
+ * @example
2256
+ * This example creates a Store outside the application, which is used in the
2257
+ * useHasValue hook by reference. A change to the data in the Store re-renders
2258
+ * the component.
2259
+ *
2260
+ * ```jsx
2261
+ * const store = createStore().setValue('open', true);
2262
+ * const App = () => (
2263
+ * <span>{JSON.stringify(useHasValue('employees', store))}</span>
2264
+ * );
2265
+ *
2266
+ * const app = document.createElement('div');
2267
+ * const root = ReactDOMClient.createRoot(app);
2268
+ * root.render(<App />); // !act
2269
+ * console.log(app.innerHTML);
2270
+ * // -> '<span>false</span>'
2271
+ *
2272
+ * store.setValue('employees', 3); // !act
2273
+ * console.log(app.innerHTML);
2274
+ * // -> '<span>true</span>'
2275
+ * ```
2276
+ * @example
2277
+ * This example creates a Provider context into which a default Store is
2278
+ * provided. A component within it then uses the useHasValue hook.
2279
+ *
2280
+ * ```jsx
2281
+ * const App = ({store}) => (
2282
+ * <Provider store={store}>
2283
+ * <Pane />
2284
+ * </Provider>
2285
+ * );
2286
+ * const Pane = () => <span>{JSON.stringify(useHasValue('employees'))}</span>;
2287
+ *
2288
+ * const store = createStore().setValue('open', true);
2289
+ * const app = document.createElement('div');
2290
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
2291
+ * console.log(app.innerHTML);
2292
+ * // -> '<span>false</span>'
2293
+ * ```
2294
+ * @example
2295
+ * This example creates a Provider context into which a Store is provided, named
2296
+ * by Id. A component within it then uses the useHasValue hook.
2297
+ *
2298
+ * ```jsx
2299
+ * const App = ({store}) => (
2300
+ * <Provider storesById={{petStore: store}}>
2301
+ * <Pane />
2302
+ * </Provider>
2303
+ * );
2304
+ * const Pane = () => (
2305
+ * <span>{JSON.stringify(useHasValue('employees', 'petStore'))}</span>
2306
+ * );
2307
+ *
2308
+ * const store = createStore().setValue('open', true);
2309
+ * const app = document.createElement('div');
2310
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
2311
+ * console.log(app.innerHTML);
2312
+ * // -> '<span>false</span>'
2313
+ * ```
2314
+ * @category Store hooks
2315
+ * @since v4.4.0
2316
+ */
2317
+ useHasValue: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
2318
+ valueId: ValueId,
2319
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
2320
+ ) => boolean;
2321
+
1647
2322
  /**
1648
2323
  * The useValue hook returns an object containing the data of a single Value in
1649
2324
  * a Store, and registers a listener so that any changes to that result will
@@ -3174,27 +3849,102 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3174
3849
  * };
3175
3850
  *
3176
3851
  * const app = document.createElement('div');
3177
- * ReactDOMClient.createRoot(app).render(<App />); // !act
3178
- * const span = app.querySelector('span');
3179
- * console.log(span.innerHTML);
3180
- * // -> '{"open":true,"employees":3}'
3852
+ * ReactDOMClient.createRoot(app).render(<App />); // !act
3853
+ * const span = app.querySelector('span');
3854
+ * console.log(span.innerHTML);
3855
+ * // -> '{"open":true,"employees":3}'
3856
+ *
3857
+ * // User clicks the <span> element:
3858
+ * // -> span MouseEvent('click', {bubbles: true})
3859
+ * // -> 'Deleted'
3860
+ *
3861
+ * console.log(span.innerHTML);
3862
+ * // -> '{"employees":3}'
3863
+ * ```
3864
+ * @category Store hooks
3865
+ * @since v3.0.0
3866
+ */
3867
+ useDelValueCallback: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
3868
+ valueId: ValueId,
3869
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
3870
+ then?: (store: Store<Schemas>) => void,
3871
+ thenDeps?: React.DependencyList,
3872
+ ) => Callback;
3873
+
3874
+ /**
3875
+ * The useHasTablesListener hook registers a listener function with the Store
3876
+ * that will be called when Tables as a whole are added to or removed from the
3877
+ * Store.
3878
+ *
3879
+ * This has schema-based typing. The following is a simplified representation:
3880
+ *
3881
+ * ```ts override
3882
+ * useHasTablesListener(
3883
+ * listener: HasTablesListener,
3884
+ * listenerDeps?: React.DependencyList,
3885
+ * mutator?: boolean,
3886
+ * storeOrStoreId?: StoreOrStoreId,
3887
+ * ): void;
3888
+ * ```
3889
+ *
3890
+ * This hook is useful for situations where a component needs to register its
3891
+ * own specific listener to do more than simply tracking the value (which is
3892
+ * more easily done with the useHasTables hook).
3893
+ *
3894
+ * Unlike the addHasTablesListener method, which returns a listener Id and
3895
+ * requires you to remove it manually, the useHasTablesListener hook manages
3896
+ * this lifecycle for you: when the listener changes (per its `listenerDeps`
3897
+ * dependencies) or the component unmounts, the listener on the underlying Store
3898
+ * will be deleted.
3899
+ * @param listener The function that will be called whenever Tables as a whole
3900
+ * are added or removed.
3901
+ * @param listenerDeps An optional array of dependencies for the `listener`
3902
+ * function, which, if any change, result in the re-registration of the
3903
+ * listener. This parameter defaults to an empty array.
3904
+ * @param mutator An optional boolean that indicates that the listener mutates
3905
+ * Store data.
3906
+ * @param storeOrStoreId The Store to register the listener with: omit for the
3907
+ * default context Store, provide an Id for a named context Store, or provide an
3908
+ * explicit reference.
3909
+ * @example
3910
+ * This example uses the useHasTablesListener hook to create a listener that is
3911
+ * scoped to a single component. When the component is unmounted, the listener
3912
+ * is removed from the Store.
3913
+ *
3914
+ * ```jsx
3915
+ * const App = ({store}) => (
3916
+ * <Provider store={store}>
3917
+ * <Pane />
3918
+ * </Provider>
3919
+ * );
3920
+ * const Pane = () => {
3921
+ * useHasTablesListener(() => console.log('Tables existence changed'));
3922
+ * return <span>App</span>;
3923
+ * };
3924
+ *
3925
+ * const store = createStore();
3926
+ * const app = document.createElement('div');
3927
+ * const root = ReactDOMClient.createRoot(app);
3928
+ * root.render(<App store={store} />); // !act
3929
+ * console.log(store.getListenerStats().hasTables);
3930
+ * // -> 1
3181
3931
  *
3182
- * // User clicks the <span> element:
3183
- * // -> span MouseEvent('click', {bubbles: true})
3184
- * // -> 'Deleted'
3932
+ * store.setCell('pets', 'fido', 'color', 'brown'); // !act
3933
+ * // -> 'Tables existence changed'
3185
3934
  *
3186
- * console.log(span.innerHTML);
3187
- * // -> '{"employees":3}'
3935
+ * root.unmount(); // !act
3936
+ * console.log(store.getListenerStats().hasTables);
3937
+ * // -> 0
3188
3938
  * ```
3189
3939
  * @category Store hooks
3190
- * @since v3.0.0
3940
+ * @since v4.4.0
3191
3941
  */
3192
- useDelValueCallback: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
3193
- valueId: ValueId,
3942
+ useHasTablesListener: (
3943
+ listener: HasTablesListener<Schemas>,
3944
+ listenerDeps?: React.DependencyList,
3945
+ mutator?: boolean,
3194
3946
  storeOrStoreId?: StoreOrStoreId<Schemas>,
3195
- then?: (store: Store<Schemas>) => void,
3196
- thenDeps?: React.DependencyList,
3197
- ) => Callback;
3947
+ ) => void;
3198
3948
 
3199
3949
  /**
3200
3950
  * The useTablesListener hook registers a listener function with a Store that
@@ -3341,6 +4091,90 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3341
4091
  storeOrStoreId?: StoreOrStoreId<Schemas>,
3342
4092
  ) => void;
3343
4093
 
4094
+ /**
4095
+ * The useHasTableListener hook registers a listener function with the Store
4096
+ * that will be called when a Table is added to or removed from the Store.
4097
+ *
4098
+ * This has schema-based typing. The following is a simplified representation:
4099
+ *
4100
+ * ```ts override
4101
+ * useHasTableListener(
4102
+ * tableId: IdOrNull,
4103
+ * listener: HasTableListener,
4104
+ * listenerDeps?: React.DependencyList,
4105
+ * mutator?: boolean,
4106
+ * storeOrStoreId?: StoreOrStoreId,
4107
+ * ): void;
4108
+ * ```
4109
+ *
4110
+ * This hook is useful for situations where a component needs to register its
4111
+ * own specific listener to do more than simply tracking the value (which is
4112
+ * more easily done with the useHasTable hook).
4113
+ *
4114
+ * You can either listen to a single Table (by specifying its Id as the method's
4115
+ * first parameter) or changes to any Table (by providing a `null` wildcard).
4116
+ *
4117
+ * Unlike the addHasTableListener method, which returns a listener Id and
4118
+ * requires you to remove it manually, the useHasTableListener hook manages this
4119
+ * lifecycle for you: when the listener changes (per its `listenerDeps`
4120
+ * dependencies) or the component unmounts, the listener on the underlying Store
4121
+ * will be deleted.
4122
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
4123
+ * @param listener The function that will be called whenever the matching
4124
+ * Table is added or removed.
4125
+ * @param listenerDeps An optional array of dependencies for the `listener`
4126
+ * function, which, if any change, result in the re-registration of the
4127
+ * listener. This parameter defaults to an empty array.
4128
+ * @param mutator An optional boolean that indicates that the listener mutates
4129
+ * Store data.
4130
+ * @param storeOrStoreId The Store to register the listener with: omit for the
4131
+ * default context Store, provide an Id for a named context Store, or provide an
4132
+ * explicit reference.
4133
+ * @example
4134
+ * This example uses the useHasTableListener hook to create a listener that is
4135
+ * scoped to a single component. When the component is unmounted, the listener
4136
+ * is removed from the Store.
4137
+ *
4138
+ * ```jsx
4139
+ * const App = ({store}) => (
4140
+ * <Provider store={store}>
4141
+ * <Pane />
4142
+ * </Provider>
4143
+ * );
4144
+ * const Pane = () => {
4145
+ * useHasTableListener('pets', () =>
4146
+ * console.log('Table existence changed'),
4147
+ * );
4148
+ * return <span>App</span>;
4149
+ * };
4150
+ *
4151
+ * const store = createStore();
4152
+ * const app = document.createElement('div');
4153
+ * const root = ReactDOMClient.createRoot(app);
4154
+ * root.render(<App store={store} />); // !act
4155
+ * console.log(store.getListenerStats().hasTable);
4156
+ * // -> 1
4157
+ *
4158
+ * store.setCell('pets', 'fido', 'color', 'walnut'); // !act
4159
+ * // -> 'Table existence changed'
4160
+ *
4161
+ * root.unmount(); // !act
4162
+ * console.log(store.getListenerStats().hasTable);
4163
+ * // -> 0
4164
+ * ```
4165
+ * @category Store hooks
4166
+ * @since v4.4.0
4167
+ */
4168
+ useHasTableListener: <
4169
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
4170
+ >(
4171
+ tableId: TableIdOrNull,
4172
+ listener: HasTableListener<Schemas, TableIdOrNull>,
4173
+ listenerDeps?: React.DependencyList,
4174
+ mutator?: boolean,
4175
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
4176
+ ) => void;
4177
+
3344
4178
  /**
3345
4179
  * The useTableListener hook registers a listener function with a Store that
3346
4180
  * will be called whenever data in a Table changes.
@@ -3503,6 +4337,100 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3503
4337
  storeOrStoreId?: StoreOrStoreId<Schemas>,
3504
4338
  ) => void;
3505
4339
 
4340
+ /**
4341
+ * The useHasTableCellListener hook registers a listener function with the Store
4342
+ * that will be called when a Cell is added to or removed from anywhere in a
4343
+ * Table as a whole.
4344
+ *
4345
+ * This has schema-based typing. The following is a simplified representation:
4346
+ *
4347
+ * ```ts override
4348
+ * useHasTableCellListener(
4349
+ * tableId: IdOrNull,
4350
+ * cellId: IdOrNull,
4351
+ * listener: HasTableCellListener,
4352
+ * listenerDeps?: React.DependencyList,
4353
+ * mutator?: boolean,
4354
+ * storeOrStoreId?: StoreOrStoreId,
4355
+ * ): void;
4356
+ * ```
4357
+ *
4358
+ * This hook is useful for situations where a component needs to register its
4359
+ * own specific listener to do more than simply tracking the value (which is
4360
+ * more easily done with the useHasTableCell hook).
4361
+ *
4362
+ * You can either listen to a single Table Cell being added or removed (by
4363
+ * specifying the Table Id and Cell Id, as the method's first two parameters) or
4364
+ * changes to any Table Cell (by providing `null` wildcards).
4365
+ *
4366
+ * Unlike the addHasTableCellIds method, which returns a listener Id and
4367
+ * requires you to remove it manually, the useHasTableCellListener hook manages
4368
+ * this lifecycle for you: when the listener changes (per its `listenerDeps`
4369
+ * dependencies) or the component unmounts, the listener on the underlying Store
4370
+ * will be deleted.
4371
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
4372
+ * @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
4373
+ * @param listener The function that will be called whenever the matching Cell
4374
+ * is added to or removed from anywhere in the Table.
4375
+ * @param listenerDeps An optional array of dependencies for the `listener`
4376
+ * function, which, if any change, result in the re-registration of the
4377
+ * listener. This parameter defaults to an empty array.
4378
+ * @param mutator An optional boolean that indicates that the listener mutates
4379
+ * Store data.
4380
+ * @param storeOrStoreId The Store to register the listener with: omit for the
4381
+ * default context Store, provide an Id for a named context Store, or provide an
4382
+ * explicit reference.
4383
+ * @example
4384
+ * This example uses the useHasTableCellListener hook to create a listener that
4385
+ * is scoped to a single component. When the component is unmounted, the
4386
+ * listener is removed from the Store.
4387
+ *
4388
+ * ```jsx
4389
+ * const App = ({store}) => (
4390
+ * <Provider store={store}>
4391
+ * <Pane />
4392
+ * </Provider>
4393
+ * );
4394
+ * const Pane = () => {
4395
+ * useHasTableCellListener('pets', 'color', () =>
4396
+ * console.log('Table Cell existence changed'),
4397
+ * );
4398
+ * return <span>App</span>;
4399
+ * };
4400
+ *
4401
+ * const store = createStore();
4402
+ * const app = document.createElement('div');
4403
+ * const root = ReactDOMClient.createRoot(app);
4404
+ * root.render(<App store={store} />); // !act
4405
+ * console.log(store.getListenerStats().hasTableCell);
4406
+ * // -> 1
4407
+ *
4408
+ * store.setRow('pets', 'fido', {color: 'brown'}); // !act
4409
+ * // -> 'Table Cell existence changed'
4410
+ *
4411
+ * root.unmount(); // !act
4412
+ * console.log(store.getListenerStats().hasTableCell);
4413
+ * // -> 0
4414
+ * ```
4415
+ * @category Store hooks
4416
+ * @since v4.4.0
4417
+ */
4418
+ useHasTableCellListener: <
4419
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
4420
+ CellIdOrNull extends
4421
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
4422
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
4423
+ : AllCellIdFromSchema<Schemas[0]>)
4424
+ | null,
4425
+ >(
4426
+ tableId: TableIdOrNull,
4427
+ cellId: CellIdOrNull,
4428
+ listener: HasTableCellListener<Schemas, TableIdOrNull, CellIdOrNull>,
4429
+ listenerDeps?: React.DependencyList,
4430
+ mutator?: boolean,
4431
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
4432
+ ) => void;
4433
+
3506
4434
  /**
3507
4435
  * The useRowCountListener hook registers a listener function with a Store that
3508
4436
  * will be called whenever the count of the Row objects in a Table changes.
@@ -3712,9 +4640,120 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3712
4640
  * default context Store, provide an Id for a named context Store, or provide an
3713
4641
  * explicit reference.
3714
4642
  * @example
3715
- * This example uses the useSortedRowIdsListener hook to create a listener that
3716
- * is scoped to a single component. When the component is unmounted, the
3717
- * listener is removed from the Store.
4643
+ * This example uses the useSortedRowIdsListener hook to create a listener that
4644
+ * is scoped to a single component. When the component is unmounted, the
4645
+ * listener is removed from the Store.
4646
+ *
4647
+ * ```jsx
4648
+ * const App = ({store}) => (
4649
+ * <Provider store={store}>
4650
+ * <Pane />
4651
+ * </Provider>
4652
+ * );
4653
+ * const Pane = () => {
4654
+ * useSortedRowIdsListener('pets', 'species', false, 0, undefined, () =>
4655
+ * console.log('Sorted Row Ids changed'),
4656
+ * );
4657
+ * return <span>App</span>;
4658
+ * };
4659
+ *
4660
+ * const store = createStore().setTables({
4661
+ * pets: {
4662
+ * fido: {species: 'dog'},
4663
+ * felix: {species: 'cat'},
4664
+ * },
4665
+ * });
4666
+ * const app = document.createElement('div');
4667
+ * const root = ReactDOMClient.createRoot(app);
4668
+ * root.render(<App store={store} />); // !act
4669
+ * console.log(store.getListenerStats().sortedRowIds);
4670
+ * // -> 1
4671
+ *
4672
+ * store.setRow('pets', 'cujo', {species: 'wolf'}); // !act
4673
+ * // -> 'Sorted Row Ids changed'
4674
+ *
4675
+ * root.unmount(); // !act
4676
+ * console.log(store.getListenerStats().sortedRowIds);
4677
+ * // -> 0
4678
+ * ```
4679
+ * @category Store hooks
4680
+ * @since v2.0.0
4681
+ */
4682
+ useSortedRowIdsListener: <
4683
+ TableId extends TableIdFromSchema<Schemas[0]>,
4684
+ CellIdOrUndefined extends CellIdFromSchema<Schemas[0], TableId> | undefined,
4685
+ Descending extends boolean,
4686
+ Offset extends number,
4687
+ Limit extends number | undefined,
4688
+ >(
4689
+ tableId: TableId,
4690
+ cellId: CellIdOrUndefined,
4691
+ descending: Descending,
4692
+ offset: Offset,
4693
+ limit: Limit,
4694
+ listener: SortedRowIdsListener<
4695
+ Schemas,
4696
+ TableId,
4697
+ CellIdOrUndefined,
4698
+ Descending,
4699
+ Offset,
4700
+ Limit
4701
+ >,
4702
+ listenerDeps?: React.DependencyList,
4703
+ mutator?: boolean,
4704
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
4705
+ ) => void;
4706
+
4707
+ /**
4708
+ * The useHasRowListener hook registers a listener function with the Store that
4709
+ * will be called when a Row is added to or removed from the Store.
4710
+ *
4711
+ * This has schema-based typing. The following is a simplified representation:
4712
+ *
4713
+ * ```ts override
4714
+ * useHasRowListener(
4715
+ * tableId: IdOrNull,
4716
+ * rowId: IdOrNull,
4717
+ * listener: HasRowListener,
4718
+ * listenerDeps?: React.DependencyList,
4719
+ * mutator?: boolean,
4720
+ * storeOrStoreId?: StoreOrStoreId,
4721
+ * ): void;
4722
+ * ```
4723
+ *
4724
+ * This hook is useful for situations where a component needs to register its
4725
+ * own specific listener to do more than simply tracking the value (which is
4726
+ * more easily done with the useHasRow hook).
4727
+ *
4728
+ * You can either listen to a single Row being added or removed (by specifying
4729
+ * the Table Id and Row Id, as the method's first two parameters) or changes
4730
+ * to any Row (by providing `null` wildcards).
4731
+ *
4732
+ * Both, either, or neither of the `tableId` and `rowId` parameters can be
4733
+ * wildcarded with `null`. You can listen to a specific Row in a specific Table,
4734
+ * any Row in a specific Table, a specific Row in any Table, or any Row in any
4735
+ * Table.
4736
+ *
4737
+ * Unlike the addHasRowListener method, which returns a listener Id and requires
4738
+ * you to remove it manually, the useHasRowListener hook manages this lifecycle
4739
+ * for you: when the listener changes (per its `listenerDeps` dependencies) or
4740
+ * the component unmounts, the listener on the underlying Store will be deleted.
4741
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
4742
+ * @param rowId The Id of the Row to listen to, or `null` as a wildcard.
4743
+ * @param listener The function that will be called whenever the matching Row
4744
+ * is added or removed.
4745
+ * @param listenerDeps An optional array of dependencies for the `listener`
4746
+ * function, which, if any change, result in the re-registration of the
4747
+ * listener. This parameter defaults to an empty array.
4748
+ * @param mutator An optional boolean that indicates that the listener mutates
4749
+ * Store data.
4750
+ * @param storeOrStoreId The Store to register the listener with: omit for the
4751
+ * default context Store, provide an Id for a named context Store, or provide an
4752
+ * explicit reference.
4753
+ * @example
4754
+ * This example uses the useHasRowListener hook to create a listener that is
4755
+ * scoped to a single component. When the component is unmounted, the listener
4756
+ * is removed from the Store.
3718
4757
  *
3719
4758
  * ```jsx
3720
4759
  * const App = ({store}) => (
@@ -3723,54 +4762,36 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3723
4762
  * </Provider>
3724
4763
  * );
3725
4764
  * const Pane = () => {
3726
- * useSortedRowIdsListener('pets', 'species', false, 0, undefined, () =>
3727
- * console.log('Sorted Row Ids changed'),
4765
+ * useHasRowListener('pets', 'fido', () =>
4766
+ * console.log('Row existence changed'),
3728
4767
  * );
3729
4768
  * return <span>App</span>;
3730
4769
  * };
3731
4770
  *
3732
- * const store = createStore().setTables({
3733
- * pets: {
3734
- * fido: {species: 'dog'},
3735
- * felix: {species: 'cat'},
3736
- * },
3737
- * });
4771
+ * const store = createStore();
3738
4772
  * const app = document.createElement('div');
3739
4773
  * const root = ReactDOMClient.createRoot(app);
3740
4774
  * root.render(<App store={store} />); // !act
3741
- * console.log(store.getListenerStats().sortedRowIds);
4775
+ * console.log(store.getListenerStats().hasRow);
3742
4776
  * // -> 1
3743
4777
  *
3744
- * store.setRow('pets', 'cujo', {species: 'wolf'}); // !act
3745
- * // -> 'Sorted Row Ids changed'
4778
+ * store.setCell('pets', 'fido', 'color', 'walnut'); // !act
4779
+ * // -> 'Row existence changed'
3746
4780
  *
3747
4781
  * root.unmount(); // !act
3748
- * console.log(store.getListenerStats().sortedRowIds);
4782
+ * console.log(store.getListenerStats().hasRow);
3749
4783
  * // -> 0
3750
4784
  * ```
3751
4785
  * @category Store hooks
3752
- * @since v2.0.0
4786
+ * @since v4.4.0
3753
4787
  */
3754
- useSortedRowIdsListener: <
3755
- TableId extends TableIdFromSchema<Schemas[0]>,
3756
- CellIdOrUndefined extends CellIdFromSchema<Schemas[0], TableId> | undefined,
3757
- Descending extends boolean,
3758
- Offset extends number,
3759
- Limit extends number | undefined,
4788
+ useHasRowListener: <
4789
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
4790
+ RowIdOrNull extends IdOrNull,
3760
4791
  >(
3761
- tableId: TableId,
3762
- cellId: CellIdOrUndefined,
3763
- descending: Descending,
3764
- offset: Offset,
3765
- limit: Limit,
3766
- listener: SortedRowIdsListener<
3767
- Schemas,
3768
- TableId,
3769
- CellIdOrUndefined,
3770
- Descending,
3771
- Offset,
3772
- Limit
3773
- >,
4792
+ tableId: TableIdOrNull,
4793
+ rowId: RowIdOrNull,
4794
+ listener: HasRowListener<Schemas, TableIdOrNull, RowIdOrNull>,
3774
4795
  listenerDeps?: React.DependencyList,
3775
4796
  mutator?: boolean,
3776
4797
  storeOrStoreId?: StoreOrStoreId<Schemas>,
@@ -3959,6 +4980,113 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3959
4980
  storeOrStoreId?: StoreOrStoreId<Schemas>,
3960
4981
  ) => void;
3961
4982
 
4983
+ /**
4984
+ * The useHasCellListener hook registers a listener function with the Store that
4985
+ * will be called when a Cell is added to or removed from the Store.
4986
+ *
4987
+ * This has schema-based typing. The following is a simplified representation:
4988
+ *
4989
+ * ```ts override
4990
+ * useHasCellListener(
4991
+ * tableId: IdOrNull,
4992
+ * rowId: IdOrNull,
4993
+ * cellId: IdOrNull,
4994
+ * listener: HasCellListener,
4995
+ * listenerDeps?: React.DependencyList,
4996
+ * mutator?: boolean,
4997
+ * storeOrStoreId?: StoreOrStoreId,
4998
+ * ): void;
4999
+ * ```
5000
+ *
5001
+ * This hook is useful for situations where a component needs to register its
5002
+ * own specific listener to do more than simply tracking the value (which is
5003
+ * more easily done with the useHasCell hook).
5004
+ *
5005
+ * You can either listen to a single Cell being added or removed (by
5006
+ * specifying the Table Id, Row Id, and Cell Id as the method's first three
5007
+ * parameters) or changes to any Cell (by providing `null` wildcards).
5008
+ *
5009
+ * All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can
5010
+ * be wildcarded with `null`. You can listen to a specific Cell in a specific
5011
+ * Row in a specific Table, any Cell in any Row in any Table, for example - or
5012
+ * every other combination of wildcards.
5013
+ *
5014
+ * Unlike the addHasCellListener method, which returns a listener Id and
5015
+ * requires you to remove it manually, the useHasCellListener hook manages this
5016
+ * lifecycle for you: when the listener changes (per its `listenerDeps`
5017
+ * dependencies) or the component unmounts, the listener on the underlying Store
5018
+ * will be deleted.
5019
+ * @param tableId The Id of the Table to listen to, or `null` as a wildcard.
5020
+ * @param rowId The Id of the Row to listen to, or `null` as a wildcard.
5021
+ * @param cellId The Id of the Cell to listen to, or `null` as a wildcard.
5022
+ * @param listener The function that will be called whenever the matching Cell
5023
+ * is added or removed.
5024
+ * @param listenerDeps An optional array of dependencies for the `listener`
5025
+ * function, which, if any change, result in the re-registration of the
5026
+ * listener. This parameter defaults to an empty array.
5027
+ * @param mutator An optional boolean that indicates that the listener mutates
5028
+ * Store data.
5029
+ * @param storeOrStoreId The Store to register the listener with: omit for the
5030
+ * default context Store, provide an Id for a named context Store, or provide an
5031
+ * explicit reference.
5032
+ * @example
5033
+ * This example uses the useHasCellListener hook to create a listener that is
5034
+ * scoped to a single component. When the component is unmounted, the listener
5035
+ * is removed from the Store.
5036
+ *
5037
+ * ```jsx
5038
+ * const App = ({store}) => (
5039
+ * <Provider store={store}>
5040
+ * <Pane />
5041
+ * </Provider>
5042
+ * );
5043
+ * const Pane = () => {
5044
+ * useHasCellListener('pets', 'fido', 'color', () =>
5045
+ * console.log('Cell existence changed'),
5046
+ * );
5047
+ * return <span>App</span>;
5048
+ * };
5049
+ *
5050
+ * const store = createStore();
5051
+ * const app = document.createElement('div');
5052
+ * const root = ReactDOMClient.createRoot(app);
5053
+ * root.render(<App store={store} />); // !act
5054
+ * console.log(store.getListenerStats().hasCell);
5055
+ * // -> 1
5056
+ *
5057
+ * store.setCell('pets', 'fido', 'color', 'brown'); // !act
5058
+ * // -> 'Cell existence changed'
5059
+ *
5060
+ * root.unmount(); // !act
5061
+ * console.log(store.getListenerStats().hasCell);
5062
+ * // -> 0
5063
+ * ```
5064
+ * @category Store hooks
5065
+ * @since v4.4.0
5066
+ */
5067
+ useHasCellListener: <
5068
+ TableIdOrNull extends TableIdFromSchema<Schemas[0]> | null,
5069
+ RowIdOrNull extends IdOrNull,
5070
+ CellIdOrNull extends
5071
+ | (TableIdOrNull extends TableIdFromSchema<Schemas[0]>
5072
+ ? CellIdFromSchema<Schemas[0], TableIdOrNull>
5073
+ : AllCellIdFromSchema<Schemas[0]>)
5074
+ | null,
5075
+ >(
5076
+ tableId: TableIdOrNull,
5077
+ rowId: RowIdOrNull,
5078
+ cellId: CellIdOrNull,
5079
+ listener: HasCellListener<
5080
+ Schemas,
5081
+ TableIdOrNull,
5082
+ RowIdOrNull,
5083
+ CellIdOrNull
5084
+ >,
5085
+ listenerDeps?: React.DependencyList,
5086
+ mutator?: boolean,
5087
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
5088
+ ) => void;
5089
+
3962
5090
  /**
3963
5091
  * The useCellListener hook registers a listener function with a Store that will
3964
5092
  * be called whenever data in a Cell changes.
@@ -4059,6 +5187,81 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
4059
5187
  storeOrStoreId?: StoreOrStoreId<Schemas>,
4060
5188
  ) => void;
4061
5189
 
5190
+ /**
5191
+ * The useHasValuesListener hook registers a listener function with the Store
5192
+ * that will be called when Values as a whole are added to or removed from the
5193
+ * Store.
5194
+ *
5195
+ * This has schema-based typing. The following is a simplified representation:
5196
+ *
5197
+ * ```ts override
5198
+ * useHasValuesListener(
5199
+ * listener: HasValuesListener,
5200
+ * listenerDeps?: React.DependencyList,
5201
+ * mutator?: boolean,
5202
+ * storeOrStoreId?: StoreOrStoreId,
5203
+ * ): void;
5204
+ * ```
5205
+ *
5206
+ * This hook is useful for situations where a component needs to register its
5207
+ * own specific listener to do more than simply tracking the value (which is
5208
+ * more easily done with the useHasValues hook).
5209
+ *
5210
+ * Unlike the addHasValuesListener method, which returns a listener Id and
5211
+ * requires you to remove it manually, the useHasValuesListener hook manages
5212
+ * this lifecycle for you: when the listener changes (per its `listenerDeps`
5213
+ * dependencies) or the component unmounts, the listener on the underlying Store
5214
+ * will be deleted.
5215
+ * @param listener The function that will be called whenever Values as a whole
5216
+ * are added or removed.
5217
+ * @param listenerDeps An optional array of dependencies for the `listener`
5218
+ * function, which, if any change, result in the re-registration of the
5219
+ * listener. This parameter defaults to an empty array.
5220
+ * @param mutator An optional boolean that indicates that the listener mutates
5221
+ * Store data.
5222
+ * @param storeOrStoreId The Store to register the listener with: omit for the
5223
+ * default context Store, provide an Id for a named context Store, or provide an
5224
+ * explicit reference.
5225
+ * @example
5226
+ * This example uses the useHasValuesListener hook to create a listener that is
5227
+ * scoped to a single component. When the component is unmounted, the listener
5228
+ * is removed from the Store.
5229
+ *
5230
+ * ```jsx
5231
+ * const App = ({store}) => (
5232
+ * <Provider store={store}>
5233
+ * <Pane />
5234
+ * </Provider>
5235
+ * );
5236
+ * const Pane = () => {
5237
+ * useHasValuesListener(() => console.log('Values existence changed'));
5238
+ * return <span>App</span>;
5239
+ * };
5240
+ *
5241
+ * const store = createStore();
5242
+ * const app = document.createElement('div');
5243
+ * const root = ReactDOMClient.createRoot(app);
5244
+ * root.render(<App store={store} />); // !act
5245
+ * console.log(store.getListenerStats().hasValues);
5246
+ * // -> 1
5247
+ *
5248
+ * store.setValue('open', true); // !act
5249
+ * // -> 'Values existence changed'
5250
+ *
5251
+ * root.unmount(); // !act
5252
+ * console.log(store.getListenerStats().hasValues);
5253
+ * // -> 0
5254
+ * ```
5255
+ * @category Store hooks
5256
+ * @since v4.4.0
5257
+ */
5258
+ useHasValuesListener: (
5259
+ listener: HasValuesListener<Schemas>,
5260
+ listenerDeps?: React.DependencyList,
5261
+ mutator?: boolean,
5262
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
5263
+ ) => void;
5264
+
4062
5265
  /**
4063
5266
  * The useValuesListener hook registers a listener function with a Store that
4064
5267
  * will be called whenever keyed value data in it changes.
@@ -4206,6 +5409,91 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
4206
5409
  storeOrStoreId?: StoreOrStoreId<Schemas>,
4207
5410
  ) => void;
4208
5411
 
5412
+ /**
5413
+ * The useHasValueListener hook registers a listener function with the Store
5414
+ * that will be called when a Value is added to or removed from the Store.
5415
+ *
5416
+ * This has schema-based typing. The following is a simplified representation:
5417
+ *
5418
+ * ```ts override
5419
+ * useHasValueListener(
5420
+ * valueId: IdOrNull,
5421
+ * listener: HasValueListener,
5422
+ * listenerDeps?: React.DependencyList,
5423
+ * mutator?: boolean,
5424
+ * storeOrStoreId?: StoreOrStoreId,
5425
+ * ): void;
5426
+ * ```
5427
+ *
5428
+ * This hook is useful for situations where a component needs to register its
5429
+ * own specific listener to do more than simply tracking the value (which is
5430
+ * more easily done with the useHasValue hook).
5431
+ *
5432
+ * You can either listen to a single Value being added or removed (by specifying
5433
+ * the Value Id) or any Value being added or removed (by providing a `null`
5434
+ * wildcard).
5435
+ *
5436
+ * Unlike the addHasValueListener method, which returns a listener Id and
5437
+ * requires you to remove it manually, the useHasValueListener hook manages this
5438
+ * lifecycle for you: when the listener changes (per its `listenerDeps`
5439
+ * dependencies) or the component unmounts, the listener on the underlying Store
5440
+ * will be deleted.
5441
+ * @param valueId The Id of the Value to listen to, or `null` as a wildcard.
5442
+ * @param listener The function that will be called whenever the matching
5443
+ * Value is added or removed.
5444
+ * @param listenerDeps An optional array of dependencies for the `listener`
5445
+ * function, which, if any change, result in the re-registration of the
5446
+ * listener. This parameter defaults to an empty array.
5447
+ * @param mutator An optional boolean that indicates that the listener mutates
5448
+ * Store data.
5449
+ * @param storeOrStoreId The Store to register the listener with: omit for the
5450
+ * default context Store, provide an Id for a named context Store, or provide an
5451
+ * explicit reference.
5452
+ * @example
5453
+ * This example uses the useHasValueListener hook to create a listener that is
5454
+ * scoped to a single component. When the component is unmounted, the listener
5455
+ * is removed from the Store.
5456
+ *
5457
+ * ```jsx
5458
+ * const App = ({store}) => (
5459
+ * <Provider store={store}>
5460
+ * <Pane />
5461
+ * </Provider>
5462
+ * );
5463
+ * const Pane = () => {
5464
+ * useHasValueListener('open', () =>
5465
+ * console.log('Value existence changed'),
5466
+ * );
5467
+ * return <span>App</span>;
5468
+ * };
5469
+ *
5470
+ * const store = createStore();
5471
+ * const app = document.createElement('div');
5472
+ * const root = ReactDOMClient.createRoot(app);
5473
+ * root.render(<App store={store} />); // !act
5474
+ * console.log(store.getListenerStats().hasValue);
5475
+ * // -> 1
5476
+ *
5477
+ * store.setValue('open', false); // !act
5478
+ * // -> 'Value existence changed'
5479
+ *
5480
+ * root.unmount(); // !act
5481
+ * console.log(store.getListenerStats().hasValue);
5482
+ * // -> 0
5483
+ * ```
5484
+ * @category Store hooks
5485
+ * @since v4.4.0
5486
+ */
5487
+ useHasValueListener: <
5488
+ ValueIdOrNull extends ValueIdFromSchema<Schemas[1]> | null,
5489
+ >(
5490
+ valueId: ValueIdOrNull,
5491
+ listener: HasValueListener<Schemas, ValueIdOrNull>,
5492
+ listenerDeps?: React.DependencyList,
5493
+ mutator?: boolean,
5494
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
5495
+ ) => void;
5496
+
4209
5497
  /**
4210
5498
  * The useValueListener hook registers a listener function with a Store that
4211
5499
  * will be called whenever data in a Value changes.