tinywidgets 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/bun.lock +778 -0
  2. package/eslint.config.js +0 -41
  3. package/package.json +14 -14
  4. package/src/common/functions.tsx +2 -2
  5. package/src/components/App/index.css.ts +22 -1
  6. package/src/components/App/index.tsx +26 -6
  7. package/src/components/Button/index.css.ts +1 -1
  8. package/src/components/Button/index.tsx +99 -102
  9. package/src/components/Card/index.css.ts +1 -1
  10. package/src/components/Card/index.tsx +1 -2
  11. package/src/components/Code/index.css.ts +1 -1
  12. package/src/components/Code/index.tsx +0 -1
  13. package/src/components/Collapsible/index.css.ts +1 -1
  14. package/src/components/Collapsible/index.tsx +3 -3
  15. package/src/components/Detail/index.css.ts +1 -1
  16. package/src/components/Detail/index.tsx +1 -2
  17. package/src/components/Hr/index.css.ts +1 -1
  18. package/src/components/Hr/index.tsx +0 -1
  19. package/src/components/Image/index.css.ts +1 -1
  20. package/src/components/Image/index.tsx +1 -1
  21. package/src/components/Metric/index.tsx +1 -2
  22. package/src/components/Row/index.css.ts +1 -1
  23. package/src/components/Row/index.tsx +1 -2
  24. package/src/components/Summary/index.css.ts +1 -1
  25. package/src/components/Summary/index.tsx +1 -2
  26. package/src/components/Tag/index.css.ts +1 -1
  27. package/src/components/Tag/index.tsx +1 -2
  28. package/src/css/dimensions.css.ts +2 -0
  29. package/src/css/global.css.ts +1 -1
  30. package/src/index.css.ts +1 -1
  31. package/src/index.ts +2 -8
  32. package/src/stores/LocalStore.tsx +1 -1
  33. package/src/stores/RouteStore.tsx +1 -1
  34. package/src/stores/SessionStore.tsx +1 -1
  35. package/tsconfig.json +1 -1
  36. package/bun.lockb +0 -0
  37. package/src/components/TasksProvider/index.tsx +0 -309
@@ -1,5 +1,5 @@
1
- import {small} from '../common/functions';
2
1
  import {globalStyle} from '@vanilla-extract/css';
2
+ import {small} from '../common/functions';
3
3
 
