@manyducks.co/dolla 2.0.0 → 3.1.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 (112) hide show
  1. package/README.md +133 -284
  2. package/dist/context-B5blupD2.js +363 -0
  3. package/dist/context-B5blupD2.js.map +1 -0
  4. package/dist/core/context.d.ts +29 -144
  5. package/dist/core/debug.d.ts +19 -0
  6. package/dist/core/index.d.ts +15 -16
  7. package/dist/core/markup/helpers.d.ts +34 -0
  8. package/dist/core/markup/html.d.ts +3 -0
  9. package/dist/core/{nodes → markup/nodes}/dom.d.ts +5 -4
  10. package/dist/core/markup/nodes/dynamic.d.ts +16 -0
  11. package/dist/core/markup/nodes/element.d.ts +14 -0
  12. package/dist/core/markup/nodes/portal.d.ts +15 -0
  13. package/dist/core/markup/nodes/repeat.d.ts +21 -0
  14. package/dist/core/markup/nodes/view.d.ts +17 -0
  15. package/dist/core/markup/scheduler.d.ts +1 -0
  16. package/dist/core/markup/types.d.ts +62 -0
  17. package/dist/core/markup/utils.d.ts +22 -0
  18. package/dist/core/ref.d.ts +6 -12
  19. package/dist/core/root.d.ts +36 -0
  20. package/dist/core/signals.d.ts +46 -76
  21. package/dist/core/symbols.d.ts +2 -0
  22. package/dist/core-JHktdqjt.js +242 -0
  23. package/dist/core-JHktdqjt.js.map +1 -0
  24. package/dist/http/index.d.ts +21 -33
  25. package/dist/http.js +89 -149
  26. package/dist/http.js.map +1 -1
  27. package/dist/index.js +4 -174
  28. package/dist/jsx-dev-runtime.d.ts +4 -3
  29. package/dist/jsx-dev-runtime.js +12 -9
  30. package/dist/jsx-dev-runtime.js.map +1 -1
  31. package/dist/jsx-runtime.d.ts +5 -4
  32. package/dist/jsx-runtime.js +17 -12
  33. package/dist/jsx-runtime.js.map +1 -1
  34. package/dist/router/index.d.ts +4 -3
  35. package/dist/router/router.d.ts +19 -162
  36. package/dist/router/store.d.ts +12 -0
  37. package/dist/router/types.d.ts +152 -0
  38. package/dist/router/utils.d.ts +99 -0
  39. package/dist/router/utils.test.d.ts +1 -0
  40. package/dist/router.js +428 -5
  41. package/dist/router.js.map +1 -1
  42. package/dist/signals-CMJPGr_M.js +354 -0
  43. package/dist/signals-CMJPGr_M.js.map +1 -0
  44. package/dist/translate/index.d.ts +82 -0
  45. package/dist/translate.js +125 -0
  46. package/dist/translate.js.map +1 -0
  47. package/dist/types.d.ts +21 -39
  48. package/dist/utils.d.ts +41 -29
  49. package/dist/utils.test.d.ts +1 -0
  50. package/dist/virtual/index.d.ts +1 -0
  51. package/dist/virtual/list.d.ts +53 -0
  52. package/package.json +19 -16
  53. package/dist/core/app.d.ts +0 -24
  54. package/dist/core/env.d.ts +0 -3
  55. package/dist/core/hooks.d.ts +0 -70
  56. package/dist/core/logger.d.ts +0 -42
  57. package/dist/core/logger.test.d.ts +0 -0
  58. package/dist/core/markup.d.ts +0 -82
  59. package/dist/core/markup.test.d.ts +0 -0
  60. package/dist/core/nodes/_markup.d.ts +0 -36
  61. package/dist/core/nodes/dynamic.d.ts +0 -22
  62. package/dist/core/nodes/element.d.ts +0 -27
  63. package/dist/core/nodes/portal.d.ts +0 -18
  64. package/dist/core/nodes/repeat.d.ts +0 -27
  65. package/dist/core/nodes/view.d.ts +0 -25
  66. package/dist/core/views/default-crash-view.d.ts +0 -25
  67. package/dist/core/views/for.d.ts +0 -21
  68. package/dist/core/views/fragment.d.ts +0 -7
  69. package/dist/core/views/portal.d.ts +0 -16
  70. package/dist/core/views/show.d.ts +0 -25
  71. package/dist/fragment-BahD_BJA.js +0 -7
  72. package/dist/fragment-BahD_BJA.js.map +0 -1
  73. package/dist/i18n/index.d.ts +0 -134
  74. package/dist/i18n.js +0 -309
  75. package/dist/i18n.js.map +0 -1
  76. package/dist/index-DRJlxs-Q.js +0 -535
  77. package/dist/index-DRJlxs-Q.js.map +0 -1
  78. package/dist/index.js.map +0 -1
  79. package/dist/logger-Aqi9m1CF.js +0 -565
  80. package/dist/logger-Aqi9m1CF.js.map +0 -1
  81. package/dist/markup-8jNhoqDe.js +0 -1089
  82. package/dist/markup-8jNhoqDe.js.map +0 -1
  83. package/dist/router/hooks.d.ts +0 -2
  84. package/dist/router/router.utils.d.ts +0 -93
  85. package/dist/typeChecking-5kmX0ulW.js +0 -65
  86. package/dist/typeChecking-5kmX0ulW.js.map +0 -1
  87. package/dist/typeChecking.d.ts +0 -95
  88. package/docs/buildless.md +0 -132
  89. package/docs/components.md +0 -238
  90. package/docs/hooks.md +0 -356
  91. package/docs/http.md +0 -178
  92. package/docs/i18n.md +0 -220
  93. package/docs/index.md +0 -10
  94. package/docs/markup.md +0 -136
  95. package/docs/mixins.md +0 -176
  96. package/docs/ref.md +0 -77
  97. package/docs/router.md +0 -281
  98. package/docs/setup.md +0 -137
  99. package/docs/signals.md +0 -262
  100. package/docs/stores.md +0 -113
  101. package/docs/views.md +0 -356
  102. package/notes/atomic.md +0 -452
  103. package/notes/elimination.md +0 -33
  104. package/notes/observable.md +0 -180
  105. package/notes/scratch.md +0 -565
  106. package/notes/splitting.md +0 -5
  107. package/notes/views.md +0 -195
  108. package/vite.config.js +0 -22
  109. /package/dist/core/{hooks.test.d.ts → markup/html.test.d.ts} +0 -0
  110. /package/dist/core/{ref.test.d.ts → markup/utils.test.d.ts} +0 -0
  111. /package/dist/router/{router.utils.test.d.ts → matcher.test.d.ts} +0 -0
  112. /package/dist/{typeChecking.test.d.ts → router/router.test.d.ts} +0 -0
