@substrate-system/tonic 17.0.0 → 17.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 (41) hide show
  1. package/README.md +220 -23
  2. package/dist/hydrate.cjs +39 -0
  3. package/dist/hydrate.cjs.map +7 -0
  4. package/dist/hydrate.d.ts +30 -0
  5. package/dist/hydrate.d.ts.map +1 -0
  6. package/dist/hydrate.js +18 -0
  7. package/dist/hydrate.js.map +7 -0
  8. package/dist/hydrate.min.cjs +2 -0
  9. package/dist/hydrate.min.cjs.map +7 -0
  10. package/dist/hydrate.min.mjs +3 -0
  11. package/dist/hydrate.min.mjs.map +7 -0
  12. package/dist/hydrate.mjs +20 -0
  13. package/dist/hydrate.mjs.map +7 -0
  14. package/dist/index.cjs +128 -24
  15. package/dist/index.cjs.map +2 -2
  16. package/dist/index.d.ts +9 -6
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +129 -25
  19. package/dist/index.js.map +2 -2
  20. package/dist/index.min.cjs +3 -0
  21. package/dist/index.min.cjs.map +7 -0
  22. package/dist/index.min.mjs +2 -2
  23. package/dist/index.min.mjs.map +3 -3
  24. package/dist/index.mjs +127 -24
  25. package/dist/index.mjs.map +2 -2
  26. package/dist/meta.json +66 -4
  27. package/dist/render-to-string.cjs +180 -0
  28. package/dist/render-to-string.cjs.map +7 -0
  29. package/dist/render-to-string.d.ts +82 -0
  30. package/dist/render-to-string.d.ts.map +1 -0
  31. package/dist/render-to-string.js +147 -0
  32. package/dist/render-to-string.js.map +7 -0
  33. package/dist/render-to-string.min.cjs +3 -0
  34. package/dist/render-to-string.min.cjs.map +7 -0
  35. package/dist/render-to-string.min.mjs +3 -0
  36. package/dist/render-to-string.min.mjs.map +7 -0
  37. package/dist/render-to-string.mjs +151 -0
  38. package/dist/render-to-string.mjs.map +7 -0
  39. package/package.json +21 -10
  40. package/dist/index.min.js +0 -3
  41. package/dist/index.min.js.map +0 -7
