tinybase 7.3.0-beta.0 → 7.3.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.
@@ -981,6 +981,80 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
981
981
  */
982
982
  useTables: (storeOrStoreId?: StoreOrStoreId<Schemas>) => Tables<Schemas[0]>;
983
983
 
984
+ /**
985
+ * The useTablesState hook returns a Tables object and a function to set it,
986
+ * following the same pattern as React's useState hook.
987
+ *
988
+ * This has schema-based typing. The following is a simplified representation:
989
+ *
990
+ * ```ts override
991
+ * useTablesState(
992
+ * storeOrStoreId?: StoreOrStoreId,
993
+ * ): [Tables, (tables: Tables) => void];
994
+ * ```
995
+ *
996
+ * This is a convenience hook that combines the useTables and
997
+ * useSetTablesCallback hooks. It's useful when you need both read and write
998
+ * access to all Tables in a single component.
999
+ *
1000
+ * A Provider component is used to wrap part of an application in a context,
1001
+ * and it can contain a default Store or a set of Store objects named by Id.
1002
+ * The useTablesState hook lets you indicate which Store to use: omit the
1003
+ * parameter for the default context Store, provide an Id for a named context
1004
+ * Store, or provide a Store explicitly by reference.
1005
+ * @param storeOrStoreId The Store to be accessed: omit for the default
1006
+ * context Store, provide an Id for a named context Store, or provide an
1007
+ * explicit reference.
1008
+ * @returns An array containing the Tables object and a function to set it.
1009
+ * @example
1010
+ * This example creates a Store outside the application, which is used in the
1011
+ * useTablesState hook by reference. A button updates the Tables when clicked.
1012
+ *
1013
+ * ```jsx
1014
+ * import {createStore} from 'tinybase';
1015
+ * import React from 'react';
1016
+ * import {createRoot} from 'react-dom/client';
1017
+ * import {useTablesState} from 'tinybase/ui-react';
1018
+ *
1019
+ * const store = createStore().setTables({pets: {fido: {species: 'dog'}}});
1020
+ * const App = () => {
1021
+ * const [tables, setTables] = useTablesState(store);
1022
+ * return (
1023
+ * <div>
1024
+ * {JSON.stringify(tables)}
1025
+ * <button
1026
+ * onClick={() => setTables({...tables, species: {dog: {price: 5}}})}
1027
+ * >
1028
+ * Add
1029
+ * </button>
1030
+ * </div>
1031
+ * );
1032
+ * };
1033
+ *
1034
+ * const app = document.createElement('div');
1035
+ * const root = createRoot(app);
1036
+ * root.render(<App />); // !act
1037
+ * console.log(app.innerHTML);
1038
+ * // -> '<div>{"pets":{"fido":{"species":"dog"}}}<button>Add</button></div>'
1039
+ *
1040
+ * const _button = app.querySelector('button');
1041
+ * // -> _button MouseEvent('click', {bubbles: true})
1042
+ * console.log(app.innerHTML);
1043
+ * // ->
1044
+ * `
1045
+ * <div>
1046
+ * {"pets":{"fido":{"species":"dog"}},"species":{"dog":{"price":5}}}
1047
+ * <button>Add</button>
1048
+ * </div>
1049
+ * `;
1050
+ * ```
1051
+ * @category State hooks
1052
+ * @since v7.3.0
1053
+ */
1054
+ useTablesState: (
1055
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
1056
+ ) => [Tables<Schemas[0]>, (tables: Tables<Schemas[0]>) => void];
1057
+
984
1058
  /**
985
1059
  * The useTableIds hook returns the Ids of every Table in a Store, and registers
986
1060
  * a listener so that any changes to that result will cause a re-render.
@@ -1294,6 +1368,86 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
1294
1368
  storeOrStoreId?: StoreOrStoreId<Schemas>,
1295
1369
  ) => Table<Schemas[0], TableId>;
1296
1370
 
1371
+ /**
1372
+ * The useTableState hook returns a Table and a function to set it, following
1373
+ * the same pattern as React's useState hook.
1374
+ *
1375
+ * This has schema-based typing. The following is a simplified representation:
1376
+ *
1377
+ * ```ts override
1378
+ * useTableState(
1379
+ * tableId: Id,
1380
+ * storeOrStoreId?: StoreOrStoreId,
1381
+ * ): [Table, (table: Table) => void];
1382
+ * ```
1383
+ *
1384
+ * This is a convenience hook that combines the useTable and useSetTableCallback
1385
+ * hooks. It's useful when you need both read and write access to a Table in a
1386
+ * single component.
1387
+ *
1388
+ * A Provider component is used to wrap part of an application in a context,
1389
+ * and it can contain a default Store or a set of Store objects named by Id.
1390
+ * The useTableState hook lets you indicate which Store to use: omit the final
1391
+ * parameter for the default context Store, provide an Id for a named context
1392
+ * Store, or provide a Store explicitly by reference.
1393
+ * @param tableId The Id of the Table in the Store.
1394
+ * @param storeOrStoreId The Store to be accessed: omit for the default
1395
+ * context Store, provide an Id for a named context Store, or provide an
1396
+ * explicit reference.
1397
+ * @returns An array containing the Table and a function to set it.
1398
+ * @example
1399
+ * This example creates a Store outside the application, which is used in the
1400
+ * useTableState hook by reference. A button updates the Table when clicked.
1401
+ *
1402
+ * ```jsx
1403
+ * import {createStore} from 'tinybase';
1404
+ * import React from 'react';
1405
+ * import {createRoot} from 'react-dom/client';
1406
+ * import {useTableState} from 'tinybase/ui-react';
1407
+ *
1408
+ * const store = createStore().setTable('pets', {fido: {species: 'dog'}});
1409
+ * const App = () => {
1410
+ * const [table, setTable] = useTableState('pets', store);
1411
+ * return (
1412
+ * <div>
1413
+ * {JSON.stringify(table)}
1414
+ * <button
1415
+ * onClick={() => setTable({...table, felix: {species: 'cat'}})}
1416
+ * >
1417
+ * Add
1418
+ * </button>
1419
+ * </div>
1420
+ * );
1421
+ * };
1422
+ *
1423
+ * const app = document.createElement('div');
1424
+ * const root = createRoot(app);
1425
+ * root.render(<App />); // !act
1426
+ * console.log(app.innerHTML);
1427
+ * // -> '<div>{"fido":{"species":"dog"}}<button>Add</button></div>'
1428
+ *
1429
+ * const _button = app.querySelector('button');
1430
+ * // -> _button MouseEvent('click', {bubbles: true})
1431
+ * console.log(app.innerHTML);
1432
+ * // ->
1433
+ * `
1434
+ * <div>
1435
+ * {"fido":{"species":"dog"},"felix":{"species":"cat"}}
1436
+ * <button>Add</button>
1437
+ * </div>
1438
+ * `;
1439
+ * ```
1440
+ * @category State hooks
1441
+ * @since v7.3.0
1442
+ */
1443
+ useTableState: <TableId extends TableIdFromSchema<Schemas[0]>>(
1444
+ tableId: TableId,
1445
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
1446
+ ) => [
1447
+ Table<Schemas[0], TableId>,
1448
+ (table: Table<Schemas[0], TableId>) => void,
1449
+ ];
1450
+
1297
1451
  /**
1298
1452
  * The useTableCellIds hook returns the Ids of every Cell used across the whole
1299
1453
  * Table, and registers a listener so that any changes to that result will cause
@@ -2167,6 +2321,78 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
2167
2321
  storeOrStoreId?: StoreOrStoreId<Schemas>,
2168
2322
  ) => Row<Schemas[0], TableId>;
2169
2323
 
2324
+ /**
2325
+ * The useRowState hook returns a Row and a function to set it, following the
2326
+ * same pattern as React's useState hook.
2327
+ *
2328
+ * This has schema-based typing. The following is a simplified representation:
2329
+ *
2330
+ * ```ts override
2331
+ * useRowState(
2332
+ * tableId: Id,
2333
+ * rowId: Id,
2334
+ * storeOrStoreId?: StoreOrStoreId,
2335
+ * ): [Row, (row: Row) => void];
2336
+ * ```
2337
+ *
2338
+ * This is a convenience hook that combines the useRow and useSetRowCallback
2339
+ * hooks. It's useful when you need both read and write access to a Row in a
2340
+ * single component.
2341
+ *
2342
+ * A Provider component is used to wrap part of an application in a context,
2343
+ * and it can contain a default Store or a set of Store objects named by Id.
2344
+ * The useRowState hook lets you indicate which Store to use: omit the final
2345
+ * parameter for the default context Store, provide an Id for a named context
2346
+ * Store, or provide a Store explicitly by reference.
2347
+ * @param tableId The Id of the Table in the Store.
2348
+ * @param rowId The Id of the Row in the Table.
2349
+ * @param storeOrStoreId The Store to be accessed: omit for the default
2350
+ * context Store, provide an Id for a named context Store, or provide an
2351
+ * explicit reference.
2352
+ * @returns An array containing the Row and a function to set it.
2353
+ * @example
2354
+ * This example creates a Store outside the application, which is used in the
2355
+ * useRowState hook by reference. A button updates the Row when clicked.
2356
+ *
2357
+ * ```jsx
2358
+ * import {createStore} from 'tinybase';
2359
+ * import React from 'react';
2360
+ * import {createRoot} from 'react-dom/client';
2361
+ * import {useRowState} from 'tinybase/ui-react';
2362
+ *
2363
+ * const store = createStore().setTable('t1', {r1: {c1: 'Alice', c2: 30}});
2364
+ * const App = () => {
2365
+ * const [row, setRow] = useRowState('t1', 'r1', store);
2366
+ * return (
2367
+ * <div>
2368
+ * {JSON.stringify(row)}
2369
+ * <button onClick={() => setRow({...row, c2: (row.c2 || 0) + 1})}>
2370
+ * Birthday
2371
+ * </button>
2372
+ * </div>
2373
+ * );
2374
+ * };
2375
+ *
2376
+ * const app = document.createElement('div');
2377
+ * const root = createRoot(app);
2378
+ * root.render(<App />); // !act
2379
+ * console.log(app.innerHTML);
2380
+ * // -> '<div>{\"c1\":\"Alice\",\"c2\":30}<button>Birthday</button></div>'
2381
+ *
2382
+ * const _button = app.querySelector('button');
2383
+ * // -> _button MouseEvent('click', {bubbles: true})
2384
+ * console.log(app.innerHTML);
2385
+ * // -> '<div>{\"c1\":\"Alice\",\"c2\":31}<button>Birthday</button></div>'
2386
+ * ```
2387
+ * @category State hooks
2388
+ * @since v7.3.0
2389
+ */
2390
+ useRowState: <TableId extends TableIdFromSchema<Schemas[0]>>(
2391
+ tableId: TableId,
2392
+ rowId: Id,
2393
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
2394
+ ) => [Row<Schemas[0], TableId>, (row: Row<Schemas[0], TableId>) => void];
2395
+
2170
2396
  /**
2171
2397
  * The useCellIds hook returns the Ids of every Cell in a given Row, in a given
2172
2398
  * Table, and registers a listener so that any changes to that result will cause
@@ -2521,6 +2747,88 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
2521
2747
  storeOrStoreId?: StoreOrStoreId<Schemas>,
2522
2748
  ) => NoInfer<CellOrUndefined<Schemas[0], TableId, CellId>>;
2523
2749
 
2750
+ /**
2751
+ * The useCellState hook returns a Cell from a Store and a callback to set it,
2752
+ * following the common React `useState` convention.
2753
+ *
2754
+ * This has schema-based typing. The following is a simplified representation:
2755
+ *
2756
+ * ```ts override
2757
+ * useCellState(
2758
+ * tableId: Id,
2759
+ * rowId: Id,
2760
+ * cellId: Id,
2761
+ * storeOrStoreId?: StoreOrStoreId,
2762
+ * ): [CellOrUndefined, (cell: Cell) => void];
2763
+ * ```
2764
+ *
2765
+ * This hook is useful for creating components that read and write a Cell in a
2766
+ * single line, similar to how you would use React's `useState` hook.
2767
+ *
2768
+ * The component this is used in will re-render when the Cell changes.
2769
+ * @param tableId The Id of the Table in the Store.
2770
+ * @param rowId The Id of the Row in the Table.
2771
+ * @param cellId The Id of the Cell in the Row.
2772
+ * @param storeOrStoreId The Store to get data from: omit for the default
2773
+ * context Store, provide an Id for a named context Store, or provide an
2774
+ * explicit reference.
2775
+ * @returns A tuple containing the current Cell and a setter callback that can
2776
+ * be called with a new Cell value.
2777
+ * @example
2778
+ * This example creates a Store outside the application, which is used in the
2779
+ * useCellState hook by reference.
2780
+ *
2781
+ * ```jsx
2782
+ * import {createRoot} from 'react-dom/client';
2783
+ * import {createStore} from 'tinybase';
2784
+ * import React from 'react';
2785
+ * import {useCellState} from 'tinybase/ui-react';
2786
+ *
2787
+ * const store = createStore().setCell('pets', 'fido', 'visits', 0);
2788
+ * const App = () => {
2789
+ * const [visits, setVisits] = useCellState(
2790
+ * 'pets',
2791
+ * 'fido',
2792
+ * 'visits',
2793
+ * store,
2794
+ * );
2795
+ * return (
2796
+ * <span>
2797
+ * Visits: {visits}
2798
+ * <button onClick={() => setVisits(visits + 1)}>Visit</button>
2799
+ * </span>
2800
+ * );
2801
+ * };
2802
+ *
2803
+ * const app = document.createElement('div');
2804
+ * const root = createRoot(app);
2805
+ * root.render(<App />); // !act
2806
+ * console.log(app.innerHTML);
2807
+ * // -> '<span>Visits: 0<button>Visit</button></span>'
2808
+ *
2809
+ * const _button = app.querySelector('button');
2810
+ * // -> _button MouseEvent('click', {bubbles: true})
2811
+ * console.log(app.innerHTML);
2812
+ * // -> '<span>Visits: 1<button>Visit</button></span>'
2813
+ *
2814
+ * root.unmount(); // !act
2815
+ * ```
2816
+ * @category State hooks
2817
+ * @since v7.3.0
2818
+ */
2819
+ useCellState: <
2820
+ TableId extends TableIdFromSchema<Schemas[0]>,
2821
+ CellId extends CellIdFromSchema<Schemas[0], TableId>,
2822
+ >(
2823
+ tableId: TableId,
2824
+ rowId: Id,
2825
+ cellId: CellId,
2826
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
2827
+ ) => [
2828
+ CellOrUndefined<Schemas[0], TableId, CellId>,
2829
+ (cell: Cell<Schemas[0], TableId, CellId>) => void,
2830
+ ];
2831
+
2524
2832
  /**
2525
2833
  * The useHasValues hook returns a boolean indicating whether any Values exist
2526
2834
  * in the Store, and registers a listener so that any changes to that result
@@ -2718,6 +3026,72 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
2718
3026
  */
