tinybase
Version:
A reactive data store and sync engine.
1,382 lines (1,357 loc) • 607 kB
TypeScript
/**
* The ui-react module of the TinyBase project provides both hooks and
* components to make it easy to create reactive apps with Store objects.
*
* The hooks in this module provide access to the data and structures exposed by
* other modules in the project. As well as immediate access, they all register
* listeners such that components using those hooks are selectively re-rendered
* when data changes.
*
* The components in this module provide a further abstraction over those hooks
* to ease the composition of user interfaces that use TinyBase.
* @see Building UIs guides
* @see Building UIs With Metrics guide
* @see Building UIs With Indexes guide
* @see Building UIs With Relationships guide
* @see Building UIs With Queries guide
* @see Building UIs With Checkpoints guide
* @see Countries demo
* @see Todo App demos
* @see Drawing demo
* @packageDocumentation
* @module ui-react
* @since v1.0.0
*/
import type {
CheckpointIds,
CheckpointIdsListener,
CheckpointListener,
Checkpoints,
} from '../checkpoints/index.d.ts';
import type {
Callback,
Id,
IdOrNull,
Ids,
ParameterizedCallback,
} from '../common/index.d.ts';
import type {
Indexes,
SliceIdsListener,
SliceRowIdsListener,
} from '../indexes/index.d.ts';
import type {MergeableStore} from '../mergeable-store/index.d.ts';
import type {MetricListener, Metrics} from '../metrics/index.d.ts';
import type {
AnyPersister,
PersistedStore,
Persister,
Persists,
Status,
StatusListener,
} from '../persisters/index.d.ts';
import type {
Queries,
ResultCellIdsListener,
ResultCellListener,
ResultRowCountListener,
ResultRowIdsListener,
ResultRowListener,
ResultSortedRowIdsListener,
ResultTableCellIdsListener,
ResultTableListener,
} from '../queries/index.d.ts';
import type {
LinkedRowIdsListener,
LocalRowIdsListener,
Relationships,
RemoteRowIdListener,
} from '../relationships/index.d.ts';
import type {
Cell,
CellIdsListener,
CellListener,
CellOrUndefined,
HasCellListener,
HasRowListener,
HasTableCellListener,
HasTableListener,
HasTablesListener,
HasValueListener,
HasValuesListener,
MapCell,
MapValue,
Row,
RowCountListener,
RowIdsListener,
RowListener,
SortedRowIdsListener,
Store,
Table,
TableCellIdsListener,
TableIdsListener,
TableListener,
Tables,
TablesListener,
TransactionListener,
Value,
ValueIdsListener,
ValueListener,
ValueOrUndefined,
Values,
ValuesListener,
} from '../store/index.d.ts';
import type {Synchronizer} from '../synchronizers/index.d.ts';
import type {ComponentType, ReactElement} from 'react';
/**
* The StoreOrStoreId type is used when you need to refer to a Store in a React
* hook or component.
*
* In some simple cases you will already have a direct reference to the Store.
*
* This module also includes a Provider component that can be used to wrap
* multiple Store objects into a context that can be used throughout the app. In
* this case you will want to refer to a Store by its Id in that context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Store or its Id.
* @category Identity
* @since v1.0.0
*/
export type StoreOrStoreId = Store | Id;
/**
* The MetricsOrMetricsId type is used when you need to refer to a Metrics
* object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the Metrics
* object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Metrics objects into a context that can be used throughout the app.
* In this case you will want to refer to a Metrics object by its Id in that
* context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Metrics object or its
* Id.
* @category Identity
* @since v1.0.0
*/
export type MetricsOrMetricsId = Metrics | Id;
/**
* The IndexesOrIndexesId type is used when you need to refer to an Indexes
* object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the Indexes
* object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Indexes objects into a context that can be used throughout the app.
* In this case you will want to refer to an Indexes object by its Id in that
* context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Indexes object or its
* Id.
* @category Identity
* @since v1.0.0
*/
export type IndexesOrIndexesId = Indexes | Id;
/**
* The RelationshipsOrRelationshipsId type is used when you need to refer to a
* Relationships object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the
* Relationships object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Relationships objects into a context that can be used throughout the
* app. In this case you will want to refer to a Relationships object by its Id
* in that context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Relationships object
* or its Id.
* @category Identity
* @since v1.0.0
*/
export type RelationshipsOrRelationshipsId = Relationships | Id;
/**
* The QueriesOrQueriesId type is used when you need to refer to a Queries
* object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the Queries
* object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Queries objects into a context that can be used throughout the app.
* In this case you will want to refer to a Queries object by its Id in that
* context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Queries object or its
* Id.
* @category Identity
* @since v2.0.0
*/
export type QueriesOrQueriesId = Queries | Id;
/**
* The CheckpointsOrCheckpointsId type is used when you need to refer to a
* Checkpoints object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the
* Checkpoints object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Checkpoints objects into a context that can be used throughout the
* app. In this case you will want to refer to a Checkpoints object by its Id in
* that context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Checkpoints object or
* its Id.
* @category Identity
* @since v1.0.0
*/
export type CheckpointsOrCheckpointsId = Checkpoints | Id;
/**
* The PersisterOrPersisterId type is used when you need to refer to a Persister
* object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the
* Persister object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Persister objects into a context that can be used throughout the
* app. In this case you will want to refer to a Persister object by its Id in
* that context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Persister or its Id.
* @category Identity
* @since v5.3.0
*/
export type PersisterOrPersisterId = AnyPersister | Id;
/**
* The SynchronizerOrSynchronizerId type is used when you need to refer to a
* Synchronizer object in a React hook or component.
*
* In some simple cases you will already have a direct reference to the
* Synchronizer object.
*
* This module also includes a Provider component that can be used to wrap
* multiple Synchronizer objects into a context that can be used throughout the
* app. In this case you will want to refer to a Synchronizer object by its Id
* in that context.
*
* Many hooks and components in this ui-react module take this type as a
* parameter or a prop, allowing you to pass in either the Synchronizer or its
* Id.
* @category Identity
* @since v5.3.0
*/
export type SynchronizerOrSynchronizerId = Synchronizer | Id;
/**
* The UndoOrRedoInformation type is an array that you can fetch from a
* Checkpoints object to that indicates if and how you can move the state of the
* underlying Store forward or backward.
*
* This type is useful if you are building undo or redo buttons. See the
* useUndoInformation hook and the useRedoInformation hook for more details and
* examples.
* @category Checkpoints
* @since v1.0.0
*/
export type UndoOrRedoInformation = [boolean, Callback, Id | undefined, string];
/**
* The GetId type describes a function which, when passed a parameter, will
* return an Id.
*
* This type is used in hooks that create callbacks - like the
* useSetTableCallback hook or useSetRowCallback hook - so that the Id arguments
* of the object to set can also be dependent on the event or parameter provided
* (as well as the object itself being set).
* @category Identity
* @since v1.0.0
*/
export type GetId<Parameter> = (parameter: Parameter, store: Store) => Id;
/**
* The useCreateStore hook is used to create a Store within a React application
* with convenient memoization.
*
* It is possible to create a Store outside of the React app with the regular
* createStore function and pass it in, but you may prefer to create it within
* the app, perhaps inside the top-level component. To prevent a new Store being
* created every time the app renders or re-renders, the useCreateStore hook
* wraps the creation in a memoization.
*
* The useCreateStore hook is a very thin wrapper around the React `useMemo`
* hook, defaulting to an empty array for its dependencies, so that by default,
* the creation only occurs once.
*
* If your `create` function contains other dependencies, the changing of which
* should cause the Store to be recreated, you can provide them in an array in
* the optional second parameter, just as you would for any React hook with
* dependencies.
* @param create A function for performing the creation of the Store, plus any
* additional steps such as adding data or listeners, and returning it.
* @param createDeps An optional array of dependencies for the `create`
* function, which, if any change, result in its rerun. This parameter defaults
* to an empty array.
* @returns A reference to the Store.
* @example
* This example creates an empty Store at the top level of a React application.
* Even though the App component is rendered twice, the Store creation only
* occurs once by default.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useCreateStore} from 'tinybase/ui-react';
*
* const App = () => {
* const store = useCreateStore(() => {
* console.log('Store created');
* return createStore().setTables({pets: {fido: {species: 'dog'}}});
* });
* return <span>{store.getCell('pets', 'fido', 'species')}</span>;
* };
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* // -> 'Store created'
*
* root.render(<App />); // !act
* // No second Store creation
*
* console.log(app.innerHTML);
* // -> '<span>dog</span>'
* ```
* @example
* This example creates an empty Store at the top level of a React application.
* The App component is rendered twice, each with a different top-level prop.
* The useCreateStore hook takes the `fidoSpecies` prop as a dependency, and so
* the Store is created again on the second render.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useCreateStore} from 'tinybase/ui-react';
*
* const App = ({fidoSpecies}) => {
* const store = useCreateStore(() => {
* console.log(`Store created for fido as ${fidoSpecies}`);
* return createStore().setTables({pets: {fido: {species: fidoSpecies}}});
* }, [fidoSpecies]);
* return <span>{store.getCell('pets', 'fido', 'species')}</span>;
* };
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App fidoSpecies="dog" />); // !act
* // -> 'Store created for fido as dog'
*
* console.log(app.innerHTML);
* // -> '<span>dog</span>'
*
* root.render(<App fidoSpecies="cat" />); // !act
* // -> 'Store created for fido as cat'
*
* console.log(app.innerHTML);
* // -> '<span>cat</span>'
* ```
* @category Store hooks
* @since v1.0.0
*/
export function useCreateStore(
create: () => Store,
createDeps?: React.DependencyList,
): Store;
/**
* The useCreateMergeableStore hook.
* @category Store hooks
* @since v1.0.0
*/
export function useCreateMergeableStore(
create: () => MergeableStore,
createDeps?: React.DependencyList,
): MergeableStore;
/**
* The useStoreIds hook is used to retrieve the Ids of all the named Store
* objects present in the current Provider component context.
* @returns A list of the Ids in the context.
* @example
* This example adds two named Store objects to a Provider context and an inner
* component accesses their Ids.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useCreateStore, useStoreIds} from 'tinybase/ui-react';
*
* const App = () => {
* const store1 = useCreateStore(createStore);
* const store2 = useCreateStore(createStore);
* return (
* <Provider storesById={{store1, store2}}>
* <Pane />
* </Provider>
* );
* };
* const Pane = () => <span>{JSON.stringify(useStoreIds())}</span>;
*
* const app = document.createElement('div');
* createRoot(app).render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>["store1","store2"]</span>'
* ```
* @category Store hooks
* @since v4.1.0
*/
export function useStoreIds(): Ids;
/**
* The useStore hook is used to get a reference to a Store from within a
* Provider component context.
*
* A Provider component is used to wrap part of an application in a context. It
* can contain a default Store (or a set of Store objects named by Id) that can
* be easily accessed without having to be passed down as props through every
* component.
*
* The useStore hook lets you either get a reference to the default Store (when
* called without a parameter), or one of the Store objects that are named by Id
* (when called with an Id parameter).
* @param id An optional Id for accessing a Store that was named with an Id in
* the Provider.
* @returns A reference to the Store (or `undefined` if not within a Provider
* context, or if the requested Store does not exist).
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useStore hook to get a
* reference to the Store again, without the need to have it passed as a prop.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useStore} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{useStore().getListenerStats().tables}</span>;
*
* const store = createStore();
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>0</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useStore hook with that Id to get
* a reference to the Store again, without the need to have it passed as a prop.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useStore} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{useStore('petStore').getListenerStats().tables}</span>
* );
*
* const store = createStore();
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>0</span>'
* ```
* @category Store hooks
* @since v1.0.0
*/
export function useStore(id?: Id): Store | undefined;
/**
* The useStores hook is used to get a reference to all the Store objects named
* by Id within a Provider component context.
*
* A Provider component is used to wrap part of an application in a context. It
* can contain a default Store (or a set of Store objects named by Id) that can
* be easily accessed without having to be passed down as props through every
* component.
*
* The useStores hook lets you get a reference to the latter as an object.
* @returns An object containing all the Store objects named by Id.
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useStores hook to get a reference
* to the Store again.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useStores} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{useStores()['petStore'].getListenerStats().tables}</span>
* );
*
* const store = createStore();
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>0</span>'
* ```
* @category Store hooks
* @since v5.4.1
*/
export function useStores(): {[storeId: Id]: Store};
/**
* The useStoreOrStoreById hook is used to get a reference to a Store object
* from within a Provider component context, _or_ have it passed directly to
* this hook.
*
* This is mostly of use when you are developing a component that needs a Store
* object and which might have been passed in explicitly to the component or is
* to be picked up from the context by Id (a common pattern for Store-based
* components).
*
* This is unlikely to be used often. For most situations, you will want to use
* the useStore hook.
* @param storeOrStoreId Either an Id for accessing a Store object that was
* named with an Id in the Provider, or the Store object itself.
* @returns A reference to the Store object (or `undefined` if not within a
* Provider context, or if the requested Store object does not exist).
* @example
* This example creates a Provider context into which a default Store object is
* provided. A component within it then uses the useStoreOrStoreById hook to get
* a reference to the Store object again, without the need to have it passed as
* a prop. Note however, that unlike the useStore hook example, this component
* would also work if you were to pass the Store object directly into it, making
* it more portable.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useStoreOrStoreById} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = ({store}) => (
* <span>{JSON.stringify(useStoreOrStoreById(store).getTableIds())}</span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets"]</span>'
* ```
* @category Store hooks
* @since v4.1.0
*/
export function useStoreOrStoreById(
storeOrStoreId?: StoreOrStoreId,
): Store | undefined;
/**
* The useProvideStore hook is used to add a Store object by Id to a Provider
* component, but imperatively from a component within it.
*
* Normally you will register a Store by Id in a context by using the
* `storesById` prop of the top-level Provider component. This hook, however,
* lets you dynamically add a new Store to the context, from within a descendent
* component. This is useful for applications where the set of Stores is not
* known at the time of the first render of the root Provider.
*
* A Store added to the Provider context in this way will be available to other
* components within the context (using the useStore hook and so on). If you use
* the same Id as an existing Store registration, the new one will take priority
* over one provided by the `storesById` prop.
*
* Note that other components that consume a Store registered like this should
* defend against it being undefined at first. On the first render, the other
* component will likely not yet have completed the registration. In the example
* below, we use the null-safe `useStore('petStore')?` to do this.
* @param storeId The Id of the Store object to be registered with the Provider.
* @param store The Store object to be registered.
* @example
* This example creates a Provider context. A child component registers a Store
* into it which is then consumable by a peer child component.
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {
* Provider,
* useCreateStore,
* useProvideStore,
* useStore,
* } from 'tinybase/ui-react';
*
* const App = () => (
* <Provider>
* <RegisterStore />
* <ConsumeStore />
* </Provider>
* );
* const RegisterStore = () => {
* const store = useCreateStore(() =>
* createStore().setCell('pets', 'fido', 'color', 'brown'),
* );
* useProvideStore('petStore', store);
* return null;
* };
* const ConsumeStore = () => (
* <span>{JSON.stringify(useStore('petStore')?.getTableIds())}</span>
* );
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets"]</span>'
* ```
* @category Store hooks
* @since v4.4.2
*/
export function useProvideStore(storeId: Id, store: Store): void;
/**
* The useHasTables hook returns a boolean indicating whether any Table objects
* exist in the Store, and registers a listener so that any changes to that
* result will cause a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useHasTables hook lets you indicate which Store to get data for: omit the
* optional parameter for the default context Store, provide an Id for a named
* context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Tables will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns Whether any Tables exist.
* @example
* This example creates a Store outside the application, which is used in the
* useHasTables hook by reference. A change to the data in the Store re-renders
* the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useHasTables} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => <span>{JSON.stringify(useHasTables(store))}</span>;
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
*
* store.delTable('pets'); // !act
* console.log(app.innerHTML);
* // -> '<span>false</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useHasTables hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTables} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useHasTables())}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useHasTables hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTables} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useHasTables('petStore'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
* ```
* @category Store hooks
* @since v4.4.0
*/
export function useHasTables(storeOrStoreId?: StoreOrStoreId): boolean;
/**
* The useTables hook returns a Tables object containing the tabular data of a
* Store, and registers a listener so that any changes to that result will cause
* a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useTables hook lets you indicate which Store to get data for: omit the
* optional parameter for the default context Store, provide an Id for a named
* context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Tables will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns A Tables object containing the tabular data of the Store.
* @example
* This example creates a Store outside the application, which is used in the
* useTables hook by reference. A change to the data in the Store re-renders the
* component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useTables} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => <span>{JSON.stringify(useTables(store))}</span>;
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>'
*
* store.setCell('pets', 'fido', 'color', 'walnut'); // !act
* console.log(app.innerHTML);
* // -> '<span>{"pets":{"fido":{"color":"walnut"}}}</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useTables hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTables} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTables())}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useTables hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTables} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTables('petStore'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"pets":{"fido":{"color":"brown"}}}</span>'
* ```
* @category Store hooks
* @since v1.0.0
*/
export function useTables(storeOrStoreId?: StoreOrStoreId): Tables;
/**
* The useTableIds hook returns the Ids of every Table in a Store, and registers
* a listener so that any changes to that result will cause a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useTableIds hook lets you indicate which Store to get data for: omit the
* optional parameter for the default context Store, provide an Id for a named
* context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Table Ids will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns An array of the Ids of every Table in the Store.
* @example
* This example creates a Store outside the application, which is used in the
* useTableIds hook by reference. A change to the data in the Store re-renders
* the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useTableIds} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => <span>{JSON.stringify(useTableIds(store))}</span>;
*
* const app = document.createElement('div');
* createRoot(app).render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets"]</span>'
*
* store.setCell('species', 'dog', 'price', 5); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets","species"]</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useTableIds hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTableIds} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTableIds())}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets"]</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useTableIds hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTableIds} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTableIds('petStore'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>["pets"]</span>'
* ```
* @category Store hooks
* @since v1.0.0
*/
export function useTableIds(storeOrStoreId?: StoreOrStoreId): Ids;
/**
* The useHasTable hook returns a boolean indicating whether a given Table
* exists in the Store, and registers a listener so that any changes to that
* result will cause a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useHasTable hook lets you indicate which Store to get data for: omit the
* optional parameter for the default context Store, provide an Id for a named
* context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Table will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param tableId The Id of the Table in the Store.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns Whether a Table with that Id exists.
* @example
* This example creates a Store outside the application, which is used in the
* useHasTable hook by reference. A change to the data in the Store re-renders
* the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useHasTable} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => (
* <span>{JSON.stringify(useHasTable('pets', store))}</span>
* );
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
*
* store.delTable('pets'); // !act
* console.log(app.innerHTML);
* // -> '<span>false</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useHasTable hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTable} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useHasTable('pets'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useHasTable hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTable} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{JSON.stringify(useHasTable('pets', 'petStore'))}</span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
* ```
* @category Store hooks
* @since v4.4.0
*/
export function useHasTable(
tableId: Id,
storeOrStoreId?: StoreOrStoreId,
): boolean;
/**
* The useTable hook returns an object containing the data of a single Table in
* a Store, and registers a listener so that any changes to that result will
* cause a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useTable hook lets you indicate which Store to get data for: omit the final
* optional final parameter for the default context Store, provide an Id for a
* named context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Table will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param tableId The Id of the Table in the Store.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns An object containing the entire data of the Table.
* @example
* This example creates a Store outside the application, which is used in the
* useTable hook by reference. A change to the data in the Store re-renders the
* component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useTable} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => <span>{JSON.stringify(useTable('pets', store))}</span>;
*
* const app = document.createElement('div');
* createRoot(app).render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"fido":{"color":"brown"}}</span>'
*
* store.setCell('pets', 'fido', 'color', 'walnut'); // !act
* console.log(app.innerHTML);
* // -> '<span>{"fido":{"color":"walnut"}}</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useTable hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTable} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTable('pets'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"fido":{"color":"brown"}}</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useTable hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTable} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{JSON.stringify(useTable('pets', 'petStore'))}</span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>{"fido":{"color":"brown"}}</span>'
* ```
* @category Store hooks
* @since v1.0.0
*/
export function useTable(tableId: Id, storeOrStoreId?: StoreOrStoreId): Table;
/**
* The useTableCellIds hook returns the Ids of every Cell used across the whole
* Table, and registers a listener so that any changes to that result will cause
* a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useTableCellIds hook lets you indicate which Store to get data for: omit the
* optional final parameter for the default context Store, provide an Id for a
* named context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Table Cell Ids will cause a re-render. When the component containing this
* hook is unmounted, the listener will be automatically removed.
* @param tableId The Id of the Table in the Store.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns An array of the Ids of every Cell used across the whole Table.
* @example
* This example creates a Store outside the application, which is used in the
* useTableCellIds hook by reference. A change to the data in the Store
* re-renders the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useTableCellIds} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => (
* <span>{JSON.stringify(useTableCellIds('pets', store))}</span>
* );
*
* const app = document.createElement('div');
* createRoot(app).render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>["color"]</span>'
*
* store.setCell('pets', 'felix', 'species', 'cat'); // !act
* console.log(app.innerHTML);
* // -> '<span>["color","species"]</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useTableCellIds hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTableCellIds} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => <span>{JSON.stringify(useTableCellIds('pets'))}</span>;
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>["color"]</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useTableCellIds hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useTableCellIds} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{JSON.stringify(useTableCellIds('pets', 'petStore'))}</span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>["color"]</span>'
* ```
* @category Store hooks
* @since v3.3.0
*/
export function useTableCellIds(
tableId: Id,
storeOrStoreId?: StoreOrStoreId,
): Ids;
/**
* The useHasTableCell hook returns a boolean indicating whether a given Cell
* exists anywhere in a Table, not just in a specific Row, and registers a
* listener so that any changes to that result will cause a re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useHasTableCell hook lets you indicate which Store to get data for: omit the
* optional parameter for the default context Store, provide an Id for a named
* context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* Table will cause a re-render. When the component containing this hook is
* unmounted, the listener will be automatically removed.
* @param tableId The Id of the Table in the Store.
* @param cellId The Id of the Cell in the Table.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns Whether a Cell with that Id exists anywhere in that Table.
* @example
* This example creates a Store outside the application, which is used in the
* useHasTableCell hook by reference. A change to the data in the Store
* re-renders the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useHasTableCell} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => (
* <span>{JSON.stringify(useHasTableCell('pets', 'legs', store))}</span>
* );
*
* const app = document.createElement('div');
* const root = createRoot(app);
* root.render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>false</span>'
*
* store.setRow('pets', 'felix', {color: 'black', legs: 4}); // !act
* console.log(app.innerHTML);
* // -> '<span>true</span>'
* ```
* @example
* This example creates a Provider context into which a default Store is
* provided. A component within it then uses the useHasTableCell hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTableCell} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider store={store}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>{JSON.stringify(useHasTableCell('pets', 'legs'))}</span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>false</span>'
* ```
* @example
* This example creates a Provider context into which a Store is provided, named
* by Id. A component within it then uses the useHasTableCell hook.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {Provider, useHasTableCell} from 'tinybase/ui-react';
*
* const App = ({store}) => (
* <Provider storesById={{petStore: store}}>
* <Pane />
* </Provider>
* );
* const Pane = () => (
* <span>
* {JSON.stringify(useHasTableCell('pets', 'legs', 'petStore'))}
* </span>
* );
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const app = document.createElement('div');
* createRoot(app).render(<App store={store} />); // !act
* console.log(app.innerHTML);
* // -> '<span>false</span>'
* ```
* @category Store hooks
* @since v4.4.0
*/
export function useHasTableCell(
tableId: Id,
cellId: Id,
storeOrStoreId?: StoreOrStoreId,
): boolean;
/**
* The useRowCount hook returns the count of the Row objects in a given Table,
* and registers a listener so that any changes to that result will cause a
* re-render.
*
* A Provider component is used to wrap part of an application in a context, and
* it can contain a default Store or a set of Store objects named by Id. The
* useRowCount hook lets you indicate which Store to get data for: omit the
* optional final parameter for the default context Store, provide an Id for a
* named context Store, or provide a Store explicitly by reference.
*
* When first rendered, this hook will create a listener so that changes to the
* count of Row objects will cause a re-render. When the component containing
* this hook is unmounted, the listener will be automatically removed.
* @param tableId The Id of the Table in the Store.
* @param storeOrStoreId The Store to be accessed: omit for the default context
* Store, provide an Id for a named context Store, or provide an explicit
* reference.
* @returns The number of Row objects in the Table.
* @example
* This example creates a Store outside the application, which is used in the
* useRowCount hook by reference. A change to the data in the Store re-renders
* the component.
*
* ```jsx
* import React from 'react';
* import {createRoot} from 'react-dom/client';
* import {createStore} from 'tinybase';
* import {useRowCount} from 'tinybase/ui-react';
*
* const store = createStore().setCell('pets', 'fido', 'color', 'brown');
* const App = () => <span>{useRowCount('pets', store)}</span>;
*
* const app = document.createElement('div');
* createRoot(app).render(<App />); // !act
* console.log(app.innerHTML);
* // -> '<span>1</span>'
*
* store.setCell('pets', 'felix', 'color', 'black'); // !act
* console.log(app.innerHTML);
* // -> '<span>2</span>'
* ```
* @example
* This