rshow 0.0.0-stage → 0.0.2
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/LICENSE +21 -0
- package/README.md +50 -2
- package/dist/main.js +8500 -0
- package/package.json +48 -4
- package/skills/rshow/SKILL.md +144 -0
- package/skills/rshow/reference/cli.md +263 -0
- package/skills/rshow/reference/dashboard.md +122 -0
- package/skills/rshow/reference/mockups.md +113 -0
- package/skills/rshow/reference/page-contract.md +83 -0
- package/skills/rshow/reference/pages.md +174 -0
- package/skills/rshow/reference/poster.md +137 -0
- package/skills/rshow/reference/project-page.md +132 -0
- package/skills/rshow/reference/reports.md +158 -0
- package/skills/rshow/reference/sketch.md +78 -0
- package/skills/rshow/reference/terminal.md +148 -0
- package/skills/rshow/reference/themes.md +139 -0
- package/skills/rshow-implement/SKILL.md +112 -0
- package/skills/rshow-implement/reference/compare.md +156 -0
- package/skills/rshow-implement/reference/handoff.md +125 -0
- package/skills/rshow-implement/reference/map.md +151 -0
- package/skills/rshow-slides/SKILL.md +136 -0
- package/skills/rshow-slides/reference/layouts.md +251 -0
- package/themes/default/dashboard.css +521 -0
- package/themes/default/dashboard.js +1390 -0
- package/themes/default/deck.css +586 -0
- package/themes/default/deck.js +741 -0
- package/themes/default/example/capture.ans +1 -0
- package/themes/default/example/dashboard.html +106 -0
- package/themes/default/example/demo.cast +14 -0
- package/themes/default/example/drawing.excalidraw +377 -0
- package/themes/default/example/index.html +311 -0
- package/themes/default/example/mockup-desktop.html +331 -0
- package/themes/default/example/mockup-platforms.html +742 -0
- package/themes/default/example/mockup.html +416 -0
- package/themes/default/example/page.html +153 -0
- package/themes/default/example/poster-figure.svg +58 -0
- package/themes/default/example/poster.html +181 -0
- package/themes/default/example/project.html +229 -0
- package/themes/default/example/report.html +404 -0
- package/themes/default/example/results.csv +61 -0
- package/themes/default/example/sketch.html +178 -0
- package/themes/default/example/teaser.svg +66 -0
- package/themes/default/example/terminal.html +231 -0
- package/themes/default/example/tui.html +223 -0
- package/themes/default/fonts/IBMPlexMono-Regular-Latin1.woff2 +0 -0
- package/themes/default/fonts/IBMPlexSans-Light-Latin1.woff2 +0 -0
- package/themes/default/fonts/IBMPlexSans-Regular-Latin1.woff2 +0 -0
- package/themes/default/fonts/IBMPlexSans-SemiBold-Latin1.woff2 +0 -0
- package/themes/default/fonts/OFL.txt +93 -0
- package/themes/default/fonts.css +63 -0
- package/themes/default/index.html +573 -0
- package/themes/default/mockup.css +1078 -0
- package/themes/default/mockup.js +1433 -0
- package/themes/default/mode.js +242 -0
- package/themes/default/page.css +320 -0
- package/themes/default/poster.css +480 -0
- package/themes/default/poster.js +223 -0
- package/themes/default/project.css +482 -0
- package/themes/default/project.js +116 -0
- package/themes/default/report.css +776 -0
- package/themes/default/report.js +427 -0
- package/themes/default/sketch.css +166 -0
- package/themes/default/sketch.js +681 -0
- package/themes/default/skins/adwaita.css +669 -0
- package/themes/default/skins/custom.css +596 -0
- package/themes/default/skins/egui.css +639 -0
- package/themes/default/skins/fluent.css +1093 -0
- package/themes/default/skins/fluent.js +458 -0
- package/themes/default/skins/mac.css +647 -0
- package/themes/default/skins/material.css +692 -0
- package/themes/default/skins/sketch.css +436 -0
- package/themes/default/skins/sketch.js +494 -0
- package/themes/default/skins/wire.css +561 -0
- package/themes/default/terminal.css +292 -0
- package/themes/default/terminal.js +433 -0
- package/themes/default/theme.json +149 -0
- package/themes/default/tokens.css +255 -0
- package/themes/default/tui.css +703 -0
- package/themes/default/tui.js +472 -0
- package/worker/index.js +6918 -0
- package/worker/migrations/0001_init.sql +52 -0
- package/worker/migrations/0002_blobs.sql +5 -0
- package/worker/migrations/0003_projects.sql +31 -0
- package/worker/migrations/0004_page_data_blob.sql +19 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* rshow theme "default": the fluent skin, the real components.
|
|
3
|
+
*
|
|
4
|
+
* skins/fluent.css draws the whole kit with Fluent-like tokens, so the skin
|
|
5
|
+
* reads as Windows 11 with no network at all. This file goes one step further
|
|
6
|
+
* while the fluent skin is active: it upgrades the six controls that a design
|
|
7
|
+
* review actually argues about into the real Microsoft Fluent UI Web Components
|
|
8
|
+
* v3, so a wf-button is a fluent-button, a wf-input is a fluent-field around a
|
|
9
|
+
* fluent-text-input, and so on. The component and the drawn kit agree because
|
|
10
|
+
* they read the same token values out of fluent.css.
|
|
11
|
+
*
|
|
12
|
+
* Pinned version. @fluentui/web-components 3.1.3, the newest 3.x on npm when
|
|
13
|
+
* this file was written, fetched as one bundled ES module from jsdelivr:
|
|
14
|
+
*
|
|
15
|
+
* https://cdn.jsdelivr.net/npm/@fluentui/web-components@3.1.3/dist/web-components.min.js
|
|
16
|
+
*
|
|
17
|
+
* It is a single self contained module: no import map, no bundler, no bare
|
|
18
|
+
* specifier. The module registers its custom elements in a task after it
|
|
19
|
+
* evaluates, so this file waits on customElements.whenDefined before it builds
|
|
20
|
+
* anything.
|
|
21
|
+
*
|
|
22
|
+
* Fallback. A mockup is a drawing and must be readable on a plane: if the
|
|
23
|
+
* module does not load, or a browser without custom elements reaches this file,
|
|
24
|
+
* nothing is upgraded and fluent.css alone draws every control. A half upgraded
|
|
25
|
+
* screen is worse than a plain one, so a failure reverts what this file built.
|
|
26
|
+
*
|
|
27
|
+
* Switching skins away from fluent puts every original wf-* element back where
|
|
28
|
+
* it was, so wire, sketch and custom see the kit they expect.
|
|
29
|
+
*
|
|
30
|
+
* Markup stays the kit's markup. data-goto, href, data-state and inline styles
|
|
31
|
+
* move onto the upgraded element, which is why a hotspot or a state still works
|
|
32
|
+
* after the upgrade.
|
|
33
|
+
*/
|
|
34
|
+
(function () {
|
|
35
|
+
'use strict';
|
|
36
|
+
|
|
37
|
+
var main = document.querySelector('.mockup');
|
|
38
|
+
if (!main) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var MODULE_URL = 'https://cdn.jsdelivr.net/npm/@fluentui/web-components@3.1.3/dist/web-components.min.js';
|
|
43
|
+
var WAIT_LIMIT = 8000;
|
|
44
|
+
|
|
45
|
+
var SELECTOR = ['.wf-button', '.wf-input', '.wf-select', '.wf-checkbox', '.wf-toggle', '.wf-tabs'].join(', ');
|
|
46
|
+
var SKIP_CLASS = ['primary', 'ghost', 'on', 'is-active', 'wf-button', 'wf-input', 'wf-select', 'wf-checkbox', 'wf-toggle', 'wf-tabs'];
|
|
47
|
+
|
|
48
|
+
var phase = 'idle';
|
|
49
|
+
var waiting = [];
|
|
50
|
+
var built = [];
|
|
51
|
+
var loadTimer = null;
|
|
52
|
+
var debounce = null;
|
|
53
|
+
var tabSeq = 0;
|
|
54
|
+
|
|
55
|
+
// The skin of a screen is the nearest data-skin above it, so a page that pins
|
|
56
|
+
// one skin per screen and carries its own elsewhere still upgrades the right
|
|
57
|
+
// screens, and only those.
|
|
58
|
+
function skinOf(node) {
|
|
59
|
+
var host = node.closest ? node.closest('[data-skin]') : null;
|
|
60
|
+
return host ? host.getAttribute('data-skin') : '';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function fluentScreens() {
|
|
64
|
+
var screens = main.querySelectorAll('.mk-screen');
|
|
65
|
+
var active = [];
|
|
66
|
+
for (var i = 0; i < screens.length; i += 1) {
|
|
67
|
+
if (skinOf(screens[i]) === 'fluent') {
|
|
68
|
+
active.push(screens[i]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return active;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isFluent() {
|
|
75
|
+
return fluentScreens().length > 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function warn(message) {
|
|
79
|
+
if (window.console && window.console.warn) {
|
|
80
|
+
window.console.warn('[rshow fluent skin] ' + message);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------- load --
|
|
85
|
+
|
|
86
|
+
function settle(ok) {
|
|
87
|
+
phase = ok ? 'ready' : 'failed';
|
|
88
|
+
main.setAttribute('data-fluent-upgrade', ok ? 'components' : 'css-only');
|
|
89
|
+
var callbacks = waiting;
|
|
90
|
+
waiting = [];
|
|
91
|
+
for (var i = 0; i < callbacks.length; i += 1) {
|
|
92
|
+
callbacks[i](ok);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function ensure(done) {
|
|
97
|
+
if (phase === 'ready' || phase === 'failed') {
|
|
98
|
+
done(phase === 'ready');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
waiting.push(done);
|
|
102
|
+
if (phase === 'loading') {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
phase = 'loading';
|
|
106
|
+
if (typeof window.customElements === 'undefined' || typeof window.customElements.whenDefined !== 'function') {
|
|
107
|
+
warn('custom elements are not supported: fluent.css draws the controls');
|
|
108
|
+
settle(false);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
window.clearTimeout(loadTimer);
|
|
112
|
+
loadTimer = window.setTimeout(function () {
|
|
113
|
+
if (phase === 'loading') {
|
|
114
|
+
warn('the Fluent module did not answer in time: fluent.css draws the controls');
|
|
115
|
+
settle(false);
|
|
116
|
+
}
|
|
117
|
+
}, WAIT_LIMIT);
|
|
118
|
+
// A dynamic import of a URL is the browser's own module loader: no build
|
|
119
|
+
// step, no import map, and the pinned version is in the URL.
|
|
120
|
+
import(MODULE_URL)
|
|
121
|
+
.then(function () {
|
|
122
|
+
return window.customElements.whenDefined('fluent-button');
|
|
123
|
+
})
|
|
124
|
+
.then(function () {
|
|
125
|
+
window.clearTimeout(loadTimer);
|
|
126
|
+
if (phase !== 'loading') {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
var all = ['fluent-button', 'fluent-text-input', 'fluent-listbox', 'fluent-dropdown', 'fluent-checkbox', 'fluent-switch', 'fluent-tablist'];
|
|
130
|
+
for (var i = 0; i < all.length; i += 1) {
|
|
131
|
+
if (!window.customElements.get(all[i])) {
|
|
132
|
+
warn('the Fluent module did not define ' + all[i] + ': fluent.css draws the controls');
|
|
133
|
+
settle(false);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
settle(true);
|
|
138
|
+
})
|
|
139
|
+
.catch(function (err) {
|
|
140
|
+
window.clearTimeout(loadTimer);
|
|
141
|
+
warn('the Fluent module could not be loaded (' + (err && err.message ? err.message : err) + '): fluent.css draws the controls');
|
|
142
|
+
settle(false);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// -------------------------------------------------------------- shapes --
|
|
147
|
+
|
|
148
|
+
function copy(node, target) {
|
|
149
|
+
var attrs = node.attributes;
|
|
150
|
+
var i;
|
|
151
|
+
for (i = 0; i < attrs.length; i += 1) {
|
|
152
|
+
var name = attrs[i].name;
|
|
153
|
+
if (name === 'class' || name.indexOf('data-') === 0) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (name === 'aria-selected' || name === 'checked') {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
target.setAttribute(name, attrs[i].value);
|
|
160
|
+
}
|
|
161
|
+
for (i = 0; i < attrs.length; i += 1) {
|
|
162
|
+
if (attrs[i].name.indexOf('data-') === 0) {
|
|
163
|
+
target.setAttribute(attrs[i].name, attrs[i].value);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
var classes = (node.className || '').split(/\s+/);
|
|
167
|
+
for (i = 0; i < classes.length; i += 1) {
|
|
168
|
+
var name2 = classes[i];
|
|
169
|
+
if (name2 !== '' && SKIP_CLASS.indexOf(name2) < 0) {
|
|
170
|
+
target.classList.add(name2);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (node.getAttribute('style')) {
|
|
174
|
+
target.setAttribute('style', node.getAttribute('style'));
|
|
175
|
+
}
|
|
176
|
+
return target;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function text(node) {
|
|
180
|
+
return String(node.textContent || '').replace(/\s+/g, ' ').trim();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// The kit labels a field in the notch on its border, so an upgraded control is
|
|
184
|
+
// wrapped in the kit's field: the label is ours, the control is Fluent's.
|
|
185
|
+
function labelled(node, control) {
|
|
186
|
+
var field = document.createElement('span');
|
|
187
|
+
field.className = 'wf-field';
|
|
188
|
+
var label = node.getAttribute('data-label');
|
|
189
|
+
if (label) {
|
|
190
|
+
var caption = document.createElement('span');
|
|
191
|
+
caption.className = 'wf-label';
|
|
192
|
+
caption.textContent = label;
|
|
193
|
+
field.appendChild(caption);
|
|
194
|
+
}
|
|
195
|
+
field.appendChild(control);
|
|
196
|
+
copy(node, field);
|
|
197
|
+
return field;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function upgradeButton(node) {
|
|
201
|
+
var primary = node.classList.contains('primary');
|
|
202
|
+
var ghost = node.classList.contains('ghost');
|
|
203
|
+
var link = node.tagName === 'A' && node.getAttribute('href');
|
|
204
|
+
var el = document.createElement(link ? 'fluent-anchor-button' : 'fluent-button');
|
|
205
|
+
el.setAttribute('appearance', primary ? 'primary' : ghost ? 'subtle' : 'secondary');
|
|
206
|
+
if (link) {
|
|
207
|
+
el.setAttribute('href', node.getAttribute('href'));
|
|
208
|
+
}
|
|
209
|
+
if (node.hasAttribute('disabled')) {
|
|
210
|
+
el.setAttribute('disabled', '');
|
|
211
|
+
}
|
|
212
|
+
var label = text(node);
|
|
213
|
+
if (label !== '') {
|
|
214
|
+
el.textContent = label;
|
|
215
|
+
}
|
|
216
|
+
copy(node, el);
|
|
217
|
+
return el;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// A text field is a fluent-text-input; the label is the kit's, kept because
|
|
221
|
+
// the library's own label needs a fluent-field wrapper and a slot per part,
|
|
222
|
+
// and the drawing wants the label in the notch on the border like the rest of
|
|
223
|
+
// the kit.
|
|
224
|
+
function upgradeInput(node) {
|
|
225
|
+
var input = document.createElement('fluent-text-input');
|
|
226
|
+
var value = text(node);
|
|
227
|
+
if (value !== '') {
|
|
228
|
+
input.setAttribute('value', value);
|
|
229
|
+
}
|
|
230
|
+
var placeholder = node.getAttribute('data-placeholder');
|
|
231
|
+
if (placeholder) {
|
|
232
|
+
input.setAttribute('placeholder', placeholder);
|
|
233
|
+
}
|
|
234
|
+
if (node.getAttribute('aria-label')) {
|
|
235
|
+
input.setAttribute('aria-label', node.getAttribute('aria-label'));
|
|
236
|
+
} else if (node.getAttribute('data-label')) {
|
|
237
|
+
input.setAttribute('aria-label', node.getAttribute('data-label'));
|
|
238
|
+
}
|
|
239
|
+
return labelled(node, input);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function optionsOf(node) {
|
|
243
|
+
var found = [];
|
|
244
|
+
var children = node.querySelectorAll('.wf-option');
|
|
245
|
+
var i;
|
|
246
|
+
for (i = 0; i < children.length; i += 1) {
|
|
247
|
+
found.push(text(children[i]));
|
|
248
|
+
}
|
|
249
|
+
if (found.length === 0 && node.getAttribute('data-options')) {
|
|
250
|
+
found = node.getAttribute('data-options').split('|');
|
|
251
|
+
for (i = 0; i < found.length; i += 1) {
|
|
252
|
+
found[i] = found[i].trim();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (found.length === 0) {
|
|
256
|
+
var only = text(node);
|
|
257
|
+
found.push(only === '' ? 'Select' : only);
|
|
258
|
+
}
|
|
259
|
+
return found;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// The dropdown reads its options out of a slotted fluent-listbox, so the
|
|
263
|
+
// options are built into one: without it the control has nothing to show.
|
|
264
|
+
function upgradeSelect(node) {
|
|
265
|
+
var dropdown = document.createElement('fluent-dropdown');
|
|
266
|
+
var listbox = document.createElement('fluent-listbox');
|
|
267
|
+
var values = optionsOf(node);
|
|
268
|
+
var current = node.getAttribute('data-value') || values[0];
|
|
269
|
+
for (var i = 0; i < values.length; i += 1) {
|
|
270
|
+
var option = document.createElement('fluent-option');
|
|
271
|
+
option.textContent = values[i];
|
|
272
|
+
if (values[i] === current) {
|
|
273
|
+
option.setAttribute('selected', '');
|
|
274
|
+
}
|
|
275
|
+
listbox.appendChild(option);
|
|
276
|
+
}
|
|
277
|
+
dropdown.appendChild(listbox);
|
|
278
|
+
return labelled(node, dropdown);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function upgradeCheckbox(node) {
|
|
282
|
+
var box = document.createElement('fluent-checkbox');
|
|
283
|
+
if (node.getAttribute('data-checked') === 'true') {
|
|
284
|
+
box.setAttribute('checked', '');
|
|
285
|
+
}
|
|
286
|
+
if (node.getAttribute('data-label')) {
|
|
287
|
+
box.textContent = node.getAttribute('data-label');
|
|
288
|
+
}
|
|
289
|
+
copy(node, box);
|
|
290
|
+
return box;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function upgradeToggle(node) {
|
|
294
|
+
var control = document.createElement('fluent-switch');
|
|
295
|
+
if (node.classList.contains('on') || node.getAttribute('data-checked') === 'true') {
|
|
296
|
+
control.setAttribute('checked', '');
|
|
297
|
+
}
|
|
298
|
+
if (node.getAttribute('data-label')) {
|
|
299
|
+
control.textContent = node.getAttribute('data-label');
|
|
300
|
+
}
|
|
301
|
+
copy(node, control);
|
|
302
|
+
return control;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function upgradeTabs(node) {
|
|
306
|
+
var list = document.createElement('fluent-tablist');
|
|
307
|
+
var active = '';
|
|
308
|
+
var children = node.children;
|
|
309
|
+
for (var i = 0; i < children.length; i += 1) {
|
|
310
|
+
var child = children[i];
|
|
311
|
+
var tab = document.createElement('fluent-tab');
|
|
312
|
+
tabSeq += 1;
|
|
313
|
+
tab.setAttribute('id', 'mk-fluent-tab-' + tabSeq);
|
|
314
|
+
tab.textContent = text(child);
|
|
315
|
+
copyTabs(child, tab);
|
|
316
|
+
if (child.classList.contains('is-active') || child.getAttribute('aria-selected') === 'true') {
|
|
317
|
+
active = tab.getAttribute('id');
|
|
318
|
+
}
|
|
319
|
+
list.appendChild(tab);
|
|
320
|
+
}
|
|
321
|
+
if (list.children.length > 0) {
|
|
322
|
+
list.setAttribute('activeid', active !== '' ? active : list.children[0].getAttribute('id'));
|
|
323
|
+
}
|
|
324
|
+
copy(node, list);
|
|
325
|
+
return list;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function copyTabs(child, tab) {
|
|
329
|
+
var attrs = child.attributes;
|
|
330
|
+
for (var i = 0; i < attrs.length; i += 1) {
|
|
331
|
+
if (attrs[i].name.indexOf('data-') === 0) {
|
|
332
|
+
tab.setAttribute(attrs[i].name, attrs[i].value);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
var BUILDERS = {
|
|
338
|
+
'wf-button': upgradeButton,
|
|
339
|
+
'wf-input': upgradeInput,
|
|
340
|
+
'wf-select': upgradeSelect,
|
|
341
|
+
'wf-checkbox': upgradeCheckbox,
|
|
342
|
+
'wf-toggle': upgradeToggle,
|
|
343
|
+
'wf-tabs': upgradeTabs
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// ------------------------------------------------------------- upgrade --
|
|
347
|
+
|
|
348
|
+
function build(node) {
|
|
349
|
+
var keys = Object.keys(BUILDERS);
|
|
350
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
351
|
+
if (!node.classList.contains(keys[i])) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
var replacement;
|
|
355
|
+
try {
|
|
356
|
+
replacement = BUILDERS[keys[i]](node);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
warn('could not upgrade ' + keys[i] + ': ' + (err && err.message ? err.message : err));
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
var parent = node.parentNode;
|
|
362
|
+
if (!parent) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
parent.replaceChild(replacement, node);
|
|
366
|
+
built.push({ original: node, upgraded: replacement });
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function upgrade() {
|
|
372
|
+
var screens = fluentScreens();
|
|
373
|
+
forget(screens);
|
|
374
|
+
if (screens.length === 0) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
ensure(function (ok) {
|
|
378
|
+
if (!ok) {
|
|
379
|
+
restore();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
for (var s = 0; s < screens.length; s += 1) {
|
|
383
|
+
if (skinOf(screens[s]) !== 'fluent') {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
var nodes = screens[s].querySelectorAll(SELECTOR);
|
|
387
|
+
for (var i = 0; i < nodes.length; i += 1) {
|
|
388
|
+
build(nodes[i]);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// A screen that stopped being fluent goes back to the kit's own controls,
|
|
395
|
+
// while the screens that are still fluent keep their real components.
|
|
396
|
+
function forget(screens) {
|
|
397
|
+
var stale = [];
|
|
398
|
+
for (var i = 0; i < built.length; i += 1) {
|
|
399
|
+
var host = built[i].upgraded.closest ? built[i].upgraded.closest('.mk-screen') : null;
|
|
400
|
+
if (screens.indexOf(host) < 0) {
|
|
401
|
+
stale.push(host);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
for (var s = 0; s < stale.length; s += 1) {
|
|
405
|
+
restore(stale[s]);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function restore(screen) {
|
|
410
|
+
for (var i = built.length - 1; i >= 0; i -= 1) {
|
|
411
|
+
var record = built[i];
|
|
412
|
+
if (screen !== undefined) {
|
|
413
|
+
var host = record.upgraded.closest ? record.upgraded.closest('.mk-screen') : null;
|
|
414
|
+
if (host !== screen) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
var parent = record.upgraded.parentNode;
|
|
419
|
+
if (parent) {
|
|
420
|
+
parent.replaceChild(record.original, record.upgraded);
|
|
421
|
+
}
|
|
422
|
+
built.splice(i, 1);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// --------------------------------------------------------------- wiring --
|
|
427
|
+
|
|
428
|
+
function schedule(delay) {
|
|
429
|
+
if (debounce !== null) {
|
|
430
|
+
window.clearTimeout(debounce);
|
|
431
|
+
}
|
|
432
|
+
debounce = window.setTimeout(function () {
|
|
433
|
+
debounce = null;
|
|
434
|
+
upgrade();
|
|
435
|
+
}, delay === undefined ? 40 : delay);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
document.addEventListener('mkchange', function () {
|
|
439
|
+
schedule(60);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// The components paint from the tokens of the active mode, so a mode change
|
|
443
|
+
// is a repaint and nothing more: the same upgrade pass keeps both modes and
|
|
444
|
+
// the toolbar's skin switch in one code path.
|
|
445
|
+
document.addEventListener('rshowmodechange', function () {
|
|
446
|
+
if (isFluent()) {
|
|
447
|
+
schedule(20);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
if (document.readyState === 'loading') {
|
|
452
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
453
|
+
schedule(0);
|
|
454
|
+
});
|
|
455
|
+
} else {
|
|
456
|
+
schedule(0);
|
|
457
|
+
}
|
|
458
|
+
}());
|