@antelopejs/dms-frontend 0.9.2 → 0.9.3
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/README.md +1 -1
- package/dist/config.js +3 -0
- package/package.json +1 -1
- package/templates/vue/app-runtime.ts +88 -7
- package/templates/vue/globals.d.ts +5 -0
- package/templates/vue/icon-bundle.ts +31 -0
- package/templates/vue/message-subset.ts +65 -0
- package/templates/vue/network-error.ts +4 -0
- package/templates/vue/ssr-renderer.ts +10 -1
- package/templates/vue/ui-lazy-icons.mjs +44 -0
- package/templates/vue/vite.config.ts +2 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/@antelopejs/dms-frontend"><img alt="npm" src="https://img.shields.io/npm/v/@antelopejs/dms-frontend?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
11
11
|
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/@antelopejs/dms-frontend?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
12
|
-
<a href="https://discord.gg/
|
|
12
|
+
<a href="https://discord.gg/g4pFt6eXqu"><img alt="Discord" src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"></a>
|
|
13
13
|
<a href="https://dms.antelopejs.com/docs/frontend"><img alt="Documentation" src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000"></a>
|
|
14
14
|
|
|
15
15
|
**The frontend of the AntelopeJS DMS: the `ajs dms` CLI, the Vue renderer and the frontend-module SDK.**
|
package/dist/config.js
CHANGED
|
@@ -50,6 +50,7 @@ exports.TEMPLATE_FILES = [
|
|
|
50
50
|
["index.html", "index.html"],
|
|
51
51
|
["main.ts", "main.ts"],
|
|
52
52
|
["app-runtime.ts", "app-runtime.ts"],
|
|
53
|
+
["message-subset.ts", "message-subset.ts"],
|
|
53
54
|
["network-error.ts", "network-error.ts"],
|
|
54
55
|
["ui-app-config.ts", "ui-app-config.ts"],
|
|
55
56
|
["layer-app-config.ts", "layer-app-config.ts"],
|
|
@@ -60,6 +61,7 @@ exports.TEMPLATE_FILES = [
|
|
|
60
61
|
["frontend-build-loader.ts", "frontend-build-loader.ts"],
|
|
61
62
|
["server-module.ts", "server-module.ts"],
|
|
62
63
|
["icon-hydration.ts", "icon-hydration.ts"],
|
|
64
|
+
["icon-bundle.ts", "icon-bundle.ts"],
|
|
63
65
|
["globals.d.ts", "globals.d.ts"],
|
|
64
66
|
["compress-assets.mjs", "compress-assets.mjs"],
|
|
65
67
|
["head-order.mjs", "head-order.mjs"],
|
|
@@ -72,6 +74,7 @@ exports.TEMPLATE_FILES = [
|
|
|
72
74
|
["icon-api.mjs", "icon-api.mjs"],
|
|
73
75
|
["icon-scan.mjs", "icon-scan.mjs"],
|
|
74
76
|
["ui-kbd.mjs", "ui-kbd.mjs"],
|
|
77
|
+
["ui-lazy-icons.mjs", "ui-lazy-icons.mjs"],
|
|
75
78
|
["email-renderer.ts", "email-renderer.ts"],
|
|
76
79
|
["email-runtime.ts", "email-runtime.ts"],
|
|
77
80
|
["email-locales.ts", "email-locales.ts"],
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { useToast } from "@nuxt/ui/composables/useToast";
|
|
|
4
4
|
import { useAppConfig } from "@nuxt/ui/runtime/vue/composables/useAppConfig";
|
|
5
5
|
import { en as uiEn, fr as uiFr } from "@nuxt/ui/locale";
|
|
6
6
|
import ui from "@nuxt/ui/vue-plugin";
|
|
7
|
+
import { router } from "@inertiajs/vue3";
|
|
7
8
|
import { useHead } from "@unhead/vue";
|
|
8
9
|
import type { VueHeadClient } from "@unhead/vue/types";
|
|
9
10
|
import type { IconifyIcon } from "@iconify/vue";
|
|
@@ -64,7 +65,13 @@ import {
|
|
|
64
65
|
supportedLocales,
|
|
65
66
|
syncLocaleMessages,
|
|
66
67
|
} from "./locales.generated";
|
|
67
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
type DmsMessageSubset,
|
|
70
|
+
SSR_MESSAGES_ID,
|
|
71
|
+
recordMessageReads,
|
|
72
|
+
} from "./message-subset";
|
|
73
|
+
import { NETWORK_ERROR_KEYS, showNetworkErrors } from "./network-error";
|
|
74
|
+
import { loadIconBundle } from "./icon-bundle";
|
|
68
75
|
import { createUiAppConfigMerger } from "./ui-app-config";
|
|
69
76
|
|
|
70
77
|
export interface DmsInertiaSetupProps {
|
|
@@ -86,8 +93,16 @@ export interface DmsAppOptions {
|
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
export interface DmsConfiguredApp {
|
|
89
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* The locale of the catalog the app shows its messages from now, none when
|
|
98
|
+
* the page is served the messages it read alone.
|
|
99
|
+
*/
|
|
90
100
|
catalogLocale: () => string | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* On the server, for a page of a visitor who is not signed in: the messages
|
|
103
|
+
* the render read, which the page carries instead of the whole catalog.
|
|
104
|
+
*/
|
|
105
|
+
messageSubset: () => DmsMessageSubset | undefined;
|
|
91
106
|
mounted: () => Promise<void>;
|
|
92
107
|
runtime: ReturnType<typeof createDmsFrontendRuntime>;
|
|
93
108
|
}
|
|
@@ -238,8 +253,18 @@ const DmsPersistentInertiaPage = Object.assign(DmsInertiaPage, {
|
|
|
238
253
|
layout: DmsPersistentLayout,
|
|
239
254
|
});
|
|
240
255
|
|
|
241
|
-
|
|
242
|
-
|
|
256
|
+
/**
|
|
257
|
+
* What a visit waits for before it shows its page, set when the first one
|
|
258
|
+
* starts from a page that began without what the pages after it read: a
|
|
259
|
+
* subset of the catalog, the icon bundle. Inertia also resolves the first page
|
|
260
|
+
* once the app is set up, which must not wait for it.
|
|
261
|
+
*/
|
|
262
|
+
let completeInitialAssets: (() => Promise<void>) | undefined;
|
|
263
|
+
|
|
264
|
+
export function resolveDmsInertiaPage(): Component | Promise<Component> {
|
|
265
|
+
return completeInitialAssets
|
|
266
|
+
? completeInitialAssets().then(() => DmsPersistentInertiaPage)
|
|
267
|
+
: DmsPersistentInertiaPage;
|
|
243
268
|
}
|
|
244
269
|
|
|
245
270
|
function renderDmsPage(
|
|
@@ -310,13 +335,66 @@ export async function configureDmsApp(
|
|
|
310
335
|
userLocale(options.initialPageProps.user) ??
|
|
311
336
|
readDmsLocaleCookie(runtime, supportedLocales) ??
|
|
312
337
|
DEFAULT_LOCALE;
|
|
313
|
-
const
|
|
338
|
+
const anonymous = !options.initialPageProps.user;
|
|
339
|
+
const subset = anonymous
|
|
340
|
+
? readServerRendered<DmsMessageSubset | undefined>(
|
|
341
|
+
SSR_MESSAGES_ID,
|
|
342
|
+
undefined,
|
|
343
|
+
)
|
|
344
|
+
: undefined;
|
|
345
|
+
const started = subset?.locale === locale ? subset : undefined;
|
|
346
|
+
const messages = started?.messages ?? (await loadLocaleMessages(locale));
|
|
347
|
+
const recorder =
|
|
348
|
+
anonymous && typeof window === "undefined"
|
|
349
|
+
? recordMessageReads(messages)
|
|
350
|
+
: undefined;
|
|
351
|
+
let loading: Promise<void> | undefined;
|
|
314
352
|
const i18n = createI18n({
|
|
315
353
|
legacy: false,
|
|
316
354
|
locale,
|
|
317
355
|
fallbackLocale: DEFAULT_LOCALE,
|
|
318
|
-
messages:
|
|
356
|
+
messages: started
|
|
357
|
+
? { [locale]: messages }
|
|
358
|
+
: { ...localeMessages, [locale]: recorder?.messages ?? messages },
|
|
359
|
+
...(started && {
|
|
360
|
+
missing: (_locale: string, key: string) => {
|
|
361
|
+
if (i18n.global.locale.value !== locale) return key;
|
|
362
|
+
void loadCompleteCatalog();
|
|
363
|
+
return "";
|
|
364
|
+
},
|
|
365
|
+
}),
|
|
319
366
|
});
|
|
367
|
+
function loadCompleteCatalog(): Promise<void> {
|
|
368
|
+
if (i18n.global.locale.value !== locale) return Promise.resolve();
|
|
369
|
+
loading ??= loadLocaleMessages(locale).then(
|
|
370
|
+
(complete) => {
|
|
371
|
+
i18n.global.setLocaleMessage(locale, complete);
|
|
372
|
+
i18n.global.setMissingHandler(null);
|
|
373
|
+
},
|
|
374
|
+
() => {
|
|
375
|
+
loading = undefined;
|
|
376
|
+
},
|
|
377
|
+
);
|
|
378
|
+
return loading;
|
|
379
|
+
}
|
|
380
|
+
if (anonymous && typeof window !== "undefined") {
|
|
381
|
+
const complete = async (): Promise<void> => {
|
|
382
|
+
await Promise.all([
|
|
383
|
+
started ? loadCompleteCatalog() : undefined,
|
|
384
|
+
loadIconBundle(),
|
|
385
|
+
]);
|
|
386
|
+
};
|
|
387
|
+
router.on("before", () => {
|
|
388
|
+
completeInitialAssets = complete;
|
|
389
|
+
void complete();
|
|
390
|
+
});
|
|
391
|
+
for (const type of ["pointerdown", "keydown", "focusin", "touchstart"])
|
|
392
|
+
addEventListener(type, () => void loadIconBundle(), {
|
|
393
|
+
once: true,
|
|
394
|
+
capture: true,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
if (recorder) for (const key of NETWORK_ERROR_KEYS) i18n.global.te(key);
|
|
320
398
|
// A translation changed in a layer during development reaches the page
|
|
321
399
|
// without a reload. A server render imports the new catalogs instead.
|
|
322
400
|
if (typeof window !== "undefined") syncLocaleMessages(i18n.global);
|
|
@@ -339,6 +417,7 @@ export async function configureDmsApp(
|
|
|
339
417
|
// rendered: the page, its layout, and the components the render reached.
|
|
340
418
|
// Hydration then adopts the server-rendered markup instead of discarding it.
|
|
341
419
|
await Promise.all([
|
|
420
|
+
anonymous ? undefined : loadIconBundle(),
|
|
342
421
|
preloadDmsPage(options.initialPageProps),
|
|
343
422
|
resolveDmsAsyncComponents(
|
|
344
423
|
readServerRendered<string[]>(SSR_ASYNC_COMPONENTS_ID, []),
|
|
@@ -352,7 +431,9 @@ export async function configureDmsApp(
|
|
|
352
431
|
supportedLocales,
|
|
353
432
|
);
|
|
354
433
|
return {
|
|
355
|
-
catalogLocale: () =>
|
|
434
|
+
catalogLocale: () =>
|
|
435
|
+
recorder ? undefined : catalogLocale(i18n.global.locale.value),
|
|
436
|
+
messageSubset: () => recorder && { locale, messages: recorder.subset() },
|
|
356
437
|
mounted,
|
|
357
438
|
runtime,
|
|
358
439
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { addIcon, type IconifyIcon } from "@iconify/vue";
|
|
2
|
+
|
|
3
|
+
function register(name: string, data: IconifyIcon): boolean {
|
|
4
|
+
const colon = name.indexOf(":");
|
|
5
|
+
if (colon !== -1 && name.slice(0, colon).includes("-")) {
|
|
6
|
+
addIcon(name.replace(":", "-"), data);
|
|
7
|
+
}
|
|
8
|
+
return addIcon(name, data);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let loading: Promise<void> | undefined;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Loads the icons Nuxt UI bundles for the client, once: every icon the
|
|
15
|
+
* application's sources name. A server render has them from the start (Nuxt
|
|
16
|
+
* UI's own plugin, left in place by `ui-lazy-icons.mjs`), so there is nothing
|
|
17
|
+
* to load.
|
|
18
|
+
*
|
|
19
|
+
* A failed load is forgotten and resolves: an icon the bundle would have
|
|
20
|
+
* held is then fetched from the icon API, as one outside the bundle always is.
|
|
21
|
+
*/
|
|
22
|
+
export function loadIconBundle(): Promise<void> {
|
|
23
|
+
if (import.meta.env.SSR) return Promise.resolve();
|
|
24
|
+
loading ??= import("virtual:nuxt-ui-icons").then(
|
|
25
|
+
({ init }) => init(register),
|
|
26
|
+
() => {
|
|
27
|
+
loading = undefined;
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
return loading;
|
|
31
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** The `<script>` the server render leaves in the document for {@link DmsMessageSubset}. */
|
|
2
|
+
export const SSR_MESSAGES_ID = "dms-ssr-messages";
|
|
3
|
+
|
|
4
|
+
type Messages = Record<string, unknown>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The messages a server render read from a locale's catalog, as a catalog of
|
|
8
|
+
* their own, with the locale they belong to.
|
|
9
|
+
*/
|
|
10
|
+
export interface DmsMessageSubset {
|
|
11
|
+
locale: string;
|
|
12
|
+
messages: Messages;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface MessageReadRecorder {
|
|
16
|
+
/** The catalog to give the render: every read through it is recorded. */
|
|
17
|
+
messages: Messages;
|
|
18
|
+
/** What the render read so far. */
|
|
19
|
+
subset: () => Messages;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isTraversable(value: unknown): value is object {
|
|
23
|
+
return typeof value === "object" && value !== null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isMessages(value: unknown): value is Messages {
|
|
27
|
+
return isTraversable(value);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type Slot = () => Messages;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Wraps a catalog so that the messages read through it are collected, with
|
|
34
|
+
* the path they sit at, into a catalog of their own.
|
|
35
|
+
*
|
|
36
|
+
* A message is recorded when a string is read from the catalog, whether by a
|
|
37
|
+
* lookup (`t`), an existence check (`te`) or a walk over a subtree (`tm`).
|
|
38
|
+
*/
|
|
39
|
+
export function recordMessageReads(messages: Messages): MessageReadRecorder {
|
|
40
|
+
const used: Messages = {};
|
|
41
|
+
const place = (source: object, parent: Slot, key: string): Slot => {
|
|
42
|
+
return () => {
|
|
43
|
+
const holder = parent();
|
|
44
|
+
const existing = holder[key];
|
|
45
|
+
if (isMessages(existing)) return existing;
|
|
46
|
+
const container: Messages = Array.isArray(source) ? [] : {};
|
|
47
|
+
holder[key] = container;
|
|
48
|
+
return container;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const wrap = <T extends object>(source: T, slot: Slot): T =>
|
|
52
|
+
new Proxy(source, {
|
|
53
|
+
get(target, key, receiver) {
|
|
54
|
+
const value: unknown = Reflect.get(target, key, receiver);
|
|
55
|
+
if (typeof key !== "string" || key === "__proto__") return value;
|
|
56
|
+
if (typeof value === "string") {
|
|
57
|
+
slot()[key] = value;
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
if (isTraversable(value)) return wrap(value, place(value, slot, key));
|
|
61
|
+
return value;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
return { messages: wrap(messages, () => used), subset: () => used };
|
|
65
|
+
}
|
|
@@ -15,6 +15,10 @@ export interface DmsNetworkErrorTranslator {
|
|
|
15
15
|
|
|
16
16
|
const NETWORK_ERROR_TOAST_ID = "dms-network-error";
|
|
17
17
|
const NETWORK_ERROR_KEY = "error.network";
|
|
18
|
+
/** The messages a module overrides the built-in texts with. */
|
|
19
|
+
export const NETWORK_ERROR_KEYS = ["title", "description"].map(
|
|
20
|
+
(name) => `${NETWORK_ERROR_KEY}.${name}`,
|
|
21
|
+
);
|
|
18
22
|
const DEFAULT_LOCALE = "en";
|
|
19
23
|
// Shipped with the renderer, since no module is guaranteed to translate the
|
|
20
24
|
// case; a module overrides them with `error.network.title` and
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
trackDmsServerScopes,
|
|
31
31
|
withPublicOptions,
|
|
32
32
|
} from "./frontend-module";
|
|
33
|
+
import { type DmsMessageSubset, SSR_MESSAGES_ID } from "./message-subset";
|
|
33
34
|
import { parsePublicOptions } from "./public-options";
|
|
34
35
|
import { frontendModules } from "./frontend-modules.generated";
|
|
35
36
|
import {
|
|
@@ -129,6 +130,12 @@ function asyncComponentsScript(names: Set<string>): string {
|
|
|
129
130
|
return `<script id="${SSR_ASYNC_COMPONENTS_ID}" type="application/json">${value}</script>`;
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
function messagesScript(subset: DmsMessageSubset | undefined): string {
|
|
134
|
+
if (!subset) return "";
|
|
135
|
+
const value = JSON.stringify(subset).replaceAll("<", "\\u003c");
|
|
136
|
+
return `<script id="${SSR_MESSAGES_ID}" type="application/json">${value}</script>`;
|
|
137
|
+
}
|
|
138
|
+
|
|
132
139
|
function iconsScript(names: Set<string>): string {
|
|
133
140
|
const value = JSON.stringify(serializeDmsIcons(names)).replaceAll(
|
|
134
141
|
"<",
|
|
@@ -195,6 +202,7 @@ async function renderDmsPageWithRuntime(
|
|
|
195
202
|
let iconSymbols = new Map<string, string>();
|
|
196
203
|
let payload: DmsPayload = { data: {}, errors: {}, state: {} };
|
|
197
204
|
let catalogLocale: (() => string | undefined) | undefined;
|
|
205
|
+
let messageSubset: (() => DmsMessageSubset | undefined) | undefined;
|
|
198
206
|
const inertiaResult = await createInertiaApp({
|
|
199
207
|
page,
|
|
200
208
|
// Read as the HTML is complete: data a run settles afterwards was never
|
|
@@ -221,6 +229,7 @@ async function renderDmsPageWithRuntime(
|
|
|
221
229
|
serverFetch,
|
|
222
230
|
});
|
|
223
231
|
catalogLocale = configured.catalogLocale;
|
|
232
|
+
messageSubset = configured.messageSubset;
|
|
224
233
|
return app;
|
|
225
234
|
},
|
|
226
235
|
});
|
|
@@ -255,7 +264,7 @@ async function renderDmsPageWithRuntime(
|
|
|
255
264
|
const renderedHead = await renderSSRHead(head);
|
|
256
265
|
return {
|
|
257
266
|
error: page.props.error,
|
|
258
|
-
body: `${inertiaResult.body}${dmsIconSprite(iconSymbols)}${payloadScript(payload)}${asyncComponentsScript(asyncComponents)}${iconsScript(icons)}`,
|
|
267
|
+
body: `${inertiaResult.body}${dmsIconSprite(iconSymbols)}${payloadScript(payload)}${asyncComponentsScript(asyncComponents)}${iconsScript(icons)}${messagesScript(messageSubset?.())}`,
|
|
259
268
|
head: {
|
|
260
269
|
bodyAttrs: renderedHead.bodyAttrs,
|
|
261
270
|
headTags: `${inertiaResult.head.join("")}${renderedHead.headTags}`,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} IconsPluginContext
|
|
3
|
+
* @property {{ config: { consumer: string } }} environment
|
|
4
|
+
* @property {(message: string) => never} error
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Nuxt UI's plugin that installs the client icon bundle. */
|
|
8
|
+
const ICONS_PLUGIN = /\/@nuxt\/ui\/dist\/runtime\/vue\/plugins\/icons\.js$/;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The client build of Nuxt UI's icons plugin, as a Vite plugin.
|
|
12
|
+
*
|
|
13
|
+
* The plugin imports the bundle of every icon the sources name, which put it
|
|
14
|
+
* in the entry of every page, the sign-in page's included, for icons it draws
|
|
15
|
+
* from the server render's own copy. The client gets an empty plugin, and
|
|
16
|
+
* `loadIconBundle` (`icon-bundle.ts`) loads the bundle when the page needs it. The server render keeps the plugin as it is. The
|
|
17
|
+
* build fails if Nuxt UI changes the form rewritten here, rather than
|
|
18
|
+
* letting the bundle return to the entry unnoticed.
|
|
19
|
+
*
|
|
20
|
+
* @param {(id: string) => boolean} isNuxtUiFile whether a module is Nuxt UI's
|
|
21
|
+
* @returns {{ name: string, enforce: "pre", transform: (this: IconsPluginContext, code: string, id: string) => { code: string, map: null } | null }}
|
|
22
|
+
*/
|
|
23
|
+
export function uiLazyIcons(isNuxtUiFile) {
|
|
24
|
+
return {
|
|
25
|
+
name: "dms-ui-lazy-icons",
|
|
26
|
+
enforce: "pre",
|
|
27
|
+
transform(code, id) {
|
|
28
|
+
const path = id.replaceAll("\\", "/").split("?")[0];
|
|
29
|
+
if (
|
|
30
|
+
this.environment.config.consumer !== "client" ||
|
|
31
|
+
!isNuxtUiFile(id) ||
|
|
32
|
+
!ICONS_PLUGIN.test(path)
|
|
33
|
+
)
|
|
34
|
+
return null;
|
|
35
|
+
if (!code.includes("virtual:nuxt-ui-icons"))
|
|
36
|
+
this.error(
|
|
37
|
+
`${id} no longer installs the client icon bundle the way the DMS ` +
|
|
38
|
+
"defers it: the bundle would return to the entry. Update " +
|
|
39
|
+
"ui-lazy-icons.mjs for this Nuxt UI release.",
|
|
40
|
+
);
|
|
41
|
+
return { code: "export default { install() {} };", map: null };
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -14,6 +14,7 @@ import { recordEntryWeight } from "./entry-weight.mjs";
|
|
|
14
14
|
import { rejectServerSourcesInClient } from "./client-server-guard.mjs";
|
|
15
15
|
import { uiInertiaPage } from "./ui-inertia-page.mjs";
|
|
16
16
|
import { uiKbd } from "./ui-kbd.mjs";
|
|
17
|
+
import { uiLazyIcons } from "./ui-lazy-icons.mjs";
|
|
17
18
|
import { uiRequestState } from "./ui-request-state.mjs";
|
|
18
19
|
import { autoImportDirectories, vitePlugins } from "./frontend-build-loader.ts";
|
|
19
20
|
import { frontendBuilds } from "./frontend-builds.generated.ts";
|
|
@@ -184,6 +185,7 @@ export default defineConfig({
|
|
|
184
185
|
},
|
|
185
186
|
},
|
|
186
187
|
uiKbd(isNuxtUiFile),
|
|
188
|
+
uiLazyIcons(isNuxtUiFile),
|
|
187
189
|
uiInertiaPage(isNuxtUiFile),
|
|
188
190
|
uiRequestState(isNuxtUiFile),
|
|
189
191
|
vue({ script: { globalTypeFiles: [sfcGlobalTypesFile] } }),
|