@venix-sistemas/jade 1.0.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 +481 -0
- package/dist/module.d.mts +26 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +249 -0
- package/dist/runtime/components/VenixIcon.d.vue.ts +14 -0
- package/dist/runtime/components/VenixIcon.vue +37 -0
- package/dist/runtime/components/VenixIcon.vue.d.ts +14 -0
- package/dist/runtime/components/VenixThemeSwitcher.d.vue.ts +9 -0
- package/dist/runtime/components/VenixThemeSwitcher.vue +191 -0
- package/dist/runtime/components/VenixThemeSwitcher.vue.d.ts +9 -0
- package/dist/runtime/composables/useThemeColors.d.ts +10 -0
- package/dist/runtime/composables/useThemeColors.js +25 -0
- package/dist/runtime/composables/useThemeCookies.d.ts +7 -0
- package/dist/runtime/composables/useThemeCookies.js +33 -0
- package/dist/runtime/composables/useThemeLocale.d.ts +12 -0
- package/dist/runtime/composables/useThemeLocale.js +87 -0
- package/dist/runtime/composables/useThemeSeasonal.d.ts +4 -0
- package/dist/runtime/composables/useThemeSeasonal.js +7 -0
- package/dist/runtime/composables/useVenixIcon.d.ts +3 -0
- package/dist/runtime/composables/useVenixIcon.js +11 -0
- package/dist/runtime/composables/useVenixTheme.d.ts +33 -0
- package/dist/runtime/composables/useVenixTheme.js +186 -0
- package/dist/runtime/nitro/theme-init.d.ts +2 -0
- package/dist/runtime/nitro/theme-init.js +11 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.js +3 -0
- package/dist/runtime/plugins/theme-init.server.d.ts +2 -0
- package/dist/runtime/plugins/theme-init.server.js +37 -0
- package/dist/runtime/plugins/vuetify-theme.d.ts +2 -0
- package/dist/runtime/plugins/vuetify-theme.js +42 -0
- package/dist/runtime/public/fonts/Iceberg/Iceberg-Regular.woff2 +0 -0
- package/dist/runtime/public/images/ui/cursor/cursor-hand.png +0 -0
- package/dist/runtime/public/images/ui/cursor/cursor-text.png +0 -0
- package/dist/runtime/public/images/ui/cursor/cursor.png +0 -0
- package/dist/runtime/scripts/theme-init.d.ts +27 -0
- package/dist/runtime/scripts/theme-init.js +89 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/shared/constants.d.ts +28 -0
- package/dist/shared/constants.js +40 -0
- package/dist/shared/css/colors.d.ts +2 -0
- package/dist/shared/css/colors.js +19 -0
- package/dist/shared/css/cursor.d.ts +2 -0
- package/dist/shared/css/cursor.js +74 -0
- package/dist/shared/css/index.d.ts +8 -0
- package/dist/shared/css/index.js +31 -0
- package/dist/shared/css/scrollbar.d.ts +2 -0
- package/dist/shared/css/scrollbar.js +51 -0
- package/dist/shared/css/transition.d.ts +2 -0
- package/dist/shared/css/transition.js +20 -0
- package/dist/shared/css/typography.d.ts +3 -0
- package/dist/shared/css/typography.js +62 -0
- package/dist/shared/theme.json +193 -0
- package/dist/shared/types/color-options.d.ts +14 -0
- package/dist/shared/types/color-options.js +0 -0
- package/dist/shared/types/colors.d.ts +38 -0
- package/dist/shared/types/colors.js +0 -0
- package/dist/shared/types/cursor.d.ts +7 -0
- package/dist/shared/types/cursor.js +0 -0
- package/dist/shared/types/icon.d.ts +7 -0
- package/dist/shared/types/icon.js +0 -0
- package/dist/shared/types/index.d.ts +10 -0
- package/dist/shared/types/index.js +1 -0
- package/dist/shared/types/runtime-config.d.ts +33 -0
- package/dist/shared/types/runtime-config.js +1 -0
- package/dist/shared/types/scrollbar.d.ts +12 -0
- package/dist/shared/types/scrollbar.js +0 -0
- package/dist/shared/types/theme.d.ts +11 -0
- package/dist/shared/types/theme.js +0 -0
- package/dist/shared/types/translation.d.ts +16 -0
- package/dist/shared/types/translation.js +0 -0
- package/dist/shared/types/typography.d.ts +15 -0
- package/dist/shared/types/typography.js +0 -0
- package/dist/shared/types/vuetify.d.ts +3 -0
- package/dist/shared/types/vuetify.js +0 -0
- package/dist/shared/unocss-preset.d.ts +32 -0
- package/dist/shared/unocss-preset.js +13 -0
- package/dist/shared/utils/consent.d.ts +8 -0
- package/dist/shared/utils/consent.js +12 -0
- package/dist/shared/utils/icon-refs.d.ts +10 -0
- package/dist/shared/utils/icon-refs.js +24 -0
- package/dist/shared/utils/icon.d.ts +27 -0
- package/dist/shared/utils/icon.js +20 -0
- package/dist/shared/utils/index.d.ts +9 -0
- package/dist/shared/utils/index.js +12 -0
- package/dist/shared/utils/load.d.ts +4 -0
- package/dist/shared/utils/load.js +24 -0
- package/dist/shared/utils/normalize.d.ts +20 -0
- package/dist/shared/utils/normalize.js +38 -0
- package/dist/shared/utils/options.d.ts +10 -0
- package/dist/shared/utils/options.js +12 -0
- package/dist/shared/utils/theme-config.d.ts +14 -0
- package/dist/shared/utils/theme-config.js +22 -0
- package/dist/shared/utils/theme-resolve.d.ts +24 -0
- package/dist/shared/utils/theme-resolve.js +45 -0
- package/dist/types.d.mts +3 -0
- package/package.json +100 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface FontConfig {
|
|
2
|
+
name: string;
|
|
3
|
+
preload: boolean;
|
|
4
|
+
sources: {
|
|
5
|
+
woff2: string;
|
|
6
|
+
};
|
|
7
|
+
weight: string;
|
|
8
|
+
style: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TypographyConfig {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
defaultFonts: string;
|
|
13
|
+
fontSize: string;
|
|
14
|
+
customFonts: FontConfig[];
|
|
15
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface VenixUnoPreset {
|
|
2
|
+
name: string;
|
|
3
|
+
theme: {
|
|
4
|
+
colors: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* UnoCSS preset that exposes the theme's colors as `theme.colors` (`primary`,
|
|
9
|
+
* `secondary`, `background2`, ...), all pointing at the CSS vars this module
|
|
10
|
+
* generates (`--color-primary`, ...) — enables utilities like `text-primary`,
|
|
11
|
+
* `bg-background2/80` or `border-accent`.
|
|
12
|
+
*
|
|
13
|
+
* Must be added manually to your `uno.config.ts`:
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { defineConfig } from 'unocss'
|
|
17
|
+
* import { venixUnoPreset } from '@venix-sistemas/jade/unocss'
|
|
18
|
+
*
|
|
19
|
+
* export default defineConfig({
|
|
20
|
+
* presets: [venixUnoPreset()],
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* Not injected automatically: `@unocss/nuxt` reloads `uno.config.ts` from
|
|
25
|
+
* disk on its own (to support HMR) and shallow-merges that file against any
|
|
26
|
+
* config injected via hook — that silently discards a hook-injected `theme`
|
|
27
|
+
* whenever the consumer's `uno.config.ts` already declares its own `theme`
|
|
28
|
+
* key (even one without any colors). As a preset inside the `presets` array
|
|
29
|
+
* itself, these colors become part of what's actually read from the file and
|
|
30
|
+
* survive that merge.
|
|
31
|
+
*/
|
|
32
|
+
export declare function venixUnoPreset(): VenixUnoPreset;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { COLOR_PROPERTIES } from "./constants.js";
|
|
2
|
+
export function venixUnoPreset() {
|
|
3
|
+
const colors = {
|
|
4
|
+
inverse: "var(--color-inverse)"
|
|
5
|
+
};
|
|
6
|
+
for (const property of COLOR_PROPERTIES) {
|
|
7
|
+
colors[property] = `var(--color-${property})`;
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
name: "venix-theme",
|
|
11
|
+
theme: { colors }
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads functional-cookie consent from `localStorage` under
|
|
3
|
+
* `COOKIE_CONSENT_STORAGE_KEY` — never written by this module on its own
|
|
4
|
+
* (only via `persistence.grant()/revoke()`), and can also come from the
|
|
5
|
+
* consumer app's own cookie-consent UI, as long as it writes the same shape
|
|
6
|
+
* (`{ functionality: boolean }`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function hasCookieConsent(): boolean;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { COOKIE_CONSENT_STORAGE_KEY } from "../constants.js";
|
|
2
|
+
export function hasCookieConsent() {
|
|
3
|
+
if (typeof localStorage === "undefined") return false;
|
|
4
|
+
const consentData = localStorage.getItem(COOKIE_CONSENT_STORAGE_KEY);
|
|
5
|
+
if (!consentData) return false;
|
|
6
|
+
try {
|
|
7
|
+
const consent = JSON.parse(consentData);
|
|
8
|
+
return consent?.functionality === true;
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ThemeColors } from '../types/colors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the Iconify `collection:icon` references used in color themes
|
|
4
|
+
* (`icon.css` / `icon.svg`) and in the configured icon aliases, grouped by
|
|
5
|
+
* collection. Lets each collection be bundled with only the icons actually
|
|
6
|
+
* used (tree-shaking) instead of the whole collection — essential for large
|
|
7
|
+
* collections like `mdi` (thousands of icons) used for only a handful of
|
|
8
|
+
* icons in the default theme.
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractIconRefs(themes: Record<string, ThemeColors>, aliases: Record<string, string>): Map<string, Set<string>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const ICONIFY_NAME = /^([\w-]+):([\w-]+)$/;
|
|
2
|
+
function addRef(refs, value) {
|
|
3
|
+
const match = value ? ICONIFY_NAME.exec(value.trim()) : null;
|
|
4
|
+
if (!match) return;
|
|
5
|
+
const collection = match[1];
|
|
6
|
+
const icon = match[2];
|
|
7
|
+
const set = refs.get(collection) ?? /* @__PURE__ */ new Set();
|
|
8
|
+
set.add(icon);
|
|
9
|
+
refs.set(collection, set);
|
|
10
|
+
}
|
|
11
|
+
export function extractIconRefs(themes, aliases) {
|
|
12
|
+
const refs = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const theme of Object.values(themes)) {
|
|
14
|
+
const icon = theme.icon;
|
|
15
|
+
if (icon && typeof icon === "object") {
|
|
16
|
+
addRef(refs, icon.css);
|
|
17
|
+
addRef(refs, icon.svg);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
for (const value of Object.values(aliases)) {
|
|
21
|
+
addRef(refs, value);
|
|
22
|
+
}
|
|
23
|
+
return refs;
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ThemeIconFormats } from '../types/colors.js';
|
|
2
|
+
export type IconKind = 'emoji' | 'icon' | 'svg';
|
|
3
|
+
export interface ResolvedIcon {
|
|
4
|
+
kind: IconKind;
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolves an icon value to the correct rendering type:
|
|
9
|
+
* - inline SVG (starts with `<svg`)
|
|
10
|
+
* - Iconify icon name (`collection:name` format, e.g. `line-md:home`)
|
|
11
|
+
* - emoji/text (any other value)
|
|
12
|
+
*
|
|
13
|
+
* Aliases are resolved first, then the resulting value goes through the same
|
|
14
|
+
* detection — an alias can point to any of the three formats.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveIcon(input: string, aliases?: Record<string, string>): ResolvedIcon;
|
|
17
|
+
export type ThemeIconFormat = 'emote' | 'css' | 'svg';
|
|
18
|
+
export interface ResolvedThemeIcon {
|
|
19
|
+
format: ThemeIconFormat;
|
|
20
|
+
value: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves a color theme's icon (a legacy string, always emote, or a
|
|
24
|
+
* `ThemeIconFormats` with variants) to the preferred format, falling back to
|
|
25
|
+
* `emote` when the theme doesn't define the chosen format.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveThemeIcon(icon: string | ThemeIconFormats | undefined, preferred: ThemeIconFormat): ResolvedThemeIcon | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function resolveIcon(input, aliases = {}) {
|
|
2
|
+
const value = (aliases[input] ?? input).trim();
|
|
3
|
+
if (/^<svg[\s>]/i.test(value)) {
|
|
4
|
+
return { kind: "svg", value };
|
|
5
|
+
}
|
|
6
|
+
if (/^[\w-]+:[\w-]+$/.test(value)) {
|
|
7
|
+
return { kind: "icon", value };
|
|
8
|
+
}
|
|
9
|
+
return { kind: "emoji", value };
|
|
10
|
+
}
|
|
11
|
+
export function resolveThemeIcon(icon, preferred) {
|
|
12
|
+
if (!icon) return null;
|
|
13
|
+
if (typeof icon === "string") {
|
|
14
|
+
return { format: "emote", value: icon };
|
|
15
|
+
}
|
|
16
|
+
if (preferred !== "emote" && icon[preferred]) {
|
|
17
|
+
return { format: preferred, value: icon[preferred] };
|
|
18
|
+
}
|
|
19
|
+
return { format: "emote", value: icon.emote };
|
|
20
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { normalizeLocale, extractFirstLocale, normalizeColor, normalizeThemeName, } from './normalize.js';
|
|
2
|
+
export { resolveFeatureOption } from './options.js';
|
|
3
|
+
export { resolveIcon, resolveThemeIcon } from './icon.js';
|
|
4
|
+
export type { IconKind, ResolvedIcon, ThemeIconFormat, ResolvedThemeIcon } from './icon.js';
|
|
5
|
+
export { extractIconRefs } from './icon-refs.js';
|
|
6
|
+
export { hasCookieConsent } from './consent.js';
|
|
7
|
+
export { isColorTheme, getActiveSeasonalTheme, resolveThemePreference } from './theme-resolve.js';
|
|
8
|
+
export { buildResolvedTheme } from './theme-config.js';
|
|
9
|
+
export type { VenixRuntimeThemeConfig } from './theme-config.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export {
|
|
2
|
+
normalizeLocale,
|
|
3
|
+
extractFirstLocale,
|
|
4
|
+
normalizeColor,
|
|
5
|
+
normalizeThemeName
|
|
6
|
+
} from "./normalize.js";
|
|
7
|
+
export { resolveFeatureOption } from "./options.js";
|
|
8
|
+
export { resolveIcon, resolveThemeIcon } from "./icon.js";
|
|
9
|
+
export { extractIconRefs } from "./icon-refs.js";
|
|
10
|
+
export { hasCookieConsent } from "./consent.js";
|
|
11
|
+
export { isColorTheme, getActiveSeasonalTheme, resolveThemePreference } from "./theme-resolve.js";
|
|
12
|
+
export { buildResolvedTheme } from "./theme-config.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import defaultTheme from "../../shared/theme.json" with { type: "json" };
|
|
2
|
+
import { DEFAULT_LOCALE } from "../constants.js";
|
|
3
|
+
import { normalizeLocale } from "./normalize.js";
|
|
4
|
+
export function loadTheme(_path) {
|
|
5
|
+
return defaultTheme;
|
|
6
|
+
}
|
|
7
|
+
export function extractLocales(theme) {
|
|
8
|
+
const locales = /* @__PURE__ */ new Set();
|
|
9
|
+
Object.values(theme.colors?.themes || {}).forEach((themeConfig) => {
|
|
10
|
+
if (themeConfig.translations) {
|
|
11
|
+
Object.keys(themeConfig.translations).forEach((locale) => {
|
|
12
|
+
locales.add(normalizeLocale(locale));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return Array.from(locales);
|
|
17
|
+
}
|
|
18
|
+
export function getDefaultLocale(theme) {
|
|
19
|
+
const locales = extractLocales(theme);
|
|
20
|
+
if (locales.includes("en-US")) return "en-US";
|
|
21
|
+
const firstLocale = locales[0];
|
|
22
|
+
if (firstLocale) return firstLocale;
|
|
23
|
+
return DEFAULT_LOCALE;
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes a locale to the standard format.
|
|
3
|
+
* E.g.: "pt" -> "pt-BR", "PT-br" -> "pt-BR"
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeLocale(locale: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts the first locale from an Accept-Language header.
|
|
8
|
+
* E.g.: "pt-BR,pt;q=0.9,en;q=0.8" -> "pt-BR"
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractFirstLocale(acceptLanguage: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes a hex color.
|
|
13
|
+
* E.g.: "fff" -> "#FFF", "ffffff" -> "#FFFFFF", "#fff" -> "#FFF"
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeColor(color: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Normalizes a theme name.
|
|
18
|
+
* E.g.: "dark" -> "Dark", "DARK" -> "Dark"
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeThemeName(name: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LOCALE_MAP, DEFAULT_LOCALE } from "../constants.js";
|
|
2
|
+
export function normalizeLocale(locale) {
|
|
3
|
+
if (!locale) return DEFAULT_LOCALE;
|
|
4
|
+
const lowerLocale = locale.toLowerCase();
|
|
5
|
+
if (lowerLocale.includes("-")) {
|
|
6
|
+
const parts = lowerLocale.split("-");
|
|
7
|
+
const base = parts[0];
|
|
8
|
+
const region = parts[1];
|
|
9
|
+
if (base && region) {
|
|
10
|
+
return `${base}-${region.toUpperCase()}`;
|
|
11
|
+
}
|
|
12
|
+
return base || lowerLocale;
|
|
13
|
+
}
|
|
14
|
+
return LOCALE_MAP[lowerLocale] || lowerLocale;
|
|
15
|
+
}
|
|
16
|
+
export function extractFirstLocale(acceptLanguage) {
|
|
17
|
+
if (!acceptLanguage) return null;
|
|
18
|
+
const parts = acceptLanguage.split(",");
|
|
19
|
+
if (parts.length === 0) return null;
|
|
20
|
+
const firstPart = parts[0];
|
|
21
|
+
if (!firstPart) return null;
|
|
22
|
+
const localeParts = firstPart.split(";");
|
|
23
|
+
if (localeParts.length === 0) return null;
|
|
24
|
+
const firstLocale = localeParts[0]?.trim();
|
|
25
|
+
return firstLocale || null;
|
|
26
|
+
}
|
|
27
|
+
export function normalizeColor(color) {
|
|
28
|
+
if (!color) return color;
|
|
29
|
+
color = color.trim();
|
|
30
|
+
if (!color.startsWith("#")) {
|
|
31
|
+
color = `#${color}`;
|
|
32
|
+
}
|
|
33
|
+
return color;
|
|
34
|
+
}
|
|
35
|
+
export function normalizeThemeName(name) {
|
|
36
|
+
if (!name) return name;
|
|
37
|
+
return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
|
|
38
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves a module option in `boolean | Partial<Config>` form against a base
|
|
3
|
+
* config. `false` disables the feature, an object enables it and merges in
|
|
4
|
+
* customizations, `true` forces the feature enabled (even if the base comes
|
|
5
|
+
* disabled, e.g. `theme.customCursor.enabled: false`), and `undefined` leaves
|
|
6
|
+
* the base config untouched.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveFeatureOption<T extends {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
}>(option: boolean | Partial<T> | undefined, base: T): T;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function resolveFeatureOption(option, base) {
|
|
2
|
+
if (option === false) {
|
|
3
|
+
return { ...base, enabled: false };
|
|
4
|
+
}
|
|
5
|
+
if (option === true) {
|
|
6
|
+
return { ...base, enabled: true };
|
|
7
|
+
}
|
|
8
|
+
if (typeof option === "object" && option !== null) {
|
|
9
|
+
return { ...base, ...option, enabled: option.enabled ?? true };
|
|
10
|
+
}
|
|
11
|
+
return base;
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ThemeConfig, ThemeColors } from '../types/index.js';
|
|
2
|
+
export interface VenixRuntimeThemeConfig {
|
|
3
|
+
defaultTheme?: string;
|
|
4
|
+
colorThemes?: Record<string, Partial<ThemeColors>>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Rebuilds the full `ThemeConfig` at runtime, layering `theme.json`
|
|
8
|
+
* (bundled with the module, with the "base" themes) with the customizations
|
|
9
|
+
* from `runtimeConfig.public.venixTheme` (resolved at build time from the
|
|
10
|
+
* module options in `nuxt.config`, see `module.ts`). Single implementation —
|
|
11
|
+
* used by the composable (`useVenixTheme`) and the SSR/Vuetify plugins, which
|
|
12
|
+
* used to each reimplement this merge their own way.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildResolvedTheme(runtimeThemeConfig?: VenixRuntimeThemeConfig): ThemeConfig;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import themeData from "../theme.json" with { type: "json" };
|
|
2
|
+
import { DEFAULT_THEME } from "../constants.js";
|
|
3
|
+
export function buildResolvedTheme(runtimeThemeConfig) {
|
|
4
|
+
const defaultColors = {
|
|
5
|
+
enabled: true,
|
|
6
|
+
defaults: true,
|
|
7
|
+
defaultColor: DEFAULT_THEME,
|
|
8
|
+
themes: {}
|
|
9
|
+
};
|
|
10
|
+
const baseColors = themeData.colors || defaultColors;
|
|
11
|
+
return {
|
|
12
|
+
...themeData,
|
|
13
|
+
colors: {
|
|
14
|
+
...baseColors,
|
|
15
|
+
defaultColor: runtimeThemeConfig?.defaultTheme || baseColors.defaultColor || DEFAULT_THEME,
|
|
16
|
+
themes: {
|
|
17
|
+
...baseColors.themes,
|
|
18
|
+
...runtimeThemeConfig?.colorThemes || {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ThemeColors } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* A theme only really counts as a "color" theme if it has at least one real
|
|
4
|
+
* color — placeholder entries like `'system'` (only used to show
|
|
5
|
+
* "Automatic" in the UI, see `theme.json`) have `translations`/`icon` but no
|
|
6
|
+
* color, and don't count.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isColorTheme(themeConfig: ThemeColors | undefined): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Active seasonal theme for today. When `prefersDark` is given, only returns
|
|
11
|
+
* themes matching that mode (light/dark); when omitted, returns the first
|
|
12
|
+
* active seasonal theme regardless of mode.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getActiveSeasonalTheme(themes: Record<string, ThemeColors>, prefersDark?: boolean, now?: Date): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Resolves a theme preference (`'system'`, a theme name, or empty) to the
|
|
17
|
+
* concrete color theme that should be applied. Single implementation of this
|
|
18
|
+
* rule — used by `useVenixTheme`/`useThemeSeasonal` and the SSR plugin
|
|
19
|
+
* (`theme-init.server.ts`). The pre-hydration script
|
|
20
|
+
* (`runtime/scripts/theme-init.ts`) is the one documented exception: it has
|
|
21
|
+
* to run as a self-contained IIFE (no imports), so it deliberately duplicates
|
|
22
|
+
* this logic — keep the two in sync when changing either.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveThemePreference(preference: string | undefined, themes: Record<string, ThemeColors>, defaultTheme: string, prefersDark: boolean): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export function isColorTheme(themeConfig) {
|
|
2
|
+
if (!themeConfig) return false;
|
|
3
|
+
return !!themeConfig.primary || !!themeConfig.background;
|
|
4
|
+
}
|
|
5
|
+
function parseDatePart(value) {
|
|
6
|
+
const parts = value.split("-").map(Number);
|
|
7
|
+
if (parts.length !== 2) return null;
|
|
8
|
+
const [month, day] = parts;
|
|
9
|
+
if (month === void 0 || day === void 0) return null;
|
|
10
|
+
return [month, day];
|
|
11
|
+
}
|
|
12
|
+
function isDateInSeasonalRange(themeConfig, now) {
|
|
13
|
+
if (themeConfig.seasonal !== true || !themeConfig.dateRange) return false;
|
|
14
|
+
const start = parseDatePart(themeConfig.dateRange.start);
|
|
15
|
+
const end = parseDatePart(themeConfig.dateRange.end);
|
|
16
|
+
if (!start || !end) return false;
|
|
17
|
+
const current = (now.getMonth() + 1) * 100 + now.getDate();
|
|
18
|
+
const startNum = start[0] * 100 + start[1];
|
|
19
|
+
const endNum = end[0] * 100 + end[1];
|
|
20
|
+
return startNum <= endNum ? current >= startNum && current <= endNum : current >= startNum || current <= endNum;
|
|
21
|
+
}
|
|
22
|
+
export function getActiveSeasonalTheme(themes, prefersDark, now = /* @__PURE__ */ new Date()) {
|
|
23
|
+
for (const [themeName, themeConfig] of Object.entries(themes)) {
|
|
24
|
+
if (themeName === "system") continue;
|
|
25
|
+
if (!isColorTheme(themeConfig)) continue;
|
|
26
|
+
if (!isDateInSeasonalRange(themeConfig, now)) continue;
|
|
27
|
+
if (prefersDark !== void 0 && themeConfig.dark !== prefersDark) continue;
|
|
28
|
+
return themeName;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
export function resolveThemePreference(preference, themes, defaultTheme, prefersDark) {
|
|
33
|
+
let resolved;
|
|
34
|
+
if (preference === "system") {
|
|
35
|
+
resolved = getActiveSeasonalTheme(themes, prefersDark) || (prefersDark ? "dark" : "light");
|
|
36
|
+
} else if (preference && isColorTheme(themes[preference])) {
|
|
37
|
+
resolved = preference;
|
|
38
|
+
} else {
|
|
39
|
+
resolved = defaultTheme;
|
|
40
|
+
}
|
|
41
|
+
if (!isColorTheme(themes[resolved])) {
|
|
42
|
+
resolved = isColorTheme(themes[defaultTheme]) ? defaultTheme : "dark";
|
|
43
|
+
}
|
|
44
|
+
return resolved;
|
|
45
|
+
}
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@venix-sistemas/jade",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Complete color system for Nuxt: seasonal colors, automatic theme, SSR, Cookie Policy, cursor, scrollbar, etc...",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"nuxt",
|
|
7
|
+
"nuxt-module",
|
|
8
|
+
"nuxt-theme",
|
|
9
|
+
"jade",
|
|
10
|
+
"jade-theme",
|
|
11
|
+
"theme",
|
|
12
|
+
"theming",
|
|
13
|
+
"colors",
|
|
14
|
+
"dark-mode",
|
|
15
|
+
"seasonal-theme",
|
|
16
|
+
"typography",
|
|
17
|
+
"scrollbar",
|
|
18
|
+
"cursor",
|
|
19
|
+
"unocss",
|
|
20
|
+
"vuetify",
|
|
21
|
+
"iconify",
|
|
22
|
+
"i18n"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"type": "module",
|
|
26
|
+
"author": "Vinicius da Silva Viana <contato@venixsistemas.com>",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/Venix-Sistemas/jade.git"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/Venix-Sistemas/jade#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/Venix-Sistemas/jade/issues"
|
|
34
|
+
},
|
|
35
|
+
"private": false,
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"exports": {
|
|
40
|
+
".": {
|
|
41
|
+
"types": "./dist/types.d.mts",
|
|
42
|
+
"import": "./dist/module.mjs",
|
|
43
|
+
"exports": "./src/module.ts"
|
|
44
|
+
},
|
|
45
|
+
"./theme.json": "./dist/shared/theme.json",
|
|
46
|
+
"./unocss": {
|
|
47
|
+
"types": "./dist/shared/unocss-preset.d.ts",
|
|
48
|
+
"import": "./dist/shared/unocss-preset.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"main": "./dist/module.mjs",
|
|
52
|
+
"typesVersions": {
|
|
53
|
+
"*": {
|
|
54
|
+
".": [
|
|
55
|
+
"./dist/types.d.mts"
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist"
|
|
61
|
+
],
|
|
62
|
+
"workspaces": [
|
|
63
|
+
"playground"
|
|
64
|
+
],
|
|
65
|
+
"scripts": {
|
|
66
|
+
"prepack": "nuxt-module-build build",
|
|
67
|
+
"dev": "npm run dev:prepare && nuxt dev playground",
|
|
68
|
+
"dev:build": "nuxt build playground",
|
|
69
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
70
|
+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
71
|
+
"release:alpha": "npm run lint && npm run test && npm run prepack && changelogen --release --prerelease alpha && npm publish --tag alpha && git push --follow-tags",
|
|
72
|
+
"lint": "eslint .",
|
|
73
|
+
"test": "vitest run",
|
|
74
|
+
"test:watch": "vitest watch",
|
|
75
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"@iconify-json/line-md": "^1.2.16",
|
|
79
|
+
"@iconify-json/mdi": "^1.2.3",
|
|
80
|
+
"@iconify/utils": "^3.1.7",
|
|
81
|
+
"@nuxt/icon": "^2.5.1",
|
|
82
|
+
"@nuxt/kit": "^4.5.2"
|
|
83
|
+
},
|
|
84
|
+
"devDependencies": {
|
|
85
|
+
"@nuxt/devtools": "4.0.0-beta.3",
|
|
86
|
+
"@nuxt/eslint-config": "^1.17.0",
|
|
87
|
+
"@nuxt/module-builder": "^1.0.3",
|
|
88
|
+
"@nuxt/schema": "^4.5.2",
|
|
89
|
+
"@nuxt/test-utils": "^4.3.3",
|
|
90
|
+
"@nuxtjs/i18n": "10.6.0",
|
|
91
|
+
"@types/node": "latest",
|
|
92
|
+
"changelogen": "^0.6.2",
|
|
93
|
+
"eslint": "^10.12.0",
|
|
94
|
+
"nuxt": "^4.5.2",
|
|
95
|
+
"typescript": "7.0.2",
|
|
96
|
+
"vitest": "5.0.3",
|
|
97
|
+
"vue-tsc": "^3.3.12"
|
|
98
|
+
},
|
|
99
|
+
"packageManager": "pnpm@12.3.4"
|
|
100
|
+
}
|