@stealthscale/sdk-host 0.1.0
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 +257 -0
- package/dist/create-routes-CkgZV-dU.js +4730 -0
- package/dist/cyclonedx/bom.json +1 -0
- package/dist/index.d.ts +288 -0
- package/dist/index.js +81 -0
- package/dist/openfeature.d.ts +27 -0
- package/dist/openfeature.js +80 -0
- package/dist/page-7ScZC_LI.js +62 -0
- package/dist/section-CtcVFcBK.js +41 -0
- package/dist/standalone/app.d.ts +65 -0
- package/dist/standalone/app.js +1426 -0
- package/dist/standalone-XfUZYt9b.d.ts +137 -0
- package/dist/standalone.d.ts +2 -0
- package/dist/standalone.js +257 -0
- package/dist/words-yI-WdYM3.js +58 -0
- package/locales/en/host.json +135 -0
- package/package.json +139 -0
|
@@ -0,0 +1,1426 @@
|
|
|
1
|
+
import { a as HostContent, c as sampledFrom, i as HostNotFound, n as HostRoot, o as createHost, r as HostProvider, s as internalsOf, t as createHostRoutes } from "../create-routes-CkgZV-dU.js";
|
|
2
|
+
import { standaloneSources } from "../standalone.js";
|
|
3
|
+
import { DataError } from "@stealthscale/provider-data";
|
|
4
|
+
import { hostContract } from "@stealthscale/sdk-core";
|
|
5
|
+
import { Into, Slot, useResolvedProduct, useSlot } from "@stealthscale/sdk-plugin";
|
|
6
|
+
import { localStore } from "@stealthscale/settings";
|
|
7
|
+
import { c } from "react/compiler-runtime";
|
|
8
|
+
import { RouterProvider, createAppRootRoute, createRouter, routeHref, routeMap, routerOptions, useRouteContext, useRouter, useRouterState } from "@stealthscale/provider-router";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { Fragment as Fragment$1, createContext, use, useState, useSyncExternalStore } from "react";
|
|
11
|
+
import { useTranslation } from "@stealthscale/provider-i18n";
|
|
12
|
+
import { Stack } from "@stealthscale/component-layout";
|
|
13
|
+
import { AppShell, FloatingPanel } from "@stealthscale/component-screen";
|
|
14
|
+
import { Field, Fieldset, NativeSelect, SegmentGroup, Switch } from "@stealthscale/component-forms";
|
|
15
|
+
import { createRoot } from "react-dom/client";
|
|
16
|
+
import { Shell, useThemeChoice } from "@stealthscale/provider-shell";
|
|
17
|
+
import { useColorMode } from "@stealthscale/provider-color-mode";
|
|
18
|
+
import { useLocale } from "@stealthscale/provider-locale";
|
|
19
|
+
//#region src/standalone/context.ts
|
|
20
|
+
/**
|
|
21
|
+
* Provides the development panel with the standalone page's sources, its operation modes, its
|
|
22
|
+
* declared flags, the router's map and the page's glyphs.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Provides the standalone page's state to the panel. The value is undefined outside the page.
|
|
26
|
+
*/
|
|
27
|
+
const StandaloneContext = createContext(void 0);
|
|
28
|
+
/**
|
|
29
|
+
* Returns the standalone page's state.
|
|
30
|
+
*
|
|
31
|
+
* @throws {@link Error} Outside the standalone page.
|
|
32
|
+
*/
|
|
33
|
+
function useStandalone() {
|
|
34
|
+
const state = use(StandaloneContext);
|
|
35
|
+
if (state === void 0) throw new Error("The development panel renders inside the standalone page alone.");
|
|
36
|
+
return state;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/standalone/data.ts
|
|
40
|
+
/**
|
|
41
|
+
* Serves a standalone product's operations as the development panel sets each one: from its
|
|
42
|
+
* sample, from its sample after a delay, or with a refusal of one kind.
|
|
43
|
+
*/
|
|
44
|
+
/**
|
|
45
|
+
* Lists every mode, in the order the panel offers them.
|
|
46
|
+
*/
|
|
47
|
+
const MODES$1 = [
|
|
48
|
+
"sample",
|
|
49
|
+
"delayed",
|
|
50
|
+
"conflict",
|
|
51
|
+
"forbidden",
|
|
52
|
+
"invalid",
|
|
53
|
+
"network",
|
|
54
|
+
"not-found",
|
|
55
|
+
"server",
|
|
56
|
+
"unauthenticated"
|
|
57
|
+
];
|
|
58
|
+
/**
|
|
59
|
+
* The milliseconds a delayed operation waits before it serves its sample.
|
|
60
|
+
*/
|
|
61
|
+
const DELAY = 2e3;
|
|
62
|
+
/**
|
|
63
|
+
* Returns the operation modes of one page, every operation at its sample until the panel sets
|
|
64
|
+
* another mode.
|
|
65
|
+
*/
|
|
66
|
+
function operationModes() {
|
|
67
|
+
let modes = {};
|
|
68
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
69
|
+
return {
|
|
70
|
+
get: () => modes,
|
|
71
|
+
set: (id, mode) => {
|
|
72
|
+
modes = {
|
|
73
|
+
...modes,
|
|
74
|
+
[id]: mode
|
|
75
|
+
};
|
|
76
|
+
for (const listener of listeners) listener();
|
|
77
|
+
},
|
|
78
|
+
subscribe: (listener) => {
|
|
79
|
+
listeners.add(listener);
|
|
80
|
+
return () => {
|
|
81
|
+
listeners.delete(listener);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns a transport that serves each declared operation in the mode the panel set for it when it
|
|
88
|
+
* runs.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* A delayed operation serves its sample after `DELAY`. A refused one rejects with a `DataError`
|
|
92
|
+
* of the mode's kind, so the page renders the error state the kind leads to. A subscription
|
|
93
|
+
* streams nothing, as the sampled transport's does.
|
|
94
|
+
* @param product - The declared queries and mutations, whose samples the transport serves.
|
|
95
|
+
* @param modes - The mode of each operation.
|
|
96
|
+
*/
|
|
97
|
+
function standaloneTransport(product, modes) {
|
|
98
|
+
const sampled = sampledFrom(product);
|
|
99
|
+
return {
|
|
100
|
+
run: async (operation, variables, options) => {
|
|
101
|
+
const mode = modes.get()[operation.id] ?? "sample";
|
|
102
|
+
if (mode === "delayed") await new Promise((resolve) => {
|
|
103
|
+
setTimeout(resolve, DELAY);
|
|
104
|
+
});
|
|
105
|
+
else if (mode !== "sample") throw new DataError({
|
|
106
|
+
kind: mode,
|
|
107
|
+
message: `The development panel refuses ${operation.id} as ${mode}.`,
|
|
108
|
+
operation: operation.id
|
|
109
|
+
});
|
|
110
|
+
return sampled.run(operation, variables, options);
|
|
111
|
+
},
|
|
112
|
+
subscribe: (operation, variables, next, signal) => sampled.subscribe(operation, variables, next, signal)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/standalone/hosted.ts
|
|
117
|
+
/**
|
|
118
|
+
* Creates the host of the standalone page.
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* The page keeps a person's switches, settings and placements in local storage by default, so
|
|
122
|
+
* they outlast a reload as they do in a product. The session, the decisions, the flag overrides
|
|
123
|
+
* and the operations' modes start afresh on every load.
|
|
124
|
+
* @param product - The standalone product, from `virtual:product`.
|
|
125
|
+
* @param glyphs - The glyphs the settings sections' forms render.
|
|
126
|
+
* @param store - The store of a person's switches, settings and placements.
|
|
127
|
+
*/
|
|
128
|
+
function standaloneHosted(product, glyphs, store = localStore()) {
|
|
129
|
+
const sources = standaloneSources(product);
|
|
130
|
+
const modes = operationModes();
|
|
131
|
+
return {
|
|
132
|
+
host: createHost({
|
|
133
|
+
access: sources.access,
|
|
134
|
+
data: { transport: standaloneTransport(product, modes) },
|
|
135
|
+
flags: sources.flags,
|
|
136
|
+
glyphs,
|
|
137
|
+
product,
|
|
138
|
+
session: sources.session,
|
|
139
|
+
store
|
|
140
|
+
}),
|
|
141
|
+
modes,
|
|
142
|
+
sources
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/standalone/group.tsx
|
|
147
|
+
/**
|
|
148
|
+
* Renders a small fieldset with its legend and its controls stacked under it.
|
|
149
|
+
*
|
|
150
|
+
* @param props - The legend and the controls.
|
|
151
|
+
* @returns The fieldset.
|
|
152
|
+
*/
|
|
153
|
+
function Group(t0) {
|
|
154
|
+
const $ = c(7);
|
|
155
|
+
const { children, title } = t0;
|
|
156
|
+
let t1;
|
|
157
|
+
if ($[0] !== title) {
|
|
158
|
+
t1 = /* @__PURE__ */ jsx(Fieldset.Legend, { children: title });
|
|
159
|
+
$[0] = title;
|
|
160
|
+
$[1] = t1;
|
|
161
|
+
} else t1 = $[1];
|
|
162
|
+
let t2;
|
|
163
|
+
if ($[2] !== children) {
|
|
164
|
+
t2 = /* @__PURE__ */ jsx(Stack, {
|
|
165
|
+
gap: "sm",
|
|
166
|
+
children
|
|
167
|
+
});
|
|
168
|
+
$[2] = children;
|
|
169
|
+
$[3] = t2;
|
|
170
|
+
} else t2 = $[3];
|
|
171
|
+
let t3;
|
|
172
|
+
if ($[4] !== t1 || $[5] !== t2) {
|
|
173
|
+
t3 = /* @__PURE__ */ jsxs(Fieldset.Root, {
|
|
174
|
+
size: "sm",
|
|
175
|
+
children: [t1, t2]
|
|
176
|
+
});
|
|
177
|
+
$[4] = t1;
|
|
178
|
+
$[5] = t2;
|
|
179
|
+
$[6] = t3;
|
|
180
|
+
} else t3 = $[6];
|
|
181
|
+
return t3;
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/standalone/access-controls.tsx
|
|
185
|
+
/**
|
|
186
|
+
* Renders the development panel's control of the decisions on single resources: every check
|
|
187
|
+
* allowed, every check denied, or every check pending.
|
|
188
|
+
*/
|
|
189
|
+
/**
|
|
190
|
+
* Lists the decisions in the order the panel offers them, each with the key of its words and the
|
|
191
|
+
* call that applies it.
|
|
192
|
+
*/
|
|
193
|
+
const DECISIONS = [
|
|
194
|
+
{
|
|
195
|
+
apply: (access) => {
|
|
196
|
+
access.allow();
|
|
197
|
+
},
|
|
198
|
+
key: "standalone.panel.access.allow",
|
|
199
|
+
value: "allow"
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
apply: (access) => {
|
|
203
|
+
access.deny();
|
|
204
|
+
},
|
|
205
|
+
key: "standalone.panel.access.deny",
|
|
206
|
+
value: "deny"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
apply: (access) => {
|
|
210
|
+
access.pending();
|
|
211
|
+
},
|
|
212
|
+
key: "standalone.panel.access.pending",
|
|
213
|
+
value: "pending"
|
|
214
|
+
}
|
|
215
|
+
];
|
|
216
|
+
/**
|
|
217
|
+
* Renders a segment group of the three decisions, which applies the one a person picks to every
|
|
218
|
+
* check from then on.
|
|
219
|
+
*
|
|
220
|
+
* @remarks
|
|
221
|
+
* The access source tells the host's access store, which drops the decisions it knew and asks
|
|
222
|
+
* again, so every `useAccess` on the page follows.
|
|
223
|
+
* @returns The group.
|
|
224
|
+
*/
|
|
225
|
+
function AccessControls() {
|
|
226
|
+
const $ = c(16);
|
|
227
|
+
const { access } = useStandalone();
|
|
228
|
+
const { t } = useTranslation("host");
|
|
229
|
+
const [decision, setDecision] = useState("allow");
|
|
230
|
+
let t0;
|
|
231
|
+
if ($[0] !== t) {
|
|
232
|
+
t0 = t("standalone.panel.access.title");
|
|
233
|
+
$[0] = t;
|
|
234
|
+
$[1] = t0;
|
|
235
|
+
} else t0 = $[1];
|
|
236
|
+
let t1;
|
|
237
|
+
if ($[2] !== t) {
|
|
238
|
+
t1 = t("standalone.panel.access.title");
|
|
239
|
+
$[2] = t;
|
|
240
|
+
$[3] = t1;
|
|
241
|
+
} else t1 = $[3];
|
|
242
|
+
let t2;
|
|
243
|
+
if ($[4] !== access) {
|
|
244
|
+
t2 = (t3) => {
|
|
245
|
+
const { value } = t3;
|
|
246
|
+
const picked = DECISIONS.find((one) => one.value === value);
|
|
247
|
+
picked.apply(access);
|
|
248
|
+
setDecision(picked.value);
|
|
249
|
+
};
|
|
250
|
+
$[4] = access;
|
|
251
|
+
$[5] = t2;
|
|
252
|
+
} else t2 = $[5];
|
|
253
|
+
let t3;
|
|
254
|
+
if ($[6] !== t) {
|
|
255
|
+
t3 = DECISIONS.map((t4) => {
|
|
256
|
+
const { key, value: value_0 } = t4;
|
|
257
|
+
return /* @__PURE__ */ jsx(SegmentGroup.Item, {
|
|
258
|
+
value: value_0,
|
|
259
|
+
children: /* @__PURE__ */ jsx(SegmentGroup.ItemText, { children: t(key) })
|
|
260
|
+
}, value_0);
|
|
261
|
+
});
|
|
262
|
+
$[6] = t;
|
|
263
|
+
$[7] = t3;
|
|
264
|
+
} else t3 = $[7];
|
|
265
|
+
let t4;
|
|
266
|
+
if ($[8] !== decision || $[9] !== t1 || $[10] !== t2 || $[11] !== t3) {
|
|
267
|
+
t4 = /* @__PURE__ */ jsx(SegmentGroup.Root, {
|
|
268
|
+
"aria-label": t1,
|
|
269
|
+
onValueChange: t2,
|
|
270
|
+
size: "sm",
|
|
271
|
+
value: decision,
|
|
272
|
+
children: t3
|
|
273
|
+
});
|
|
274
|
+
$[8] = decision;
|
|
275
|
+
$[9] = t1;
|
|
276
|
+
$[10] = t2;
|
|
277
|
+
$[11] = t3;
|
|
278
|
+
$[12] = t4;
|
|
279
|
+
} else t4 = $[12];
|
|
280
|
+
let t5;
|
|
281
|
+
if ($[13] !== t0 || $[14] !== t4) {
|
|
282
|
+
t5 = /* @__PURE__ */ jsx(Group, {
|
|
283
|
+
title: t0,
|
|
284
|
+
children: t4
|
|
285
|
+
});
|
|
286
|
+
$[13] = t0;
|
|
287
|
+
$[14] = t4;
|
|
288
|
+
$[15] = t5;
|
|
289
|
+
} else t5 = $[15];
|
|
290
|
+
return t5;
|
|
291
|
+
}
|
|
292
|
+
//#endregion
|
|
293
|
+
//#region src/standalone/picker.tsx
|
|
294
|
+
/**
|
|
295
|
+
* Renders a small native select in a field its label names.
|
|
296
|
+
*
|
|
297
|
+
* @remarks
|
|
298
|
+
* The panel picks with a native select, because a listbox opened inside a floating panel stacks
|
|
299
|
+
* under the panel. The select states its size itself: the stylesheet compiler emits the rules of
|
|
300
|
+
* the sizes it reads in the source, and a size the select takes from the field at run time has
|
|
301
|
+
* none.
|
|
302
|
+
* @param props - The choices, the value, the words, the glyph and the callback a pick calls.
|
|
303
|
+
* @returns The field.
|
|
304
|
+
*/
|
|
305
|
+
function Picker(t0) {
|
|
306
|
+
const $ = c(18);
|
|
307
|
+
const { choices, indicator, label, onValueChange, value } = t0;
|
|
308
|
+
let t1;
|
|
309
|
+
if ($[0] !== label) {
|
|
310
|
+
t1 = /* @__PURE__ */ jsx(Field.Label, { children: label });
|
|
311
|
+
$[0] = label;
|
|
312
|
+
$[1] = t1;
|
|
313
|
+
} else t1 = $[1];
|
|
314
|
+
let t2;
|
|
315
|
+
if ($[2] !== onValueChange) {
|
|
316
|
+
t2 = (event) => {
|
|
317
|
+
onValueChange(event.currentTarget.value);
|
|
318
|
+
};
|
|
319
|
+
$[2] = onValueChange;
|
|
320
|
+
$[3] = t2;
|
|
321
|
+
} else t2 = $[3];
|
|
322
|
+
let t3;
|
|
323
|
+
if ($[4] !== choices) {
|
|
324
|
+
t3 = choices.map(_temp$7);
|
|
325
|
+
$[4] = choices;
|
|
326
|
+
$[5] = t3;
|
|
327
|
+
} else t3 = $[5];
|
|
328
|
+
let t4;
|
|
329
|
+
if ($[6] !== t2 || $[7] !== t3 || $[8] !== value) {
|
|
330
|
+
t4 = /* @__PURE__ */ jsx(NativeSelect.Field, {
|
|
331
|
+
onChange: t2,
|
|
332
|
+
value,
|
|
333
|
+
children: t3
|
|
334
|
+
});
|
|
335
|
+
$[6] = t2;
|
|
336
|
+
$[7] = t3;
|
|
337
|
+
$[8] = value;
|
|
338
|
+
$[9] = t4;
|
|
339
|
+
} else t4 = $[9];
|
|
340
|
+
let t5;
|
|
341
|
+
if ($[10] !== indicator) {
|
|
342
|
+
t5 = indicator === void 0 ? null : /* @__PURE__ */ jsx(NativeSelect.Indicator, { children: indicator });
|
|
343
|
+
$[10] = indicator;
|
|
344
|
+
$[11] = t5;
|
|
345
|
+
} else t5 = $[11];
|
|
346
|
+
let t6;
|
|
347
|
+
if ($[12] !== t4 || $[13] !== t5) {
|
|
348
|
+
t6 = /* @__PURE__ */ jsxs(NativeSelect.Root, {
|
|
349
|
+
size: "sm",
|
|
350
|
+
children: [t4, t5]
|
|
351
|
+
});
|
|
352
|
+
$[12] = t4;
|
|
353
|
+
$[13] = t5;
|
|
354
|
+
$[14] = t6;
|
|
355
|
+
} else t6 = $[14];
|
|
356
|
+
let t7;
|
|
357
|
+
if ($[15] !== t1 || $[16] !== t6) {
|
|
358
|
+
t7 = /* @__PURE__ */ jsxs(Field.Root, {
|
|
359
|
+
size: "sm",
|
|
360
|
+
children: [t1, t6]
|
|
361
|
+
});
|
|
362
|
+
$[15] = t1;
|
|
363
|
+
$[16] = t6;
|
|
364
|
+
$[17] = t7;
|
|
365
|
+
} else t7 = $[17];
|
|
366
|
+
return t7;
|
|
367
|
+
}
|
|
368
|
+
function _temp$7(choice) {
|
|
369
|
+
return /* @__PURE__ */ jsx("option", {
|
|
370
|
+
value: choice.value,
|
|
371
|
+
children: choice.label
|
|
372
|
+
}, choice.value);
|
|
373
|
+
}
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/standalone/data-controls.tsx
|
|
376
|
+
/**
|
|
377
|
+
* Renders the development panel's operation controls: a picker per declared query and mutation of
|
|
378
|
+
* how the page's transport serves it.
|
|
379
|
+
*/
|
|
380
|
+
/**
|
|
381
|
+
* Maps each mode to the key of its words.
|
|
382
|
+
*/
|
|
383
|
+
const WORDS = {
|
|
384
|
+
conflict: "standalone.panel.data.modes.conflict",
|
|
385
|
+
delayed: "standalone.panel.data.modes.delayed",
|
|
386
|
+
forbidden: "standalone.panel.data.modes.forbidden",
|
|
387
|
+
invalid: "standalone.panel.data.modes.invalid",
|
|
388
|
+
network: "standalone.panel.data.modes.network",
|
|
389
|
+
"not-found": "standalone.panel.data.modes.not-found",
|
|
390
|
+
sample: "standalone.panel.data.modes.sample",
|
|
391
|
+
server: "standalone.panel.data.modes.server",
|
|
392
|
+
unauthenticated: "standalone.panel.data.modes.unauthenticated"
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* Renders one picker per declared query and mutation, named by its qualified id, which sets how the
|
|
396
|
+
* page's transport serves its operation.
|
|
397
|
+
*
|
|
398
|
+
* @remarks
|
|
399
|
+
* A query's pick resets every query of the page's data client and invalidates the router, so a
|
|
400
|
+
* page on screen loads again from nothing in the new mode: a refusal shows the page's error, a
|
|
401
|
+
* delay its pending state, and a page that failed renders again. An invalidation of the queries
|
|
402
|
+
* alone would keep the cached data through a refetch that fails or waits. A mutation runs in its
|
|
403
|
+
* mode the next time a person sends it, and its pick loads nothing again.
|
|
404
|
+
* @returns The group.
|
|
405
|
+
*/
|
|
406
|
+
function DataControls() {
|
|
407
|
+
const $ = c(22);
|
|
408
|
+
const { glyphs, modes } = useStandalone();
|
|
409
|
+
let t0;
|
|
410
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
411
|
+
t0 = { strict: false };
|
|
412
|
+
$[0] = t0;
|
|
413
|
+
} else t0 = $[0];
|
|
414
|
+
const { host } = useRouteContext(t0);
|
|
415
|
+
const router = useRouter();
|
|
416
|
+
const { t } = useTranslation("host");
|
|
417
|
+
const { mutations, queries } = useResolvedProduct();
|
|
418
|
+
const current = useSyncExternalStore(modes.subscribe, modes.get, modes.get);
|
|
419
|
+
let t1;
|
|
420
|
+
if ($[1] !== t) {
|
|
421
|
+
t1 = MODES$1.map((mode) => ({
|
|
422
|
+
label: t(WORDS[mode]),
|
|
423
|
+
value: mode
|
|
424
|
+
}));
|
|
425
|
+
$[1] = t;
|
|
426
|
+
$[2] = t1;
|
|
427
|
+
} else t1 = $[2];
|
|
428
|
+
const choices = t1;
|
|
429
|
+
let t2;
|
|
430
|
+
if ($[3] !== queries) {
|
|
431
|
+
t2 = new Set(queries.map(_temp$6));
|
|
432
|
+
$[3] = queries;
|
|
433
|
+
$[4] = t2;
|
|
434
|
+
} else t2 = $[4];
|
|
435
|
+
const loaded = t2;
|
|
436
|
+
let t3;
|
|
437
|
+
if ($[5] !== t) {
|
|
438
|
+
t3 = t("standalone.panel.data.title");
|
|
439
|
+
$[5] = t;
|
|
440
|
+
$[6] = t3;
|
|
441
|
+
} else t3 = $[6];
|
|
442
|
+
let t4;
|
|
443
|
+
if ($[7] !== mutations || $[8] !== queries) {
|
|
444
|
+
t4 = [...queries, ...mutations];
|
|
445
|
+
$[7] = mutations;
|
|
446
|
+
$[8] = queries;
|
|
447
|
+
$[9] = t4;
|
|
448
|
+
} else t4 = $[9];
|
|
449
|
+
let t5;
|
|
450
|
+
if ($[10] !== choices || $[11] !== current || $[12] !== glyphs || $[13] !== host || $[14] !== loaded || $[15] !== modes || $[16] !== router || $[17] !== t4) {
|
|
451
|
+
t5 = t4.map((t6) => {
|
|
452
|
+
const { id, operation: operation_0 } = t6;
|
|
453
|
+
return /* @__PURE__ */ jsx(Picker, {
|
|
454
|
+
choices,
|
|
455
|
+
indicator: glyphs.select?.indicator,
|
|
456
|
+
label: id,
|
|
457
|
+
onValueChange: (value) => {
|
|
458
|
+
modes.set(operation_0.id, value);
|
|
459
|
+
if (!loaded.has(operation_0.id)) return;
|
|
460
|
+
host.data.resetQueries();
|
|
461
|
+
router.invalidate();
|
|
462
|
+
},
|
|
463
|
+
value: current[operation_0.id] ?? "sample"
|
|
464
|
+
}, id);
|
|
465
|
+
});
|
|
466
|
+
$[10] = choices;
|
|
467
|
+
$[11] = current;
|
|
468
|
+
$[12] = glyphs;
|
|
469
|
+
$[13] = host;
|
|
470
|
+
$[14] = loaded;
|
|
471
|
+
$[15] = modes;
|
|
472
|
+
$[16] = router;
|
|
473
|
+
$[17] = t4;
|
|
474
|
+
$[18] = t5;
|
|
475
|
+
} else t5 = $[18];
|
|
476
|
+
let t6;
|
|
477
|
+
if ($[19] !== t3 || $[20] !== t5) {
|
|
478
|
+
t6 = /* @__PURE__ */ jsx(Group, {
|
|
479
|
+
title: t3,
|
|
480
|
+
children: t5
|
|
481
|
+
});
|
|
482
|
+
$[19] = t3;
|
|
483
|
+
$[20] = t5;
|
|
484
|
+
$[21] = t6;
|
|
485
|
+
} else t6 = $[21];
|
|
486
|
+
return t6;
|
|
487
|
+
}
|
|
488
|
+
function _temp$6(t0) {
|
|
489
|
+
const { operation } = t0;
|
|
490
|
+
return operation.id;
|
|
491
|
+
}
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/standalone/toggle.tsx
|
|
494
|
+
/**
|
|
495
|
+
* Renders a small switch that spreads across the panel, its words at the start and its control at
|
|
496
|
+
* the end.
|
|
497
|
+
*
|
|
498
|
+
* @param props - The state, the words and the callback a press calls.
|
|
499
|
+
* @returns The switch.
|
|
500
|
+
*/
|
|
501
|
+
function Toggle(t0) {
|
|
502
|
+
const $ = c(9);
|
|
503
|
+
const { checked, label, onCheckedChange } = t0;
|
|
504
|
+
let t1;
|
|
505
|
+
if ($[0] !== onCheckedChange) {
|
|
506
|
+
t1 = (details) => {
|
|
507
|
+
onCheckedChange(details.checked);
|
|
508
|
+
};
|
|
509
|
+
$[0] = onCheckedChange;
|
|
510
|
+
$[1] = t1;
|
|
511
|
+
} else t1 = $[1];
|
|
512
|
+
let t2;
|
|
513
|
+
if ($[2] !== label) {
|
|
514
|
+
t2 = /* @__PURE__ */ jsx(Switch.Label, { children: label });
|
|
515
|
+
$[2] = label;
|
|
516
|
+
$[3] = t2;
|
|
517
|
+
} else t2 = $[3];
|
|
518
|
+
let t3;
|
|
519
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
520
|
+
t3 = /* @__PURE__ */ jsx(Switch.Control, { children: /* @__PURE__ */ jsx(Switch.Thumb, {}) });
|
|
521
|
+
$[4] = t3;
|
|
522
|
+
} else t3 = $[4];
|
|
523
|
+
let t4;
|
|
524
|
+
if ($[5] !== checked || $[6] !== t1 || $[7] !== t2) {
|
|
525
|
+
t4 = /* @__PURE__ */ jsxs(Switch.Root, {
|
|
526
|
+
checked,
|
|
527
|
+
onCheckedChange: t1,
|
|
528
|
+
size: "sm",
|
|
529
|
+
spread: true,
|
|
530
|
+
children: [t2, t3]
|
|
531
|
+
});
|
|
532
|
+
$[5] = checked;
|
|
533
|
+
$[6] = t1;
|
|
534
|
+
$[7] = t2;
|
|
535
|
+
$[8] = t4;
|
|
536
|
+
} else t4 = $[8];
|
|
537
|
+
return t4;
|
|
538
|
+
}
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region src/standalone/flag-controls.tsx
|
|
541
|
+
/**
|
|
542
|
+
* Renders the development panel's flag controls: a switch per boolean flag, and a picker per
|
|
543
|
+
* experiment.
|
|
544
|
+
*/
|
|
545
|
+
/**
|
|
546
|
+
* Renders one control per flag the installed plugins declare, named by its qualified id, which
|
|
547
|
+
* overrides the flag in this tab.
|
|
548
|
+
*
|
|
549
|
+
* @remarks
|
|
550
|
+
* An override replaces the value every condition, menu and `useFeatureFlag` on the page reads, as
|
|
551
|
+
* the flag store's overrides do in a product outside production.
|
|
552
|
+
* @returns The group.
|
|
553
|
+
*/
|
|
554
|
+
function FlagControls() {
|
|
555
|
+
const $ = c(13);
|
|
556
|
+
const { flags: declared, glyphs } = useStandalone();
|
|
557
|
+
let t0;
|
|
558
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
559
|
+
t0 = { strict: false };
|
|
560
|
+
$[0] = t0;
|
|
561
|
+
} else t0 = $[0];
|
|
562
|
+
const { host } = useRouteContext(t0);
|
|
563
|
+
const { flags } = host.stores;
|
|
564
|
+
const { t } = useTranslation("host");
|
|
565
|
+
useSyncExternalStore(flags.subscribe, flags.get, flags.get);
|
|
566
|
+
let t1;
|
|
567
|
+
if ($[1] !== t) {
|
|
568
|
+
t1 = t("standalone.panel.flags.title");
|
|
569
|
+
$[1] = t;
|
|
570
|
+
$[2] = t1;
|
|
571
|
+
} else t1 = $[2];
|
|
572
|
+
let t2;
|
|
573
|
+
if ($[3] !== declared || $[4] !== flags || $[5] !== glyphs) {
|
|
574
|
+
let t3;
|
|
575
|
+
if ($[7] !== flags || $[8] !== glyphs) {
|
|
576
|
+
t3 = (t4) => {
|
|
577
|
+
const { id, variants } = t4;
|
|
578
|
+
return variants === void 0 ? /* @__PURE__ */ jsx(Toggle, {
|
|
579
|
+
checked: flags.read(id) === true,
|
|
580
|
+
label: id,
|
|
581
|
+
onCheckedChange: (on) => {
|
|
582
|
+
flags.override(id, on);
|
|
583
|
+
}
|
|
584
|
+
}, id) : /* @__PURE__ */ jsx(Picker, {
|
|
585
|
+
choices: variants.map(_temp$5),
|
|
586
|
+
indicator: glyphs.select?.indicator,
|
|
587
|
+
label: id,
|
|
588
|
+
onValueChange: (variant_0) => {
|
|
589
|
+
flags.override(id, variant_0);
|
|
590
|
+
},
|
|
591
|
+
value: String(flags.read(id))
|
|
592
|
+
}, id);
|
|
593
|
+
};
|
|
594
|
+
$[7] = flags;
|
|
595
|
+
$[8] = glyphs;
|
|
596
|
+
$[9] = t3;
|
|
597
|
+
} else t3 = $[9];
|
|
598
|
+
t2 = declared.map(t3);
|
|
599
|
+
$[3] = declared;
|
|
600
|
+
$[4] = flags;
|
|
601
|
+
$[5] = glyphs;
|
|
602
|
+
$[6] = t2;
|
|
603
|
+
} else t2 = $[6];
|
|
604
|
+
let t3;
|
|
605
|
+
if ($[10] !== t1 || $[11] !== t2) {
|
|
606
|
+
t3 = /* @__PURE__ */ jsx(Group, {
|
|
607
|
+
title: t1,
|
|
608
|
+
children: t2
|
|
609
|
+
});
|
|
610
|
+
$[10] = t1;
|
|
611
|
+
$[11] = t2;
|
|
612
|
+
$[12] = t3;
|
|
613
|
+
} else t3 = $[12];
|
|
614
|
+
return t3;
|
|
615
|
+
}
|
|
616
|
+
function _temp$5(variant) {
|
|
617
|
+
return {
|
|
618
|
+
label: variant,
|
|
619
|
+
value: variant
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region src/standalone/page-controls.tsx
|
|
624
|
+
/**
|
|
625
|
+
* Renders a picker of the routes in the router's map that a sample or an empty path fills, each
|
|
626
|
+
* named by its qualified id, which opens the route a person picks.
|
|
627
|
+
*
|
|
628
|
+
* @remarks
|
|
629
|
+
* The picker shows the address the page is at, and lists it first where no route's sample leads
|
|
630
|
+
* there, such as a page a link opened with other parameters.
|
|
631
|
+
* @returns The field.
|
|
632
|
+
*/
|
|
633
|
+
function PageControls() {
|
|
634
|
+
const $ = c(19);
|
|
635
|
+
const { glyphs, routes } = useStandalone();
|
|
636
|
+
const router = useRouter();
|
|
637
|
+
let t0;
|
|
638
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
639
|
+
t0 = { select: _temp$4 };
|
|
640
|
+
$[0] = t0;
|
|
641
|
+
} else t0 = $[0];
|
|
642
|
+
const pathname = useRouterState(t0);
|
|
643
|
+
const { t } = useTranslation("host");
|
|
644
|
+
const t1 = useResolvedProduct();
|
|
645
|
+
let t2;
|
|
646
|
+
if ($[1] !== pathname || $[2] !== routes || $[3] !== t1.routes) {
|
|
647
|
+
let t3;
|
|
648
|
+
if ($[5] !== routes) {
|
|
649
|
+
t3 = (t4) => {
|
|
650
|
+
const { id, path, sample } = t4;
|
|
651
|
+
return routes.has(id) && (sample !== void 0 || !path.includes("$"));
|
|
652
|
+
};
|
|
653
|
+
$[5] = routes;
|
|
654
|
+
$[6] = t3;
|
|
655
|
+
} else t3 = $[6];
|
|
656
|
+
const declared = t1.routes.filter(t3);
|
|
657
|
+
let t4;
|
|
658
|
+
if ($[7] !== routes) {
|
|
659
|
+
t4 = (t5) => {
|
|
660
|
+
const { id: id_0, sample: sample_0 } = t5;
|
|
661
|
+
return {
|
|
662
|
+
label: id_0,
|
|
663
|
+
value: routeHref(routes, { id: id_0 }, sample_0)
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
$[7] = routes;
|
|
667
|
+
$[8] = t4;
|
|
668
|
+
} else t4 = $[8];
|
|
669
|
+
const choices = declared.map(t4);
|
|
670
|
+
t2 = choices.some((t5) => {
|
|
671
|
+
const { value } = t5;
|
|
672
|
+
return value === pathname;
|
|
673
|
+
}) ? choices : [{
|
|
674
|
+
label: pathname,
|
|
675
|
+
value: pathname
|
|
676
|
+
}, ...choices];
|
|
677
|
+
$[1] = pathname;
|
|
678
|
+
$[2] = routes;
|
|
679
|
+
$[3] = t1.routes;
|
|
680
|
+
$[4] = t2;
|
|
681
|
+
} else t2 = $[4];
|
|
682
|
+
const listed = t2;
|
|
683
|
+
const t3 = glyphs.select?.indicator;
|
|
684
|
+
let t4;
|
|
685
|
+
if ($[9] !== t) {
|
|
686
|
+
t4 = t("standalone.panel.page.route");
|
|
687
|
+
$[9] = t;
|
|
688
|
+
$[10] = t4;
|
|
689
|
+
} else t4 = $[10];
|
|
690
|
+
let t5;
|
|
691
|
+
if ($[11] !== router) {
|
|
692
|
+
t5 = (to) => {
|
|
693
|
+
router.navigate({ to });
|
|
694
|
+
};
|
|
695
|
+
$[11] = router;
|
|
696
|
+
$[12] = t5;
|
|
697
|
+
} else t5 = $[12];
|
|
698
|
+
let t6;
|
|
699
|
+
if ($[13] !== listed || $[14] !== pathname || $[15] !== t3 || $[16] !== t4 || $[17] !== t5) {
|
|
700
|
+
t6 = /* @__PURE__ */ jsx(Picker, {
|
|
701
|
+
choices: listed,
|
|
702
|
+
indicator: t3,
|
|
703
|
+
label: t4,
|
|
704
|
+
onValueChange: t5,
|
|
705
|
+
value: pathname
|
|
706
|
+
});
|
|
707
|
+
$[13] = listed;
|
|
708
|
+
$[14] = pathname;
|
|
709
|
+
$[15] = t3;
|
|
710
|
+
$[16] = t4;
|
|
711
|
+
$[17] = t5;
|
|
712
|
+
$[18] = t6;
|
|
713
|
+
} else t6 = $[18];
|
|
714
|
+
return t6;
|
|
715
|
+
}
|
|
716
|
+
function _temp$4(state) {
|
|
717
|
+
return state.location.pathname;
|
|
718
|
+
}
|
|
719
|
+
//#endregion
|
|
720
|
+
//#region src/standalone/plugin-controls.tsx
|
|
721
|
+
/**
|
|
722
|
+
* Renders the development panel's plugin controls: the plugin's switch, and its kill switch.
|
|
723
|
+
*/
|
|
724
|
+
/**
|
|
725
|
+
* Renders the switch of the plugin the standalone product runs, and the switch of its kill switch.
|
|
726
|
+
*
|
|
727
|
+
* @remarks
|
|
728
|
+
* The standalone product's id is the plugin's. The first switch writes the person's switch, as
|
|
729
|
+
* the Plugins page does. The second overrides the kill switch in this tab, so the plugin's pages
|
|
730
|
+
* turn not found and its contributions leave the page.
|
|
731
|
+
* @returns The group.
|
|
732
|
+
*/
|
|
733
|
+
function PluginControls() {
|
|
734
|
+
const $ = c(9);
|
|
735
|
+
let t0;
|
|
736
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
737
|
+
t0 = { strict: false };
|
|
738
|
+
$[0] = t0;
|
|
739
|
+
} else t0 = $[0];
|
|
740
|
+
const { host } = useRouteContext(t0);
|
|
741
|
+
const { switches } = internalsOf(host);
|
|
742
|
+
const { flags } = host.stores;
|
|
743
|
+
const { t } = useTranslation("host");
|
|
744
|
+
const { plugins, productId } = useResolvedProduct();
|
|
745
|
+
const switched = useSyncExternalStore(switches.subscribe, switches.get, switches.get);
|
|
746
|
+
useSyncExternalStore(flags.subscribe, flags.get, flags.get);
|
|
747
|
+
const T0 = Group;
|
|
748
|
+
let t1;
|
|
749
|
+
if ($[1] !== t) {
|
|
750
|
+
t1 = t("standalone.panel.plugin.title");
|
|
751
|
+
$[1] = t;
|
|
752
|
+
$[2] = t1;
|
|
753
|
+
} else t1 = $[2];
|
|
754
|
+
let t2;
|
|
755
|
+
if ($[3] !== productId) {
|
|
756
|
+
t2 = (t3) => {
|
|
757
|
+
const { id } = t3;
|
|
758
|
+
return id === productId;
|
|
759
|
+
};
|
|
760
|
+
$[3] = productId;
|
|
761
|
+
$[4] = t2;
|
|
762
|
+
} else t2 = $[4];
|
|
763
|
+
const t4 = plugins.filter(t2).map((t3) => {
|
|
764
|
+
const { id: id_0, killSwitch } = t3;
|
|
765
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Toggle, {
|
|
766
|
+
checked: switched[id_0] !== false,
|
|
767
|
+
label: t("standalone.panel.plugin.switch"),
|
|
768
|
+
onCheckedChange: (on) => {
|
|
769
|
+
switches.set(id_0, on);
|
|
770
|
+
}
|
|
771
|
+
}), /* @__PURE__ */ jsx(Toggle, {
|
|
772
|
+
checked: flags.read(killSwitch) !== false,
|
|
773
|
+
label: t("standalone.panel.plugin.kill"),
|
|
774
|
+
onCheckedChange: (on_0) => {
|
|
775
|
+
flags.override(killSwitch, on_0);
|
|
776
|
+
}
|
|
777
|
+
})] }, id_0);
|
|
778
|
+
});
|
|
779
|
+
let t5;
|
|
780
|
+
if ($[5] !== T0 || $[6] !== t1 || $[7] !== t4) {
|
|
781
|
+
t5 = /* @__PURE__ */ jsx(T0, {
|
|
782
|
+
title: t1,
|
|
783
|
+
children: t4
|
|
784
|
+
});
|
|
785
|
+
$[5] = T0;
|
|
786
|
+
$[6] = t1;
|
|
787
|
+
$[7] = t4;
|
|
788
|
+
$[8] = t5;
|
|
789
|
+
} else t5 = $[8];
|
|
790
|
+
return t5;
|
|
791
|
+
}
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region src/standalone/session-controls.tsx
|
|
794
|
+
/**
|
|
795
|
+
* Renders the development panel's session controls: whether somebody is signed in, and each
|
|
796
|
+
* permission and entitlement the session has.
|
|
797
|
+
*/
|
|
798
|
+
/**
|
|
799
|
+
* Returns the session with one id added to one of its lists, or taken out of it.
|
|
800
|
+
*/
|
|
801
|
+
function grantedIn(session, list, id, on) {
|
|
802
|
+
const others = session[list].filter((one) => one !== id);
|
|
803
|
+
return {
|
|
804
|
+
...session,
|
|
805
|
+
[list]: on ? [...others, id] : others
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Renders a switch for signing in, then one per declared permission and entitlement, each named by
|
|
810
|
+
* its qualified id.
|
|
811
|
+
*
|
|
812
|
+
* @remarks
|
|
813
|
+
* Each switch replaces the session, so every condition, menu and decision on the page follows at
|
|
814
|
+
* once.
|
|
815
|
+
* @returns The group.
|
|
816
|
+
*/
|
|
817
|
+
function SessionControls() {
|
|
818
|
+
const $ = c(20);
|
|
819
|
+
const { session } = useStandalone();
|
|
820
|
+
const { t } = useTranslation("host");
|
|
821
|
+
const { entitlements, permissions } = useResolvedProduct();
|
|
822
|
+
const current = useSyncExternalStore(session.subscribe, session.read, session.read);
|
|
823
|
+
let t0;
|
|
824
|
+
if ($[0] !== t) {
|
|
825
|
+
t0 = t("standalone.panel.session.title");
|
|
826
|
+
$[0] = t;
|
|
827
|
+
$[1] = t0;
|
|
828
|
+
} else t0 = $[1];
|
|
829
|
+
const t1 = current.authenticated;
|
|
830
|
+
let t2;
|
|
831
|
+
if ($[2] !== t) {
|
|
832
|
+
t2 = t("standalone.panel.session.signedIn");
|
|
833
|
+
$[2] = t;
|
|
834
|
+
$[3] = t2;
|
|
835
|
+
} else t2 = $[3];
|
|
836
|
+
let t3;
|
|
837
|
+
if ($[4] !== current || $[5] !== session) {
|
|
838
|
+
t3 = (authenticated) => {
|
|
839
|
+
session.set({
|
|
840
|
+
...current,
|
|
841
|
+
authenticated
|
|
842
|
+
});
|
|
843
|
+
};
|
|
844
|
+
$[4] = current;
|
|
845
|
+
$[5] = session;
|
|
846
|
+
$[6] = t3;
|
|
847
|
+
} else t3 = $[6];
|
|
848
|
+
let t4;
|
|
849
|
+
if ($[7] !== current.authenticated || $[8] !== t2 || $[9] !== t3) {
|
|
850
|
+
t4 = /* @__PURE__ */ jsx(Toggle, {
|
|
851
|
+
checked: t1,
|
|
852
|
+
label: t2,
|
|
853
|
+
onCheckedChange: t3
|
|
854
|
+
});
|
|
855
|
+
$[7] = current.authenticated;
|
|
856
|
+
$[8] = t2;
|
|
857
|
+
$[9] = t3;
|
|
858
|
+
$[10] = t4;
|
|
859
|
+
} else t4 = $[10];
|
|
860
|
+
let t5;
|
|
861
|
+
if ($[11] !== current || $[12] !== entitlements || $[13] !== permissions || $[14] !== session) {
|
|
862
|
+
t5 = [...permissions.map(_temp$3), ...entitlements.map(_temp2$1)].map((t6) => {
|
|
863
|
+
const [list, id_1] = t6;
|
|
864
|
+
return /* @__PURE__ */ jsx(Toggle, {
|
|
865
|
+
checked: current[list].includes(id_1),
|
|
866
|
+
label: id_1,
|
|
867
|
+
onCheckedChange: (on) => {
|
|
868
|
+
session.set(grantedIn(current, list, id_1, on));
|
|
869
|
+
}
|
|
870
|
+
}, id_1);
|
|
871
|
+
});
|
|
872
|
+
$[11] = current;
|
|
873
|
+
$[12] = entitlements;
|
|
874
|
+
$[13] = permissions;
|
|
875
|
+
$[14] = session;
|
|
876
|
+
$[15] = t5;
|
|
877
|
+
} else t5 = $[15];
|
|
878
|
+
let t6;
|
|
879
|
+
if ($[16] !== t0 || $[17] !== t4 || $[18] !== t5) {
|
|
880
|
+
t6 = /* @__PURE__ */ jsxs(Group, {
|
|
881
|
+
title: t0,
|
|
882
|
+
children: [t4, t5]
|
|
883
|
+
});
|
|
884
|
+
$[16] = t0;
|
|
885
|
+
$[17] = t4;
|
|
886
|
+
$[18] = t5;
|
|
887
|
+
$[19] = t6;
|
|
888
|
+
} else t6 = $[19];
|
|
889
|
+
return t6;
|
|
890
|
+
}
|
|
891
|
+
function _temp2$1(t0) {
|
|
892
|
+
const { id: id_0 } = t0;
|
|
893
|
+
return ["entitlements", id_0];
|
|
894
|
+
}
|
|
895
|
+
function _temp$3(t0) {
|
|
896
|
+
const { id } = t0;
|
|
897
|
+
return ["permissions", id];
|
|
898
|
+
}
|
|
899
|
+
//#endregion
|
|
900
|
+
//#region src/standalone/shell-controls.tsx
|
|
901
|
+
/**
|
|
902
|
+
* Lists the color mode choices in the order the panel offers them, each with the key of its words.
|
|
903
|
+
*/
|
|
904
|
+
const MODES = [
|
|
905
|
+
{
|
|
906
|
+
key: "standalone.panel.shell.light",
|
|
907
|
+
value: "light"
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
key: "standalone.panel.shell.dark",
|
|
911
|
+
value: "dark"
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
key: "standalone.panel.shell.system",
|
|
915
|
+
value: "system"
|
|
916
|
+
}
|
|
917
|
+
];
|
|
918
|
+
/**
|
|
919
|
+
* Renders a picker of the page's locales and one of its themes, each where the page offers more
|
|
920
|
+
* than one, and a segment group of the color modes.
|
|
921
|
+
*
|
|
922
|
+
* @remarks
|
|
923
|
+
* Each control calls the shell's own setter, so the choice is remembered as a product's would be.
|
|
924
|
+
* A locale and a theme are named by their codes, as the page's configuration states them.
|
|
925
|
+
* @returns The group.
|
|
926
|
+
*/
|
|
927
|
+
function ShellControls() {
|
|
928
|
+
const $ = c(30);
|
|
929
|
+
const { glyphs } = useStandalone();
|
|
930
|
+
const { t } = useTranslation("host");
|
|
931
|
+
const { locale, locales, setLocale } = useLocale();
|
|
932
|
+
const { setTheme, theme, themes } = useThemeChoice();
|
|
933
|
+
const { choice, setColorMode } = useColorMode();
|
|
934
|
+
let t0;
|
|
935
|
+
if ($[0] !== t) {
|
|
936
|
+
t0 = t("standalone.panel.shell.title");
|
|
937
|
+
$[0] = t;
|
|
938
|
+
$[1] = t0;
|
|
939
|
+
} else t0 = $[1];
|
|
940
|
+
let t1;
|
|
941
|
+
if ($[2] !== glyphs || $[3] !== locale || $[4] !== locales || $[5] !== setLocale || $[6] !== t) {
|
|
942
|
+
t1 = locales.length > 1 ? /* @__PURE__ */ jsx(Picker, {
|
|
943
|
+
choices: locales.map(_temp$2),
|
|
944
|
+
indicator: glyphs.select?.indicator,
|
|
945
|
+
label: t("standalone.panel.shell.language"),
|
|
946
|
+
onValueChange: setLocale,
|
|
947
|
+
value: locale
|
|
948
|
+
}) : null;
|
|
949
|
+
$[2] = glyphs;
|
|
950
|
+
$[3] = locale;
|
|
951
|
+
$[4] = locales;
|
|
952
|
+
$[5] = setLocale;
|
|
953
|
+
$[6] = t;
|
|
954
|
+
$[7] = t1;
|
|
955
|
+
} else t1 = $[7];
|
|
956
|
+
let t2;
|
|
957
|
+
if ($[8] !== glyphs || $[9] !== setTheme || $[10] !== t || $[11] !== theme || $[12] !== themes) {
|
|
958
|
+
t2 = themes.length > 1 ? /* @__PURE__ */ jsx(Picker, {
|
|
959
|
+
choices: themes.map(_temp2),
|
|
960
|
+
indicator: glyphs.select?.indicator,
|
|
961
|
+
label: t("standalone.panel.shell.theme"),
|
|
962
|
+
onValueChange: setTheme,
|
|
963
|
+
value: theme
|
|
964
|
+
}) : null;
|
|
965
|
+
$[8] = glyphs;
|
|
966
|
+
$[9] = setTheme;
|
|
967
|
+
$[10] = t;
|
|
968
|
+
$[11] = theme;
|
|
969
|
+
$[12] = themes;
|
|
970
|
+
$[13] = t2;
|
|
971
|
+
} else t2 = $[13];
|
|
972
|
+
let t3;
|
|
973
|
+
if ($[14] !== t) {
|
|
974
|
+
t3 = t("standalone.panel.shell.colorMode");
|
|
975
|
+
$[14] = t;
|
|
976
|
+
$[15] = t3;
|
|
977
|
+
} else t3 = $[15];
|
|
978
|
+
let t4;
|
|
979
|
+
if ($[16] !== setColorMode) {
|
|
980
|
+
t4 = (t5) => {
|
|
981
|
+
const { value } = t5;
|
|
982
|
+
setColorMode(value);
|
|
983
|
+
};
|
|
984
|
+
$[16] = setColorMode;
|
|
985
|
+
$[17] = t4;
|
|
986
|
+
} else t4 = $[17];
|
|
987
|
+
let t5;
|
|
988
|
+
if ($[18] !== t) {
|
|
989
|
+
t5 = MODES.map((t6) => {
|
|
990
|
+
const { key, value: value_0 } = t6;
|
|
991
|
+
return /* @__PURE__ */ jsx(SegmentGroup.Item, {
|
|
992
|
+
value: value_0,
|
|
993
|
+
children: /* @__PURE__ */ jsx(SegmentGroup.ItemText, { children: t(key) })
|
|
994
|
+
}, value_0);
|
|
995
|
+
});
|
|
996
|
+
$[18] = t;
|
|
997
|
+
$[19] = t5;
|
|
998
|
+
} else t5 = $[19];
|
|
999
|
+
let t6;
|
|
1000
|
+
if ($[20] !== choice || $[21] !== t3 || $[22] !== t4 || $[23] !== t5) {
|
|
1001
|
+
t6 = /* @__PURE__ */ jsx(SegmentGroup.Root, {
|
|
1002
|
+
"aria-label": t3,
|
|
1003
|
+
onValueChange: t4,
|
|
1004
|
+
size: "sm",
|
|
1005
|
+
value: choice,
|
|
1006
|
+
children: t5
|
|
1007
|
+
});
|
|
1008
|
+
$[20] = choice;
|
|
1009
|
+
$[21] = t3;
|
|
1010
|
+
$[22] = t4;
|
|
1011
|
+
$[23] = t5;
|
|
1012
|
+
$[24] = t6;
|
|
1013
|
+
} else t6 = $[24];
|
|
1014
|
+
let t7;
|
|
1015
|
+
if ($[25] !== t0 || $[26] !== t1 || $[27] !== t2 || $[28] !== t6) {
|
|
1016
|
+
t7 = /* @__PURE__ */ jsxs(Group, {
|
|
1017
|
+
title: t0,
|
|
1018
|
+
children: [
|
|
1019
|
+
t1,
|
|
1020
|
+
t2,
|
|
1021
|
+
t6
|
|
1022
|
+
]
|
|
1023
|
+
});
|
|
1024
|
+
$[25] = t0;
|
|
1025
|
+
$[26] = t1;
|
|
1026
|
+
$[27] = t2;
|
|
1027
|
+
$[28] = t6;
|
|
1028
|
+
$[29] = t7;
|
|
1029
|
+
} else t7 = $[29];
|
|
1030
|
+
return t7;
|
|
1031
|
+
}
|
|
1032
|
+
function _temp2(one_0) {
|
|
1033
|
+
return {
|
|
1034
|
+
label: one_0,
|
|
1035
|
+
value: one_0
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
function _temp$2(one) {
|
|
1039
|
+
return {
|
|
1040
|
+
label: one,
|
|
1041
|
+
value: one
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
//#endregion
|
|
1045
|
+
//#region src/standalone/controls.tsx
|
|
1046
|
+
/**
|
|
1047
|
+
* Renders the page picker, then the session, the decisions, the flags, the plugin's switches, the
|
|
1048
|
+
* operations and the display.
|
|
1049
|
+
*
|
|
1050
|
+
* @returns The stack of groups.
|
|
1051
|
+
*/
|
|
1052
|
+
function PanelControls() {
|
|
1053
|
+
const $ = c(1);
|
|
1054
|
+
let t0;
|
|
1055
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1056
|
+
t0 = /* @__PURE__ */ jsxs(Stack, {
|
|
1057
|
+
gap: "lg",
|
|
1058
|
+
children: [
|
|
1059
|
+
/* @__PURE__ */ jsx(PageControls, {}),
|
|
1060
|
+
/* @__PURE__ */ jsx(SessionControls, {}),
|
|
1061
|
+
/* @__PURE__ */ jsx(AccessControls, {}),
|
|
1062
|
+
/* @__PURE__ */ jsx(FlagControls, {}),
|
|
1063
|
+
/* @__PURE__ */ jsx(PluginControls, {}),
|
|
1064
|
+
/* @__PURE__ */ jsx(DataControls, {}),
|
|
1065
|
+
/* @__PURE__ */ jsx(ShellControls, {})
|
|
1066
|
+
]
|
|
1067
|
+
});
|
|
1068
|
+
$[0] = t0;
|
|
1069
|
+
} else t0 = $[0];
|
|
1070
|
+
return t0;
|
|
1071
|
+
}
|
|
1072
|
+
//#endregion
|
|
1073
|
+
//#region src/standalone/panel.tsx
|
|
1074
|
+
/**
|
|
1075
|
+
* Renders the development panel: a floating window over the standalone page, open from the start,
|
|
1076
|
+
* with every control of the page.
|
|
1077
|
+
*/
|
|
1078
|
+
/**
|
|
1079
|
+
* The panel's width, in CSS pixels.
|
|
1080
|
+
*/
|
|
1081
|
+
const WIDTH = 352;
|
|
1082
|
+
/**
|
|
1083
|
+
* The panel's height where the window has room for it, in CSS pixels.
|
|
1084
|
+
*/
|
|
1085
|
+
const HEIGHT = 560;
|
|
1086
|
+
/**
|
|
1087
|
+
* The room between the panel and the window's edges, in CSS pixels.
|
|
1088
|
+
*/
|
|
1089
|
+
const GAP = 16;
|
|
1090
|
+
/**
|
|
1091
|
+
* Returns the panel's place at the window's bottom-end corner, no taller than the window allows.
|
|
1092
|
+
*/
|
|
1093
|
+
function placementOf(width, height) {
|
|
1094
|
+
const tall = Math.min(HEIGHT, height - 32);
|
|
1095
|
+
return {
|
|
1096
|
+
position: {
|
|
1097
|
+
x: Math.max(GAP, width - WIDTH - GAP),
|
|
1098
|
+
y: Math.max(GAP, height - tall - GAP)
|
|
1099
|
+
},
|
|
1100
|
+
size: {
|
|
1101
|
+
height: tall,
|
|
1102
|
+
width: WIDTH
|
|
1103
|
+
}
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Renders the panel, which a person drags, resizes and minimizes, and never closes.
|
|
1108
|
+
*
|
|
1109
|
+
* @remarks
|
|
1110
|
+
* The panel opens at the window's bottom-end corner and is open for the page's life, so it needs
|
|
1111
|
+
* no trigger on the page. It is not modal: the page under it takes the pointer and the keys. Its
|
|
1112
|
+
* stage triggers render where the page's glyphs give theirs.
|
|
1113
|
+
* @returns The panel's root.
|
|
1114
|
+
*/
|
|
1115
|
+
function StandalonePanel() {
|
|
1116
|
+
const $ = c(22);
|
|
1117
|
+
const { glyphs } = useStandalone();
|
|
1118
|
+
const { t } = useTranslation("host");
|
|
1119
|
+
const [t0] = useState(_temp$1);
|
|
1120
|
+
const { position, size } = t0;
|
|
1121
|
+
let t1;
|
|
1122
|
+
if ($[0] !== t) {
|
|
1123
|
+
t1 = t("standalone.panel.title");
|
|
1124
|
+
$[0] = t;
|
|
1125
|
+
$[1] = t1;
|
|
1126
|
+
} else t1 = $[1];
|
|
1127
|
+
let t2;
|
|
1128
|
+
if ($[2] !== t1) {
|
|
1129
|
+
t2 = /* @__PURE__ */ jsx(FloatingPanel.DragTrigger, { children: /* @__PURE__ */ jsx(FloatingPanel.Title, { children: t1 }) });
|
|
1130
|
+
$[2] = t1;
|
|
1131
|
+
$[3] = t2;
|
|
1132
|
+
} else t2 = $[3];
|
|
1133
|
+
let t3;
|
|
1134
|
+
if ($[4] !== glyphs.minimize) {
|
|
1135
|
+
t3 = glyphs.minimize === void 0 ? null : /* @__PURE__ */ jsx(FloatingPanel.StageTrigger, {
|
|
1136
|
+
stage: "minimized",
|
|
1137
|
+
children: glyphs.minimize
|
|
1138
|
+
});
|
|
1139
|
+
$[4] = glyphs.minimize;
|
|
1140
|
+
$[5] = t3;
|
|
1141
|
+
} else t3 = $[5];
|
|
1142
|
+
let t4;
|
|
1143
|
+
if ($[6] !== glyphs.restore) {
|
|
1144
|
+
t4 = glyphs.restore === void 0 ? null : /* @__PURE__ */ jsx(FloatingPanel.StageTrigger, {
|
|
1145
|
+
stage: "default",
|
|
1146
|
+
children: glyphs.restore
|
|
1147
|
+
});
|
|
1148
|
+
$[6] = glyphs.restore;
|
|
1149
|
+
$[7] = t4;
|
|
1150
|
+
} else t4 = $[7];
|
|
1151
|
+
let t5;
|
|
1152
|
+
if ($[8] !== t3 || $[9] !== t4) {
|
|
1153
|
+
t5 = /* @__PURE__ */ jsxs(FloatingPanel.Control, { children: [t3, t4] });
|
|
1154
|
+
$[8] = t3;
|
|
1155
|
+
$[9] = t4;
|
|
1156
|
+
$[10] = t5;
|
|
1157
|
+
} else t5 = $[10];
|
|
1158
|
+
let t6;
|
|
1159
|
+
if ($[11] !== t2 || $[12] !== t5) {
|
|
1160
|
+
t6 = /* @__PURE__ */ jsxs(FloatingPanel.Header, { children: [t2, t5] });
|
|
1161
|
+
$[11] = t2;
|
|
1162
|
+
$[12] = t5;
|
|
1163
|
+
$[13] = t6;
|
|
1164
|
+
} else t6 = $[13];
|
|
1165
|
+
let t7;
|
|
1166
|
+
let t8;
|
|
1167
|
+
if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1168
|
+
t7 = /* @__PURE__ */ jsx(FloatingPanel.Body, { children: /* @__PURE__ */ jsx(PanelControls, {}) });
|
|
1169
|
+
t8 = /* @__PURE__ */ jsx(FloatingPanel.ResizeTriggers, {});
|
|
1170
|
+
$[14] = t7;
|
|
1171
|
+
$[15] = t8;
|
|
1172
|
+
} else {
|
|
1173
|
+
t7 = $[14];
|
|
1174
|
+
t8 = $[15];
|
|
1175
|
+
}
|
|
1176
|
+
let t9;
|
|
1177
|
+
if ($[16] !== t6) {
|
|
1178
|
+
t9 = /* @__PURE__ */ jsx(FloatingPanel.Positioner, { children: /* @__PURE__ */ jsxs(FloatingPanel.Content, { children: [
|
|
1179
|
+
t6,
|
|
1180
|
+
t7,
|
|
1181
|
+
t8
|
|
1182
|
+
] }) });
|
|
1183
|
+
$[16] = t6;
|
|
1184
|
+
$[17] = t9;
|
|
1185
|
+
} else t9 = $[17];
|
|
1186
|
+
let t10;
|
|
1187
|
+
if ($[18] !== position || $[19] !== size || $[20] !== t9) {
|
|
1188
|
+
t10 = /* @__PURE__ */ jsx(FloatingPanel.Root, {
|
|
1189
|
+
defaultPosition: position,
|
|
1190
|
+
defaultSize: size,
|
|
1191
|
+
open: true,
|
|
1192
|
+
children: t9
|
|
1193
|
+
});
|
|
1194
|
+
$[18] = position;
|
|
1195
|
+
$[19] = size;
|
|
1196
|
+
$[20] = t9;
|
|
1197
|
+
$[21] = t10;
|
|
1198
|
+
} else t10 = $[21];
|
|
1199
|
+
return t10;
|
|
1200
|
+
}
|
|
1201
|
+
function _temp$1() {
|
|
1202
|
+
return placementOf(window.innerWidth, window.innerHeight);
|
|
1203
|
+
}
|
|
1204
|
+
//#endregion
|
|
1205
|
+
//#region src/standalone/frame.tsx
|
|
1206
|
+
/**
|
|
1207
|
+
* Renders the shell with a bar, a column and a band for each region a contribution fills, the page
|
|
1208
|
+
* in the main region, and the panel through `Into`.
|
|
1209
|
+
*
|
|
1210
|
+
* @remarks
|
|
1211
|
+
* A region nobody fills renders no part of the shell, so an empty aside takes no column, as a
|
|
1212
|
+
* product's frame leaves it out.
|
|
1213
|
+
* @returns The host's root around the shell.
|
|
1214
|
+
*/
|
|
1215
|
+
function StandaloneFrame() {
|
|
1216
|
+
const $ = c(22);
|
|
1217
|
+
const { slots } = hostContract;
|
|
1218
|
+
const header = [
|
|
1219
|
+
useSlot(slots.brand),
|
|
1220
|
+
useSlot(slots.header),
|
|
1221
|
+
useSlot(slots.userMenu)
|
|
1222
|
+
].some(_temp);
|
|
1223
|
+
const navigation = useSlot(slots.navigation).filled;
|
|
1224
|
+
const aside = useSlot(slots.aside).filled;
|
|
1225
|
+
const footer = useSlot(slots.footer).filled;
|
|
1226
|
+
const status = useSlot(slots.status).filled;
|
|
1227
|
+
let t0;
|
|
1228
|
+
if ($[0] !== header) {
|
|
1229
|
+
t0 = header ? /* @__PURE__ */ jsxs(AppShell.Header, { children: [
|
|
1230
|
+
/* @__PURE__ */ jsx(Slot, { slot: slots.brand }),
|
|
1231
|
+
/* @__PURE__ */ jsx(Slot, { slot: slots.header }),
|
|
1232
|
+
/* @__PURE__ */ jsx(Slot, { slot: slots.userMenu })
|
|
1233
|
+
] }) : null;
|
|
1234
|
+
$[0] = header;
|
|
1235
|
+
$[1] = t0;
|
|
1236
|
+
} else t0 = $[1];
|
|
1237
|
+
let t1;
|
|
1238
|
+
if ($[2] !== navigation) {
|
|
1239
|
+
t1 = navigation ? /* @__PURE__ */ jsx(AppShell.Navbar, { children: /* @__PURE__ */ jsx(Slot, { slot: slots.navigation }) }) : null;
|
|
1240
|
+
$[2] = navigation;
|
|
1241
|
+
$[3] = t1;
|
|
1242
|
+
} else t1 = $[3];
|
|
1243
|
+
let t2;
|
|
1244
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1245
|
+
t2 = /* @__PURE__ */ jsx(AppShell.Main, { children: /* @__PURE__ */ jsx(HostContent, {}) });
|
|
1246
|
+
$[4] = t2;
|
|
1247
|
+
} else t2 = $[4];
|
|
1248
|
+
let t3;
|
|
1249
|
+
if ($[5] !== aside) {
|
|
1250
|
+
t3 = aside ? /* @__PURE__ */ jsx(AppShell.Aside, { children: /* @__PURE__ */ jsx(Slot, { slot: slots.aside }) }) : null;
|
|
1251
|
+
$[5] = aside;
|
|
1252
|
+
$[6] = t3;
|
|
1253
|
+
} else t3 = $[6];
|
|
1254
|
+
let t4;
|
|
1255
|
+
if ($[7] !== t1 || $[8] !== t3) {
|
|
1256
|
+
t4 = /* @__PURE__ */ jsxs(AppShell.Body, { children: [
|
|
1257
|
+
t1,
|
|
1258
|
+
t2,
|
|
1259
|
+
t3
|
|
1260
|
+
] });
|
|
1261
|
+
$[7] = t1;
|
|
1262
|
+
$[8] = t3;
|
|
1263
|
+
$[9] = t4;
|
|
1264
|
+
} else t4 = $[9];
|
|
1265
|
+
let t5;
|
|
1266
|
+
if ($[10] !== footer) {
|
|
1267
|
+
t5 = footer ? /* @__PURE__ */ jsx(AppShell.Footer, { children: /* @__PURE__ */ jsx(Slot, { slot: slots.footer }) }) : null;
|
|
1268
|
+
$[10] = footer;
|
|
1269
|
+
$[11] = t5;
|
|
1270
|
+
} else t5 = $[11];
|
|
1271
|
+
let t6;
|
|
1272
|
+
if ($[12] !== status) {
|
|
1273
|
+
t6 = status ? /* @__PURE__ */ jsx(AppShell.Status, { children: /* @__PURE__ */ jsx(Slot, { slot: slots.status }) }) : null;
|
|
1274
|
+
$[12] = status;
|
|
1275
|
+
$[13] = t6;
|
|
1276
|
+
} else t6 = $[13];
|
|
1277
|
+
let t7;
|
|
1278
|
+
if ($[14] !== t0 || $[15] !== t4 || $[16] !== t5 || $[17] !== t6) {
|
|
1279
|
+
t7 = /* @__PURE__ */ jsxs(AppShell.Root, { children: [
|
|
1280
|
+
t0,
|
|
1281
|
+
t4,
|
|
1282
|
+
t5,
|
|
1283
|
+
t6
|
|
1284
|
+
] });
|
|
1285
|
+
$[14] = t0;
|
|
1286
|
+
$[15] = t4;
|
|
1287
|
+
$[16] = t5;
|
|
1288
|
+
$[17] = t6;
|
|
1289
|
+
$[18] = t7;
|
|
1290
|
+
} else t7 = $[18];
|
|
1291
|
+
let t8;
|
|
1292
|
+
if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
|
|
1293
|
+
t8 = /* @__PURE__ */ jsx(Into, {
|
|
1294
|
+
slot: slots.overlay,
|
|
1295
|
+
children: /* @__PURE__ */ jsx(StandalonePanel, {})
|
|
1296
|
+
});
|
|
1297
|
+
$[19] = t8;
|
|
1298
|
+
} else t8 = $[19];
|
|
1299
|
+
let t9;
|
|
1300
|
+
if ($[20] !== t7) {
|
|
1301
|
+
t9 = /* @__PURE__ */ jsxs(HostRoot, { children: [t7, t8] });
|
|
1302
|
+
$[20] = t7;
|
|
1303
|
+
$[21] = t9;
|
|
1304
|
+
} else t9 = $[21];
|
|
1305
|
+
return t9;
|
|
1306
|
+
}
|
|
1307
|
+
function _temp(t0) {
|
|
1308
|
+
const { filled } = t0;
|
|
1309
|
+
return filled;
|
|
1310
|
+
}
|
|
1311
|
+
//#endregion
|
|
1312
|
+
//#region src/standalone/start.ts
|
|
1313
|
+
/**
|
|
1314
|
+
* Reads what the standalone page starts from: the address it opens at, and the flags the panel
|
|
1315
|
+
* offers.
|
|
1316
|
+
*/
|
|
1317
|
+
/**
|
|
1318
|
+
* Returns the address the standalone page opens at: the plugin's first menu entry, else its first
|
|
1319
|
+
* route that a sample or an empty path fills. Undefined where the plugin has neither.
|
|
1320
|
+
*
|
|
1321
|
+
* @param product - The standalone product, whose id is the plugin's.
|
|
1322
|
+
* @param routes - The router's map.
|
|
1323
|
+
*/
|
|
1324
|
+
function startOf(product, routes) {
|
|
1325
|
+
const filled = product.routes.filter(({ plugin }) => plugin === product.productId).filter(({ path, sample }) => sample !== void 0 || !path.includes("$"));
|
|
1326
|
+
const [start] = [...filled.filter(({ navigation }) => navigation !== void 0), ...filled];
|
|
1327
|
+
return start === void 0 ? void 0 : routeHref(routes, { id: start.id }, start.sample);
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Returns every flag the installed plugins' contracts declare, in install order, with the variants
|
|
1331
|
+
* of each experiment.
|
|
1332
|
+
*/
|
|
1333
|
+
function flagsOf(product) {
|
|
1334
|
+
return Object.values(product.manifests).flatMap(({ contract }) => Object.values(contract.featureFlags).map(({ id, variants }) => ({
|
|
1335
|
+
id,
|
|
1336
|
+
variants: variants?.map(String)
|
|
1337
|
+
})));
|
|
1338
|
+
}
|
|
1339
|
+
//#endregion
|
|
1340
|
+
//#region src/standalone/router.ts
|
|
1341
|
+
/**
|
|
1342
|
+
* Builds the standalone page's router: the host's routes under a root that renders the standalone
|
|
1343
|
+
* frame, opened at the plugin's start.
|
|
1344
|
+
*/
|
|
1345
|
+
/**
|
|
1346
|
+
* Returns the standalone page's router over the browser's address.
|
|
1347
|
+
*
|
|
1348
|
+
* @remarks
|
|
1349
|
+
* A page opened at `/` replaces its address with the plugin's start, so the back button does not
|
|
1350
|
+
* return to an empty page. The start is read once the router has given every route its path.
|
|
1351
|
+
* @param host - The host the router's context contains.
|
|
1352
|
+
* @param product - The standalone product, whose routes the host compiles.
|
|
1353
|
+
*/
|
|
1354
|
+
function standaloneRouter(host, product) {
|
|
1355
|
+
const root = createAppRootRoute()({
|
|
1356
|
+
component: StandaloneFrame,
|
|
1357
|
+
notFoundComponent: HostNotFound
|
|
1358
|
+
});
|
|
1359
|
+
const tree = root.addChildren([...createHostRoutes(product)(root)]);
|
|
1360
|
+
const routes = routeMap(tree);
|
|
1361
|
+
const router = createRouter({
|
|
1362
|
+
...routerOptions({
|
|
1363
|
+
data: host.data,
|
|
1364
|
+
host,
|
|
1365
|
+
routes
|
|
1366
|
+
}),
|
|
1367
|
+
routeTree: tree
|
|
1368
|
+
});
|
|
1369
|
+
const start = startOf(product, routes);
|
|
1370
|
+
if (start !== void 0 && router.history.location.pathname === "/") router.history.replace(start);
|
|
1371
|
+
return {
|
|
1372
|
+
router,
|
|
1373
|
+
routes
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
//#endregion
|
|
1377
|
+
//#region src/standalone/app.tsx
|
|
1378
|
+
/**
|
|
1379
|
+
* Starts the standalone page of a plugin: the plugin under a real host, the plugins beside it from
|
|
1380
|
+
* their contracts alone, and the development panel over the page.
|
|
1381
|
+
*
|
|
1382
|
+
* @remarks
|
|
1383
|
+
* The standalone layer of `vite-config-product` serves a page whose entry calls
|
|
1384
|
+
* `renderStandalone` with `virtual:product` and `virtual:i18n`. The module renders React, so it
|
|
1385
|
+
* is an entry of its own, apart from `./standalone`, which the build evaluates in Node.
|
|
1386
|
+
*/
|
|
1387
|
+
/**
|
|
1388
|
+
* Renders the standalone page once the host is ready.
|
|
1389
|
+
*
|
|
1390
|
+
* @param options - The product, the catalogues, the glyphs, the locales, the themes and the
|
|
1391
|
+
* element.
|
|
1392
|
+
* @returns The React root the page renders in, which `unmount` takes down.
|
|
1393
|
+
* @throws {@link Error} Where no element is given and the document has none with the id `root`.
|
|
1394
|
+
*/
|
|
1395
|
+
async function renderStandalone({ catalogues, element = document.querySelector("#root"), glyphs = {}, locales, product, themes }) {
|
|
1396
|
+
if (element === null) throw new Error("The standalone page renders into the element with the id root, and the document has none.");
|
|
1397
|
+
const { host, modes, sources } = standaloneHosted(product, glyphs);
|
|
1398
|
+
const { router, routes } = standaloneRouter(host, product);
|
|
1399
|
+
const state = {
|
|
1400
|
+
access: sources.access,
|
|
1401
|
+
flags: flagsOf(product),
|
|
1402
|
+
glyphs,
|
|
1403
|
+
modes,
|
|
1404
|
+
routes,
|
|
1405
|
+
session: sources.session
|
|
1406
|
+
};
|
|
1407
|
+
await host.ready();
|
|
1408
|
+
const root = createRoot(element);
|
|
1409
|
+
root.render(/* @__PURE__ */ jsx(StandaloneContext, {
|
|
1410
|
+
value: state,
|
|
1411
|
+
children: /* @__PURE__ */ jsx(Shell, {
|
|
1412
|
+
app: product.productId,
|
|
1413
|
+
catalogues,
|
|
1414
|
+
locales,
|
|
1415
|
+
themes,
|
|
1416
|
+
children: /* @__PURE__ */ jsx(HostProvider, {
|
|
1417
|
+
host,
|
|
1418
|
+
router,
|
|
1419
|
+
children: /* @__PURE__ */ jsx(RouterProvider, { router })
|
|
1420
|
+
})
|
|
1421
|
+
})
|
|
1422
|
+
}));
|
|
1423
|
+
return root;
|
|
1424
|
+
}
|
|
1425
|
+
//#endregion
|
|
1426
|
+
export { renderStandalone };
|