Skip to content

Commit f87a5ef

Browse files
author
abdel-17
committed
update box
1 parent 82a1c74 commit f87a5ef

File tree

2 files changed

+63
-93
lines changed

2 files changed

+63
-93
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,113 @@
1-
import { Derived, Ref } from "./box.svelte.js";
1+
import { box, ref } from "./box.svelte.js";
22

33
describe("box", () => {
44
it("updates when the referenced value updates", () => {
5-
let count = 0;
6-
const box = Ref.to(() => count);
7-
expect(box.current).toBe(0);
5+
let count = $state(0);
6+
const boxed = box(() => count);
7+
expect(boxed.current).toBe(0);
88

99
count = 1;
10-
expect(box.current).toBe(1);
10+
expect(boxed.current).toBe(1);
1111
});
1212

1313
it("creates a readonly box when only a getter is passed", () => {
14-
const box = Ref.to(() => 0);
15-
expect(box.current).toBe(0);
14+
const boxed = box(() => 0);
1615

1716
function set() {
1817
// @ts-expect-error It's readonly
19-
box.current = 1;
18+
boxed.current = 1;
2019
}
2120

2221
expect(set).toThrowError();
2322
});
2423

2524
it("creates a writable box when a getter and setter are passed", () => {
26-
let count = 0;
27-
const box = Ref.to(
25+
let count = $state(0);
26+
const boxed = box(
2827
() => count,
2928
(value) => {
3029
count = value;
3130
}
3231
);
33-
expect(box.current).toBe(0);
32+
expect(boxed.current).toBe(0);
3433

35-
box.current = 1;
36-
expect(box.current).toBe(1);
34+
boxed.current = 1;
35+
expect(boxed.current).toBe(1);
3736
expect(count).toBe(1);
3837

3938
count = 2;
40-
expect(box.current).toBe(2);
39+
expect(boxed.current).toBe(2);
4140
});
4241

43-
it("does not memoize the getter", () => {
44-
const fn = vi.fn(() => 0);
45-
const box = Ref.to(fn);
42+
it("memoizes the getter", () => {
43+
let count = $state(0);
44+
const fn = vi.fn(() => count);
45+
const boxed = box(fn);
4646
expect(fn).not.toHaveBeenCalled();
4747

48-
box.current;
48+
boxed.current;
49+
expect(fn).toHaveBeenCalledTimes(1);
50+
51+
boxed.current;
4952
expect(fn).toHaveBeenCalledTimes(1);
5053

51-
box.current;
54+
count = 1;
55+
boxed.current;
56+
expect(fn).toHaveBeenCalledTimes(2);
57+
58+
boxed.current;
5259
expect(fn).toHaveBeenCalledTimes(2);
5360
});
5461
});
5562

56-
describe("Derived", () => {
63+
describe("ref", () => {
5764
it("updates when the referenced value updates", () => {
58-
let count = $state(0);
59-
const box = Derived.by(() => count);
60-
expect(box.current).toBe(0);
65+
let count = 0;
66+
const boxed = ref(() => count);
67+
expect(boxed.current).toBe(0);
6168

6269
count = 1;
63-
expect(box.current).toBe(1);
70+
expect(boxed.current).toBe(1);
6471
});
6572

6673
it("creates a readonly box when only a getter is passed", () => {
67-
const box = Derived.by(() => 0);
68-
expect(box.current).toBe(0);
74+
const boxed = ref(() => 0);
6975

7076
function set() {
7177
// @ts-expect-error It's readonly
72-
box.current = 1;
78+
boxed.current = 1;
7379
}
7480

7581
expect(set).toThrowError();
7682
});
7783

7884
it("creates a writable box when a getter and setter are passed", () => {
79-
let count = $state(0);
80-
const box = Derived.by(
85+
let count = 0;
86+
const boxed = ref(
8187
() => count,
8288
(value) => {
8389
count = value;
8490
}
8591
);
86-
expect(box.current).toBe(0);
92+
expect(boxed.current).toBe(0);
8793

88-
box.current = 1;
89-
expect(box.current).toBe(1);
94+
boxed.current = 1;
95+
expect(boxed.current).toBe(1);
9096
expect(count).toBe(1);
9197

9298
count = 2;
93-
expect(box.current).toBe(2);
99+
expect(boxed.current).toBe(2);
94100
});
95101

96-
it("memoizes the getter", () => {
97-
let count = $state(0);
98-
const fn = vi.fn(() => count);
99-
const box = Derived.by(fn);
102+
it("does not memoize the getter", () => {
103+
const fn = vi.fn(() => 0);
104+
const boxed = ref(fn);
100105
expect(fn).not.toHaveBeenCalled();
101106

102-
box.current;
103-
expect(fn).toHaveBeenCalledTimes(1);
104-
105-
box.current;
107+
boxed.current;
106108
expect(fn).toHaveBeenCalledTimes(1);
107109

108-
count = 1;
109-
box.current;
110-
expect(fn).toHaveBeenCalledTimes(2);
111-
112-
box.current;
110+
boxed.current;
113111
expect(fn).toHaveBeenCalledTimes(2);
114112
});
115113
});

packages/runed/src/lib/utilities/box/box.svelte.ts

+19-47
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,43 @@ export type WritableBox<T> = {
1111
readonly set: Setter<T>;
1212
};
1313

14-
export class Ref<T> implements Box<T> {
15-
readonly get: Getter<T>;
16-
17-
constructor(get: Getter<T>) {
18-
this.get = get;
19-
}
20-
21-
static to<T>(get: Getter<T>): Box<T>;
22-
static to<T>(get: Getter<T>, set: Setter<T>): WritableBox<T>;
23-
static to<T>(get: Getter<T>, set?: Setter<T>): Box<T> {
24-
if (set !== undefined) {
25-
return new WritableRef(get, set);
26-
}
27-
return new Ref(get);
28-
}
29-
30-
get current(): T {
31-
return this.get();
32-
}
14+
export function box<T>(get: Getter<T>): Box<T>;
15+
export function box<T>(get: Getter<T>, set: Setter<T>): WritableBox<T>;
16+
export function box<T>(get: Getter<T>, set?: Setter<T>): Box<T> {
17+
const current = $derived.by(get);
18+
if (set !== undefined) {
19+
return new WritableRef(() => current, set);
20+
}
21+
return new Ref(() => current);
3322
}
3423

35-
class WritableRef<T> extends Ref<T> implements WritableBox<T> {
36-
readonly set: Setter<T>;
37-
38-
constructor(get: Getter<T>, set: Setter<T>) {
39-
super(get);
40-
this.set = set;
41-
}
42-
43-
get current(): T {
44-
return this.get();
45-
}
46-
47-
set current(value: T) {
48-
this.set(value);
24+
export function ref<T>(get: Getter<T>): Box<T>;
25+
export function ref<T>(get: Getter<T>, set: Setter<T>): WritableBox<T>;
26+
export function ref<T>(get: Getter<T>, set?: Setter<T>): Box<T> {
27+
if (set !== undefined) {
28+
return new WritableRef(get, set);
4929
}
30+
return new Ref(get);
5031
}
5132

52-
export class Derived<T> implements Box<T> {
33+
class Ref<T> {
5334
readonly get: Getter<T>;
5435

5536
constructor(get: Getter<T>) {
56-
const current = $derived.by(get);
57-
this.get = () => current;
58-
}
59-
60-
static by<T>(get: Getter<T>): Derived<T>;
61-
static by<T>(get: Getter<T>, set: Setter<T>): WritableDerived<T>;
62-
static by<T>(get: Getter<T>, set?: Setter<T>): Derived<T> {
63-
if (set !== undefined) {
64-
return new WritableDerived(get, set);
65-
}
66-
return new Derived(get);
37+
this.get = get;
6738
}
6839

6940
get current(): T {
7041
return this.get();
7142
}
7243
}
7344

74-
class WritableDerived<T> extends Derived<T> implements WritableBox<T> {
45+
class WritableRef<T> {
46+
readonly get: Getter<T>;
7547
readonly set: Setter<T>;
7648

7749
constructor(get: Getter<T>, set: Setter<T>) {
78-
super(get);
50+
this.get = get;
7951
this.set = set;
8052
}
8153

0 commit comments

Comments
 (0)