tinybase 8.5.0-beta.0 → 8.5.0-beta.2

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 (137) hide show
  1. package/@types/ui-react-dom-charts/index.d.ts +387 -0
  2. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +476 -0
  3. package/common/index.js +3 -2
  4. package/common/with-schemas/index.js +3 -2
  5. package/index.js +5 -3
  6. package/mergeable-store/index.js +5 -3
  7. package/mergeable-store/with-schemas/index.js +5 -3
  8. package/metrics/index.js +1 -1
  9. package/metrics/with-schemas/index.js +1 -1
  10. package/min/common/index.js +1 -1
  11. package/min/common/index.js.gz +0 -0
  12. package/min/common/with-schemas/index.js +1 -1
  13. package/min/common/with-schemas/index.js.gz +0 -0
  14. package/min/index.js +1 -1
  15. package/min/index.js.gz +0 -0
  16. package/min/mergeable-store/index.js +1 -1
  17. package/min/mergeable-store/index.js.gz +0 -0
  18. package/min/mergeable-store/with-schemas/index.js +1 -1
  19. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  20. package/min/omni/index.js +1 -1
  21. package/min/omni/index.js.gz +0 -0
  22. package/min/omni/with-schemas/index.js +1 -1
  23. package/min/omni/with-schemas/index.js.gz +0 -0
  24. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  25. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  26. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  27. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  28. package/min/persisters/persister-partykit-server/index.js +1 -1
  29. package/min/persisters/persister-partykit-server/index.js.gz +0 -0
  30. package/min/persisters/persister-partykit-server/with-schemas/index.js +1 -1
  31. package/min/persisters/persister-partykit-server/with-schemas/index.js.gz +0 -0
  32. package/min/queries/index.js +1 -1
  33. package/min/queries/index.js.gz +0 -0
  34. package/min/queries/with-schemas/index.js +1 -1
  35. package/min/queries/with-schemas/index.js.gz +0 -0
  36. package/min/synchronizers/index.js +1 -1
  37. package/min/synchronizers/index.js.gz +0 -0
  38. package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
  39. package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
  40. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
  41. package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
  42. package/min/synchronizers/synchronizer-local/index.js +1 -1
  43. package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
  44. package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
  45. package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
  46. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  47. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  48. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  49. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  50. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  51. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  52. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  53. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  54. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  55. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  56. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  57. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  58. package/min/synchronizers/with-schemas/index.js +1 -1
  59. package/min/synchronizers/with-schemas/index.js.gz +0 -0
  60. package/min/ui-react/index.js +1 -1
  61. package/min/ui-react/index.js.gz +0 -0
  62. package/min/ui-react/with-schemas/index.js +1 -1
  63. package/min/ui-react/with-schemas/index.js.gz +0 -0
  64. package/min/ui-react-dom/index.js +1 -1
  65. package/min/ui-react-dom/index.js.gz +0 -0
  66. package/min/ui-react-dom/with-schemas/index.js +1 -1
  67. package/min/ui-react-dom/with-schemas/index.js.gz +0 -0
  68. package/min/ui-react-dom-charts/index.js +1 -0
  69. package/min/ui-react-dom-charts/index.js.gz +0 -0
  70. package/min/ui-react-dom-charts/with-schemas/index.js +1 -0
  71. package/min/ui-react-dom-charts/with-schemas/index.js.gz +0 -0
  72. package/min/ui-react-inspector/index.js +1 -1
  73. package/min/ui-react-inspector/index.js.gz +0 -0
  74. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  75. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  76. package/min/ui-solid-dom/index.js +1 -1
  77. package/min/ui-solid-dom/index.js.gz +0 -0
  78. package/min/ui-solid-dom/with-schemas/index.js +1 -1
  79. package/min/ui-solid-dom/with-schemas/index.js.gz +0 -0
  80. package/min/ui-solid-inspector/index.js +1 -1
  81. package/min/ui-solid-inspector/index.js.gz +0 -0
  82. package/min/ui-solid-inspector/with-schemas/index.js +1 -1
  83. package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
  84. package/min/ui-svelte-dom/index.js +1 -1
  85. package/min/ui-svelte-dom/index.js.gz +0 -0
  86. package/min/ui-svelte-dom/with-schemas/index.js +1 -1
  87. package/min/ui-svelte-dom/with-schemas/index.js.gz +0 -0
  88. package/min/ui-svelte-inspector/index.js +1 -1
  89. package/min/ui-svelte-inspector/index.js.gz +0 -0
  90. package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
  91. package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
  92. package/min/with-schemas/index.js +1 -1
  93. package/min/with-schemas/index.js.gz +0 -0
  94. package/omni/index.js +7 -4
  95. package/omni/with-schemas/index.js +7 -4
  96. package/package.json +53 -17
  97. package/persisters/persister-durable-object-sql-storage/index.js +13 -11
  98. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +13 -11
  99. package/persisters/persister-partykit-client/index.js +2 -1
  100. package/persisters/persister-partykit-client/with-schemas/index.js +2 -1
  101. package/persisters/persister-partykit-server/index.js +2 -1
  102. package/persisters/persister-partykit-server/with-schemas/index.js +2 -1
  103. package/queries/index.js +1 -1
  104. package/queries/with-schemas/index.js +1 -1
  105. package/readme.md +14 -14
  106. package/releases.md +124 -61
  107. package/synchronizers/index.js +3 -2
  108. package/synchronizers/synchronizer-broadcast-channel/index.js +3 -2
  109. package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +3 -2
  110. package/synchronizers/synchronizer-local/index.js +3 -2
  111. package/synchronizers/synchronizer-local/with-schemas/index.js +3 -2
  112. package/synchronizers/synchronizer-ws-client/index.js +3 -2
  113. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +3 -2
  114. package/synchronizers/synchronizer-ws-server/index.js +3 -2
  115. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +3 -2
  116. package/synchronizers/synchronizer-ws-server-durable-object/index.js +3 -2
  117. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +3 -2
  118. package/synchronizers/with-schemas/index.js +3 -2
  119. package/ui-react/index.js +3 -0
  120. package/ui-react/with-schemas/index.js +3 -0
  121. package/ui-react-dom/index.js +18 -12
  122. package/ui-react-dom/with-schemas/index.js +18 -12
  123. package/ui-react-dom-charts/index.js +1783 -0
  124. package/ui-react-dom-charts/with-schemas/index.js +1783 -0
  125. package/ui-react-inspector/index.js +29 -20
  126. package/ui-react-inspector/with-schemas/index.js +29 -20
  127. package/ui-solid-dom/index.js +10 -7
  128. package/ui-solid-dom/with-schemas/index.js +10 -7
  129. package/ui-solid-inspector/index.js +16 -10
  130. package/ui-solid-inspector/with-schemas/index.js +16 -10
  131. package/ui-svelte/index.js +5 -5
  132. package/ui-svelte/with-schemas/index.js +5 -5
  133. package/ui-svelte-dom/index.js +162 -164
  134. package/ui-svelte-dom/with-schemas/index.js +162 -164
  135. package/ui-svelte-inspector/index.js +192 -196
  136. package/ui-svelte-inspector/with-schemas/index.js +192 -196
  137. package/with-schemas/index.js +5 -3
