Skip to content

Commit 5d2e235

Browse files
committed
[svelte] useBindableX
1 parent 941e413 commit 5d2e235

File tree

10 files changed

+113
-89
lines changed

10 files changed

+113
-89
lines changed

site/guides/02_building_uis/6_building_uis_with_svelte.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,19 @@ the hook re-fetches automatically when it changes:
8585
Without the `() => rowId` wrapper, changing the `rowId` prop would not cause
8686
the hook to re-read the Store for the new row.
8787

88-
## Writable State With useCellState
88+
## Writable State With useBindableCell
8989

90-
The `useCellState` and `useValueState` hooks expose a writable `current`
90+
The `useBindableCell` and `useBindableValue` hooks expose a writable `current`
9191
property. Writing to it calls `store.setCell()` or `store.setValue()`. This
9292
makes Svelte's `bind:value` directive work for two-way binding:
9393

9494
```svelte
9595
<script>
9696
import {createStore} from 'tinybase';
97-
import {useCellState} from 'tinybase/ui-svelte';
97+
import {useBindableCell} from 'tinybase/ui-svelte';
9898
9999
const store = createStore().setCell('pets', 'fido', 'color', 'brown');
100-
const color = useCellState('pets', 'fido', 'color', store);
100+
const color = useBindableCell('pets', 'fido', 'color', store);
101101
</script>
102102
103103
<input bind:value={color.current} />

site/guides/17_releases.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ underlying TinyBase data changes:
3030
<p>Color: {color.current}</p>
3131
```
3232

33-
The `useCellState` and `useValueState` hooks go further, providing a writable
34-
`current` property that pairs naturally with Svelte's `bind:` directive for
35-
two-way data binding:
33+
The `useBindableCell` and `useBindableValue` hooks go further, providing a
34+
writable `current` property that pairs naturally with Svelte's `bind:`
35+
directive for two-way data binding:
3636

