moulify 1.0.0 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/module.d.mts +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +25 -2
- package/dist/runtime/components/MoulifyButton.vue +31 -9
- package/dist/runtime/plugin.js +81 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -34,6 +34,25 @@ export default defineNuxtConfig({
|
|
|
34
34
|
})
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
You can also use a config file in the project root. Create `.moulifyrc` or `.moulifyrc.json` (JSON). Options from `nuxt.config.ts` override the file.
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"primaryColor": "#fafafa"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or in `nuxt.config.ts`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
export default defineNuxtConfig({
|
|
49
|
+
modules: ['moulify'],
|
|
50
|
+
moulify: {
|
|
51
|
+
primaryColor: '#fafafa',
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
37
56
|
Use the button in any page or component:
|
|
38
57
|
|
|
39
58
|
```vue
|
|
@@ -42,6 +61,65 @@ Use the button in any page or component:
|
|
|
42
61
|
</template>
|
|
43
62
|
```
|
|
44
63
|
|
|
64
|
+
## SCSS helpers
|
|
65
|
+
|
|
66
|
+
The module provides a SCSS helpers file you can import in your app.
|
|
67
|
+
|
|
68
|
+
**Path** (from your project, e.g. in `nuxt.config.ts` via `vite.css.preprocessorOptions.scss.additionalData` or in any component):
|
|
69
|
+
|
|
70
|
+
- When developing the module: `moulify/src/runtime/assets/scss/helpers`
|
|
71
|
+
- From `node_modules`: ensure the package exposes this path or copy the file into your app’s `assets/scss`.
|
|
72
|
+
|
|
73
|
+
### 1. `rem($pixels)`
|
|
74
|
+
|
|
75
|
+
Converts pixels to `rem` (base 16px).
|
|
76
|
+
|
|
77
|
+
```scss
|
|
78
|
+
@use 'moulify/src/runtime/assets/scss/helpers' as moulify;
|
|
79
|
+
|
|
80
|
+
.my-class {
|
|
81
|
+
padding: moulify.rem(16); // 1rem
|
|
82
|
+
font-size: moulify.rem(14); // 0.875rem
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Primary color shades (50–900)
|
|
87
|
+
|
|
88
|
+
The plugin sets CSS variables from your configured `primaryColor`:
|
|
89
|
+
|
|
90
|
+
- `--moulify-primary` (same as 500)
|
|
91
|
+
- `--moulify-primary-50` … `--moulify-primary-900`
|
|
92
|
+
|
|
93
|
+
Use them anywhere:
|
|
94
|
+
|
|
95
|
+
```css
|
|
96
|
+
.card {
|
|
97
|
+
background: var(--moulify-primary-100);
|
|
98
|
+
border-color: var(--moulify-primary-300);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
In SCSS you can use the **`primary-shades($base-color)`** mixin to generate the same scale for a given color (e.g. for static styles or docs):
|
|
103
|
+
|
|
104
|
+
```scss
|
|
105
|
+
@use 'moulify/src/runtime/assets/scss/helpers' as moulify;
|
|
106
|
+
|
|
107
|
+
:root {
|
|
108
|
+
@include moulify.primary-shades(#fafafa);
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
And the **`primary($shade)`** function to reference a shade (default 500):
|
|
113
|
+
|
|
114
|
+
```scss
|
|
115
|
+
@use 'moulify/src/runtime/assets/scss/helpers' as moulify;
|
|
116
|
+
|
|
117
|
+
.button {
|
|
118
|
+
background: moulify.primary(500);
|
|
119
|
+
color: moulify.primary(900);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
45
123
|
## Contribution
|
|
46
124
|
|
|
47
125
|
<details>
|
package/dist/module.d.mts
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { defineNuxtModule, createResolver, addComponentsDir, addPlugin } from '@nuxt/kit';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
|
|
5
|
+
const CONFIG_FILES = [".moulifyrc", ".moulifyrc.json"];
|
|
6
|
+
const loadRcConfig = (rootDir) => {
|
|
7
|
+
for (const file of CONFIG_FILES) {
|
|
8
|
+
const path = join(rootDir, file);
|
|
9
|
+
if (existsSync(path)) {
|
|
10
|
+
try {
|
|
11
|
+
const content = readFileSync(path, "utf-8");
|
|
12
|
+
return JSON.parse(content);
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {};
|
|
18
|
+
};
|
|
3
19
|
const module$1 = defineNuxtModule({
|
|
4
20
|
meta: {
|
|
5
21
|
name: "moulify",
|
|
6
22
|
configKey: "moulify"
|
|
7
23
|
},
|
|
8
24
|
// Default configuration options of the Nuxt module
|
|
9
|
-
defaults: {
|
|
10
|
-
|
|
25
|
+
defaults: {
|
|
26
|
+
primaryColor: "#fafafa"
|
|
27
|
+
},
|
|
28
|
+
setup(options, nuxt) {
|
|
29
|
+
const rcOptions = loadRcConfig(nuxt.options.rootDir);
|
|
30
|
+
const resolvedOptions = { ...rcOptions, ...options };
|
|
31
|
+
nuxt.options.runtimeConfig.public.moulify = {
|
|
32
|
+
primaryColor: resolvedOptions.primaryColor ?? "#fafafa"
|
|
33
|
+
};
|
|
11
34
|
const resolver = createResolver(import.meta.url);
|
|
12
35
|
addComponentsDir({
|
|
13
36
|
path: resolver.resolve("./runtime/components")
|
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<button
|
|
3
|
-
class="moulify-button"
|
|
4
|
-
type="button"
|
|
5
|
-
v-bind="$attrs"
|
|
6
|
-
>
|
|
2
|
+
<button class="moulify-button" type="button" v-bind="$attrs">
|
|
7
3
|
<slot />
|
|
8
4
|
</button>
|
|
9
5
|
</template>
|
|
10
6
|
|
|
11
7
|
<script setup>
|
|
12
|
-
defineOptions({
|
|
13
|
-
name: "MoulifyButton"
|
|
14
|
-
});
|
|
8
|
+
defineOptions({ name: "MoulifyButton" });
|
|
15
9
|
</script>
|
|
16
10
|
|
|
17
11
|
<style scoped>
|
|
18
|
-
.moulify-button
|
|
12
|
+
.moulify-button {
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
padding: px-to-rem(8) px-to-rem(16);
|
|
17
|
+
border-radius: px-to-rem(6);
|
|
18
|
+
border: px-to-rem(1) solid rgba(15, 23, 42, 0.15);
|
|
19
|
+
background: var(--moulify-primary);
|
|
20
|
+
font-size: px-to-rem(14);
|
|
21
|
+
font-weight: 500;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
transition: background-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.moulify-button:hover {
|
|
27
|
+
background: color-mix(in srgb, var(--moulify-primary) 85%, #000);
|
|
28
|
+
box-shadow: 0 px-to-rem(8) px-to-rem(20) rgba(15, 23, 42, 0.15);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.moulify-button:active {
|
|
32
|
+
transform: translateY(px-to-rem(1));
|
|
33
|
+
box-shadow: 0 px-to-rem(4) px-to-rem(10) rgba(15, 23, 42, 0.1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.moulify-button:disabled {
|
|
37
|
+
opacity: 0.6;
|
|
38
|
+
cursor: not-allowed;
|
|
39
|
+
box-shadow: none;
|
|
40
|
+
}
|
|
19
41
|
</style>
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -1,3 +1,83 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from "#app";
|
|
1
|
+
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
|
|
2
|
+
const SHADE_LIGHTNESS = {
|
|
3
|
+
50: 0.98,
|
|
4
|
+
100: 0.95,
|
|
5
|
+
200: 0.9,
|
|
6
|
+
300: 0.8,
|
|
7
|
+
400: 0.7,
|
|
8
|
+
500: -1,
|
|
9
|
+
// use base
|
|
10
|
+
600: 0.55,
|
|
11
|
+
700: 0.45,
|
|
12
|
+
800: 0.35,
|
|
13
|
+
900: 0.25
|
|
14
|
+
};
|
|
15
|
+
const hexToRgb = (hex) => {
|
|
16
|
+
const m = hex.replace(/^#/, "").match(/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
|
|
17
|
+
if (!m || m[1] === void 0 || m[2] === void 0 || m[3] === void 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];
|
|
21
|
+
};
|
|
22
|
+
const rgbToHsl = (r, g, b) => {
|
|
23
|
+
r /= 255;
|
|
24
|
+
g /= 255;
|
|
25
|
+
b /= 255;
|
|
26
|
+
const max = Math.max(r, g, b);
|
|
27
|
+
const min = Math.min(r, g, b);
|
|
28
|
+
let h = 0;
|
|
29
|
+
let s = 0;
|
|
30
|
+
const l = (max + min) / 2;
|
|
31
|
+
if (max !== min) {
|
|
32
|
+
const d = max - min;
|
|
33
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
34
|
+
switch (max) {
|
|
35
|
+
case r:
|
|
36
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
37
|
+
break;
|
|
38
|
+
case g:
|
|
39
|
+
h = ((b - r) / d + 2) / 6;
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
h = ((r - g) / d + 4) / 6;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return [h * 360, s * 100, l * 100];
|
|
46
|
+
};
|
|
47
|
+
const hslToHex = (h, s, l) => {
|
|
48
|
+
s /= 100;
|
|
49
|
+
l /= 100;
|
|
50
|
+
const a = s * Math.min(l, 1 - l);
|
|
51
|
+
const f = (n) => {
|
|
52
|
+
const k = (n + h / 30) % 12;
|
|
53
|
+
const x = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
54
|
+
return Math.round(255 * x).toString(16).padStart(2, "0");
|
|
55
|
+
};
|
|
56
|
+
return `#${f(0)}${f(8)}${f(4)}`;
|
|
57
|
+
};
|
|
58
|
+
const generatePrimaryShades = (hex) => {
|
|
59
|
+
const rgb = hexToRgb(hex);
|
|
60
|
+
if (!rgb) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
const [h, s, baseL] = rgbToHsl(rgb[0], rgb[1], rgb[2]);
|
|
64
|
+
const result = {};
|
|
65
|
+
for (const shade of [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]) {
|
|
66
|
+
const targetL = SHADE_LIGHTNESS[shade];
|
|
67
|
+
const l = targetL === void 0 || targetL === -1 ? baseL : targetL * 100;
|
|
68
|
+
result[shade] = hslToHex(h, s, l);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
2
72
|
export default defineNuxtPlugin(() => {
|
|
73
|
+
const config = useRuntimeConfig();
|
|
74
|
+
const moulify = config.public.moulify;
|
|
75
|
+
const primaryColor = moulify?.primaryColor ?? "red";
|
|
76
|
+
if (import.meta.client) {
|
|
77
|
+
document.documentElement.style.setProperty("--moulify-primary", primaryColor);
|
|
78
|
+
const shades = generatePrimaryShades(primaryColor);
|
|
79
|
+
for (const [shade, value] of Object.entries(shades)) {
|
|
80
|
+
document.documentElement.style.setProperty(`--moulify-primary-${shade}`, value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
3
83
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moulify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Nuxt module with UI components including MoulifyButton",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,17 +30,20 @@
|
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
32
|
"prepack": "nuxt-module-build build",
|
|
33
|
-
"dev": "
|
|
33
|
+
"dev": "bun run dev:prepare && nuxt dev playground",
|
|
34
34
|
"dev:build": "nuxt build playground",
|
|
35
35
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
|
|
36
36
|
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
37
37
|
"lint": "eslint .",
|
|
38
38
|
"test": "vitest run",
|
|
39
39
|
"test:watch": "vitest watch",
|
|
40
|
-
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
40
|
+
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
41
|
+
"dev:clean": "rm -rf dist playground/.nuxt playground/.output playground/node_modules/.vite",
|
|
42
|
+
"dev:full": "bun run dev:clean && bun run dev"
|
|
41
43
|
},
|
|
42
44
|
"dependencies": {
|
|
43
|
-
"@nuxt/kit": "^4.3.1"
|
|
45
|
+
"@nuxt/kit": "^4.3.1",
|
|
46
|
+
"sass": "^1.97.3"
|
|
44
47
|
},
|
|
45
48
|
"peerDependencies": {
|
|
46
49
|
"nuxt": ">=3.0.0"
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@nuxt/devtools": "^3.2.1",
|
|
50
53
|
"@nuxt/eslint-config": "^1.15.1",
|
|
54
|
+
"@stylistic/eslint-plugin": "^5.8.0",
|
|
51
55
|
"@nuxt/module-builder": "^1.0.2",
|
|
52
56
|
"@nuxt/schema": "^4.3.1",
|
|
53
57
|
"@nuxt/test-utils": "^4.0.0",
|