@adaas/are-html 0.0.20 → 0.0.22
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.
- package/.conf/tsconfig.base.json +1 -0
- package/.conf/tsconfig.browser.json +1 -0
- package/.conf/tsconfig.node.json +1 -0
- package/dist/browser/index.d.mts +206 -7
- package/dist/browser/index.mjs +527 -65
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/directives/AreDirectiveFor.directive.d.mts +44 -1
- package/dist/node/directives/AreDirectiveFor.directive.d.ts +44 -1
- package/dist/node/directives/AreDirectiveFor.directive.js +102 -6
- package/dist/node/directives/AreDirectiveFor.directive.js.map +1 -1
- package/dist/node/directives/AreDirectiveFor.directive.mjs +102 -6
- package/dist/node/directives/AreDirectiveFor.directive.mjs.map +1 -1
- package/dist/node/directives/AreDirectiveShow.directive.d.mts +32 -0
- package/dist/node/directives/AreDirectiveShow.directive.d.ts +32 -0
- package/dist/node/directives/AreDirectiveShow.directive.js +81 -0
- package/dist/node/directives/AreDirectiveShow.directive.js.map +1 -0
- package/dist/node/directives/AreDirectiveShow.directive.mjs +71 -0
- package/dist/node/directives/AreDirectiveShow.directive.mjs.map +1 -0
- package/dist/node/engine/AreHTML.engine.d.mts +2 -1
- package/dist/node/engine/AreHTML.engine.d.ts +2 -1
- package/dist/node/engine/AreHTML.engine.js +8 -2
- package/dist/node/engine/AreHTML.engine.js.map +1 -1
- package/dist/node/engine/AreHTML.engine.mjs +8 -2
- package/dist/node/engine/AreHTML.engine.mjs.map +1 -1
- package/dist/node/engine/AreHTML.interpreter.d.mts +3 -0
- package/dist/node/engine/AreHTML.interpreter.d.ts +3 -0
- package/dist/node/engine/AreHTML.interpreter.js +29 -0
- package/dist/node/engine/AreHTML.interpreter.js.map +1 -1
- package/dist/node/engine/AreHTML.interpreter.mjs +29 -0
- package/dist/node/engine/AreHTML.interpreter.mjs.map +1 -1
- package/dist/node/engine/AreHTML.lifecycle.d.mts +8 -1
- package/dist/node/engine/AreHTML.lifecycle.d.ts +8 -1
- package/dist/node/engine/AreHTML.lifecycle.js +46 -3
- package/dist/node/engine/AreHTML.lifecycle.js.map +1 -1
- package/dist/node/engine/AreHTML.lifecycle.mjs +46 -3
- package/dist/node/engine/AreHTML.lifecycle.mjs.map +1 -1
- package/dist/node/helpers/AreScheduler.helper.d.mts +39 -0
- package/dist/node/helpers/AreScheduler.helper.d.ts +39 -0
- package/dist/node/helpers/AreScheduler.helper.js +40 -0
- package/dist/node/helpers/AreScheduler.helper.js.map +1 -0
- package/dist/node/helpers/AreScheduler.helper.mjs +40 -0
- package/dist/node/helpers/AreScheduler.helper.mjs.map +1 -0
- package/dist/node/index.d.mts +4 -1
- package/dist/node/index.d.ts +4 -1
- package/dist/node/index.js +21 -0
- package/dist/node/index.mjs +3 -0
- package/dist/node/instructions/AreHTML.instructions.constants.d.mts +1 -0
- package/dist/node/instructions/AreHTML.instructions.constants.d.ts +1 -0
- package/dist/node/instructions/AreHTML.instructions.constants.js +2 -1
- package/dist/node/instructions/AreHTML.instructions.constants.js.map +1 -1
- package/dist/node/instructions/AreHTML.instructions.constants.mjs +2 -1
- package/dist/node/instructions/AreHTML.instructions.constants.mjs.map +1 -1
- package/dist/node/instructions/AreHTML.instructions.types.d.mts +9 -1
- package/dist/node/instructions/AreHTML.instructions.types.d.ts +9 -1
- package/dist/node/instructions/HideElement.instruction.d.mts +13 -0
- package/dist/node/instructions/HideElement.instruction.d.ts +13 -0
- package/dist/node/instructions/HideElement.instruction.js +31 -0
- package/dist/node/instructions/HideElement.instruction.js.map +1 -0
- package/dist/node/instructions/HideElement.instruction.mjs +24 -0
- package/dist/node/instructions/HideElement.instruction.mjs.map +1 -0
- package/dist/node/lib/AreRoot/AreRoot.component.d.mts +57 -3
- package/dist/node/lib/AreRoot/AreRoot.component.d.ts +57 -3
- package/dist/node/lib/AreRoot/AreRoot.component.js +138 -49
- package/dist/node/lib/AreRoot/AreRoot.component.js.map +1 -1
- package/dist/node/lib/AreRoot/AreRoot.component.mjs +140 -51
- package/dist/node/lib/AreRoot/AreRoot.component.mjs.map +1 -1
- package/dist/node/lib/AreRoot/AreRootCache.context.d.mts +58 -0
- package/dist/node/lib/AreRoot/AreRootCache.context.d.ts +58 -0
- package/dist/node/lib/AreRoot/AreRootCache.context.js +106 -0
- package/dist/node/lib/AreRoot/AreRootCache.context.js.map +1 -0
- package/dist/node/lib/AreRoot/AreRootCache.context.mjs +99 -0
- package/dist/node/lib/AreRoot/AreRootCache.context.mjs.map +1 -0
- package/examples/dashboard/dist/index.html +1 -1
- package/examples/dashboard/dist/{mq19zxz4-mnlgmd.js → mqh9ryml-xat335.js} +1922 -1316
- package/examples/dashboard/src/concept.ts +3 -2
- package/examples/for-perf/concept.ts +45 -0
- package/examples/for-perf/containers/UI.container.ts +161 -0
- package/examples/for-perf/dist/index.html +270 -0
- package/examples/for-perf/dist/mqh9ryde-m243t8.js +15223 -0
- package/examples/for-perf/dist/mqh9ryfo-6a8d0o.js +15223 -0
- package/examples/for-perf/dist/mqh9ryfq-4pf5cv.js +15223 -0
- package/examples/for-perf/public/index.html +270 -0
- package/examples/for-perf/src/components/PerfApp.component.ts +37 -0
- package/examples/for-perf/src/components/PerfControls.component.ts +34 -0
- package/examples/for-perf/src/components/PerfGrid.component.ts +225 -0
- package/examples/for-perf/src/components/PerfHeader.component.ts +34 -0
- package/examples/for-perf/src/components/PerfStats.component.ts +43 -0
- package/examples/for-perf/src/concept.ts +94 -0
- package/examples/jumpstart/dist/index.html +1 -1
- package/examples/jumpstart/dist/{mq1a0fv0-ccgtz6.js → mq7mgf58-vbf07e.js} +895 -521
- package/examples/signal-routing/dist/index.html +1 -1
- package/examples/signal-routing/dist/{mq1bzrik-4lec86.js → mqh9ryc9-dkcbkx.js} +2024 -1300
- package/examples/signal-routing/src/components/SettingsPage.component.ts +39 -0
- package/examples/signal-routing/src/concept.ts +2 -0
- package/jest.config.ts +1 -0
- package/package.json +10 -9
- package/src/directives/AreDirectiveFor.directive.ts +185 -12
- package/src/directives/AreDirectiveShow.directive.ts +127 -0
- package/src/engine/AreHTML.engine.ts +11 -1
- package/src/engine/AreHTML.interpreter.ts +50 -0
- package/src/engine/AreHTML.lifecycle.ts +83 -6
- package/src/helpers/AreScheduler.helper.ts +61 -0
- package/src/index.ts +3 -0
- package/src/instructions/AreHTML.instructions.constants.ts +1 -0
- package/src/instructions/AreHTML.instructions.types.ts +9 -0
- package/src/instructions/HideElement.instruction.ts +29 -0
- package/src/lib/AreRoot/AreRoot.component.ts +205 -72
- package/src/lib/AreRoot/AreRootCache.context.ts +133 -0
- 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
|
+
}
|