Rocket Projection Pro

Rocket is currently in beta.

A small demo showing how Rocket components can work with host-provided children in both light DOM and shadow DOM.

Demo

CSS styling is applied to all elements, since this is a light DOM component.


CSS styling is applied to slotted content only, since this is a shadow DOM component.

Explanation #

This is an intentional advanced example. Unlike the simpler prop-driven demos, host-provided children here are supposed to read and write component-local $$ state after Rocket rewrites those expressions into the instance scope.

Usage Example #

 1<light-counter>
 2    <div class="callout success">
 3        <button
 4            data-on:click="$$clicks++"
 5            data-text="'Light clicks: ' + $$clicks"
 6        ></button>
 7    </div>
 8</light-counter>
 9
10<slot-counter>
11    <button
12        data-on:click="$$clicks++"
13        data-text="'Shadow clicks: ' + $$clicks"
14    ></button>
15</slot-counter>

Rocket Components #

 1import { rocket } from 'datastar'
 2
 3const rewriteRocketScopedChildren = (root, base) => {
 4  if (!base) return
 5  for (const node of root.querySelectorAll('*')) {
 6    for (const { name, value } of [...node.attributes]) {
 7      if (!name.startsWith('data-') || !value.includes('$$')) continue
 8      node.setAttribute(
 9        name,
10        value.replace(
11          /\$\$([a-zA-Z_\d]\w*(?:[.-]\w+)*)/g,
12          (_, path) => `$${'.'}${base}.${path}`,
13        ),
14      )
15    }
16  }
17}
18
19rocket('light-counter', {
20  mode: 'light',
21  props: ({ number }) => ({ clicks: number }),
22  setup: ({ $$, props }) => {
23    $$.clicks = props.clicks
24  },
25  render: ({ html }) => html`
26    <div data-rocket-content>
27      <slot></slot>
28    </div>
29  `,
30})
31
32rocket('slot-counter', {
33  props: ({ number }) => ({ clicks: number }),
34  setup: ({ apply, host, $$, props }) => {
35    $$.clicks = props.clicks
36    rewriteRocketScopedChildren(host, host.rocketSignalPath)
37    apply(host, false)
38  },
39  render: ({ html }) => html`
40    <div class="callout success">
41      <slot></slot>
42    </div>
43  `,
44})