@@ -0,0 +1,476 @@
1
+ /**
2
+ * The ui-react-dom-charts module of the TinyBase project provides components
3
+ * to make it easy to create web-based reactive charts with Store and Queries
4
+ * objects.
5
+ *
6
+ * The components in this module use the react-dom module and so are not
7
+ * appropriate for environments like React Native (although those in the
8
+ * lower-level ui-react module are).
9
+ *
10
+ * For a full list of SVG class names that can be styled with CSS, see the
11
+ * Using Charts guide.
12
+ * @packageDocumentation
13
+ * @module ui-react-dom-charts
14
+ * @since v8.5.0
15
+ */
16
+ import type {ReactNode} from 'react';
17
+ import type {
18
+ CellIdFromSchema,
19
+ TableIdFromSchema,
20
+ } from '../../_internal/store/with-schemas/index.d.ts';
21
+ import type {ComponentReturnType} from '../../_internal/ui-react/with-schemas/index.d.ts';
22
+ import type {
23
+ QueriesOrQueriesId,
24
+ StoreOrStoreId,
25
+ } from '../../_internal/ui/with-schemas/index.d.ts';
26
+ import type {Id} from '../../common/with-schemas/index.d.ts';
27
+ import type {OptionalSchemas} from '../../store/with-schemas/index.d.ts';
28
+
29
+ /**
30
+ * The ChartProps type describes the props that are used to configure the
31
+ * chart element that renders a chart.
32
+ * @category Configuration
33
+ * @since v8.5.0
34
+ */
35
+ export type ChartProps = {
36
+ /**
37
+ * An optional string that will be used as the class attribute of the chart's
38
+ * SVG element. This can be used as the root selector for styling chart
39
+ * internals, as shown in the Using Charts guide.
40
+ * @category Prop
41
+ * @since v8.5.0
42
+ */
43
+ readonly className?: string;
44
+ };
45
+
46
+ /**
47
+ * The ChartTableSourceProps type describes the props that bind a chart to a
48
+ * Table in a Store.
49
+ * @category Configuration
50
+ * @since v8.5.0
51
+ */
52
+ export type ChartTableSourceProps<
53
+ Schemas extends OptionalSchemas,
54
+ TableIds extends TableIdFromSchema<Schemas[0]> = TableIdFromSchema<
55
+ Schemas[0]
56
+ >,
57
+ > = TableIds extends infer TableId
58
+ ? TableId extends TableIdFromSchema<Schemas[0]>
59
+ ? {
60
+ /**
61
+ * The Id of the Table in the Store to chart.
62
+ * @category Prop
63
+ * @since v8.5.0
64
+ */
65
+ readonly tableId: TableId;
66
+ /**
67
+ * The Store to chart, or the Id of a Store that is registered with the
68
+ * Provider component.
69
+ * @category Prop
70
+ * @since v8.5.0
71
+ */
72
+ readonly store?: StoreOrStoreId<Schemas>;
73
+ /**
74
+ * This prop is not used when binding a chart to a Table.
75
+ * @category Prop
76
+ * @since v8.5.0
77
+ */
78
+ readonly queryId?: never;
79
+ /**
80
+ * This prop is not used when binding a chart to a Table.
81
+ * @category Prop
82
+ * @since v8.5.0
83
+ */
84
+ readonly queries?: never;
85
+ }
86
+ : never
87
+ : never;
88
+
89
+ /**
90
+ * The ChartQuerySourceProps type describes the props that bind a chart to a
91
+ * Query in a Queries object.
92
+ * @category Configuration
93
+ * @since v8.5.0
94
+ */
95
+ export type ChartQuerySourceProps<Schemas extends OptionalSchemas> = {
96
+ /**
97
+ * The Id of the query in the Queries object to chart.
98
+ * @category Prop
99
+ * @since v8.5.0
100
+ */
101
+ readonly queryId: Id;
102
+ /**
103
+ * The Queries object to chart, or the Id of a Queries object that is
104
+ * registered with the Provider component.
105
+ * @category Prop
106
+ * @since v8.5.0
107
+ */
108
+ readonly queries?: QueriesOrQueriesId<Schemas>;
109
+ /**
110
+ * This prop is not used when binding a chart to a Query.
111
+ * @category Prop
112
+ * @since v8.5.0
113
+ */
114
+ readonly tableId?: never;
115
+ /**
116
+ * This prop is not used when binding a chart to a Query.
117
+ * @category Prop
118
+ * @since v8.5.0
119
+ */
120
+ readonly store?: never;
121
+ };
122
+
123
+ /**
124
+ * The ChartBindingProps type describes the props that bind a LineChart or
125
+ * BarChart component to Cell values in TinyBase data. An x Cell value can be a
126
+ * finite number, string, or boolean. A y Cell value must be a finite number.
127
+ * @category Configuration
128
+ * @since v8.5.0
129
+ */
130
+ export type ChartBindingProps<
131
+ XCellId extends Id = Id,
132
+ YCellId extends Id = Id,
133
+ SortCellId extends Id = XCellId,
134
+ > = {
135
+ /**
136
+ * The Id of the Cell that provides each data point's x value. Finite numbers
137
+ * can be used as continuous x values in line charts, while strings and
138
+ * booleans are used as category values. Boolean category labels are rendered
139
+ * as `true` and `false`.
140
+ * @category Prop
141
+ * @since v8.5.0
142
+ */
143
+ readonly xCellId: XCellId;
144
+ /**
145
+ * The Id of the Cell that provides each data point's y value. Only finite
146
+ * numbers are charted; rows with missing, non-numeric, or non-finite y values
147
+ * are ignored.
148
+ * @category Prop
149
+ * @since v8.5.0
150
+ */
151
+ readonly yCellId: YCellId;
152
+ /**
153
+ * The Id of the Cell used to sort the charted rows.
154
+ * @category Prop
155
+ * @since v8.5.0
156
+ */
157
+ readonly sortCellId?: SortCellId;
158
+ /**
159
+ * Whether the charted rows should be sorted in descending order.
160
+ * @category Prop
161
+ * @since v8.5.0
162
+ */
163
+ readonly descending?: boolean;
164
+ /**
165
+ * The number of sorted rows to skip before charting.
166
+ * @category Prop
167
+ * @since v8.5.0
168
+ */
169
+ readonly offset?: number;
170
+ /**
171
+ * The maximum number of sorted rows to chart.
172
+ * @category Prop
173
+ * @since v8.5.0
174
+ */
175
+ readonly limit?: number;
176
+ };
177
+
178
+ /**
179
+ * The ChartSeriesProps type describes the props that bind a chart series to
180
+ * Cell values in TinyBase data. An x Cell value can be a finite number,
181
+ * string, or boolean. A y Cell value must be a finite number.
182
+ * @category Configuration
183
+ * @since v8.5.0
184
+ */
185
+ export type ChartSeriesProps<CellId extends Id = Id> = {
186
+ /**
187
+ * An optional string that will be added to the class attribute of the series'
188
+ * SVG group element.
189
+ * @category Prop
190
+ * @since v8.5.0
191
+ */
192
+ readonly className?: string;
193
+ /**
194
+ * The Id of the Cell that provides each data point's x value. Finite numbers
195
+ * can be used as continuous x values in line series, while strings and
196
+ * booleans are used as category values. Boolean category labels are rendered
197
+ * as `true` and `false`.
198
+ * @category Prop
199
+ * @since v8.5.0
200
+ */
201
+ readonly xCellId: CellId;
202
+ /**
203
+ * The Id of the Cell that provides each data point's y value. Only finite
204
+ * numbers are charted; rows with missing, non-numeric, or non-finite y values
205
+ * are ignored.
206
+ * @category Prop
207
+ * @since v8.5.0
208
+ */
209
+ readonly yCellId: CellId;
210
+ /**
211
+ * An optional label to use for the series in axis titles and tooltips,
212
+ * defaulting to the y Cell Id.
213
+ * @category Prop
214
+ * @since v8.5.0
215
+ */
216
+ readonly label?: string;
217
+ /**
218
+ * The Id of the Cell used to sort the charted rows.
219
+ * @category Prop
220
+ * @since v8.5.0
221
+ */
222
+ readonly sortCellId?: CellId;
223
+ /**
224
+ * Whether the charted rows should be sorted in descending order.
225
+ * @category Prop
226
+ * @since v8.5.0
227
+ */
228
+ readonly descending?: boolean;
229
+ /**
230
+ * The number of sorted rows to skip before charting.
231
+ * @category Prop
232
+ * @since v8.5.0
233
+ */
234
+ readonly offset?: number;
235
+ /**
236
+ * The maximum number of sorted rows to chart.
237
+ * @category Prop
238
+ * @since v8.5.0
239
+ */
240
+ readonly limit?: number;
241
+ };
242
+
243
+ type NumericCellIdFromSchema<
244
+ Schemas extends OptionalSchemas,
245
+ TableId extends TableIdFromSchema<Schemas[0]>,
246
+ > = {
247
+ [CellId in CellIdFromSchema<
248
+ Schemas[0],
249
+ TableId
250
+ >]: Schemas[0][TableId][CellId] extends {type: 'any' | 'number'}
251
+ ? CellId
252
+ : never;
253
+ }[CellIdFromSchema<Schemas[0], TableId>];
254
+
255
+ type ChartTableBindingProps<
256
+ Schemas extends OptionalSchemas,
257
+ TableIds extends TableIdFromSchema<Schemas[0]> = TableIdFromSchema<
258
+ Schemas[0]
259
+ >,
260
+ > = TableIds extends infer TableId
261
+ ? TableId extends TableIdFromSchema<Schemas[0]>
262
+ ? ChartTableSourceProps<Schemas, TableId> &
263
+ ChartBindingProps<
264
+ CellIdFromSchema<Schemas[0], TableId>,
265
+ NumericCellIdFromSchema<Schemas, TableId>,
266
+ CellIdFromSchema<Schemas[0], TableId>
267
+ >
268
+ : never
269
+ : never;
270
+
271
+ /**
272
+ * The WithSchemas type provides a version of this module that is typed with
273
+ * schemas.
274
+ * @category Development
275
+ * @since v8.5.0
276
+ */
277
+ export type WithSchemas<Schemas extends OptionalSchemas> = {
278
+ /**
279
+ * The CartesianChart component renders a chart frame and provides TinyBase
280
+ * source and layout context to child LineSeries and BarSeries components.
281
+ *
282
+ * This has schema-based typing. The following is a simplified representation:
283
+ *
284
+ * ```ts override
285
+ * CartesianChart(
286
+ * props: (ChartTableSourceProps | ChartQuerySourceProps) &
287
+ * ChartProps & {readonly children?: ReactNode},
288
+ * ): ComponentReturnType;
289
+ * ```
290
+ *
291
+ * The series children declare their own xCellId and yCellId bindings.
292
+ * @category Store components
293
+ * @since v8.5.0
294
+ * @example
295
+ * This example creates a Store and renders two LineSeries components in a
296
+ * CartesianChart.
297
+ *
298
+ * ```jsx
299
+ * import React from 'react';
300
+ * import {createRoot} from 'react-dom/client';
301
+ * import {createStore} from 'tinybase';
302
+ * import {CartesianChart, LineSeries} from 'tinybase/ui-react-dom-charts';
303
+ *
304
+ * const store = createStore().setTable('pets', {
305
+ * hamsters: {order: 1, sold: 12, returned: 1},
306
+ * rabbits: {order: 2, sold: 9, returned: 2},
307
+ * });
308
+ * const App = () => (
309
+ * <CartesianChart store={store} tableId="pets">
310
+ * <LineSeries
311
+ * className="sold"
312
+ * label="Sold pets"
313
+ * xCellId="order"
314
+ * yCellId="sold"
315
+ * />
316
+ * <LineSeries
317
+ * className="returned"
318
+ * label="Returned pets"
319
+ * xCellId="order"
320
+ * yCellId="returned"
321
+ * />
322
+ * </CartesianChart>
323
+ * );
324
+ * const app = document.createElement('div');
325
+ * createRoot(app).render(<App />); // !act
326
+ * console.log(app.firstChild?.nodeName.toLowerCase());
327
+ * // -> 'svg'
328
+ * ```
329
+ */
330
+ CartesianChart: {
331
+ (
332
+ props: ChartTableSourceProps<Schemas> &
333
+ ChartProps & {readonly children?: ReactNode},
334
+ ): ComponentReturnType;
335
+ (
336
+ props: ChartQuerySourceProps<Schemas> &
337
+ ChartProps & {readonly children?: ReactNode},
338
+ ): ComponentReturnType;
339
+ };
340
+
341
+ /**
342
+ * The LineSeries component renders a line series in a CartesianChart
343
+ * component. If every x value in every series is a finite number, the x axis is
344
+ * rendered as a continuous numeric scale. If any x value is a string or
345
+ * boolean, the x axis is rendered categorically. When sortCellId is omitted,
346
+ * rows are sorted by xCellId.
347
+ * @category Store components
348
+ * @since v8.5.0
349
+ */
350
+ LineSeries: (props: ChartSeriesProps) => ComponentReturnType;
351
+
352
+ /**
353
+ * The BarSeries component renders a bar series in a CartesianChart component.
354
+ * Its x values are always rendered categorically, even when they are finite
355
+ * numbers. Boolean category labels are rendered as `true` and `false`.
356
+ * @category Store components
357
+ * @since v8.5.0
358
+ */
359
+ BarSeries: (props: ChartSeriesProps) => ComponentReturnType;
360
+
361
+ /**
362
+ * The LineChart component renders a line chart from TinyBase data. If every x
363
+ * value is a finite number, the x axis is rendered as a continuous numeric
364
+ * scale. If any x value is a string or boolean, the x axis is rendered
365
+ * categorically. When sortCellId is omitted, rows are sorted by xCellId.
366
+ * @category Store components
367
+ * @since v8.5.0
368
+ * @example
369
+ * This example creates a Provider context into which a default Store is
370
+ * provided. The LineChart component then renders an SVG chart from Cells in the
371
+ * `pets` Table.
372
+ *
373
+ * This has schema-based typing. The following is a simplified representation:
374
+ *
375
+ * ```ts override
376
+ * LineChart(
377
+ * props: (ChartTableSourceProps | ChartQuerySourceProps) &
378
+ * ChartBindingProps &
379
+ * ChartProps,
380
+ * ): ComponentReturnType;
381
+ * ```
382
+ *
383
+ * ```jsx
384
+ * import React from 'react';
385
+ * import {createRoot} from 'react-dom/client';
386
+ * import {createStore} from 'tinybase';
387
+ * import {Provider} from 'tinybase/ui-react';
388
+ * import {LineChart} from 'tinybase/ui-react-dom-charts';
389
+ *
390
+ * const App = ({store}) => (
391
+ * <Provider store={store}>
392
+ * <LineChart
393
+ * tableId="pets"
394
+ * xCellId="order"
395
+ * yCellId="sold"
396
+ * className="sales"
397
+ * />
398
+ * </Provider>
399
+ * );
400
+ *
401
+ * const store = createStore().setTable('pets', {
402
+ * hamsters: {order: 1, sold: 12},
403
+ * rabbits: {order: 2, sold: 9},
404
+ * });
405
+ * const app = document.createElement('div');
406
+ * createRoot(app).render(<App store={store} />); // !act
407
+ * console.log(app.firstChild?.nodeName.toLowerCase());
408
+ * // -> 'svg'
409
+ * console.log(app.firstChild?.getAttribute('class'));
410
+ * // -> 'sales'
411
+ * ```
412
+ */
413
+ LineChart: (
414
+ props:
415
+ | (ChartTableBindingProps<Schemas> & ChartProps)
416
+ | (ChartQuerySourceProps<Schemas> & ChartBindingProps & ChartProps),
417
+ ) => ComponentReturnType;
418
+
419
+ /**
420
+ * The BarChart component renders a bar chart from TinyBase data. Its x values
421
+ * are always rendered categorically, even when they are finite numbers. Boolean
422
+ * category labels are rendered as `true` and `false`.
423
+ * @category Store components
424
+ * @since v8.5.0
425
+ * @example
426
+ * This example creates a Queries object and provides it through Provider
427
+ * context. The BarChart component then renders an SVG chart from Cells in the
428
+ * `bySpecies` query.
429
+ *
430
+ * This has schema-based typing. The following is a simplified representation:
431
+ *
432
+ * ```ts override
433
+ * BarChart(
434
+ * props: (ChartTableSourceProps | ChartQuerySourceProps) &
435
+ * ChartBindingProps &
436
+ * ChartProps,
437
+ * ): ComponentReturnType;
438
+ * ```
439
+ *
440
+ * ```jsx
441
+ * import React from 'react';
442
+ * import {createRoot} from 'react-dom/client';
443
+ * import {createQueries, createStore} from 'tinybase';
444
+ * import {Provider} from 'tinybase/ui-react';
445
+ * import {BarChart} from 'tinybase/ui-react-dom-charts';
446
+ *
447
+ * const App = ({queries}) => (
448
+ * <Provider queries={queries}>
449
+ * <BarChart queryId="bySpecies" xCellId="species" yCellId="sold" />
450
+ * </Provider>
451
+ * );
452
+ *
453
+ * const store = createStore().setTable('pets', {
454
+ * hamsters: {species: 'hamster', sold: 12},
455
+ * rabbits: {species: 'rabbit', sold: 9},
456
+ * });
457
+ * const queries = createQueries(store).setQueryDefinition(
458
+ * 'bySpecies',
459
+ * 'pets',
460
+ * ({select}) => {
461
+ * select('species');
462
+ * select('sold');
463
+ * },
464
+ * );
465
+ * const app = document.createElement('div');
466
+ * createRoot(app).render(<App queries={queries} />); // !act
467
+ * console.log(app.firstChild?.nodeName.toLowerCase());
468
+ * // -> 'svg'
469
+ * ```
470
+ */
471
+ BarChart: (
472
+ props:
473
+ | (ChartTableBindingProps<Schemas> & ChartProps)
474
+ | (ChartQuerySourceProps<Schemas> & ChartBindingProps & ChartProps),
475
+ ) => ComponentReturnType;
476
+ };
package/common/index.js CHANGED
@@ -2,15 +2,16 @@ const EMPTY_STRING = '';
2
2
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
3
3
  str.split(separator, limit);
