@adaas/are-html 0.0.21 → 0.0.23

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 (154) hide show
  1. package/.conf/tsconfig.base.json +1 -0
  2. package/.conf/tsconfig.browser.json +1 -0
  3. package/.conf/tsconfig.node.json +1 -0
  4. package/dist/browser/index.d.mts +214 -3
  5. package/dist/browser/index.mjs +787 -201
  6. package/dist/browser/index.mjs.map +1 -1
  7. package/dist/node/{AreBinding.attribute-doUvtOjc.d.mts → AreBinding.attribute-BWzEIw6H.d.mts} +45 -0
  8. package/dist/node/{AreBinding.attribute-Bm5LlOyE.d.ts → AreBinding.attribute-GpT-5Qmf.d.ts} +45 -0
  9. package/dist/node/attributes/AreBinding.attribute.d.mts +1 -1
  10. package/dist/node/attributes/AreBinding.attribute.d.ts +1 -1
  11. package/dist/node/attributes/AreDirective.attribute.d.mts +1 -1
  12. package/dist/node/attributes/AreDirective.attribute.d.ts +1 -1
  13. package/dist/node/attributes/AreEvent.attribute.d.mts +1 -1
  14. package/dist/node/attributes/AreEvent.attribute.d.ts +1 -1
  15. package/dist/node/attributes/AreStatic.attribute.d.mts +1 -1
  16. package/dist/node/attributes/AreStatic.attribute.d.ts +1 -1
  17. package/dist/node/directives/AreDirectiveFor.directive.d.mts +55 -2
  18. package/dist/node/directives/AreDirectiveFor.directive.d.ts +55 -2
  19. package/dist/node/directives/AreDirectiveFor.directive.js +141 -12
  20. package/dist/node/directives/AreDirectiveFor.directive.js.map +1 -1
  21. package/dist/node/directives/AreDirectiveFor.directive.mjs +141 -12
  22. package/dist/node/directives/AreDirectiveFor.directive.mjs.map +1 -1
  23. package/dist/node/directives/AreDirectiveIf.directive.d.mts +1 -1
  24. package/dist/node/directives/AreDirectiveIf.directive.d.ts +1 -1
  25. package/dist/node/directives/AreDirectiveShow.directive.d.mts +1 -1
  26. package/dist/node/directives/AreDirectiveShow.directive.d.ts +1 -1
  27. package/dist/node/engine/AreHTML.compiler.d.mts +1 -1
  28. package/dist/node/engine/AreHTML.compiler.d.ts +1 -1
  29. package/dist/node/engine/AreHTML.compiler.js +4 -0
  30. package/dist/node/engine/AreHTML.compiler.js.map +1 -1
  31. package/dist/node/engine/AreHTML.compiler.mjs +4 -0
  32. package/dist/node/engine/AreHTML.compiler.mjs.map +1 -1
  33. package/dist/node/engine/AreHTML.constants.d.mts +33 -1
  34. package/dist/node/engine/AreHTML.constants.d.ts +33 -1
  35. package/dist/node/engine/AreHTML.constants.js +166 -0
  36. package/dist/node/engine/AreHTML.constants.js.map +1 -1
  37. package/dist/node/engine/AreHTML.constants.mjs +165 -1
  38. package/dist/node/engine/AreHTML.constants.mjs.map +1 -1
  39. package/dist/node/engine/AreHTML.context.d.mts +66 -0
  40. package/dist/node/engine/AreHTML.context.d.ts +66 -0
  41. package/dist/node/engine/AreHTML.context.js +98 -0
  42. package/dist/node/engine/AreHTML.context.js.map +1 -1
  43. package/dist/node/engine/AreHTML.context.mjs +98 -0
  44. package/dist/node/engine/AreHTML.context.mjs.map +1 -1
  45. package/dist/node/engine/AreHTML.interpreter.d.mts +3 -0
  46. package/dist/node/engine/AreHTML.interpreter.d.ts +3 -0
  47. package/dist/node/engine/AreHTML.interpreter.js +66 -10
  48. package/dist/node/engine/AreHTML.interpreter.js.map +1 -1
  49. package/dist/node/engine/AreHTML.interpreter.mjs +66 -10
  50. package/dist/node/engine/AreHTML.interpreter.mjs.map +1 -1
  51. package/dist/node/engine/AreHTML.lifecycle.d.mts +2 -2
  52. package/dist/node/engine/AreHTML.lifecycle.d.ts +2 -2
  53. package/dist/node/engine/AreHTML.lifecycle.js +32 -4
  54. package/dist/node/engine/AreHTML.lifecycle.js.map +1 -1
  55. package/dist/node/engine/AreHTML.lifecycle.mjs +32 -4
  56. package/dist/node/engine/AreHTML.lifecycle.mjs.map +1 -1
  57. package/dist/node/engine/AreHTML.tokenizer.d.mts +1 -1
  58. package/dist/node/engine/AreHTML.tokenizer.d.ts +1 -1
  59. package/dist/node/engine/AreHTML.tokenizer.js +7 -1
  60. package/dist/node/engine/AreHTML.tokenizer.js.map +1 -1
  61. package/dist/node/engine/AreHTML.tokenizer.mjs +7 -1
  62. package/dist/node/engine/AreHTML.tokenizer.mjs.map +1 -1
  63. package/dist/node/engine/AreHTML.transformer.d.mts +1 -1
  64. package/dist/node/engine/AreHTML.transformer.d.ts +1 -1
  65. package/dist/node/helpers/AreScheduler.helper.d.mts +39 -0
  66. package/dist/node/helpers/AreScheduler.helper.d.ts +39 -0
  67. package/dist/node/helpers/AreScheduler.helper.js +40 -0
  68. package/dist/node/helpers/AreScheduler.helper.js.map +1 -0
  69. package/dist/node/helpers/AreScheduler.helper.mjs +40 -0
  70. package/dist/node/helpers/AreScheduler.helper.mjs.map +1 -0
  71. package/dist/node/index.d.mts +4 -3
  72. package/dist/node/index.d.ts +4 -3
  73. package/dist/node/index.js +7 -0
  74. package/dist/node/index.mjs +1 -0
  75. package/dist/node/instructions/AddStaticHTML.instruction.d.mts +8 -0
  76. package/dist/node/instructions/AddStaticHTML.instruction.d.ts +8 -0
  77. package/dist/node/instructions/AddStaticHTML.instruction.js +31 -0
  78. package/dist/node/instructions/AddStaticHTML.instruction.js.map +1 -0
  79. package/dist/node/instructions/AddStaticHTML.instruction.mjs +24 -0
  80. package/dist/node/instructions/AddStaticHTML.instruction.mjs.map +1 -0
  81. package/dist/node/instructions/AreHTML.instructions.constants.d.mts +1 -0
  82. package/dist/node/instructions/AreHTML.instructions.constants.d.ts +1 -0
  83. package/dist/node/instructions/AreHTML.instructions.constants.js +1 -0
  84. package/dist/node/instructions/AreHTML.instructions.constants.js.map +1 -1
  85. package/dist/node/instructions/AreHTML.instructions.constants.mjs +1 -0
  86. package/dist/node/instructions/AreHTML.instructions.constants.mjs.map +1 -1
  87. package/dist/node/instructions/AreHTML.instructions.types.d.mts +9 -1
  88. package/dist/node/instructions/AreHTML.instructions.types.d.ts +9 -1
  89. package/dist/node/lib/AreDirective/AreDirective.component.d.mts +1 -1
  90. package/dist/node/lib/AreDirective/AreDirective.component.d.ts +1 -1
  91. package/dist/node/lib/AreDirective/AreDirective.types.d.mts +1 -1
  92. package/dist/node/lib/AreDirective/AreDirective.types.d.ts +1 -1
  93. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.mts +1 -1
  94. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.ts +1 -1
  95. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.mts +1 -1
  96. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.ts +1 -1
  97. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.mts +1 -1
  98. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.ts +1 -1
  99. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js +51 -0
  100. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js.map +1 -1
  101. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs +51 -0
  102. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs.map +1 -1
  103. package/dist/node/lib/AreRoot/AreRoot.component.js +1 -1
  104. package/dist/node/lib/AreRoot/AreRoot.component.js.map +1 -1
  105. package/dist/node/lib/AreRoot/AreRoot.component.mjs +1 -1
  106. package/dist/node/lib/AreRoot/AreRoot.component.mjs.map +1 -1
  107. package/dist/node/nodes/AreComment.d.mts +1 -1
  108. package/dist/node/nodes/AreComment.d.ts +1 -1
  109. package/dist/node/nodes/AreComponent.d.mts +1 -1
  110. package/dist/node/nodes/AreComponent.d.ts +1 -1
  111. package/dist/node/nodes/AreInterpolation.d.mts +1 -1
  112. package/dist/node/nodes/AreInterpolation.d.ts +1 -1
  113. package/dist/node/nodes/AreRoot.d.mts +1 -1
  114. package/dist/node/nodes/AreRoot.d.ts +1 -1
  115. package/dist/node/nodes/AreText.d.mts +1 -1
  116. package/dist/node/nodes/AreText.d.ts +1 -1
  117. package/examples/dashboard/concept.ts +1 -1
  118. package/examples/dashboard/dist/index.html +1 -1
  119. package/examples/dashboard/dist/{mq19zxz4-mnlgmd.js → mqiw5sqa-ypckmj.js} +2275 -1323
  120. package/examples/dashboard/src/concept.ts +3 -2
  121. package/examples/for-perf/concept.ts +45 -0
  122. package/examples/for-perf/containers/UI.container.ts +161 -0
  123. package/examples/for-perf/dist/index.html +270 -0
  124. package/examples/for-perf/dist/mqj1mpf2-z4aokv.js +15664 -0
  125. package/examples/for-perf/dist/mqj1mpff-4fr7mw.js +15664 -0
  126. package/examples/for-perf/public/index.html +270 -0
  127. package/examples/for-perf/src/components/PerfApp.component.ts +37 -0
  128. package/examples/for-perf/src/components/PerfControls.component.ts +34 -0
  129. package/examples/for-perf/src/components/PerfGrid.component.ts +225 -0
  130. package/examples/for-perf/src/components/PerfHeader.component.ts +34 -0
  131. package/examples/for-perf/src/components/PerfStats.component.ts +43 -0
  132. package/examples/for-perf/src/concept.ts +94 -0
  133. package/examples/jumpstart/dist/index.html +1 -1
  134. package/examples/jumpstart/dist/{mq7hqrxy-4kus50.js → mq7mgf58-vbf07e.js} +269 -91
  135. package/examples/signal-routing/dist/index.html +1 -1
  136. package/examples/signal-routing/dist/{mq7k53th-qiwy4x.js → mqiwo23h-bhcolu.js} +2090 -1430
  137. package/jest.config.ts +1 -0
  138. package/package.json +10 -9
  139. package/src/directives/AreDirectiveFor.directive.ts +233 -19
  140. package/src/engine/AreHTML.compiler.ts +13 -0
  141. package/src/engine/AreHTML.constants.ts +142 -0
  142. package/src/engine/AreHTML.context.ts +112 -0
  143. package/src/engine/AreHTML.interpreter.ts +114 -13
  144. package/src/engine/AreHTML.lifecycle.ts +91 -7
  145. package/src/engine/AreHTML.tokenizer.ts +30 -1
  146. package/src/helpers/AreScheduler.helper.ts +61 -0
  147. package/src/index.ts +1 -0
  148. package/src/instructions/AddStaticHTML.instruction.ts +23 -0
  149. package/src/instructions/AreHTML.instructions.constants.ts +1 -0
  150. package/src/instructions/AreHTML.instructions.types.ts +9 -0
  151. package/src/lib/AreHTMLNode/AreHTMLNode.ts +74 -0
  152. package/src/lib/AreRoot/AreRoot.component.ts +4 -1
  153. package/tests/StaticIsland.test.ts +115 -0
  154. package/tsconfig.json +1 -0
