@movk/nuxt 0.1.1 → 1.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.
Files changed (78) hide show
  1. package/README.md +84 -9
  2. package/dist/module.d.mts +19 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +77 -8
  5. package/dist/runtime/components/AutoForm.d.vue.ts +12 -6
  6. package/dist/runtime/components/AutoForm.vue +4 -1
  7. package/dist/runtime/components/AutoForm.vue.d.ts +12 -6
  8. package/dist/runtime/components/ColorChooser.d.vue.ts +11 -5
  9. package/dist/runtime/components/ColorChooser.vue.d.ts +11 -5
  10. package/dist/runtime/components/DatePicker.d.vue.ts +14 -5
  11. package/dist/runtime/components/DatePicker.vue.d.ts +14 -5
  12. package/dist/runtime/components/SlideVerify.d.vue.ts +107 -0
  13. package/dist/runtime/components/SlideVerify.vue +147 -0
  14. package/dist/runtime/components/SlideVerify.vue.d.ts +107 -0
  15. package/dist/runtime/components/StarRating.d.vue.ts +7 -7
  16. package/dist/runtime/components/StarRating.vue +1 -0
  17. package/dist/runtime/components/StarRating.vue.d.ts +7 -7
  18. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.d.vue.ts +6 -4
  19. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue +1 -1
  20. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue.d.ts +6 -4
  21. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.d.vue.ts +6 -4
  22. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue.d.ts +6 -4
  23. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.d.vue.ts +6 -4
  24. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue.d.ts +6 -4
  25. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.d.vue.ts +6 -4
  26. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue.d.ts +6 -4
  27. package/dist/runtime/components/input/WithCharacterLimit.d.vue.ts +11 -5
  28. package/dist/runtime/components/input/WithCharacterLimit.vue.d.ts +11 -5
  29. package/dist/runtime/components/input/WithClear.d.vue.ts +12 -5
  30. package/dist/runtime/components/input/WithClear.vue.d.ts +12 -5
  31. package/dist/runtime/components/input/WithCopy.d.vue.ts +12 -5
  32. package/dist/runtime/components/input/WithCopy.vue.d.ts +12 -5
  33. package/dist/runtime/components/input/WithPasswordToggle.d.vue.ts +11 -5
  34. package/dist/runtime/components/input/WithPasswordToggle.vue.d.ts +11 -5
  35. package/dist/runtime/components/theme-picker/ThemePicker.d.vue.ts +3 -0
  36. package/dist/runtime/components/theme-picker/ThemePicker.vue +235 -0
  37. package/dist/runtime/components/theme-picker/ThemePicker.vue.d.ts +3 -0
  38. package/dist/runtime/components/theme-picker/ThemePickerButton.d.vue.ts +18 -0
  39. package/dist/runtime/components/theme-picker/ThemePickerButton.vue +34 -0
  40. package/dist/runtime/components/theme-picker/ThemePickerButton.vue.d.ts +18 -0
  41. package/dist/runtime/composables/useApiAuth.d.ts +47 -0
  42. package/dist/runtime/composables/useApiAuth.js +66 -0
  43. package/dist/runtime/composables/useApiFetch.d.ts +42 -0
  44. package/dist/runtime/composables/useApiFetch.js +41 -0
  45. package/dist/runtime/composables/useAutoForm.d.ts +81 -605
  46. package/dist/runtime/composables/useAutoForm.js +3 -1
  47. package/dist/runtime/composables/useClientApiFetch.d.ts +24 -0
  48. package/dist/runtime/composables/useClientApiFetch.js +8 -0
  49. package/dist/runtime/composables/useDateFormatter.d.ts +21 -7
  50. package/dist/runtime/composables/useDateFormatter.js +92 -57
  51. package/dist/runtime/composables/useDownloadWithProgress.d.ts +48 -0
  52. package/dist/runtime/composables/useDownloadWithProgress.js +85 -0
  53. package/dist/runtime/composables/useTheme.d.ts +21 -0
  54. package/dist/runtime/composables/useTheme.js +143 -0
  55. package/dist/runtime/composables/useUploadWithProgress.d.ts +52 -0
  56. package/dist/runtime/composables/useUploadWithProgress.js +117 -0
  57. package/dist/runtime/internal/useAutoFormProvider.js +2 -2
  58. package/dist/runtime/plugins/api.factory.d.ts +2 -0
  59. package/dist/runtime/plugins/api.factory.js +186 -0
  60. package/dist/runtime/plugins/theme.d.ts +2 -0
  61. package/dist/runtime/plugins/theme.js +89 -0
  62. package/dist/runtime/schemas/api.d.ts +590 -0
  63. package/dist/runtime/schemas/api.js +228 -0
  64. package/dist/runtime/server/api/_movk/session.post.d.ts +10 -0
  65. package/dist/runtime/server/api/_movk/session.post.js +18 -0
  66. package/dist/runtime/style.css +1 -0
  67. package/dist/runtime/types/api.d.ts +218 -0
  68. package/dist/runtime/types/api.js +0 -0
  69. package/dist/runtime/types/auth.d.ts +34 -0
  70. package/dist/runtime/types/auto-form-renderer.d.ts +14 -22
  71. package/dist/runtime/types/auto-form-renderer.js +0 -0
  72. package/dist/runtime/types/components.d.ts +29 -41
  73. package/dist/runtime/types/components.js +0 -0
  74. package/dist/runtime/types/index.d.ts +1 -0
  75. package/dist/runtime/types/index.js +3 -2
  76. package/dist/runtime/utils/api-utils.d.ts +79 -0
  77. package/dist/runtime/utils/api-utils.js +127 -0
  78. package/package.json +38 -31