2719
3027
  useValues: (storeOrStoreId?: StoreOrStoreId<Schemas>) => Values<Schemas[1]>;
2720
3028
 
3029
+ /**
3030
+ * The useValuesState hook returns a Values object and a function to set it,
3031
+ * following the same pattern as React's useState hook.
3032
+ *
3033
+ * This has schema-based typing. The following is a simplified representation:
3034
+ *
3035
+ * ```ts override
3036
+ * useValuesState(
3037
+ * storeOrStoreId?: StoreOrStoreId,
3038
+ * ): [Values, (values: Values) => void];
3039
+ * ```
3040
+ *
3041
+ * This is a convenience hook that combines the useValues and
3042
+ * useSetValuesCallback hooks. It's useful when you need both read and write
3043
+ * access to all Values in a single component.
3044
+ *
3045
+ * A Provider component is used to wrap part of an application in a context,
3046
+ * and it can contain a default Store or a set of Store objects named by Id.
3047
+ * The useValuesState hook lets you indicate which Store to use: omit the
3048
+ * parameter for the default context Store, provide an Id for a named context
3049
+ * Store, or provide a Store explicitly by reference.
3050
+ * @param storeOrStoreId The Store to be accessed: omit for the default
3051
+ * context Store, provide an Id for a named context Store, or provide an
3052
+ * explicit reference.
3053
+ * @returns An array containing the Values object and a function to set it.
3054
+ * @example
3055
+ * This example creates a Store outside the application, which is used in the
3056
+ * useValuesState hook by reference. A button updates the Values when clicked.
3057
+ *
3058
+ * ```jsx
3059
+ * import {createStore} from 'tinybase';
3060
+ * import React from 'react';
3061
+ * import {createRoot} from 'react-dom/client';
3062
+ * import {useValuesState} from 'tinybase/ui-react';
3063
+ *
3064
+ * const store = createStore().setValues({open: true});
3065
+ * const App = () => {
3066
+ * const [values, setValues] = useValuesState(store);
3067
+ * return (
3068
+ * <div>
3069
+ * {JSON.stringify(values)}
3070
+ * <button onClick={() => setValues({...values, employees: 3})}>
3071
+ * Add
3072
+ * </button>
3073
+ * </div>
3074
+ * );
3075
+ * };
3076
+ *
3077
+ * const app = document.createElement('div');
3078
+ * const root = createRoot(app);
3079
+ * root.render(<App />); // !act
3080
+ * console.log(app.innerHTML);
3081
+ * // -> '<div>{"open":true}<button>Add</button></div>'
3082
+ *
3083
+ * const _button = app.querySelector('button');
3084
+ * // -> _button MouseEvent('click', {bubbles: true})
3085
+ * console.log(app.innerHTML);
3086
+ * // -> '<div>{"open":true,"employees":3}<button>Add</button></div>'
3087
+ * ```
3088
+ * @category State hooks
3089
+ * @since v7.3.0
3090
+ */
3091
+ useValuesState: (
3092
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
3093
+ ) => [Values<Schemas[1]>, (values: Values<Schemas[1]>) => void];
3094
+
2721
3095
  /**
2722
3096
  * The useValueIds hook returns the Ids of every Value in a Store, and registers
2723
3097
  * a listener so that any changes to that result will cause a re-render.
@@ -3035,6 +3409,75 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
3035
3409
  storeOrStoreId?: StoreOrStoreId<Schemas>,
3036
3410
  ) => DefaultedValueFromSchema<Schemas[1], ValueId>;
3037
3411
 
3412
+ /**
3413
+ * The useValueState hook returns a Value from a Store and a callback to set it,
3414
+ * following the common React `useState` convention.
3415
+ *
3416
+ * This has schema-based typing. The following is a simplified representation:
3417
+ *
3418
+ * ```ts override
3419
+ * useValueState(
3420
+ * valueId: Id,
3421
+ * storeOrStoreId?: StoreOrStoreId,
3422
+ * ): [value: ValueOrUndefined, setValue: (value: Value) => void];
3423
+ * ```
3424
+ *
3425
+ * This hook is useful for creating components that read and write a Value in a
3426
+ * single line, similar to how you would use React's `useState` hook.
3427
+ *
3428
+ * The component this is used in will re-render when the Value changes.
3429
+ * @param valueId The Id of the Value.
3430
+ * @param storeOrStoreId The Store to get data from: omit for the default
3431
+ * context Store, provide an Id for a named context Store, or provide an
3432
+ * explicit reference.
3433
+ * @returns A tuple containing the current Value and a setter callback that can
3434
+ * be called with a new Value.
3435
+ * @example
3436
+ * This example creates a Store outside the application, which is used in the
3437
+ * useValueState hook by reference.
3438
+ *
3439
+ * ```jsx
3440
+ * import {createRoot} from 'react-dom/client';
3441
+ * import {createStore} from 'tinybase';
3442
+ * import React from 'react';
3443
+ * import {useValueState} from 'tinybase/ui-react';
3444
+ *
3445
+ * const store = createStore().setValues({employees: 3});
3446
+ * const App = () => {
3447
+ * const [employees, setEmployees] = useValueState('employees', store);
3448
+ * return (
3449
+ * <span>
3450
+ * Employees: {employees}
3451
+ * <button onClick={() => setEmployees(employees + 1)}>Hire</button>
3452
+ * </span>
3453
+ * );
3454
+ * };
3455
+ *
3456
+ * const app = document.createElement('div');
3457
+ * const root = createRoot(app);
3458
+ * root.render(<App />); // !act
3459
+ * console.log(app.innerHTML);
3460
+ * // -> '<span>Employees: 3<button>Hire</button></span>'
3461
+ *
3462
+ * const _button = app.querySelector('button');
3463
+ * // -> _button MouseEvent('click', {bubbles: true})
3464
+ *
3465
+ * console.log(app.innerHTML);
3466
+ * // -> '<span>Employees: 4<button>Hire</button></span>'
3467
+ *
3468
+ * root.unmount(); // !act
3469
+ * ```
3470
+ * @category State hooks
3471
+ * @since v7.3.0
3472
+ */
3473
+ useValueState: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
3474
+ valueId: ValueId,
3475
+ storeOrStoreId?: StoreOrStoreId<Schemas>,
3476
+ ) => [
3477
+ value: DefaultedValueFromSchema<Schemas[1], ValueId>,
3478
+ setValue: (value: Value<Schemas[1], ValueId>) => void,
3479
+ ];
3480
+
3038
3481
  /**
3039
3482
  * The useSetTablesCallback hook returns a parameterized callback that can be
3040
3483
  * used to set the tabular data of a Store.
@@ -11788,7 +12231,7 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
11788
12231
  * useParamValues(
11789
12232
  * queryId: Id,
11790
12233
  * queriesOrQueriesId?: QueriesOrQueriesId,
11791
- * ): ParamValues | undefined;
12234
+ * ): ParamValues;
11792
12235
  * ```
11793
12236
  *
11794
12237
  * A Provider component is used to wrap part of an application in a context, and
@@ -11933,7 +12376,93 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
11933
12376
  useParamValues: (
11934
12377
  queryId: Id,
11935
12378
  queriesOrQueriesId?: QueriesOrQueriesId<Schemas>,
11936
- ) => ParamValues | undefined;
12379
+ ) => ParamValues;
12380
+
12381
+ /**
12382
+ * The useParamValuesState hook returns an array containing all the parameter
12383
+ * values for a query, and a callback for changing them, providing an easy way
12384
+ * to bind a query's parameters to a user-controlled component.
12385
+ *
12386
+ * This has schema-based typing. The following is a simplified representation:
12387
+ *
12388
+ * ```ts override
12389
+ * useParamValuesState(
12390
+ * queryId: Id,
12391
+ * queriesOrQueriesId?: QueriesOrQueriesId,
12392
+ * ): [ParamValues, (paramValues: ParamValues) => void];
12393
+ * ```
12394
+ *
12395
+ * This is a convenience hook that combines the useParamValues and
12396
+ * useSetParamValuesCallback hooks. It's useful when you need both read and
12397
+ * write access to query parameters in a single component.
12398
+ *
12399
+ * A Provider component is used to wrap part of an application in a context,
12400
+ * and it can contain a default Queries object or a set of Queries objects
12401
+ * named by Id. The useParamValuesState hook lets you indicate which Queries
12402
+ * object to use: omit the final parameter for the default context Queries
12403
+ * object, provide an Id for a named context Queries object, or provide an
12404
+ * explicit reference.
12405
+ * @param queryId The Id of the query.
12406
+ * @param queriesOrQueriesId The Queries object to be accessed: omit for the
12407
+ * default context Queries object, provide an Id for a named context Queries
12408
+ * object, or provide an explicit reference.
12409
+ * @returns An array containing the parameter values and a function to set them.
12410
+ * @example
12411
+ * This example creates a Queries object outside the application, which is used
12412
+ * in the useParamValuesState hook by reference. A button updates the parameters
12413
+ * when clicked.
12414
+ *
12415
+ * ```jsx
12416
+ * import {createQueries, createStore} from 'tinybase';
12417
+ * import React from 'react';
12418
+ * import {createRoot} from 'react-dom/client';
12419
+ * import {useParamValuesState} from 'tinybase/ui-react';
12420
+ *
12421
+ * const store = createStore().setTable('pets', {
12422
+ * fido: {species: 'dog'},
12423
+ * felix: {species: 'cat'},
12424
+ * cujo: {species: 'dog'},
12425
+ * });
12426
+ * const queries = createQueries(store);
12427
+ * queries.setQueryDefinition(
12428
+ * 'petsBySpecies',
12429
+ * 'pets',
12430
+ * ({select, where, param}) => {
12431
+ * select('species');
12432
+ * where('species', param('species'));
12433
+ * },
12434
+ * {species: 'dog'},
12435
+ * );
12436
+ *
12437
+ * const App = () => {
12438
+ * const [paramValues, setParamValues] = useParamValuesState(
12439
+ * 'petsBySpecies',
12440
+ * queries,
12441
+ * );
12442
+ * return (
12443
+ * <button onClick={() => setParamValues({species: 'cat'})}>
12444
+ * {JSON.stringify(paramValues)}
12445
+ * </button>
12446
+ * );
12447
+ * };
12448
+ *
12449
+ * const app = document.createElement('div');
12450
+ * createRoot(app).render(<App />); // !act
12451
+ * console.log(app.innerHTML);
12452
+ * // -> '<button>{"species":"dog"}</button>'
12453
+ *
12454
+ * const _button = app.querySelector('button');
12455
+ * // -> _button MouseEvent('click', {bubbles: true})
12456
+ * console.log(app.innerHTML);
12457
+ * // -> '<button>{"species":"cat"}</button>'
12458
+ * ```
12459
+ * @category State hooks
12460
+ * @since v7.3.0
12461
+ */
12462
+ useParamValuesState: (
12463
+ queryId: Id,
12464
+ queriesOrQueriesId?: QueriesOrQueriesId<Schemas>,
12465
+ ) => [ParamValues, (paramValues: ParamValues) => void];
11937
12466
 