3737
```svelte
3838
<script>
39-
import {useCellState} from 'tinybase/ui-svelte';
39+
import {useBindableCell} from 'tinybase/ui-svelte';
4040
41-
const color = useCellState('pets', 'fido', 'color', store);
41+
const color = useBindableCell('pets', 'fido', 'color', store);
4242
</script>
4343
4444
<input bind:value={color.current} />

src/@types/ui-svelte/docs.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@
13081308
*/
13091309
/// ui-svelte.useCell
13101310
/**
1311-
* The useCellState hook returns a reactive object reflecting the value of a
1311+
* The useBindableCell hook returns a reactive object reflecting the value of a
13121312
* Cell, with a settable `current` property that writes back to the Store.
13131313
* @param tableId The Id of the Table (or a getter returning it).
13141314
* @param rowId The Id of the Row (or a getter returning it).
@@ -1318,7 +1318,7 @@
13181318
* @category Hook
13191319
* @since v8.1.0
13201320
*/
1321-
/// ui-svelte.useCellState
1321+
/// ui-svelte.useBindableCell
13221322
/**
13231323
* The useHasValues hook returns a reactive object indicating whether any Values
13241324
* exist in the Store, and registers a listener so that any changes to that
@@ -1371,15 +1371,15 @@
13711371
*/
13721372
/// ui-svelte.useValue
13731373
/**
1374-
* The useValueState hook returns a reactive object reflecting the value of a
1374+
* The useBindableValue hook returns a reactive object reflecting the value of a
13751375
* Value, with a settable `current` property that writes back to the Store.
13761376
* @param valueId The Id of the Value (or a getter returning it).
13771377
* @param storeOrStoreId The Store to use (plain value or getter), or its Id.
13781378
* @returns A reactive object with gettable and settable `current`.
13791379
* @category Hook
13801380
* @since v8.1.0
13811381
*/
1382-
/// ui-svelte.useValueState
1382+
/// ui-svelte.useBindableValue
13831383
/**
13841384
* The useStore hook returns the default Store from the current Provider context
13851385
* (or a named Store if an Id is provided).

src/@types/ui-svelte/index.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ export function useCell(
528528
storeOrStoreId?: R<Store | Id | undefined>,
529529
): {readonly current: CellOrUndefined};
530530

531-
/// ui-svelte.useCellState
532-
export function useCellState(
531+
/// ui-svelte.useBindableCell
532+
export function useBindableCell(
533533
tableId: R<Id>,
534534
rowId: R<Id>,
535535
cellId: R<Id>,
@@ -563,8 +563,8 @@ export function useValue(
563563
storeOrStoreId?: R<Store | Id | undefined>,
564564
): {readonly current: ValueOrUndefined};
565565

566-
/// ui-svelte.useValueState
567-
export function useValueState(
566+
/// ui-svelte.useBindableValue
567+
export function useBindableValue(
568568
valueId: R<Id>,
569569
storeOrStoreId?: R<Store | Id | undefined>,
570570
): {get current(): ValueOrUndefined; set current(v: Value)};

src/@types/ui-svelte/with-schemas/index.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
405405
readonly current: NoInfer<CellOrUndefined<Schemas[0], TableId, CellId>>;
406406
};
407407

408-
/// ui-svelte.useCellState
409-
useCellState: <
408+
/// ui-svelte.useBindableCell
409+
useBindableCell: <
410410
TableId extends TableIdFromSchema<Schemas[0]>,
411411
CellId extends CellIdFromSchema<Schemas[0], TableId>,
412412
>(
@@ -458,8 +458,8 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
458458
readonly current: NoInfer<DefaultedValueFromSchema<Schemas[1], ValueId>>;
459459
};
460460

461-
/// ui-svelte.useValueState
462-
useValueState: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
461+
/// ui-svelte.useBindableValue
462+
useBindableValue: <ValueId extends ValueIdFromSchema<Schemas[1]>>(
463463
valueId: ValueId | (() => ValueId),
464464
storeOrStoreId?: Store<Schemas> | Id,
465465
) => {

src/ui-svelte/hooks.svelte.ts

Lines changed: 80 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,17 @@ const useListenable = <T>(
155155
let value = $state<T>(
156156
(getThing()?.[getMethod]?.(...getArgs()) ?? defaultValue) as T,
157157
);
158-
$effect(() => {
159-
const thing = getThing();
160-
const args = getArgs();
161-
value = (thing?.[getMethod]?.(...args) ?? defaultValue) as T;
162-
const listenerId = thing?.[addMethod]?.(...args, () => {
163-
value = (thing[getMethod](...getArgs()) ?? defaultValue) as T;
158+
if (typeof window !== 'undefined') {
159+
$effect(() => {
160+
const thing = getThing();
161+
const args = getArgs();
162+
value = (thing?.[getMethod]?.(...args) ?? defaultValue) as T;
163+
const listenerId = thing?.[addMethod]?.(...args, () => {
164+
value = (thing[getMethod](...getArgs()) ?? defaultValue) as T;
165+
});
166+
return () => thing?.delListener?.(listenerId);
164167
});
165-
return () => thing?.delListener?.(listenerId);
166-
});
168+
}
167169
return {
168170
get current(): T {
169171
return value as T;
@@ -311,7 +313,7 @@ export const useCell = (
311313
rv(cellId),
312314
]);
313315

314-
export const useCellState = (
316+
export const useBindableCell = (
315317
tableId: R<Id>,
316318
rowId: R<Id>,
317319
cellId: R<Id>,
@@ -321,17 +323,19 @@ export const useCellState = (
321323
let value = $state<CellOrUndefined>(
322324
getS()?.getCell(rv(tableId), rv(rowId), rv(cellId)),
323325
);
324-
$effect(() => {
325-
const s: any = getS();
326-
const t = rv(tableId),
327-
r = rv(rowId),
328-
c = rv(cellId);
329-
value = s?.getCell(t, r, c);
330-
const listenerId = s?.addCellListener(t, r, c, (st: any) => {
331-
value = st.getCell(rv(tableId), rv(rowId), rv(cellId));
326+
if (typeof window !== 'undefined') {
327+
$effect(() => {
328+
const s: any = getS();
329+
const t = rv(tableId),
330+
r = rv(rowId),
331+
c = rv(cellId);
332+
value = s?.getCell(t, r, c);
333+
const listenerId = s?.addCellListener(t, r, c, (st: any) => {
334+
value = st.getCell(rv(tableId), rv(rowId), rv(cellId));
335+
});
336+
return () => s?.delListener?.(listenerId);
332337
});
333-
return () => s?.delListener?.(listenerId);
334-
});
338+
}
335339
return {
336340
get current(): CellOrUndefined {
337341
return value;
@@ -367,21 +371,23 @@ export const useValue = (
367371
): {readonly current: ValueOrUndefined} =>
368372
useGet(sg(storeOrStoreId), VALUE, undefined, () => [rv(valueId)]);
369373

370-
export const useValueState = (
374+
export const useBindableValue = (
371375
valueId: R<Id>,
372376
storeOrStoreId?: R<Store | Id | undefined>,
373377
): {get current(): ValueOrUndefined; set current(v: Value)} => {
374378
const getS = sg(storeOrStoreId);
375379
let value = $state<ValueOrUndefined>(getS()?.getValue(rv(valueId)));
376-
$effect(() => {
377-
const s: any = getS();
378-
const vid = rv(valueId);
379-
value = s?.getValue(vid);
380-
const listenerId = s?.addValueListener(vid, (st: any) => {
381-
value = st.getValue(rv(valueId));
380+
if (typeof window !== 'undefined') {
381+
$effect(() => {
382+
const s: any = getS();
383+
const vid = rv(valueId);
384+
value = s?.getValue(vid);
385+
const listenerId = s?.addValueListener(vid, (st: any) => {
386+
value = st.getValue(rv(valueId));
387+
});
388+
return () => s?.delListener?.(listenerId);
382389
});
383-
return () => s?.delListener?.(listenerId);
384-
});
390+
}
385391
return {
386392
get current(): ValueOrUndefined {
387393
return value;
@@ -398,9 +404,11 @@ export const useStore = (id?: Id): Store | undefined =>
398404
export const useStoreIds = (): {readonly current: Ids} => {
399405
const ctx = getCtx();
400406
let ids = $state<Ids>(getThingIds(ctx, OFFSET_STORE));
401-
$effect(() => {
402-
ids = getThingIds(ctx, OFFSET_STORE);
403-
});
407+
if (typeof window !== 'undefined') {
408+
$effect(() => {
409+
ids = getThingIds(ctx, OFFSET_STORE);
410+
});
411+
}
404412
return {
405413
get current() {
406414
return ids;
@@ -414,9 +422,11 @@ export const useMetrics = (id?: Id): Metrics | undefined =>
414422
export const useMetricsIds = (): {readonly current: Ids} => {
415423
const ctx = getCtx();
416424
let ids = $state<Ids>(getThingIds(ctx, OFFSET_METRICS));
417-
$effect(() => {
418-
ids = getThingIds(ctx, OFFSET_METRICS);
419-
});
425+
if (typeof window !== 'undefined') {
426+
$effect(() => {
427+
ids = getThingIds(ctx, OFFSET_METRICS);
428+
});
429+
}
420430
return {
421431
get current() {
422432
return ids;
@@ -441,9 +451,11 @@ export const useIndexes = (id?: Id): Indexes | undefined =>
441451
export const useIndexesIds = (): {readonly current: Ids} => {
442452
const ctx = getCtx();
443453
let ids = $state<Ids>(getThingIds(ctx, OFFSET_INDEXES));
444-
$effect(() => {
445-
ids = getThingIds(ctx, OFFSET_INDEXES);
446-
});
454+
if (typeof window !== 'undefined') {
455+
$effect(() => {
456+
ids = getThingIds(ctx, OFFSET_INDEXES);
457+
});
458+
}
447459
return {
448460
get current() {
449461
return ids;
@@ -478,9 +490,11 @@ export const useQueries = (id?: Id): Queries | undefined =>
478490
export const useQueriesIds = (): {readonly current: Ids} => {
479491
const ctx = getCtx();
480492
let ids = $state<Ids>(getThingIds(ctx, OFFSET_QUERIES));
481-
$effect(() => {
482-
ids = getThingIds(ctx, OFFSET_QUERIES);
483-
});
493+
if (typeof window !== 'undefined') {
494+
$effect(() => {
495+
ids = getThingIds(ctx, OFFSET_QUERIES);
496+
});
497+
}
484498
return {
485499
get current() {
486500
return ids;
@@ -577,9 +591,11 @@ export const useRelationships = (id?: Id): Relationships | undefined =>
577591
export const useRelationshipsIds = (): {readonly current: Ids} => {
578592
const ctx = getCtx();
579593
let ids = $state<Ids>(getThingIds(ctx, OFFSET_RELATIONSHIPS));
580-
$effect(() => {
581-
ids = getThingIds(ctx, OFFSET_RELATIONSHIPS);
582-
});
594+
if (typeof window !== 'undefined') {
595+
$effect(() => {
596+
ids = getThingIds(ctx, OFFSET_RELATIONSHIPS);
597+
});
598+
}
583599
return {
584600
get current() {
585601
return ids;
@@ -630,9 +646,11 @@ export const useCheckpoints = (id?: Id): Checkpoints | undefined =>
630646
export const useCheckpointsIds = (): {readonly current: Ids} => {
631647
const ctx = getCtx();
632648
let ids = $state<Ids>(getThingIds(ctx, OFFSET_CHECKPOINTS));
633-
$effect(() => {
634-
ids = getThingIds(ctx, OFFSET_CHECKPOINTS);
635-
});
649+
if (typeof window !== 'undefined') {
650+
$effect(() => {
651+
ids = getThingIds(ctx, OFFSET_CHECKPOINTS);
652+
});
653+
}
636654
return {
637655
get current() {
638656
return ids;
@@ -677,9 +695,11 @@ export const usePersister = (id?: Id): AnyPersister | undefined =>
677695
export const usePersisterIds = (): {readonly current: Ids} => {
678696
const ctx = getCtx();
679697
let ids = $state<Ids>(getThingIds(ctx, OFFSET_PERSISTER));
680-
$effect(() => {
681-
ids = getThingIds(ctx, OFFSET_PERSISTER);
682-
});
698+
if (typeof window !== 'undefined') {
699+
$effect(() => {
700+
ids = getThingIds(ctx, OFFSET_PERSISTER);
701+
});
702+
}
683703
return {
684704
get current() {
685705
return ids;
@@ -698,9 +718,11 @@ export const useSynchronizer = (id?: Id): Synchronizer | undefined =>
698718
export const useSynchronizerIds = (): {readonly current: Ids} => {
699719
const ctx = getCtx();
700720
let ids = $state<Ids>(getThingIds(ctx, OFFSET_SYNCHRONIZER));
701-
$effect(() => {
702-
ids = getThingIds(ctx, OFFSET_SYNCHRONIZER);
703-
});
721+
if (typeof window !== 'undefined') {
722+
$effect(() => {
723+
ids = getThingIds(ctx, OFFSET_SYNCHRONIZER);
724+
});
725+
}
704726
return {
705727
get current() {
706728
return ids;
@@ -715,10 +737,12 @@ export const useSynchronizerStatus = (
715737

716738
const injectThing = (offset: number, id: Id, thing: any): void => {
717739
const ctx = getCtx();
718-
$effect(() => {
719-
ctx[16]?.(offset, id, thing);
720-
return () => ctx[17]?.(offset, id);
721-
});
740+
if (typeof window !== 'undefined') {
741+
$effect(() => {
742+
ctx[16]?.(offset, id, thing);
743+
return () => ctx[17]?.(offset, id);
744+
});
745+
}
722746
};
723747

724748
export const provideStore = (storeId: Id, store: Store): void =>

src/ui-svelte/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export {
1414
provideSynchronizer,
1515
useCell,
1616
useCellIds,
17-
useCellState,
17+
useBindableCell,
1818
useCheckpoint,
1919
useCheckpointIds,
2020
useCheckpoints,
@@ -72,7 +72,7 @@ export {
7272
useTables,
7373
useValue,
7474
useValueIds,
75-
useValueState,
75+
useBindableValue,
7676
useValues,
7777
} from './hooks.svelte.ts';
7878
export {default as IndexView} from './IndexView.svelte';

test/unit/core/ui-svelte/helpers/HookCellState.svelte renamed to test/unit/core/ui-svelte/helpers/HookBindableCell.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import {useCellState} from 'tinybase/ui-svelte';
2+
import {useBindableCell} from 'tinybase/ui-svelte';
33
import type {Id} from 'tinybase';
44
import type {Store} from 'tinybase';
55
import type {Cell} from 'tinybase';
@@ -17,7 +17,7 @@
1717
cellId: Id;
1818
newValue?: Cell;
1919
} = $props();
20-
const v = useCellState(
20+
const v = useBindableCell(
2121
() => tableId,
2222
() => rowId,
2323
() => cellId,

0 commit comments

Comments
 (0)