package/README.md CHANGED
@@ -31,12 +31,14 @@ with all modern browsers. It's built on top of
31
31
  * [Rerender](#rerender)
32
32
  * [Events](#events)
33
33
  * [State](#state)
34
+ - [Server-Side Rendering](#server-side-rendering)
35
+ * [SSR Example](#ssr-example)
36
+ * [Async Components](#async-components)
37
+ * [Hydration](#hydration)
38
+ - [Docs](#docs)
34
39
  - [API](#api)
35
40
  * [Event listeners](#event-listeners)
36
- - [DOM state](#dom-state)
37
- - [docs](#docs)
38
- - [types](#types)
39
- - [`tag`](#tag)
41
+ * [`tag`](#tag)
40
42
  * [`emit`](#emit)
41
43
  * [`static event`](#static-event)
42
44
  * [`dispatch`](#dispatch)
@@ -64,6 +66,10 @@ This is a front-end view library, like React, but using web components.
64
66
  > DOM state, such as element focus and input values, is preserved
65
67
  > across multiple calls to `reRender`.
66
68
 
69
+
70
+ -------
71
+
72
+
67
73
  ## Use
68
74
 
69
75
  ### Bundler
@@ -245,11 +251,11 @@ class ButtonExample extends Tonic {
245
251
  ### State
246
252
 
247
253
  `this.state` is a plain-old javascript object. Its value will be persisted if
248
- the component is re-rendered. Any element that has an id attribute can use
249
- state, and any component that uses state must have an id property.
254
+ the component is re-rendered. **Any component with state must have an**
255
+ **id property**.
250
256
 
251
257
  Setting the state will not cause a component to re-render. This way you can
252
- make incremental updates. Components can be updated independently. And
258
+ make incremental updates. Components can be updated independently, and
253
259
  rendering only happens only when necessary.
254
260
 
255
261
  Remember to clean up! States are just a set of key-value pairs on the Tonic
@@ -260,6 +266,201 @@ all use state, I should delete their state after they get destroyed.
260
266
  Delete `Tonic._states[someRandomId]`
261
267
 
262
268
 
269
+ ## Server-Side Rendering
270
+
271
+ Tonic includes a `renderToString` function that converts component instances
272
+ to static HTML strings, making it easy to implement server-side rendering.
273
+
274
+ The `renderToString` function will process nested Tonic components recursively.
275
+
276
+ ### SSR Example
277
+
278
+ #### The Component
279
+
280
+ ```js
281
+ // my-component.js
282
+ import Tonic from '@substrate-system/tonic'
283
+
284
+ export class MyComponent extends Tonic {
285
+ render () {
286
+ return this.html`<div class="greeting">
287
+ Hello, ${this.props.name}!
288
+ </div>`
289
+ }
290
+ }
291
+ ```
292
+
293
+ #### Render
294
+
295
+ Need to import `Tonic` after `render`, because it will polyfill some globals.
296
+
297
+ ```js
298
+ // this runs in node
299
+ import {
300
+ render as renderToString
301
+ } from '@substrate-system/tonic/render-to-string'
302
+ // Import Tonic after render-to-string
303
+ import { Tonic } from '@substrate-system/tonic'
304
+ import { MyComponent } from './my-component.js'
305
+
306
+ // Create a component instance
307
+ const component = new MyComponent()
308
+ component.props = { name: 'World' }
309
+
310
+ // Render to HTML string
311
+ const html = await renderToString(component)
312
+ console.log(html)
313
+
314
+ // => '<div class="greeting">Hello, World!</div>'
315
+ ```
316
+
317
+ #### Nested Components
318
+
319
+ ```js
320
+ class InnerComponent extends Tonic {
321
+ render () {
322
+ return this.html`<span>${this.props.text}</span>`
323
+ }
324
+ }
325
+
326
+ class OuterComponent extends Tonic {
327
+ render () {
328
+ return this.html`
329
+ <div class="outer">
330
+ <inner-component text="Nested content"></inner-component>
331
+ </div>
332
+ `
333
+ }
334
+ }
335
+
336
+ Tonic.add(InnerComponent)
337
+ Tonic.add(OuterComponent)
338
+
339
+ const component = new OuterComponent()
340
+ const html = await renderToString(component)
341
+ // Nested components are rendered correctly
342
+ ```
343
+
344
+ ### Async Components
345
+
346
+ The `renderToString` function works with async component render methods:
347
+
348
+ ```js
349
+ class AsyncComponent extends Tonic {
350
+ async render () {
351
+ const data = await fetchData()
352
+ return this.html`<div>${data}</div>`
353
+ }
354
+ }
355
+
356
+ Tonic.add(AsyncComponent)
357
+
358
+ const component = new AsyncComponent()
359
+ const html = await renderToString(component)
360
+ // Waits for async render to complete
361
+ ```
362
+
363
+ ### Hydration
364
+
365
+ Add interactivity to server-rendered HTML without re-rendering.
366
+ The server attaches serialized state to the page,
367
+ and the client initializes components with that state.
368
+
369
+ #### Start a local example
370
+
371
+ ```sh
372
+ npm run start:hydration
373
+ ```
374
+
375
+ #### Build the hydration example
376
+
377
+ ```sh
378
+ npm run build:hydration
379
+ ```
380
+
381
+ #### Server
382
+
383
+ `render` returns the inner HTML of a component. `toHtml`
384
+ wraps that in the custom element tag (e.g.
385
+ `<my-app>...content...</my-app>`), with props encoded as
386
+ attributes. Pass a `state` option to embed complex props
387
+ as JSON.
388
+
389
+ ```js
390
+ import {
391
+ render,
392
+ toHtml
393
+ } from '@substrate-system/tonic/render-to-string'
394
+
395
+ class MyApp extends Tonic {
396
+ render () {
397
+ return this.html`<div>
398
+ <h1>${this.props.title}</h1>
399
+ <ul>
400
+ ${this.props.items.map(item =>
401
+ this.html`<li>${item}</li>`
402
+ )}
403
+ </ul>
404
+ <button>Click me</button>
405
+ </div>`
406
+ }
407
+ }
408
+
409
+ Tonic.add(MyApp)
410
+
411
+ const props = { title: 'Hello', items: ['a', 'b', 'c'] }
412
+ const app = new MyApp()
413
+ app.props = props
414
+ const content = await render(app)
415
+
416
+ // Wrap in component tag + embed state for hydration
417
+ const html = toHtml(app, content, {
418
+ id: 'app',
419
+ state: { app: props }
420
+ })
421
+
422
+ // html =>
423
+ // <my-app id="app" title="Hello">
424
+ // <div><h1>Hello</h1>...</div>
425
+ // </my-app>
426
+ // <script type="application/json" data-tonic-ssr>
427
+ // {"app":{"title":"Hello","items":["a","b","c"]}}
428
+ // </script>
429
+ ```
430
+
431
+ Simple props (strings, numbers, booleans, null) are encoded
432
+ as HTML attributes automatically. Complex props (objects,
433
+ arrays) are transferred via the JSON `<script>` tag, keyed
434
+ by the component's `id`.
435
+
436
+ #### Client
437
+
438
+ Use `hydrate` to register components without re-rendering.
439
+ The existing server-rendered DOM is preserved, event handlers
440
+ are attached, and lifecycle hooks run normally.
441
+
442
+ ```js
443
+ import { Tonic } from '@substrate-system/tonic'
444
+ import { hydrate } from '@substrate-system/tonic/hydrate'
445
+ import { MyApp } from './components.js'
446
+
447
+ // Register components inside the callback --
448
+ // the DOM is preserved, not re-rendered.
449
+ const state = hydrate(() => {
450
+ Tonic.add(MyApp)
451
+ })
452
+
453
+ // state => { app: { title: 'Hello', items: ['a', 'b', 'c'] } }
454
+ // Event handlers (handle_click, etc.) are active.
455
+ // Calling reRender() works normally after hydration.
456
+ ```
457
+
458
+ ## Docs
459
+
460
+ See [API docs](https://substrate-system.github.io/tonic/).
461
+
462
+ ---
463
+
263
464
  ## API
264
465
 
265
466
  ### Event listeners
@@ -288,22 +489,16 @@ class MyClicker extends Tonic {
288
489
  Tonic.add(MyClicker)
289
490
  ```
290
491
 
492
+ -------
291
493
 
292
- ## DOM state
293
-
294
- DOM state (like element focus) should be preserved across re-renders.
494
+ ### `tag`
295
495
 
296
- ## docs
297
- See [API docs](https://substrate-system.github.io/tonic/).
298
-
299
- ## types
300
- See [src/index.ts](./src/index.ts).
301
-
302
- ## `tag`
303
496
  Get the HTML tag name given a Tonic class.
304
497
 
305
498
  ```ts
306
- static get tag():string;
499
+ class Tonic {
500
+ static get tag():string;
501
+ }
307
502
  ```
308
503
 
309
504
  ```js
@@ -326,10 +521,12 @@ Given an event name, the dispatched event will be prefixed with the element
326
521
  name, for example, `my-element:event-name`.
327
522
 
328
523
  ```ts
329
- emit (type:string, detail:string|object|any[] = {}, opts:Partial<{
330
- bubbles:boolean;
331
- cancelable:boolean
332
- }> = {}):boolean
524
+ {
525
+ emit (type:string, detail:string|object|any[] = {}, opts:Partial<{
526
+ bubbles:boolean;
527
+ cancelable:boolean
528
+ }> = {}):boolean
529
+ }
333
530
  ```
334
531
 
335
532
  #### emit example
@@ -365,7 +562,7 @@ Return the namespaced event name given a string.
365
562
  ```ts
366
563
  class {
367
564
  static event (type:string):string {
368
- return `${this.tag}:${type}`
565
+ return `${this.TAG}:${type}`
369
566
  }
370
567
  }
371
568
  ```
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var hydrate_exports = {};
21
+ __export(hydrate_exports, {
22
+ hydrate: () => hydrate
23
+ });
24
+ module.exports = __toCommonJS(hydrate_exports);
25
+ var import_index = require("./index.js");
26
+ function hydrate(callback) {
27
+ const script = document.querySelector(
28
+ "script[data-tonic-ssr]"
29
+ );
30
+ const state = script ? JSON.parse(script.textContent || "{}") : null;
31
+ import_index.Tonic._ssrState = state;
32
+ import_index.Tonic._hydrating = true;
33
+ callback();
34
+ import_index.Tonic._hydrating = false;
35
+ import_index.Tonic._ssrState = null;
36
+ return state;
37
+ }
38
+ __name(hydrate, "hydrate");
39
+ //# sourceMappingURL=hydrate.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/hydrate.ts"],
4
+ "sourcesContent": ["import { Tonic } from './index.js'\n\n/**\n * Hydrate server-rendered Tonic components.\n *\n * Call this to wrap component registration so that existing\n * server-rendered DOM is preserved instead of being re-rendered.\n * Event handlers are still attached, props are parsed from\n * attributes, and lifecycle hooks (`willConnect`, `connected`)\n * are called.\n *\n * If a `<script type=\"application/json\" data-tonic-ssr>` tag\n * exists in the document, its JSON content is parsed and used\n * to restore complex props (objects, arrays) for components\n * with matching `id` attributes.\n *\n * @param callback Register your components inside this callback\n * @returns The parsed SSR state, or null if none was embedded\n *\n * @example\n * ```ts\n * import { hydrate } from '@substrate-system/tonic/hydrate'\n * import { Tonic } from '@substrate-system/tonic'\n * import { MyApp } from './components.js'\n *\n * const state = hydrate(() => {\n * Tonic.add(MyApp)\n * })\n * ```\n */\nexport function hydrate (\n callback:() => void\n):Record<string, any>|null {\n const script = document.querySelector(\n 'script[data-tonic-ssr]'\n )\n\n const state:Record<string, any>|null = script ?\n JSON.parse(script.textContent || '{}') :\n null\n\n Tonic._ssrState = state\n Tonic._hydrating = true\n\n callback()\n\n Tonic._hydrating = false\n Tonic._ssrState = null\n\n return state\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAsB;AA8Bf,SAAS,QACZ,UACuB;AACvB,QAAM,SAAS,SAAS;AAAA,IACpB;AAAA,EACJ;AAEA,QAAM,QAAiC,SACnC,KAAK,MAAM,OAAO,eAAe,IAAI,IACrC;AAEJ,qBAAM,YAAY;AAClB,qBAAM,aAAa;AAEnB,WAAS;AAET,qBAAM,aAAa;AACnB,qBAAM,YAAY;AAElB,SAAO;AACX;AApBgB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Hydrate server-rendered Tonic components.
3
+ *
4
+ * Call this to wrap component registration so that existing
5
+ * server-rendered DOM is preserved instead of being re-rendered.
6
+ * Event handlers are still attached, props are parsed from
7
+ * attributes, and lifecycle hooks (`willConnect`, `connected`)
8
+ * are called.
9
+ *
10
+ * If a `<script type="application/json" data-tonic-ssr>` tag
11
+ * exists in the document, its JSON content is parsed and used
12
+ * to restore complex props (objects, arrays) for components
13
+ * with matching `id` attributes.
14
+ *
15
+ * @param callback Register your components inside this callback
16
+ * @returns The parsed SSR state, or null if none was embedded
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { hydrate } from '@substrate-system/tonic/hydrate'
21
+ * import { Tonic } from '@substrate-system/tonic'
22
+ * import { MyApp } from './components.js'
23
+ *
24
+ * const state = hydrate(() => {
25
+ * Tonic.add(MyApp)
26
+ * })
27
+ * ```
28
+ */
29
+ export declare function hydrate(callback: () => void): Record<string, any> | null;
30
+ //# sourceMappingURL=hydrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../src/hydrate.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,OAAO,CACnB,QAAQ,EAAC,MAAM,IAAI,GACrB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAC,IAAI,CAkBzB"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ import { Tonic } from "./index.js";
5
+ export function hydrate(callback) {
6
+ const script = document.querySelector(
7
+ "script[data-tonic-ssr]"
8
+ );
9
+ const state = script ? JSON.parse(script.textContent || "{}") : null;
10
+ Tonic._ssrState = state;
11
+ Tonic._hydrating = true;
12
+ callback();
13
+ Tonic._hydrating = false;
14
+ Tonic._ssrState = null;
15
+ return state;
16
+ }
17
+ __name(hydrate, "hydrate");
18
+ //# sourceMappingURL=hydrate.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/hydrate.ts"],
4
+ "sourcesContent": ["import { Tonic } from './index.js'\n\n/**\n * Hydrate server-rendered Tonic components.\n *\n * Call this to wrap component registration so that existing\n * server-rendered DOM is preserved instead of being re-rendered.\n * Event handlers are still attached, props are parsed from\n * attributes, and lifecycle hooks (`willConnect`, `connected`)\n * are called.\n *\n * If a `<script type=\"application/json\" data-tonic-ssr>` tag\n * exists in the document, its JSON content is parsed and used\n * to restore complex props (objects, arrays) for components\n * with matching `id` attributes.\n *\n * @param callback Register your components inside this callback\n * @returns The parsed SSR state, or null if none was embedded\n *\n * @example\n * ```ts\n * import { hydrate } from '@substrate-system/tonic/hydrate'\n * import { Tonic } from '@substrate-system/tonic'\n * import { MyApp } from './components.js'\n *\n * const state = hydrate(() => {\n * Tonic.add(MyApp)\n * })\n * ```\n */\nexport function hydrate (\n callback:() => void\n):Record<string, any>|null {\n const script = document.querySelector(\n 'script[data-tonic-ssr]'\n )\n\n const state:Record<string, any>|null = script ?\n JSON.parse(script.textContent || '{}') :\n null\n\n Tonic._ssrState = state\n Tonic._hydrating = true\n\n callback()\n\n Tonic._hydrating = false\n Tonic._ssrState = null\n\n return state\n}\n"],
5
+ "mappings": ";;;AAAA,SAAS,aAAa;AA8Bf,gBAAS,QACZ,UACuB;AACvB,QAAM,SAAS,SAAS;AAAA,IACpB;AAAA,EACJ;AAEA,QAAM,QAAiC,SACnC,KAAK,MAAM,OAAO,eAAe,IAAI,IACrC;AAEJ,QAAM,YAAY;AAClB,QAAM,aAAa;AAEnB,WAAS;AAET,QAAM,aAAa;AACnB,QAAM,YAAY;AAElB,SAAO;AACX;AApBgB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";var o=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var c=(r,t)=>o(r,"name",{value:t,configurable:!0});var d=(r,t)=>{for(var n in t)o(r,n,{get:t[n],enumerable:!0})},y=(r,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of l(t))!u.call(r,e)&&e!==n&&o(r,e,{get:()=>t[e],enumerable:!(a=i(t,e))||a.enumerable});return r};var p=r=>y(o({},"__esModule",{value:!0}),r);var S={};d(S,{hydrate:()=>g});module.exports=p(S);var s=require("./index.js");function g(r){const t=document.querySelector("script[data-tonic-ssr]"),n=t?JSON.parse(t.textContent||"{}"):null;return s.Tonic._ssrState=n,s.Tonic._hydrating=!0,r(),s.Tonic._hydrating=!1,s.Tonic._ssrState=null,n}c(g,"hydrate");
2
+ //# sourceMappingURL=hydrate.min.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/hydrate.ts"],
4
+ "sourcesContent": ["import { Tonic } from './index.js'\n\n/**\n * Hydrate server-rendered Tonic components.\n *\n * Call this to wrap component registration so that existing\n * server-rendered DOM is preserved instead of being re-rendered.\n * Event handlers are still attached, props are parsed from\n * attributes, and lifecycle hooks (`willConnect`, `connected`)\n * are called.\n *\n * If a `<script type=\"application/json\" data-tonic-ssr>` tag\n * exists in the document, its JSON content is parsed and used\n * to restore complex props (objects, arrays) for components\n * with matching `id` attributes.\n *\n * @param callback Register your components inside this callback\n * @returns The parsed SSR state, or null if none was embedded\n *\n * @example\n * ```ts\n * import { hydrate } from '@substrate-system/tonic/hydrate'\n * import { Tonic } from '@substrate-system/tonic'\n * import { MyApp } from './components.js'\n *\n * const state = hydrate(() => {\n * Tonic.add(MyApp)\n * })\n * ```\n */\nexport function hydrate (\n callback:() => void\n):Record<string, any>|null {\n const script = document.querySelector(\n 'script[data-tonic-ssr]'\n )\n\n const state:Record<string, any>|null = script ?\n JSON.parse(script.textContent || '{}') :\n null\n\n Tonic._ssrState = state\n Tonic._hydrating = true\n\n callback()\n\n Tonic._hydrating = false\n Tonic._ssrState = null\n\n return state\n}\n"],
5
+ "mappings": "4dAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAsB,sBA8Bf,SAASC,EACZC,EACuB,CACvB,MAAMC,EAAS,SAAS,cACpB,wBACJ,EAEMC,EAAiCD,EACnC,KAAK,MAAMA,EAAO,aAAe,IAAI,EACrC,KAEJ,eAAM,UAAYC,EAClB,QAAM,WAAa,GAEnBF,EAAS,EAET,QAAM,WAAa,GACnB,QAAM,UAAY,KAEXE,CACX,CApBgBC,EAAAJ,EAAA",
6
+ "names": ["hydrate_exports", "__export", "hydrate", "__toCommonJS", "import_index", "hydrate", "callback", "script", "state", "__name"]
7
+ }
@@ -0,0 +1,3 @@
1
+ var le=Object.defineProperty;var p=(n,s)=>le(n,"name",{value:s,configurable:!0});var Y=11;function oe(n,s){var e=s.attributes,t,i,r,o,a;if(!(s.nodeType===Y||n.nodeType===Y)){for(var f=e.length-1;f>=0;f--)t=e[f],i=t.name,r=t.namespaceURI,o=t.value,r?(i=t.localName||i,a=n.getAttributeNS(r,i),a!==o&&(t.prefix==="xmlns"&&(i=t.name),n.setAttributeNS(r,i,o))):(a=n.getAttribute(i),a!==o&&n.setAttribute(i,o));for(var u=n.attributes,v=u.length-1;v>=0;v--)t=u[v],i=t.name,r=t.namespaceURI,r?(i=t.localName||i,s.hasAttributeNS(r,i)||n.removeAttributeNS(r,i)):s.hasAttribute(i)||n.removeAttribute(i)}}p(oe,"morphAttrs");var $,de="http://www.w3.org/1999/xhtml",_=typeof document>"u"?void 0:document,ue=!!_&&"content"in _.createElement("template"),pe=!!_&&_.createRange&&"createContextualFragment"in _.createRange();function he(n){var s=_.createElement("template");return s.innerHTML=n,s.content.childNodes[0]}p(he,"createFragmentFromTemplate");function fe(n){$||($=_.createRange(),$.selectNode(_.body));var s=$.createContextualFragment(n);return s.childNodes[0]}p(fe,"createFragmentFromRange");function ve(n){var s=_.createElement("body");return s.innerHTML=n,s.childNodes[0]}p(ve,"createFragmentFromWrap");function ge(n){return n=n.trim(),ue?he(n):pe?fe(n):ve(n)}p(ge,"toElement");function F(n,s){var e=n.nodeName,t=s.nodeName,i,r;return e===t?!0:(i=e.charCodeAt(0),r=t.charCodeAt(0),i<=90&&r>=97?e===t.toUpperCase():r<=90&&i>=97?t===e.toUpperCase():!1)}p(F,"compareNodeNames");function ye(n,s){return!s||s===de?_.createElement(n):_.createElementNS(s,n)}p(ye,"createElementNS");function me(n,s){for(var e=n.firstChild;e;){var t=e.nextSibling;s.appendChild(e),e=t}return s}p(me,"moveChildren");function X(n,s,e){n[e]!==s[e]&&(n[e]=s[e],n[e]?n.setAttribute(e,""):n.removeAttribute(e))}p(X,"syncBooleanAttrProp");var Q={OPTION:p(function(n,s){var e=n.parentNode;if(e){var t=e.nodeName.toUpperCase();t==="OPTGROUP"&&(e=e.parentNode,t=e&&e.nodeName.toUpperCase()),t==="SELECT"&&!e.hasAttribute("multiple")&&(n.hasAttribute("selected")&&!s.selected&&(n.setAttribute("selected","selected"),n.removeAttribute("selected")),e.selectedIndex=-1)}X(n,s,"selected")},"OPTION"),INPUT:p(function(n,s){X(n,s,"checked"),X(n,s,"disabled"),n.value!==s.value&&(n.value=s.value),s.hasAttribute("value")||n.removeAttribute("value")},"INPUT"),TEXTAREA:p(function(n,s){var e=s.value;n.value!==e&&(n.value=e);var t=n.firstChild;if(t){var i=t.nodeValue;if(i==e||!e&&i==n.placeholder)return;t.nodeValue=e}},"TEXTAREA"),SELECT:p(function(n,s){if(!s.hasAttribute("multiple")){for(var e=-1,t=0,i=n.firstChild,r,o;i;)if(o=i.nodeName&&i.nodeName.toUpperCase(),o==="OPTGROUP")r=i,i=r.firstChild,i||(i=r.nextSibling,r=null);else{if(o==="OPTION"){if(i.hasAttribute("selected")){e=t;break}t++}i=i.nextSibling,!i&&r&&(i=r.nextSibling,r=null)}n.selectedIndex=e}},"SELECT")},L=1,ee=11,te=3,ne=8;function w(){}p(w,"noop");function Te(n){if(n)return n.getAttribute&&n.getAttribute("id")||n.id}p(Te,"defaultGetNodeKey");function _e(n){return p(function(e,t,i){if(i||(i={}),typeof t=="string")if(e.nodeName==="#document"||e.nodeName==="HTML"||e.nodeName==="BODY"){var r=t;t=_.createElement("html"),t.innerHTML=r}else t=ge(t);else t.nodeType===ee&&(t=t.firstElementChild);var o=i.getNodeKey||Te,a=i.onBeforeNodeAdded||w,f=i.onNodeAdded||w,u=i.onBeforeElUpdated||w,v=i.onElUpdated||w,d=i.onBeforeNodeDiscarded||w,y=i.onNodeDiscarded||w,N=i.onBeforeElChildrenUpdated||w,re=i.skipFromChildren||w,K=i.addChild||function(c,l){return c.appendChild(l)},D=i.childrenOnly===!0,M=Object.create(null),O=[];function I(c){O.push(c)}p(I,"addKeyedRemoval");function J(c,l){if(c.nodeType===L)for(var m=c.firstChild;m;){var h=void 0;l&&(h=o(m))?I(h):(y(m),m.firstChild&&J(m,l)),m=m.nextSibling}}p(J,"walkDiscardedChildNodes");function H(c,l,m){d(c)!==!1&&(l&&l.removeChild(c),y(c),J(c,m))}p(H,"removeNode");function V(c){if(c.nodeType===L||c.nodeType===ee)for(var l=c.firstChild;l;){var m=o(l);m&&(M[m]=l),V(l),l=l.nextSibling}}p(V,"indexTree"),V(e);function B(c){f(c);for(var l=c.firstChild;l;){var m=l.nextSibling,h=o(l);if(h){var g=M[h];g&&F(l,g)?(l.parentNode.replaceChild(g,l),j(g,l)):B(l)}else B(l);l=m}}p(B,"handleNodeAdded");function se(c,l,m){for(;l;){var h=l.nextSibling;(m=o(l))?I(m):H(l,c,!0),l=h}}p(se,"cleanupFromEl");function j(c,l,m){var h=o(l);if(h&&delete M[h],!m){var g=u(c,l);if(g===!1||(g instanceof HTMLElement&&(c=g,V(c)),n(c,l),v(c),N(c,l)===!1))return}c.nodeName!=="TEXTAREA"?ae(c,l):Q.TEXTAREA(c,l)}p(j,"morphEl");function ae(c,l){var m=re(c,l),h=l.firstChild,g=c.firstChild,x,b,E,k,A;e:for(;h;){for(k=h.nextSibling,x=o(h);!m&&g;){if(E=g.nextSibling,h.isSameNode&&h.isSameNode(g)){h=k,g=E;continue e}b=o(g);var U=g.nodeType,S=void 0;if(U===h.nodeType&&(U===L?(x?x!==b&&((A=M[x])?E===A?S=!1:(c.insertBefore(A,g),b?I(b):H(g,c,!0),g=A,b=o(g)):S=!1):b&&(S=!1),S=S!==!1&&F(g,h),S&&j(g,h)):(U===te||U==ne)&&(S=!0,g.nodeValue!==h.nodeValue&&(g.nodeValue=h.nodeValue))),S){h=k,g=E;continue e}b?I(b):H(g,c,!0),g=E}if(x&&(A=M[x])&&F(A,h))m||K(c,A),j(A,h);else{var z=a(h);z!==!1&&(z&&(h=z),h.actualize&&(h=h.actualize(c.ownerDocument||_)),K(c,h),B(h))}h=k,g=E}se(c,g,b);var Z=Q[c.nodeName];Z&&Z(c,l)}p(ae,"morphChildren");var T=e,P=T.nodeType,W=t.nodeType;if(!D){if(P===L)W===L?F(e,t)||(y(e),T=me(e,ye(t.nodeName,t.namespaceURI))):T=t;else if(P===te||P===ne){if(W===P)return T.nodeValue!==t.nodeValue&&(T.nodeValue=t.nodeValue),T;T=t}}if(T===t)y(e);else{if(t.isSameNode&&t.isSameNode(T))return;if(j(T,t,D),O)for(var G=0,ce=O.length;G<ce;G++){var q=M[O[G]];q&&H(q,q.parentNode,!1)}}return!D&&T!==e&&e.parentNode&&(T.actualize&&(T=T.actualize(e.ownerDocument||_)),e.parentNode.replaceChild(T,e)),T},"morphdom")}p(_e,"morphdomFactory");var be=_e(oe),ie=be;var C=class{static{p(this,"TonicTemplate")}constructor(s,e,t){this.isTonicTemplate=!0,this.unsafe=!!t,this.rawText=s,this.templateStrings=e}valueOf(){return this.rawText}toString(){return this.rawText}},R=class n extends window.HTMLElement{constructor(){super();this._props=n.getPropertyNames(this);let e=n._states[super.id];delete n._states[super.id],this._state=e||{},this.preventRenderOnReconnect=!1,this.props={},this.elements=[...this.children],this.elements.__children__=!0,this.nodes=[...this.childNodes],this.nodes.__children__=!0,this._events()}static{p(this,"Tonic")}static{this._tags=""}static{this._refIds=[]}static{this._data={}}static{this._states={}}static{this._children={}}static{this._reg={}}static{this._stylesheetRegistry=[]}static{this._index=0}static get version(){return VERSION??null}static get SPREAD(){return/\.\.\.\s?(__\w+__\w+__)/g}static get ESC(){return/["&'<>`/]/g}static get AsyncFunctionGenerator(){return async function*(){}.constructor}static get AsyncFunction(){return async function(){}.constructor}static get MAP(){return{'"':"&quot;","&":"&amp;","'":"&#x27;","<":"&lt;",">":"&gt;","`":"&#x60;","/":"&#x2F;"}}static{this._hydrating=!1}static{this._ssrState=null}defaults(){return{}}get isTonicComponent(){return!0}static event(e){return`${this.TAG}:${e}`}static get TAG(){return n.getTagName(this.name)}static _createId(){return`tonic${n._index++}`}static _normalizeAttrs(e,t={}){return[...e].forEach(i=>t[i.name]=i.value),t}_checkId(){let e=super.id;if(!e){let t=this.outerHTML.replace(this.innerHTML,"...");throw new Error(`Component: ${t} has no id`)}return e}get state(){return this._checkId(),this._state}set state(e){this._state=(this._checkId(),e)}_events(){let e=Object.getOwnPropertyNames(window.HTMLElement.prototype);for(let t of this._props){if(!t.includes("handle_"))continue;let i=t.split("_")[1];e.indexOf("on"+i)!==-1&&this.addEventListener(i,this)}}_prop(e){let t=this._id,i=`__${t}__${n._createId()}__`;return n._data[t]=n._data[t]||{},n._data[t][i]=e,i}_placehold(e){let t=this._id,i=`placehold:${t}:${n._createId()}__`;return n._children[t]=n._children[t]||{},n._children[t][i]=e,i}static match(e,t){return e.matches||(e=e.parentElement),e.matches(t)?e:e.closest(t)}static getTagName(e){return e.match(/[A-Z][a-z0-9]*/g).join("-").toLowerCase()}static getPropertyNames(e){let t=[];for(;e&&e!==n.prototype;)t.push(...Object.getOwnPropertyNames(e)),e=Object.getPrototypeOf(e);return t}static add(e,t){if(!(t||e.name&&e.name.length>1))throw Error("Mangling. https://bit.ly/2TkJ6zP");if(t||(t=n.getTagName(e.name)),!n.ssr&&window.customElements.get(t))throw new Error(`Cannot Tonic.add(${e.name}, '${t}') twice`);if(!e.prototype||!e.prototype.isTonicComponent){let r={[e.name]:class extends n{render(){return new C("",null)}}}[e.name];r.prototype.render=e,e=r}return e.prototype._props=n.getPropertyNames(e.prototype),n._reg[t]=e,n._tags=Object.keys(n._reg).join(),window.customElements.define(t,e),typeof e.stylesheet=="function"&&n.registerStyles(e.stylesheet),e}static registerStyles(e){if(n._stylesheetRegistry.includes(e))return;n._stylesheetRegistry.push(e);let t=document.createElement("style");n.nonce&&t.setAttribute("nonce",n.nonce),t.appendChild(document.createTextNode(e())),document.head&&document.head.appendChild(t)}static escape(e){return e.replace(n.ESC,t=>n.MAP[t])}static unsafeRawString(e,t){return new C(e,t,!0)}dispatch(e,t=null){let i={bubbles:!0,detail:t};this.dispatchEvent(new window.CustomEvent(e,i))}emit(e,t={},i={}){let r=n.getTagName(this.constructor.name),o=new CustomEvent(`${r}:${e}`,{bubbles:i.bubbles===void 0?!0:i.bubbles,cancelable:i.cancelable===void 0?!0:i.cancelable,detail:t});return this.dispatchEvent(o)}html(e,...t){let i=p(a=>{if(a&&a.__children__)return this._placehold(a);if(a&&a.isTonicTemplate)return a.rawText;switch(Object.prototype.toString.call(a)){case"[object HTMLCollection]":case"[object NodeList]":return this._placehold([...a]);case"[object Array]":return a.every(f=>f.isTonicTemplate&&!f.unsafe)?new C(a.join(`
2
+ `),null,!1):this._prop(a);case"[object Object]":case"[object Function]":case"[object AsyncFunction]":case"[object Set]":case"[object Map]":case"[object WeakMap]":case"[object File]":return this._prop(a);case"[object NamedNodeMap]":return this._prop(n._normalizeAttrs(a));case"[object Number]":return`${a}__float`;case"[object String]":return n.escape(a);case"[object Boolean]":return`${a}__boolean`;case"[object Null]":return`${a}__null`;case"[object HTMLElement]":return this._placehold([a])}return typeof a=="object"&&a&&a.nodeType===1&&typeof a.cloneNode=="function"?this._placehold([a]):a},"refs"),r=[];for(let a=0;a<e.length-1;a++)r.push(e[a],i(t[a]));r.push(e[e.length-1]);let o=r.join("").replace(n.SPREAD,(a,f)=>{let u=n._data[f.split("__")[1]][f];return Object.entries(u).map(([v,d])=>{let y=v.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();return d===!0?y:d?`${y}="${n.escape(String(d))}"`:""}).filter(Boolean).join(" ")}).replace(/(\d+(?:\.\d+)?)__float/g,"$1").replace(/(true|false)__boolean/g,"$1").replace(/null__null/g,"null");return new C(o,e,!1)}scheduleReRender(e){return this.pendingReRender?this.pendingReRender:(this.pendingReRender=new Promise(t=>setTimeout(()=>{if(!this.isInDocument(this.shadowRoot||this))return;let i=this._set(this.shadowRoot||this,this.render);if(this.pendingReRender=null,i&&i.then)return i.then(()=>{this.updated&&this.updated(e),t(this)});this.updated&&this.updated(e),t(this)},0)),this.pendingReRender)}reRender(e=this.props){let t={...this.props};return this.props=typeof e=="function"?e(t):e,this.scheduleReRender(t)}handleEvent(e){this["handle_"+e.type]&&this["handle_"+e.type](e)}_drainIterator(e,t){return t.next().then(i=>{if(this._set(e,null,i.value),!i.done)return this._drainIterator(e,t)})}_set(e,t,i=""){this.willRender&&this.willRender();for(let r of e.querySelectorAll(n._tags)){if(!r.isTonicComponent)continue;let o=r.getAttribute("id");!o||!n._refIds.includes(o)||(n._states[o]=r.state)}if(t instanceof n.AsyncFunction)return t.call(this,this.html,this.props).then(r=>this._apply(e,r));if(t instanceof n.AsyncFunctionGenerator)return this._drainIterator(e,t.call(this));t===null?this._apply(e,i):t instanceof Function&&this._apply(e,t.call(this,this.html,this.props)||"")}_apply(e,t){if(t&&t.isTonicTemplate?t=t.rawText:typeof t=="string"&&(t=n.escape(t)),typeof t=="string"){this.stylesheet&&(t=`<style nonce=${n.nonce||""}>${this.stylesheet()}</style>${t}`);let i=e.querySelector&&(e.querySelector("input")||e.querySelector("textarea")||e.querySelector("select"));if(i&&document.activeElement&&(e.contains(document.activeElement)||e===document.activeElement)){let f=document.createElement("div");f.innerHTML=t,ie(e,f,{childrenOnly:!0,onBeforeElUpdated:p((u,v)=>{if(u.isEqualNode&&u.isEqualNode(v))return!1;if(u.tagName==="INPUT"&&v.tagName==="INPUT"){let d=u,y=v;d.value!==""&&(y.value=d.value),document.activeElement===d&&(y.setAttribute("data-preserve-focus","true"),y.setAttribute("data-selection-start",String(d.selectionStart||0)),y.setAttribute("data-selection-end",String(d.selectionEnd||0)))}if(u.tagName==="TEXTAREA"&&v.tagName==="TEXTAREA"){let d=u,y=v;d.value!==""&&(y.value=d.value),document.activeElement===d&&(y.setAttribute("data-preserve-focus","true"),y.setAttribute("data-selection-start",String(d.selectionStart||0)),y.setAttribute("data-selection-end",String(d.selectionEnd||0)))}return!0},"onBeforeElUpdated"),onElUpdated:p(u=>{if(!u.hasAttribute("data-preserve-focus"))return;let v=parseInt(u.getAttribute("data-selection-start")||"0",10),d=parseInt(u.getAttribute("data-selection-end")||"0",10);u.removeAttribute("data-preserve-focus"),u.removeAttribute("data-selection-start"),u.removeAttribute("data-selection-end"),u.focus(),"setSelectionRange"in u&&u.setSelectionRange(v,d)},"onElUpdated")})}else{let f="input, textarea, select",u=[];if(i){let v=e.querySelectorAll(f);for(let d of v){let y=d,N=y.type==="checkbox"||y.type==="radio";u.push({v:d.value,c:y.checked,dirty:N?y.checked!==y.defaultChecked:d.value!==d.defaultValue})}}if(e.innerHTML=t,u.length){let v=e.querySelectorAll(f);for(let d=0;d<Math.min(u.length,v.length);d++){if(!u[d].dirty)continue;let y=v[d],N=y.type;N==="checkbox"||N==="radio"?y.checked=u[d].c:y.value=u[d].v}}}if(this.styles){let f=this.styles();for(let u of e.querySelectorAll("[styles]"))for(let v of u.getAttribute("styles").split(/\s+/))Object.assign(u.style,f[v.trim()])}let o=n._children[this._id]||{},a=p((f,u)=>{if(f.nodeType===3){let d=f.textContent.trim();o[d]&&u(f,o[d],d)}let v=f.childNodes;if(v)for(let d=0;d<v.length;d++)a(v[d],u)},"walk");a(e,(f,u,v)=>{for(let d of u)f.parentNode.insertBefore(d,f);delete n._children[this._id][v],f.parentNode.removeChild(f)})}else e.innerHTML="",e.appendChild(t.cloneNode(!0))}connectedCallback(){this.root=this.shadowRoot||this,super.id&&!n._refIds.includes(super.id)&&n._refIds.push(super.id);let e=p(t=>t.replace(/-(.)/g,(i,r)=>r.toUpperCase()),"cc");for(let{name:t,value:i}of this.attributes){let r=e(t),o=this.props[r]=i;if(/__\w+__\w+__/.test(o)){let{1:a}=o.split("__");this.props[r]=n._data[a][o]}else if(/\d+__float/.test(o))this.props[r]=parseFloat(o);else if(o==="null__null")this.props[r]=null;else if(/\w+__boolean/.test(o))this.props[r]=o.includes("true");else if(/placehold:\w+:\w+__/.test(o)){let{1:a}=o.split(":");this.props[r]=n._children[a][o][0]}}if(this.props=Object.assign(this.defaults(),this.props),this._id=this._id||n._createId(),this.willConnect&&this.willConnect(),!!this.isInDocument(this.root)){if(n._hydrating){super.id&&n._ssrState?.[super.id]&&(this.props=Object.assign(this.props,n._ssrState[super.id])),this._source=this.innerHTML,this.connected&&this.connected();return}if(!this.preventRenderOnReconnect){this._source?this.innerHTML=this._source:this._source=this.innerHTML;let t=this._set(this.root,this.render);if(t&&t.then)return t.then(()=>this.connected&&this.connected())}this.connected&&this.connected()}}isInDocument(e){let t=e.getRootNode();return t===document||t.toString()==="[object ShadowRoot]"}disconnectedCallback(){this.disconnected&&this.disconnected(),delete n._data[this._id],delete n._children[this._id]}};function Ce(n){let s=document.querySelector("script[data-tonic-ssr]"),e=s?JSON.parse(s.textContent||"{}"):null;return R._ssrState=e,R._hydrating=!0,n(),R._hydrating=!1,R._ssrState=null,e}p(Ce,"hydrate");export{Ce as hydrate};
3
+ //# sourceMappingURL=hydrate.min.mjs.map