@@ -0,0 +1,270 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>ARE $for Performance Lab</title>
8
+ <style>
9
+ * {
10
+ box-sizing: border-box;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ body {
16
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
17
+ background: #0f0f17;
18
+ color: #e5e7eb;
19
+ }
20
+
21
+ are-root {
22
+ display: block;
23
+ min-height: 100vh;
24
+ }
25
+
26
+ .app {
27
+ max-width: 1100px;
28
+ margin: 0 auto;
29
+ padding: 24px 20px 60px;
30
+ }
31
+
32
+ /* ---------- header ---------- */
33
+ .header {
34
+ display: flex;
35
+ align-items: baseline;
36
+ justify-content: space-between;
37
+ gap: 16px;
38
+ padding-bottom: 16px;
39
+ border-bottom: 1px solid #23232f;
40
+ flex-wrap: wrap;
41
+ }
42
+
43
+ .brand {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 10px;
47
+ }
48
+
49
+ .logo {
50
+ font-size: 22px;
51
+ color: #7c3aed;
52
+ }
53
+
54
+ .title {
55
+ font-size: 20px;
56
+ font-weight: 700;
57
+ }
58
+
59
+ .subtitle {
60
+ font-size: 12px;
61
+ color: #8b8b9b;
62
+ }
63
+
64
+ /* ---------- legend ---------- */
65
+ .legend {
66
+ display: flex;
67
+ gap: 10px;
68
+ flex-wrap: wrap;
69
+ margin: 18px 0 10px;
70
+ }
71
+
72
+ .legend-card {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: 2px;
76
+ background: #181824;
77
+ border: 1px solid #23232f;
78
+ border-radius: 8px;
79
+ padding: 8px 12px;
80
+ min-width: 130px;
81
+ }
82
+
83
+ .legend-key {
84
+ font-size: 11px;
85
+ text-transform: uppercase;
86
+ letter-spacing: 0.06em;
87
+ color: #7c3aed;
88
+ font-weight: 700;
89
+ }
90
+
91
+ .legend-label {
92
+ font-size: 12px;
93
+ color: #b6b6c6;
94
+ }
95
+
96
+ /* ---------- hint ---------- */
97
+ .hint {
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 8px;
101
+ font-size: 12px;
102
+ color: #8b8b9b;
103
+ margin-bottom: 18px;
104
+ }
105
+
106
+ .hint-icon {
107
+ color: #7c3aed;
108
+ }
109
+
110
+ /* ---------- toolbar ---------- */
111
+ .toolbar {
112
+ display: flex;
113
+ gap: 8px;
114
+ flex-wrap: wrap;
115
+ align-items: center;
116
+ margin-bottom: 12px;
117
+ }
118
+
119
+ .btn {
120
+ background: #1f1f2e;
121
+ color: #e5e7eb;
122
+ border: 1px solid #2d2d3d;
123
+ border-radius: 6px;
124
+ padding: 8px 14px;
125
+ font-size: 13px;
126
+ cursor: pointer;
127
+ transition: background 0.15s, border-color 0.15s;
128
+ }
129
+
130
+ .btn:hover {
131
+ background: #2a2a3e;
132
+ border-color: #7c3aed;
133
+ }
134
+
135
+ .btn-danger:hover {
136
+ border-color: #ef4444;
137
+ }
138
+
139
+ .sep {
140
+ width: 1px;
141
+ height: 22px;
142
+ background: #2d2d3d;
143
+ margin: 0 4px;
144
+ }
145
+
146
+ /* ---------- meta ---------- */
147
+ .meta {
148
+ display: flex;
149
+ gap: 8px;
150
+ flex-wrap: wrap;
151
+ margin-bottom: 14px;
152
+ }
153
+
154
+ .pill {
155
+ background: #181824;
156
+ border: 1px solid #23232f;
157
+ border-radius: 999px;
158
+ padding: 4px 12px;
159
+ font-size: 12px;
160
+ color: #b6b6c6;
161
+ }
162
+
163
+ .empty {
164
+ padding: 30px;
165
+ text-align: center;
166
+ color: #6b6b7b;
167
+ border: 1px dashed #2d2d3d;
168
+ border-radius: 8px;
169
+ }
170
+
171
+ /* ---------- grid ---------- */
172
+ .grid {
173
+ display: flex;
174
+ flex-direction: column;
175
+ gap: 4px;
176
+ }
177
+
178
+ .row {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 12px;
182
+ background: #15151f;
183
+ border: 1px solid #1f1f2b;
184
+ border-radius: 6px;
185
+ padding: 6px 12px;
186
+ font-size: 13px;
187
+ }
188
+
189
+ .row-active {
190
+ border-color: #7c3aed;
191
+ background: #1a1626;
192
+ }
193
+
194
+ .row-id {
195
+ width: 64px;
196
+ color: #6b6b7b;
197
+ font-variant-numeric: tabular-nums;
198
+ }
199
+
200
+ .row-label {
201
+ width: 90px;
202
+ font-weight: 600;
203
+ }
204
+
205
+ .badge {
206
+ font-size: 11px;
207
+ font-weight: 600;
208
+ padding: 2px 8px;
209
+ border-radius: 999px;
210
+ text-transform: uppercase;
211
+ letter-spacing: 0.04em;
212
+ }
213
+
214
+ .badge-ok {
215
+ background: #064e3b;
216
+ color: #6ee7b7;
217
+ }
218
+
219
+ .badge-warn {
220
+ background: #4d3c06;
221
+ color: #fcd34d;
222
+ }
223
+
224
+ .badge-error {
225
+ background: #4c0519;
226
+ color: #fda4af;
227
+ }
228
+
229
+ .badge-idle {
230
+ background: #1f2937;
231
+ color: #9ca3af;
232
+ }
233
+
234
+ .star {
235
+ color: #fbbf24;
236
+ }
237
+
238
+ .cells {
239
+ display: flex;
240
+ gap: 4px;
241
+ margin-left: auto;
242
+ }
243
+
244
+ .cell {
245
+ background: #1f1f2e;
246
+ border-radius: 4px;
247
+ padding: 2px 8px;
248
+ font-size: 12px;
249
+ color: #b6b6c6;
250
+ font-variant-numeric: tabular-nums;
251
+ }
252
+
253
+ .row-value {
254
+ width: 70px;
255
+ text-align: right;
256
+ color: #8b8b9b;
257
+ font-variant-numeric: tabular-nums;
258
+ }
259
+ </style>
260
+ </head>
261
+
262
+ <body>
263
+ <are-root id="app">
264
+ <perf-app></perf-app>
265
+ </are-root>
266
+
267
+ <script type="module" src="./{{BUNDLE_ID}}.js"></script>
268
+ </body>
269
+
270
+ </html>
@@ -0,0 +1,37 @@
1
+ import { A_Inject } from "@adaas/a-concept";
2
+ import { A_Caller } from "@adaas/a-concept";
3
+ import { Are } from "@adaas/are";
4
+ import { AreNode } from "@adaas/are";
5
+ import { AreStore } from "@adaas/are";
6
+
7
+
8
+ /**
9
+ * Application shell. Composes the page out of several child components so the
10
+ * scene contains "many components" while the heavy $for stress test lives in
11
+ * <perf-grid>.
12
+ */
13
+ export class PerfApp extends Are {
14
+
15
+ @Are.Template
16
+ template(
17
+ @A_Inject(A_Caller) node: AreNode,
18
+ ) {
19
+ node.setContent(`
20
+ <div class="app">
21
+ <perf-header></perf-header>
22
+ <perf-stats></perf-stats>
23
+ <perf-controls></perf-controls>
24
+ <perf-grid></perf-grid>
25
+ </div>
26
+ `);
27
+ }
28
+
29
+ @Are.Data
30
+ data(
31
+ @A_Inject(AreStore) store: AreStore,
32
+ ) {
33
+ store.set({
34
+ appName: 'ARE $for Performance Lab',
35
+ });
36
+ }
37
+ }
@@ -0,0 +1,34 @@
1
+ import { A_Inject } from "@adaas/a-concept";
2
+ import { A_Caller } from "@adaas/a-concept";
3
+ import { Are } from "@adaas/are";
4
+ import { AreNode } from "@adaas/are";
5
+ import { AreStore } from "@adaas/are";
6
+
7
+
8
+ /**
9
+ * Static informational strip. Kept presentational so the scene has more
10
+ * components without competing for the grid's store.
11
+ */
12
+ export class PerfControls extends Are {
13
+
14
+ @Are.Template
15
+ template(
16
+ @A_Inject(A_Caller) node: AreNode,
17
+ ) {
18
+ node.setContent(`
19
+ <section class="hint">
20
+ <span class="hint-icon">ℹ</span>
21
+ <span class="hint-text">{{hint}}</span>
22
+ </section>
23
+ `);
24
+ }
25
+
26
+ @Are.Data
27
+ data(
28
+ @A_Inject(AreStore) store: AreStore,
29
+ ) {
30
+ store.set({
31
+ hint: 'Each button below mutates the store; the $for directive re-renders synchronously and the timing is logged.',
32
+ });
33
+ }
34
+ }
@@ -0,0 +1,225 @@
1
+ import { A_Inject } from "@adaas/a-concept";
2
+ import { A_Caller } from "@adaas/a-concept";
3
+ import { A_Logger } from "@adaas/a-utils/a-logger";
4
+ import { Are } from "@adaas/are";
5
+ import { AreContext } from "@adaas/are";
6
+ import { AreEvent } from "@adaas/are";
7
+ import { AreNode } from "@adaas/are";
8
+ import { AreStore } from "@adaas/are";
9
+
10
+
11
+ const STATUSES = ['ok', 'warn', 'error', 'idle'];
12
+
13
+ let ROW_SEQ = 0;
14
+
15
+ function makeCells(rowId: number): Array<{ id: string; v: number }> {
16
+ const cells: Array<{ id: string; v: number }> = [];
17
+ for (let c = 0; c < 4; c++) {
18
+ cells.push({ id: `${rowId}:${c}`, v: Math.floor(Math.random() * 1000) });
19
+ }
20
+ return cells;
21
+ }
22
+
23
+ function makeRows(count: number): Array<any> {
24
+ const rows: Array<any> = [];
25
+ for (let i = 0; i < count; i++) {
26
+ const id = ++ROW_SEQ;
27
+ rows.push({
28
+ id,
29
+ label: `Row ${id}`,
30
+ status: STATUSES[id % STATUSES.length],
31
+ value: Math.floor(Math.random() * 10000),
32
+ active: id % 7 === 0,
33
+ cells: makeCells(id),
34
+ });
35
+ }
36
+ return rows;
37
+ }
38
+
39
+ /**
40
+ * Wraps the store mutation with wall-clock + engine timers and dumps every
41
+ * captured performance metric to the browser console.
42
+ */
43
+ function commit(
44
+ action: string,
45
+ rows: Array<any>,
46
+ context: AreContext,
47
+ store: AreStore,
48
+ logger: A_Logger,
49
+ ) {
50
+ const label = `$for: ${action}`;
51
+
52
+ console.group(`%c${label}`, 'color:#7c3aed;font-weight:bold');
53
+
54
+ const t0 = performance.now();
55
+ context.startPerformance(label);
56
+
57
+ // Synchronous: dispatch -> notify -> $for watcher update happens here.
58
+ store.set('rows', rows);
59
+ store.set('count', rows.length);
60
+
61
+ context.endPerformance(label);
62
+ const wall = (performance.now() - t0).toFixed(2);
63
+
64
+ store.set('lastAction', action);
65
+ store.set('lastWall', wall);
66
+
67
+ logger.debug(`${label} | rows=${rows.length} | wall=${wall}ms`);
68
+ logger.info(`${label} done in ${wall}ms`, ...context.performance);
69
+
70
+ console.log('%cWall time:', 'font-weight:bold', `${wall} ms`);
71
+ console.log('%cEngine performance:', 'font-weight:bold');
72
+ context.performance.forEach((line) => console.log(' ' + line));
73
+ console.log('%cScene stats:', 'font-weight:bold');
74
+ context.stats.forEach((line) => console.log(' ' + line));
75
+
76
+ console.groupEnd();
77
+ }
78
+
79
+ /**
80
+ * The heavy component. Holds the action buttons AND the $for grid in a single
81
+ * store so mutations re-render the directive synchronously, which lets us wrap
82
+ * each mutation with performance timers and dump the result to the console.
83
+ *
84
+ * NOTE: $if and $for are intentionally kept on separate elements.
85
+ */
86
+ export class PerfGrid extends Are {
87
+
88
+ @Are.Template
89
+ template(
90
+ @A_Inject(A_Caller) node: AreNode,
91
+ ) {
92
+ node.setContent(`
93
+ <section class="grid-panel">
94
+ <div class="toolbar">
95
+ <button class="btn" @click="$render(100)">Render 100</button>
96
+ <button class="btn" @click="$render(1000)">Render 1000</button>
97
+ <button class="btn" @click="$render(5000)">Render 5000</button>
98
+ <span class="sep"></span>
99
+ <button class="btn" @click="$append(100)">Append 100</button>
100
+ <button class="btn" @click="$prepend(100)">Prepend 100</button>
101
+ <button class="btn" @click="$shuffle()">Shuffle</button>
102
+ <button class="btn" @click="$updateInPlace()">Update in place</button>
103
+ <button class="btn btn-danger" @click="$clear()">Clear</button>
104
+ </div>
105
+
106
+ <div class="meta">
107
+ <span class="pill">Rows: {{count}}</span>
108
+ <span class="pill">Last action: {{lastAction}}</span>
109
+ <span class="pill">Wall time: {{lastWall}} ms</span>
110
+ </div>
111
+
112
+ <div class="empty" $if="count == 0">No rows. Pick a "Render N" button to start.</div>
113
+
114
+ <div class="grid">
115
+ <div class="row" $for="row in rows track row.id" :class="row.active ? 'row-active' : ''">
116
+ <span class="row-id">#{{row.id}}</span>
117
+ <span class="row-label">{{row.label}}</span>
118
+ <span class="badge" :class="'badge-' + row.status">{{row.status}}</span>
119
+ <span class="star" $if="row.active">★</span>
120
+ <span class="cells">
121
+ <span class="cell" $for="cell in row.cells track cell.id">{{cell.v}}</span>
122
+ </span>
123
+ <span class="row-value">{{row.value}}</span>
124
+ </div>
125
+ </div>
126
+ </section>
127
+ `);
128
+ }
129
+
130
+ @Are.Data
131
+ data(
132
+ @A_Inject(AreStore) store: AreStore,
133
+ ) {
134
+ const initial = makeRows(25);
135
+ store.set({
136
+ rows: initial,
137
+ count: initial.length,
138
+ lastAction: 'initial',
139
+ lastWall: '0.00',
140
+ });
141
+ }
142
+
143
+ @Are.EventHandler
144
+ render(
145
+ @A_Inject(A_Caller) node: AreNode,
146
+ @A_Inject(AreEvent) event: AreEvent,
147
+ @A_Inject(AreContext) context: AreContext,
148
+ @A_Inject(AreStore) store: AreStore,
149
+ @A_Inject(A_Logger) logger: A_Logger,
150
+ ) {
151
+ const n = Number(event.get('args')?.[0]) || 100;
152
+ const rows = makeRows(n);
153
+ commit(`Render ${n}`, rows, context, store, logger);
154
+ }
155
+
156
+ @Are.EventHandler
157
+ append(
158
+ @A_Inject(A_Caller) node: AreNode,
159
+ @A_Inject(AreEvent) event: AreEvent,
160
+ @A_Inject(AreContext) context: AreContext,
161
+ @A_Inject(AreStore) store: AreStore,
162
+ @A_Inject(A_Logger) logger: A_Logger,
163
+ ) {
164
+ const n = Number(event.get('args')?.[0]) || 100;
165
+ const rows = (store.get('rows') || []).concat(makeRows(n));
166
+ commit(`Append ${n}`, rows, context, store, logger);
167
+ }
168
+
169
+ @Are.EventHandler
170
+ prepend(
171
+ @A_Inject(A_Caller) node: AreNode,
172
+ @A_Inject(AreEvent) event: AreEvent,
173
+ @A_Inject(AreContext) context: AreContext,
174
+ @A_Inject(AreStore) store: AreStore,
175
+ @A_Inject(A_Logger) logger: A_Logger,
176
+ ) {
177
+ const n = Number(event.get('args')?.[0]) || 100;
178
+ const rows = makeRows(n).concat(store.get('rows') || []);
179
+ commit(`Prepend ${n}`, rows, context, store, logger);
180
+ }
181
+
182
+ @Are.EventHandler
183
+ shuffle(
184
+ @A_Inject(A_Caller) node: AreNode,
185
+ @A_Inject(AreEvent) event: AreEvent,
186
+ @A_Inject(AreContext) context: AreContext,
187
+ @A_Inject(AreStore) store: AreStore,
188
+ @A_Inject(A_Logger) logger: A_Logger,
189
+ ) {
190
+ const rows = (store.get('rows') || []).slice();
191
+ for (let i = rows.length - 1; i > 0; i--) {
192
+ const j = Math.floor(Math.random() * (i + 1));
193
+ [rows[i], rows[j]] = [rows[j], rows[i]];
194
+ }
195
+ commit('Shuffle', rows, context, store, logger);
196
+ }
197
+
198
+ @Are.EventHandler
199
+ updateInPlace(
200
+ @A_Inject(A_Caller) node: AreNode,
201
+ @A_Inject(AreEvent) event: AreEvent,
202
+ @A_Inject(AreContext) context: AreContext,
203
+ @A_Inject(AreStore) store: AreStore,
204
+ @A_Inject(A_Logger) logger: A_Logger,
205
+ ) {
206
+ const rows = (store.get('rows') || []).map((row: any) => ({
207
+ ...row,
208
+ value: Math.floor(Math.random() * 10000),
209
+ status: STATUSES[Math.floor(Math.random() * STATUSES.length)],
210
+ cells: makeCells(row.id),
211
+ }));
212
+ commit('Update in place', rows, context, store, logger);
213
+ }
214
+
215
+ @Are.EventHandler
216
+ clear(
217
+ @A_Inject(A_Caller) node: AreNode,
218
+ @A_Inject(AreEvent) event: AreEvent,
219
+ @A_Inject(AreContext) context: AreContext,
220
+ @A_Inject(AreStore) store: AreStore,
221
+ @A_Inject(A_Logger) logger: A_Logger,
222
+ ) {
223
+ commit('Clear', [], context, store, logger);
224
+ }
225
+ }
@@ -0,0 +1,34 @@
1
+ import { A_Inject } from "@adaas/a-concept";
2
+ import { A_Caller } from "@adaas/a-concept";
3
+ import { Are } from "@adaas/are";
4
+ import { AreNode } from "@adaas/are";
5
+ import { AreStore } from "@adaas/are";
6
+
7
+
8
+ export class PerfHeader extends Are {
9
+
10
+ @Are.Template
11
+ template(
12
+ @A_Inject(A_Caller) node: AreNode,
13
+ ) {
14
+ node.setContent(`
15
+ <header class="header">
16
+ <div class="brand">
17
+ <span class="logo">▦</span>
18
+ <span class="title">{{title}}</span>
19
+ </div>
20
+ <span class="subtitle">{{subtitle}}</span>
21
+ </header>
22
+ `);
23
+ }
24
+
25
+ @Are.Data
26
+ data(
27
+ @A_Inject(AreStore) store: AreStore,
28
+ ) {
29
+ store.set({
30
+ title: 'ARE $for Performance Lab',
31
+ subtitle: 'Open DevTools console — logger is at debug, perf metrics are printed on every action',
32
+ });
33
+ }
34
+ }
@@ -0,0 +1,43 @@
1
+ import { A_Inject } from "@adaas/a-concept";
2
+ import { A_Caller } from "@adaas/a-concept";
3
+ import { Are } from "@adaas/are";
4
+ import { AreNode } from "@adaas/are";
5
+ import { AreStore } from "@adaas/are";
6
+
7
+
8
+ /**
9
+ * Presentational cards describing the available scenarios. Uses its own $for
10
+ * over a small static list so the scene exercises the directive in more than
11
+ * one place.
12
+ */
13
+ export class PerfStats extends Are {
14
+
15
+ @Are.Template
16
+ template(
17
+ @A_Inject(A_Caller) node: AreNode,
18
+ ) {
19
+ node.setContent(`
20
+ <section class="legend">
21
+ <div class="legend-card" $for="card in cards track card.key">
22
+ <span class="legend-key">{{card.key}}</span>
23
+ <span class="legend-label">{{card.label}}</span>
24
+ </div>
25
+ </section>
26
+ `);
27
+ }
28
+
29
+ @Are.Data
30
+ data(
31
+ @A_Inject(AreStore) store: AreStore,
32
+ ) {
33
+ store.set({
34
+ cards: [
35
+ { key: 'render', label: 'Replace the whole list' },
36
+ { key: 'append', label: 'Add rows at the end' },
37
+ { key: 'prepend', label: 'Add rows at the start' },
38
+ { key: 'shuffle', label: 'Reorder existing rows' },
39
+ { key: 'update', label: 'Mutate every row in place' },
40
+ ],
41
+ });
42
+ }
43
+ }