mirror of
https://github.com/unraid/api.git
synced 2026-05-08 08:00:19 -05:00
fix: inject Tailwind CSS into client entry point (#1537)
Added a Vite plugin to automatically inject the Tailwind CSS import into the `unraid-components.client.js` entry file, enhancing the integration of Tailwind CSS within the application. This change improves the setup for styling components consistently across the project. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added automated validation to ensure Tailwind CSS styles are correctly included in the custom elements build output. * **Chores** * Updated the build process to include a CSS validation step after manifest generation. * Enhanced development build configuration to enable CSS source maps and optimize Tailwind CSS injection into web components. * Extended CSS theme with new responsive breakpoint variables. * Improved CSS class specificity in user profile, server state, and update modal components for consistent styling. * Removed redundant style blocks and global CSS imports from multiple components to streamline styling and reduce duplication. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -16,7 +16,6 @@
|
|||||||
"mcp__ide__getDiagnostics",
|
"mcp__ide__getDiagnostics",
|
||||||
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)",
|
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)",
|
||||||
"Bash(pnpm storybook:*)",
|
"Bash(pnpm storybook:*)",
|
||||||
"Bash(rm:*)",
|
|
||||||
"Bash(pnpm add:*)",
|
"Bash(pnpm add:*)",
|
||||||
"Bash(pnpm install:*)",
|
"Bash(pnpm install:*)",
|
||||||
"Bash(pkill:*)",
|
"Bash(pkill:*)",
|
||||||
@@ -33,7 +32,13 @@
|
|||||||
"Bash(pnpm --filter @unraid/ui build)",
|
"Bash(pnpm --filter @unraid/ui build)",
|
||||||
"Bash(pnpm --filter @unraid/web build)",
|
"Bash(pnpm --filter @unraid/web build)",
|
||||||
"Bash(python3:*)",
|
"Bash(python3:*)",
|
||||||
"Bash(pnpm tailwind:build:*)"
|
"Bash(pnpm tailwind:build:*)",
|
||||||
|
"WebFetch(domain:erangrin.github.io)",
|
||||||
|
"Bash(pnpm clean:*)",
|
||||||
|
"Bash(pnpm validate:css:*)",
|
||||||
|
"Bash(node:*)",
|
||||||
|
"Bash(rm:*)",
|
||||||
|
"Bash(pnpm run:*)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enableAllProjectMcpServers": false
|
"enableAllProjectMcpServers": false
|
||||||
|
|||||||
+1
@@ -39,6 +39,7 @@ class WebComponentsExtractor
|
|||||||
return $contents ? json_decode($contents, true) : [];
|
return $contents ? json_decode($contents, true) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getRichComponentsFile(): string
|
private function getRichComponentsFile(): string
|
||||||
{
|
{
|
||||||
$manifestFiles = $this->findManifestFiles('manifest.json');
|
$manifestFiles = $this->findManifestFiles('manifest.json');
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
@custom-variant dark (&:where(.dark, .dark *));
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
|
/* Breakpoints */
|
||||||
|
--breakpoint-xs: 30rem;
|
||||||
|
--breakpoint-2xl: 100rem;
|
||||||
|
--breakpoint-3xl: 120rem;
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
--color-primary-50: #fff7ed;
|
--color-primary-50: #fff7ed;
|
||||||
--color-primary-100: #ffedd5;
|
--color-primary-100: #ffedd5;
|
||||||
--color-primary-200: #fed7aa;
|
--color-primary-200: #fed7aa;
|
||||||
|
|||||||
@@ -101,57 +101,3 @@ watchEffect(() => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -6,8 +6,3 @@ import ApiKeyManager from '~/components/ApiKey/ApiKeyManager.vue';
|
|||||||
<ApiKeyManager />
|
<ApiKeyManager />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style>
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -30,9 +30,3 @@ const { authAction, stateData } = storeToRefs(serverStore);
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -14,9 +14,3 @@ onBeforeMount(() => {
|
|||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -74,9 +74,3 @@ const items = [
|
|||||||
<Switch id="banner" v-model:checked="form.banner" />
|
<Switch id="banner" v-model:checked="form.banner" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -148,8 +148,3 @@ const onChange = ({ data }: { data: Record<string, unknown> }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '../../assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -23,9 +23,3 @@ import { CogIcon } from '@heroicons/vue/24/solid';
|
|||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -77,9 +77,3 @@ onBeforeMount(() => {
|
|||||||
</PageContainer>
|
</PageContainer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -71,9 +71,3 @@ const downloadUrl = computed(() => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -24,9 +24,3 @@ const items = [
|
|||||||
<Select v-model="selector" :items="items" placeholder="Select an initial state" />
|
<Select v-model="selector" :items="items" placeholder="Select an initial state" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -127,10 +127,3 @@ const updateOsStatus = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -191,9 +191,3 @@ watch(selectedLogFile, (newValue) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -31,57 +31,3 @@ const { modalVisible: apiKeyModalVisible } = storeToRefs(useApiKeyStore());
|
|||||||
<ApiKeyCreate :open="apiKeyModalVisible" :t="t" />
|
<ApiKeyCreate :open="apiKeyModalVisible" :t="t" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -238,8 +238,3 @@ provide('isSubmitting', isCreating);
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -324,9 +324,3 @@ const items = computed((): RegistrationItemProps[] => {
|
|||||||
</PageContainer>
|
</PageContainer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -150,9 +150,3 @@ const navigateToExternalSSOUrl = () => {
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -91,9 +91,3 @@ const handleThemeChange = (event: Event) => {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -73,57 +73,3 @@ onBeforeMount(() => {
|
|||||||
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
KeyIcon,
|
KeyIcon,
|
||||||
ServerStackIcon,
|
ServerStackIcon,
|
||||||
} from '@heroicons/vue/24/solid';
|
} from '@heroicons/vue/24/solid';
|
||||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
import { BrandButton, BrandLoading, cn } from '@unraid/ui';
|
||||||
import { allowedDocsOriginRegex, allowedDocsUrlRegex } from '~/helpers/urls';
|
import { allowedDocsOriginRegex, allowedDocsUrlRegex } from '~/helpers/urls';
|
||||||
|
|
||||||
import type { ComposerTranslation } from 'vue-i18n';
|
import type { ComposerTranslation } from 'vue-i18n';
|
||||||
@@ -176,8 +176,8 @@ watch(darkMode, () => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="flex flex-col-reverse xs:flex-row justify-between gap-3 md:gap-4">
|
<div :class="cn('flex flex-col-reverse xs:!flex-row justify-between gap-3 md:gap-4')">
|
||||||
<div class="flex flex-col-reverse xs:flex-row xs:justify-start gap-3 md:gap-4">
|
<div :class="cn('flex flex-col-reverse xs:!flex-row xs:justify-start gap-3 md:gap-4')">
|
||||||
<!-- Back to changelog button (when navigated away) -->
|
<!-- Back to changelog button (when navigated away) -->
|
||||||
<BrandButton
|
<BrandButton
|
||||||
v-if="hasNavigated && docsChangelogUrl"
|
v-if="hasNavigated && docsChangelogUrl"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
KeyIcon,
|
KeyIcon,
|
||||||
XMarkIcon,
|
XMarkIcon,
|
||||||
} from '@heroicons/vue/24/solid';
|
} from '@heroicons/vue/24/solid';
|
||||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
import { BrandButton, BrandLoading, cn } from '@unraid/ui';
|
||||||
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
||||||
|
|
||||||
import type { BrandButtonProps } from '@unraid/ui';
|
import type { BrandButtonProps } from '@unraid/ui';
|
||||||
@@ -276,7 +276,7 @@ const modalWidth = computed(() => {
|
|||||||
<template v-if="renderMainSlot" #main>
|
<template v-if="renderMainSlot" #main>
|
||||||
<BrandLoading v-if="checkForUpdatesLoading" class="w-[150px] mx-auto" />
|
<BrandLoading v-if="checkForUpdatesLoading" class="w-[150px] mx-auto" />
|
||||||
<div v-else class="flex flex-col gap-y-4">
|
<div v-else class="flex flex-col gap-y-4">
|
||||||
<div v-if="extraLinks.length > 0" class="flex flex-col xs:flex-row justify-center gap-2">
|
<div v-if="extraLinks.length > 0" :class="cn('flex flex-col xs:!flex-row justify-center gap-2')">
|
||||||
<BrandButton
|
<BrandButton
|
||||||
v-for="item in extraLinks"
|
v-for="item in extraLinks"
|
||||||
:key="item.text"
|
:key="item.text"
|
||||||
@@ -335,13 +335,12 @@ const modalWidth = computed(() => {
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div
|
<div
|
||||||
class="w-full flex gap-2 mx-auto"
|
:class="cn(
|
||||||
:class="{
|
'w-full flex gap-2 mx-auto',
|
||||||
'flex-col-reverse xs:flex-row justify-between': actionButtons,
|
actionButtons ? 'flex-col-reverse xs:!flex-row justify-between' : 'justify-center'
|
||||||
'justify-center': !actionButtons,
|
)"
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<div class="flex flex-col-reverse xs:flex-row justify-start gap-2">
|
<div :class="cn('flex flex-col-reverse xs:!flex-row justify-start gap-2')">
|
||||||
<BrandButton
|
<BrandButton
|
||||||
variant="underline-hover-red"
|
variant="underline-hover-red"
|
||||||
:icon="XMarkIcon"
|
:icon="XMarkIcon"
|
||||||
@@ -355,7 +354,7 @@ const modalWidth = computed(() => {
|
|||||||
@click="accountStore.updateOs()"
|
@click="accountStore.updateOs()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="actionButtons" class="flex flex-col xs:flex-row justify-end gap-2">
|
<div v-if="actionButtons" :class="cn('flex flex-col xs:!flex-row justify-end gap-2')">
|
||||||
<BrandButton
|
<BrandButton
|
||||||
v-for="item in actionButtons"
|
v-for="item in actionButtons"
|
||||||
:key="item.text"
|
:key="item.text"
|
||||||
|
|||||||
@@ -130,9 +130,3 @@ const downgradeButton = ref<UserProfileLink>({
|
|||||||
</div>
|
</div>
|
||||||
</CardWrapper>
|
</CardWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -262,9 +262,3 @@ watchEffect(() => {
|
|||||||
</div>
|
</div>
|
||||||
</CardWrapper>
|
</CardWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -121,9 +121,3 @@ watchEffect(() => {
|
|||||||
</div>
|
</div>
|
||||||
</CardWrapper>
|
</CardWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
|
|||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useClipboard } from '@vueuse/core';
|
import { useClipboard } from '@vueuse/core';
|
||||||
|
|
||||||
import { DropdownMenu } from '@unraid/ui';
|
import { DropdownMenu, cn } from '@unraid/ui';
|
||||||
import { devConfig } from '~/helpers/env';
|
import { devConfig } from '~/helpers/env';
|
||||||
|
|
||||||
import type { Server } from '~/types/server';
|
import type { Server } from '~/types/server';
|
||||||
@@ -109,10 +109,10 @@ onMounted(() => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="text-xs text-header-text-secondary text-right font-semibold leading-normal relative z-10 flex flex-wrap items-baseline justify-end gap-x-1 xs:flex-row xs:gap-x-4"
|
:class="cn('text-xs text-header-text-secondary text-right font-semibold leading-normal relative z-10 flex flex-wrap xs:!flex-row items-baseline justify-end gap-x-1 xs:gap-x-4')"
|
||||||
>
|
>
|
||||||
<UpcUptimeExpire :as="'span'" :t="t" class="text-xs" />
|
<UpcUptimeExpire :as="'span'" :t="t" class="text-xs" />
|
||||||
<span class="hidden xs:block">•</span>
|
<span class="hidden xs:!block">•</span>
|
||||||
<UpcServerState :t="t" class="text-xs" />
|
<UpcServerState :t="t" class="text-xs" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ onMounted(() => {
|
|||||||
class="text-md sm:text-lg relative flex flex-col-reverse items-end md:flex-row border-0 text-header-text-primary"
|
class="text-md sm:text-lg relative flex flex-col-reverse items-end md:flex-row border-0 text-header-text-primary"
|
||||||
>
|
>
|
||||||
<template v-if="description && theme?.descriptionShow">
|
<template v-if="description && theme?.descriptionShow">
|
||||||
<span class="text-right text-xs sm:text-lg hidden 2xs:block" v-html="description" />
|
<span class="text-right text-xs sm:text-lg hidden 2xs:!block" v-html="description" />
|
||||||
<span class="text-header-text-secondary hidden md:inline-block px-2">•</span>
|
<span class="text-header-text-secondary hidden md:!inline-block px-2">•</span>
|
||||||
</template>
|
</template>
|
||||||
<button
|
<button
|
||||||
v-if="lanIp"
|
v-if="lanIp"
|
||||||
@@ -164,57 +164,3 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -410,57 +410,3 @@ const showUpdateEligibility = computed(() => {
|
|||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -57,74 +57,3 @@ const showExpireTime = computed(
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
.DropdownWrapper_blip {
|
|
||||||
box-shadow: var(--ring-offset-shadow), var(--ring-shadow), var(--shadow-foreground);
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
@apply absolute z-20 block;
|
|
||||||
|
|
||||||
content: '';
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
top: -10px;
|
|
||||||
right: 42px;
|
|
||||||
border-right: 11px solid transparent;
|
|
||||||
border-bottom: 11px solid var(--color-popover);
|
|
||||||
border-left: 11px solid transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unraid_mark_2,
|
|
||||||
.unraid_mark_4 {
|
|
||||||
animation: mark_2 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_3 {
|
|
||||||
animation: mark_3 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_6,
|
|
||||||
.unraid_mark_8 {
|
|
||||||
animation: mark_6 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
.unraid_mark_7 {
|
|
||||||
animation: mark_7 1.5s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mark_2 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_3 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_6 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(40px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes mark_7 {
|
|
||||||
50% {
|
|
||||||
transform: translateY(62px);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const upgradeAction = computed((): ServerStateDataAction | undefined => {
|
|||||||
|
|
||||||
<template v-if="purchaseAction">
|
<template v-if="purchaseAction">
|
||||||
<UpcServerStateBuy
|
<UpcServerStateBuy
|
||||||
class="text-orange-dark relative top-px hidden sm:block"
|
class="text-orange-dark relative top-px hidden sm:!block"
|
||||||
:title="t('Purchase Key')"
|
:title="t('Purchase Key')"
|
||||||
@click="purchaseAction.click?.()"
|
@click="purchaseAction.click?.()"
|
||||||
>{{ t('Purchase') }}</UpcServerStateBuy>
|
>{{ t('Purchase') }}</UpcServerStateBuy>
|
||||||
|
|||||||
@@ -79,9 +79,3 @@ watchEffect(async () => {
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style >
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import { createI18n } from 'vue-i18n';
|
|||||||
import type { App } from 'vue';
|
import type { App } from 'vue';
|
||||||
import { DefaultApolloClient } from '@vue/apollo-composable';
|
import { DefaultApolloClient } from '@vue/apollo-composable';
|
||||||
|
|
||||||
|
// Import Tailwind CSS for web components shadow DOM injection
|
||||||
|
import tailwindStyles from '~/assets/main.css?inline';
|
||||||
|
|
||||||
import en_US from '~/locales/en_US.json';
|
import en_US from '~/locales/en_US.json';
|
||||||
import { createHtmlEntityDecoder } from '~/helpers/i18n-utils';
|
import { createHtmlEntityDecoder } from '~/helpers/i18n-utils';
|
||||||
import { globalPinia } from '~/store/globalPinia';
|
import { globalPinia } from '~/store/globalPinia';
|
||||||
@@ -46,4 +49,19 @@ export default function (Vue: App) {
|
|||||||
|
|
||||||
// Provide Apollo client for all web components
|
// Provide Apollo client for all web components
|
||||||
Vue.provide(DefaultApolloClient, client);
|
Vue.provide(DefaultApolloClient, client);
|
||||||
}
|
|
||||||
|
// Inject Tailwind CSS into the shadow DOM
|
||||||
|
Vue.mixin({
|
||||||
|
mounted() {
|
||||||
|
if (typeof window !== 'undefined' && this.$el) {
|
||||||
|
const shadowRoot = this.$el.getRootNode();
|
||||||
|
if (shadowRoot && shadowRoot !== document && !shadowRoot.querySelector('style[data-tailwind]')) {
|
||||||
|
const styleElement = document.createElement('style');
|
||||||
|
styleElement.setAttribute('data-tailwind', 'true');
|
||||||
|
styleElement.textContent = tailwindStyles;
|
||||||
|
shadowRoot.prepend(styleElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
+32
-91
@@ -34,6 +34,16 @@ console.log(dropConsole ? 'WARN: Console logs are disabled' : 'INFO: Console log
|
|||||||
|
|
||||||
const assetsDir = path.join(__dirname, '../api/dev/webGui/');
|
const assetsDir = path.join(__dirname, '../api/dev/webGui/');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tag configuration
|
||||||
|
*/
|
||||||
|
const createWebComponentTag = (name: string, path: string, appContext: string) => ({
|
||||||
|
async: false,
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
appContext
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared terser options for consistent minification
|
* Shared terser options for consistent minification
|
||||||
*/
|
*/
|
||||||
@@ -190,99 +200,30 @@ export default defineNuxtConfig({
|
|||||||
{
|
{
|
||||||
name: 'UnraidComponents',
|
name: 'UnraidComponents',
|
||||||
viteExtend(config: UserConfig) {
|
viteExtend(config: UserConfig) {
|
||||||
return applySharedViteConfig(config, true);
|
const sharedConfig = applySharedViteConfig(config, true);
|
||||||
|
|
||||||
|
// Optimize CSS while keeping it inlined for functionality
|
||||||
|
if (!sharedConfig.css) sharedConfig.css = {};
|
||||||
|
sharedConfig.css.devSourcemap = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
|
return sharedConfig;
|
||||||
},
|
},
|
||||||
tags: [
|
tags: [
|
||||||
{
|
createWebComponentTag('UnraidAuth', '@/components/Auth.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
async: false,
|
createWebComponentTag('UnraidConnectSettings', '@/components/ConnectSettings/ConnectSettings.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
name: 'UnraidAuth',
|
createWebComponentTag('UnraidDownloadApiLogs', '@/components/DownloadApiLogs.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
path: '@/components/Auth.ce',
|
createWebComponentTag('UnraidHeaderOsVersion', '@/components/HeaderOsVersion.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
createWebComponentTag('UnraidModals', '@/components/Modals.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
},
|
createWebComponentTag('UnraidUserProfile', '@/components/UserProfile.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
{
|
createWebComponentTag('UnraidUpdateOs', '@/components/UpdateOs.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
async: false,
|
createWebComponentTag('UnraidDowngradeOs', '@/components/DowngradeOs.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
name: 'UnraidConnectSettings',
|
createWebComponentTag('UnraidRegistration', '@/components/Registration.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
path: '@/components/ConnectSettings/ConnectSettings.ce',
|
createWebComponentTag('UnraidWanIpCheck', '@/components/WanIpCheck.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
createWebComponentTag('UnraidWelcomeModal', '@/components/Activation/WelcomeModal.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
},
|
createWebComponentTag('UnraidSsoButton', '@/components/SsoButton.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
{
|
createWebComponentTag('UnraidLogViewer', '@/components/Logs/LogViewer.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
async: false,
|
createWebComponentTag('UnraidThemeSwitcher', '@/components/ThemeSwitcher.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
name: 'UnraidDownloadApiLogs',
|
createWebComponentTag('UnraidApiKeyManager', '@/components/ApiKeyPage.ce', '@/components/Wrapper/web-component-plugins'),
|
||||||
path: '@/components/DownloadApiLogs.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidHeaderOsVersion',
|
|
||||||
path: '@/components/HeaderOsVersion.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidModals',
|
|
||||||
path: '@/components/Modals.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidUserProfile',
|
|
||||||
path: '@/components/UserProfile.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidUpdateOs',
|
|
||||||
path: '@/components/UpdateOs.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidDowngradeOs',
|
|
||||||
path: '@/components/DowngradeOs.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidRegistration',
|
|
||||||
path: '@/components/Registration.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidWanIpCheck',
|
|
||||||
path: '@/components/WanIpCheck.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidWelcomeModal',
|
|
||||||
path: '@/components/Activation/WelcomeModal.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidSsoButton',
|
|
||||||
path: '@/components/SsoButton.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidLogViewer',
|
|
||||||
path: '@/components/Logs/LogViewer.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidThemeSwitcher',
|
|
||||||
path: '@/components/ThemeSwitcher.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
async: false,
|
|
||||||
name: 'UnraidApiKeyManager',
|
|
||||||
path: '@/components/ApiKeyPage.ce',
|
|
||||||
appContext: '@/components/Wrapper/web-component-plugins',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
+2
-1
@@ -13,11 +13,12 @@
|
|||||||
"prebuild:dev": "pnpm predev",
|
"prebuild:dev": "pnpm predev",
|
||||||
"build:dev": "nuxi build --dotenv .env.staging && pnpm run manifest-ts && pnpm run deploy-to-unraid:dev",
|
"build:dev": "nuxi build --dotenv .env.staging && pnpm run manifest-ts && pnpm run deploy-to-unraid:dev",
|
||||||
"build:webgui": "pnpm run type-check && nuxi build --dotenv .env.production && pnpm run manifest-ts && pnpm run copy-to-webgui-repo",
|
"build:webgui": "pnpm run type-check && nuxi build --dotenv .env.production && pnpm run manifest-ts && pnpm run copy-to-webgui-repo",
|
||||||
"build": "NODE_ENV=production nuxi build --dotenv .env.production && pnpm run manifest-ts",
|
"build": "NODE_ENV=production nuxi build --dotenv .env.production && pnpm run manifest-ts && pnpm run validate:css",
|
||||||
"prebuild:watch": "pnpm predev",
|
"prebuild:watch": "pnpm predev",
|
||||||
"build:watch": "nuxi build --dotenv .env.production --watch && pnpm run manifest-ts",
|
"build:watch": "nuxi build --dotenv .env.production --watch && pnpm run manifest-ts",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"manifest-ts": "node ./scripts/add-timestamp-webcomponent-manifest.js",
|
"manifest-ts": "node ./scripts/add-timestamp-webcomponent-manifest.js",
|
||||||
|
"validate:css": "node ./scripts/validate-custom-elements-css.js",
|
||||||
"// Deployment": "",
|
"// Deployment": "",
|
||||||
"unraid:deploy": "pnpm build:dev",
|
"unraid:deploy": "pnpm build:dev",
|
||||||
"deploy-to-unraid:dev": "./scripts/deploy-dev.sh",
|
"deploy-to-unraid:dev": "./scripts/deploy-dev.sh",
|
||||||
|
|||||||
@@ -220,17 +220,3 @@ watch(
|
|||||||
<Toaster rich-colors close-button />
|
<Toaster rich-colors close-button />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Import unraid-ui globals first */
|
|
||||||
@import '@unraid/ui/styles';
|
|
||||||
@import '~/assets/main.css';
|
|
||||||
|
|
||||||
code {
|
|
||||||
@apply rounded-lg bg-gray-200 p-1 text-black shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
@apply overflow-x-scroll py-3;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively find JS files in a directory
|
||||||
|
*/
|
||||||
|
function findJSFiles(dir, jsFiles = []) {
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
return jsFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = fs.readdirSync(dir);
|
||||||
|
for (const item of items) {
|
||||||
|
const fullPath = path.join(dir, item);
|
||||||
|
const stat = fs.statSync(fullPath);
|
||||||
|
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
findJSFiles(fullPath, jsFiles);
|
||||||
|
} else if (item.endsWith('.js')) {
|
||||||
|
jsFiles.push(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that Tailwind CSS styles are properly inlined in the JavaScript bundle
|
||||||
|
*/
|
||||||
|
function validateCustomElementsCSS() {
|
||||||
|
console.log('🔍 Validating custom elements JS bundle includes inlined Tailwind styles...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Find the custom elements JS files
|
||||||
|
const customElementsDir = '.nuxt/nuxt-custom-elements/dist';
|
||||||
|
const jsFiles = findJSFiles(customElementsDir);
|
||||||
|
|
||||||
|
if (jsFiles.length === 0) {
|
||||||
|
throw new Error('No custom elements JS files found in ' + customElementsDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the largest JS file (likely the main bundle with inlined CSS)
|
||||||
|
const jsFile = jsFiles.reduce((largest, current) => {
|
||||||
|
const currentSize = fs.statSync(current).size;
|
||||||
|
const largestSize = fs.statSync(largest).size;
|
||||||
|
return currentSize > largestSize ? current : largest;
|
||||||
|
});
|
||||||
|
console.log(`📁 Checking JS bundle: ${jsFile}`);
|
||||||
|
|
||||||
|
// Read the JS content
|
||||||
|
const jsContent = fs.readFileSync(jsFile, 'utf8');
|
||||||
|
|
||||||
|
// Define required Tailwind indicators (looking for inlined CSS in JS)
|
||||||
|
const requiredIndicators = [
|
||||||
|
{
|
||||||
|
name: 'Tailwind utility classes (inline)',
|
||||||
|
pattern: /\.flex\s*\{[^}]*display:\s*flex/,
|
||||||
|
description: 'Basic Tailwind utility classes inlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tailwind margin utilities (inline)',
|
||||||
|
pattern: /\.m-\d+\s*\{[^}]*margin:/,
|
||||||
|
description: 'Tailwind margin utilities inlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tailwind padding utilities (inline)',
|
||||||
|
pattern: /\.p-\d+\s*\{[^}]*padding:/,
|
||||||
|
description: 'Tailwind padding utilities inlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tailwind color utilities (inline)',
|
||||||
|
pattern: /\.text-\w+\s*\{[^}]*color:/,
|
||||||
|
description: 'Tailwind text color utilities inlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tailwind background utilities (inline)',
|
||||||
|
pattern: /\.bg-\w+\s*\{[^}]*background/,
|
||||||
|
description: 'Tailwind background utilities inlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'CSS custom properties',
|
||||||
|
pattern: /--[\w-]+:\s*[^;]+;/,
|
||||||
|
description: 'CSS custom properties (variables)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Responsive breakpoints',
|
||||||
|
pattern: /@media\s*\([^)]*min-width/,
|
||||||
|
description: 'Responsive media queries'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'CSS reset styles',
|
||||||
|
pattern: /\*[^}]*box-sizing|box-sizing[^}]*border-box/,
|
||||||
|
description: 'Tailwind CSS reset/normalize styles'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate each indicator
|
||||||
|
const results = [];
|
||||||
|
let allPassed = true;
|
||||||
|
|
||||||
|
for (const indicator of requiredIndicators) {
|
||||||
|
const found = indicator.pattern.test(jsContent);
|
||||||
|
results.push({
|
||||||
|
name: indicator.name,
|
||||||
|
description: indicator.description,
|
||||||
|
passed: found
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
allPassed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report results
|
||||||
|
console.log('\n📊 Validation Results:');
|
||||||
|
console.log('====================');
|
||||||
|
|
||||||
|
for (const result of results) {
|
||||||
|
const status = result.passed ? '✅' : '❌';
|
||||||
|
console.log(`${status} ${result.name}`);
|
||||||
|
if (!result.passed) {
|
||||||
|
console.log(` └─ Missing: ${result.description}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File size check
|
||||||
|
const fileSizeKB = Math.round(fs.statSync(jsFile).size / 1024);
|
||||||
|
console.log(`\n📏 JS bundle size: ${fileSizeKB} KB`);
|
||||||
|
|
||||||
|
if (fileSizeKB < 1000) {
|
||||||
|
console.log('⚠️ WARNING: JS bundle seems too small, inlined Tailwind styles might not be included');
|
||||||
|
allPassed = false;
|
||||||
|
} else {
|
||||||
|
console.log('✅ JS bundle size looks good');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final result
|
||||||
|
if (allPassed) {
|
||||||
|
console.log('\n🎉 SUCCESS: All Tailwind styles are properly inlined in the JS bundle!');
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
console.log('\n❌ FAILURE: Some Tailwind styles are missing from the JS bundle!');
|
||||||
|
console.log('\n💡 This might indicate:');
|
||||||
|
console.log(' - The CSS inline import in viteExtend is not working properly');
|
||||||
|
console.log(' - Tailwind configuration is not being processed');
|
||||||
|
console.log(' - CSS is not being injected into shadow DOM components');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('\n❌ ERROR during validation:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the validation
|
||||||
|
validateCustomElementsCSS();
|
||||||
Reference in New Issue
Block a user