Rocket Letter Stream Pro
Rocket is a Pro feature, currently in beta.
Explanation #
This is the kind of component where plain setup() is still the right tool: it owns local animated state, but it does not need any rendered refs. The outer loop uses the default i index, while the inner loops bind j and k.
The component starts from a seed string, derives named blocks and rows from that stream, and appends one more letter per animation frame until it reaches Z.
Usage Example #
1<alphabet-stream seed="ABCDEF"></alphabet-stream>Rocket Component #
1import { rocket } from 'datastar'
2
3rocket('alphabet-stream', {
4 props({ string }) {
5 return { seed: string.default('ABCDEF') }
6 },
7 setup({ props, $$ }) {
8 $$.letters = props.seed.split('')
9 $$.blocks = () => {
10 const letters = [...$$.letters]
11 const blocks = []
12 for (let offset = 0; offset < letters.length; offset += 9) {
13 const rows = []
14 for (let rowOffset = offset; rowOffset < offset + 9; rowOffset += 3) {
15 const cells = letters.slice(rowOffset, rowOffset + 3)
16 if (!cells.length) continue
17 rows.push({
18 name: `Row ${rows.length + 1}`,
19 cells,
20 })
21 }
22 if (!rows.length) continue
23 blocks.push({
24 name: `Block ${blocks.length + 1}`,
25 rows,
26 })
27 }
28 return blocks
29 }
30 let nextCode = 65 + $$.letters.length
31 const streamNextLetter = () => {
32 $$.letters.push(String.fromCharCode(nextCode++))
33 if (nextCode <= 90) requestAnimationFrame(streamNextLetter)
34 }
35 requestAnimationFrame(streamNextLetter)
36 },
37 render: ({ html }) => html`
38 <section>
39 <style>
40 :host {
41 display: block;
42 }
43
44 section {
45 display: grid;
46 gap: 0.75rem;
47 }
48
49 ul,
50 ol {
51 display: flex;
52 flex-wrap: wrap;
53 gap: 0.5rem;
54 list-style: none;
55 padding: 0;
56 margin: 0;
57 }
58
59 .block-list {
60 display: grid;
61 gap: 1rem;
62 }
63
64 .block-card {
65 display: grid;
66 gap: 0.75rem;
67 padding: 1rem;
68 border: 1px solid var(--gray-5);
69 border-radius: 1rem;
70 background: linear-gradient(180deg, var(--gray-1), var(--gray-2));
71 }
72
73 .block-card h4,
74 .block-card h5 {
75 margin: 0;
76 }
77
78 .row-list {
79 display: grid;
80 gap: 0.75rem;
81 }
82
83 .cell-list li {
84 padding: 0.35rem 0.6rem;
85 border-radius: 999px;
86 background: var(--blue-2);
87 color: var(--blue-12);
88 border: 1px solid var(--blue-6);
89 }
90
91 li strong {
92 font-variant-numeric: tabular-nums;
93 margin-right: 0.25rem;
94 }
95
96 p {
97 margin: 0;
98 color: var(--gray-11);
99 }
100
101 code {
102 color: var(--gray-12);
103 }
104 </style>
105
106 <h3>Letter Stream</h3>
107 <p>
108 This example nests three Rocket loops to exercise default and named aliases:
109 outer <code>i</code>, middle <code>j</code>, inner <code>k</code>.
110 </p>
111 <div class="block-list">
112 <template data-for="block in $$blocks">
113 <section class="block-card">
114 <h4 data-text="block.name"></h4>
115 <div class="row-list">
116 <template data-for="row, j in block.rows">
117 <article>
118 <h5 data-text="row.name"></h5>
119 <ol class="cell-list">
120 <template data-for="letter, k in row.cells">
121 <li>
122 <strong data-text="letter"></strong>
123 <span data-text="i + ':' + j + ':' + k"></span>
124 </li>
125 </template>
126 </ol>
127 </article>
128 </template>
129 </div>
130 </section>
131 </template>
132 </div>
133 <div data-text="$$letters.join(' ')"></div>
134 </section>
135 `,
136})