tinybase 4.1.0-beta.0 → 4.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/cjs/tools.cjs +1 -1
  2. package/lib/cjs/tools.cjs.gz +0 -0
  3. package/lib/cjs/ui-react-dom.cjs +1 -0
  4. package/lib/cjs/ui-react-dom.cjs.gz +0 -0
  5. package/lib/cjs/ui-react.cjs +1 -1
  6. package/lib/cjs/ui-react.cjs.gz +0 -0
  7. package/lib/cjs-es6/tools.cjs +1 -1
  8. package/lib/cjs-es6/tools.cjs.gz +0 -0
  9. package/lib/cjs-es6/ui-react-dom.cjs +1 -0
  10. package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
  11. package/lib/cjs-es6/ui-react.cjs +1 -1
  12. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  13. package/lib/debug/tools.js +25 -4
  14. package/lib/debug/ui-react-dom.js +205 -0
  15. package/lib/debug/ui-react.js +21 -13
  16. package/lib/es6/tools.js +1 -1
  17. package/lib/es6/tools.js.gz +0 -0
  18. package/lib/es6/ui-react-dom.js +1 -0
  19. package/lib/es6/ui-react-dom.js.gz +0 -0
  20. package/lib/es6/ui-react.js +1 -1
  21. package/lib/es6/ui-react.js.gz +0 -0
  22. package/lib/tools.js +1 -1
  23. package/lib/tools.js.gz +0 -0
  24. package/lib/types/ui-react-dom.d.ts +544 -0
  25. package/lib/types/ui-react.d.ts +59 -18
  26. package/lib/types/with-schemas/internal/ui-react.d.ts +15 -0
  27. package/lib/types/with-schemas/ui-react-dom.d.ts +590 -0
  28. package/lib/types/with-schemas/ui-react.d.ts +44 -18
  29. package/lib/ui-react-dom.js +1 -0
  30. package/lib/ui-react-dom.js.gz +0 -0
  31. package/lib/ui-react.js +1 -1
  32. package/lib/ui-react.js.gz +0 -0
  33. package/lib/umd/tools.js +1 -1
  34. package/lib/umd/tools.js.gz +0 -0
  35. package/lib/umd/ui-react-dom.js +1 -0
  36. package/lib/umd/ui-react-dom.js.gz +0 -0
  37. package/lib/umd/ui-react.js +1 -1
  38. package/lib/umd/ui-react.js.gz +0 -0
  39. package/lib/umd-es6/tools.js +1 -1
  40. package/lib/umd-es6/tools.js.gz +0 -0
  41. package/lib/umd-es6/ui-react-dom.js +1 -0
  42. package/lib/umd-es6/ui-react-dom.js.gz +0 -0
  43. package/lib/umd-es6/ui-react.js +1 -1
  44. package/lib/umd-es6/ui-react.js.gz +0 -0
  45. package/package.json +32 -28
  46. package/readme.md +41 -24