4
4
  globalStyle('*', {
5
5
  margin: 0,
package/src/index.css.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import './css/global.css.ts';
2
2
 
3
- export {colors} from './css/colors.css.ts';
4
3
  export {code} from './css/code.css.ts';
4
+ export {colors} from './css/colors.css.ts';
5
5
  export {dimensions} from './css/dimensions.css.ts';
6
6
  export {screens} from './css/screens.ts';
package/src/index.ts CHANGED
@@ -10,13 +10,7 @@ export {Metric} from './components/Metric/index.tsx';
10
10
  export {Row} from './components/Row/index.tsx';
11
11
  export {Summary} from './components/Summary/index.tsx';
12
12
  export {Tag} from './components/Tag/index.tsx';
13
- export {
14
- TasksProvider,
15
- useScheduleTask,
16
- } from './components/TasksProvider/index.tsx';
17
13
 
18
- export {useRoute, useSetRouteCallback} from './stores/RouteStore.tsx';
19
- export {useDark} from './stores/LocalStore.tsx';
20
14
  export {classNames} from './common/functions.tsx';
21
-
22
- export type {ScheduleTask} from './components/TasksProvider/index.tsx';
15
+ export {useDark} from './stores/LocalStore.tsx';
16
+ export {useRoute, useSetRouteCallback} from './stores/RouteStore.tsx';
@@ -1,8 +1,8 @@
1
- import {CHANGE, READY, READY_SCHEMA} from './common';
2
1
  import {useCallback, useEffect} from 'react';
3
2
  import {createLocalPersister} from 'tinybase/persisters/persister-browser/with-schemas';
4
3
  import * as UiReact from 'tinybase/ui-react/with-schemas';
5
4
  import {type NoTablesSchema, createStore} from 'tinybase/with-schemas';
5
+ import {CHANGE, READY, READY_SCHEMA} from './common';
6
6
 
7
7
  const PREFERS_DARK = matchMedia?.('(prefers-color-scheme: dark)');
8
8
 
@@ -1,7 +1,7 @@
1
- import {READY, READY_SCHEMA} from './common';
2
1
  import {createCustomPersister} from 'tinybase/persisters/with-schemas';
3
2
  import * as UiReact from 'tinybase/ui-react/with-schemas';
4
3
  import {type NoTablesSchema, createStore} from 'tinybase/with-schemas';
4
+ import {READY, READY_SCHEMA} from './common';
5
5
 
6
6
  const ROUTE_STORE = 'tinywidgets/Route';
7
7
  const ROUTE = 'route';
@@ -1,7 +1,7 @@
1
- import {READY, READY_SCHEMA} from './common';
2
1
  import {createSessionPersister} from 'tinybase/persisters/persister-browser/with-schemas';
3
2
  import * as UiReact from 'tinybase/ui-react/with-schemas';
4
3
  import {createStore} from 'tinybase/with-schemas';
4
+ import {READY, READY_SCHEMA} from './common';
5
5
 
6
6
  const SESSION_STORE = 'tinywidgets/Session';
7
7
  const COLLAPSIBLE = 'collapsible';
package/tsconfig.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "resolveJsonModule": true,
11
11
  "isolatedModules": true,
12
12
  "noEmit": true,
13
- "jsx": "react",
13
+ "jsx": "react-jsx",
14
14
  "strict": true,
15
15
  "noUnusedLocals": true,
16
16
  "noUnusedParameters": true,
package/bun.lockb DELETED
Binary file
@@ -1,309 +0,0 @@
1
- import React, {
2
- ReactNode,
3
- createContext,
4
- useCallback,
5
- useContext,
6
- useEffect,
7
- useRef,
8
- } from 'react';
9
- import type {Store} from 'tinybase';
10
- import {createLocalPersister} from 'tinybase/persisters/persister-browser/with-schemas';
11
- import type {Persister} from 'tinybase/persisters/with-schemas';
12
- import {
13
- Provider as UiReactProvider,
14
- useStore,
15
- useStores,
16
- } from 'tinybase/ui-react';
17
- import * as UiReact from 'tinybase/ui-react/with-schemas';
18
- import type {Id, Store as StoreWithSchemas} from 'tinybase/with-schemas';
19
- import {createStore} from 'tinybase/with-schemas';
20
-
21
- export type Task =
22
- | ((
23
- arg: string,
24
- store: Store | undefined,
25
- scheduleTask: ScheduleTask,
26
- ) => void)
27
- | ((
28
- arg: string,
29
- store: StoreWithSchemas<any> | undefined,
30
- scheduleTask: ScheduleTask,
31
- ) => void)
32
- | ((
33
- arg: string,
34
- store: Store | undefined,
35
- scheduleTask: ScheduleTask,
36
- ) => Promise<void>)
37
- | ((
38
- arg: string,
39
- store: StoreWithSchemas<any> | undefined,
40
- scheduleTask: ScheduleTask,
41
- ) => Promise<void>);
42
- export type Tasks = {
43
- [taskId: string]: Task;
44
- };
45
- export type ScheduleTask = (taskId: Id, arg?: string, storeId?: string) => void;
46
-
47
- const STORE_ID = 'tinywidgets/Tasks';
48
- const TABLE_ID = 'tasks';
49
-
50
- const TABLES_SCHEMA = {
51
- tasks: {
52
- taskId: {type: 'string', default: ''},
53
- arg: {type: 'string'},
54
- storeId: {type: 'string'},
55
- running: {type: 'boolean'},
56
- expires: {type: 'number', default: 0},
57
- },
58
- } as const;
59
- const VALUES_SCHEMA = {} as const;
60
- type Schemas = [typeof TABLES_SCHEMA, typeof VALUES_SCHEMA];
61
- const {useCreateStore, useCreatePersister} =
62
- UiReact as UiReact.WithSchemas<Schemas>;
63
-
64
- const Context = createContext<ScheduleTask>(() => {});
65
-
66
- const TaskRunner = ({
67
- tasks,
68
- tasksStore,
69
- interval,
70
- }: {
71
- readonly tasks: Tasks;
72
- readonly tasksStore: StoreWithSchemas<Schemas>;
73
- readonly interval: number;
74
- }) => {
75
- const store = useStore();
76
- const stores = useStores();
77
- const scheduleTask = useContext(Context);
78
- useEffect(() => {
79
- const nextJob = async () => {
80
- const jobId = tasksStore.getRowIds(TABLE_ID)[0];
81
- if (jobId != null) {
82
- const {taskId, arg, storeId, running, expires} = tasksStore.getRow(
83
- TABLE_ID,
84
- jobId,
85
- );
86
- if (expires > Date.now()) {
87
- const task = tasks[taskId];
88
- if (task && !running) {
89
- tasksStore.setCell(TABLE_ID, jobId, 'running', true);
90
- try {
91
- await task(
92
- arg ?? '',
93
- storeId == null ? store : (stores[storeId] as any),
94
- scheduleTask,
95
- );
96
- } catch {}
97
- tasksStore.delRow(TABLE_ID, jobId);
98
- }
99
- } else {
100
- tasksStore.delRow(TABLE_ID, jobId);
101
- }
102
- }
103
- };
104
- const intervalHandle = setInterval(nextJob, interval * 1000);
105
- return () => clearInterval(intervalHandle);
106
- // eslint-disable-next-line react-hooks/exhaustive-deps
107
- }, [tasksStore, JSON.stringify(Object.keys(stores))]);
108
-
109
- return null;
110
- };
111
-
112
- /**
113
- * The useScheduleTask hook returns a function that can be used to schedule a
114
- * new task.
115
- *
116
- * The returned function takes the following arguments:
117
- *
118
- * - `taskId`: a required string to identify the task by Id.
119
- * - `arg`: an optional string that will be passed to the task when run.
120
- * - `storeId`: an optional string that will be used to look up a Store by Id in
121
- * the current TinyBase Provider context and be passed to the task.
122
- *
123
- * @example
124
- * ```tsx
125
- * const TaskButton = () => {
126
- * const scheduleTask = useScheduleTask();
127
- * return (<Button
128
- * title="Hello"
129
- * onClick={() => scheduleTask('greet', 'Hello')}
130
- * />);
131
- * };
132
- * // ...
133
- * <TasksProvider tasks={{greet: (arg: string) => alert(arg)}}>
134
- * <TaskButton />
135
- * </TasksProvider>
136
- * ```
137
- * This example shows the hook returning a function that will schedule a task to
138
- * be run by the provider. Note that it may take as long as a second (the
139
- * default interval between task executions) for the alert to appear.
140
- * @example
141
- * ```tsx
142
- * const TaskButton2 = () => {
143
- * const scheduleTask = useScheduleTask();
144
- * return (<Button
145
- * iconRight={Lucide.Globe}
146
- * title="Hello"
147
- * onClick={() => scheduleTask('greet1', 'Hello')}
148
- * />);
149
- * };
150
- * // ...
151
- * <TasksProvider tasks={{
152
- * greet1: async (arg: string, _: unknown, scheduleTask: ScheduleTask) => {
153
- * scheduleTask('greet2', 'World');
154
- * alert(arg);
155
- * },
156
- * greet2: (arg: string) => alert(arg)
157
- * }}>
158
- * <TaskButton2 />
159
- * </TasksProvider>
160
- * ```
161
- * This example shows the hook returning a function that will schedule a task to
162
- * be run by the provider. That task in turn will call another.
163
- * @example
164
- * ```tsx
165
- * const TaskButton3 = () => {
166
- * const scheduleTask = useScheduleTask();
167
- * return (<Button
168
- * title="JSON"
169
- * onClick={() => scheduleTask('json', '', 'store1')}
170
- * />);
171
- * };
172
- * // ...
173
- * <Provider storesById={{
174
- * store1: useCreateStore(() =>
175
- * createStore().setCell('pets', 'fido', 'species', 'dog')),
176
- * }}>
177
- * <TasksProvider tasks={{
178
- * json: (_arg: string, store: Store | undefined) =>
179
- * alert(store?.getJson()),
180
- * }}>
181
- * <TaskButton3 />
182
- * </TasksProvider>
183
- * </Provider>
184
- * ```
185
- * This example shows the hook returning a function that will schedule a task to
186
- * be run by the provider, using a Store from the current context, specified by
187
- * Id.
188
- */
189
- export const useScheduleTask = () => useContext(Context);
190
-
191
- /**
192
- * The `TasksProvider` component is a non-visual component that makes it easy to
193
- * manage sequential tasks in your TinyWidget application.
194
- *
195
- * @param props The props for the component.
196
- * @returns The TasksProvider component.
197
- * @icon Lucide.FileClock
198
- * @example
199
- * ```tsx
200
- * const TaskButton1 = () => {
201
- * const scheduleTask = useScheduleTask();
202
- * return (<Button
203
- * iconRight={Lucide.Hand}
204
- * title="Hello"
205
- * onClick={() => scheduleTask('greet1')}
206
- * />);
207
- * };
208
- * const TaskButton2 = () => {
209
- * const scheduleTask = useScheduleTask();
210
- * return (<Button
211
- * iconRight={Lucide.Globe}
212
- * title="World"
213
- * onClick={() => scheduleTask('greet2')}
214
- * />);
215
- * };
216
- * // ...
217
- * <TasksProvider tasks={{
218
- * greet1: () => alert('Hello'),
219
- * greet2: () => alert('World'),
220
- * }}>
221
- * <TaskButton1 />
222
- * <TaskButton2 />
223
- * </TasksProvider>
224
- * ```
225
- * This example shows the hook returning a function that will schedule a task to
226
- * be run by the provider. That task in turn will call another.
227
- */
228
- export const TasksProvider = ({
229
- tasks,
230
- interval = 1,
231
- expiry = 5,
232
- children,
233
- }: {
234
- /**
235
- * An object listing all the tasks that can be executed, keyed by Id.
236
- *
237
- * Each task is a function that receives a string argument, a reference to a
238
- * Store (each as specified when `scheduleTask` was called), and a reference
239
- * to the `scheduleTask` function again so that tasks can be chained.
240
- *
241
- * A task can be asynchronous.
242
- */
243
- readonly tasks: Tasks;
244
- /**
245
- * The interval in seconds between each task execution, defaulting to 1.
246
- */
247
- readonly interval?: number;
248
- /**
249
- * The time in seconds from scheduling until a task expires and will not be
250
- * started, defaulting to 5.
251
- */
252
- readonly expiry?: number;
253
- /**
254
- * The children of the component to be rendered.
255
- */
256
- readonly children: ReactNode;
257
- }) => {
258
- const pendingAddedJobs = useRef<
259
- [taskId: string, arg?: string, storeId?: string][]
260
- >([]);
261
- const activePersister = useRef<Persister<Schemas> | undefined>(undefined);
262
-
263
- const tasksStore = useCreateStore(() =>
264
- createStore().setSchema(TABLES_SCHEMA, VALUES_SCHEMA),
265
- );
266
-
267
- useCreatePersister(
268
- tasksStore,
269
- (tasksStore) => createLocalPersister(tasksStore, STORE_ID),
270
- [],
271
- async (persister) => {
272
- await persister.startAutoLoad();
273
- tasksStore.forEachRow('tasks', (taskId, _) =>
274
- tasksStore.delCell('tasks', taskId, 'running'),
275
- );
276
- await persister.startAutoSave();
277
- activePersister.current = persister;
278
- pendingAddedJobs.current.forEach((pendingAddedJob) =>
279
- scheduleTask(...pendingAddedJob),
280
- );
281
- pendingAddedJobs.current.splice(0);
282
- },
283
- );
284
-
285
- const scheduleTask: ScheduleTask = useCallback(
286
- (taskId: string, arg?: string, storeId?: string) => {
287
- if (activePersister.current) {
288
- tasksStore.addRow(TABLE_ID, {
289
- taskId,
290
- expires: Date.now() + expiry * 1000,
291
- arg,
292
- storeId,
293
- });
294
- } else {
295
- pendingAddedJobs.current.push([taskId, arg, storeId]);
296
- }
297
- },
298
- [tasksStore, expiry],
299
- );
300
-
301
- return (
302
- <Context.Provider value={scheduleTask}>
303
- <UiReactProvider>
304
- {children}
305
- <TaskRunner tasks={tasks} tasksStore={tasksStore} interval={interval} />
306
- </UiReactProvider>
307
- </Context.Provider>
308
- );
309
- };