package/notes/scratch.md DELETED
@@ -1,565 +0,0 @@
1
- # Scratch Note
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
-
186
- Bring the $ back and the name full circle.
187
-
188
- ```js
189
- import { $, $$ } from "@manyducks.co/dolla";
190
-
191
- // Shorthand dolla sign
192
-
193
- // An initial value (with optional options object) creates a state.
194
- const [$count, setCount] = $(0);
195
- // = createState(0)
196
-
197
- // An array and a function derives a state.
198
- const $doubled = $.map([$count], (count) => count * 2);
199
- // = derive([$count], (count) => count * 2);
200
-
201
- // A state returns the same state.
202
- const $sameCount = $.from($count);
203
- const $wrapped = $.from({ message: "This is a state with no setter." });
204
- // = toState($count)
205
-
206
- // Get value from a state. Values that are not states are returned directly.
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>
358
-
359
- <Show when={condition}>
360
- Condition is true.
361
- </Show>
362
-
363
- // Get
364
- count();
365
-
366
- // Set
367
- count(52);
368
- ```
369
-
370
- ---
371
-
372
- What if Dolla was just a global object that you don't instantiate. I have never personally run into a use case for having more than one app on a page at once. In all my projects, the page and the app are synonymous.
373
-
374
- Doing this would make it possible to access things inside the Dolla app from _outside_ code such as Quill blots. Effectively all code that has access to your Dolla import is _inside_ the app.
375
-
376
- - Remove stores in favor of just exporting variables and functions from ES modules and importing them where desired.
377
- -
378
-
379
- ```jsx
380
- import Dolla from "@manyducks.co/dolla";
381
-
382
- // Languages: add translation, set language and get localized string as a signal
383
- Dolla.i18n.setup({
384
- initialLanguage: Dolla.i18n.detect({ fallback: "ja" }), // Detect user's language and fall back to passed value
385
- languages: [
386
- { name: "ja", path: "/static/locales/ja.json" },
387
- {
388
- name: "en",
389
- fetch: async () => {
390
- // Pass a path string, or if additional logic is needed, a fetch function.
391
- const res = await Dolla.http.get("/static/locales/en.json");
392
- return res.body;
393
- }
394
- }
395
- ]
396
- });
397
-
398
- Dolla.i18n.$locale
399
- Dolla.i18n.t$()
400
-
401
- // A single setup call to keep things contained (must happen before mount)
402
- Dolla.router.setup({
403
- // Initial path must point to a route that actually exists (will be validated on mount) (initialPath is "/" by default)
404
- initialPath: "/",
405
- routes: [
406
- { path: "/", view: SomeView }
407
- ]
408
- });
409
- // And then you can route from anywhere.
410
- Dolla.router.go("/some/path");
411
- // Or get route information from anywhere.
412
- Dolla.router.$path;
413
- Dolla.router.$params;
414
-
415
- // Also utils are available
416
- const joinedPath = Dolla.router.utils.joinPath("/api/records", "5");
417
- const resolvedPath = Dolla.router.utils.resolvePath("../"); // Resolves with window.location.href as the base
418
-
419
- // Initializes the app and matches first route
420
- Dolla.mount("#app");
421
- // If you pass a view as the second argument it becomes the root view (this works for simple apps without a router)
422
- Dolla.mount("#app", MyRootView);
423
- // If router setup function wasn't called then the root view is mounted equivalent to the following:
424
- Dolla.router.setup({
425
- defaultPath: "/",
426
- routes: [
427
- { path: "/*", view: MyRootView },
428
- ]
429
- });
430
-
431
- // Add HTTP middleware
432
- Dolla.http.use(async (req, next) => {
433
- const res = await next()
434
- });
435
- // Make HTTP calls
436
- const res = await Dolla.get("/some/path");
437
-
438
- // Adjust log level
439
- Dolla.setLogLevel(Dolla.LOG_LEVEL_INFO);
440
- Dolla.setLogFilter("*,-Dolla/*")
441
- // Create a scoped logger
442
- const debug = Dolla.createLogger("debug-logger");
443
- debug.log("HELLO");
444
- debug.warn("THIS IS A SCOPED LOGGER");
445
-
446
- // Efficiently and safely read and mutate the DOM using Dolla's render batching
447
- Dolla.batch.read(() => {
448
- // Reference DOM nodes
449
- });
450
- Dolla.batch.write(() => {
451
- // Mutate the DOM as part of Dolla's next batch
452
- }, "some-key");
453
-
454
- // Respond to lifecycle events
455
- Dolla.onMount(() => {});
456
- Dolla.onRouteMatch(() => {});
457
- // Dolla.onWhatever(() => {});
458
-
459
- interface SomeViewProps {}
460
-
461
- function SomeView (props: SomeViewProps, ctx: Dolla.ViewContext) {
462
- const debug = Dolla.createLogger("SomeView");
463
-
464
- // returns a signal and a setter function
465
- const [$someValue, setSomeValue] = Dolla.createState(4);
466
-
467
- // Router is now a part of the Dolla object
468
- Dolla.router.$path;
469
- Dolla.router.$params;
470
-
471
- Dolla.router.go("/some-other-path");
472
-
473
- ctx.watch([$someValue], (value) => {
474
- debug.log(value);
475
- });
476
-
477
- // View helpers are on ViewContext
478
- ctx.repeat()
479
- ctx.cond()
480
- ctx.render([...states], (...values) => {
481
- // return Renderable (equivalent to Dolla.derive(states, (...values) => Renderable))
482
- })
483
- ctx.portal()
484
- ctx.outlet()
485
-
486
- // TODO: Add Dolla.dialog.show() and Dolla.toast.show() or create separate libraries?
487
-
488
- return <h1>{ctx.t$("home.headerText")}</h1>;
489
- }
490
- ```
491
-
492
- ```tsx
493
- // import { signal, computed } from "@manyducks.co/dolla";
494
-
495
- function signal(initialValue, options = {}) {}
496
-
497
- function computed();
498
-
499
- function WhateverView(props, c) {
500
- // IDEA: Have state, computed and effect be methods on the view context.
501
- // PROBLEM: Then what are the types when passing as props? State? ComputedState? or just a generic Dynamic<T> for readable/writable?
502
-
503
- // Context variables (replacement for stores)
504
- c.set("name", {
505
- value: 5,
506
- });
507
-
508
- // Can get in the same context scope or on a child.
509
- // Throws an error if value is not set.
510
- c.get("name");
511
-
512
- // If we use this $readable and set function pattern then we only have a single type of signal which is read-only.
513
- // Take props as Signal<T> and deal with setting in callbacks. Simple and predictable.
514
- const [$count, setCount] = signal(5);
515
-
516
- const $doubled = derived($count, (value) => value * 2);
517
-
518
- // const watcher = new SignalWatcher($count, (value) => {
519
- // c.debug.log("watcher received value: " + value);
520
- // });
521
-
522
- // watcher.start();
523
- // watcher.stop();
524
-
525
- $count.get(); // returns the current value
526
- setCount(10); // updates the value
527
-
528
- // Observe and trigger side effects.
529
- c.watch($count, (count) => {
530
- c.debug.log(`The value of count is: ${count}`);
531
- });
532
-
533
- // Exposes language and translation tools.
534
- c.i18n.translate$("");
535
- c.i18n.$language;
536
- c.i18n.setLanguage();
537
-
538
- // Exposes internal HTTP client.
539
- c.http.get(); // put, post, patch, delete, etc.
540
-
541
- // Exposes router helpers and variables.
542
- c.route.go("/");
543
- c.route.$params;
544
- c.route.$path;
545
- c.route.$query;
546
- c.route.setQuery({
547
- value: 1,
548
- });
549
-
550
- return html`
551
- <h1>This is the template</h1>
552
-
553
- ${render($count, (count) => {
554
- // Render rebuilds the markup within when any of the dependencies change.
555
- return html`<p>The count is ${count}</p>`;
556
-
557
- // Other view helpers are also provided as exports
558
- repeat();
559
- cond();
560
- outlet();
561
- portal();
562
- })}
563
- `;
564
- }
565
- ```
@@ -1,5 +0,0 @@
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.