11938
12467
  /**
11939
12468
  * The useParamValue hook returns the current value of a single parameter in a
@@ -12092,6 +12621,95 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
12092
12621
  queriesOrQueriesId?: QueriesOrQueriesId<Schemas>,
12093
12622
  ) => ParamValue | undefined;
12094
12623
 
12624
+ /**
12625
+ * The useParamValueState hook returns a parameter value and a function to set
12626
+ * it, following the same pattern as React's useState hook.
12627
+ *
12628
+ * This has schema-based typing. The following is a simplified representation:
12629
+ *
12630
+ * ```ts override
12631
+ * useParamValueState(
12632
+ * queryId: Id,
12633
+ * paramId: Id,
12634
+ * queriesOrQueriesId?: QueriesOrQueriesId,
12635
+ * ): [ParamValue | undefined, (paramValue: ParamValue) => void];
12636
+ * ```
12637
+ *
12638
+ * This is a convenience hook that combines the useParamValue and
12639
+ * useSetParamValueCallback hooks. It's useful when you need both read and write
12640
+ * access to a query parameter in a single component.
12641
+ *
12642
+ * A Provider component is used to wrap part of an application in a context,
12643
+ * and it can contain a default Queries object or a set of Queries objects
12644
+ * named by Id. The useParamValueState hook lets you indicate which Queries
12645
+ * object to use: omit the final parameter for the default context Queries
12646
+ * object, provide an Id for a named context Queries object, or provide an
12647
+ * explicit reference.
12648
+ * @param queryId The Id of the query.
12649
+ * @param paramId The Id of the parameter.
12650
+ * @param queriesOrQueriesId The Queries object to be accessed: omit for the
12651
+ * default context Queries object, provide an Id for a named context Queries
12652
+ * object, or provide an explicit reference.
12653
+ * @returns An array containing the parameter value and a function to set it.
12654
+ * @example
12655
+ * This example creates a Queries object outside the application, which is used
12656
+ * in the useParamValueState hook by reference. A button updates the parameter
12657
+ * when clicked.
12658
+ *
12659
+ * ```jsx
12660
+ * import {createQueries, createStore} from 'tinybase';
12661
+ * import React from 'react';
12662
+ * import {createRoot} from 'react-dom/client';
12663
+ * import {useParamValueState} from 'tinybase/ui-react';
12664
+ *
12665
+ * const store = createStore().setTable('pets', {
12666
+ * fido: {species: 'dog'},
12667
+ * felix: {species: 'cat'},
12668
+ * });
12669
+ * const queries = createQueries(store);
12670
+ * queries.setQueryDefinition(
12671
+ * 'petsBySpecies',
12672
+ * 'pets',
12673
+ * ({select, where, param}) => {
12674
+ * select('species');
12675
+ * where('species', param('species'));
12676
+ * },
12677
+ * {species: 'dog'},
12678
+ * );
12679
+ * const App = () => {
12680
+ * const [species, setSpecies] = useParamValueState(
12681
+ * 'petsBySpecies',
12682
+ * 'species',
12683
+ * queries,
12684
+ * );
12685
+ * return (
12686
+ * <div>
12687
+ * Species: {species}
12688
+ * <button onClick={() => setSpecies('cat')}>Change</button>
12689
+ * </div>
12690
+ * );
12691
+ * };
12692
+ *
12693
+ * const app = document.createElement('div');
12694
+ * const root = createRoot(app);
12695
+ * root.render(<App />); // !act
12696
+ * console.log(app.innerHTML);
12697
+ * // -> '<div>Species: dog<button>Change</button></div>'
12698
+ *
12699
+ * const _button = app.querySelector('button');
12700
+ * // -> _button MouseEvent('click', {bubbles: true})
12701
+ * console.log(app.innerHTML);
12702
+ * // -> '<div>Species: cat<button>Change</button></div>'
12703
+ * ```
12704
+ * @category State hooks
12705
+ * @since v7.3.0
12706
+ */
12707
+ useParamValueState: (
12708
+ queryId: Id,
12709
+ paramId: Id,
12710
+ queriesOrQueriesId?: QueriesOrQueriesId<Schemas>,
12711
+ ) => [ParamValue | undefined, (paramValue: ParamValue) => void];
12712
+
12095
12713
  /**
12096
12714
  * The useParamValuesListener hook registers a listener function with a Queries
12097
12715
  * object that will be called whenever the parameter values for a query change.