@manyducks.co/dolla 2.0.0-alpha.9 → 2.0.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.
- package/README.md +222 -512
- package/dist/core/app.d.ts +24 -0
- package/dist/core/context.d.ts +147 -0
- package/dist/core/env.d.ts +3 -0
- package/dist/core/hooks.d.ts +70 -0
- package/dist/core/hooks.test.d.ts +1 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/logger.d.ts +42 -0
- package/dist/core/logger.test.d.ts +0 -0
- package/dist/core/markup.d.ts +82 -0
- package/dist/core/markup.test.d.ts +0 -0
- package/dist/core/nodes/_markup.d.ts +36 -0
- package/dist/core/nodes/dom.d.ts +13 -0
- package/dist/core/nodes/dynamic.d.ts +22 -0
- package/dist/core/nodes/element.d.ts +27 -0
- package/dist/core/nodes/portal.d.ts +18 -0
- package/dist/core/nodes/repeat.d.ts +27 -0
- package/dist/core/nodes/view.d.ts +25 -0
- package/dist/core/ref.d.ts +19 -0
- package/dist/core/ref.test.d.ts +1 -0
- package/dist/core/signals.d.ts +100 -0
- package/dist/core/signals.test.d.ts +1 -0
- package/dist/{views → core/views}/default-crash-view.d.ts +11 -4
- package/dist/core/views/for.d.ts +21 -0
- package/dist/core/views/fragment.d.ts +7 -0
- package/dist/core/views/portal.d.ts +16 -0
- package/dist/core/views/show.d.ts +25 -0
- package/dist/fragment-BahD_BJA.js +7 -0
- package/dist/fragment-BahD_BJA.js.map +1 -0
- package/dist/{modules/http.d.ts → http/index.d.ts} +3 -5
- package/dist/http.js +150 -0
- package/dist/http.js.map +1 -0
- package/dist/i18n/index.d.ts +134 -0
- package/dist/i18n.js +309 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index-DRJlxs-Q.js +535 -0
- package/dist/index-DRJlxs-Q.js.map +1 -0
- package/dist/index.js +160 -1414
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +3 -2
- package/dist/jsx-dev-runtime.js +5 -12
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +4 -3
- package/dist/jsx-runtime.js +9 -15
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/logger-Aqi9m1CF.js +565 -0
- package/dist/logger-Aqi9m1CF.js.map +1 -0
- package/dist/markup-8jNhoqDe.js +1089 -0
- package/dist/markup-8jNhoqDe.js.map +1 -0
- package/dist/router/hooks.d.ts +2 -0
- package/dist/router/index.d.ts +3 -0
- package/dist/router/router.d.ts +166 -0
- package/dist/{routing.d.ts → router/router.utils.d.ts} +17 -3
- package/dist/router/router.utils.test.d.ts +1 -0
- package/dist/router.js +6 -0
- package/dist/router.js.map +1 -0
- package/dist/typeChecking-5kmX0ulW.js +65 -0
- package/dist/typeChecking-5kmX0ulW.js.map +1 -0
- package/dist/typeChecking.d.ts +2 -98
- package/dist/typeChecking.test.d.ts +1 -0
- package/dist/types.d.ts +97 -25
- package/dist/utils.d.ts +25 -3
- package/docs/buildless.md +132 -0
- package/docs/components.md +238 -0
- package/docs/hooks.md +356 -0
- package/docs/http.md +178 -0
- package/docs/i18n.md +220 -0
- package/docs/index.md +10 -0
- package/docs/markup.md +136 -0
- package/docs/mixins.md +176 -0
- package/docs/ref.md +77 -0
- package/docs/router.md +281 -0
- package/docs/setup.md +137 -0
- package/docs/signals.md +262 -0
- package/docs/stores.md +113 -0
- package/docs/views.md +356 -0
- package/index.d.ts +2 -2
- package/notes/atomic.md +452 -0
- package/notes/elimination.md +33 -0
- package/notes/observable.md +180 -0
- package/notes/scratch.md +346 -14
- package/notes/splitting.md +5 -0
- package/package.json +29 -15
- package/vite.config.js +5 -11
- package/build.js +0 -34
- package/dist/index.d.ts +0 -21
- package/dist/markup.d.ts +0 -108
- package/dist/modules/dolla.d.ts +0 -111
- package/dist/modules/i18n.d.ts +0 -59
- package/dist/modules/render.d.ts +0 -17
- package/dist/modules/router.d.ts +0 -152
- package/dist/nodes/cond.d.ts +0 -26
- package/dist/nodes/html.d.ts +0 -31
- package/dist/nodes/observer.d.ts +0 -29
- package/dist/nodes/outlet.d.ts +0 -22
- package/dist/nodes/portal.d.ts +0 -19
- package/dist/nodes/repeat.d.ts +0 -34
- package/dist/nodes/text.d.ts +0 -19
- package/dist/passthrough-9kwwjgWk.js +0 -1279
- package/dist/passthrough-9kwwjgWk.js.map +0 -1
- package/dist/state.d.ts +0 -101
- package/dist/view.d.ts +0 -65
- package/dist/views/passthrough.d.ts +0 -5
- package/notes/context-vars.md +0 -21
- package/notes/readme-scratch.md +0 -222
- package/notes/route-middleware.md +0 -42
- package/tests/state.test.js +0 -135
- /package/dist/{routing.test.d.ts → core/context.test.d.ts} +0 -0
package/notes/scratch.md
CHANGED
|
@@ -1,5 +1,188 @@
|
|
|
1
1
|
# Scratch Note
|
|
2
2
|
|
|
3
|
+
## Dolla Custom Elements
|
|
4
|
+
|
|
5
|
+
Define custom HTML elements with Dolla.
|
|
6
|
+
|
|
7
|
+
```jsx
|
|
8
|
+
defineElement("my-counter", {
|
|
9
|
+
props: {
|
|
10
|
+
// Defines props and their types
|
|
11
|
+
},
|
|
12
|
+
setup: (props, ctx) => {
|
|
13
|
+
// Returns markup (this is a view)
|
|
14
|
+
return html` <div></div> `;
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Rendering standalone elements outside an app
|
|
22
|
+
|
|
23
|
+
Library needs to be easier to render standalone elements. Idea to replace constructView and a lot of the store management weirdness with a `createContext` function and a `render` function that takes markup and a context.
|
|
24
|
+
|
|
25
|
+
The context is basically a refactor of the old ElementContext and serves the same purpose.
|
|
26
|
+
|
|
27
|
+
```jsx
|
|
28
|
+
import { m, render, createContext } from "@manyducks.co/dolla";
|
|
29
|
+
|
|
30
|
+
const context = createContext();
|
|
31
|
+
context.addStore(SomeStore);
|
|
32
|
+
|
|
33
|
+
function ExampleView(props, ctx) {
|
|
34
|
+
// Views now access the Context directly.
|
|
35
|
+
const store = ctx.getStore(SomeStore);
|
|
36
|
+
|
|
37
|
+
return <h1>Hello World</h1>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const element = render(ExampleView, context);
|
|
41
|
+
|
|
42
|
+
element.mount(document.body);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Monomorphic app context
|
|
48
|
+
|
|
49
|
+
> Replaces StoreContext, ViewContext, etc.
|
|
50
|
+
|
|
51
|
+
Routes are baked into the app once again, but
|
|
52
|
+
|
|
53
|
+
```jsx
|
|
54
|
+
import { createRoot } from "@manyducks.co/dolla";
|
|
55
|
+
import { example } from "./stores/example.js";
|
|
56
|
+
|
|
57
|
+
const root = createRoot();
|
|
58
|
+
|
|
59
|
+
root.use(example());
|
|
60
|
+
|
|
61
|
+
async function auth(_, state, redirect) {
|
|
62
|
+
// route context
|
|
63
|
+
// Routes run through each callback until one resolves to a renderable value.
|
|
64
|
+
// If redirect is called, the route is re-matched and no further callbacks are run for this route.
|
|
65
|
+
|
|
66
|
+
if (state.auth == null) {
|
|
67
|
+
redirect("/login");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
root.route("/users/*", auth, (C) => {
|
|
72
|
+
C.route("/{#id}/*", (C) => {
|
|
73
|
+
C.route("/", (C) => <UserDetailRoute userId={C.params.id} />);
|
|
74
|
+
C.route("*", "./");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
root.route("/users/*", auth, (route) => {
|
|
79
|
+
route("/{#id}/*", (route) => {
|
|
80
|
+
// TODO: It's possible to reference the wrong 'route'
|
|
81
|
+
// Track active context and throw error if the one you call belongs to the wrong context?
|
|
82
|
+
route("/", (_, state) => <UserDetailView userId={state.params.id} />);
|
|
83
|
+
route("*", "./");
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
function ExampleView(props, ctx) {
|
|
88
|
+
// ctx.routes returns a special type of outlet that renders children based on
|
|
89
|
+
// the route segments that come after the ones at this ctx.
|
|
90
|
+
|
|
91
|
+
// The weakness of this idea is that routes can't be validated without initializing views.
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
<Suspense fallback={<span>Loading...</span>}>
|
|
95
|
+
{ctx.routes((route) => {
|
|
96
|
+
route("/subroute", () => <OtherView />);
|
|
97
|
+
|
|
98
|
+
// Routes can be async.
|
|
99
|
+
route("/other", () => import("some-module"));
|
|
100
|
+
})}
|
|
101
|
+
</Suspense>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Also Suspense. This can be simply implemented with events.
|
|
106
|
+
ctx.emit("suspense:begin", uniqueId);
|
|
107
|
+
// Then when done:
|
|
108
|
+
ctx.emit("suspense:end", uniqueId);
|
|
109
|
+
|
|
110
|
+
// The nearest Suspense view will track ids which are in suspense and show fallback content in the meantime.
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function Suspense(props, ctx) {
|
|
114
|
+
const [$tracked, setTracked] = createState({});
|
|
115
|
+
|
|
116
|
+
ctx.on("suspense:begin", (e) => {
|
|
117
|
+
setTracked((tracked) => {
|
|
118
|
+
return {
|
|
119
|
+
...tracked,
|
|
120
|
+
[e.detail]: new Date(),
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
ctx.on("suspense:end", (e) => {
|
|
126
|
+
setTracked((tracked) => {
|
|
127
|
+
const updated = Object.assign({}, tracked);
|
|
128
|
+
delete updated[e.detail];
|
|
129
|
+
return updated;
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// TODO: Hide suspended view without unmounting it. This might take special logic.
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Can also pass markup directly if you don't need the context.
|
|
137
|
+
root.route("/", auth, <HomeRoute />);
|
|
138
|
+
|
|
139
|
+
// Static redirect.
|
|
140
|
+
root.route("*", "/");
|
|
141
|
+
|
|
142
|
+
// Programmatic redirect.
|
|
143
|
+
root.route("*", (C) => {
|
|
144
|
+
C.log("hit wildcard");
|
|
145
|
+
C.redirect("/");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
root.mount(document.body);
|
|
149
|
+
|
|
150
|
+
// generate an HTML string for server side rendering.
|
|
151
|
+
root.toString("/some/path");
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
class ClockStore extends Store {
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
constructor() {
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
class CounterStore extends Store {
|
|
166
|
+
// Could have better name. This will catch any
|
|
167
|
+
// this.emit('counter:increment') or this.emit('counter:decrement') calls
|
|
168
|
+
// and update the state according to these functions.
|
|
169
|
+
value = new Emittable('counter', 0, {
|
|
170
|
+
increment: state => state + 1,
|
|
171
|
+
decrement: state => state - 1
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
type CounterEvents = {
|
|
176
|
+
increment: [amount: number];
|
|
177
|
+
decrement: [amount: number];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
3
186
|
Bring the $ back and the name full circle.
|
|
4
187
|
|
|
5
188
|
```js
|
|
@@ -12,27 +195,176 @@ const [$count, setCount] = $(0);
|
|
|
12
195
|
// = createState(0)
|
|
13
196
|
|
|
14
197
|
// An array and a function derives a state.
|
|
15
|
-
const $doubled =
|
|
198
|
+
const $doubled = $.map([$count], (count) => count * 2);
|
|
16
199
|
// = derive([$count], (count) => count * 2);
|
|
17
200
|
|
|
18
201
|
// A state returns the same state.
|
|
19
|
-
const $sameCount = $.
|
|
20
|
-
const $wrapped = $.
|
|
202
|
+
const $sameCount = $.from($count);
|
|
203
|
+
const $wrapped = $.from({ message: "This is a state with no setter." });
|
|
21
204
|
// = toState($count)
|
|
22
205
|
|
|
23
206
|
// Get value from a state. Values that are not states are returned directly.
|
|
24
|
-
const count = $.
|
|
207
|
+
const count = $.get($count);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
What about other operators like RxJS?
|
|
211
|
+
|
|
212
|
+
```js
|
|
213
|
+
// These would be functionally equivalent.
|
|
214
|
+
const $doubled = $count.pipe($.map((count) => count * 2));
|
|
215
|
+
const $doubled = $.map([$count], (count) => count * 2);
|
|
216
|
+
|
|
217
|
+
// Chainable. Get doubled value, but only update if it's between 10 and 100.
|
|
218
|
+
const $boundedDouble = $count.pipe(
|
|
219
|
+
// Transforms the value
|
|
220
|
+
$.map((count) => count * 2),
|
|
221
|
+
|
|
222
|
+
// Receives the value when it changes without affecting the output.
|
|
223
|
+
// Only receives values while this state is actively being watched.
|
|
224
|
+
$.tap((count) => console.log(`doubled value is ${count}`))
|
|
225
|
+
|
|
226
|
+
// Value only changes if it's within the range.
|
|
227
|
+
$.filter((count) => count >= 10 && count <= 100),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
// Could have a top level pipe operator
|
|
231
|
+
const $boundedDouble = $.pipe(
|
|
232
|
+
[$count],
|
|
233
|
+
$.map((count) => count * 2),
|
|
234
|
+
$.tap((count) => console.log(`doubled value is ${count}`))
|
|
235
|
+
$.filter((count) => count >= 10 && count <= 100),
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// Could also be chainable
|
|
239
|
+
const $boundedDouble = $count
|
|
240
|
+
.map((count) => count * 2)
|
|
241
|
+
.tap((count) => console.log(`doubled value is ${count}`))
|
|
242
|
+
.filter((count) => count >= 10 && count <= 100);
|
|
243
|
+
|
|
244
|
+
// I kind of like this more than the current derive. It's cleaner.
|
|
245
|
+
$count.map(c => c * 2);
|
|
246
|
+
$count.merge([$other], (c, o) => c * o);
|
|
247
|
+
|
|
248
|
+
// Another way to merge multiple.
|
|
249
|
+
$.merge([$count, $other], (c, o) => c * o);
|
|
250
|
+
|
|
251
|
+
// What if you want to add something in the middle?
|
|
252
|
+
|
|
253
|
+
const $example = $count
|
|
254
|
+
.map((count) => count * 2)
|
|
255
|
+
.tap((count) => console.log(`doubled value is ${count}`))
|
|
256
|
+
.merge([$other1, $other2], (count, other1, other2) => /* ... */)
|
|
257
|
+
.filter((value) => value >= 10 && value <= 100);
|
|
258
|
+
|
|
259
|
+
// Is this a good pattern?
|
|
260
|
+
$count
|
|
261
|
+
.merge([$other], (count, other) => count * other)
|
|
262
|
+
.merge([$another], (merged, another) => merged * another);
|
|
263
|
+
// I think it gets a little weird to follow.
|
|
264
|
+
|
|
265
|
+
// equivalent to
|
|
266
|
+
derive(
|
|
267
|
+
[
|
|
268
|
+
derive([$count, $other], (count, other) => count * other),
|
|
269
|
+
$another
|
|
270
|
+
],
|
|
271
|
+
(merged, another) => merged * another)
|
|
272
|
+
// Is this a pattern? Yeah, I guess I do that. Just never in line like that.
|
|
273
|
+
|
|
274
|
+
// Do we want to handle errors?
|
|
275
|
+
// I feel like errors usually happen in watchers though.
|
|
276
|
+
$boundedDouble.watch((value) => {
|
|
277
|
+
// Received a value.
|
|
278
|
+
}, (error) => {
|
|
279
|
+
// Something threw an error.
|
|
280
|
+
});
|
|
281
|
+
// Or like this.
|
|
282
|
+
$boundedDouble.watch({
|
|
283
|
+
change: (value) => {
|
|
284
|
+
// Received a value.
|
|
285
|
+
// This code is most likely to throw an error.
|
|
286
|
+
// Should errors here be passed to the error callback?
|
|
287
|
+
// What is the point if you can just try/catch?
|
|
288
|
+
|
|
289
|
+
// Although if you don't then Dolla could use this to catch
|
|
290
|
+
// and trace errors better than it does now.
|
|
291
|
+
},
|
|
292
|
+
error: (error) => {
|
|
293
|
+
// Something threw an error.
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Filter derives a new state where the value only updates if the function returns truthy.
|
|
298
|
+
const $evens = $count.pipe($.filter((count) => count % 1 === 0));
|
|
299
|
+
// This is equivalent to
|
|
300
|
+
const $events = $.map([$count], (count) => count, { equals: (a, b) => a % 1 === 0 });
|
|
301
|
+
|
|
302
|
+
function filter(...args) {
|
|
303
|
+
if (isArray(args[0]) && isFunction(args[1])) {
|
|
304
|
+
// Standalone signature. Returns a new derived state.
|
|
305
|
+
} else if (args.length === 1 && isFunction(args[1])) {
|
|
306
|
+
// Curried signature. Returns a function that takes an array of states
|
|
307
|
+
// and returns one with args[1] as the equality check.
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
And you can write your own operators that implement these two signatures.
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
// Here's one I might want to include.
|
|
316
|
+
// Use this to prevent ever getting a null value.
|
|
317
|
+
compare((next, previous) => next ?? previous ?? "default");
|
|
318
|
+
|
|
319
|
+
function compare(...args) {}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
I've been looking into other libraries that don't make you track your dependencies specifically. I think this is weird and unhinged to be honest. Calling functions with side effects that magically re-run things when the value changes is a truly weird and unexpected lifecycle. At least if you're explicitly tracking dependencies you know exactly what depends on what at a glance. Getting the computer to figure it out for you doesn't seem smart.
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
import { $ } from "@manyducks.co/dolla";
|
|
328
|
+
|
|
329
|
+
const [count, setCount] = $(0);
|
|
330
|
+
|
|
331
|
+
const doubled = $.computed(() => count() * 2);
|
|
332
|
+
|
|
333
|
+
$.effect(() => {
|
|
334
|
+
console.log(doubled());
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
$.batch(() => {
|
|
338
|
+
// Set multiple things but defer updates to after this function returns.
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// Helpers on $; can plug into template as is.
|
|
342
|
+
$.if(
|
|
343
|
+
$.computed(() => count() > 5),
|
|
344
|
+
<span>Greater than 5!</span>,
|
|
345
|
+
<span>Not greater than 5...</span>,
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const switched = $.switch(count, [[1, "one"], [2, "two"], [3, "three"]], "more...");
|
|
349
|
+
|
|
350
|
+
$.repeat()
|
|
351
|
+
|
|
352
|
+
// TODO: How feasible is this?
|
|
353
|
+
<Repeat each={}>
|
|
354
|
+
{(item, index) => {
|
|
355
|
+
|
|
356
|
+
}}
|
|
357
|
+
</Repeat>
|
|
25
358
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
359
|
+
<Show when={condition}>
|
|
360
|
+
Condition is true.
|
|
361
|
+
</Show>
|
|
29
362
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
// = toSettableState($count, setCount);
|
|
363
|
+
// Get
|
|
364
|
+
count();
|
|
33
365
|
|
|
34
|
-
//
|
|
35
|
-
|
|
366
|
+
// Set
|
|
367
|
+
count(52);
|
|
36
368
|
```
|
|
37
369
|
|
|
38
370
|
---
|
|
@@ -112,10 +444,10 @@ debug.log("HELLO");
|
|
|
112
444
|
debug.warn("THIS IS A SCOPED LOGGER");
|
|
113
445
|
|
|
114
446
|
// Efficiently and safely read and mutate the DOM using Dolla's render batching
|
|
115
|
-
Dolla.
|
|
447
|
+
Dolla.batch.read(() => {
|
|
116
448
|
// Reference DOM nodes
|
|
117
449
|
});
|
|
118
|
-
Dolla.
|
|
450
|
+
Dolla.batch.write(() => {
|
|
119
451
|
// Mutate the DOM as part of Dolla's next batch
|
|
120
452
|
}, "some-key");
|
|
121
453
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Splitting
|
|
2
|
+
|
|
3
|
+
Thinking again of splitting this out into multiple libraries. Or at least having the base signals+markup be its own standalone thing that the rest of the framework is built on.
|
|
4
|
+
|
|
5
|
+
This implementation of signals + templates would be useful for web components.
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@manyducks.co/dolla",
|
|
3
|
-
"version": "2.0.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "A fast, batteries-included JavaScript framework with a React-like API and the power of Signals.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
6
|
+
"types": "dist/core/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"sideEffects": false,
|
|
9
|
-
"repository":
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/manyducksco/dolla.git"
|
|
12
|
+
},
|
|
10
13
|
"scripts": {
|
|
11
|
-
"test": "
|
|
14
|
+
"test": "vitest",
|
|
12
15
|
"build:esbuild": "tsc && node build.js",
|
|
13
16
|
"build": "vite build && tsc",
|
|
14
17
|
"start": "tsc --watch",
|
|
@@ -25,7 +28,19 @@
|
|
|
25
28
|
"exports": {
|
|
26
29
|
".": {
|
|
27
30
|
"import": "./dist/index.js",
|
|
28
|
-
"types": "./index.d.ts"
|
|
31
|
+
"types": "./dist/core/index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./router": {
|
|
34
|
+
"import": "./dist/router.js",
|
|
35
|
+
"types": "./dist/router/index.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./http": {
|
|
38
|
+
"import": "./dist/http.js",
|
|
39
|
+
"types": "./dist/http/index.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./i18n": {
|
|
42
|
+
"import": "./dist/i18n.js",
|
|
43
|
+
"types": "./dist/i18n/index.d.ts"
|
|
29
44
|
},
|
|
30
45
|
"./jsx-runtime": {
|
|
31
46
|
"import": "./dist/jsx-runtime.js",
|
|
@@ -36,16 +51,15 @@
|
|
|
36
51
|
"types": "./jsx-dev-runtime.d.ts"
|
|
37
52
|
}
|
|
38
53
|
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"alien-signals": "^2.0.5"
|
|
56
|
+
},
|
|
39
57
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^
|
|
58
|
+
"@types/node": "^24.1.0",
|
|
41
59
|
"csstype": "^3.1.3",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"prettier": "^3.4.2",
|
|
47
|
-
"simple-color-hash": "^1.0.2",
|
|
48
|
-
"typescript": "^5.7.3",
|
|
49
|
-
"vite": "^6.0.7"
|
|
60
|
+
"prettier": "^3.6.2",
|
|
61
|
+
"typescript": "^5.8.3",
|
|
62
|
+
"vite": "^7.0.6",
|
|
63
|
+
"vitest": "^3.2.4"
|
|
50
64
|
}
|
|
51
65
|
}
|
package/vite.config.js
CHANGED
|
@@ -3,26 +3,20 @@ import { defineConfig } from "vite";
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
build: {
|
|
6
|
-
// minify: "terser",
|
|
7
|
-
// minify: false,
|
|
8
6
|
sourcemap: true,
|
|
7
|
+
minify: true,
|
|
9
8
|
|
|
10
9
|
lib: {
|
|
11
10
|
entry: {
|
|
12
|
-
index: resolve(__dirname, "src/index.ts"),
|
|
11
|
+
index: resolve(__dirname, "src/core/index.ts"),
|
|
12
|
+
http: resolve(__dirname, "src/http/index.ts"),
|
|
13
|
+
i18n: resolve(__dirname, "src/i18n/index.ts"),
|
|
14
|
+
router: resolve(__dirname, "src/router/index.ts"),
|
|
13
15
|
"jsx-runtime": resolve(__dirname, "src/jsx-runtime.js"),
|
|
14
16
|
"jsx-dev-runtime": resolve(__dirname, "src/jsx-dev-runtime.js"),
|
|
15
17
|
},
|
|
16
18
|
name: "Dolla",
|
|
17
19
|
formats: ["es"],
|
|
18
20
|
},
|
|
19
|
-
// rollupOptions: {
|
|
20
|
-
// external: ["vue"],
|
|
21
|
-
// output: {
|
|
22
|
-
// globals: {
|
|
23
|
-
// vue: "Vue",
|
|
24
|
-
// },
|
|
25
|
-
// },
|
|
26
|
-
// },
|
|
27
21
|
},
|
|
28
22
|
});
|
package/build.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import esbuild from "esbuild";
|
|
3
|
-
|
|
4
|
-
esbuild
|
|
5
|
-
.build({
|
|
6
|
-
entryPoints: ["src/index.ts"],
|
|
7
|
-
bundle: true,
|
|
8
|
-
metafile: true,
|
|
9
|
-
sourcemap: true,
|
|
10
|
-
// minify: process.env.NODE_ENV === "production",
|
|
11
|
-
outdir: "dist",
|
|
12
|
-
format: "esm",
|
|
13
|
-
})
|
|
14
|
-
.then((result) => {
|
|
15
|
-
fs.writeFileSync("esbuild-meta.json", JSON.stringify(result.metafile));
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
esbuild.build({
|
|
19
|
-
entryPoints: ["src/jsx-runtime.js"],
|
|
20
|
-
bundle: false,
|
|
21
|
-
minify: false,
|
|
22
|
-
sourcemap: true,
|
|
23
|
-
outdir: "dist",
|
|
24
|
-
format: "esm",
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
esbuild.build({
|
|
28
|
-
entryPoints: ["src/jsx-dev-runtime.js"],
|
|
29
|
-
bundle: false,
|
|
30
|
-
minify: false,
|
|
31
|
-
sourcemap: true,
|
|
32
|
-
outdir: "dist",
|
|
33
|
-
format: "esm",
|
|
34
|
-
});
|
package/dist/index.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export { createSettableState, createSetter, createState, derive, toSettableState, toState, valueOf } from "./state.js";
|
|
2
|
-
export type { MaybeState, SettableState, State, StopFunction } from "./state.js";
|
|
3
|
-
export { cond, createMarkup, createRef, html, isRef, portal, repeat } from "./markup.js";
|
|
4
|
-
export type { Markup, MarkupNode, Ref } from "./markup.js";
|
|
5
|
-
import { Dolla } from "./modules/dolla.js";
|
|
6
|
-
declare const dolla: Dolla;
|
|
7
|
-
export default dolla;
|
|
8
|
-
export declare const t: (key: string, values?: Record<string, import("./types.js").Stringable | import("./state.js").State<import("./types.js").Stringable>>) => import("./state.js").State<string>;
|
|
9
|
-
export type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from "./modules/dolla.js";
|
|
10
|
-
export type { HTTPRequest, HTTPResponse } from "./modules/http.js";
|
|
11
|
-
export type { InputType, Renderable } from "./types.js";
|
|
12
|
-
export type { ViewContext, ViewFunction, ViewNode } from "./view.js";
|
|
13
|
-
export type { CrashViewProps } from "./views/default-crash-view.js";
|
|
14
|
-
import type { IntrinsicElements as Elements } from "./types";
|
|
15
|
-
declare global {
|
|
16
|
-
namespace JSX {
|
|
17
|
-
interface IntrinsicElements extends Elements {
|
|
18
|
-
[tag: string]: any;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
package/dist/markup.d.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import type { Dolla } from "./modules/dolla.js";
|
|
2
|
-
import { MaybeState, type State } from "./state.js";
|
|
3
|
-
import type { Renderable, Stringable } from "./types.js";
|
|
4
|
-
import { type ViewFunction, type ViewContext, type ViewResult } from "./view.js";
|
|
5
|
-
export interface ElementContext {
|
|
6
|
-
/**
|
|
7
|
-
* The root Dolla instance this element belongs to.
|
|
8
|
-
*/
|
|
9
|
-
root: Dolla;
|
|
10
|
-
/**
|
|
11
|
-
* Storage for context variables.
|
|
12
|
-
*/
|
|
13
|
-
data: Record<string | symbol, unknown>;
|
|
14
|
-
/**
|
|
15
|
-
* A reference to the parent context.
|
|
16
|
-
*/
|
|
17
|
-
parent?: ElementContext;
|
|
18
|
-
/**
|
|
19
|
-
* Whether to create DOM nodes in the SVG namespace. An `<svg>` element will set this to true and pass it down to children.
|
|
20
|
-
*/
|
|
21
|
-
isSVG?: boolean;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Markup is a set of element metadata that hasn't been constructed into a MarkupNode yet.
|
|
25
|
-
*/
|
|
26
|
-
export interface Markup {
|
|
27
|
-
type: string | ViewFunction<any>;
|
|
28
|
-
props?: Record<string, any>;
|
|
29
|
-
children?: Markup[];
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* A DOM node that has been constructed from a Markup object.
|
|
33
|
-
*/
|
|
34
|
-
export interface MarkupNode {
|
|
35
|
-
readonly node?: Node;
|
|
36
|
-
readonly isMounted: boolean;
|
|
37
|
-
mount(parent: Node, after?: Node): void;
|
|
38
|
-
unmount(): void;
|
|
39
|
-
}
|
|
40
|
-
export declare function isMarkup(value: unknown): value is Markup;
|
|
41
|
-
export declare function isNode(value: unknown): value is MarkupNode;
|
|
42
|
-
export declare function toMarkup(renderables: Renderable | Renderable[]): Markup[];
|
|
43
|
-
export interface MarkupAttributes {
|
|
44
|
-
$text: {
|
|
45
|
-
value: MaybeState<Stringable>;
|
|
46
|
-
};
|
|
47
|
-
$cond: {
|
|
48
|
-
$predicate: State<any>;
|
|
49
|
-
thenContent?: Renderable;
|
|
50
|
-
elseContent?: Renderable;
|
|
51
|
-
};
|
|
52
|
-
$repeat: {
|
|
53
|
-
$items: State<any[]>;
|
|
54
|
-
keyFn: (value: any, index: number) => string | number | symbol;
|
|
55
|
-
renderFn: ($item: State<any>, $index: State<number>, c: ViewContext) => ViewResult;
|
|
56
|
-
};
|
|
57
|
-
$observer: {
|
|
58
|
-
states: State<any>[];
|
|
59
|
-
renderFn: (...items: any) => Renderable;
|
|
60
|
-
};
|
|
61
|
-
$outlet: {
|
|
62
|
-
$children: State<MarkupNode[]>;
|
|
63
|
-
};
|
|
64
|
-
$node: {
|
|
65
|
-
value: Node;
|
|
66
|
-
};
|
|
67
|
-
$portal: {
|
|
68
|
-
content: Renderable;
|
|
69
|
-
parent: Node;
|
|
70
|
-
};
|
|
71
|
-
[tag: string]: Record<string, any>;
|
|
72
|
-
}
|
|
73
|
-
export declare function createMarkup<T extends keyof MarkupAttributes>(type: T, attributes: MarkupAttributes[T], ...children: Renderable[]): Markup;
|
|
74
|
-
export declare function createMarkup<I>(type: ViewFunction<I>, attributes?: I, ...children: Renderable[]): Markup;
|
|
75
|
-
/**
|
|
76
|
-
* Generate markup with HTML in a tagged template literal.
|
|
77
|
-
*/
|
|
78
|
-
export declare const html: (strings: TemplateStringsArray, ...values: any[]) => Markup | Markup[];
|
|
79
|
-
/**
|
|
80
|
-
* Displays content conditionally. When `predicate` holds a truthy value, `thenContent` is displayed; when `predicate` holds a falsy value, `elseContent` is displayed.
|
|
81
|
-
*/
|
|
82
|
-
export declare function cond(predicate: MaybeState<any>, thenContent?: Renderable, elseContent?: Renderable): Markup;
|
|
83
|
-
/**
|
|
84
|
-
* Calls `renderFn` for each item in `items`. Dynamically adds and removes views as items change.
|
|
85
|
-
* The result of `keyFn` is used to compare items and decide if item was added, removed or updated.
|
|
86
|
-
*/
|
|
87
|
-
export declare function repeat<T>(items: MaybeState<T[]>, keyFn: (value: T, index: number) => string | number | symbol, renderFn: ($value: State<T>, $index: State<number>, ctx: ViewContext) => ViewResult): Markup;
|
|
88
|
-
/**
|
|
89
|
-
* Render `content` into a `parent` node anywhere in the page, rather than at its position in the view.
|
|
90
|
-
*/
|
|
91
|
-
export declare function portal(parent: Node, content: Renderable): Markup;
|
|
92
|
-
/**
|
|
93
|
-
* A special kind of State exclusively for storing references to DOM nodes.
|
|
94
|
-
*/
|
|
95
|
-
export declare function createRef<T extends Node>(): Ref<T>;
|
|
96
|
-
export declare function isRef<T extends Node>(value: any): value is Ref<T>;
|
|
97
|
-
export interface Ref<T extends Node> extends State<T | undefined> {
|
|
98
|
-
node: T | undefined;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Construct Markup metadata into a set of MarkupNodes.
|
|
102
|
-
*/
|
|
103
|
-
export declare function constructMarkup(elementContext: ElementContext, markup: Markup | Markup[]): MarkupNode[];
|
|
104
|
-
/**
|
|
105
|
-
* Combines one or more MarkupNodes into a single MarkupNode.
|
|
106
|
-
*/
|
|
107
|
-
export declare function mergeNodes(nodes: MarkupNode[]): MarkupNode;
|
|
108
|
-
export declare function isRenderable(value: unknown): value is Renderable;
|