/** * 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 { AllCellIdFromSchema, CellIdFromSchema, DefaultedValueFromSchema, NoInfer, TableIdFromSchema, ValueIdFromSchema, } from '../../_internal/store/with-schemas/index.d.ts'; import type { BackwardCheckpointsProps, CellProps, CheckpointProps, CheckpointsOrCheckpointsId, ComponentReturnType, CurrentCheckpointProps, ExtraProps, ForwardCheckpointsProps, GetId, IndexProps, IndexesOrIndexesId, LinkedRowsProps, LocalRowsProps, MetricProps, MetricsOrMetricsId, ProviderProps, QueriesOrQueriesId, RelationshipsOrRelationshipsId, RemoteRowProps, ResultCellProps, ResultRowProps, ResultSortedTableProps, ResultTableProps, RowProps, SliceProps, SortedTableProps, StoreOrStoreId, TableProps, TablesProps, UndoOrRedoInformation, ValueProps, ValuesProps, } from '../../_internal/ui-react/with-schemas/index.d.ts'; import type { Callback, Id, IdOrNull, Ids, ParameterizedCallback, } from '../../common/with-schemas/index.d.ts'; import type { Cell, CellIdsListener, CellListener, CellOrUndefined, HasCellListener, HasRowListener, HasTableCellListener, HasTableListener, HasTablesListener, HasValueListener, HasValuesListener, MapCell, MapValue, OptionalSchemas, Row, RowCountListener, RowIdsListener, RowListener, SortedRowIdsListener, Store, Table, TableCellIdsListener, TableIdsListener, TableListener, Tables, TablesListener, TransactionListener, Value, ValueIdsListener, ValueListener, Values, ValuesListener, } from '../../store/with-schemas/index.d.ts'; import type { CheckpointIds, CheckpointIdsListener, CheckpointListener, Checkpoints, } from '../../checkpoints/with-schemas/index.d.ts'; import type { Indexes, SliceIdsListener, SliceRowIdsListener, } from '../../indexes/with-schemas/index.d.ts'; import type { LinkedRowIdsListener, LocalRowIdsListener, Relationships, RemoteRowIdListener, } from '../../relationships/with-schemas/index.d.ts'; import type { MetricListener, Metrics, } from '../../metrics/with-schemas/index.d.ts'; import type { Queries, ResultCell, ResultCellIdsListener, ResultCellListener, ResultRow, ResultRowCountListener, ResultRowIdsListener, ResultRowListener, ResultSortedRowIdsListener, ResultTable, ResultTableCellIdsListener, ResultTableListener, } from '../../queries/with-schemas/index.d.ts'; import type {MergeableStore} from '../../mergeable-store/with-schemas/index.d.ts'; import type {Persister} from '../../persisters/with-schemas/index.d.ts'; import type {ReactElement} from 'react'; import type {Synchronizer} from '../../synchronizers/with-schemas/index.d.ts'; export type WithSchemas = { /** * The StoreOrStoreId type is used when you need to refer to a Store in a React * hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Store | Id; * ``` * * 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 */ StoreOrStoreId: StoreOrStoreId; /** * The MetricsOrMetricsId type is used when you need to refer to a Metrics * object in a React hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Metrics | Id; * ``` * * 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 Store or its Id. * @category Identity * @since v1.0.0 */ MetricsOrMetricsId: MetricsOrMetricsId; /** * The IndexesOrIndexesId type is used when you need to refer to an Indexes * object in a React hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Indexes | Id; * ``` * * 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 Store or its Id. * @category Identity * @since v1.0.0 */ IndexesOrIndexesId: IndexesOrIndexesId; /** * The RelationshipsOrRelationshipsId type is used when you need to refer to a * Relationships object in a React hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Relationships | Id; * ``` * * 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 Store or its Id. * @category Identity * @since v1.0.0 */ RelationshipsOrRelationshipsId: RelationshipsOrRelationshipsId; /** * The QueriesOrQueriesId type is used when you need to refer to a Queries * object in a React hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Queries | Id; * ``` * * 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 Store or its Id. * @category Identity * @since v2.0.0 */ QueriesOrQueriesId: QueriesOrQueriesId; /** * The CheckpointsOrCheckpointsId type is used when you need to refer to a * Checkpoints object in a React hook or component. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Checkpoints | Id; * ``` * * 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 Store or its Id. * @category Identity * @since v1.0.0 */ CheckpointsOrCheckpointsId: CheckpointsOrCheckpointsId; /** * 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 */ UndoOrRedoInformation: UndoOrRedoInformation; /** * The useCreateStore hook is used to create a Store within a React application * with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateStore( * create: () => Store, * createDeps?: React.DependencyList, * ): Store; * ``` * * 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 {store.getCell('pets', 'fido', 'species')}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Store created' * * root.render(); // !act * // No second Store creation * * console.log(app.innerHTML); * // -> 'dog' * ``` * @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 {store.getCell('pets', 'fido', 'species')}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Store created for fido as dog' * * console.log(app.innerHTML); * // -> 'dog' * * root.render(); // !act * // -> 'Store created for fido as cat' * * console.log(app.innerHTML); * // -> 'cat' * ``` * @category Store hooks * @since v1.0.0 */ useCreateStore: ( create: () => Store, createDeps?: React.DependencyList, ) => Store; /** * The useCreateMergeableStore hook. * @category Store hooks * @since v1.0.0 */ 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 {Provider, useCreateStore, useStoreIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = () => { * const store1 = useCreateStore(createStore); * const store2 = useCreateStore(createStore); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useStoreIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["store1","store2"]' * ``` * @category Store hooks * @since v4.1.0 */ useStoreIds: () => Ids; /** * The useStore hook is used to get a reference to a Store from within a * Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useStore(id?: Id): Store | undefined; * ``` * * 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 {Provider, useStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {useStore().getListenerStats().tables}; * * const store = createStore(); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @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 {Provider, useStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {useStore('petStore').getListenerStats().tables} * ); * * const store = createStore(); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Store hooks * @since v1.0.0 */ useStore: (id?: Id) => Store | undefined; /** * 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 has schema-based typing. The following is a simplified representation: * * ```ts override * useStoreOrStoreById( * storeOrStoreId?: StoreOrStoreId, * ): Store | undefined; * ``` * * 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 {Provider, useStoreOrStoreById} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = ({store}) => ( * {JSON.stringify(useStoreOrStoreById(store).getTableIds())} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["pets"]' * ``` * @category Store hooks * @since v4.1.0 */ 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useProvideStore(storeId: Id, store: Store): void; * ``` * * 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 { * Provider, * useCreateStore, * useProvideStore, * useStore, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = () => ( * * * * * ); * const RegisterStore = () => { * const store = useCreateStore(() => * createStore().setCell('pets', 'fido', 'color', 'brown'), * ); * useProvideStore('petStore', store); * return null; * }; * const ConsumeStore = () => ( * {JSON.stringify(useStore('petStore')?.getTableIds())} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["pets"]' * ``` * @category Store hooks * @since v4.4.2 */ 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTables(storeOrStoreId?: StoreOrStoreId): boolean; * ``` * * 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 = () => {JSON.stringify(useHasTables(store))}; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'true' * * store.delTable('pets'); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @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 {Provider, useHasTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasTables())}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @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 {Provider, useHasTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasTables('petStore'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @category Store hooks * @since v4.4.0 */ 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTables(storeOrStoreId?: StoreOrStoreId): Tables; * ``` * * 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 = () => {JSON.stringify(useTables(store))}; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '{"pets":{"fido":{"color":"brown"}}}' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '{"pets":{"fido":{"color":"walnut"}}}' * ``` * @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 {Provider, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTables())}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"pets":{"fido":{"color":"brown"}}}' * ``` * @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 {Provider, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTables('petStore'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"pets":{"fido":{"color":"brown"}}}' * ``` * @category Store hooks * @since v1.0.0 */ 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTableIds(storeOrStoreId?: StoreOrStoreId): Ids; * ``` * * 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 = () => {JSON.stringify(useTableIds(store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["pets"]' * * store.setCell('species', 'dog', 'price', 5); // !act * console.log(app.innerHTML); * // -> '["pets","species"]' * ``` * @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 {Provider, useTableIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTableIds())}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["pets"]' * ``` * @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 {Provider, useTableIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTableIds('petStore'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["pets"]' * ``` * @category Store hooks * @since v1.0.0 */ useTableIds: ( storeOrStoreId?: StoreOrStoreId, ) => TableIdFromSchema[]; /** * 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTable( * tableId: Id, * storeOrStoreId?: StoreOrStoreId, * ): boolean; * ``` * * 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 = () => ( * {JSON.stringify(useHasTable('pets', store))} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'true' * * store.delTable('pets'); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @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 {Provider, useHasTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasTable('pets'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @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 {Provider, useHasTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasTable('pets', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @category Store hooks * @since v4.4.0 */ useHasTable: >( tableId: TableId, 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTable(tableId: Id, storeOrStoreId?: StoreOrStoreId): Table; * ``` * * 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 = () => {JSON.stringify(useTable('pets', store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"}}' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"walnut"}}' * ``` * @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 {Provider, useTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTable('pets'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"}}' * ``` * @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 {Provider, useTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useTable('pets', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"}}' * ``` * @category Store hooks * @since v1.0.0 */ useTable: >( tableId: TableId, 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTableCellIds( * tableId: Id, * storeOrStoreId?: StoreOrStoreId, * ): Ids; * ``` * * 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 = () => ( * {JSON.stringify(useTableCellIds('pets', store))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * * store.setCell('pets', 'felix', 'species', 'cat'); // !act * console.log(app.innerHTML); * // -> '["color","species"]' * ``` * @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 {Provider, useTableCellIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useTableCellIds('pets'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * ``` * @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 {Provider, useTableCellIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useTableCellIds('pets', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * ``` * @category Store hooks * @since v3.3.0 */ useTableCellIds: >( tableId: TableId, storeOrStoreId?: StoreOrStoreId, ) => CellIdFromSchema[]; /** * 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTableCell( * tableId: Id, * cellId: Id, * storeOrStoreId?: StoreOrStoreId, * ): boolean; * ``` * * 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 = () => ( * {JSON.stringify(useHasTableCell('pets', 'legs', store))} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'false' * * store.setRow('pets', 'felix', {color: 'black', legs: 4}); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @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 {Provider, useHasTableCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasTableCell('pets', 'legs'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @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 {Provider, useHasTableCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useHasTableCell('pets', 'legs', 'petStore'))} * * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @category Store hooks * @since v4.4.0 */ useHasTableCell: >( tableId: TableId, cellId: CellIdFromSchema, 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. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRowCount( * tableId: Id, * storeOrStoreId?: StoreOrStoreId, * ): number; * ``` * * 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 = () => {useRowCount('pets', store)}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '1' * * store.setCell('pets', 'felix', 'color', 'black'); // !act * console.log(app.innerHTML); * // -> '2' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useRowCount hook. * * ```jsx * import {Provider, useRowCount} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {useRowCount('pets')}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '1' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useRowCount hook. * * ```jsx * import {Provider, useRowCount} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {useRowCount('pets', 'petStore')}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '1' * ``` * @category Store hooks * @since v4.1.0 */ useRowCount: ( tableId: TableIdFromSchema, storeOrStoreId?: StoreOrStoreId, ) => number; /** * The useRowIds hook returns the Ids of every Row in a given Table, and * registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRowIds(tableId: Id, storeOrStoreId?: StoreOrStoreId): Ids; * ``` * * 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 * useRowIds 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 * Row 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 Row in the Table. * @example * This example creates a Store outside the application, which is used in the * useRowIds 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 {useRowIds} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => {JSON.stringify(useRowIds('pets', store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido"]' * * store.setCell('pets', 'felix', 'color', 'black'); // !act * console.log(app.innerHTML); * // -> '["fido","felix"]' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useRowIds hook. * * ```jsx * import {Provider, useRowIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useRowIds('pets'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido"]' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useRowIds hook. * * ```jsx * import {Provider, useRowIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useRowIds('pets', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido"]' * ``` * @category Store hooks * @since v1.0.0 */ useRowIds: ( tableId: TableIdFromSchema, storeOrStoreId?: StoreOrStoreId, ) => Ids; /** * The useSortedRowIds hook returns the sorted (and optionally, paginated) Ids * of every Row in a given Table, and registers a listener so that any changes * to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSortedRowIds( * tableId: Id, * cellId?: Id, * descending?: boolean, * offset?: number, * limit?: number, * storeOrStoreId?: StoreOrStoreId, * ): Ids; * ``` * * 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 * useSortedRowIds 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 * sorted Row 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 cellId The Id of the Cell whose values are used for the sorting, or * `undefined` to by sort the Row Id itself. * @param descending Whether the sorting should be in descending order. * @param offset The number of Row Ids to skip for pagination purposes, if any. * @param limit The maximum number of Row Ids to return, or `undefined` for all. * @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 sorted Ids of every Row in the Table. * @example * This example creates a Store outside the application, which is used in the * useSortedRowIds 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 {useSortedRowIds} from 'tinybase/ui-react'; * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const App = () => ( * * {JSON.stringify( * useSortedRowIds('pets', 'species', false, 0, undefined, store), * )} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["felix","fido"]' * * store.setRow('pets', 'cujo', {species: 'wolf'}); // !act * console.log(app.innerHTML); * // -> '["felix","fido","cujo"]' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useSortedRowIds hook. * * ```jsx * import {Provider, useSortedRowIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useSortedRowIds('pets'))}; * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["felix","fido"]' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useSortedRowIds hook. * * ```jsx * import {Provider, useSortedRowIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify( * useSortedRowIds('pets', 'species', false, 0, undefined, 'petStore'), * )} * * ); * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["felix","fido"]' * ``` * @category Store hooks * @since v2.0.0 */ useSortedRowIds: < TableId extends TableIdFromSchema, CellId extends CellIdFromSchema, >( tableId: TableId, cellId?: CellId, descending?: boolean, offset?: number, limit?: number, storeOrStoreId?: StoreOrStoreId, ) => Ids; /** * The useHasRow hook returns a boolean indicating whether a given Row exists in * the Store, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasRow( * tableId: Id, * rowId: Id, * storeOrStoreId?: StoreOrStoreId, * ): boolean; * ``` * * 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 * useHasRow 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 * Row 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 rowId The Id of the Row 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 Row with that Id exists in that Table. * @example * This example creates a Store outside the application, which is used in the * useHasRow 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 {useHasRow} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * {JSON.stringify(useHasRow('pets', 'felix', store))} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'false' * * store.setCell('pets', 'felix', 'color', 'black'); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasRow hook. * * ```jsx * import {Provider, useHasRow} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasRow('pets', 'felix'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasRow hook. * * ```jsx * import {Provider, useHasRow} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasRow('pets', 'felix', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @category Store hooks * @since v4.4.0 */ useHasRow: >( tableId: TableId, rowId: Id, storeOrStoreId?: StoreOrStoreId, ) => boolean; /** * The useRow hook returns an object containing the data of a single Row in a * given Table, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRow( * tableId: Id, * rowId: Id, * storeOrStoreId?: StoreOrStoreId, * ): Row; * ``` * * 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 * useRow 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 * Row 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 rowId The Id of the Row 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 An object containing the entire data of the Row. * @example * This example creates a Store outside the application, which is used in the * useRow 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 {useRow} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * {JSON.stringify(useRow('pets', 'fido', store))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '{"color":"walnut"}' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useRow hook. * * ```jsx * import {Provider, useRow} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useRow('pets', 'fido'))}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useRow hook. * * ```jsx * import {Provider, useRow} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useRow('pets', 'fido', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * ``` * @category Store hooks * @since v1.0.0 */ useRow: >( tableId: TableId, rowId: Id, storeOrStoreId?: StoreOrStoreId, ) => Row; /** * The useCellIds hook returns the Ids of every Cell in a given Row, in a given * Table, and registers a listener so that any changes to that result will cause * a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCellIds( * tableId: Id, * rowId: Id, * storeOrStoreId?: StoreOrStoreId, * ): Ids; * ``` * * 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 * useCellIds 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 * 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 rowId The Id of the Row 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 An array of the Ids of every Cell in the Row. * @example * This example creates a Store outside the application, which is used in the * useCellIds 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 {useCellIds} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * {JSON.stringify(useCellIds('pets', 'fido', store))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * console.log(app.innerHTML); * // -> '["color","species"]' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useCellIds hook. * * ```jsx * import {Provider, useCellIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useCellIds('pets', 'fido'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useCellIds hook. * * ```jsx * import {Provider, useCellIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useCellIds('pets', 'fido', 'petStore'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * ``` * @category Store hooks * @since v1.0.0 */ useCellIds: >( tableId: TableId, rowId: Id, storeOrStoreId?: StoreOrStoreId, ) => CellIdFromSchema[]; /** * The useHasCell hook returns a boolean indicating whether a given Cell exists * in a given Row in a given Table, and registers a listener so that any changes * to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasCell( * tableId: Id, * rowId: Id, * cellId: Id, * storeOrStoreId?: StoreOrStoreId, * ): boolean; * ``` * * 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 * useHasCell 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 * Cell 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 rowId The Id of the Row in the Table. * @param cellId The Id of the Cell in the Row. * @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 in that Row in that Table. * @example * This example creates a Store outside the application, which is used in the * useHasCell 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 {useHasCell} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * {JSON.stringify(useHasCell('pets', 'fido', 'legs', store))} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'false' * * store.setCell('pets', 'fido', 'legs', 4); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasCell hook. * * ```jsx * import {Provider, useHasCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasCell('pets', 'fido', 'legs'))} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasCell hook. * * ```jsx * import {Provider, useHasCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useHasCell('pets', 'fido', 'legs', 'petStore'))} * * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @category Store hooks * @since v4.4.0 */ useHasCell: < TableId extends TableIdFromSchema, CellId extends CellIdFromSchema, >( tableId: TableId, rowId: Id, cellId: CellId, storeOrStoreId?: StoreOrStoreId, ) => boolean; /** * The useCell hook returns an object containing the value of a single Cell in a * given Row, in a given Table, and registers a listener so that any changes to * that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCell( * tableId: Id, * rowId: Id, * cellId: Id, * storeOrStoreId?: StoreOrStoreId, * ): CellOrUndefined; * ``` * * 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 * useCell 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 * Cell 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 rowId The Id of the Row in the Table. * @param cellId The Id of the Cell in the Row. * @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 value of the Cell. * @example * This example creates a Store outside the application, which is used in the * useCell 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 {useCell} from 'tinybase/ui-react'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => {useCell('pets', 'fido', 'color', store)}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> 'walnut' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useCell hook. * * ```jsx * import {Provider, useCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {useCell('pets', 'fido', 'color')}; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useCell hook. * * ```jsx * import {Provider, useCell} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {useCell('pets', 'fido', 'color', 'petStore')} * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * ``` * @category Store hooks * @since v1.0.0 */ useCell: < TableId extends TableIdFromSchema, CellId extends CellIdFromSchema, >( tableId: TableId, rowId: Id, cellId: CellId, storeOrStoreId?: StoreOrStoreId, ) => NoInfer>; /** * The useHasValues hook returns a boolean indicating whether any Values exist * in the Store, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasValues(storeOrStoreId?: StoreOrStoreId): boolean; * ``` * * 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 * useHasValues 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 * Values 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 Values exist. * @example * This example creates a Store outside the application, which is used in the * useHasValues 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 {useHasValues} from 'tinybase/ui-react'; * * const store = createStore().setValue('open', true); * const App = () => {JSON.stringify(useHasValues(store))}; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'true' * * store.delValue('open'); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasValues hook. * * ```jsx * import {Provider, useHasValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasValues())}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasValues hook. * * ```jsx * import {Provider, useHasValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasValues('petStore'))}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @category Store hooks * @since v4.4.0 */ useHasValues: (storeOrStoreId?: StoreOrStoreId) => boolean; /** * The useValues hook returns a Values object containing the keyed value data of * a Store, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValues(storeOrStoreId?: StoreOrStoreId): Values; * ``` * * 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 * useValues 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 * Values 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 Values object containing the keyed value data of the Store. * @example * This example creates a Store outside the application, which is used in the * useValues 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 {useValues} from 'tinybase/ui-react'; * * const store = createStore().setValue('open', true); * const App = () => {JSON.stringify(useValues(store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"open":true}' * * store.setValue('open', false); // !act * console.log(app.innerHTML); * // -> '{"open":false}' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useValues hook. * * ```jsx * import {Provider, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useValues())}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"open":true}' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useValues hook. * * ```jsx * import {Provider, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useValues('petStore'))}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"open":true}' * ``` * @category Store hooks * @since v3.0.0 */ useValues: (storeOrStoreId?: StoreOrStoreId) => Values; /** * The useValueIds hook returns the Ids of every Value in a Store, and registers * a listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValueIds(storeOrStoreId?: StoreOrStoreId): Ids; * ``` * * 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 * useValueIds 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 * Value 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 Value in the Store. * @example * This example creates a Store outside the application, which is used in the * useValueIds 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 {useValueIds} from 'tinybase/ui-react'; * * const store = createStore().setValue('open', true); * const App = () => {JSON.stringify(useValueIds(store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["open"]' * * store.setValue('employees', 3); // !act * console.log(app.innerHTML); * // -> '["open","employees"]' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useValueIds hook. * * ```jsx * import {Provider, useValueIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useValueIds())}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["open"]' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useValueIds hook. * * ```jsx * import {Provider, useValueIds} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useValueIds('petStore'))}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["open"]' * ``` * @category Store hooks * @since v3.0.0 */ useValueIds: ( storeOrStoreId?: StoreOrStoreId, ) => ValueIdFromSchema[]; /** * The useHasValue hook returns a boolean indicating whether a given Value * exists in the Store, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasValue( * valueId: Id, * storeOrStoreId?: StoreOrStoreId, * ): boolean; * ``` * * 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 * useHasValue 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 * Value will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param valueId The Id of the Value 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 Value with that Id exists in the Store. * @example * This example creates a Store outside the application, which is used in the * useHasValue 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 {useHasValue} from 'tinybase/ui-react'; * * const store = createStore().setValue('open', true); * const App = () => ( * {JSON.stringify(useHasValue('employees', store))} * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'false' * * store.setValue('employees', 3); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useHasValue hook. * * ```jsx * import {Provider, useHasValue} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useHasValue('employees'))}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useHasValue hook. * * ```jsx * import {Provider, useHasValue} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useHasValue('employees', 'petStore'))} * ); * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @category Store hooks * @since v4.4.0 */ useHasValue: >( valueId: ValueId, storeOrStoreId?: StoreOrStoreId, ) => boolean; /** * The useValue hook returns an object containing the data of a single Value in * a Store, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValue( * valueId: Id, * storeOrStoreId?: StoreOrStoreId, * ): ValueOrUndefined; * ``` * * 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 * useValue 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 * Value will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param valueId The Id of the Value 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 Value. * @example * This example creates a Store outside the application, which is used in the * useValue 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 {useValue} from 'tinybase/ui-react'; * * const store = createStore().setValue('open', true); * const App = () => {JSON.stringify(useValue('open', store))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * * store.setValue('open', false); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a default Store is * provided. A component within it then uses the useValue hook. * * ```jsx * import {Provider, useValue} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => {JSON.stringify(useValue('open'))}; * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @example * This example creates a Provider context into which a Store is provided, named * by Id. A component within it then uses the useValue hook. * * ```jsx * import {Provider, useValue} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useValue('open', 'petStore'))} * ); * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * ``` * @category Store hooks * @since v3.0.0 */ useValue: >( valueId: ValueId, storeOrStoreId?: StoreOrStoreId, ) => DefaultedValueFromSchema; /** * The useSetTablesCallback hook returns a parameterized callback that can be * used to set the tabular data of a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetTablesCallback( * getTables: (parameter: Parameter, store: Store) => Tables, * getTablesDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, tables: Tables) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The first parameter is a function which will produce the Tables object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback 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. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param getTables A function which returns the Tables object that will be used * to update the Store, based on the parameter the callback will receive (and * which is most likely a DOM event). * @param getTablesDeps An optional array of dependencies for the `getTables` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Tables used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetTablesCallback hook to create an event handler * which updates the Store when the `span` element is clicked. * * ```jsx * import {useSetTablesCallback, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const App = () => { * const handleClick = useSetTablesCallback( * (e) => ({pets: {nemo: {species: 'fish', bubbles: e.bubbles}}}), * [], * store, * (store, tables) => console.log(`Updated: ${JSON.stringify(tables)}`), * ); * return ( * * {JSON.stringify(useTables(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish"}}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"pets":{"nemo":{"species":"fish","bubbles":true}}}' * * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish","bubbles":true}}}' * ``` * @category Store hooks * @since v1.0.0 */ useSetTablesCallback: >( getTables: ( parameter: Parameter, store: Store, ) => NoInfer, getTablesDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, tables: SetTables) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetTableCallback hook returns a parameterized callback that can be * used to set the data of a single Table in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetTableCallback( * tableId: Id | GetId, * getTable: (parameter: Parameter, store: Store) => Table, * getTableDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, table: Table) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The second parameter is a function which will produce the Table object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional third parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store to set, or a GetId function * that will return it. * @param getTable A function which returns the Table object that will be used * to update the Store, based on the parameter the callback will receive (and * which is most likely a DOM event). * @param getTableDeps An optional array of dependencies for the `getTable` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of a GetId function if used as the tableId argument. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Table used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetTableCallback hook to create an event handler * which updates the Store when the `span` element is clicked. * * ```jsx * import {useSetTableCallback, useTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTable('pets', {nemo: {species: 'fish'}}); * const App = () => { * const handleClick = useSetTableCallback( * 'pets', * (e) => ({nemo: {species: 'fish', bubbles: e.bubbles}}), * [], * store, * (store, table) => console.log(`Updated: ${JSON.stringify(table)}`), * ); * return ( * * {JSON.stringify(useTable('pets', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"nemo":{"species":"fish"}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"nemo":{"species":"fish","bubbles":true}}' * * console.log(span.innerHTML); * // -> '{"nemo":{"species":"fish","bubbles":true}}' * ``` * @category Store hooks * @since v1.0.0 */ useSetTableCallback: < Parameter, TableId extends TableIdFromSchema, SetTable = Table, >( tableId: TableId | GetId, getTable: ( parameter: Parameter, store: Store, ) => NoInfer, getTableDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, table: SetTable) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetRowCallback hook returns a parameterized callback that can be used * to set the data of a single Row in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetRowCallback( * tableId: Id | GetId, * rowId: Id | GetId, * getRow: (parameter: Parameter, store: Store) => Row, * getRowDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, row: Row) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The third parameter is a function which will produce the Row object that will * then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional fourth parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param rowId The Id of the Row in the Table to set, or a GetId function that * will return it. * @param getRow A function which returns the Row object that will be used to * update the Store, based on the parameter the callback will receive (and which * is most likely a DOM event). * @param getRowDeps An optional array of dependencies for the `getRow` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of any GetId functions if used as the tableId or rowId * arguments. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Row used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetRowCallback hook to create an event handler which * updates the Store when the `span` element is clicked. * * ```jsx * import {useRow, useSetRowCallback} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setRow('pets', 'nemo', {species: 'fish'}); * const App = () => { * const handleClick = useSetRowCallback( * 'pets', * 'nemo', * (e) => ({species: 'fish', bubbles: e.bubbles}), * [], * store, * (store, row) => console.log(`Updated: ${JSON.stringify(row)}`), * ); * return ( * * {JSON.stringify(useRow('pets', 'nemo', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"species":"fish"}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"species":"fish","bubbles":true}' * * console.log(span.innerHTML); * // -> '{"species":"fish","bubbles":true}' * ``` * @category Store hooks * @since v1.0.0 */ useSetRowCallback: < Parameter, TableId extends TableIdFromSchema, SetRow = Row, >( tableId: TableId | GetId, rowId: Id | GetId, getRow: (parameter: Parameter, store: Store) => NoInfer, getRowDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, row: SetRow) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useAddRowCallback hook returns a parameterized callback that can be used * to create a new Row in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useAddRowCallback( * tableId: Id | GetId, * getRow: (parameter: Parameter, store: Store) => Row, * getRowDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (rowId: Id | undefined, store: Store, row: Row) => void, * thenDeps?: React.DependencyList, * reuseRowIds?: boolean, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The second parameter is a function which will produce the Row object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional third parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * * The `reuseRowIds` parameter defaults to `true`, which means that if you * delete a Row and then add another, the Id will be re-used - unless you delete * the entire Table, in which case all Row Ids will reset. Otherwise, if you * specify `reuseRowIds` to be `false`, then the Id will be a monotonically * increasing string representation of an increasing integer, regardless of any * you may have previously deleted. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param getRow A function which returns the Row object that will be used to * update the Store, based on the parameter the callback will receive (and which * is most likely a DOM event). * @param getRowDeps An optional array of dependencies for the `getRow` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of a GetId function if used as the tableId argument. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with the new Row * Id, a reference to the Store, and the Row used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @param reuseRowIds Whether Ids should be recycled from previously deleted Row * objects, defaulting to `true`. * @returns A parameterized callback for subsequent use. * @example * This example uses the useAddRowCallback hook to create an event handler which * updates the Store when the `span` element is clicked. * * ```jsx * import {useAddRowCallback, useTable} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setRow('pets', 'nemo', {species: 'fish'}); * const App = () => { * const handleClick = useAddRowCallback( * 'pets', * (e) => ({species: 'frog', bubbles: e.bubbles}), * [], * store, * (rowId) => console.log(`Added row: ${rowId}`), * ); * return ( * * {JSON.stringify(useTable('pets', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"nemo":{"species":"fish"}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Added row: 0' * * console.log(span.innerHTML); * // -> '{"0":{"species":"frog","bubbles":true},"nemo":{"species":"fish"}}' * ``` * @category Store hooks * @since v1.0.0 */ useAddRowCallback: < Parameter, TableId extends TableIdFromSchema, AddRow = Row, >( tableId: TableId | GetId, getRow: (parameter: Parameter, store: Store) => NoInfer, getRowDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (rowId: Id | undefined, store: Store, row: AddRow) => void, thenDeps?: React.DependencyList, reuseRowIds?: boolean, ) => ParameterizedCallback; /** * The useSetPartialRowCallback hook returns a parameterized callback that can * be used to set partial data of a single Row in the Store, leaving other Cell * values unaffected. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetPartialRowCallback( * tableId: Id | GetId, * rowId: Id | GetId, * getPartialRow: (parameter: Parameter, store: Store) => Row, * getPartialRowDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, partialRow: Row) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The third parameter is a function which will produce the partial Row object * that will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional fourth parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param rowId The Id of the Row in the Table to set, or a GetId function that * will return it. * @param getPartialRow A function which returns the partial Row object that * will be used to update the Store, based on the parameter the callback will * receive (and which is most likely a DOM event). * @param getPartialRowDeps An optional array of dependencies for the `getRow` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of any GetId functions if used as the tableId, rowId, or cellId * arguments. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Row used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetPartialRowCallback hook to create an event * handler which updates the Store when the `span` element is clicked. * * ```jsx * import {useRow, useSetPartialRowCallback} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setRow('pets', 'nemo', {species: 'fish'}); * const App = () => { * const handleClick = useSetPartialRowCallback( * 'pets', * 'nemo', * (e) => ({bubbles: e.bubbles}), * [], * store, * (store, partialRow) => * console.log(`Updated: ${JSON.stringify(partialRow)}`), * ); * return ( * * {JSON.stringify(useRow('pets', 'nemo', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"species":"fish"}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"bubbles":true}' * * console.log(span.innerHTML); * // -> '{"species":"fish","bubbles":true}' * ``` * @category Store hooks * @since v1.0.0 */ useSetPartialRowCallback: < Parameter, TableId extends TableIdFromSchema, SetPartialRow = Row, >( tableId: TableId | GetId, rowId: Id | GetId, getPartialRow: ( parameter: Parameter, store: Store, ) => NoInfer, getPartialRowDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, partialRow: SetPartialRow) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetCellCallback hook returns a parameterized callback that can be used * to set the value of a single Cell in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetCellCallback( * tableId: Id | GetId, * rowId: Id | GetId, * cellId: Id | GetId, * getCell: (parameter: Parameter, store: Store) => Cell | MapCell, * getCellDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, cell: Cell | MapCell) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The fourth parameter is a function which will produce the Cell object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional fourth parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param rowId The Id of the Row in the Table, or a GetId function that will * return it. * @param cellId The Id of the Cell in the Row to set, or a GetId function that * will return it. * @param getCell A function which returns the Cell value that will be used to * update the Store, or a MapCell function to update it, based on the parameter * the callback will receive (and which is most likely a DOM event). * @param getCellDeps An optional array of dependencies for the `getCell` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of any GetId functions if used as the tableId, rowId, or cellId * arguments. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Cell value (or MapCell function) used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetCellCallback hook to create an event handler * which updates the Store with a Cell value when the `span` element is clicked. * * ```jsx * import {useRow, useSetCellCallback} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setCell('pets', 'nemo', 'species', 'fish'); * const App = () => { * const handleClick = useSetCellCallback( * 'pets', * 'nemo', * 'bubbles', * (e) => e.bubbles, * [], * store, * (store, cell) => console.log(`Updated: ${cell}`), * ); * return ( * * {JSON.stringify(useRow('pets', 'nemo', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"species":"fish"}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: true' * * console.log(span.innerHTML); * // -> '{"species":"fish","bubbles":true}' * ``` * @example * This example uses the useSetCellCallback hook to create an event handler * which updates the Store via a MapCell function when the `span` element is * clicked. * * ```jsx * import {useRow, useSetCellCallback} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setCell('pets', 'nemo', 'visits', 1); * const App = () => { * const handleClick = useSetCellCallback( * 'pets', * 'nemo', * 'visits', * (e) => (visits) => visits + (e.bubbles ? 1 : 0), * [], * store, * () => console.log(`Updated with MapCell function`), * ); * return ( * * {JSON.stringify(useRow('pets', 'nemo', store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"visits":1}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated with MapCell function' * * console.log(span.innerHTML); * // -> '{"visits":2}' * ``` * @category Store hooks * @since v1.0.0 */ useSetCellCallback: < Parameter, TableId extends TableIdFromSchema, CellId extends CellIdFromSchema, SetOrMapCell = | Cell | MapCell, >( tableId: TableId | GetId, rowId: Id | GetId, cellId: CellId | GetId, getCell: ( parameter: Parameter, store: Store, ) => NoInfer, getCellDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, cell: SetOrMapCell) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetValuesCallback hook returns a parameterized callback that can be * used to set the keyed value data of a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetValuesCallback( * getValues: (parameter: Parameter, store: Store) => Values, * getValuesDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, values: Values) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The first parameter is a function which will produce the Values object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback 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. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param getValues A function which returns the Values object that will be used * to update the Store, based on the parameter the callback will receive (and * which is most likely a DOM event). * @param getValuesDeps An optional array of dependencies for the `getValues` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Values used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetValuesCallback hook to create an event handler * which updates the Store when the `span` element is clicked. * * ```jsx * import {useSetValuesCallback, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValues({open: true}); * const App = () => { * const handleClick = useSetValuesCallback( * (e) => ({bubbles: e.bubbles}), * [], * store, * (store, values) => console.log(`Updated: ${JSON.stringify(values)}`), * ); * return ( * * {JSON.stringify(useValues(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"open":true}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"bubbles":true}' * * console.log(span.innerHTML); * // -> '{"bubbles":true}' * ``` * @category Store hooks * @since v3.0.0 */ useSetValuesCallback: >( getValues: ( parameter: Parameter, store: Store, ) => NoInfer, getValuesDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, values: SetValues) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetPartialValuesCallback hook returns a parameterized callback that * can be used to set partial Values data in the Store, leaving other Values * unaffected. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetPartialValuesCallback( * getPartialValues: (parameter: Parameter, store: Store) => Values, * getPartialValuesDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, partialValues: Values) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The third parameter is a function which will produce the partial Values * object that will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional fourth parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param getPartialValues A function which returns the partial Values object * that will be used to update the Store, based on the parameter the callback * will receive (and which is most likely a DOM event). * @param getPartialValuesDeps An optional array of dependencies for the * `getValues` function, which, if any change, result in the regeneration of the * callback. This parameter defaults to an empty array. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Values used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetPartialValuesCallback hook to create an event * handler which updates the Store when the `span` element is clicked. * * ```jsx * import {useSetPartialValuesCallback, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValues({open: true}); * const App = () => { * const handleClick = useSetPartialValuesCallback( * (e) => ({bubbles: e.bubbles}), * [], * store, * (store, partialValues) => * console.log(`Updated: ${JSON.stringify(partialValues)}`), * ); * return ( * * {JSON.stringify(useValues(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"open":true}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: {"bubbles":true}' * * console.log(span.innerHTML); * // -> '{"open":true,"bubbles":true}' * ``` * @category Store hooks * @since v3.0.0 */ useSetPartialValuesCallback: < Parameter, SetPartialValues = Values, >( getPartialValues: ( parameter: Parameter, store: Store, ) => NoInfer, getPartialValuesDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, partialValues: SetPartialValues) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useSetValueCallback hook returns a parameterized callback that can be * used to set the data of a single Value in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetValueCallback( * valueId: Id | GetId, * getValue: (parameter: Parameter, store: Store) => Value | MapValue, * getValueDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store, value: Value | MapValue) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * mutate the data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the mutation. * * The second parameter is a function which will produce the Value object that * will then be used to update the Store in the callback. * * If that function has any other dependencies, the changing of which should * also cause the callback to be recreated, you can provide them in an array in * the optional third parameter, just as you would for any React hook with * dependencies. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the mutation to your application's undo stack. * * The Store to which the callback will make the mutation (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param valueId The Id of the Value in the Store to set, or a GetId function * that will return it. * @param getValue A function which returns the Value object that will be used * to update the Store, based on the parameter the callback will receive (and * which is most likely a DOM event). * @param getValueDeps An optional array of dependencies for the `getValue` * function, which, if any change, result in the regeneration of the callback. * This parameter defaults to an empty array. Also use this to indicate the * dependencies of a GetId function if used as the valueId argument. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the mutation, with a reference * to the Store and the Value used in the update. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetValueCallback hook to create an event handler * which updates the Store when the `span` element is clicked. * * ```jsx * import {useSetValueCallback, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValue('open', true); * const App = () => { * const handleClick = useSetValueCallback( * 'bubbles', * (e) => e.bubbles, * [], * store, * (store, value) => console.log(`Updated: ${JSON.stringify(value)}`), * ); * return ( * * {JSON.stringify(useValues(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"open":true}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Updated: true' * * console.log(span.innerHTML); * // -> '{"open":true,"bubbles":true}' * ``` * @category Store hooks * @since v3.0.0 */ useSetValueCallback: < Parameter, ValueId extends ValueIdFromSchema, SetOrMapValue = Value | MapValue, >( valueId: ValueId | GetId, getValue: ( parameter: Parameter, store: Store, ) => NoInfer, getValueDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, then?: (store: Store, value: SetOrMapValue) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useDelTablesCallback hook returns a callback that can be used to remove * all of the tabular data in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelTablesCallback( * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): Callback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in the Store. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A callback for subsequent use. * @example * This example uses the useDelTablesCallback hook to create an event handler * which deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelTablesCallback, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const App = () => { * const handleClick = useDelTablesCallback(store, () => * console.log('Deleted'), * ); * return ( * * {JSON.stringify(useTables(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish"}}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{}' * ``` * @category Store hooks * @since v1.0.0 */ useDelTablesCallback: ( storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => Callback; /** * The useDelTableCallback hook returns a parameterized callback that can be * used to remove a single Table from a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelTableCallback( * tableId: Id | GetId, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the deletion. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store to delete, or a GetId * function that will return it. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. Also use this to indicate the * dependencies of an GetId function if used as the tableId argument. * @returns A parameterized callback for subsequent use. * @example * This example uses the useDelTableCallback hook to create an event handler * which deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelTableCallback, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const App = () => { * const handleClick = useDelTableCallback('pets', store, () => * console.log('Deleted'), * ); * return ( * * {JSON.stringify(useTables(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish"}}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{}' * ``` * @category Store hooks * @since v1.0.0 */ useDelTableCallback: < Parameter, TableId extends TableIdFromSchema, >( tableId: TableId | GetId, storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useDelRowCallback hook returns a parameterized callback that can be used * to remove a single Row from a Table. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelRowCallback( * tableId: Id | GetId, * rowId: Id | GetId, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the deletion. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param rowId The Id of the Row in the Table to delete, or a GetId function * that will return it. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. Also use this to indicate the * dependencies of any GetId functions if used as the tableId or rowId * arguments. * @returns A parameterized callback for subsequent use. * @example * This example uses the useDelRowCallback hook to create an event handler which * deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelRowCallback, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const App = () => { * const handleClick = useDelRowCallback('pets', 'nemo', store, () => * console.log('Deleted'), * ); * return ( * * {JSON.stringify(useTables(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish"}}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{}' * ``` * @category Store hooks * @since v1.0.0 */ useDelRowCallback: >( tableId: TableId | GetId, rowId: Id | GetId, storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useDelCellCallback hook returns a parameterized callback that can be used * to remove a single Cell from a Row. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelCellCallback( * tableId: Id | GetId, * rowId: Id | GetId, * cellId: Id | GetId, * forceDel?: boolean, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the deletion. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param tableId The Id of the Table in the Store, or a GetId function that * will return it. * @param rowId The Id of the Row in the Table, or a GetId function that will * return it. * @param cellId The Id of the Cell in the Row to delete, or a GetId function * that will return it. * @param forceDel An optional flag to indicate that the whole Row should be * deleted, even if a TablesSchema provides a default value for this Cell. * Defaults to `false`. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. Also use this to indicate the * dependencies of any GetId functions if used as the tableId, rowId, or cellId * arguments. * @returns A parameterized callback for subsequent use. * @example * This example uses the useDelCellCallback hook to create an event handler * which deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelCellCallback, useTables} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const App = () => { * const handleClick = useDelCellCallback( * 'pets', * 'nemo', * 'species', * false, * store, * () => console.log('Deleted'), * ); * return ( * * {JSON.stringify(useTables(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"pets":{"nemo":{"species":"fish"}}}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{}' * ``` * @category Store hooks * @since v1.0.0 */ useDelCellCallback: < Parameter, TableId extends TableIdFromSchema, CellId extends CellIdFromSchema, >( tableId: TableId | GetId, rowId: Id | GetId, cellId: CellId | GetId, forceDel?: boolean, storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useDelValuesCallback hook returns a callback that can be used to remove * all of the keyed value data in a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelValuesCallback( * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): Callback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in a Store. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A callback for subsequent use. * @example * This example uses the useDelValuesCallback hook to create an event handler * which deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelValuesCallback, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValues({open: true}); * const App = () => { * const handleClick = useDelValuesCallback(store, () => * console.log('Deleted'), * ); * return ( * * {JSON.stringify(useValues(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"open":true}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{}' * ``` * @category Store hooks * @since v3.0.0 */ useDelValuesCallback: ( storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => Callback; /** * The useDelValueCallback hook returns a parameterized callback that can be * used to remove a single Value from a Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDelValueCallback( * valueId: Id | GetId, * storeOrStoreId?: StoreOrStoreId, * then?: (store: Store) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * delete data in the Store. In this case, the parameter will likely be the * event, so that you can use data from it as part of the deletion. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the Store has been * updated. This is a useful place to call the addCheckpoint method, for * example, if you wish to add the deletion to your application's undo stack. * * The Store to which the callback will make the deletion (indicated by the * hook's `storeOrStoreId` parameter) is always automatically used as a hook * dependency for the callback. * @param valueId The Id of the Value in the Store to delete, or a GetId * function that will return it. * @param storeOrStoreId The Store to be updated: omit for the default context * Store, provide an Id for a named context Store, or provide an explicit * reference. * @param then A function which is called after the deletion, with a reference * to the Store. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. Also use this to indicate the * dependencies of a GetId function if used as the valueId argument. * @returns A parameterized callback for subsequent use. * @example * This example uses the useDelValueCallback hook to create an event handler * which deletes from the Store when the `span` element is clicked. * * ```jsx * import {useDelValueCallback, useValues} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValues({open: true, employees: 3}); * const App = () => { * const handleClick = useDelValueCallback('open', store, () => * console.log('Deleted'), * ); * return ( * * {JSON.stringify(useValues(store))} * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const span = app.querySelector('span'); * console.log(span.innerHTML); * // -> '{"open":true,"employees":3}' * * // User clicks the element: * // -> span MouseEvent('click', {bubbles: true}) * // -> 'Deleted' * * console.log(span.innerHTML); * // -> '{"employees":3}' * ``` * @category Store hooks * @since v3.0.0 */ useDelValueCallback: < Parameter, ValueId extends ValueIdFromSchema, >( valueId: ValueId | GetId, storeOrStoreId?: StoreOrStoreId, then?: (store: Store) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useHasTablesListener hook registers a listener function with the Store * that will be called when Tables as a whole are added to or removed from the * Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTablesListener( * listener: HasTablesListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasTables hook). * * Unlike the addHasTablesListener method, which returns a listener Id and * requires you to remove it manually, the useHasTablesListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param listener The function that will be called whenever Tables as a whole * are added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasTablesListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasTablesListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasTablesListener(() => console.log('Tables existence changed')); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasTables); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'brown'); // !act * // -> 'Tables existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasTables); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasTablesListener: ( listener: HasTablesListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useTablesListener hook registers a listener function with a Store that * will be called whenever tabular data in it changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTablesListener( * listener: TablesListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useTables hook). * * Unlike the addTablesListener method, which returns a listener Id and requires * you to remove it manually, the useTablesListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param listener The function that will be called whenever tabular data in the * Store changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useTablesListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useTablesListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useTablesListener(() => console.log('Tables changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().tables); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Tables changed' * * root.unmount(); // !act * console.log(store.getListenerStats().tables); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useTablesListener: ( listener: TablesListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useTableIdsListener hook registers a listener function with a Store that * will be called whenever the Table Ids in it change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTableIdsListener( * listener: TableIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useTableIds hook). * * Unlike the addTableIdsListener method, which returns a listener Id and * requires you to remove it manually, the useTableIdsListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param listener The function that will be called whenever the Table Ids in * the Store change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useTableIdsListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useTableIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useTableIdsListener(() => console.log('Table Ids changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().tableIds); * // -> 1 * * store.setTable('species', {dog: {price: 5}}); // !act * // -> 'Table Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().tableIds); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useTableIdsListener: ( listener: TableIdsListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasTableListener hook registers a listener function with the Store * that will be called when a Table is added to or removed from the Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTableListener( * tableId: IdOrNull, * listener: HasTableListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasTable hook). * * You can either listen to a single Table (by specifying its Id as the method's * first parameter) or changes to any Table (by providing a `null` wildcard). * * Unlike the addHasTableListener method, which returns a listener Id and * requires you to remove it manually, the useHasTableListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the matching Table * is added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasTableListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasTableListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasTableListener('pets', () => * console.log('Table existence changed'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasTable); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Table existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasTable); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasTableListener: < TableIdOrNull extends TableIdFromSchema | null, >( tableId: TableIdOrNull, listener: HasTableListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useTableListener hook registers a listener function with a Store that * will be called whenever data in a Table changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTableListener( * tableId: IdOrNull, * listener: TableListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useTable hook). * * You can either listen to a single Table (by specifying its Id as the method's * first parameter) or changes to any Table (by providing a `null` wildcard). * * Unlike the addTableListener method, which returns a listener Id and requires * you to remove it manually, the useTableListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the Table * changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useTableListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useTableListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useTableListener('pets', () => console.log('Table changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().table); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Table changed' * * root.unmount(); // !act * console.log(store.getListenerStats().table); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useTableListener: < TableIdOrNull extends TableIdFromSchema | null, >( tableId: TableIdOrNull, listener: TableListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useTableCellIdsListener hook registers a listener function with a Store * that will be called whenever the Cell Ids that appear anywhere in a Table * change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useTableCellIdsListener( * tableId: IdOrNull, * listener: TableCellIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useTableCellIds hook). * * You can either listen to a single Table (by specifying its Id as the method's * first parameter) or changes to any Table (by providing `null`). * * Unlike the addTableCellIdsListener method, which returns a listener Id and * requires you to remove it manually, the useTableCellIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Cell Ids that * appear anywhere in a Table change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useTableCellIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useTableCellIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useTableCellIdsListener('pets', () => console.log('Cell Ids changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().tableCellIds); * // -> 1 * * store.setRow('pets', 'felix', {species: 'cat'}); // !act * // -> 'Cell Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().rowIds); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useTableCellIdsListener: < TableIdOrNull extends TableIdFromSchema | null, >( tableId: TableIdOrNull, listener: TableCellIdsListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasTableCellListener hook registers a listener function with the Store * that will be called when a Cell is added to or removed from anywhere in a * Table as a whole. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasTableCellListener( * tableId: IdOrNull, * cellId: IdOrNull, * listener: HasTableCellListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasTableCell hook). * * You can either listen to a single Table Cell being added or removed (by * specifying the Table Id and Cell Id, as the method's first two parameters) or * changes to any Table Cell (by providing `null` wildcards). * * Unlike the addHasTableCellIds method, which returns a listener Id and * requires you to remove it manually, the useHasTableCellListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param cellId The Id of the Cell to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the matching Cell * is added to or removed from anywhere in the Table. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasTableCellListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useHasTableCellListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasTableCellListener('pets', 'color', () => * console.log('Table Cell existence changed'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasTableCell); * // -> 1 * * store.setRow('pets', 'fido', {color: 'brown'}); // !act * // -> 'Table Cell existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasTableCell); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasTableCellListener: < TableIdOrNull extends TableIdFromSchema | null, CellIdOrNull extends | (TableIdOrNull extends TableIdFromSchema ? CellIdFromSchema : AllCellIdFromSchema) | null, >( tableId: TableIdOrNull, cellId: CellIdOrNull, listener: HasTableCellListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useRowCountListener hook registers a listener function with a Store that * will be called whenever the count of the Row objects in a Table changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRowCountListener( * tableId: IdOrNull, * listener: RowCountListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useRowCount hook). * * You can either listen to a single Table (by specifying its Id as the method's * first parameter) or changes to any Table (by providing `null`). * * Unlike the addRowCountListener method, which returns a listener Id and * requires you to remove it manually, the useRowCountListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the count of the * Row objects in the Table changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useRowCountListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useRowCountListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useRowCountListener('pets', () => console.log('Row count changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().rowCount); * // -> 1 * * store.setRow('pets', 'felix', {color: 'black'}); // !act * // -> 'Row count changed' * * root.unmount(); // !act * console.log(store.getListenerStats().rowCount); * // -> 0 * ``` * @category Store hooks * @since v4.1.0 */ useRowCountListener: < TableIdOrNull extends TableIdFromSchema | null, >( tableId: TableIdOrNull, listener: RowCountListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useRowIdsListener hook registers a listener function with a Store that * will be called whenever the Row Ids in a Table change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRowIdsListener( * tableId: IdOrNull, * listener: RowIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useRowIds hook). * * You can either listen to a single Table (by specifying its Id as the method's * first parameter) or changes to any Table (by providing `null`). * * Unlike the addRowIdsListener method, which returns a listener Id and requires * you to remove it manually, the useRowIdsListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Row Ids in the * Table change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useRowIdsListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useRowIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useRowIdsListener('pets', () => console.log('Row Ids changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().rowIds); * // -> 1 * * store.setRow('pets', 'felix', {color: 'black'}); // !act * // -> 'Row Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().rowIds); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useRowIdsListener: < TableIdOrNull extends TableIdFromSchema | null, >( tableId: TableIdOrNull, listener: RowIdsListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useSortedRowIdsListener hook registers a listener function with a Store * that will be called whenever sorted (and optionally, paginated) Row Ids in a * Table change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSortedRowIdsListener( * tableId: Id, * cellId: Id | undefined, * descending: boolean, * offset: number, * limit: number | undefined, * listener: SortedRowIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useSortedRowIds hook). * * Unlike the addSortedRowIdsListener method, which returns a listener Id and * requires you to remove it manually, the useSortedRowIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table in the Store. * @param cellId The Id of the Cell whose values are used for the sorting, or * `undefined` to by sort the Row Id itself. * @param descending Whether the sorting should be in descending order. * @param offset The number of Row Ids to skip for pagination purposes, if any. * @param limit The maximum number of Row Ids to return, or `undefined` for all. * @param listener The function that will be called whenever the sorted Row Ids * in the Table change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useSortedRowIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useSortedRowIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useSortedRowIdsListener('pets', 'species', false, 0, undefined, () => * console.log('Sorted Row Ids changed'), * ); * return App; * }; * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().sortedRowIds); * // -> 1 * * store.setRow('pets', 'cujo', {species: 'wolf'}); // !act * // -> 'Sorted Row Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().sortedRowIds); * // -> 0 * ``` * @category Store hooks * @since v2.0.0 */ useSortedRowIdsListener: < TableId extends TableIdFromSchema, CellIdOrUndefined extends CellIdFromSchema | undefined, Descending extends boolean, Offset extends number, Limit extends number | undefined, >( tableId: TableId, cellId: CellIdOrUndefined, descending: Descending, offset: Offset, limit: Limit, listener: SortedRowIdsListener< Schemas, TableId, CellIdOrUndefined, Descending, Offset, Limit >, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasRowListener hook registers a listener function with the Store that * will be called when a Row is added to or removed from the Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasRowListener( * tableId: IdOrNull, * rowId: IdOrNull, * listener: HasRowListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasRow hook). * * You can either listen to a single Row being added or removed (by specifying * the Table Id and Row Id, as the method's first two parameters) or changes to * any Row (by providing `null` wildcards). * * Both, either, or neither of the `tableId` and `rowId` parameters can be * wildcarded with `null`. You can listen to a specific Row in a specific Table, * any Row in a specific Table, a specific Row in any Table, or any Row in any * Table. * * Unlike the addHasRowListener method, which returns a listener Id and requires * you to remove it manually, the useHasRowListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param rowId The Id of the Row to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the matching Row is * added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasRowListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasRowListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasRowListener('pets', 'fido', () => * console.log('Row existence changed'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasRow); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Row existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasRow); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasRowListener: < TableIdOrNull extends TableIdFromSchema | null, RowIdOrNull extends IdOrNull, >( tableId: TableIdOrNull, rowId: RowIdOrNull, listener: HasRowListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useRowListener hook registers a listener function with a Store that will * be called whenever data in a Row changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRowListener( * tableId: IdOrNull, * rowId: IdOrNull, * listener: RowListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useRow hook). * * You can either listen to a single Row (by specifying the Table Id and Row Id * as the method's first two parameters) or changes to any Row (by providing * `null` wildcards). * * Both, either, or neither of the `tableId` and `rowId` parameters can be * wildcarded with `null`. You can listen to a specific Row in a specific Table, * any Row in a specific Table, a specific Row in any Table, or any Row in any * Table. * * Unlike the addRowListener method, which returns a listener Id and requires * you to remove it manually, the useRowListener hook manages this lifecycle for * you: when the listener changes (per its `listenerDeps` dependencies) or the * component unmounts, the listener on the underlying Store will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param rowId The Id of the Row to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the Row * changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useRowListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useRowListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useRowListener('pets', 'fido', () => console.log('Row changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().row); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Row changed' * * root.unmount(); // !act * console.log(store.getListenerStats().row); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useRowListener: < TableIdOrNull extends TableIdFromSchema | null, RowIdOrNull extends IdOrNull, >( tableId: TableIdOrNull, rowId: RowIdOrNull, listener: RowListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useCellIdsListener hook registers a listener function with a Store that * will be called whenever the Cell Ids in a Row change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCellIdsListener( * tableId: IdOrNull, * rowId: IdOrNull, * listener: CellIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useCellIds hook). * * You can either listen to a single Row (by specifying the Table Id and Row Id * as the method's first two parameters) or changes to any Row (by providing * `null` wildcards). * * Both, either, or neither of the `tableId` and `rowId` parameters can be * wildcarded with `null`. You can listen to a specific Row in a specific Table, * any Row in a specific Table, a specific Row in any Table, or any Row in any * Table. * * Unlike the addCellIdsListener method, which returns a listener Id and * requires you to remove it manually, the useCellIdsListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param rowId The Id of the Row to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Cell Ids in the * Row change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useCellIdsListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useCellIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useCellIdsListener('pets', 'fido', () => * console.log('Cell Ids changed'), * ); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().cellIds); * // -> 1 * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * // -> 'Cell Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().cellIds); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useCellIdsListener: < TableIdOrNull extends TableIdFromSchema | null, RowIdOrNull extends IdOrNull, >( tableId: TableIdOrNull, rowId: RowIdOrNull, listener: CellIdsListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasCellListener hook registers a listener function with the Store that * will be called when a Cell is added to or removed from the Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasCellListener( * tableId: IdOrNull, * rowId: IdOrNull, * cellId: IdOrNull, * listener: HasCellListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasCell hook). * * You can either listen to a single Cell being added or removed (by specifying * the Table Id, Row Id, and Cell Id as the method's first three parameters) or * changes to any Cell (by providing `null` wildcards). * * All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can be * wildcarded with `null`. You can listen to a specific Cell in a specific Row * in a specific Table, any Cell in any Row in any Table, for example - or every * other combination of wildcards. * * Unlike the addHasCellListener method, which returns a listener Id and * requires you to remove it manually, the useHasCellListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param rowId The Id of the Row to listen to, or `null` as a wildcard. * @param cellId The Id of the Cell to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the matching Cell * is added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasCellListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasCellListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasCellListener('pets', 'fido', 'color', () => * console.log('Cell existence changed'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasCell); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'brown'); // !act * // -> 'Cell existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasCell); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasCellListener: < TableIdOrNull extends TableIdFromSchema | null, RowIdOrNull extends IdOrNull, CellIdOrNull extends | (TableIdOrNull extends TableIdFromSchema ? CellIdFromSchema : AllCellIdFromSchema) | null, >( tableId: TableIdOrNull, rowId: RowIdOrNull, cellId: CellIdOrNull, listener: HasCellListener< Schemas, TableIdOrNull, RowIdOrNull, CellIdOrNull >, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useCellListener hook registers a listener function with a Store that will * be called whenever data in a Cell changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCellListener( * tableId: IdOrNull, * rowId: IdOrNull, * cellId: IdOrNull, * listener: CellListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useCell hook). * * You can either listen to a single Cell (by specifying the Table Id, Row Id, * and Cell Id as the method's first three parameters) or changes to any Cell * (by providing `null` wildcards). * * All, some, or none of the `tableId`, `rowId`, and `cellId` parameters can be * wildcarded with `null`. You can listen to a specific Cell in a specific Row * in a specific Table, any Cell in any Row in any Table, for example - or every * other combination of wildcards. * * Unlike the addCellListener method, which returns a listener Id and requires * you to remove it manually, the useCellListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param tableId The Id of the Table to listen to, or `null` as a wildcard. * @param rowId The Id of the Row to listen to, or `null` as a wildcard. * @param cellId The Id of the Cell to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the Cell * changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useCellListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useCellListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useCellListener('pets', 'fido', 'color', () => * console.log('Cell changed'), * ); * return App; * }; * * const store = createStore().setTables({pets: {fido: {color: 'brown'}}}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().cell); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Cell changed' * * root.unmount(); // !act * console.log(store.getListenerStats().cell); * // -> 0 * ``` * @category Store hooks * @since v1.0.0 */ useCellListener: < TableIdOrNull extends TableIdFromSchema | null, RowIdOrNull extends IdOrNull, CellIdOrNull extends | (TableIdOrNull extends TableIdFromSchema ? CellIdFromSchema : AllCellIdFromSchema) | null, >( tableId: TableIdOrNull, rowId: RowIdOrNull, cellId: CellIdOrNull, listener: CellListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasValuesListener hook registers a listener function with the Store * that will be called when Values as a whole are added to or removed from the * Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasValuesListener( * listener: HasValuesListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasValues hook). * * Unlike the addHasValuesListener method, which returns a listener Id and * requires you to remove it manually, the useHasValuesListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param listener The function that will be called whenever Values as a whole * are added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasValuesListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasValuesListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasValuesListener(() => console.log('Values existence changed')); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasValues); * // -> 1 * * store.setValue('open', true); // !act * // -> 'Values existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasValues); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasValuesListener: ( listener: HasValuesListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useValuesListener hook registers a listener function with a Store that * will be called whenever keyed value data in it changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValuesListener( * listener: ValuesListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useValues hook). * * Unlike the addValuesListener method, which returns a listener Id and requires * you to remove it manually, the useValuesListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param listener The function that will be called whenever keyed value data in * the Store changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useValuesListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useValuesListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useValuesListener(() => console.log('Values changed')); * return App; * }; * * const store = createStore().setValues({open: true}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().values); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Values changed' * * root.unmount(); // !act * console.log(store.getListenerStats().values); * // -> 0 * ``` * @category Store hooks * @since v3.0.0 */ useValuesListener: ( listener: ValuesListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useValueIdsListener hook registers a listener function with a Store that * will be called whenever the Value Ids in it change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValueIdsListener( * listener: ValueIdsListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useValueIds hook). * * Unlike the addValueIdsListener method, which returns a listener Id and * requires you to remove it manually, the useValueIdsListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param listener The function that will be called whenever the Value Ids in * the Store change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useValueIdsListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useValueIdsListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useValueIdsListener(() => console.log('Value Ids changed')); * return App; * }; * * const store = createStore().setValues({open: true}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().valueIds); * // -> 1 * * store.setValue('employees', 3); // !act * // -> 'Value Ids changed' * * root.unmount(); // !act * console.log(store.getListenerStats().valueIds); * // -> 0 * ``` * @category Store hooks * @since v3.0.0 */ useValueIdsListener: ( listener: ValueIdsListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useHasValueListener hook registers a listener function with the Store * that will be called when a Value is added to or removed from the Store. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useHasValueListener( * valueId: IdOrNull, * listener: HasValueListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useHasValue hook). * * You can either listen to a single Value being added or removed (by specifying * the Value Id) or any Value being added or removed (by providing a `null` * wildcard). * * Unlike the addHasValueListener method, which returns a listener Id and * requires you to remove it manually, the useHasValueListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying Store * will be deleted. * @param valueId The Id of the Value to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the matching Value * is added or removed. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useHasValueListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useHasValueListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useHasValueListener('open', () => * console.log('Value existence changed'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().hasValue); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Value existence changed' * * root.unmount(); // !act * console.log(store.getListenerStats().hasValue); * // -> 0 * ``` * @category Store hooks * @since v4.4.0 */ useHasValueListener: < ValueIdOrNull extends ValueIdFromSchema | null, >( valueId: ValueIdOrNull, listener: HasValueListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useValueListener hook registers a listener function with a Store that * will be called whenever data in a Value changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useValueListener( * valueId: IdOrNull, * listener: ValueListener, * listenerDeps?: React.DependencyList, * mutator?: boolean, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useValue hook). * * You can either listen to a single Value (by specifying its Id as the method's * first parameter) or changes to any Value (by providing a `null` wildcard). * * Unlike the addValueListener method, which returns a listener Id and requires * you to remove it manually, the useValueListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Store will be deleted. * @param valueId The Id of the Value to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the Value * changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param mutator An optional boolean that indicates that the listener mutates * Store data. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useValueListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Store. * * ```jsx * import {Provider, useValueListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useValueListener('open', () => console.log('Value changed')); * return App; * }; * * const store = createStore().setValues({open: true}); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().value); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Value changed' * * root.unmount(); // !act * console.log(store.getListenerStats().value); * // -> 0 * ``` * @category Store hooks * @since v3.0.0 */ useValueListener: < ValueIdOrNull extends ValueIdFromSchema | null, >( valueId: ValueIdOrNull, listener: ValueListener, listenerDeps?: React.DependencyList, mutator?: boolean, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useStartTransactionListener hook registers a listener function with the * Store that will be called at the start of a transaction. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useStartTransactionListener( * listener: TransactionListener, * listenerDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * Unlike the addStartTransactionListener method, which returns a listener Id * and requires you to remove it manually, the useStartTransactionListener hook * manages this lifecycle for you: when the listener changes (per its * `listenerDeps` dependencies) or the component unmounts, the listener on the * underlying Store will be deleted. * @param listener The function that will be called at the start of a * transaction. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useStartTransactionListener hook to create a listener * that is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useStartTransactionListener} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useStartTransactionListener(() => console.log('Start transaction')); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().transaction); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Start transaction' * * root.unmount(); // !act * console.log(store.getListenerStats().transaction); * // -> 0 * ``` * @category Store hooks * @since v4.2.2 */ useStartTransactionListener: ( listener: TransactionListener, listenerDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useWillFinishTransactionListener hook registers a listener function with * a Store that will be called just before other non-mutating listeners are * called at the end of the transaction. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useWillFinishTransactionListener( * listener: TransactionListener, * listenerDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * Unlike the addWillFinisTransactionListener method, which returns a listener * Id and requires you to remove it manually, the * useWillFinishTransactionListener hook manages this lifecycle for you: when * the listener changes (per its `listenerDeps` dependencies) or the component * unmounts, the listener on the underlying Store will be deleted. * @param listener The function that will be called before the end of a * transaction. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useWillFinishTransactionListener hook to create a * listener that is scoped to a single component. When the component is * unmounted, the listener is removed from the Store. * * ```jsx * import { * Provider, * useWillFinishTransactionListener, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useWillFinishTransactionListener(() => * console.log('Will finish transaction'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().transaction); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Will finish transaction' * * root.unmount(); // !act * console.log(store.getListenerStats().transaction); * // -> 0 * ``` * @category Store hooks * @since v4.2.2 */ useWillFinishTransactionListener: ( listener: TransactionListener, listenerDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useDidFinishTransactionListener hook registers a listener function with a * Store that will be called just after other non-mutating listeners are called * at the end of the transaction. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useDidFinishTransactionListener( * listener: TransactionListener, * listenerDeps?: React.DependencyList, * storeOrStoreId?: StoreOrStoreId, * ): void; * ``` * * Unlike the addDidFinishTransactionListener method, which returns a listener * Id and requires you to remove it manually, the * useDidFinishTransactionListener hook manages this lifecycle for you: when the * listener changes (per its `listenerDeps` dependencies) or the component * unmounts, the listener on the underlying Store will be deleted. * @param listener The function that will be called after the end of a * transaction. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param storeOrStoreId The Store to register the listener with: omit for the * default context Store, provide an Id for a named context Store, or provide an * explicit reference. * @example * This example uses the useDidFinishTransactionListener hook to create a * listener that is scoped to a single component. When the component is * unmounted, the listener is removed from the Store. * * ```jsx * import { * Provider, * useDidFinishTransactionListener, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => { * useDidFinishTransactionListener(() => * console.log('Did finish transaction'), * ); * return App; * }; * * const store = createStore(); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(store.getListenerStats().transaction); * // -> 1 * * store.setValue('open', false); // !act * // -> 'Did finish transaction' * * root.unmount(); // !act * console.log(store.getListenerStats().transaction); * // -> 0 * ``` * @category Store hooks * @since v4.2.2 */ useDidFinishTransactionListener: ( listener: TransactionListener, listenerDeps?: React.DependencyList, storeOrStoreId?: StoreOrStoreId, ) => void; /** * The useCreateMetrics hook is used to create a Metrics object within a React * application with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateMetrics( * store: Store | undefined, * create: (store: Store) => Metrics, * createDeps?: React.DependencyList, * ): Metrics | undefined; * ``` * * It is possible to create a Metrics object outside of the React app with the * regular createMetrics 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 * Metrics object being created every time the app renders or re-renders, since * v5.0 this hook performs the creation in an effect. As a result it will return * `undefined` on the brief first render (or if the Store is not yet defined), * which you should defend against. * * If your `create` function contains other dependencies, the changing of which * should also cause the Metrics object 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. * * This hook ensures the Metrics object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Metrics * object. * @param create A function for performing the creation steps of the Metrics * object for the Store, plus any additional steps such as adding definitions 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 Metrics object. * @example * This example creates a Metrics object at the top level of a React * application. Even though the App component is rendered twice, the Metrics * object creation only occurs once by default. * * ```jsx * import {createMetrics, createStore} from 'tinybase'; * import {useCreateMetrics, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(() => * createStore().setTable('species', {dog: {price: 5}, cat: {price: 4}}), * ); * const metrics = useCreateMetrics(store, (store) => { * console.log('Metrics created'); * return createMetrics(store).setMetricDefinition( * 'speciesCount', * 'species', * ); * }); * return {metrics?.getMetric('speciesCount')}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Metrics created' * * root.render(); // !act * // No second Metrics creation * * console.log(app.innerHTML); * // -> '2' * ``` * @example * This example creates a Metrics object at the top level of a React * application. The App component is rendered twice, each with a different * top-level prop. The useCreateMetrics hook takes the tableToCount prop as a * dependency, and so the Metrics object is created again on the second render. * * ```jsx * import {createMetrics, createStore} from 'tinybase'; * import {useCreateMetrics, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({tableToCount}) => { * const store = useCreateStore(() => * createStore() * .setTable('pets', {fido: {species: 'dog'}}) * .setTable('species', {dog: {price: 5}, cat: {price: 4}}), * ); * const metrics = useCreateMetrics( * store, * (store) => { * console.log(`Count created for ${tableToCount} table`); * return createMetrics(store).setMetricDefinition( * 'tableCount', * tableToCount, * ); * }, * [tableToCount], * ); * return {metrics?.getMetric('tableCount')}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Count created for pets table' * * console.log(app.innerHTML); * // -> '1' * * root.render(); // !act * // -> 'Count created for species table' * * console.log(app.innerHTML); * // -> '2' * ``` * @category Metrics hooks * @since v1.0.0 */ useCreateMetrics: ( store: Store | undefined, create: (store: Store) => Metrics, createDeps?: React.DependencyList, ) => Metrics | undefined; /** * The useMetricsIds hook is used to retrieve the Ids of all the named Metrics * objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Metrics objects to a Provider context and an * inner component accesses their Ids. * * ```jsx * import { * Provider, * useCreateMetrics, * useCreateStore, * useMetricsIds, * } from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store1 = useCreateStore(createStore); * const metrics1 = useCreateMetrics(store1, createMetrics); * const store2 = useCreateStore(createStore); * const metrics2 = useCreateMetrics(store2, createMetrics); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useMetricsIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["metrics1","metrics2"]' * ``` * @category Metrics hooks * @since v4.1.0 */ useMetricsIds: () => Ids; /** * The useMetrics hook is used to get a reference to a Metrics object from * within a Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useMetrics(id?: Id): Metrics | undefined; * ``` * * A Provider component is used to wrap part of an application in a context. It * can contain a default Metrics object (or a set of Metrics objects named by * Id) that can be easily accessed without having to be passed down as props * through every component. * * The useMetrics hook lets you either get a reference to the default Metrics * object (when called without a parameter), or one of the Metrics objects that * are named by Id (when called with an Id parameter). * @param id An optional Id for accessing a Metrics object that was named with * an Id in the Provider. * @returns A reference to the Metrics object (or `undefined` if not within a * Provider context, or if the requested Metrics object does not exist). * @example * This example creates a Provider context into which a default Metrics object * is provided. A component within it then uses the useMetrics hook to get a * reference to the Metrics object again, without the need to have it passed * as a prop. * * ```jsx * import {Provider, useMetrics} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => {useMetrics().getListenerStats().metric}; * * const metrics = createMetrics(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @example * This example creates a Provider context into which a Metrics object is * provided, named by Id. A component within it then uses the useMetrics hook * with that Id to get a reference to the Metrics object again, without the need * to have it passed as a prop. * * ```jsx * import {Provider, useMetrics} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => ( * {useMetrics('petStore').getListenerStats().metric} * ); * * const metrics = createMetrics(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Metrics hooks * @since v1.0.0 */ useMetrics: (id?: Id) => Metrics | undefined; /** * The useMetricsOrMetricsById hook is used to get a reference to a Metrics * object from within a Provider component context, _or_ have it passed directly * to this hook. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useMetricsOrMetricsById( * metricsOrMetricsId?: MetricsOrMetricsId, * ): Metrics | undefined; * ``` * * This is mostly of use when you are developing a component that needs a * Metrics 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 * Metrics-based components). * * This hook is unlikely to be used often. For most situations, you will want to * use the useMetrics hook. * @param metricsOrMetricsId Either an Id for accessing a Metrics object that * was named with an Id in the Provider, or the Metrics object itself. * @returns A reference to the Metrics object (or `undefined` if not within a * Provider context, or if the requested Metrics object does not exist). * @example * This example creates a Provider context into which a default Metrics object * is provided. A component within it then uses the useMetricsOrMetricsById hook * to get a reference to the Metrics object again, without the need to have it * passed as a prop. Note however, that unlike the useMetrics hook example, this * component would also work if you were to pass the Metrics object directly * into it, making it more portable. * * ```jsx * import {Provider, useMetricsOrMetricsById} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = ({metrics}) => ( * * {JSON.stringify(useMetricsOrMetricsById(metrics).getMetricIds())} * * ); * * const metrics = createMetrics( * createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }), * ).setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["highestPrice"]' * ``` * @category Metrics hooks * @since v4.1.0 */ useMetricsOrMetricsById: ( metricsOrMetricsId?: MetricsOrMetricsId, ) => Metrics | undefined; /** * The useMetricIds hook gets an array of the Metric Ids registered with a * Metrics object, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useMetricIds(metricsOrMetricsId?: MetricsOrMetricsId): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Metrics object or a set of Metrics objects named by * Id. The useMetricIds hook lets you indicate which Metrics object to get data * for: omit the optional final parameter for the default context Metrics * object, provide an Id for a named context Metrics object, or provide a * Metrics object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Metric Ids in the Metrics object will cause a re-render. When the component * containing this hook is unmounted, the listener will be automatically * removed. * @param metricsOrMetricsId The Metrics object to be accessed: omit for the * default context Metrics object, provide an Id for a named context Metrics * object, or provide an explicit reference. * @returns The Metric Ids in the Metrics object, or an empty array. * @example * This example creates an Metrics object outside the application, which is used * in the useMetricIds hook by reference. A newly-registered Metric re-renders * the component. * * ```jsx * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useMetricIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const metrics = createMetrics(store); * const App = () => {JSON.stringify(useMetricIds(metrics))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '[]' * * const addMetricDefinition = () => * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * addMetricDefinition(); // !act * console.log(app.innerHTML); * // -> '["highestPrice"]' * ``` * @category Metrics hooks * @since v4.1.0 */ useMetricIds(metricsOrMetricsId?: MetricsOrMetricsId): Ids; /** * The useMetric hook gets the current value of a Metric, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useMetric( * metricId: Id, * metricsOrMetricsId?: MetricsOrMetricsId, * ): number | undefined; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Metrics object or a set of Metrics objects named by * Id. The useMetric hook lets you indicate which Metrics object to get data * for: omit the optional final parameter for the default context Metrics * object, provide an Id for a named context Metrics object, or provide a * Metrics object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Metric will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param metricId The Id of the Metric. * @param metricsOrMetricsId The Metrics object to be accessed: omit for the * default context Metrics object, provide an Id for a named context Metrics * object, or provide an explicit reference. * @returns The numeric value of the Metric, or `undefined`. * @example * This example creates a Metrics object outside the application, which is used * in the useMetric hook by reference. A change to the Metric re-renders the * component. * * ```jsx * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useMetric} from 'tinybase/ui-react'; * * const store = createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * const App = () => {useMetric('highestPrice', metrics)}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '5' * * store.setCell('species', 'horse', 'price', 20); // !act * console.log(app.innerHTML); * // -> '20' * ``` * @example * This example creates a Provider context into which a default Metrics object * is provided. A component within it then uses the useMetric hook. * * ```jsx * import {Provider, useMetric} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => {useMetric('highestPrice')}; * * const metrics = createMetrics( * createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }), * ).setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '5' * ``` * @example * This example creates a Provider context into which a default Metrics object * is provided. A component within it then uses the useMetric hook. * * ```jsx * import {Provider, useMetric} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => {useMetric('highestPrice', 'petMetrics')}; * * const metrics = createMetrics( * createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }), * ).setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '5' * ``` * @category Metrics hooks * @since v1.0.0 */ useMetric: ( metricId: Id, metricsOrMetricsId?: MetricsOrMetricsId, ) => number | undefined; /** * The useMetricListener hook registers a listener function with the Metrics * object that will be called whenever the value of a specified Metric changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useMetricListener( * metricId: IdOrNull, * listener: MetricListener, * listenerDeps?: React.DependencyList, * metricsOrMetricsId?: MetricsOrMetricsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useMetric hook). * * You can either listen to a single Metric (by specifying the Metric Id as the * method's first parameter), or changes to any Metric (by providing a `null` * wildcard). * * Unlike the addMetricListener method, which returns a listener Id and requires * you to remove it manually, the useMetricListener hook manages this lifecycle * for you: when the listener changes (per its `listenerDeps` dependencies) or * the component unmounts, the listener on the underlying Metrics object, will * be deleted. * @param metricId The Id of the Metric to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Metric changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param metricsOrMetricsId The Metrics object to register the listener with: * omit for the default context Metrics object, provide an Id for a named * context Metrics object, or provide an explicit reference. * @example * This example uses the useMetricListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Metrics object. * * ```jsx * import {Provider, useMetricListener} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => { * useMetricListener('highestPrice', () => console.log('Metric changed')); * return App; * }; * * const store = createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(metrics.getListenerStats().metric); * // -> 1 * * store.setCell('species', 'horse', 'price', 20); // !act * // -> 'Metric changed' * * root.unmount(); // !act * console.log(metrics.getListenerStats().metric); * // -> 0 * ``` * @category Metrics hooks * @since v1.0.0 */ useMetricListener: ( metricId: IdOrNull, listener: MetricListener, listenerDeps?: React.DependencyList, metricsOrMetricsId?: MetricsOrMetricsId, ) => void; /** * The useCreateIndexes hook is used to create an Indexes object within a React * application with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateIndexes( * store: Store | undefined, * create: (store: Store) => Indexes, * createDeps?: React.DependencyList, * ): Indexes | undefined; * ``` * * It is possible to create an Indexes object outside of the React app with the * regular createIndexes 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 * Indexes object being created every time the app renders or re-renders, since * v5.0 the this hook performs the creation in an effect. As a result it will * return `undefined` on the brief first render (or if the Store is not yet * defined), which you should defend against. * * If your `create` function contains other dependencies, the changing of which * should also cause the Indexes object 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. * * This hook ensures the Indexes object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Indexes * object. * @param create A function for performing the creation steps of the Indexes * object for the Store, plus any additional steps such as adding definitions 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 Indexes object. * @example * This example creates an Indexes object at the top level of a React * application. Even though the App component is rendered twice, the Indexes * object creation only occurs once by default. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import {useCreateIndexes, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(() => * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ); * const indexes = useCreateIndexes(store, (store) => { * console.log('Indexes created'); * return createIndexes(store).setIndexDefinition( * 'bySpecies', * 'pets', * 'species', * ); * }); * return {JSON.stringify(indexes?.getSliceIds('bySpecies'))}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Indexes created' * * root.render(); // !act * // No second Indexes creation * * console.log(app.innerHTML); * // -> '["dog","cat"]' * ``` * @example * This example creates an Indexes object at the top level of a React * application. The App component is rendered twice, each with a different * top-level prop. The useCreateIndexes hook takes the cellToIndex prop as a * dependency, and so the Indexes object is created again on the second render. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import {useCreateIndexes, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({cellToIndex}) => { * const store = useCreateStore(() => * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'brown'}, * }), * ); * const indexes = useCreateIndexes( * store, * (store) => { * console.log(`Index created for ${cellToIndex} cell`); * return createIndexes(store).setIndexDefinition( * 'byCell', * 'pets', * cellToIndex, * ); * }, * [cellToIndex], * ); * return {JSON.stringify(indexes?.getSliceIds('byCell'))}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Index created for species cell' * * console.log(app.innerHTML); * // -> '["dog","cat"]' * * root.render(); // !act * // -> 'Index created for color cell' * * console.log(app.innerHTML); * // -> '["brown","black"]' * ``` * @category Indexes hooks * @since v1.0.0 */ useCreateIndexes: ( store: Store | undefined, create: (store: Store) => Indexes, createDeps?: React.DependencyList, ) => Indexes | undefined; /** * The useIndexesIds hook is used to retrieve the Ids of all the named Indexes * objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Indexes objects to a Provider context and an * inner component accesses their Ids. * * ```jsx * import { * Provider, * useCreateIndexes, * useCreateStore, * useIndexesIds, * } from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store1 = useCreateStore(createStore); * const indexes1 = useCreateIndexes(store1, createIndexes); * const store2 = useCreateStore(createStore); * const indexes2 = useCreateIndexes(store2, createIndexes); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useIndexesIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["indexes1","indexes2"]' * ``` * @category Indexes hooks * @since v4.1.0 */ useIndexesIds: () => Ids; /** * The useIndexes hook is used to get a reference to an Indexes object from * within a Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useIndexes(id?: Id): Indexes | undefined; * ``` * * A Provider component is used to wrap part of an application in a context. It * can contain a default Indexes object (or a set of Indexes objects named by * Id) that can be easily accessed without having to be passed down as props * through every component. * * The useIndexes hook lets you either get a reference to the default Indexes * object (when called without a parameter), or one of the Indexes objects that * are named by Id (when called with an Id parameter). * @param id An optional Id for accessing an Indexes object that was named with * an Id in the Provider. * @returns A reference to the Indexes object (or `undefined` if not within a * Provider context, or if the requested Indexes object does not exist). * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useIndexes hook to get a * reference to the Indexes object again, without the need to have it passed * as a prop. * * ```jsx * import {Provider, useIndexes} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => {useIndexes().getListenerStats().sliceIds}; * * const indexes = createIndexes(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @example * This example creates a Provider context into which an Indexes object is * provided, named by Id. A component within it then uses the useIndexes hook * with that Id to get a reference to the Indexes object again, without the need * to have it passed as a prop. * * ```jsx * import {Provider, useIndexes} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( * {useIndexes('petStore').getListenerStats().sliceIds} * ); * * const indexes = createIndexes(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Indexes hooks * @since v1.0.0 */ useIndexes: (id?: Id) => Indexes | undefined; /** * The useIndexesOrIndexesById hook is used to get a reference to an Indexes * object from within a Provider component context, _or_ have it passed directly * to this hook. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useIndexesOrIndexesById( * indexesOrIndexesId?: IndexesOrIndexesId, * ): Indexes | undefined; * ``` * * This is mostly of use when you are developing a component that needs an * Indexes 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 * Indexes-based components). * * This hook is unlikely to be used often. For most situations, you will want to * use the useIndexes hook. * @param indexesOrIndexesId Either an Id for accessing a Indexes object that * was named with an Id in the Provider, or the Indexes object itself. * @returns A reference to the Indexes object (or `undefined` if not within a * Provider context, or if the requested Indexes object does not exist). * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useIndexesOrIndexesById hook * to get a reference to the Indexes object again, without the need to have it * passed as a prop. Note however, that unlike the useIndexes hook example, this * component would also work if you were to pass the Indexes object directly * into it, making it more portable. * * ```jsx * import {Provider, useIndexesOrIndexesById} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = ({indexes}) => ( * * {JSON.stringify(useIndexesOrIndexesById(indexes).getIndexIds())} * * ); * * const indexes = createIndexes( * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ).setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["bySpecies"]' * ``` * @category Indexes hooks * @since v4.1.0 */ useIndexesOrIndexesById: ( indexesOrIndexesId?: IndexesOrIndexesId, ) => Indexes | undefined; /** * The useIndexIds hook gets an array of the Index Ids registered with an * Indexes object, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useIndexIds(indexesOrIndexesId?: IndexesOrIndexesId): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Indexes object or a set of Indexes objects named by * Id. The useIndexIds hook lets you indicate which Indexes object to get data * for: omit the optional final parameter for the default context Indexes * object, provide an Id for a named context Indexes object, or provide an * Indexes object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Index Ids in the Indexes object will cause a re-render. When the component * containing this hook is unmounted, the listener will be automatically * removed. * @param indexesOrIndexesId The Indexes object to be accessed: omit for the * default context Indexes object, provide an Id for a named context Indexes * object, or provide an explicit reference. * @returns The Index Ids in the Indexes object, or an empty array. * @example * This example creates an Indexes object outside the application, which is used * in the useIndexIds hook by reference. A newly-registered Index re-renders the * component. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useIndexIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * const App = () => {JSON.stringify(useIndexIds(indexes))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '[]' * * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); // !act * console.log(app.innerHTML); * // -> '["bySpecies"]' * ``` * @category Indexes hooks * @since v4.1.0 */ useIndexIds(indexesOrIndexesId?: IndexesOrIndexesId): Ids; /** * The useSliceIds hook gets the list of Slice Ids in an Index, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSliceIds( * indexId: Id, * indexesOrIndexesId?: IndexesOrIndexesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Indexes object or a set of Indexes objects named by * Id. The useSliceIds hook lets you indicate which Indexes object to get data * for: omit the optional final parameter for the default context Indexes * object, provide an Id for a named context Indexes object, or provide a * Indexes object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Slice Ids will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param indexId The Id of the Index. * @param indexesOrIndexesId The Indexes object to be accessed: omit for the * default context Indexes object, provide an Id for a named context Indexes * object, or provide an explicit reference. * @returns The Slice Ids in the Index, or an empty array. * @example * This example creates an Indexes object outside the application, which is used * in the useSliceIds hook by reference. A change to the Slice Ids re-renders * the component. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useSliceIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * const App = () => ( * {JSON.stringify(useSliceIds('bySpecies', indexes))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["dog","cat"]' * * store.setRow('pets', 'lowly', {species: 'worm'}); // !act * console.log(app.innerHTML); * // -> '["dog","cat","worm"]' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useSliceIds hook. * * ```jsx * import {Provider, useSliceIds} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => {JSON.stringify(useSliceIds('bySpecies'))}; * * const indexes = createIndexes( * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ).setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["dog","cat"]' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useSliceIds hook. * * ```jsx * import {Provider, useSliceIds} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useSliceIds('bySpecies', 'petIndexes'))} * ); * * const indexes = createIndexes( * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ).setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["dog","cat"]' * ``` * @category Indexes hooks * @since v1.0.0 */ useSliceIds: ( indexId: Id, indexesOrIndexesId?: IndexesOrIndexesId, ) => Ids; /** * The useSliceRowIds hook gets the list of Row Ids in a given Slice, and * registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSliceRowIds( * indexId: Id, * sliceId: Id, * indexesOrIndexesId?: IndexesOrIndexesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Indexes object or a set of Indexes objects named by * Id. The useSliceRowIds hook lets you indicate which Indexes object to get * data for: omit the optional final parameter for the default context Indexes * object, provide an Id for a named context Indexes object, or provide an * Indexes object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Row Ids in the Slice will cause a re-render. When the component containing * this hook is unmounted, the listener will be automatically removed. * @param indexId The Id of the Index. * @param sliceId The Id of the Slice in the Index. * @param indexesOrIndexesId The Indexes object to be accessed: omit for the * default context Indexes object, provide an Id for a named context Indexes * object, or provide an explicit reference. * @returns The Row Ids in the Slice, or an empty array. * @example * This example creates an Indexes object outside the application, which is used * in the useSliceRowIds hook by reference. A change to the Row Ids in the Slice * re-renders the component. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useSliceRowIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * const App = () => ( * * {JSON.stringify(useSliceRowIds('bySpecies', 'dog', indexes))} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * console.log(app.innerHTML); * // -> '["fido","cujo","toto"]' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useSliceRowIds hook. * * ```jsx * import {Provider, useSliceRowIds} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useSliceRowIds('bySpecies', 'dog'))} * ); * * const indexes = createIndexes( * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ).setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. A component within it then uses the useSliceRowIds hook. * * ```jsx * import {Provider, useSliceRowIds} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useSliceRowIds('bySpecies', 'dog', 'petIndexes'))} * * ); * * const indexes = createIndexes( * createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }), * ).setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @category Indexes hooks * @since v1.0.0 */ useSliceRowIds: ( indexId: Id, sliceId: Id, indexesOrIndexesId?: IndexesOrIndexesId, ) => Ids; /** * The useSliceIdsListener hook registers a listener function with the Indexes * object that will be called whenever the Slice Ids in an Index change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSliceIdsListener( * indexId: IdOrNull, * listener: SliceIdsListener, * listenerDeps?: React.DependencyList, * indexesOrIndexesId?: IndexesOrIndexesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useSliceIds hook). * * You can either listen to a single Index (by specifying the Index Id as the * method's first parameter), or changes to any Index (by providing a `null` * wildcard). * * Unlike the addSliceIdsListener method, which returns a listener Id and * requires you to remove it manually, the useSliceIdsListener hook manages this * lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Indexes object will be deleted. * @param indexId The Id of the Index to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Slice Ids in * the Index change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param indexesOrIndexesId The Indexes object to register the listener with: * omit for the default context Indexes object, provide an Id for a named * context Indexes object, or provide an explicit reference. * @example * This example uses the useSliceIdsListener hook to create a listener that is * scoped to a single component. When the component is unmounted, the listener * is removed from the Indexes object. * * ```jsx * import {Provider, useSliceIdsListener} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => { * useSliceIdsListener('bySpecies', () => console.log('Slice Ids changed')); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(indexes.getListenerStats().sliceIds); * // -> 1 * * store.setRow('pets', 'lowly', {species: 'worm'}); // !act * // -> 'Slice Ids changed' * * root.unmount(); // !act * console.log(indexes.getListenerStats().sliceIds); * // -> 0 * ``` * @category Indexes hooks * @since v1.0.0 */ useSliceIdsListener: ( indexId: IdOrNull, listener: SliceIdsListener, listenerDeps?: React.DependencyList, indexesOrIndexesId?: IndexesOrIndexesId, ) => void; /** * The useSliceRowIdsListener hook registers a listener function with the * Indexes object that will be called whenever the Row Ids in a Slice change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSliceRowIdsListener( * indexId: IdOrNull, * sliceId: IdOrNull, * listener: SliceRowIdsListener, * listenerDeps?: React.DependencyList, * indexesOrIndexesId?: IndexesOrIndexesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useSliceRowIds hook). * * You can either listen to a single Slice (by specifying the Index Id and Slice * Id as the method's first two parameters), or changes to any Slice (by * providing `null` wildcards). * * Both, either, or neither of the `indexId` and `sliceId` parameters can be * wildcarded with `null`. You can listen to a specific Slice in a specific * Index, any Slice in a specific Index, a specific Slice in any Index, or any * Slice in any Index. * * Unlike the addSliceRowIdsListener method, which returns a listener Id and * requires you to remove it manually, the useSliceRowIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Indexes object will be deleted. * @param indexId The Id of the Index to listen to, or `null` as a wildcard. * @param sliceId The Id of the Slice to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Row Ids in the * Slice change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param indexesOrIndexesId The Indexes object to register the listener with: * omit for the default context Indexes object, provide an Id for a named * context Indexes object, or provide an explicit reference. * @example * This example uses the useSliceRowIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Indexes object. * * ```jsx * import {Provider, useSliceRowIdsListener} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => { * useSliceRowIdsListener('bySpecies', 'dog', () => * console.log('Slice Row Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(indexes.getListenerStats().sliceRowIds); * // -> 1 * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * // -> 'Slice Row Ids changed' * * root.unmount(); // !act * console.log(indexes.getListenerStats().sliceRowIds); * // -> 0 * ``` * @category Indexes hooks * @since v1.0.0 */ useSliceRowIdsListener: ( indexId: IdOrNull, sliceId: IdOrNull, listener: SliceRowIdsListener, listenerDeps?: React.DependencyList, indexesOrIndexesId?: IndexesOrIndexesId, ) => void; /** * The useCreateRelationships hook is used to create a Relationships object * within a React application with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateRelationships( * store: Store | undefined, * create: (store: Store) => Relationships, * createDeps?: React.DependencyList, * ): Relationships | undefined; * ``` * * It is possible to create a Relationships object outside of the React app with * the regular createRelationships 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 Relationships object being created every time the app renders * or re-renders, since v5.0 this hook performs the creation in an effect. As a * result it will return `undefined` on the brief first render (or if the Store * is not yet defined), which you should defend against. * * If your `create` function contains other dependencies, the changing of which * should also cause the Relationships object 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. * * This hook ensures the Relationships object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Relationships * object. * @param create An optional callback for performing post-creation steps on the * Relationships object, such as adding definitions or listeners. * @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 Relationships object. * @example * This example creates a Relationships object at the top level of a React * application. Even though the App component is rendered twice, the * Relationships object creation only occurs once by default. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import {useCreateRelationships, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(() => * createStore() * .setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }) * .setTable('species', {dog: {price: 5}, cat: {price: 4}}), * ); * const relationships = useCreateRelationships(store, (store) => { * console.log('Relationships created'); * return createRelationships(store).setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * }); * return ( * {relationships?.getRemoteRowId('petSpecies', 'fido')} * ); * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Relationships created' * * root.render(); // !act * // No second Relationships creation * * console.log(app.innerHTML); * // -> 'dog' * ``` * @example * This example creates a Relationships object at the top level of a React * application. The App component is rendered twice, each with a different * top-level prop. The useCreateRelationships hook takes the * `remoteTableAndCellToLink` prop as a dependency, and so the Relationships * object is created again on the second render. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import {useCreateRelationships, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({remoteTableAndCellToLink}) => { * const store = useCreateStore(() => * createStore() * .setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'brown'}, * }) * .setTable('species', {dog: {price: 5}, cat: {price: 4}}) * .setTable('color', {brown: {discount: 0.1}, black: {discount: 0}}), * ); * const relationships = useCreateRelationships( * store, * (store) => { * console.log(`Relationship created to ${remoteTableAndCellToLink}`); * return createRelationships(store).setRelationshipDefinition( * 'cellLinked', * 'pets', * remoteTableAndCellToLink, * remoteTableAndCellToLink, * ); * }, * [remoteTableAndCellToLink], * ); * return ( * {relationships?.getRemoteRowId('cellLinked', 'fido')} * ); * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Relationship created to species' * * console.log(app.innerHTML); * // -> 'dog' * * root.render(); // !act * // -> 'Relationship created to color' * * console.log(app.innerHTML); * // -> 'brown' * ``` * @category Relationships hooks * @since v1.0.0 */ useCreateRelationships: ( store: Store | undefined, create: (store: Store) => Relationships, createDeps?: React.DependencyList, ) => Relationships | undefined; /** * The useRelationshipsIds hook is used to retrieve the Ids of all the named * Relationships objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Relationships objects to a Provider context and * an inner component accesses their Ids. * * ```jsx * import { * Provider, * useCreateRelationships, * useCreateStore, * useRelationshipsIds, * } from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store1 = useCreateStore(createStore); * const relationships1 = useCreateRelationships( * store1, * createRelationships, * ); * const store2 = useCreateStore(createStore); * const relationships2 = useCreateRelationships( * store2, * createRelationships, * ); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useRelationshipsIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["relationships1","relationships2"]' * ``` * @category Relationships hooks * @since v4.1.0 */ useRelationshipsIds: () => Ids; /** * The useRelationships hook is used to get a reference to a Relationships * object from within a Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRelationships(id?: Id): Relationships | undefined; * ``` * * A Provider component is used to wrap part of an application in a context. It * can contain a default Relationships object (or a set of Relationships objects * named by Id) that can be easily accessed without having to be passed down as * props through every component. * * The useRelationships hook lets you either get a reference to the default * Relationships object (when called without a parameter), or one of the * Relationships objects that are named by Id (when called with an Id * parameter). * @param id An optional Id for accessing a Relationships object that was named * with an Id in the Provider. * @returns A reference to the Relationships object (or `undefined` if not * within a Provider context, or if the requested Relationships object does not * exist). * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useRelationships hook * to get a reference to the Relationships object again, without the need to * have it passed as a prop. * * ```jsx * import {Provider, useRelationships} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * {useRelationships().getListenerStats().remoteRowId} * ); * * const relationships = createRelationships(createStore()); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @example * This example creates a Provider context into which a Relationships object is * provided, named by Id. A component within it then uses the useRelationships * hook with that Id to get a reference to the Relationships object again, * without the need to have it passed as a prop. * * ```jsx * import {Provider, useRelationships} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * * {useRelationships('petStore').getListenerStats().remoteRowId} * * ); * * const relationships = createRelationships(createStore()); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Relationships hooks * @since v1.0.0 */ useRelationships: (id?: Id) => Relationships | undefined; /** * The useRelationshipsOrRelationshipsById hook is used to get a reference to a * Relationships object from within a Provider component context, _or_ have it * passed directly to this hook. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRelationshipsOrRelationshipsById( * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): Relationships | undefined; * ``` * * This is mostly of use when you are developing a component that needs a * Relationships 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 * Relationships-based components). * * This is unlikely to be used often. For most situations, you will want to use * the useRelationships hook. * @param relationshipsOrRelationshipsId Either an Id for accessing a * Relationships object that was named with an Id in the Provider, or the * Relationships object itself. * @returns A reference to the Relationships object (or `undefined` if not * within a Provider context, or if the requested Relationships object does not * exist). * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the * useRelationshipsOrRelationshipsById hook to get a reference to the * Relationships object again, without the need to have it passed as a prop. * Note however, that unlike the useRelationships hook example, this component * would also work if you were to pass the Relationships object directly into * it, making it more portable. * * ```jsx * import { * Provider, * useRelationshipsOrRelationshipsById, * } from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = ({relationships}) => ( * * {JSON.stringify( * useRelationshipsOrRelationshipsById( * relationships, * ).getRelationshipIds(), * )} * * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["petSpecies"]' * ``` * @category Relationships hooks * @since v4.1.0 */ useRelationshipsOrRelationshipsById: ( relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => Relationships | undefined; /** * The useRelationshipIds hook gets an array of the Relationship Ids registered * with a Relationships object, and registers a listener so that any changes to * that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRelationshipIds( * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Relationships object or a set of Relationships * objects named by Id. The useRelationshipIds hook lets you indicate which * Relationships object to get data for: omit the optional final parameter for * the default context Relationships object, provide an Id for a named context * Relationships object, or provide a Relationships object explicitly by * reference. * * When first rendered, this hook will create a listener so that changes to the * Relationship Ids in the Relationships object will cause a re-render. When the * component containing this hook is unmounted, the listener will be * automatically removed. * @param relationshipsOrRelationshipsId The Relationships object to be * accessed: omit for the default context Relationships object, provide an Id * for a named context Relationships object, or provide an explicit reference. * @returns The Relationship Ids in the Relationships object, or an empty array. * @example * This example creates an Relationships object outside the application, which * is used in the useRelationshipIds hook by reference. A newly-registered * Relationship re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useRelationshipIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const relationships = createRelationships(store); * const App = () => ( * {JSON.stringify(useRelationshipIds(relationships))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '[]' * * const addRelationshipDefinition = () => * relationships.setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * addRelationshipDefinition(); // !act * console.log(app.innerHTML); * // -> '["petSpecies"]' * ``` * @category Relationships hooks * @since v4.1.0 */ useRelationshipIds( relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ): Ids; /** * The useRemoteRowId hook gets the remote Row Id for a given local Row in a * Relationship, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRemoteRowId( * relationshipId: Id, * localRowId: Id, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): Id | undefined; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Relationships object or a set of Relationships * objects named by Id. The useRemoteRowId hook lets you indicate which * Relationships object to get data for: omit the optional final parameter for * the default context Relationships object, provide an Id for a named context * Relationships object, or provide a Relationships object explicitly by * reference. * * When first rendered, this hook will create a listener so that changes to the * remote Row Id will cause a re-render. When the component containing this hook * is unmounted, the listener will be automatically removed. * @param relationshipId The Id of the Relationship. * @param localRowId The Id of the local Row in the Relationship. * @param relationshipsOrRelationshipsId The Relationships object to be * accessed: omit for the default context Relationships object, provide an Id * for a named context Relationships object, or provide an explicit reference. * @returns The remote Row Id in the Relationship, or `undefined`. * @example * This example creates a Relationships object outside the application, which is * used in the useRemoteRowId hook by reference. A change to the remote Row Id * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useRemoteRowId} from 'tinybase/ui-react'; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * const App = () => ( * {useRemoteRowId('petSpecies', 'cujo', relationships)} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'dog' * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * console.log(app.innerHTML); * // -> 'wolf' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useRemoteRowId hook. * * ```jsx * import {Provider, useRemoteRowId} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => {useRemoteRowId('petSpecies', 'cujo')}; * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'dog' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useRemoteRowId hook. * * ```jsx * import {Provider, useRemoteRowId} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * {useRemoteRowId('petSpecies', 'cujo', 'petRelationships')} * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'dog' * ``` * @category Relationships hooks * @since v1.0.0 */ useRemoteRowId: ( relationshipId: Id, localRowId: Id, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => Id | undefined; /** * The useLocalRowIds hook gets the local Row Ids for a given remote Row in a * Relationship, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useLocalRowIds( * relationshipId: Id, * remoteRowId: Id, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Relationships object or a set of Relationships * objects named by Id. The useLocalRowIds hook lets you indicate which * Relationships object to get data for: omit the optional final parameter for * the default context Relationships object, provide an Id for a named context * Relationships object, or provide a Relationships object explicitly by * reference. * * When first rendered, this hook will create a listener so that changes to the * local Row Id will cause a re-render. When the component containing this hook * is unmounted, the listener will be automatically removed. * @param relationshipId The Id of the Relationship. * @param remoteRowId The Id of the remote Row in the Relationship. * @param relationshipsOrRelationshipsId The Relationships object to be * accessed: omit for the default context Relationships object, provide an Id * for a named context Relationships object, or provide an explicit reference. * @returns The local Row Ids in the Relationship, or an empty array. * @example * This example creates a Relationships object outside the application, which is * used in the useLocalRowIds hook by reference. A change to the local Row Ids * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useLocalRowIds} from 'tinybase/ui-react'; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * const App = () => ( * * {JSON.stringify(useLocalRowIds('petSpecies', 'dog', relationships))} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * console.log(app.innerHTML); * // -> '["fido","cujo","toto"]' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useLocalRowIds hook. * * ```jsx * import {Provider, useLocalRowIds} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useLocalRowIds('petSpecies', 'dog'))} * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useLocalRowIds hook. * * ```jsx * import {Provider, useLocalRowIds} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify( * useLocalRowIds('petSpecies', 'dog', 'petRelationships'), * )} * * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @category Relationships hooks * @since v1.0.0 */ useLocalRowIds: ( relationshipId: Id, remoteRowId: Id, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => Ids; /** * The useLinkedRowIds hook gets the linked Row Ids for a given Row in a linked * list Relationship, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useLinkedRowIds( * relationshipId: Id, * firstRowId: Id, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Relationships object or a set of Relationships * objects named by Id. The useLinkedRowIds hook lets you indicate which * Relationships object to get data for: omit the optional final parameter for * the default context Relationships object, provide an Id for a named context * Relationships object, or provide a Relationships object explicitly by * reference. * * When first rendered, this hook will create a listener so that changes to the * linked Row Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param relationshipId The Id of the Relationship. * @param firstRowId The Id of the first Row in the linked list Relationship. * @param relationshipsOrRelationshipsId The Relationships object to be * accessed: omit for the default context Relationships object, provide an Id * for a named context Relationships object, or provide an explicit reference. * @returns The linked Row Ids in the Relationship. * @example * This example creates a Relationships object outside the application, which is * used in the useLinkedRowIds hook by reference. A change to the linked Row Ids * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useLinkedRowIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', next: 'felix'}, * felix: {species: 'cat', next: 'cujo'}, * cujo: {species: 'dog'}, * }); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSequence', * 'pets', * 'pets', * 'next', * ); * const App = () => ( * * {JSON.stringify(useLinkedRowIds('petSequence', 'fido', relationships))} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","felix","cujo"]' * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * store.setCell('pets', 'cujo', 'next', 'toto'); // !act * console.log(app.innerHTML); * // -> '["fido","felix","cujo","toto"]' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useLinkedRowIds hook. * * ```jsx * import {Provider, useLinkedRowIds} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useLinkedRowIds('petSequence', 'fido'))} * ); * * const relationships = createRelationships( * createStore().setTable('pets', { * fido: {species: 'dog', next: 'felix'}, * felix: {species: 'cat', next: 'cujo'}, * cujo: {species: 'dog'}, * }), * ).setRelationshipDefinition('petSequence', 'pets', 'pets', 'next'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["fido","felix","cujo"]' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. A component within it then uses the useLinkedRowIds hook. * * ```jsx * import {Provider, useLinkedRowIds} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify( * useLinkedRowIds('petSequence', 'fido', 'petRelationships'), * )} * * ); * * const relationships = createRelationships( * createStore().setTable('pets', { * fido: {species: 'dog', next: 'felix'}, * felix: {species: 'cat', next: 'cujo'}, * cujo: {species: 'dog'}, * }), * ).setRelationshipDefinition('petSequence', 'pets', 'pets', 'next'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["fido","felix","cujo"]' * ``` * @category Relationships hooks * @since v1.0.0 */ useLinkedRowIds: ( relationshipId: Id, firstRowId: Id, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => Ids; /** * The useRemoteRowIdListener hook registers a listener function with the * Relationships object that will be called whenever a remote Row Id in a * Relationship changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRemoteRowIdListener( * relationshipId: IdOrNull, * localRowId: IdOrNull, * listener: RemoteRowIdListener, * listenerDeps?: React.DependencyList, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useRemoteRowId hook). * * You can either listen to a single local Row (by specifying the Relationship * Id and local Row Id as the method's first two parameters), or changes to any * local Row (by providing a `null` wildcards). * * Both, either, or neither of the `relationshipId` and `localRowId` parameters * can be wildcarded with `null`. You can listen to a specific local Row in a * specific Relationship, any local Row in a specific Relationship, a specific * local Row in any Relationship, or any local Row in any Relationship. * * Unlike the addRemoteRowIdListener method, which returns a listener Id and * requires you to remove it manually, the useRemoteRowIdListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Indexes object will be deleted. * @param relationshipId The Id of the Relationship to listen to, or `null` as a * wildcard. * @param localRowId The Id of the local Row to listen to, or `null` as a * wildcard. * @param listener The function that will be called whenever the remote Row Id * changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param relationshipsOrRelationshipsId The Relationships object to register * the listener with: omit for the default context Relationships object, provide * an Id for a named context Relationships object, or provide an explicit * reference. * @example * This example uses the useRemoteRowIdListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Relationships object. * * ```jsx * import {Provider, useRemoteRowIdListener} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => { * useRemoteRowIdListener('petSpecies', 'cujo', () => * console.log('Remote Row Id changed'), * ); * return App; * }; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store); * relationships.setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(relationships.getListenerStats().remoteRowId); * // -> 1 * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * // -> 'Remote Row Id changed' * * root.unmount(); // !act * console.log(relationships.getListenerStats().remoteRowId); * // -> 0 * ``` * @category Relationships hooks * @since v1.0.0 */ useRemoteRowIdListener: ( relationshipId: IdOrNull, localRowId: IdOrNull, listener: RemoteRowIdListener, listenerDeps?: React.DependencyList, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => void; /** * The useLocalRowIdsListener hook registers a listener function with the * Relationships object that will be called whenever the local Row Ids in a * Relationship change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useLocalRowIdsListener( * relationshipId: IdOrNull, * remoteRowId: IdOrNull, * listener: LocalRowIdsListener, * listenerDeps?: React.DependencyList, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useLocalRowsId hook). * * You can either listen to a single local Row (by specifying the Relationship * Id and local Row Id as the method's first two parameters), or changes to any * local Row (by providing a `null` wildcards). * * Both, either, or neither of the `relationshipId` and `remoteRowId` parameters * can be wildcarded with `null`. You can listen to a specific remote Row in a * specific Relationship, any remote Row in a specific Relationship, a specific * remote Row in any Relationship, or any remote Row in any Relationship. * * Unlike the addLocalRowsIdListener method, which returns a listener Id and * requires you to remove it manually, the useLocalRowIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Indexes object will be deleted. * @param relationshipId The Id of the Relationship to listen to, or `null` as a * wildcard. * @param remoteRowId The Id of the remote Row to listen to, or `null` as a * wildcard. * @param listener The function that will be called whenever the local Row Ids * change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param relationshipsOrRelationshipsId The Relationships object to register * the listener with: omit for the default context Relationships object, provide * an Id for a named context Relationships object, or provide an explicit * reference. * @example * This example uses the useLocalRowIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Relationships object. * * ```jsx * import {Provider, useLocalRowIdsListener} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => { * useLocalRowIdsListener('petSpecies', 'dog', () => * console.log('Local Row Ids changed'), * ); * return App; * }; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store); * relationships.setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(relationships.getListenerStats().localRowIds); * // -> 1 * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * // -> 'Local Row Ids changed' * * root.unmount(); // !act * console.log(relationships.getListenerStats().localRowIds); * // -> 0 * ``` * @category Relationships hooks * @since v1.0.0 */ useLocalRowIdsListener: ( relationshipId: IdOrNull, remoteRowId: IdOrNull, listener: LocalRowIdsListener, listenerDeps?: React.DependencyList, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => void; /** * The useLinkedRowIdsListener hook registers a listener function with the * Relationships object that will be called whenever the linked Row Ids in a * Relationship change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useLinkedRowIdsListener( * relationshipId: Id, * firstRowId: Id, * listener: LinkedRowIdsListener, * listenerDeps?: React.DependencyList, * relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useLinkedRowsId hook). * * Unlike other listener registration methods, you cannot provide `null` * wildcards for the first two parameters of the useLinkedRowIdsListener method. * This prevents the prohibitive expense of tracking all the possible linked * lists (and partial linked lists within them) in a Store. * * Unlike the addLinkedRowsIdListener method, which returns a listener Id and * requires you to remove it manually, the useLinkedRowIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Indexes object will be deleted. * @param relationshipId The Id of the Relationship to listen to. * @param firstRowId The Id of the first Row of the linked list to listen to. * @param listener The function that will be called whenever the linked Row Ids * change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param relationshipsOrRelationshipsId The Relationships object to register * the listener with: omit for the default context Relationships object, provide * an Id for a named context Relationships object, or provide an explicit * reference. * @example * This example uses the useLinkedRowIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Relationships object. * * ```jsx * import {Provider, useLinkedRowIdsListener} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => { * useLinkedRowIdsListener('petSequence', 'fido', () => * console.log('Linked Row Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', next: 'felix'}, * felix: {species: 'cat', next: 'cujo'}, * cujo: {species: 'dog'}, * }); * const relationships = createRelationships(store); * relationships.setRelationshipDefinition( * 'petSequence', * 'pets', * 'pets', * 'next', * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(relationships.getListenerStats().linkedRowIds); * // -> 1 * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * store.setCell('pets', 'cujo', 'next', 'toto'); // !act * // -> 'Linked Row Ids changed' * * root.unmount(); // !act * console.log(relationships.getListenerStats().linkedRowIds); * // -> 0 * ``` * @category Relationships hooks * @since v1.0.0 */ useLinkedRowIdsListener: ( relationshipId: Id, firstRowId: Id, listener: LinkedRowIdsListener, listenerDeps?: React.DependencyList, relationshipsOrRelationshipsId?: RelationshipsOrRelationshipsId, ) => void; /** * The useCreateQueries hook is used to create a Queries object within a React * application with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateQueries( * store: Store | undefined, * create: (store: Store) => Queries, * createDeps?: React.DependencyList, * ): Queries | undefined; * ``` * * It is possible to create a Queries object outside of the React app with the * regular createQueries 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 * Queries object being created every time the app renders or re-renders, since * v5.0 this hook performs the creation in an effect. As a result it will return * `undefined` on the brief first render (or if the Store is not yet defined), * which you should defend against. * * If your `create` function contains other dependencies, the changing of which * should also cause the Queries object 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. * * This hook ensures the Queries object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Queries * object. * @param create An optional callback for performing post-creation steps on the * Queries object, such as adding definitions or listeners. * @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 Queries object. * @example * This example creates a Queries object at the top level of a React * application. Even though the App component is rendered twice, the Queries * object creation only occurs once by default. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import {useCreateQueries, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(() => * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ); * const queries = useCreateQueries(store, (store) => { * console.log('Queries created'); * return createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * }); * return ( * {queries?.getResultCell('dogColors', 'fido', 'color')} * ); * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Queries created' * * root.render(); // !act * // No second Queries creation * * console.log(app.innerHTML); * // -> 'brown' * ``` * @example * This example creates a Queries object at the top level of a React * application. The App component is rendered twice, each with a different * top-level prop. The useCreateQueries hook takes the `resultCell` prop as a * dependency, and so the Queries object is created again on the second render. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import {useCreateQueries, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(() => * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ); * const queries = useCreateQueries(store, (store) => { * console.log('Queries created'); * return createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * }); * return ( * {queries?.getResultCell('dogColors', 'fido', 'color')} * ); * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Queries created' * * root.render(); // !act * // No second Queries creation * * console.log(app.innerHTML); * // -> 'brown' * ``` * @category Queries hooks * @since v2.0.0 */ useCreateQueries: ( store: Store | undefined, create: (store: Store) => Queries, createDeps?: React.DependencyList, ) => Queries | undefined; /** * The useQueriesIds hook is used to retrieve the Ids of all the named Queries * objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Queries objects to a Provider context and an * inner component accesses their Ids. * * ```jsx * import { * Provider, * useCreateQueries, * useCreateStore, * useQueriesIds, * } from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store1 = useCreateStore(createStore); * const queries1 = useCreateQueries(store1, createQueries); * const store2 = useCreateStore(createStore); * const queries2 = useCreateQueries(store2, createQueries); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useQueriesIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["queries1","queries2"]' * ``` * @category Queries hooks * @since v4.1.0 */ useQueriesIds: () => Ids; /** * The useQueries hook is used to get a reference to a Queries object from * within a Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useQueries(id?: Id): Queries | undefined; * ``` * * A Provider component is used to wrap part of an application in a context. It * can contain a default Queries object (or a set of Queries objects named by * Id) that can be easily accessed without having to be passed down as props * through every component. * * The useQueries hook lets you either get a reference to the default Queries * object (when called without a parameter), or one of the Queries objects that * are named by Id (when called with an Id parameter). * @param id An optional Id for accessing a Queries object that was named with * an Id in the Provider. * @returns A reference to the Queries object (or `undefined` if not within a * Provider context, or if the requested Queries object does not exist). * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useQueries hook to get a * reference to the Queries object again, without the need to have it passed as * a prop. * * ```jsx * import {Provider, useQueries} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => {useQueries().getListenerStats().table}; * * const queries = createQueries(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useQueries hook * with that Id to get a reference to the Queries object again, without the need * to have it passed as a prop. * * ```jsx * import {Provider, useQueries} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {useQueries('petQueries').getListenerStats().table} * ); * * const queries = createQueries(createStore()); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Queries hooks * @since v2.0.0 */ useQueries: (id?: Id) => Queries | undefined; /** * The useQueriesOrQueriesById hook is used to get a reference to a Queries * object from within a Provider component context, _or_ have it passed directly * to this hook. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useQueriesOrQueriesById( * queriesOrQueriesId?: QueriesOrQueriesId, * ): Queries | undefined; * ``` * * This is mostly of use when you are developing a component that needs a * Queries 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 * Queries-based components). * * This is unlikely to be used often. For most situations, you will want to use * the useQueries hook. * @param queriesOrQueriesId Either an Id for accessing a Queries object that * was named with an Id in the Provider, or the Queries object itself. * @returns A reference to the Queries object (or `undefined` if not within a * Provider context, or if the requested Queries object does not exist). * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useQueriesOrQueriesById hook * to get a reference to the Queries object again, without the need to have it * passed as a prop. Note however, that unlike the useQueries hook example, this * component would also work if you were to pass the Queries object directly * into it, making it more portable. * * ```jsx * import {Provider, useQueriesOrQueriesById} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = ({queries}) => ( * * {JSON.stringify(useQueriesOrQueriesById(queries).getQueryIds())} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '["dogColors"]' * ``` * @category Queries hooks * @since v4.1.0 */ useQueriesOrQueriesById: ( queriesOrQueriesId?: QueriesOrQueriesId, ) => Queries | undefined; /** * The useQueryIds hook gets an array of the Query Ids registered with a Queries * object, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useQueryIds(queriesOrQueriesId?: QueriesOrQueriesId): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useQueryIds hook lets you indicate which Queries object to get data * for: omit the optional final parameter for the default context Queries * object, provide an Id for a named context Queries object, or provide a * Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * Query Ids in the Queries object will cause a re-render. When the component * containing this hook is unmounted, the listener will be automatically * removed. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns The Query Ids in the Queries object, or an empty array. * @example * This example creates an Queries object outside the application, which is used * in the useQueryIds hook by reference. A newly-registered Relationship * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useQueryIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const queries = createQueries(store); * const App = () => {JSON.stringify(useQueryIds(queries))}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '[]' * * const addQueryDefinition = () => * queries.setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * addQueryDefinition(); // !act * console.log(app.innerHTML); * // -> '["dogColors"]' * ``` * @category Queries hooks * @since v4.1.0 */ useQueryIds(queriesOrQueriesId?: QueriesOrQueriesId): Ids; /** * The useResultTable hook returns an object containing the entire data of the * ResultTable of the given query, and registers a listener so that any changes * to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultTable( * queryId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Table; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultTable hook lets you indicate which Queries object to get * data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * query result will cause a re-render. When the component containing this hook * is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns An object containing the entire data of the ResultTable. * @example * This example creates a Queries object outside the application, which is used * in the useTable hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultTable} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * const App = () => ( * {JSON.stringify(useResultTable('dogColors', queries))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"},"cujo":{"color":"black"}}' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"walnut"},"cujo":{"color":"black"}}' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultTable hook. * * ```jsx * import {Provider, useResultTable} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultTable('dogColors'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"},"cujo":{"color":"black"}}' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultTable * hook. * * ```jsx * import {Provider, useResultTable} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultTable('dogColors', 'petQueries'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"fido":{"color":"brown"},"cujo":{"color":"black"}}' * ``` * @category Queries hooks * @since v2.0.0 */ useResultTable: ( queryId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => ResultTable; /** * The useResultTableCellIds hook returns the Ids of every Cell used across the * whole ResultTable of the given query, and registers a listener so that any * changes to those Ids will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultTableCellIds( * queryId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultTableCellIds hook lets you indicate which Queries object to * get data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * result Cell Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. See the * addResultTableCellIdsListener method for more details. * @returns An array of the Ids of every Cell in the result of the query. * @example * This example creates a Queries object outside the application, which is used * in the useResultTableCellIds hook by reference. A change to the data in the * query re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultTableCellIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColorsAndLegs', * 'pets', * ({select, where}) => { * select('color'); * select('legs'); * where('species', 'dog'); * }, * ); * const App = () => ( * * {JSON.stringify(useResultTableCellIds('dogColorsAndLegs', queries))} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color"]' * * store.setCell('pets', 'cujo', 'legs', 4); // !act * console.log(app.innerHTML); * // -> '["color","legs"]' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultTableCellIds hook. * * ```jsx * import {Provider, useResultTableCellIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultTableCellIds('dogColorsAndLegs'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black', legs: 4}, * }), * ).setQueryDefinition('dogColorsAndLegs', 'pets', ({select, where}) => { * select('color'); * select('legs'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color","legs"]' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the * useResultTableCellIds hook. * * ```jsx * import {Provider, useResultTableCellIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify( * useResultTableCellIds('dogColorsAndLegs', 'petQueries'), * )} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black', legs: 4}, * }), * ).setQueryDefinition('dogColorsAndLegs', 'pets', ({select, where}) => { * select('color'); * select('legs'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["color","legs"]' * ``` * @category Queries hooks * @since v4.1.0 */ useResultTableCellIds: ( queryId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => Ids; /** * The useResultRowCount hook returns the count of the Row objects in the * ResultTable of the given query, and registers a listener so that any changes * to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRowCount( * queryId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): number; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultRowCount hook lets you indicate which Queries object to get * data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * count of ResultRow objects will cause a re-render. When the component * containing this hook is unmounted, the listener will be automatically * removed. * @param queryId The Id of the query. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. See the addResultRowCountListener * method for more details. * @returns The number of ResultRow objects in the ResultTable. * @example * This example creates a Queries object outside the application, which is used * in the useResultRowCount hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultRowCount} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * const App = () => {useResultRowCount('dogColors', queries)}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '2' * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * console.log(app.innerHTML); * // -> '1' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultRowCount hook. * * ```jsx * import {Provider, useResultRowCount} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => {useResultRowCount('dogColors')}; * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '2' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultRowCount * hook. * * ```jsx * import {Provider, useResultRowCount} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {useResultRowCount('dogColors', 'petQueries')} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '2' * ``` * @category Queries hooks * @since v4.1.0 */ useResultRowCount: ( queryId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => number; /** * The useResultRowIds hook returns the Ids of every Row in the ResultTable of * the given query, and registers a listener so that any changes to those Ids * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRowIds( * queryId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultRowIds hook lets you indicate which Queries object to get * data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * result Row Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. See the addResultRowIdsListener * method for more details. * @returns An array of the Ids of every Row in the result of the query. * @example * This example creates a Queries object outside the application, which is used * in the useResultRowIds hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultRowIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * const App = () => ( * {JSON.stringify(useResultRowIds('dogColors', queries))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * console.log(app.innerHTML); * // -> '["fido"]' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultRowIds hook. * * ```jsx * import {Provider, useResultRowIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultRowIds('dogColors'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultRowIds * hook. * * ```jsx * import {Provider, useResultRowIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultRowIds('dogColors', 'petQueries'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["fido","cujo"]' * ``` * @category Queries hooks * @since v2.0.0 */ useResultRowIds: ( queryId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => Ids; /** * The useResultSortedRowIds hook returns the sorted (and optionally, paginated) * Ids of every Row in the ResultTable of the given query, and registers a * listener so that any changes to those Ids will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultSortedRowIds( * queryId: Id, * cellId?: Id, * descending?: boolean, * offset?: number, * limit?: number, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultSortedRowIds hook lets you indicate which Queries object to * get data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * sorted result Row Ids will cause a re-render. When the component containing * this hook is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param cellId The Id of the result Cell whose values are used for the * sorting, or `undefined` to by sort the result Row Id itself. * @param descending Whether the sorting should be in descending order. * @param offset The number of Row Ids to skip for pagination purposes, if any. * @param limit The maximum number of Row Ids to return, or `undefined` for all. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns An array of the Ids of every Row in the result of the query. * @example * This example creates a Queries object outside the application, which is used * in the useResultSortedRowIds hook by reference. A change to the data in the * query re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultSortedRowIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * const App = () => ( * * {JSON.stringify( * useResultSortedRowIds( * 'dogColors', * 'color', * false, * 0, * undefined, * queries, * ), * )} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["cujo","fido"]' * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * console.log(app.innerHTML); * // -> '["fido"]' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultSortedRowIds hook. * * ```jsx * import {Provider, useResultSortedRowIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useResultSortedRowIds('dogColors', 'color'))} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["cujo","fido"]' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the * useResultSortedRowIds hook. * * ```jsx * import {Provider, useResultSortedRowIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify( * useResultSortedRowIds( * 'dogColors', * 'color', * false, * 0, * undefined, * 'petQueries', * ), * )} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["cujo","fido"]' * ``` * @category Queries hooks * @since v2.0.0 */ useResultSortedRowIds: ( queryId: Id, cellId?: Id, descending?: boolean, offset?: number, limit?: number, queriesOrQueriesId?: QueriesOrQueriesId, ) => Ids; /** * The useResultRow hook returns an object containing the data of a single Row * in the ResultTable of the given query, and registers a listener so that any * changes to that Row will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRow( * queryId: Id, * rowId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Row; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultRow hook lets you indicate which Queries object to get data * for: omit the final optional final parameter for the default context Queries * object, provide an Id for a named context Queries object, or provide a * Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * result Row will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param rowId The Id of the Row in the ResultTable. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns An object containing the entire data of the Row in the ResultTable * of the query. * @example * This example creates a Queries object outside the application, which is used * in the useResultRow hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultRow} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('color'); * where('species', 'dog'); * }, * ); * const App = () => ( * {JSON.stringify(useResultRow('dogColors', 'fido', queries))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '{"color":"walnut"}' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultRow hook. * * ```jsx * import {Provider, useResultRow} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultRow('dogColors', 'fido'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultRow * hook. * * ```jsx * import {Provider, useResultRow} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useResultRow('dogColors', 'fido', 'petQueries'))} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '{"color":"brown"}' * ``` * @category Queries hooks * @since v2.0.0 */ useResultRow: ( queryId: Id, rowId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => ResultRow; /** * The useResultCellIds hook returns the Ids of every Cell in a given Row in the * ResultTable of the given query, and registers a listener so that any changes * to those Ids will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultCellIds( * queryId: Id, * rowId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Ids; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultCellIds hook lets you indicate which Queries object to get * data for: omit the final optional final parameter for the default context * Queries object, provide an Id for a named context Queries object, or provide * a Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * result Cell Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param rowId The Id of the Row in the ResultTable. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns An array of the Ids of every Cell in the Row in the result of the * query. * @example * This example creates a Queries object outside the application, which is used * in the useResultCellIds hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultCellIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('species'); * select('color'); * select('legs'); * where('species', 'dog'); * }, * ); * const App = () => ( * * {JSON.stringify(useResultCellIds('dogColors', 'fido', queries))} * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["species","color"]' * * store.setCell('pets', 'fido', 'legs', 4); // !act * console.log(app.innerHTML); * // -> '["species","color","legs"]' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultCellIds hook. * * ```jsx * import {Provider, useResultCellIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useResultCellIds('dogColors', 'fido'))} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('species'); * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["species","color"]' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultCellIds * hook. * * ```jsx * import {Provider, useResultCellIds} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * {JSON.stringify(useResultCellIds('dogColors', 'fido', 'petQueries'))} * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('species'); * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["species","color"]' * ``` * @category Queries hooks * @since v2.0.0 */ useResultCellIds: ( queryId: Id, rowId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => Ids; /** * The useResultCell hook returns the value of a single Cell in a given Row in * the ResultTable of the given query, and registers a listener so that any * changes to that value will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultCell( * queryId: Id, * rowId: Id, * cellId: Id, * queriesOrQueriesId?: QueriesOrQueriesId, * ): Cell | undefined; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Queries object or a set of Queries objects named by * Id. The useResultCell hook lets you indicate which Queries object to get data * for: omit the final optional final parameter for the default context Queries * object, provide an Id for a named context Queries object, or provide a * Queries object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * result Cell will cause a re-render. When the component containing this hook * is unmounted, the listener will be automatically removed. * @param queryId The Id of the query. * @param rowId The Id of the Row in the ResultTable. * @param cellId The Id of the Cell in the Row. * @param queriesOrQueriesId The Queries object to be accessed: omit for the * default context Queries object, provide an Id for a named context Queries * object, or provide an explicit reference. * @returns The value of the Cell, or `undefined`. * @example * This example creates a Queries object outside the application, which is used * in the useResultCell hook by reference. A change to the data in the query * re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useResultCell} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'dogColors', * 'pets', * ({select, where}) => { * select('species'); * select('color'); * select('legs'); * where('species', 'dog'); * }, * ); * const App = () => ( * {useResultCell('dogColors', 'fido', 'color', queries)} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> 'walnut' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. A component within it then uses the useResultCell hook. * * ```jsx * import {Provider, useResultCell} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {useResultCell('dogColors', 'fido', 'color')} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('species'); * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * ``` * @example * This example creates a Provider context into which a Queries object is * provided, named by Id. A component within it then uses the useResultCell * hook. * * ```jsx * import {Provider, useResultCell} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * {useResultCell('dogColors', 'fido', 'color', 'petQueries')} * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('dogColors', 'pets', ({select, where}) => { * select('species'); * select('color'); * where('species', 'dog'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * ``` * @category Queries hooks * @since v2.0.0 */ useResultCell: ( queryId: Id, rowId: Id, cellId: Id, queriesOrQueriesId?: QueriesOrQueriesId, ) => ResultCell | undefined; /** * The useResultTableListener hook registers a listener function with a Queries * object that will be called whenever data in a ResultTable changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultTableListener( * queryId: IdOrNull, * listener: ResultTableListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultTable hook). * * You can either listen to a single ResultTable (by specifying a query Id as * the method's first parameter) or changes to any ResultTable (by providing a * `null` wildcard). * * Unlike the addResultTableListener method, which returns a listener Id and * requires you to remove it manually, the useResultTableListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the * matching ResultTable changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultTableListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultTableListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultTableListener('petColors', () => * console.log('Result table changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().table); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Result table changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().table); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultTableListener: ( queryId: IdOrNull, listener: ResultTableListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultTableCellIdsListener hook registers a listener function with a * Queries object that will be called whenever the Cell Ids that appear anywhere * in a ResultTable change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultTableCellIdsListener( * queryId: IdOrNull, * listener: ResultTableCellIdsListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultTableCellIds hook). * * You can either listen to a single ResultTable (by specifying a query Id as * the method's first parameter) or changes to any ResultTable (by providing a * `null` wildcard). * * Unlike the addResultTableCellIdsListener method, which returns a listener Id * and requires you to remove it manually, the useResultTableCellIdsListener * hook manages this lifecycle for you: when the listener changes (per its * `listenerDeps` dependencies) or the component unmounts, the listener on the * underlying Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Cell Ids that * appear anywhere in the ResultTable change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultTableCellIdsListener hook to create a listener * that is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultTableCellIdsListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultTableCellIdsListener('petColorsAndLegs', () => * console.log('Result Cell Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColorsAndLegs', * 'pets', * ({select}) => { * select('color'); * select('legs'); * }, * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().tableCellIds); * // -> 1 * * store.setCell('pets', 'cujo', 'legs', 4); // !act * // -> 'Result Cell Ids changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().tableCellIds); * // -> 0 * ``` * @category Queries hooks * @since v4.1.0 */ useResultTableCellIdsListener: ( queryId: IdOrNull, listener: ResultTableCellIdsListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultRowCountListener hook registers a listener function with a * Queries object that will be called whenever the count of ResultRow objects in * a ResultTable changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRowCountListener( * queryId: IdOrNull, * listener: ResultRowCountListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultRowCount hook). * * You can either listen to a single ResultTable (by specifying a query Id as * the method's first parameter) or changes to any ResultTable (by providing a * `null` wildcard). * * Unlike the addResultRowCountListener method, which returns a listener Id and * requires you to remove it manually, the useResultRowCountListener hook * manages this lifecycle for you: when the listener changes (per its * `listenerDeps` dependencies) or the component unmounts, the listener on the * underlying Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Row Ids in the * matching ResultTable change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultRowCountListener hook to create a listener * that is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultRowCountListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultRowCountListener('petColors', () => * console.log('Result Row count changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().rowCount); * // -> 1 * * store.setRow('pets', 'rex', {species: 'dog', color: 'tan'}); // !act * // -> 'Result Row count changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().rowCount); * // -> 0 * ``` * @category Queries hooks * @since v4.1.0 */ useResultRowCountListener: ( queryId: IdOrNull, listener: ResultRowCountListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultRowIdsListener hook registers a listener function with a Queries * object that will be called whenever the Row Ids in a ResultTable change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRowIdsListener( * queryId: IdOrNull, * listener: ResultRowIdsListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultRowIds hook). * * You can either listen to a single ResultTable (by specifying a query Id as * the method's first parameter) or changes to any ResultTable (by providing a * `null` wildcard). * * Unlike the addResultRowIdsListener method, which returns a listener Id and * requires you to remove it manually, the useResultRowIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Row Ids in the * matching ResultTable change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultRowIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultRowIdsListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultRowIdsListener('petColors', () => * console.log('Result Row Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().rowIds); * // -> 1 * * store.setRow('pets', 'rex', {species: 'dog', color: 'tan'}); // !act * // -> 'Result Row Ids changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().rowIds); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultRowIdsListener: ( queryId: IdOrNull, listener: ResultRowIdsListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultSortedRowIdsListener hook registers a listener function with a * Queries object that will be called whenever the sorted (and optionally, * paginated) Row Ids in a ResultTable change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultSortedRowIdsListener( * queryId: Id, * cellId: Id | undefined, * descending: boolean, * offset: number, * limit: number | undefined, * listener: ResultSortedRowIdsListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultSortedRowIds hook). * * Unlike the addResultSortedRowIdsListener method, which returns a listener Id * and requires you to remove it manually, the useResultSortedRowIdsListener * hook manages this lifecycle for you: when the listener changes (per its * `listenerDeps` dependencies) or the component unmounts, the listener on the * underlying Queries object will be deleted. * @param queryId The Id of the query to listen to. * @param cellId The Id of the Cell whose values are used for the sorting, or * `undefined` to by sort the Row Id itself. * @param descending Whether the sorting should be in descending order. * @param offset The number of Row Ids to skip for pagination purposes, if any. * @param limit The maximum number of Row Ids to return, or `undefined` for all. * @param listener The function that will be called whenever the Row Ids in the * matching ResultTable change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultSortedRowIdsListener hook to create a listener * that is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultSortedRowIdsListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultSortedRowIdsListener( * 'petColors', * 'color', * false, * 0, * undefined, * () => console.log('Sorted result Row Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().sortedRowIds); * // -> 1 * * store.setRow('pets', 'cujo', {color: 'tan'}); // !act * // -> 'Sorted result Row Ids changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().sortedRowIds); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultSortedRowIdsListener: ( queryId: Id, cellId: Id | undefined, descending: boolean, offset: number, limit: number | undefined, listener: ResultSortedRowIdsListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultRowListener hook registers a listener function with a Queries * object that will be called whenever data in a result Row changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultRowListener( * queryId: IdOrNull, * rowId: IdOrNull, * listener: ResultRowListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultRow hook). * * You can either listen to a single result Row (by specifying a query Id and * Row Id as the method's first two parameters) or changes to any result Row (by * providing `null` wildcards). * * Both, either, or neither of the `queryId` and `rowId` parameters can be * wildcarded with `null`. You can listen to a specific result Row in a specific * query, any result Row in a specific query, a specific result Row in any * query, or any result Row in any query. * * Unlike the addResultRowListener method, which returns a listener Id and * requires you to remove it manually, the useResultRowListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param rowId The Id of the result Row to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever data in the * matching result Row changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultRowListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultRowListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultRowListener('petColors', 'fido', () => * console.log('Result row changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().row); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Result row changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().row); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultRowListener: ( queryId: IdOrNull, rowId: IdOrNull, listener: ResultRowListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultCellIdsListener hook registers a listener function with a * Queries object that will be called whenever the Cell Ids in a result Row * change. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultCellIdsListener( * queryId: IdOrNull, * rowId: IdOrNull, * listener: ResultCellIdsListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultCellIds hook). * * Both, either, or neither of the `queryId` and `rowId` parameters can be * wildcarded with `null`. You can listen to a specific result Row in a specific * query, any result Row in a specific query, a specific result Row in any * query, or any result Row in any query. * * Unlike the addResultCellIdsListener method, which returns a listener Id and * requires you to remove it manually, the useResultCellIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param rowId The Id of the result Row to listen to, or `null` as a wildcard. * @param listener The function that will be called whenever the Row Ids in the * matching ResultTable change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultCellIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultCellIdsListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultCellIdsListener('petColors', 'fido', () => * console.log('Result cell Ids changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => { * select('color'); * select('legs'); * }, * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().cellIds); * // -> 1 * * store.setCell('pets', 'fido', 'legs', 4); // !act * // -> 'Result cell Ids changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().cellIds); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultCellIdsListener: ( queryId: IdOrNull, rowId: IdOrNull, listener: ResultCellIdsListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useResultCellListener hook registers a listener function with a Queries * object that will be called whenever data in a Cell changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useResultCellListener( * queryId: IdOrNull, * rowId: IdOrNull, * cellId: IdOrNull, * listener: ResultCellListener, * listenerDeps?: React.DependencyList, * queriesOrQueriesId?: QueriesOrQueriesId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useResultCell hook). * * You can either listen to a single Cell (by specifying the Table Id, Row Id, * and Cell Id as the method's first three parameters) or changes to any Cell * (by providing `null` wildcards). * * All, some, or none of the `queryId`, `rowId`, and `cellId` parameters can be * wildcarded with `null`. You can listen to a specific Cell in a specific * result Row in a specific query, any Cell in any result Row in any query, for * example - or every other combination of wildcards. * * Unlike the addResultCellListener method, which returns a listener Id and * requires you to remove it manually, the useResultCellListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Queries object will be deleted. * @param queryId The Id of the query to listen to, or `null` as a wildcard. * @param rowId The Id of the result Row to listen to, or `null` as a wildcard. * @param cellId The Id of the result Cell to listen to, or `null` as a * wildcard. * @param listener The function that will be called whenever data in the * matching result Cell changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param queriesOrQueriesId The Queries object to register the listener with: * omit for the default context Queries object, provide an Id for a named * context Queries object, or provide an explicit reference. * @example * This example uses the useResultCellListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Queries object. * * ```jsx * import {Provider, useResultCellListener} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => { * useResultCellListener('petColors', 'fido', 'color', () => * console.log('Result cell changed'), * ); * return App; * }; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(queries.getListenerStats().cell); * // -> 1 * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * // -> 'Result cell changed' * * root.unmount(); // !act * console.log(queries.getListenerStats().cell); * // -> 0 * ``` * @category Queries hooks * @since v2.0.0 */ useResultCellListener: ( queryId: IdOrNull, rowId: IdOrNull, cellId: IdOrNull, listener: ResultCellListener, listenerDeps?: React.DependencyList, queriesOrQueriesId?: QueriesOrQueriesId, ) => void; /** * The useCreateCheckpoints hook is used to create a Checkpoints object within a * React application with convenient memoization. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateCheckpoints( * store: Store | undefined, * create: (store: Store) => Checkpoints, * createDeps?: React.DependencyList, * ): Checkpoints | undefined; * ``` * * It is possible to create a Checkpoints object outside of the React app with * the regular createCheckpoints 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 Checkpoints object being created every time the app renders or * re-renders, since v5.0 this hook performs the creation in an effect. As a * result it will return `undefined` on the brief first render (or if the * Store is not yet defined), which you should defend against. * * If your `create` function contains other dependencies, the changing of which * should also cause the Checkpoints object 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. * * This hook ensures the Checkpoints object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Checkpoints * object. * @param create A function for performing the creation steps of the Checkpoints * object for the Store, plus any additional steps such as adding definitions 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 Checkpoints object. * @example * This example creates a Checkpoints object at the top level of a React * application. Even though the App component is rendered twice, the * Checkpoints object creation only occurs once by default. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {useCreateCheckpoints, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateStore(createStore); * const checkpoints = useCreateCheckpoints(store, (store) => { * console.log('Checkpoints created'); * return createCheckpoints(store).setSize(10); * }); * return {JSON.stringify(checkpoints?.getCheckpointIds())}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Checkpoints created' * * root.render(); // !act * // No second Checkpoints creation * * console.log(app.innerHTML); * // -> '[[],"0",[]]' * ``` * @example * This example creates a Checkpoints object at the top level of a React * application. The App component is rendered twice, each with a different * top-level prop. The useCreateCheckpoints hook takes the size prop as a * dependency, and so the Checkpoints object is created again on the second * render. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {useCreateCheckpoints, useCreateStore} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({size}) => { * const store = useCreateStore(createStore); * const checkpoints = useCreateCheckpoints( * store, * (store) => { * console.log(`Checkpoints created, size ${size}`); * return createCheckpoints(store).setSize(size); * }, * [size], * ); * return {JSON.stringify(checkpoints?.getCheckpointIds())}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Checkpoints created, size 20' * * console.log(app.innerHTML); * // -> '[[],"0",[]]' * * root.render(); // !act * // -> 'Checkpoints created, size 50' * * console.log(app.innerHTML); * // -> '[[],"0",[]]' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCreateCheckpoints: ( store: Store | undefined, create: (store: Store) => Checkpoints, createDeps?: React.DependencyList, ) => Checkpoints | undefined; /** * The useCheckpointsIds hook is used to retrieve the Ids of all the named * Checkpoints objects present in the current Provider component context. * @returns A list of the Ids in the context. * @example * This example adds two named Checkpoints objects to a Provider context and an * inner component accesses their Ids. * * ```jsx * import { * Provider, * useCheckpointsIds, * useCreateCheckpoints, * useCreateStore, * } from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store1 = useCreateStore(createStore); * const checkpoints1 = useCreateCheckpoints(store1, createCheckpoints); * const store2 = useCreateStore(createStore); * const checkpoints2 = useCreateCheckpoints(store2, createCheckpoints); * return ( * * * * ); * }; * const Pane = () => {JSON.stringify(useCheckpointsIds())}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '["checkpoints1","checkpoints2"]' * ``` * @category Checkpoints hooks * @since v4.1.0 */ useCheckpointsIds: () => Ids; /** * The useCheckpoints hook is used to get a reference to a Checkpoints object * from within a Provider component context. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpoints(id?: Id): Checkpoints | undefined; * ``` * * A Provider component is used to wrap part of an application in a context. It * can contain a default Checkpoints object (or a set of Checkpoints objects * named by Id) that can be easily accessed without having to be passed down as * props through every component. * * The useCheckpoints hook lets you either get a reference to the default * Checkpoints object (when called without a parameter), or one of the * Checkpoints objects that are named by Id (when called with an Id parameter). * @param id An optional Id for accessing a Checkpoints object that was named * with an Id in the Provider. * @returns A reference to the Checkpoints object (or `undefined` if not within * a Provider context, or if the requested Checkpoints object does not exist). * @example * This example creates a Provider context into which a default Checkpoint * object is provided. A component within it then uses the useCheckpoints hook * to get a reference to the Checkpoints object again, without the need to have * it passed as a prop. * * ```jsx * import {Provider, useCheckpoints} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( * {useCheckpoints().getListenerStats().checkpointIds} * ); * * const checkpoints = createCheckpoints(createStore()); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @example * This example creates a Provider context into which a Checkpoints object is * provided, named by Id. A component within it then uses the useCheckpoints * hook with that Id to get a reference to the Checkpoints object again, without * the need to have it passed as a prop. * * ```jsx * import {Provider, useCheckpoints} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( * * {useCheckpoints('petStore').getListenerStats().checkpointIds} * * ); * * const checkpoints = createCheckpoints(createStore()); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '0' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCheckpoints: (id?: Id) => Checkpoints | undefined; /** * The useCheckpointsOrCheckpointsById hook is used to get a reference to a * Checkpoints object from within a Provider component context, _or_ have it * passed directly to this hook. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpointsOrCheckpointsById( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): Checkpoints | undefined; * ``` * * This is mostly of use when you are developing a component that needs a * Checkpoints 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 * Checkpoints-based components). * * This is unlikely to be used often. For most situations, you will want to use * the useCheckpoints hook. * @param checkpointsOrCheckpointsId Either an Id for accessing a Checkpoints * object that was named with an Id in the Provider, or the Checkpoints object * itself. * @returns A reference to the Checkpoints object (or `undefined` if not within * a Provider context, or if the requested Checkpoints object does not exist). * @example * This example creates a Provider context into which a default Checkpoints * object is provided. A component within it then uses the * useCheckpointsOrCheckpointsById hook to get a reference to the Checkpoints * object again, without the need to have it passed as a prop. Note however, * that unlike the useCheckpoints hook example, this component would also work * if you were to pass the Checkpoints object directly into it, making it more * portable. * * ```jsx * import { * Provider, * useCheckpointsOrCheckpointsById, * } from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = ({checkpoints}) => ( * * {JSON.stringify( * useCheckpointsOrCheckpointsById(checkpoints).getCheckpointIds(), * )} * * ); * * const checkpoints = createCheckpoints(createStore()); * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '[[],"0",[]]' * ``` * @category Checkpoints hooks * @since v4.1.0 */ useCheckpointsOrCheckpointsById: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => Checkpoints | undefined; /** * The useCheckpointIds hook returns an array of the checkpoint Ids being * managed by this Checkpoints object, and registers a listener so that any * changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpointIds( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): CheckpointIds; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Checkpoints object or a set of Checkpoints objects * named by Id. The useCheckpointIds hook lets you indicate which Checkpoints * object to get data for: omit the optional parameter for the default context * Checkpoints object, provide an Id for a named context Checkpoints object, or * provide a Checkpoints object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * checkpoint Ids will cause a re-render. When the component containing this * hook is unmounted, the listener will be automatically removed. * @param checkpointsOrCheckpointsId The Checkpoints object to be accessed: omit * for the default context Checkpoints object, provide an Id for a named context * Checkpoints object, or provide an explicit reference. * @returns A CheckpointIds array, containing the checkpoint Ids managed by this * Checkpoints object. * @example * This example creates a Checkpoints object outside the application, which is * used in the useCheckpointIds hook by reference. A change to the checkpoint * Ids re-renders the component. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useCheckpointIds} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', {fido: {species: 'dog'}}); * const checkpoints = createCheckpoints(store); * const App = () => ( * {JSON.stringify(useCheckpointIds(checkpoints))} * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '[[],"0",[]]' * * store.setCell('pets', 'fido', 'sold', true); // !act * console.log(app.innerHTML); * // -> '[["0"],null,[]]' * * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> '[["0"],"1",[]]' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. A component within it then uses the useCheckpointIds * hook. * * ```jsx * import {Provider, useCheckpointIds} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => {JSON.stringify(useCheckpointIds())}; * * const checkpoints = createCheckpoints( * createStore().setTable('pets', {fido: {species: 'dog'}}), * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '[[],"0",[]]' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. A component within it then uses the useCheckpointIds * hook. * * ```jsx * import {Provider, useCheckpointIds} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( * {JSON.stringify(useCheckpointIds('petCheckpoints'))} * ); * * const checkpoints = createCheckpoints( * createStore().setTable('pets', {fido: {species: 'dog'}}), * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '[[],"0",[]]' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCheckpointIds: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => CheckpointIds; /** * The useCheckpoint hook returns the label for a checkpoint, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpoint( * checkpointId: Id, * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): string | undefined; * ``` * * A Provider component is used to wrap part of an application in a context, and * it can contain a default Checkpoints object or a set of Checkpoints objects * named by Id. The useCheckpoint hook lets you indicate which Checkpoints * object to get data for: omit the optional final parameter for the default * context Checkpoints object, provide an Id for a named context Checkpoints * object, or provide a Checkpoints object explicitly by reference. * * When first rendered, this hook will create a listener so that changes to the * label will cause a re-render. When the component containing this hook is * unmounted, the listener will be automatically removed. * @param checkpointId The Id of the checkpoint. * @param checkpointsOrCheckpointsId The Checkpoints object to be accessed: omit * for the default context Checkpoints object, provide an Id for a named context * Checkpoints object, or provide an explicit reference. * @returns A string label for the requested checkpoint, an empty string if it * was never set, or `undefined` if the checkpoint does not exist. * @example * This example creates a Checkpoints object outside the application, which is * used in the useCheckpoint hook by reference. A change to the checkpoint label * re-renders the component. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useCheckpoint} from 'tinybase/ui-react'; * * const store = createStore().setTable('pets', {fido: {species: 'dog'}}); * const checkpoints = createCheckpoints(store); * const App = () => {useCheckpoint('1', checkpoints)}; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '' * * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> 'sale' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. A component within it then uses the useCheckpoint * hook. * * ```jsx * import {Provider, useCheckpoint} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => {useCheckpoint('0')}; * * const checkpoints = createCheckpoints( * createStore().setTable('pets', {fido: {species: 'dog'}}), * ).setCheckpoint('0', 'initial'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'initial' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. A component within it then uses the useCheckpoint * hook. * * ```jsx * import {Provider, useCheckpoint} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => {useCheckpoint('0', 'petCheckpoints')}; * * const checkpoints = createCheckpoints( * createStore().setTable('pets', {fido: {species: 'dog'}}), * ).setCheckpoint('0', 'initial'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> 'initial' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCheckpoint: ( checkpointId: Id, checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => string | undefined; /** * The useSetCheckpointCallback hook returns a parameterized callback that can * be used to record a checkpoint of a Store into a Checkpoints object that can * be reverted to in the future. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useSetCheckpointCallback( * getCheckpoint?: (parameter: Parameter) => string, * getCheckpointDeps?: React.DependencyList, * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * then?: (checkpointId: Id, checkpoints: Checkpoints, label?: string) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * set the checkpoint. In this case, the parameter will likely be the event, so * that you can use data from it as the checkpoint label. * * The optional first parameter is a function which will produce the label that * will then be used to name the checkpoint. * * If that function has any other dependencies, the changing of which should * also cause the callback 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. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the checkpoint has been * set. * * The Checkpoints object for which the callback will set the checkpoint * (indicated by the hook's `checkpointsOrCheckpointsId` parameter) is always * automatically used as a hook dependency for the callback. * @param getCheckpoint An optional function which returns a string that will be * used to describe the actions leading up to this checkpoint, based on the * parameter the callback will receive (and which is most likely a DOM event). * @param getCheckpointDeps An optional array of dependencies for the * `getCheckpoint` function, which, if any change, result in the regeneration of * the callback. This parameter defaults to an empty array. * @param checkpointsOrCheckpointsId The Checkpoints object to be updated: omit * for the default context Checkpoints object, provide an Id for a named context * Checkpoints object, or provide an explicit reference. * @param then A function which is called after the checkpoint is set, with the * new checkpoint Id, a reference to the Checkpoints object and the label * provided, if any. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. This * parameter defaults to an empty array. * @returns A parameterized callback for subsequent use. * @example * This example uses the useSetCheckpointCallback hook to create an event * handler which sets a checkpoint when the `span` element is clicked. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useSetCheckpointCallback} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => { * const handleClick = useSetCheckpointCallback( * (e) => `with #${e.target.id} button`, * [], * checkpoints, * (checkpointId, checkpoints, label) => * console.log(`Checkpoint ${checkpointId} set, ${label}`), * ); * return ( * * Set * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const _span = app.querySelector('span'); * * store.setCell('pets', 'nemo', 'color', 'orange'); * * // User clicks the element: * // -> _span MouseEvent('click', {bubbles: true}) * // -> 'Checkpoint 1 set, with #span button' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useSetCheckpointCallback: ( getCheckpoint?: (parameter: Parameter) => string, getCheckpointDeps?: React.DependencyList, checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, then?: ( checkpointId: Id, checkpoints: Checkpoints, label?: string, ) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useGoBackwardCallback hook returns a callback that moves the state of the * underlying Store back to the previous checkpoint, effectively performing an * 'undo' on the Store data. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useGoBackwardCallback( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): Callback; * ``` * * This hook is useful, for example, when creating an event handler that will go * backward to the previous checkpoint - such as when clicking an undo button. * * If there is no previous checkpoint to return to, this callback has no effect. * @param checkpointsOrCheckpointsId The Checkpoints object to use to go * backward: omit for the default context Checkpoints object, provide an Id for * a named context Checkpoints object, or provide an explicit reference. * @returns A callback for subsequent use. * @example * This example uses the useGoBackwardCallback hook to create an event handler * which goes backward in the checkpoint stack when the `span` element is * clicked. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useGoBackwardCallback} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => ( * * Backward * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const _span = app.querySelector('span'); * * store.setCell('pets', 'nemo', 'color', 'orange'); * checkpoints.addCheckpoint(); * console.log(checkpoints.getCheckpointIds()); * // -> [["0"], "1", []] * * // User clicks the element: * // -> _span MouseEvent('click', {bubbles: true}) * console.log(checkpoints.getCheckpointIds()); * // -> [[], "0", ["1"]] * ``` * @category Checkpoints hooks * @since v1.0.0 */ useGoBackwardCallback: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => Callback; /** * The useGoForwardCallback hook returns a callback that moves the state of the * underlying Store forwards to a future checkpoint, effectively performing an * 'redo' on the Store data. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useGoForwardCallback( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): Callback; * ``` * * This hook is useful, for example, when creating an event handler that will go * forward to the next checkpoint - such as when clicking an redo button. * * If there is no future checkpoint to return to, this callback has no effect. * @param checkpointsOrCheckpointsId The Checkpoints object to use to go * backward: omit for the default context Checkpoints object, provide an Id for * a named context Checkpoints object, or provide an explicit reference. * @returns A callback for subsequent use. * @example * This example uses the useGoForwardCallback hook to create an event handler * which goes backward in the checkpoint stack when the `span` element is * clicked. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useGoForwardCallback} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => ( * * Forward * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const _span = app.querySelector('span'); * * store.setCell('pets', 'nemo', 'color', 'orange'); * checkpoints.addCheckpoint(); * console.log(checkpoints.getCheckpointIds()); * // -> [["0"], "1", []] * * checkpoints.goBackward(); * console.log(checkpoints.getCheckpointIds()); * // -> [[], "0", ["1"]] * * // User clicks the element: * // -> _span MouseEvent('click', {bubbles: true}) * console.log(checkpoints.getCheckpointIds()); * // -> [["0"], "1", []] * ``` * @category Checkpoints hooks * @since v1.0.0 */ useGoForwardCallback: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => Callback; /** * The useGoToCallback hook returns a parameterized callback that can be used to * move the state of the underlying Store backwards or forwards to a specified * checkpoint. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useGoToCallback( * getCheckpointId: (parameter: Parameter) => Id, * getCheckpointIdDeps?: React.DependencyList, * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * then?: (checkpoints: Checkpoints, checkpointId: Id) => void, * thenDeps?: React.DependencyList, * ): ParameterizedCallback; * ``` * * This hook is useful, for example, when creating an event handler that will * move the checkpoint. In this case, the parameter will likely be the event, so * that you can use data from it as the checkpoint Id to move to. * * The optional first parameter is a function which will produce the label that * will then be used to name the checkpoint. * * If that function has any other dependencies, the changing of which should * also cause the callback 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. * * For convenience, you can optionally provide a `then` function (with its own * set of dependencies) which will be called just after the checkpoint has been * set. * * The Checkpoints object for which the callback will set the checkpoint * (indicated by the hook's `checkpointsOrCheckpointsId` parameter) is always * automatically used as a hook dependency for the callback. * @param getCheckpointId A function which returns an Id that will be used to * indicate which checkpoint to move to, based on the parameter the callback * will receive (and which is most likely a DOM event). * @param getCheckpointIdDeps An optional array of dependencies for the * `getCheckpointId` function, which, if any change, result in the regeneration * of the callback. This parameter defaults to an empty array. * @param checkpointsOrCheckpointsId The Checkpoints object to be updated: omit * for the default context Checkpoints object, provide an Id for a named context * Checkpoints object, or provide an explicit reference. * @param then A function which is called after the checkpoint is moved, with a * reference to the Checkpoints object and the checkpoint Id moved to. * @param thenDeps An optional array of dependencies for the `then` function, * which, if any change, result in the regeneration of the callback. * @returns A parameterized callback for subsequent use. This parameter defaults * to an empty array. * @example * This example uses the useGoToCallback hook to create an event handler which * moves to a checkpoint when the `span` element is clicked. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useGoToCallback} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => { * const handleClick = useGoToCallback(() => '0', [], checkpoints); * return ( * * Goto 0 * * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * const _span = app.querySelector('span'); * * store.setCell('pets', 'nemo', 'color', 'orange'); * checkpoints.addCheckpoint(); * console.log(checkpoints.getCheckpointIds()); * // -> [["0"], "1", []] * * // User clicks the element: * // -> _span MouseEvent('click', {bubbles: true}) * console.log(checkpoints.getCheckpointIds()); * // -> [[], "0", ["1"]] * ``` * @category Checkpoints hooks * @since v1.0.0 */ useGoToCallback: ( getCheckpointId: (parameter: Parameter) => Id, getCheckpointIdDeps?: React.DependencyList, checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, then?: (checkpoints: Checkpoints, checkpointId: Id) => void, thenDeps?: React.DependencyList, ) => ParameterizedCallback; /** * The useUndoInformation hook returns an UndoOrRedoInformation array that * indicates if and how you can move the state of the underlying Store backward * to the previous checkpoint. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useUndoInformation( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): UndoOrRedoInformation; * ``` * * This hook is useful if you are building an undo button: the information * contains whether an undo action is available (to enable the button), the * callback to perform the undo action, the current checkpoint Id that will be * undone, and its label, if available. * @param checkpointsOrCheckpointsId The Checkpoints object to use to go * backward: omit for the default context Checkpoints object, provide an Id for * a named context Checkpoints object, or provide an explicit reference. * @returns UndoOrRedoInformation about if and how you can move the state of the * underlying Store backward. * @example * This example uses the useUndoInformation hook to create an undo button. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useUndoInformation} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => { * const [canUndo, handleUndo, _id, label] = * useUndoInformation(checkpoints); * return canUndo ? ( * Undo {label} * ) : ( * Nothing to undo * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'Nothing to undo' * * store.setCell('pets', 'nemo', 'color', 'orange'); // !act * checkpoints.addCheckpoint('color'); // !act * console.log(app.innerHTML); * // -> 'Undo color' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useUndoInformation: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => UndoOrRedoInformation; /** * The useRedoInformation hook returns an UndoOrRedoInformation array that * indicates if and how you can move the state of the underlying Store forwards * to a future checkpoint. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useRedoInformation( * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): UndoOrRedoInformation; * ``` * * This hook is useful if you are building an redo button: the information * contains whether a redo action is available (to enable the button), the * callback to perform the redo action, the checkpoint Id that will be redone, * and its label, if available. * @param checkpointsOrCheckpointsId The Checkpoints object to use to go * backward: omit for the default context Checkpoints object, provide an Id for * a named context Checkpoints object, or provide an explicit reference. * @returns UndoOrRedoInformation about if and how you can move the state of the * underlying Store forward. * @example * This example uses the useUndoInformation hook to create a redo button. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {useRedoInformation} from 'tinybase/ui-react'; * * const store = createStore().setTables({pets: {nemo: {species: 'fish'}}}); * const checkpoints = createCheckpoints(store); * const App = () => { * const [canRedo, handleRedo, _id, label] = * useRedoInformation(checkpoints); * return canRedo ? ( * Redo {label} * ) : ( * Nothing to redo * ); * }; * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'Nothing to redo' * * store.setCell('pets', 'nemo', 'color', 'orange'); // !act * checkpoints.addCheckpoint('color'); // !act * checkpoints.goTo('0'); // !act * console.log(app.innerHTML); * // -> 'Redo color' * ``` * @category Checkpoints hooks * @since v1.0.0 */ useRedoInformation: ( checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => UndoOrRedoInformation; /** * The useCheckpointIdsListener hook registers a listener function with the * Checkpoints object that will be called whenever its set of checkpoints * changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpointIdsListener( * listener: CheckpointIdsListener, * listenerDeps?: React.DependencyList, * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useCheckpointIds hook). * * Unlike the addCheckpointIdsListener method, which returns a listener Id and * requires you to remove it manually, the useCheckpointIdsListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Checkpoints object will be deleted. * @param listener The function that will be called whenever the checkpoints * change. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param checkpointsOrCheckpointsId The Checkpoints object to register the * listener with: omit for the default context Checkpoints object, provide an Id * for a named context Checkpoints object, or provide an explicit reference. * @example * This example uses the useCheckpointIdsListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useCheckpointIdsListener} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => { * useCheckpointIdsListener(() => console.log('Checkpoint Ids changed')); * return App; * }; * * const store = createStore().setTables({pets: {fido: {sold: false}}}); * const checkpoints = createCheckpoints(store); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(checkpoints.getListenerStats().checkpointIds); * // -> 1 * * store.setCell('pets', 'fido', 'sold', true); // !act * // -> 'Checkpoint Ids changed' * checkpoints.addCheckpoint(); // !act * // -> 'Checkpoint Ids changed' * * root.unmount(); // !act * console.log(checkpoints.getListenerStats().checkpointIds); * // -> 0 * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCheckpointIdsListener: ( listener: CheckpointIdsListener, listenerDeps?: React.DependencyList, checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => void; /** * The useCheckpointListener hook registers a listener function with the * Checkpoints object that will be called whenever the label of a checkpoint * changes. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCheckpointListener( * checkpointId: IdOrNull, * listener: CheckpointListener, * listenerDeps?: React.DependencyList, * checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, * ): void; * ``` * * This hook is useful for situations where a component needs to register its * own specific listener to do more than simply tracking the value (which is * more easily done with the useCheckpoint hook). * * You can either listen to a single checkpoint label (by specifying the * checkpoint Id as the method's first parameter), or changes to any checkpoint * label (by providing a `null` wildcard). * * Unlike the addCheckpointListener method, which returns a listener Id and * requires you to remove it manually, the useCheckpointListener hook manages * this lifecycle for you: when the listener changes (per its `listenerDeps` * dependencies) or the component unmounts, the listener on the underlying * Checkpoints object will be deleted. * @param checkpointId The Id of the checkpoint to listen to, or `null` as a * wildcard. * @param listener The function that will be called whenever the checkpoint * label changes. * @param listenerDeps An optional array of dependencies for the `listener` * function, which, if any change, result in the re-registration of the * listener. This parameter defaults to an empty array. * @param checkpointsOrCheckpointsId The Checkpoints object to register the * listener with: omit for the default context Checkpoints object, provide an Id * for a named context Checkpoints object, or provide an explicit reference. * @example * This example uses the useCheckpointListener hook to create a listener that * is scoped to a single component. When the component is unmounted, the * listener is removed from the Store. * * ```jsx * import {Provider, useCheckpointListener} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => { * useCheckpointListener('0', () => * console.log('Checkpoint label changed'), * ); * return App; * }; * * const store = createStore().setTables({pets: {fido: {sold: false}}}); * const checkpoints = createCheckpoints(store); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(checkpoints.getListenerStats().checkpoint); * // -> 1 * * checkpoints.setCheckpoint('0', 'initial'); // !act * // -> 'Checkpoint label changed' * * root.unmount(); // !act * console.log(checkpoints.getListenerStats().checkpoint); * // -> 0 * ``` * @category Checkpoints hooks * @since v1.0.0 */ useCheckpointListener: ( checkpointId: IdOrNull, listener: CheckpointListener, listenerDeps?: React.DependencyList, checkpointsOrCheckpointsId?: CheckpointsOrCheckpointsId, ) => void; /** * The useCreatePersister hook is used to create a Persister within a React * application along with convenient memoization and callbacks. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreatePersister< * PersisterOrUndefined extends Persister | undefined, * >( * store: Store | undefined, * create: (store: Store) => PersisterOrUndefined, * createDeps?: React.DependencyList, * then?: (persister: Persister) => Promise, * thenDeps?: React.DependencyList, * destroy?: (persister: Persister) => void, * destroyDeps?: React.DependencyList, * ): PersisterOrUndefined; * ``` * * It is possible to create a Persister outside of the React app with the * regular createPersister 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 * Persister being created every time the app renders or re-renders, since v5.0 * the this hook performs the creation in an effect. * * If your `create` function (the second parameter to the hook) contains * dependencies, the changing of which should cause the Persister to be * recreated, you can provide them in an array in the third parameter, just as * you would for any React hook with dependencies. The Store passed in as the * first parameter of this hook is used as a dependency by default. * * A second callback, called `then`, can be provided as the fourth parameter. * This is called after the creation, and, importantly, can be asynchronous, so * that you can configure the Persister with the startAutoLoad method and * startAutoSave method, for example. If this callback contains dependencies, * the changing of which should cause the Persister to be reconfigured, you can * provide them in an array in the fifth parameter. The Persister itself is used * as a dependency by default. * * Since v4.3.0, the `create` function can return undefined, meaning that you * can enable or disable persistence conditionally within this hook. This is * useful for applications which might turn on or off their cloud persistence or * collaboration features. This hook can return `undefined` if the Store is not * yet defined, which you should defend against. * * Since v4.3.19, a `destroy` function can be provided which will be called * after an old Persister is destroyed due to a change in the `createDeps` * dependencies that causes a new one to be created. Use this to clean up any * underlying storage objects that you set up during the `then` function, for * example. If this callback itself contains additional dependencies, you can * provide them in an array in the seventh parameter. * * This hook ensures the Persister object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the Store for which to create a new Persister * object. * @param create A function for performing the creation steps of the Persister * object for the Store. * @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. * @param then An optional callback for performing asynchronous post-creation * steps on the Persister, such as starting automatic loading and saving. * @param thenDeps An optional array of dependencies for the `then` callback, * which, if any change, result in its rerun. This parameter defaults to an * empty array. * @param destroy An optional callback whenever the Persister is destroyed due * to a change in the `createDeps` dependencies. * @param destroyDeps An optional array of dependencies for the `destroy` * callback, which, if any change, result in `destroy` and `then` being rerun. * This parameter defaults to an empty array. * @returns A reference to the Persister. * @example * This example creates a Persister at the top level of a React application. * Even though the App component is rendered twice, the Persister creation only * occurs once by default. * * ```jsx * import { * useCreatePersister, * useCreateStore, * useTables, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createSessionPersister} from 'tinybase/persisters/persister-browser'; * import {createStore} from 'tinybase'; * * const App = () => { * const store = useCreateStore(createStore); * useCreatePersister( * store, * (store) => { * console.log('Persister created'); * return createSessionPersister(store, 'pets'); * }, * [], * async (persister) => { * await persister.startAutoLoad(); * await persister.startAutoSave(); * }, * ); * return {JSON.stringify(useTables(store))}; * }; * * sessionStorage.setItem( * 'pets', * '[{"pets":{"fido":{"species":"dog"}}}, {}]', * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Persister created' * * // ... // !act * root.render(); // !act * // No second Persister creation * * console.log(app.innerHTML); * // -> '{\"pets\":{\"fido\":{\"species\":\"dog\"}}}' * * root.unmount(); // !act * ``` * @example * This example creates a Persister at the top level of a React application. The * App component is rendered twice, each with a different top-level prop. The * useCreatePersister hook takes the `sessionKey` prop as a dependency, and so * the Persister object is created again on the second render. The first is * destroyed and the `destroy` parameter is called for it. * * ```jsx * import { * useCreatePersister, * useCreateStore, * useTables, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createSessionPersister} from 'tinybase/persisters/persister-browser'; * import {createStore} from 'tinybase'; * * const App = ({sessionKey}) => { * const store = useCreateStore(createStore); * useCreatePersister( * store, * (store) => { * console.log(`Persister created for session key ${sessionKey}`); * return createSessionPersister(store, sessionKey); * }, * [sessionKey], * async (persister) => { * await persister.startAutoLoad(); * }, * [], * (persister) => * console.log( * `Persister destroyed for session key ${persister.getStorageName()}`, * ), * ); * return {JSON.stringify(useTables(store))}; * }; * * sessionStorage.setItem( * 'fidoStore', * '[{"pets":{"fido":{"species":"dog"}}}, {}]', * ); * sessionStorage.setItem( * 'cujoStore', * '[{"pets":{"cujo":{"species":"dog"}}}, {}]', * ); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Persister created for session key fidoStore' * * // ... // !act * console.log(app.innerHTML); * // -> '{\"pets\":{\"fido\":{\"species\":\"dog\"}}}' * * root.render(); // !act * // -> 'Persister created for session key cujoStore' * // -> 'Persister destroyed for session key fidoStore' * * // ... // !act * console.log(app.innerHTML); * // -> '{\"pets\":{\"cujo\":{\"species\":\"dog\"}}}' * * root.unmount(); // !act * // -> 'Persister destroyed for session key cujoStore' * ``` * @category Persister hooks * @since v1.0.0 */ useCreatePersister: < PersisterOrUndefined extends Persister | undefined, >( store: Store | undefined, create: (store: Store) => Persister | undefined, createDeps?: React.DependencyList, destroy?: (persister: Persister) => void, destroyDeps?: React.DependencyList, ) => PersisterOrUndefined; /** * The useCreateSynchronizer hook is used to create a Synchronizer within a * React application along with convenient memoization and callbacks. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * useCreateSynchronizer< * SynchronizerOrUndefined extends Synchronizer | undefined, * >( * store: MergeableStore | undefined, * create: (store: MergeableStore) => Promise, * createDeps?: React.DependencyList, * destroy?: (synchronizer: Synchronizer) => void, * destroyDeps?: React.DependencyList, * ): SynchronizerOrUndefined; * ``` * * It is possible to create a Synchronizer outside of the React app with the * regular createSynchronizer 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 Synchronizer being created every time the app renders or re-renders, * the useCreateSynchronizer hook performs the creation in an effect. * * If your asynchronous `create` function (the second parameter to the hook) * contains dependencies, the changing of which should cause the Synchronizer to * be recreated, you can provide them in an array in the third parameter, just * as you would for any React hook with dependencies. The MergeableStore passed * in as the first parameter of this hook is used as a dependency by default. * * The `create` function can return undefined, meaning that you can enable or * disable synchronization conditionally within this hook. This is useful for * applications which might turn on or off their cloud synchronization or * collaboration features. * * This hook ensures the Synchronizer object is destroyed whenever a new one is * created or the component is unmounted. * @param store A reference to the MergeableStore for which to create a new * Synchronizer object. * @param create An asynchronous function for performing the creation steps of * the Synchronizer object for the Store. * @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. * @param destroy An optional callback whenever the Synchronizer is destroyed * due to a change in the `createDeps` dependencies. * @param destroyDeps An optional array of dependencies for the `destroy` * callback, which, if any change, result in `destroy` and `then` being rerun. * This parameter defaults to an empty array. * @returns A reference to the Synchronizer. * @example * This example creates a Synchronizer at the top level of a React application. * Even though the App component is rendered twice, the Synchronizer creation * only occurs once by default. * * ```jsx * import { * useCreateMergeableStore, * useCreateSynchronizer, * useTables, * } from 'tinybase/ui-react'; * import React from 'react'; * import {createLocalSynchronizer} from 'tinybase/synchronizers/synchronizer-local'; * import {createMergeableStore} from 'tinybase'; * import {createRoot} from 'react-dom/client'; * * const App = () => { * const store = useCreateMergeableStore(() => createMergeableStore('s1')); * useCreateSynchronizer(store, async (store) => { * console.log('Synchronizer created'); * return await createLocalSynchronizer(store, 'pets'); * }); * return {JSON.stringify(useTables(store))}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // -> 'Synchronizer created' * * // ... // !act * root.render(); // !act * // No second Synchronizer creation * * root.unmount(); // !act * ``` * @example * This example creates a Synchronizer at the top level of a React application. * The App component is rendered twice, each with a different top-level prop. * The useCreateSynchronizer hook takes the `url` prop as a dependency, and so * the Synchronizer object is created again on the second render. The first is * destroyed and the `destroy` parameter is called for it. A `then` parameter * is provided to start both Synchronizers' synchronization. * * ```jsx * import { * useCreateMergeableStore, * useCreateSynchronizer, * useTables, * } from 'tinybase/ui-react'; * import React from 'react'; * import {WebSocketServer} from 'ws'; * import {createMergeableStore} from 'tinybase'; * import {createRoot} from 'react-dom/client'; * import {createWsServer} from 'tinybase/synchronizers/synchronizer-ws-server'; * import {createWsSynchronizer} from 'tinybase/synchronizers/synchronizer-ws-client'; * * const server1 = createWsServer(new WebSocketServer({port: 8044})); * const server2 = createWsServer(new WebSocketServer({port: 8045})); * * const App = ({url}) => { * const store = useCreateMergeableStore(() => createMergeableStore('s1')); * useCreateSynchronizer( * store, * async (store) => { * const webSocket = new WebSocket(url); * console.log(`Synchronizer created for ${webSocket.url}`); * return await createWsSynchronizer(store, webSocket); * }, * [url], * (synchronizer) => { * const webSocket = synchronizer.getWebSocket(); * console.log(`Synchronizer destroyed for ${webSocket.url}`); * }, * ); * return {JSON.stringify(useTables(store))}; * }; * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * // ... // !act * // -> 'Synchronizer created for ws://localhost:8044/' * * root.render(); // !act * // ... // !act * // -> 'Synchronizer created for ws://localhost:8045/' * // -> 'Synchronizer destroyed for ws://localhost:8044/' * * root.unmount(); // !act * // -> 'Synchronizer destroyed for ws://localhost:8045/' * * server1.destroy(); * server2.destroy(); * ``` * @category Synchronizer hooks * @since v5.0.0 */ useCreateSynchronizer: < SynchronizerOrUndefined extends Synchronizer | undefined, >( store: MergeableStore | undefined, create: ( store: MergeableStore, ) => Promise, createDeps?: React.DependencyList, destroy?: (synchronizer: Synchronizer) => void, destroyDeps?: React.DependencyList, ) => SynchronizerOrUndefined; /** * The ExtraProps type represents a set of arbitrary additional props. * @category Props * @since v1.0.0 */ ExtraProps: ExtraProps; /** * TablesProps props are used for components that refer to all the Tables in a * Store, such as the TablesView component. * @category Props * @since v1.0.0 */ TablesProps: TablesProps; /** * TableProps props are used for components that refer to a single Table in a * Store, such as the TableView component. * @category Props * @since v1.0.0 */ TableProps: TableProps; /** * SortedTableProps props are used for components that refer to a single sorted * Table in a Store, such as the SortedTableView component. * @category Props * @since v2.0.0 */ SortedTableProps: SortedTableProps; /** * RowProps props are used for components that refer to a single Row in a Table, * such as the RowView component. * @category Props * @since v1.0.0 */ RowProps: RowProps; /** * CellProps props are used for components that refer to a single Cell in a Row, * such as the CellView component. * @category Props * @since v1.0.0 */ CellProps: CellProps; /** * ValuesProps props are used for components that refer to all the Values in a * Store, such as the ValuesView component. * @category Props * @since v3.0.0 */ ValuesProps: ValuesProps; /** * ValueProps props are used for components that refer to a single Value in a * Row, such as the ValueView component. * @category Props * @since v3.0.0 */ ValueProps: ValueProps; /** * MetricProps props are used for components that refer to a single Metric in a * Metrics object, such as the MetricView component. * @category Props * @since v1.0.0 */ MetricProps: MetricProps; /** * IndexProps props are used for components that refer to a single Index in an * Indexes object, such as the IndexView component. * @category Props * @since v1.0.0 */ IndexProps: IndexProps; /** * SliceProps props are used for components that refer to a single Slice in an * Index object, such as the SliceView component. * @category Props * @since v1.0.0 */ SliceProps: SliceProps; /** * RemoteRowProps props are used for components that refer to a single * Relationship in a Relationships object, and where you want to render a remote * Row based on a local Row, such as in the RemoteRowView component. * @category Props * @since v1.0.0 */ RemoteRowProps: RemoteRowProps; /** * LocalRowsProps props are used for components that refer to a single * Relationship in a Relationships object, and where you want to render local * Rows based on a remote Row, such as the LocalRowsView component. * @category Props * @since v1.0.0 */ LocalRowsProps: LocalRowsProps; /** * LinkedRowsProps props are used for components that refer to a single * Relationship in a Relationships object, and where you want to render a linked * list of Rows starting from a first Row, such as the LinkedRowsView component. * @category Props * @since v1.0.0 */ LinkedRowsProps: LinkedRowsProps; /** * ResultTableProps props are used for components that refer to a single query * ResultTable, such as the ResultTableView component. * @category Props * @since v2.0.0 */ ResultTableProps: ResultTableProps; /** * ResultSortedTableProps props are used for components that refer to a single * sorted query ResultTable, such as the ResultSortedTableView component. * @category Props * @since v2.0.0 */ ResultSortedTableProps: ResultSortedTableProps; /** * ResultRowProps props are used for components that refer to a single Row in a * query ResultTable, such as the ResultRowView component. * @category Props * @since v2.0.0 */ ResultRowProps: ResultRowProps; /** * ResultRowProps props are used for components that refer to a single Cell in a * Row of a ResultTable, such as the ResultCellView component. * @category Props * @since v2.0.0 */ ResultCellProps: ResultCellProps; /** * CheckpointProps props are used for components that refer to a single * checkpoint in a Checkpoints object, such as the CheckpointView component. * @category Props * @since v1.0.0 */ CheckpointProps: CheckpointProps; /** * BackwardCheckpointsProps props are used for components that refer to a list * of previous checkpoints in a Checkpoints object, such as the * BackwardCheckpointsView component. * @category Props * @since v1.0.0 */ BackwardCheckpointsProps: BackwardCheckpointsProps; /** * CurrentCheckpointsProps props are used for components that refer to the * current checkpoints in a Checkpoints object, such as the * BackwardCheckpointsView component. * @category Props * @since v1.0.0 */ CurrentCheckpointProps: CurrentCheckpointProps; /** * ForwardCheckpointsProps props are used for components that refer to a list of * future checkpoints in a Checkpoints object, such as the * ForwardCheckpointsView component. * @category Props * @since v1.0.0 */ ForwardCheckpointsProps: ForwardCheckpointsProps; /** * ProviderProps props are used with the Provider component, so that Store * Metrics, Indexes, Relationships, Queries, and Checkpoints objects can be * passed into the context of an application and used throughout. * * One of each type of object can be provided as a default within the context. * Additionally, multiple of each type of object can be provided in an Id-keyed * map to the `___ById` props. * @category Props * @since v1.0.0 */ ProviderProps: ProviderProps; /** * ComponentReturnType is a simple alias for what a React component can return: * either a ReactElement, or `null` for an empty component. * @category Component * @since v1.0.0 */ ComponentReturnType: ReactElement | null; /** * The Provider component is used to wrap part of an application in a context * that provides default objects to be used by hooks and components within. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * Provider( * props: ProviderProps & {children: React.ReactNode}, * ): ComponentReturnType; * ``` * * Store, Metrics, Indexes, Relationships, Queries, and Checkpoints objects can * be passed into the context of an application and used throughout. One of each * type of object can be provided as a default within the context. Additionally, * multiple of each type of object can be provided in an Id-keyed map to the * `___ById` props. * * Provider contexts can be nested and the objects passed in will be merged. For * example, if an outer context contains a default Metrics object and an inner * context contains only a default Store, both the Metrics objects and the Store * will be visible within the inner context. If the outer context contains a * Store named by Id and the inner context contains a Store named by a different * Id, both will be visible within the inner context. * @param props The props for this component. * @returns A rendering of the child components. * @example * This example creates a Provider context into which a Store and a Metrics * object are provided, one by default, and one named by Id. Components within * it then render content from both, without the need to have them passed as * props. * * ```jsx * import {CellView, Provider, useMetric} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({store, metrics}) => ( * * * * ); * const Pane = () => ( * * , * , * {useMetric('highestPrice', 'petStore')} * * ); * * const store = createStore(); * store.setTable('species', {dog: {price: 5}, cat: {price: 4}}); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '5,4,5' * ``` * @example * This example creates nested Provider contexts into which Store and Metrics * objects are provided, showing how visibility is merged. * * ```jsx * import { * CellView, * Provider, * useCreateStore, * useMetric, * } from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({petStore, metrics}) => ( * * * * ); * const OuterPane = () => { * const planetStore = useCreateStore(() => * createStore().setTables({planets: {mars: {moons: 2}}}), * ); * return ( * * * * ); * }; * const InnerPane = () => ( * * , * {useMetric('highestPrice')}, * * * ); * * const petStore = createStore(); * petStore.setTable('species', {dog: {price: 5}, cat: {price: 4}}); * const metrics = createMetrics(petStore); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '5,5,2' * ``` * @category Context components * @since v1.0.0 */ Provider: ( props: ProviderProps & {children: React.ReactNode}, ) => ComponentReturnType; /** * The CellView component renders the value of a single Cell in a given Row, in * a given Table, and registers a listener so that any changes to that result * will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * CellView(props: CellProps): ComponentReturnType; * ``` * * The component's props identify which Cell to render based on Table Id, Row * Id, Cell Id, and Store (which is either the default context Store, a named * context Store, or an explicit reference). * * A Cell contains a string, number, or boolean, so the value is rendered * directly without further decoration. You can create your own CellView-like * component to customize the way that a Cell is rendered: see the RowView * component for more details. * * This component uses the useCell hook under the covers, which means that any * changes to the specified Cell will cause a re-render. * @param props The props for this component. * @returns A rendering of the Cell, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * CellView component by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import {CellView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const App = () => ( * * * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> 'walnut' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The CellView component within it then renders the Cell (with its Id * for readability). * * ```jsx * import {CellView, Provider} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'color:{brown}' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The CellView component within it then attempts to render a * non-existent Cell. * * ```jsx * import {CellView, Provider} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const store = createStore().setCell('pets', 'fido', 'color', 'brown'); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '' * ``` * @category Store components * @since v1.0.0 */ CellView: (props: CellProps) => ComponentReturnType; /** * The RowView component renders the contents of a single Row in a given Table, * and registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * RowView(props: RowProps): ComponentReturnType; * ``` * * The component's props identify which Row to render based on Table Id, Row Id, * and Store (which is either the default context Store, a named context Store, * or an explicit reference). * * This component renders a Row by iterating over its Cell values. By default * these are in turn rendered with the CellView component, but you can override * this behavior by providing a `cellComponent` prop, a custom component of your * own that will render a Cell based on CellProps. You can also pass additional * props to your custom component with the `getCellComponentProps` callback * prop. * * You can create your own RowView-like component to customize the way that a * Row is rendered: see the TableView component for more details. * * Since v4.1.0, you can use the `customCellIds` prop if you want to render a * prescribed set of the Row's Cells in a given order. Otherwise, this component * uses the useCellIds hook under the covers, which means that any changes to * the structure of the Row will cause a re-render. * @param props The props for this component. * @returns A rendering of the Row, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * RowView component by reference. A change to the data in the Store re-renders * the component. * * ```jsx * import React from 'react'; * import {RowView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setRow('pets', 'fido', {species: 'dog'}); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog
' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '
dog/walnut
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The RowView component within it then renders the Row for a custom * set of Cell Ids (and rendered with Ids for readability). * * ```jsx * import {Provider, RowView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const customCellIds = ['color', 'species']; * const Pane = () => ( *
* *
* ); * * const store = createStore().setRow('pets', 'fido', { * species: 'dog', * color: 'walnut', * legs: 4, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
fido:{color:{walnut}species:{dog}}
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The RowView component within it then renders the Row with a custom * Cell component and a custom props callback. * * ```jsx * import {CellView, Provider, RowView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const getBoldProp = (cellId) => ({bold: cellId == 'species'}); * const Pane = () => ( *
* *
* ); * const FormattedCellView = ({tableId, rowId, cellId, bold}) => ( * * {bold ? {cellId} : cellId} * {': '} * * * ); * * const store = createStore().setRow('pets', 'fido', { * species: 'dog', * color: 'walnut', * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
species: dogcolor: walnut
' * ``` * @category Store components * @since v1.0.0 */ RowView: (props: RowProps) => ComponentReturnType; /** * The SortedTableView component renders the contents of a single sorted Table * in a Store, and registers a listener so that any changes to that result will * cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * SortedTableView(props: SortedTableProps): ComponentReturnType; * ``` * * The component's props identify which Table to render based on Table Id, and * Store (which is either the default context Store, a named context Store, or * by explicit reference). It also takes a Cell Id to sort by and a boolean to * indicate that the sorting should be in descending order. The `offset` and * `limit` props are used to paginate results, but default to `0` and * `undefined` to return all available Row Ids if not specified. * * This component renders a Table by iterating over its Row objects, in the * order dictated by the sort parameters. By default these are in turn rendered * with the RowView component, but you can override this behavior by providing a * `rowComponent` prop, a custom component of your own that will render a Row * based on RowProps. You can also pass additional props to your custom * component with the `getRowComponentProps` callback prop. * * This component uses the useSortedRowIds hook under the covers, which means * that any changes to the structure or sorting of the Table will cause a * re-render. * * Since v4.1.0, you can use the `customCellIds` prop if you want to render a * prescribed set of the Table's Cells in a given order for each Row. * @param props The props for this component. * @returns A rendering of the Table, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * SortedTableView component by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {SortedTableView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
cat/dog
' * * store.setRow('pets', 'cujo', {species: 'wolf'}); // !act * console.log(app.innerHTML); * // -> '
cat/dog/wolf
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The SortedTableView component within it then renders the Table for * a custom set of Cell Ids (and rendered with Ids for readability). * * ```jsx * import {Provider, SortedTableView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const customCellIds = ['species']; * const Pane = () => ( *
* *
* ); * * const store = createStore().setTables({ * pets: { * fido: {color: 'black', species: 'dog'}, * felix: {color: 'brown', species: 'cat'}, * }, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
pets:{felix:{species:{cat}}fido:{species:{dog}}}
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The SortedTableView component within it then renders the Table with * a custom Row component and a custom props callback. * * ```jsx * import {Provider, RowView, SortedTableView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const store = createStore().setTables({ * pets: { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
felix: catfido: dog
' * ``` * @category Store components * @since v2.0.0 */ SortedTableView: (props: SortedTableProps) => ComponentReturnType; /** * The TableView component renders the contents of a single Table in a Store, * and registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * TableView(props: TableProps): ComponentReturnType; * ``` * * The component's props identify which Table to render based on Table Id, and * Store (which is either the default context Store, a named context Store, or * by explicit reference). * * This component renders a Table by iterating over its Row objects. By default * these are in turn rendered with the RowView component, but you can override * this behavior by providing a `rowComponent` prop, a custom component of your * own that will render a Row based on RowProps. You can also pass additional * props to your custom component with the `getRowComponentProps` callback prop. * * You can create your own TableView-like component to customize the way that a * Table is rendered: see the TablesView component for more details. * * This component uses the useRowIds hook under the covers, which means that any * changes to the structure of the Table will cause a re-render. * * Since v4.1.0, you can use the `customCellIds` prop if you want to render a * prescribed set of the Table's Cells in a given order for each Row. * @param props The props for this component. * @returns A rendering of the Table, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * TableView component by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {TableView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTable('pets', {fido: {species: 'dog'}}); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog
' * * store.setRow('pets', 'felix', {species: 'cat'}); // !act * console.log(app.innerHTML); * // -> '
dog/cat
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The TableView component within it then renders the Table for a * custom set of Cell Ids (and rendered with Ids for readability). * * ```jsx * import {Provider, TableView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const customCellIds = ['species']; * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', { * fido: {color: 'black', species: 'dog'}, * felix: {color: 'brown', species: 'cat'}, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
pets:{fido:{species:{dog}}felix:{species:{cat}}}
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The TableView component within it then renders the Table with a * custom Row component and a custom props callback. * * ```jsx * import {Provider, RowView, TableView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
fido: dogfelix: cat
' * ``` * @category Store components * @since v1.0.0 */ TableView: (props: TableProps) => ComponentReturnType; /** * The TablesView component renders the tabular contents of a Store, and * registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * TablesView(props: TablesProps): ComponentReturnType; * ``` * * The component's props can identify which Store to render - either the default * context Store, a named context Store, or an explicit reference. * * This component renders a Store by iterating over its Table objects. By * default these are in turn rendered with the TableView component, but you can * override this behavior by providing a `tableComponent` prop, a custom * component of your own that will render a Table based on TableProps. You can * also pass additional props to your custom component with the * `getTableComponentProps` callback prop. * * This component uses the useTableIds hook under the covers, which means that * any changes to the structure of the Store will cause a re-render. * @param props The props for this component. * @returns A rendering of the Store, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * TablesView component by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {TablesView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setTables({pets: {fido: {species: 'dog'}}}); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog
' * * store.setTable('species', {dog: {price: 5}}); // !act * console.log(app.innerHTML); * // -> '
dog/5
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The TablesView component within it then renders the Store (with Ids * for readability). * * ```jsx * import {Provider, TablesView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTables({ * pets: {fido: {species: 'dog'}}, * species: {dog: {price: 5}}, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
pets:{fido:{species:{dog}}}species:{dog:{price:{5}}}
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The TablesView component within it then renders the Store with a * custom Table component and a custom props callback. * * ```jsx * import {Provider, TableView, TablesView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const getBoldProp = (tableId) => ({bold: tableId == 'pets'}); * const Pane = () => ( *
* *
* ); * const FormattedTableView = ({tableId, bold}) => ( * * {bold ? {tableId} : tableId} * {': '} * * * ); * * const store = createStore().setTables({ * pets: {fido: {species: 'dog'}}, * species: {dog: {price: 5}}, * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
pets: dogspecies: 5
' * ``` * @category Store components * @since v1.0.0 */ TablesView: (props: TablesProps) => ComponentReturnType; /** * The ValueView component renders the value of a single Value, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ValueView(props: ValueProps): ComponentReturnType; * ``` * * The component's props identify which Value to render based on Value Id and * Store (which is either the default context Store, a named context Store, or * an explicit reference). * * A Value contains a string, number, or boolean, so the value is rendered * directly without further decoration. You can create your own ValueView-like * component to customize the way that a Value is rendered: see the ValuesView * component for more details. * * This component uses the useValue hook under the covers, which means that any * changes to the specified Value will cause a re-render. * @param props The props for this component. * @returns A rendering of the Value, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * ValueView component by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {ValueView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValue('open', true); * const App = () => ( * * * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'true' * * store.setValue('open', false); // !act * console.log(app.innerHTML); * // -> 'false' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The ValueView component within it then renders the Value (with its * Id for readability). * * ```jsx * import {Provider, ValueView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'open:{true}' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The ValueView component within it then attempts to render a * non-existent Value. * * ```jsx * import {Provider, ValueView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const store = createStore().setValue('open', true); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '' * ``` * @category Store components * @since v3.0.0 */ ValueView: (props: ValueProps) => ComponentReturnType; /** * The ValuesView component renders the keyed value contents of a Store, and * registers a listener so that any changes to that result will cause a * re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ValuesView(props: ValuesProps): ComponentReturnType; * ``` * * The component's props can identify which Store to render - either the default * context Store, a named context Store, or an explicit reference. * * This component renders a Store by iterating over its Value objects. By * default these are in turn rendered with the ValueView component, but you can * override this behavior by providing a `valueComponent` prop, a custom * component of your own that will render a Value based on ValueProps. You can * also pass additional props to your custom component with the * `getValueComponentProps` callback prop. * * This component uses the useValueIds hook under the covers, which means that * any changes to the Values in the Store will cause a re-render. * * This component uses the useValueIds hook under the covers, which means that * any changes to the Store's Values will cause a re-render. * @param props The props for this component. * @returns A rendering of the Values, or nothing, if not present. * @example * This example creates a Store outside the application, which is used in the * ValuesView component by reference. A change to the data in the Store * re-renders the component. * * ```jsx * import React from 'react'; * import {ValuesView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const store = createStore().setValue('open', true); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
true
' * * store.setValue('employees', 3); // !act * console.log(app.innerHTML); * // -> '
true/3
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The ValuesView component within it then renders the Values (with * Ids for readability). * * ```jsx * import {Provider, ValuesView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setValues({open: true, employees: 3}); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
open:{true}employees:{3}
' * ``` * @example * This example creates a Provider context into which a default Store is * provided. The ValuesView component within it then renders the Values with a * custom Value component and a custom props callback. * * ```jsx * import {Provider, ValueView, ValuesView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * import {createStore} from 'tinybase'; * * const App = ({store}) => ( * * * * ); * const getBoldProp = (valueId) => ({bold: valueId == 'open'}); * const Pane = () => ( *
* *
* ); * const FormattedValueView = ({valueId, bold}) => ( * * {bold ? {valueId} : valueId} * {': '} * * * ); * * const store = createStore().setValues({open: true, employees: 3}); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
open: trueemployees: 3
' * ``` * @category Store components * @since v3.0.0 */ ValuesView: (props: ValuesProps) => ComponentReturnType; /** * The MetricView component renders the current value of a Metric, and registers * a listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * MetricView(props: MetricProps): ComponentReturnType; * ``` * * The component's props can identify which Metrics object to get data for: omit * the optional final parameter for the default context Metrics object, provide * an Id for a named context Metrics object, or by explicit reference. * * This component uses the useMetric hook under the covers, which means that any * changes to the Metric will cause a re-render. * @param props The props for this component. * @returns A rendering of the Metric, or nothing, if not present. * @example * This example creates a Metrics object outside the application, which is used * in the MetricView component hook by reference. A change to the Metric * re-renders the component. * * ```jsx * import {createMetrics, createStore} from 'tinybase'; * import {MetricView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
5
' * * store.setCell('species', 'horse', 'price', 20); // !act * console.log(app.innerHTML); * // -> '
20
' * ``` * @example * This example creates a Provider context into which a default Metrics object * is provided. The MetricView component within it then renders the Metric (with * its Id for readability). * * ```jsx * import {MetricView, Provider} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
highestPrice:{5}
' * ``` * @example * This example creates a Provider context into which a default Metrics object * is provided. The MetricView component within it then attempts to render a * non-existent Metric. * * ```jsx * import {MetricView, Provider} from 'tinybase/ui-react'; * import {createMetrics, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({metrics}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('species', { * dog: {price: 5}, * cat: {price: 4}, * worm: {price: 1}, * }); * const metrics = createMetrics(store); * metrics.setMetricDefinition('highestPrice', 'species', 'max', 'price'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
' * ``` * @category Metrics components * @since v1.0.0 */ MetricView: (props: MetricProps) => ComponentReturnType; /** * The SliceView component renders the contents of a Slice, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * SliceView(props: SliceProps): ComponentReturnType; * ``` * * The component's props identify which Slice to render based on Index Id, Slice * Id, and Indexes object (which is either the default context Indexes object, a * named context Indexes object, or an explicit reference). * * This component renders a Slice by iterating over its Row objects. By default * these are in turn rendered with the RowView component, but you can override * this behavior by providing a `rowComponent` prop, a custom component of your * own that will render a Row based on RowProps. You can also pass additional * props to your custom component with the `getRowComponentProps` callback prop. * * This component uses the useSliceRowIds hook under the covers, which means * that any changes to the structure of the Slice will cause a re-render. * @param props The props for this component. * @returns A rendering of the Slice, or nothing, if not present. * @example * This example creates an Indexes object outside the application, which is used * in the SliceView component by reference. A change to the Row Ids re-renders * the component. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {SliceView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog
' * * store.setRow('pets', 'cujo', {species: 'dog'}); // !act * console.log(app.innerHTML); * // -> '
dog/dog
' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. The SliceView component within it then renders the Slice (with * Ids for readability). * * ```jsx * import {Provider, SliceView} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog:{fido:{species:{dog}}cujo:{species:{dog}}}
' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. The SliceView component within it then renders the Slice with a * custom Row component and a custom props callback. * * ```jsx * import {Provider, RowView, SliceView} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({store, tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
fido: dog/browncujo: dog
' * ``` * @category Indexes components * @since v1.0.0 */ SliceView: (props: SliceProps) => ComponentReturnType; /** * The IndexView component renders the contents of a Index, and registers a * listener so that any changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * IndexView(props: IndexProps): ComponentReturnType; * ``` * * The component's props identify which Index to render based on Index Id, and * Indexes object (which is either the default context Indexes object, a named * context Indexes object, or an explicit reference). * * This component renders a Index by iterating over its Slice objects. By * default these are in turn rendered with the SliceView component, but you can * override this behavior by providing a `sliceComponent` prop, a custom * component of your own that will render a Slice based on SliceProps. You can * also pass additional props to your custom component with the * `getSliceComponentProps` callback prop. * * This component uses the useSliceIds hook under the covers, which means that * any changes to the structure of the Index will cause a re-render. * @param props The props for this component. * @returns A rendering of the Index, or nothing, if not present. * @example * This example creates an Indexes object outside the application, which is used * in the IndexView component by reference. A change to the Slice Ids re-renders * the component. * * ```jsx * import {createIndexes, createStore} from 'tinybase'; * import {IndexView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog/cat
' * * store.setRow('pets', 'lowly', {species: 'worm'}); // !act * console.log(app.innerHTML); * // -> '
dog/cat/worm
' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. The IndexView component within it then renders the Index (with * Ids for readability). * * ```jsx * import {IndexView, Provider} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
bySpecies:{dog:{fido:{species:{dog}}cujo:{species:{dog}}}}
' * ``` * @example * This example creates a Provider context into which a default Indexes object * is provided. The IndexView component within it then renders the Index with a * custom Slice component and a custom props callback. * * ```jsx * import {IndexView, Provider, SliceView} from 'tinybase/ui-react'; * import {createIndexes, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({indexes}) => ( * * * * ); * const getBoldProp = (sliceId) => ({bold: sliceId == 'dog'}); * const Pane = () => ( *
* *
* ); * const FormattedSliceView = ({indexId, sliceId, bold}) => ( * * {bold ? {sliceId} : sliceId} * {': '} * * * ); * * const store = createStore().setTable('pets', { * fido: {species: 'dog'}, * felix: {species: 'cat'}, * cujo: {species: 'dog'}, * }); * const indexes = createIndexes(store); * indexes.setIndexDefinition('bySpecies', 'pets', 'species'); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog: dog/dogcat: cat
' * ``` * @category Indexes components * @since v1.0.0 */ IndexView: (props: IndexProps) => ComponentReturnType; /** * The RemoteRowView component renders the remote Row Id for a given local Row * in a Relationship, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * RemoteRowView(props: RemoteRowProps): ComponentReturnType; * ``` * * The component's props identify which remote Row to render based on * Relationship Id, local Row Id, and Relationships object (which is either the * default context Relationships object, a named context Relationships object, * or an explicit reference). * * By default the remote Row is rendered with the RowView component, but you can * override this behavior by providing a `rowComponent` prop, a custom component * of your own that will render the Row based on RowProps. You can also pass * additional props to your custom component with the `getRowComponentProps` * callback prop. * * This component uses the useRemoteRowId hook under the covers, which means * that any changes to the remote Row Id in the Relationship will cause a * re-render. * @param props The props for this component. * @returns A rendering of the remote Row, or nothing, if not present. * @example * This example creates a Relationships object outside the application, which * is used in the RemoteRowView component by reference. A change to the Row Ids * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {RemoteRowView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
5
' * * store.setCell('pets', 'cujo', 'species', 'wolf'); // !act * console.log(app.innerHTML); * // -> '
10
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The RemoteRowView component within it then renders the * remote Row (with Ids for readability). * * ```jsx * import {Provider, RemoteRowView} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
cujo:{dog:{price:{5}}}
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The RemoteRowView component within it then renders the * remote Row with a custom Row component and a custom props callback. * * ```jsx * import {Provider, RemoteRowView, RowView} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'dog'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({store, tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
dog: 5
' * ``` * @category Relationships components * @since v1.0.0 */ RemoteRowView: (props: RemoteRowProps) => ComponentReturnType; /** * The LocalRowsView component renders the local Row objects for a given remote * Row in a Relationship, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * LocalRowsView(props: LocalRowsProps): ComponentReturnType; * ``` * * The component's props identify which local Rows to render based on * Relationship Id, remote Row Id, and Relationships object (which is either the * default context Relationships object, a named context Relationships object, * or an explicit reference). * * By default the local Rows are rendered with the RowView component, but you * can override this behavior by providing a `rowComponent` prop, a custom * component of your own that will render the Row based on RowProps. You can * also pass additional props to your custom component with the * `getRowComponentProps` callback prop. * * This component uses the useLocalRowIds hook under the covers, which means * that any changes to the local Row Ids in the Relationship will cause a * re-render. * @param props The props for this component. * @returns A rendering of the local Row objects, or nothing, if not present. * @example * This example creates a Relationships object outside the application, which * is used in the LocalRowsView component by reference. A change to the Row Ids * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import {LocalRowsView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSpecies', * 'pets', * 'species', * 'species', * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog/dog
' * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * console.log(app.innerHTML); * // -> '
dog/dog/dog
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The LocalRowsView component within it then renders the * local Row objects (with Ids for readability). * * ```jsx * import {LocalRowsView, Provider} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
dog:{fido:{species:{dog}}cujo:{species:{dog}}}
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The LocalRowsView component within it then renders the * local Row objects with a custom Row component and a custom props callback. * * ```jsx * import {LocalRowsView, Provider, RowView} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({store, tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const relationships = createRelationships( * createStore() * .setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}}) * .setTable('species', {wolf: {price: 10}, dog: {price: 5}}), * ).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
fido: dogcujo: dog
' * ``` * @category Relationships components * @since v1.0.0 */ LocalRowsView: (props: LocalRowsProps) => ComponentReturnType; /** * The LinkedRowsView component renders the local Row objects for a given remote * Row in a Relationship, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * LinkedRowsView(props: LinkedRowsProps): ComponentReturnType; * ``` * * The component's props identify which local Rows to render based on * Relationship Id, remote Row Id, and Relationships object (which is either the * default context Relationships object, a named context Relationships object, * or an explicit reference). * * By default the local Rows are rendered with the RowView component, but you * can override this behavior by providing a `rowComponent` prop, a custom * component of your own that will render the Row based on RowProps. You can * also pass additional props to your custom component with the * `getRowComponentProps` callback prop. * * This component uses the useLocalRowIds hook under the covers, which means * that any changes to the local Row Ids in the Relationship will cause a * re-render. * @param props The props for this component. * @returns A rendering of the local Row objects, or nothing, if not present. * @example * This example creates a Relationships object outside the application, which * is used in the LinkedRowsView component by reference. A change to the Row Ids * re-renders the component. * * ```jsx * import {createRelationships, createStore} from 'tinybase'; * import {LinkedRowsView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {next: 'felix'}, * felix: {next: 'cujo'}, * cujo: {species: 'dog'}, * }); * const relationships = createRelationships(store).setRelationshipDefinition( * 'petSequence', * 'pets', * 'pets', * 'next', * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
felix/cujo/dog
' * * store.setRow('pets', 'toto', {species: 'dog'}); // !act * store.setRow('pets', 'cujo', {next: 'toto'}); // !act * console.log(app.innerHTML); * // -> '
felix/cujo/toto/dog
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The LinkedRowsView component within it then renders the * local Row objects (with Ids for readability). * * ```jsx * import {LinkedRowsView, Provider} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const relationships = createRelationships( * createStore().setTable('pets', { * fido: {next: 'felix'}, * felix: {species: 'cat'}, * }), * ).setRelationshipDefinition('petSequence', 'pets', 'pets', 'next'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
fido:{fido:{next:{felix}}felix:{species:{cat}}}
' * ``` * @example * This example creates a Provider context into which a default Relationships * object is provided. The LinkedRowsView component within it then renders the * local Row objects with a custom Row component and a custom props callback. * * ```jsx * import {LinkedRowsView, Provider, RowView} from 'tinybase/ui-react'; * import {createRelationships, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({relationships}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({store, tableId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const relationships = createRelationships( * createStore().setTable('pets', { * fido: {next: 'felix'}, * felix: {species: 'cat'}, * }), * ).setRelationshipDefinition('petSequence', 'pets', 'pets', 'next'); * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
fido: felixfelix: cat
' * ``` * @category Relationships components * @since v1.0.0 */ LinkedRowsView: (props: LinkedRowsProps) => ComponentReturnType; /** * The ResultCellView component renders the value of a single Cell in a given * Row, in a given query's ResultTable, and registers a listener so that any * changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ResultCellView(props: ResultCellProps): ComponentReturnType; * ``` * * The component's props identify which Cell to render based on query Id, Row * Id, Cell Id, and Queries object (which is either the default context Queries * object, a named context Queries object, or an explicit reference). * * A Cell contains a string, number, or boolean, so the value is rendered * directly without further decoration. You can create your own * ResultCellView-like component to customize the way that a Cell is rendered: * see the ResultRowView component for more details. * * This component uses the useResultCell hook under the covers, which means that * any changes to the specified Cell will cause a re-render. * @param props The props for this component. * @returns A rendering of the result Cell, or nothing, if not present. * @example * This example creates a Queries object outside the application, which is used * in the ResultCellView component by reference. A change to the data in the * Store re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {ResultCellView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const App = () => ( * * * * ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'brown' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> 'walnut' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultCellView component within it then renders the Cell * (with its Id for readability). * * ```jsx * import {Provider, ResultCellView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> 'color:{brown}' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultCellView component within it then attempts to render a * non-existent Cell. * * ```jsx * import {Provider, ResultCellView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( * * * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '' * ``` * @category Queries components * @since v2.0.0 */ ResultCellView: (props: ResultCellProps) => ComponentReturnType; /** * The ResultRowView component renders the contents of a single Row in a given * query's ResultTable, and registers a listener so that any changes to that * result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ResultRowView(props: ResultRowProps): ComponentReturnType; * ``` * * The component's props identify which Row to render based on query Id, Row Id, * and Queries object (which is either the default context Queries object, a * named context Queries object, or an explicit reference). * * This component renders a Row by iterating over its Cell values. By default * these are in turn rendered with the ResultCellView component, but you can * override this behavior by providing a `resultCellComponent` prop, a custom * component of your own that will render a Cell based on ResultCellProps. You * can also pass additional props to your custom component with the * `getResultCellComponentProps` callback prop. * * You can create your own ResultRowView-like component to customize the way * that a result Row is rendered: see the ResultTableView component for more * details. * * This component uses the useResultCellIds hook under the covers, which means * that any changes to the structure of the result Row will cause a re-render. * @param props The props for this component. * @returns A rendering of the result Row, or nothing, if not present. * @example * This example creates a Queries object outside the application, which is used * in the ResultRowView component by reference. A change to the data in the * Store re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {ResultRowView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => { * select('species'); * select('color'); * }, * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
dog/brown
' * * store.setCell('pets', 'fido', 'color', 'walnut'); // !act * console.log(app.innerHTML); * // -> '
dog/walnut
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultRowView component within it then renders the Row (with * Ids for readability). * * ```jsx * import {Provider, ResultRowView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => { * select('species'); * select('color'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
fido:{species:{dog}color:{brown}}
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultRowView component within it then renders the Row with * a custom Cell component and a custom props callback. * * ```jsx * import {Provider, ResultCellView, ResultRowView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const getBoldProp = (cellId) => ({bold: cellId == 'species'}); * const Pane = () => ( *
* *
* ); * const FormattedResultCellView = ({queryId, rowId, cellId, bold}) => ( * * {bold ? {cellId} : cellId} * {': '} * * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * cujo: {species: 'dog', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => { * select('species'); * select('color'); * }); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
species: dogcolor: brown
' * ``` * @category Queries components * @since v2.0.0 */ ResultRowView: (props: ResultRowProps) => ComponentReturnType; /** * The ResultSortedTableView component renders the contents of a single query's * sorted ResultTable in a Queries object, and registers a listener so that any * changes to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ResultSortedTableView( * props: ResultSortedTableProps, * ): ComponentReturnType; * ``` * * The component's props identify which ResultTable to render based on query Id, * and Queries object (which is either the default context Queries object, a * named context Queries object, or by explicit reference). It also takes a Cell * Id to sort by and a boolean to indicate that the sorting should be in * descending order. The `offset` and `limit` props are used to paginate * results, but default to `0` and `undefined` to return all available Row Ids * if not specified. * * This component renders a ResultTable by iterating over its Row objects, in * the order dictated by the sort parameters. By default these are in turn * rendered with the ResultRowView component, but you can override this behavior * by providing a `resultRowComponent` prop, a custom component of your own that * will render a Row based on ResultRowProps. You can also pass additional props * to your custom component with the `getResultRowComponentProps` callback prop. * * This component uses the useResultSortedRowIds hook under the covers, which * means that any changes to the structure or sorting of the ResultTable will * cause a re-render. * @param props The props for this component. * @returns A rendering of the ResultTable, or nothing, if not present. * @example * This example creates a Queries object outside the application, which is used * in the ResultSortedTableView component by reference. A change to the data in * the Store re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {ResultSortedTableView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
black/brown
' * * store.setCell('pets', 'felix', 'color', 'white'); // !act * console.log(app.innerHTML); * // -> '
brown/white
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultSortedTableView component within it then renders the * Table (with Ids for readability). * * ```jsx * import {Provider, ResultSortedTableView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
petColors:{felix:{color:{black}}fido:{color:{brown}}}
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultSortedTableView component within it then renders the * Table with a custom Row component and a custom props callback. * * ```jsx * import { * Provider, * ResultRowView, * ResultSortedTableView, * } from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({queryId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
felix: blackfido: brown
' * ``` * @category Queries components * @since v2.0.0 */ ResultSortedTableView: ( props: ResultSortedTableProps, ) => ComponentReturnType; /** * The ResultTableView component renders the contents of a single query's * ResultTable in a Queries object, and registers a listener so that any changes * to that result will cause a re-render. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ResultTableView(props: ResultTableProps): ComponentReturnType; * ``` * * The component's props identify which ResultTable to render based on query Id, * and Queries object (which is either the default context Queries object, a * named context Queries object, or by explicit reference). * * This component renders a ResultTable by iterating over its Row objects. By * default these are in turn rendered with the ResultRowView component, but you * can override this behavior by providing a `resultRowComponent` prop, a custom * component of your own that will render a Row based on ResultRowProps. You can * also pass additional props to your custom component with the * `getResultRowComponentProps` callback prop. * * This component uses the useResultRowIds hook under the covers, which means * that any changes to the structure of the ResultTable will cause a re-render. * @param props The props for this component. * @returns A rendering of the ResultTable, or nothing, if not present. * @example * This example creates a Queries object outside the application, which is used * in the ResultTableView component by reference. A change to the data in the * Store re-renders the component. * * ```jsx * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {ResultTableView} from 'tinybase/ui-react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }); * const queries = createQueries(store).setQueryDefinition( * 'petColors', * 'pets', * ({select}) => select('color'), * ); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
brown/black
' * * store.setRow('pets', 'cujo', {species: 'dog', color: 'black'}); // !act * console.log(app.innerHTML); * // -> '
brown/black/black
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultTableView component within it then renders the Table * (with Ids for readability). * * ```jsx * import {Provider, ResultTableView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
petColors:{fido:{color:{brown}}felix:{color:{black}}}
' * ``` * @example * This example creates a Provider context into which a default Queries object * is provided. The ResultTableView component within it then renders the Table * with a custom Row component and a custom props callback. * * ```jsx * import {Provider, ResultRowView, ResultTableView} from 'tinybase/ui-react'; * import {createQueries, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({queries}) => ( * * * * ); * const getBoldProp = (rowId) => ({bold: rowId == 'fido'}); * const Pane = () => ( *
* *
* ); * const FormattedRowView = ({queryId, rowId, bold}) => ( * * {bold ? {rowId} : rowId} * {': '} * * * ); * * const queries = createQueries( * createStore().setTable('pets', { * fido: {species: 'dog', color: 'brown'}, * felix: {species: 'cat', color: 'black'}, * }), * ).setQueryDefinition('petColors', 'pets', ({select}) => select('color')); * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
fido: brownfelix: black
' * ``` * @category Queries components * @since v2.0.0 */ ResultTableView: (props: ResultTableProps) => ComponentReturnType; /** * The CheckpointView component simply renders the label of a checkpoint. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * CheckpointView(props: CheckpointProps): ComponentReturnType; * ``` * * The component's props identify which checkpoint to render based on Checkpoint * Id and Checkpoints object (which is either the default context Checkpoints * object, a named context Checkpoints object, or an explicit reference). * * The primary purpose of this component is to render multiple checkpoints in a * BackwardCheckpointsView component or ForwardCheckpointsView component. * * This component uses the useCheckpoint hook under the covers, which means that * any changes to the local Row Ids in the Relationship will cause a re-render. * @param props The props for this component. * @returns A rendering of the checkpoint: its label if present, or Id. * @example * This example creates a Checkpoints object outside the application, which is * used in the CheckpointView component by reference to render a checkpoint with * a label (with its Id for readability). * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {CheckpointView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', {fido: {species: 'dog'}}); * const checkpoints = createCheckpoints(store); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
1:{}
' * * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> '
1:{sale}
' * * checkpoints.setCheckpoint('1', 'sold'); // !act * console.log(app.innerHTML); * // -> '
1:{sold}
' * ``` * @category Checkpoints components * @since v1.0.0 */ CheckpointView: (props: CheckpointProps) => ComponentReturnType; /** * The BackwardCheckpointsView component renders a list of previous checkpoints * that the underlying Store can go back to. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * BackwardCheckpointsView( * props: BackwardCheckpointsProps, * ): ComponentReturnType; * ``` * * The component's props identify which previous checkpoints to render based on * the Checkpoints object (which is either the default context Checkpoints * object, a named context Checkpoints object, or an explicit reference). * * This component renders a list by iterating over each checkpoints. By default * these are in turn rendered with the CheckpointView component, but you can * override this behavior by providing a `checkpointComponent` prop, a custom * component of your own that will render a checkpoint based on CheckpointProps. * You can also pass additional props to your custom component with the * `getCheckpointComponentProps` callback prop. * * This component uses the useCheckpointIds hook under the covers, which means * that any changes to the checkpoint Ids in the Checkpoints object will cause a * re-render. * @param props The props for this component. * @returns A rendering of the previous checkpoints, if present. * @example * This example creates a Checkpoints object outside the application, which is * used in the BackwardCheckpointsView component by reference to render a list * of previous checkpoints. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {BackwardCheckpointsView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
' * * checkpoints.setCheckpoint('0', 'initial'); // !act * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * console.log(app.innerHTML); * // -> '
initial
' * * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> '
initial/identified
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The BackwardCheckpointsView component within it then * renders the list of previous checkpoints (with Ids for readability). * * ```jsx * import {BackwardCheckpointsView, Provider} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * checkpoints.setCheckpoint('0', 'initial'); // !act * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
0:{initial}1:{identified}
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The BackwardCheckpointsView component within it then * renders the list of previous checkpoints with a custom Row component and a * custom props callback. * * ```jsx * import { * BackwardCheckpointsView, * CheckpointView, * Provider, * } from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const getBoldProp = (checkpointId) => ({bold: checkpointId == '0'}); * const Pane = () => ( *
* *
* ); * const FormattedCheckpointView = ({checkpoints, checkpointId, bold}) => ( * * {bold ? {checkpointId} : checkpointId} * {': '} * * * ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * checkpoints.setCheckpoint('0', 'initial'); // !act * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
0: initial1: identified
' * ``` * @category Checkpoints components * @since v1.0.0 */ BackwardCheckpointsView: ( props: BackwardCheckpointsProps, ) => ComponentReturnType; /** * The CurrentCheckpointView component renders the current checkpoint that the * underlying Store is currently on. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * CurrentCheckpointView( * props: CurrentCheckpointProps, * ): ComponentReturnType; * ``` * * The component's props identify which current checkpoint to render based on * the Checkpoints object (which is either the default context Checkpoints * object, a named context Checkpoints object, or an explicit reference). * * By default the current checkpoint is rendered with the CheckpointView * component, but you can override this behavior by providing a * `checkpointComponent` prop, a custom component of your own that will render a * checkpoint based on CheckpointProps. You can also pass additional props to * your custom component with the `getCheckpointComponentProps` callback prop. * * This component uses the useCheckpointIds hook under the covers, which means * that any changes to the current checkpoint Id in the Checkpoints object will * cause a re-render. * @param props The props for this component. * @returns A rendering of the current checkpoint, if present. * @example * This example creates a Checkpoints object outside the application, which is * used in the CurrentCheckpointView component by reference to render the * current checkpoints. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {CurrentCheckpointView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
' * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * console.log(app.innerHTML); * // -> '
identified
' * * store.setCell('pets', 'fido', 'sold', true); // !act * console.log(app.innerHTML); * // -> '
' * * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> '
sale
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The CurrentCheckpointView component within it then * renders current checkpoint (with its Id for readability). * * ```jsx * import {CurrentCheckpointView, Provider} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
1:{identified}
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The CurrentCheckpointView component within it then * renders the list of future checkpoints with a custom Row component and a * custom props callback. * * ```jsx * import { * CheckpointView, * CurrentCheckpointView, * Provider, * } from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const getBoldProp = (checkpointId) => ({bold: checkpointId == '1'}); * const Pane = () => ( *
* *
* ); * const FormattedCheckpointView = ({checkpoints, checkpointId, bold}) => ( * * {bold ? {checkpointId} : checkpointId} * {': '} * * * ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
1: identified
' * * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * console.log(app.innerHTML); * // -> '
2: sale
' * ``` * @category Checkpoints components * @since v1.0.0 */ CurrentCheckpointView: ( props: CurrentCheckpointProps, ) => ComponentReturnType; /** * The ForwardCheckpointsView component renders a list of future checkpoints * that the underlying Store can go forwards to. * * This has schema-based typing. The following is a simplified representation: * * ```ts override * ForwardCheckpointsView( * props: ForwardCheckpointsProps, * ): ComponentReturnType; * ``` * * The component's props identify which future checkpoints to render based on * the Checkpoints object (which is either the default context Checkpoints * object, a named context Checkpoints object, or an explicit reference). * * This component renders a list by iterating over each checkpoints. By default * these are in turn rendered with the CheckpointView component, but you can * override this behavior by providing a `checkpointComponent` prop, a custom * component of your own that will render a checkpoint based on CheckpointProps. * You can also pass additional props to your custom component with the * `getCheckpointComponentProps` callback prop. * * This component uses the useCheckpointIds hook under the covers, which means * that any changes to the checkpoint Ids in the Checkpoints object will cause a * re-render. * @param props The props for this component. * @returns A rendering of the future checkpoints, if present. * @example * This example creates a Checkpoints object outside the application, which is * used in the ForwardCheckpointsView component by reference to render a list * of future checkpoints. * * ```jsx * import {createCheckpoints, createStore} from 'tinybase'; * import {ForwardCheckpointsView} from 'tinybase/ui-react'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * const App = () => ( *
* *
* ); * * const app = document.createElement('div'); * createRoot(app).render(); // !act * console.log(app.innerHTML); * // -> '
' * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * checkpoints.goBackward(); // !act * console.log(app.innerHTML); * // -> '
sale
' * * checkpoints.goBackward(); // !act * console.log(app.innerHTML); * // -> '
identified/sale
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The ForwardCheckpointsView component within it then * renders the list of future checkpoints (with Ids for readability). * * ```jsx * import {ForwardCheckpointsView, Provider} from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const Pane = () => ( *
* *
* ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * checkpoints.goTo('0'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
1:{identified}2:{sale}
' * ``` * @example * This example creates a Provider context into which a default Checkpoints * object is provided. The ForwardCheckpointsView component within it then * renders the list of future checkpoints with a custom Row component and a * custom props callback. * * ```jsx * import { * CheckpointView, * ForwardCheckpointsView, * Provider, * } from 'tinybase/ui-react'; * import {createCheckpoints, createStore} from 'tinybase'; * import React from 'react'; * import {createRoot} from 'react-dom/client'; * * const App = ({checkpoints}) => ( * * * * ); * const getBoldProp = (checkpointId) => ({bold: checkpointId == '1'}); * const Pane = () => ( *
* *
* ); * const FormattedCheckpointView = ({checkpoints, checkpointId, bold}) => ( * * {bold ? {checkpointId} : checkpointId} * {': '} * * * ); * * const store = createStore().setTable('pets', {fido: {color: 'brown'}}); * const checkpoints = createCheckpoints(store); * * store.setCell('pets', 'fido', 'species', 'dog'); // !act * checkpoints.addCheckpoint('identified'); // !act * store.setCell('pets', 'fido', 'sold', true); // !act * checkpoints.addCheckpoint('sale'); // !act * checkpoints.goTo('0'); // !act * * const app = document.createElement('div'); * const root = createRoot(app); * root.render(); // !act * console.log(app.innerHTML); * // -> '
1: identified2: sale
' * ``` * @category Checkpoints components * @since v1.0.0 */ ForwardCheckpointsView: ( props: ForwardCheckpointsProps, ) => ComponentReturnType; };