@@ -0,0 +1,544 @@
1
+ /**
2
+ * The ui-react-dom module of the TinyBase project provides components to make
3
+ * it easy to create web-based reactive apps with Store objects.
4
+ *
5
+ * The components in this module use the react-dom module and so are not
6
+ * appropriate for environments like React Native (although those in the
7
+ * lower-level ui-react module are).
8
+ * @see UI Components demos
9
+ * @packageDocumentation
10
+ * @module ui-react-dom
11
+ * @since v4.1.0
12
+ */
13
+
14
+ import {
15
+ CellProps,
16
+ ComponentReturnType,
17
+ ExtraProps,
18
+ StoreOrStoreId,
19
+ ValueProps,
20
+ } from './ui-react';
21
+ import {Id, Ids} from './common';
22
+ import {ComponentType} from 'react';
23
+
24
+ // TableInHtmlTableProps
25
+ export type TableInHtmlTableProps = {
26
+ /**
27
+ * The Id of the Table in the Store to be rendered.
28
+ */
29
+ readonly tableId: Id;
30
+ /**
31
+ * The Store to be accessed: omit for the default context Store, provide an Id
32
+ * for a named context Store, or provide an explicit reference.
33
+ */
34
+ readonly store?: StoreOrStoreId;
35
+ /**
36
+ * A custom component for rendering each Cell in the Table (to override the
37
+ * default CellView component).
38
+ */
39
+ readonly cellComponent?: ComponentType<CellProps>;
40
+ /**
41
+ * A function for generating extra props for each custom Cell component based
42
+ * on its Id.
43
+ */
44
+ readonly getCellComponentProps?: (rowId: Id, cellId: Id) => ExtraProps;
45
+ /**
46
+ * A string className to use on the root of the resulting element.
47
+ */
48
+ readonly className?: string;
49
+ /**
50
+ * Whether a header row should be rendered at the top of the table, defaulting
51
+ * to `true`.
52
+ */
53
+ readonly headerRow?: boolean;
54
+ /**
55
+ * Whether an Id column should be rendered on the left of the table,
56
+ * defaulting to `true`.
57
+ */
58
+ readonly idColumn?: boolean;
59
+ /**
60
+ * An optional list of Cell Ids to use for rendering a prescribed set of the
61
+ * Row's Cells in a given order.
62
+ */
63
+ readonly customCellIds?: Ids;
64
+ };
65
+
66
+ // SortedTableInHtmlTableProps
67
+ export type SortedTableInHtmlTableProps = {
68
+ /**
69
+ * The Id of the Table in the Store to be rendered.
70
+ */
71
+ readonly tableId: Id;
72
+ /**
73
+ * The Id of the Cell whose values are used for the sorting. If omitted, the
74
+ * view will sort the Row Id itself.
75
+ */
76
+ readonly cellId?: Id;
77
+ /**
78
+ * Whether the sorting should be in descending order.
79
+ */
80
+ readonly descending?: boolean;
81
+ /**
82
+ * The number of Row Ids to skip for pagination purposes.
83
+ */
84
+ readonly offset?: number;
85
+ /**
86
+ * The maximum number of Row Ids to return.
87
+ */
88
+ readonly limit?: number;
89
+ /**
90
+ * The Store to be accessed: omit for the default context Store, provide an Id
91
+ * for a named context Store, or provide an explicit reference.
92
+ */
93
+ readonly store?: StoreOrStoreId;
94
+ /**
95
+ * A custom component for rendering each Cell in the Table (to override the
96
+ * default CellView component).
97
+ */
98
+ readonly cellComponent?: ComponentType<CellProps>;
99
+ /**
100
+ * A function for generating extra props for each custom Cell component based
101
+ * on its Id.
102
+ */
103
+ readonly getCellComponentProps?: (rowId: Id, cellId: Id) => ExtraProps;
104
+ /**
105
+ * A string className to use on the root of the resulting element.
106
+ */
107
+ readonly className?: string;
108
+ /**
109
+ * Whether a header row should be rendered at the top of the table, defaulting
110
+ * to `true`.
111
+ */
112
+ readonly headerRow?: boolean;
113
+ /**
114
+ * Whether an Id column should be rendered on the left of the table,
115
+ * defaulting to `true`.
116
+ */
117
+ readonly idColumn?: boolean;
118
+ /**
119
+ * An optional list of Cell Ids to use for rendering a prescribed set of the
120
+ * Row's Cells in a given order.
121
+ */
122
+ readonly customCellIds?: Ids;
123
+ /**
124
+ * Whether the table should be interactive such that clicking a header changes
125
+ * the sorting and/or direction.
126
+ */
127
+ readonly sortOnClick?: boolean;
128
+ };
129
+
130
+ // ValuesInHtmlTableProps
131
+ export type ValuesInHtmlTableProps = {
132
+ /**
133
+ * The Store to be accessed: omit for the default context Store, provide an Id
134
+ * for a named context Store, or provide an explicit reference.
135
+ */
136
+ readonly store?: StoreOrStoreId;
137
+ /**
138
+ * A custom component for rendering each Value in the Store (to override the
139
+ * default ValueView component).
140
+ */
141
+ readonly valueComponent?: ComponentType<ValueProps>;
142
+ /**
143
+ * A function for generating extra props for each custom Value component based
144
+ * on its Id.
145
+ */
146
+ readonly getValueComponentProps?: (valueId: Id) => ExtraProps;
147
+ /**
148
+ * A string className to use on the root of the resulting element.
149
+ */
150
+ readonly className?: string;
151
+ /**
152
+ * Whether a header row should be rendered at the top of the table, defaulting
153
+ * to `true`.
154
+ */
155
+ readonly headerRow?: boolean;
156
+ /**
157
+ * Whether an Id column should be rendered on the left of the table,
158
+ * defaulting to `true`.
159
+ */
160
+ readonly idColumn?: boolean;
161
+ };
162
+
163
+ /**
164
+ * The TableInHtmlTable component renders the contents of a single Table in a
165
+ * Store as an HTML <table> element, and registers a listener so that any
166
+ * changes to that result will cause a re-render.
167
+ *
168
+ * The component's props identify which Table to render based on Table Id, and
169
+ * Store (which is either the default context Store, a named context Store, or
170
+ * by explicit reference).
171
+ *
172
+ * See the <TableInHtmlTable /> demo for this component in action.
173
+ *
174
+ * This component renders a Table by iterating over its Row objects. By default
175
+ * these are in turn rendered with the RowInHtmlTr component, but you can
176
+ * override this behavior by providing a `rowComponent` prop, a custom component
177
+ * of your own that will render a Row based on RowProps. You can also pass
178
+ * additional props to your custom component with the `getRowComponentProps`
179
+ * callback prop.
180
+ *
181
+ * This component uses the useRowIds hook under the covers, which means that any
182
+ * changes to the structure of the Table will cause a re-render.
183
+ *
184
+ * You can use the `headerRow` and `idColumn` props to control whether the Ids
185
+ * appear in a <th> element at the top of the table, and the start of each row.
186
+ * @param props The props for this component.
187
+ * @returns A rendering of the Table in a <table> element.
188
+ * @see <TableInHtmlTable /> demo
189
+ * @example
190
+ * This example creates a Provider context into which a default Store is
191
+ * provided. The TableInHtmlTable component within it then renders the Table in
192
+ * a <table> element with a CSS class.
193
+ *
194
+ * ```jsx
195
+ * const App = ({store}) => (
196
+ * <Provider store={store}>
197
+ * <Pane />
198
+ * </Provider>
199
+ * );
200
+ * const Pane = () => <TableInHtmlTable tableId="pets" className="table" />;
201
+ *
202
+ * const store = createStore().setTable('pets', {
203
+ * fido: {species: 'dog'},
204
+ * felix: {species: 'cat'},
205
+ * });
206
+ * const app = document.createElement('div');
207
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
208
+ * console.log(app.innerHTML);
209
+ * // ->
210
+ * `
211
+ * <table class="table">
212
+ * <thead>
213
+ * <tr>
214
+ * <th>Id</th>
215
+ * <th>species</th>
216
+ * </tr>
217
+ * </thead>
218
+ * <tbody>
219
+ * <tr>
220
+ * <th>fido</th>
221
+ * <td>dog</td>
222
+ * </tr>
223
+ * <tr>
224
+ * <th>felix</th>
225
+ * <td>cat</td>
226
+ * </tr>
227
+ * </tbody>
228
+ * </table>
229
+ * `;
230
+ * ```
231
+ * @example
232
+ * This example creates a Provider context into which a default Store is
233
+ * provided. The TableInHtmlTable component within it then renders the Table
234
+ * with a custom Row component and a custom props callback. The header row at
235
+ * the top of the table and the Id column at the start of each row is removed.
236
+ *
237
+ * ```jsx
238
+ * const App = ({store}) => (
239
+ * <Provider store={store}>
240
+ * <Pane />
241
+ * </Provider>
242
+ * );
243
+ * const Pane = () => (
244
+ * <TableInHtmlTable
245
+ * tableId="pets"
246
+ * cellComponent={FormattedCellView}
247
+ * getCellComponentProps={(rowId, cellId) => ({bold: rowId == 'fido'})}
248
+ * headerRow={false}
249
+ * idColumn={false}
250
+ * />
251
+ * );
252
+ * const FormattedCellView = ({tableId, rowId, cellId, bold}) => (
253
+ * <>
254
+ * {bold ? <b>{rowId}</b> : rowId}:
255
+ * <CellView tableId={tableId} rowId={rowId} cellId={cellId} />
256
+ * </>
257
+ * );
258
+ *
259
+ * const store = createStore().setTable('pets', {
260
+ * fido: {species: 'dog'},
261
+ * felix: {species: 'cat'},
262
+ * });
263
+ * const app = document.createElement('div');
264
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
265
+ * console.log(app.innerHTML);
266
+ * // ->
267
+ * `
268
+ * <table>
269
+ * <tbody>
270
+ * <tr>
271
+ * <td><b>fido</b>:dog</td>
272
+ * </tr>
273
+ * <tr>
274
+ * <td>felix:cat</td>
275
+ * </tr>
276
+ * </tbody>
277
+ * </table>
278
+ * `;
279
+ * ```
280
+ * @category Store components
281
+ * @since v4.1.0
282
+ */
283
+ export function TableInHtmlTable(
284
+ props: TableInHtmlTableProps,
285
+ ): ComponentReturnType;
286
+
287
+ /**
288
+ * The SortedTableInHtmlTable component renders the contents of a single sorted
289
+ * Table in a Store, as an HTML <table> element, and registers a listener so
290
+ * that any changes to that result will cause a re-render.
291
+ *
292
+ * The component's props identify which Table to render based on Table Id, and
293
+ * Store (which is either the default context Store, a named context Store, or
294
+ * by explicit reference). It also takes a Cell Id to sort by and a boolean to
295
+ * indicate that the sorting should be in descending order. The `offset` and
296
+ * `limit` props are used to paginate results, but default to `0` and
297
+ * `undefined` to return all available Row Ids if not specified.
298
+ *
299
+ * See the <SortedTableInHtmlTable /> demo for this component in action.
300
+ *
301
+ * This component renders a Table by iterating over its Row objects, in the
302
+ * order dictated by the sort parameters. By default these are in turn rendered
303
+ * with the RowInHtmlTr component, but you can override this behavior by
304
+ * providing a `rowComponent` prop, a custom component of your own that will
305
+ * render a Row based on RowProps. You can also pass additional props to your
306
+ * custom component with the `getRowComponentProps` callback prop.
307
+ *
308
+ * This component uses the useSortedRowIds hook under the covers, which means
309
+ * that any changes to the structure or sorting of the Table will cause a
310
+ * re-render.
311
+ *
312
+ * You can use the `headerRow` and `idColumn` props to control whether the Ids
313
+ * appear in a <th> element at the top of the table, and the start of each row.
314
+ *
315
+ * The `sortOnClick` prop makes the table's sorting interactive such that the
316
+ * user can click on a column heading to sort by that column. The style classes
317
+ * `sorted` and `ascending` (or `descending`) are added so that you can provide
318
+ * hints to the user how the sorting is being applied.
319
+ * @param props The props for this component.
320
+ * @returns A rendering of the Table in a <table> element.
321
+ * @example
322
+ * This example creates a Provider context into which a default Store is
323
+ * provided. The SortedTableInHtmlTable component within it then renders the
324
+ * Table in a <table> element with a CSS class.
325
+ *
326
+ * ```jsx
327
+ * const App = ({store}) => (
328
+ * <Provider store={store}>
329
+ * <Pane />
330
+ * </Provider>
331
+ * );
332
+ * const Pane = () => (
333
+ * <SortedTableInHtmlTable
334
+ * tableId="pets"
335
+ * cellId="species"
336
+ * className="table"
337
+ * />
338
+ * );
339
+ *
340
+ * const store = createStore().setTables({
341
+ * pets: {
342
+ * fido: {species: 'dog'},
343
+ * felix: {species: 'cat'},
344
+ * },
345
+ * });
346
+ * const app = document.createElement('div');
347
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
348
+ * console.log(app.innerHTML);
349
+ * // ->
350
+ * `
351
+ * <table class="table">
352
+ * <thead>
353
+ * <tr>
354
+ * <th>Id</th>
355
+ * <th class="sorted ascending">species</th>
356
+ * </tr>
357
+ * </thead>
358
+ * <tbody>
359
+ * <tr>
360
+ * <th>felix</th>
361
+ * <td>cat</td>
362
+ * </tr>
363
+ * <tr>
364
+ * <th>fido</th>
365
+ * <td>dog</td>
366
+ * </tr>
367
+ * </tbody>
368
+ * </table>
369
+ * `;
370
+ * ```
371
+ * @example
372
+ * This example creates a Provider context into which a default Store is
373
+ * provided. The SortedTableInHtmlTable component within it then renders the
374
+ * Table with a custom Row component and a custom props callback. The header row
375
+ * at the top of the table and the Id column at the start of each row is
376
+ * removed.
377
+ *
378
+ * ```jsx
379
+ * const App = ({store}) => (
380
+ * <Provider store={store}>
381
+ * <Pane />
382
+ * </Provider>
383
+ * );
384
+ * const Pane = () => (
385
+ * <SortedTableInHtmlTable
386
+ * tableId="pets"
387
+ * cellId="species"
388
+ * cellComponent={FormattedCellView}
389
+ * getCellComponentProps={(rowId, cellId) => ({bold: rowId == 'fido'})}
390
+ * headerRow={false}
391
+ * idColumn={false}
392
+ * />
393
+ * );
394
+ * const FormattedCellView = ({tableId, rowId, cellId, bold}) => (
395
+ * <>
396
+ * {bold ? <b>{rowId}</b> : rowId}:
397
+ * <CellView tableId={tableId} rowId={rowId} cellId={cellId} />
398
+ * </>
399
+ * );
400
+ *
401
+ * const store = createStore().setTables({
402
+ * pets: {
403
+ * fido: {species: 'dog'},
404
+ * felix: {species: 'cat'},
405
+ * },
406
+ * });
407
+ * const app = document.createElement('div');
408
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
409
+ * console.log(app.innerHTML);
410
+ * // ->
411
+ * `
412
+ * <table>
413
+ * <tbody>
414
+ * <tr>
415
+ * <td>felix:cat</td>
416
+ * </tr>
417
+ * <tr>
418
+ * <td><b>fido</b>:dog</td>
419
+ * </tr>
420
+ * </tbody>
421
+ * </table>
422
+ * `;
423
+ * ```
424
+ * @category Store components
425
+ * @since v4.1.0
426
+ */
427
+ export function SortedTableInHtmlTable(
428
+ props: SortedTableInHtmlTableProps,
429
+ ): ComponentReturnType;
430
+
431
+ /**
432
+ * The ValuesInHtmlTable component renders the keyed value contents of a Store
433
+ * as an HTML <table> element, and registers a listener so that any changes to
434
+ * that result will cause a re-render.
435
+ *
436
+ * The component's props identify which Row to render based on Table Id, Row Id,
437
+ * and Store (which is either the default context Store, a named context Store,
438
+ * or an explicit reference).
439
+ *
440
+ * See the <ValuesInHtmlTable /> demo for this component in action.
441
+ *
442
+ * This component renders a Store by iterating over its Value objects. By
443
+ * default these are in turn rendered with the ValueInHtmlTr component, but you
444
+ * can override this behavior by providing a `valueComponent` prop, a custom
445
+ * component of your own that will render a Value based on ValueProps. You can
446
+ * also pass additional props to your custom component with the
447
+ * `getValueComponentProps` callback prop.
448
+ *
449
+ * This component uses the useValueIds hook under the covers, which means that
450
+ * any changes to the structure of the Values in the Store will cause a
451
+ * re-render.
452
+ *
453
+ * You can use the `headerRow` and `idColumn` props to control whether labels
454
+ * and Ids appear in a <th> element at the top of the table, and the start of
455
+ * each row.
456
+ * @param props The props for this component.
457
+ * @returns A rendering of the Values in a <table> element.
458
+ * @example
459
+ * This example creates a Provider context into which a default Store is
460
+ * provided. The ValuesInHtmlTable component within it then renders the Values
461
+ * in a <table> element with a CSS class.
462
+ *
463
+ * ```jsx
464
+ * const App = ({store}) => (
465
+ * <Provider store={store}>
466
+ * <Pane />
467
+ * </Provider>
468
+ * );
469
+ * const Pane = () => <ValuesInHtmlTable className="values" />;
470
+ *
471
+ * const store = createStore().setValues({open: true, employees: 3});
472
+ * const app = document.createElement('div');
473
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
474
+ * console.log(app.innerHTML);
475
+ * // ->
476
+ * `
477
+ * <table class="values">
478
+ * <thead>
479
+ * <tr>
480
+ * <th>Id</th>
481
+ * <th>Value</th>
482
+ * </tr>
483
+ * </thead>
484
+ * <tbody>
485
+ * <tr>
486
+ * <th>open</th>
487
+ * <td>true</td>
488
+ * </tr>
489
+ * <tr>
490
+ * <th>employees</th>
491
+ * <td>3</td>
492
+ * </tr>
493
+ * </tbody>
494
+ * </table>
495
+ * `;
496
+ * ```
497
+ * @example
498
+ * This example creates a Provider context into which a default Store is
499
+ * provided. The ValuesInHtmlTable component within it then renders the Row
500
+ * with a custom Cell component and a custom props callback. The header row at
501
+ * the top of the table and the Id column at the start of each row is removed.
502
+ *
503
+ * ```jsx
504
+ * const App = ({store}) => (
505
+ * <Provider store={store}>
506
+ * <Pane />
507
+ * </Provider>
508
+ * );
509
+ * const Pane = () => (
510
+ * <ValuesInHtmlTable
511
+ * valueComponent={FormattedValueView}
512
+ * getValueComponentProps={(valueId) => ({bold: valueId == 'open'})}
513
+ * headerRow={false}
514
+ * idColumn={false}
515
+ * />
516
+ * );
517
+ * const FormattedValueView = ({valueId, bold}) => (
518
+ * <>
519
+ * {bold ? <b>{valueId}</b> : valueId}
520
+ * {': '}
521
+ * <ValueView valueId={valueId} />
522
+ * </>
523
+ * );
524
+ *
525
+ * const store = createStore().setValues({open: true, employees: 3});
526
+ * const app = document.createElement('div');
527
+ * ReactDOMClient.createRoot(app).render(<App store={store} />); // !act
528
+ * console.log(app.innerHTML);
529
+ * // ->
530
+ * `
531
+ * <table>
532
+ * <tbody>
533
+ * <tr><td><b>open</b>: true</td></tr>
534
+ * <tr><td>employees: 3</td></tr>
535
+ * </tbody>
536
+ * </table>
537
+ * `;
538
+ * ```
539
+ * @category Store components
540
+ * @since v4.1.0
541
+ */
542
+ export function ValuesInHtmlTable(
543
+ props: ValuesInHtmlTableProps,
544
+ ): ComponentReturnType;