4
4
 
5
+ const math = Math;
5
6
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
6
7
  predicate(value)
7
8
  ? /* istanbul ignore next */
8
9
  otherwise?.()
9
10
  : then(value);
10
11
  const GLOBAL = globalThis;
11
- const math = Math;
12
12
  const mathMax = math.max;
13
13
  const mathFloor = math.floor;
14
+ const mathRandom = math.random;
14
15
  const isInstanceOf = (thing, cls) => thing instanceof cls;
15
16
  const isUndefined = (thing) => thing === void 0;
16
17
  const ifNotUndefined = getIfNotFunction(isUndefined);
@@ -38,7 +39,7 @@ const decode = (str, pos) => mapGet(DECODE, str[pos]) ?? 0;
38
39
  const getRandomValues = GLOBAL.crypto
39
40
  ? (array) => GLOBAL.crypto.getRandomValues(array)
40
41
  : /* istanbul ignore next */
41
- (array) => arrayMap(array, () => mathFloor(math.random() * 256));
42
+ (array) => arrayMap(array, () => mathFloor(mathRandom() * 256));
42
43
  const getUniqueId = (length = 16) =>
43
44
  arrayReduce(
44
45
  getRandomValues(new Uint8Array(length)),
@@ -2,15 +2,16 @@ const EMPTY_STRING = '';
2
2
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
3
3
  str.split(separator, limit);
4
4
 
5
+ const math = Math;
5
6
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
6
7
  predicate(value)
7
8
  ? /* istanbul ignore next */
8
9
  otherwise?.()
9
10
  : then(value);
10
11
  const GLOBAL = globalThis;
11
- const math = Math;
12
12
  const mathMax = math.max;
13
13
  const mathFloor = math.floor;
14
+ const mathRandom = math.random;
14
15
  const isInstanceOf = (thing, cls) => thing instanceof cls;
15
16
  const isUndefined = (thing) => thing === void 0;
16
17
  const ifNotUndefined = getIfNotFunction(isUndefined);
@@ -38,7 +39,7 @@ const decode = (str, pos) => mapGet(DECODE, str[pos]) ?? 0;
38
39
  const getRandomValues = GLOBAL.crypto
39
40
  ? (array) => GLOBAL.crypto.getRandomValues(array)
40
41
  : /* istanbul ignore next */
41
- (array) => arrayMap(array, () => mathFloor(math.random() * 256));
42
+ (array) => arrayMap(array, () => mathFloor(mathRandom() * 256));
42
43
  const getUniqueId = (length = 16) =>
43
44
  arrayReduce(
44
45
  getRandomValues(new Uint8Array(length)),
package/index.js CHANGED
@@ -42,16 +42,17 @@ const strEndsWith = (str, suffix) => str.endsWith(suffix);
42
42
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
43
43
  str.split(separator, limit);
44
44
 
45
+ const math = Math;
45
46
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
46
47
  predicate(value)
47
48
  ? /* istanbul ignore next */
48
49
  otherwise?.()
49
50
  : then(value);
50
51
  const GLOBAL = globalThis;
51
- const math = Math;
52
52
  const mathMax = math.max;
53
53
  const mathMin = math.min;
54
54
  const mathFloor = math.floor;
55
+ const mathRandom = math.random;
55
56
  const isFiniteNumber = isFinite;
56
57
  const isInstanceOf = (thing, cls) => thing instanceof cls;
57
58
  const isNullish = (thing) => thing == null;
@@ -63,6 +64,7 @@ const ifNotNullish = getIfNotFunction(isNullish);
63
64
  const ifNotUndefined = getIfNotFunction(isUndefined);
64
65
  const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
65
66
  const isString = (thing) => getTypeOf(thing) == STRING;
67
+ const isNumber = (thing) => getTypeOf(thing) == NUMBER;
66
68
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
67
69
  const isArray = (thing) => Array.isArray(thing);
68
70
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
@@ -785,7 +787,7 @@ const decode = (str, pos) => mapGet(DECODE, str[pos]) ?? 0;
785
787
  const getRandomValues = GLOBAL.crypto
786
788
  ? (array) => GLOBAL.crypto.getRandomValues(array)
787
789
  : /* istanbul ignore next */
788
- (array) => arrayMap(array, () => mathFloor(math.random() * 256));
790
+ (array) => arrayMap(array, () => mathFloor(mathRandom() * 256));
789
791
  const getUniqueId = (length = 16) =>
790
792
  arrayReduce(
791
793
  getRandomValues(new Uint8Array(length)),
@@ -1191,7 +1193,7 @@ const stampValidate = (stamp, validateThing) =>
1191
1193
  isArray(stamp) &&
1192
1194
  size(stamp) == 3 &&
1193
1195
  isString(stamp[1]) &&
1194
- getTypeOf(stamp[2]) == NUMBER &&
1196
+ isNumber(stamp[2]) &&
1195
1197
  isFiniteNumber(stamp[2]) &&
1196
1198
  validateThing(stamp[0]);
1197
1199
 
@@ -35,15 +35,16 @@ const strEndsWith = (str, suffix) => str.endsWith(suffix);
35
35
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
36
36
  str.split(separator, limit);
37
37
 
38
+ const math = Math;
38
39
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
39
40
  predicate(value)
40
41
  ? /* istanbul ignore next */
41
42
  otherwise?.()
42
43
  : then(value);
43
44
  const GLOBAL = globalThis;
44
- const math = Math;
45
45
  const mathMax = math.max;
46
46
  const mathFloor = math.floor;
47
+ const mathRandom = math.random;
47
48
  const isFiniteNumber = isFinite;
48
49
  const isInstanceOf = (thing, cls) => thing instanceof cls;
49
50
  const isNullish = (thing) => thing == null;
@@ -53,6 +54,7 @@ const ifNotNullish = getIfNotFunction(isNullish);
53
54
  const ifNotUndefined = getIfNotFunction(isUndefined);
54
55
  const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
55
56
  const isString = (thing) => getTypeOf(thing) == STRING;
57
+ const isNumber = (thing) => getTypeOf(thing) == NUMBER;
56
58
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
57
59
  const isArray = (thing) => Array.isArray(thing);
58
60
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
@@ -307,7 +309,7 @@ const decode = (str, pos) => mapGet(DECODE, str[pos]) ?? 0;
307
309
  const getRandomValues = GLOBAL.crypto
308
310
  ? (array) => GLOBAL.crypto.getRandomValues(array)
309
311
  : /* istanbul ignore next */
310
- (array) => arrayMap(array, () => mathFloor(math.random() * 256));
312
+ (array) => arrayMap(array, () => mathFloor(mathRandom() * 256));
311
313
  const getUniqueId = (length = 16) =>
312
314
  arrayReduce(
313
315
  getRandomValues(new Uint8Array(length)),
@@ -432,7 +434,7 @@ const stampValidate = (stamp, validateThing) =>
432
434
  isArray(stamp) &&
433
435
  size(stamp) == 3 &&
434
436
  isString(stamp[1]) &&
435
- getTypeOf(stamp[2]) == NUMBER &&
437
+ isNumber(stamp[2]) &&
436
438
  isFiniteNumber(stamp[2]) &&
437
439
  validateThing(stamp[0]);
438
440
 
@@ -35,15 +35,16 @@ const strEndsWith = (str, suffix) => str.endsWith(suffix);
35
35
  const strSplit = (str, separator = EMPTY_STRING, limit) =>
36
36
  str.split(separator, limit);
37
37
 
38
+ const math = Math;
38
39
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
39
40
  predicate(value)
40
41
  ? /* istanbul ignore next */
41
42
  otherwise?.()
42
43
  : then(value);
43
44
  const GLOBAL = globalThis;
44
- const math = Math;
45
45
  const mathMax = math.max;
46
46
  const mathFloor = math.floor;
47
+ const mathRandom = math.random;
47
48
  const isFiniteNumber = isFinite;
48
49
  const isInstanceOf = (thing, cls) => thing instanceof cls;
49
50
  const isNullish = (thing) => thing == null;
@@ -53,6 +54,7 @@ const ifNotNullish = getIfNotFunction(isNullish);
53
54
  const ifNotUndefined = getIfNotFunction(isUndefined);
54
55
  const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
55
56
  const isString = (thing) => getTypeOf(thing) == STRING;
57
+ const isNumber = (thing) => getTypeOf(thing) == NUMBER;
56
58
  const isFunction = (thing) => getTypeOf(thing) == FUNCTION;
57
59
  const isArray = (thing) => Array.isArray(thing);
58
60
  const slice = (arrayOrString, start, end) => arrayOrString.slice(start, end);
@@ -307,7 +309,7 @@ const decode = (str, pos) => mapGet(DECODE, str[pos]) ?? 0;
307
309
  const getRandomValues = GLOBAL.crypto
308
310
  ? (array) => GLOBAL.crypto.getRandomValues(array)
309
311
  : /* istanbul ignore next */
310
- (array) => arrayMap(array, () => mathFloor(math.random() * 256));
312
+ (array) => arrayMap(array, () => mathFloor(mathRandom() * 256));
311
313
  const getUniqueId = (length = 16) =>
312
314
  arrayReduce(
313
315
  getRandomValues(new Uint8Array(length)),
@@ -432,7 +434,7 @@ const stampValidate = (stamp, validateThing) =>
432
434
  isArray(stamp) &&
433
435
  size(stamp) == 3 &&
434
436
  isString(stamp[1]) &&
435
- getTypeOf(stamp[2]) == NUMBER &&
437
+ isNumber(stamp[2]) &&
436
438
  isFiniteNumber(stamp[2]) &&
437
439
  validateThing(stamp[0]);
438
440
 
package/metrics/index.js CHANGED
@@ -7,12 +7,12 @@ const AVG = 'avg';
7
7
  const MIN = 'min';
8
8
  const MAX = 'max';
9
9
 
10
+ const math = Math;
10
11
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
11
12
  predicate(value)
12
13
  ? /* istanbul ignore next */
13
14
  otherwise?.()
14
15
  : then(value);
15
- const math = Math;
16
16
  const mathMax = math.max;
17
17
  const mathMin = math.min;
18
18
  const isFiniteNumber = isFinite;
@@ -7,12 +7,12 @@ const AVG = 'avg';
7
7
  const MIN = 'min';
8
8
  const MAX = 'max';
9
9
 
10
+ const math = Math;
10
11
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
11
12
  predicate(value)
12
13
  ? /* istanbul ignore next */
13
14
  otherwise?.()
14
15
  : then(value);
15
- const math = Math;
16
16
  const mathMax = math.max;
17
17
  const mathMin = math.min;
18
18
  const isFiniteNumber = isFinite;