@@ -0,0 +1,52 @@
1
+ import type { ApiResponse, RequestToastOptions } from '../types/api.js';
2
+ /**
3
+ * 上传选项(带进度监控)
4
+ */
5
+ export interface UploadWithProgressOptions {
6
+ /** 文件字段名 @defaultValue 'file' */
7
+ fieldName?: string;
8
+ /** 额外的表单字段 */
9
+ fields?: Record<string, string | Blob>;
10
+ /** 额外的请求头 */
11
+ headers?: Record<string, string>;
12
+ /** Toast 配置 */
13
+ toast?: RequestToastOptions | false;
14
+ /** 端点名称 */
15
+ endpoint?: string;
16
+ /** 上传成功回调 */
17
+ onSuccess?: (response: ApiResponse) => void;
18
+ /** 上传失败回调 */
19
+ onError?: (error: Error) => void;
20
+ }
21
+ /**
22
+ * 带进度监控的文件上传 composable
23
+ *
24
+ * 基于原生 XMLHttpRequest 实现,支持实时进度和取消上传
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const { progress, uploading, upload, abort } = useUploadWithProgress()
29
+ *
30
+ * const { data, error } = await upload('/api/upload', files, {
31
+ * fieldName: 'files',
32
+ * onSuccess: (res) => console.log('上传成功', res)
33
+ * })
34
+ * ```
35
+ */
36
+ export declare function useUploadWithProgress<T = unknown>(): {
37
+ /** 上传进度 (0-100) */
38
+ progress: any;
39
+ /** 是否正在上传 */
40
+ uploading: any;
41
+ /** 上传结果 */
42
+ data: any;
43
+ /** 错误信息 */
44
+ error: any;
45
+ /** 执行上传 */
46
+ upload: (url: string, files: File | File[], options?: UploadWithProgressOptions) => Promise<{
47
+ data: ApiResponse<T> | null;
48
+ error: Error | null;
49
+ }>;
50
+ /** 中止上传 */
51
+ abort: () => void;
52
+ };
@@ -0,0 +1,117 @@
1
+ import { ref, useNuxtApp } from "#imports";
2
+ import {
3
+ showToast,
4
+ isBusinessSuccess,
5
+ extractMessage,
6
+ extractToastMessage,
7
+ getAuthHeaders
8
+ } from "../utils/api-utils.js";
9
+ export function useUploadWithProgress() {
10
+ const { $api } = useNuxtApp();
11
+ const progress = ref(0);
12
+ const uploading = ref(false);
13
+ const data = ref(null);
14
+ const error = ref(null);
15
+ let currentXhr = null;
16
+ const abort = () => {
17
+ currentXhr?.abort();
18
+ currentXhr = null;
19
+ uploading.value = false;
20
+ progress.value = 0;
21
+ };
22
+ const upload = async (url, files, options = {}) => {
23
+ const { fieldName = "file", fields = {}, headers = {}, toast, endpoint, onSuccess, onError } = options;
24
+ const apiInstance = endpoint ? $api.use(endpoint) : $api;
25
+ const config = apiInstance.getConfig();
26
+ const fullUrl = `${config.baseURL || ""}${url}`;
27
+ const formData = new FormData();
28
+ const fileArray = Array.isArray(files) ? files : [files];
29
+ fileArray.forEach((file) => formData.append(fieldName, file));
30
+ Object.entries(fields).forEach(([key, value]) => formData.append(key, value));
31
+ progress.value = 0;
32
+ uploading.value = true;
33
+ data.value = null;
34
+ error.value = null;
35
+ return new Promise((resolve) => {
36
+ const xhr = new XMLHttpRequest();
37
+ currentXhr = xhr;
38
+ xhr.upload.addEventListener("progress", (e) => {
39
+ if (e.lengthComputable) {
40
+ progress.value = Math.round(e.loaded / e.total * 100);
41
+ }
42
+ });
43
+ xhr.addEventListener("load", () => {
44
+ uploading.value = false;
45
+ currentXhr = null;
46
+ try {
47
+ const response = JSON.parse(xhr.responseText);
48
+ const isSuccess = isBusinessSuccess(response, config.response);
49
+ const message = extractMessage(response, config.response);
50
+ if (isSuccess) {
51
+ data.value = response;
52
+ if (import.meta.client && toast !== false) {
53
+ const msg = extractToastMessage(toast, "success", message || "\u4E0A\u4F20\u6210\u529F");
54
+ showToast("success", msg, toast, config.toast);
55
+ }
56
+ onSuccess?.(response);
57
+ resolve({ data: response, error: null });
58
+ } else {
59
+ const err = new Error(message || "\u4E0A\u4F20\u5931\u8D25");
60
+ error.value = err;
61
+ if (import.meta.client && toast !== false) {
62
+ const msg = extractToastMessage(toast, "error", message || "\u4E0A\u4F20\u5931\u8D25");
63
+ showToast("error", msg, toast, config.toast);
64
+ }
65
+ onError?.(err);
66
+ resolve({ data: null, error: err });
67
+ }
68
+ } catch (err) {
69
+ const parseError = err instanceof Error ? err : new Error("\u54CD\u5E94\u89E3\u6790\u5931\u8D25");
70
+ error.value = parseError;
71
+ if (import.meta.client && toast !== false) {
72
+ showToast("error", "\u4E0A\u4F20\u5931\u8D25", toast, config.toast);
73
+ }
74
+ onError?.(parseError);
75
+ resolve({ data: null, error: parseError });
76
+ }
77
+ });
78
+ xhr.addEventListener("error", () => {
79
+ uploading.value = false;
80
+ currentXhr = null;
81
+ const err = new Error("\u7F51\u7EDC\u9519\u8BEF");
82
+ error.value = err;
83
+ if (import.meta.client && toast !== false) {
84
+ showToast("error", "\u4E0A\u4F20\u5931\u8D25", toast, config.toast);
85
+ }
86
+ onError?.(err);
87
+ resolve({ data: null, error: err });
88
+ });
89
+ xhr.addEventListener("abort", () => {
90
+ uploading.value = false;
91
+ currentXhr = null;
92
+ error.value = new Error("\u4E0A\u4F20\u5DF2\u53D6\u6D88");
93
+ resolve({ data: null, error: error.value });
94
+ });
95
+ xhr.open("POST", fullUrl);
96
+ const authHeaders = getAuthHeaders(config);
97
+ Object.entries({ ...headers, ...authHeaders }).forEach(([key, value]) => {
98
+ xhr.setRequestHeader(key, value);
99
+ });
100
+ xhr.send(formData);
101
+ });
102
+ };
103
+ return {
104
+ /** 上传进度 (0-100) */
105
+ progress,
106
+ /** 是否正在上传 */
107
+ uploading,
108
+ /** 上传结果 */
109
+ data,
110
+ /** 错误信息 */
111
+ error,
112
+ /** 执行上传 */
113
+ upload,
114
+ /** 中止上传 */
115
+ abort
116
+ };
117
+ }
@@ -174,8 +174,8 @@ export function useAutoFormProvider(state, slots) {
174
174
  return defu(field, {
175
175
  meta: {
176
176
  fieldSlots: {
177
- hint: ({ open }) => h(UIcon, {
178
- name: open ? "i-lucide-chevron-down" : "i-lucide-chevron-right",
177
+ hint: (props) => h(UIcon, {
178
+ name: props.open ? "i-lucide-chevron-down" : "i-lucide-chevron-right",
179
179
  class: "shrink-0 size-5 transition-transform duration-200"
180
180
  })
181
181
  }
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,186 @@
1
+ import { getPath, triggerDownload, extractFilename } from "@movk/core";
2
+ import {
3
+ showToast,
4
+ isBusinessSuccess,
5
+ extractMessage,
6
+ extractToastMessage
7
+ } from "../utils/api-utils.js";
8
+ import { defineNuxtPlugin, navigateTo, useNuxtApp, useUserSession, useRuntimeConfig } from "#imports";
9
+ import defu from "defu";
10
+ function getUserSession() {
11
+ try {
12
+ const nuxtApp = useNuxtApp();
13
+ return nuxtApp.runWithContext(() => useUserSession());
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function getTokenFromSession(tokenPath) {
19
+ const userSession = getUserSession();
20
+ if (!userSession?.session?.value) return null;
21
+ const sessionData = userSession.session.value;
22
+ return getPath(sessionData, tokenPath) || null;
23
+ }
24
+ function buildAuthHeader(token, config) {
25
+ const tokenType = config.tokenType === "Custom" ? config.customTokenType || "" : config.tokenType || "Bearer";
26
+ return tokenType ? `${tokenType} ${token}` : token;
27
+ }
28
+ async function handleUnauthorized(config) {
29
+ const userSession = getUserSession();
30
+ const unauthorizedConfig = config.unauthorized;
31
+ if (unauthorizedConfig?.clearSession && userSession?.clear) {
32
+ await userSession.clear();
33
+ }
34
+ if (unauthorizedConfig?.redirect) {
35
+ const loginPath = unauthorizedConfig.loginPath || "/login";
36
+ const nuxtApp = useNuxtApp();
37
+ await nuxtApp.runWithContext(() => navigateTo(loginPath));
38
+ }
39
+ }
40
+ function getApiFetchContext(context) {
41
+ return context.options.context || {};
42
+ }
43
+ function createBuiltinHooks(resolvedConfig, publicConfig) {
44
+ const { auth: authConfig, toast: toastConfig, response: responseConfig } = resolvedConfig;
45
+ return {
46
+ onRequest(context) {
47
+ if (authConfig.enabled) {
48
+ const tokenPath = authConfig.sessionTokenPath || "token";
49
+ const token = getTokenFromSession(tokenPath);
50
+ if (token) {
51
+ const headerName = authConfig.headerName || "Authorization";
52
+ const headerValue = buildAuthHeader(token, authConfig);
53
+ context.options.headers = context.options.headers || new Headers();
54
+ if (context.options.headers instanceof Headers) {
55
+ context.options.headers.set(headerName, headerValue);
56
+ } else {
57
+ context.options.headers[headerName] = headerValue;
58
+ }
59
+ }
60
+ }
61
+ if (publicConfig.debug) {
62
+ console.log(`[Movk API] Request: ${context.options.method || "GET"} ${resolvedConfig.baseURL}${context.request}`);
63
+ }
64
+ },
65
+ async onRequestError({ error }) {
66
+ if (publicConfig.debug) {
67
+ console.error("[Movk API] Request Error:", error);
68
+ }
69
+ },
70
+ async onResponse(context) {
71
+ const response = context.response;
72
+ const data = response._data;
73
+ if (publicConfig.debug) {
74
+ console.log("[Movk API] Response:", data);
75
+ }
76
+ if (!import.meta.client) return;
77
+ const { toast, skipBusinessCheck } = getApiFetchContext(context);
78
+ const isSuccess = skipBusinessCheck || isBusinessSuccess(data, responseConfig);
79
+ const message = extractMessage(data, responseConfig);
80
+ if (isSuccess) {
81
+ const successMessage = toast !== false ? toast?.successMessage || message : void 0;
82
+ showToast("success", successMessage, toast, toastConfig);
83
+ }
84
+ },
85
+ async onResponseError(context) {
86
+ const { response } = context;
87
+ if (response.status === 401) {
88
+ await handleUnauthorized(authConfig);
89
+ }
90
+ if (publicConfig.debug) {
91
+ console.error("[Movk API] Error:", response.status, response._data);
92
+ }
93
+ if (!import.meta.client) return;
94
+ const { toast } = getApiFetchContext(context);
95
+ const data = response._data;
96
+ const message = data ? extractMessage(data, responseConfig) : void 0;
97
+ const errorMessage = toast !== false ? toast?.errorMessage || message || `\u8BF7\u6C42\u5931\u8D25 (${response.status})` : void 0;
98
+ showToast("error", errorMessage, toast, toastConfig);
99
+ }
100
+ };
101
+ }
102
+ function createApiClient(resolvedConfig, publicConfig, getOrCreateEndpoint) {
103
+ const builtinHooks = createBuiltinHooks(resolvedConfig, publicConfig);
104
+ resolvedConfig.builtinHooks = builtinHooks;
105
+ const $fetchInstance = $fetch.create({
106
+ baseURL: resolvedConfig.baseURL,
107
+ headers: resolvedConfig.headers,
108
+ onRequest: builtinHooks.onRequest,
109
+ onRequestError: builtinHooks.onRequestError,
110
+ onResponse: builtinHooks.onResponse,
111
+ onResponseError: builtinHooks.onResponseError
112
+ });
113
+ const download = async (url, filename, options = {}) => {
114
+ const { toast, ...fetchOptions } = options;
115
+ const response = await $fetchInstance.raw(url, {
116
+ ...fetchOptions,
117
+ method: "GET",
118
+ responseType: "blob",
119
+ context: { toast }
120
+ });
121
+ if (!response._data) {
122
+ throw new Error("\u4E0B\u8F7D\u5931\u8D25: \u672A\u63A5\u6536\u5230\u6570\u636E");
123
+ }
124
+ const finalFilename = filename || extractFilename(response.headers, url.split("/").pop() || "download");
125
+ triggerDownload(response._data, finalFilename);
126
+ if (import.meta.client && toast !== false) {
127
+ const message = extractToastMessage(toast, "success", `\u4E0B\u8F7D\u6210\u529F: ${finalFilename}`);
128
+ showToast("success", message, toast, resolvedConfig.toast);
129
+ }
130
+ };
131
+ const upload = async (url, file, options = {}) => {
132
+ const { toast, fieldName = "file", ...fetchOptions } = options;
133
+ const formData = file instanceof FormData ? file : (() => {
134
+ const fd = new FormData();
135
+ const files = Array.isArray(file) ? file : [file];
136
+ files.forEach((f) => fd.append(fieldName, f));
137
+ return fd;
138
+ })();
139
+ return $fetchInstance(url, {
140
+ ...fetchOptions,
141
+ method: "POST",
142
+ body: formData,
143
+ context: { toast }
144
+ });
145
+ };
146
+ return {
147
+ $fetch: $fetchInstance,
148
+ use: (endpoint) => getOrCreateEndpoint(endpoint),
149
+ download,
150
+ upload,
151
+ getConfig: () => resolvedConfig
152
+ };
153
+ }
154
+ export default defineNuxtPlugin(() => {
155
+ const runtimeConfig = useRuntimeConfig();
156
+ const publicConfig = runtimeConfig.public.movkApi;
157
+ const privateConfig = import.meta.server ? runtimeConfig.movkApi : void 0;
158
+ const endpointCache = /* @__PURE__ */ new Map();
159
+ const getOrCreateEndpoint = (endpointName) => {
160
+ if (endpointCache.has(endpointName)) {
161
+ return endpointCache.get(endpointName);
162
+ }
163
+ const endpoints = publicConfig.endpoints || {};
164
+ const endpointConfig = endpoints[endpointName];
165
+ if (!endpointConfig) {
166
+ console.warn(`[Movk API] Endpoint "${endpointName}" not found, using default`);
167
+ return getOrCreateEndpoint(publicConfig.defaultEndpoint || "default");
168
+ }
169
+ const privateEndpointConfig = privateConfig?.endpoints?.[endpointName];
170
+ const resolvedConfig = {
171
+ ...endpointConfig,
172
+ headers: privateEndpointConfig?.headers,
173
+ auth: defu(endpointConfig.auth, publicConfig.auth),
174
+ toast: defu(endpointConfig.toast, publicConfig.toast),
175
+ response: defu(endpointConfig.response, publicConfig.response)
176
+ };
177
+ const client = createApiClient(resolvedConfig, publicConfig, getOrCreateEndpoint);
178
+ endpointCache.set(endpointName, client);
179
+ return client;
180
+ };
181
+ const defaultEndpoint = publicConfig.defaultEndpoint || "default";
182
+ const api = getOrCreateEndpoint(defaultEndpoint);
183
+ return {
184
+ provide: { api }
185
+ };
186
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,89 @@
1
+ import { defineNuxtPlugin, useAppConfig, useHead, useSiteConfig } from "#imports";
2
+ export default defineNuxtPlugin({
3
+ enforce: "post",
4
+ setup() {
5
+ const appConfig = useAppConfig();
6
+ const site = useSiteConfig();
7
+ if (import.meta.client) {
8
+ let updateColor = function(type) {
9
+ const color = localStorage.getItem(`${site.name}-ui-${type}`);
10
+ if (color) {
11
+ appConfig.ui.colors[type] = color;
12
+ }
13
+ }, updateRadius = function() {
14
+ const radius = localStorage.getItem(`${site.name}-ui-radius`);
15
+ if (radius) {
16
+ appConfig.theme.radius = Number.parseFloat(radius);
17
+ }
18
+ }, updateBlackAsPrimary = function() {
19
+ const blackAsPrimary = localStorage.getItem(`${site.name}-ui-black-as-primary`);
20
+ if (blackAsPrimary) {
21
+ appConfig.theme.blackAsPrimary = blackAsPrimary === "true";
22
+ }
23
+ }, updateFont = function() {
24
+ const font = localStorage.getItem(`${site.name}-ui-font`);
25
+ if (font) {
26
+ appConfig.theme.font = font;
27
+ }
28
+ };
29
+ updateColor("primary");
30
+ updateColor("neutral");
31
+ updateRadius();
32
+ updateBlackAsPrimary();
33
+ updateFont();
34
+ }
35
+ if (import.meta.server) {
36
+ useHead({
37
+ script: [{
38
+ innerHTML: `
39
+ let html = document.querySelector('style#nuxt-ui-colors').innerHTML;
40
+
41
+ if (localStorage.getItem('${site.name}-ui-primary')) {
42
+ const primaryColor = localStorage.getItem('${site.name}-ui-primary');
43
+ if (primaryColor !== 'black') {
44
+ html = html.replace(
45
+ /(--ui-color-primary-\\d{2,3}:\\s*var\\(--color-)${appConfig.ui.colors.primary}(-\\d{2,3}.*?\\))/g,
46
+ \`$1\${primaryColor}$2\`
47
+ );
48
+ }
49
+ }
50
+ if (localStorage.getItem('${site.name}-ui-neutral')) {
51
+ let neutralColor = localStorage.getItem('${site.name}-ui-neutral');
52
+ html = html.replace(
53
+ /(--ui-color-neutral-\\d{2,3}:\\s*var\\(--color-)${appConfig.ui.colors.neutral}(-\\d{2,3}.*?\\))/g,
54
+ \`$1\${neutralColor === 'neutral' ? 'old-neutral' : neutralColor}$2\`
55
+ );
56
+ }
57
+
58
+ document.querySelector('style#nuxt-ui-colors').innerHTML = html;
59
+ `.replace(/\s+/g, " "),
60
+ type: "text/javascript",
61
+ tagPriority: -1
62
+ }, {
63
+ innerHTML: `
64
+ if (localStorage.getItem('${site.name}-ui-radius')) {
65
+ document.querySelector('style#nuxt-ui-radius').innerHTML = ':root { --ui-radius: ' + localStorage.getItem('${site.name}-ui-radius') + 'rem; }';
66
+ }
67
+ `.replace(/\s+/g, " "),
68
+ type: "text/javascript",
69
+ tagPriority: -1
70
+ }, {
71
+ innerHTML: `
72
+ if (localStorage.getItem('${site.name}-ui-black-as-primary') === 'true') {
73
+ document.querySelector('style#nuxt-ui-black-as-primary').innerHTML = ':root { --ui-primary: black; } .dark { --ui-primary: white; }';
74
+ } else {
75
+ document.querySelector('style#nuxt-ui-black-as-primary').innerHTML = '';
76
+ }
77
+ `.replace(/\s+/g, " ")
78
+ }, {
79
+ innerHTML: `
80
+ if (localStorage.getItem('${site.name}-ui-font')) {
81
+ const font = localStorage.getItem('${site.name}-ui-font');
82
+ document.querySelector('style#nuxt-ui-font').innerHTML = ':root { --font-sans: \\'' + font + '\\', sans-serif; }';
83
+ }
84
+ `.replace(/\s+/g, " ")
85
+ }]
86
+ });
87
+ }
88
+ }
89
+ });