moulify 1.0.0 → 1.0.4

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 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
@@ -1,6 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
3
  interface ModuleOptions {
4
+ /** Primary color used by components (e.g. button background). */
5
+ primaryColor?: string;
4
6
  }
5
7
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
8
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "moulify",
3
3
  "configKey": "moulify",
4
- "version": "1.0.0",
4
+ "version": "1.0.4",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
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
- setup(_options, _nuxt) {
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{align-items:center;background:linear-gradient(135deg,#0f172a,#1e293b);border:1px solid rgba(15,23,42,.15);border-radius:.375rem;color:#f9fafb;cursor:pointer;display:inline-flex;font-size:.875rem;font-weight:500;justify-content:center;padding:.5rem 1rem;transition:background-color .15s ease,box-shadow .15s ease,transform .05s ease}.moulify-button:hover{background:linear-gradient(135deg,#111827,#1f2937);box-shadow:0 8px 20px rgba(15,23,42,.25)}.moulify-button:active{box-shadow:0 4px 10px rgba(15,23,42,.2);transform:translateY(1px)}.moulify-button:disabled{box-shadow:none;cursor:not-allowed;opacity:.6}
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>
@@ -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.0",
3
+ "version": "1.0.4",
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": "npm run dev:prepare && nuxt dev playground",
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",