@bhooai/nexus-postcss 0.1.3 → 0.1.5
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 +89 -9
- package/package.json +8 -1
- package/src/plugins.js +32 -7
- package/src/theme-light-dark.css +68 -0
- package/src/types.ts +4 -0
package/README.md
CHANGED
|
@@ -29,14 +29,68 @@ export default createPreset({
|
|
|
29
29
|
});
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
### With Tailwind forms + typography plugins
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { createPreset } from '@bhooai/nexus-postcss';
|
|
36
|
+
import forms from '@tailwindcss/forms';
|
|
37
|
+
import typography from '@tailwindcss/typography';
|
|
38
|
+
|
|
39
|
+
export default createPreset({
|
|
40
|
+
tailwindPlugins: [forms, typography],
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Modern CSS nesting (spec-compliant)
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { createPreset } from '@bhooai/nexus-postcss';
|
|
48
|
+
|
|
49
|
+
export default createPreset({
|
|
50
|
+
nestingMode: 'modern', // use postcss-nesting (real CSS Nesting spec) instead of postcss-nested
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Lightning CSS engine (experimental, ~100x faster)
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import { createPreset } from '@bhooai/nexus-postcss';
|
|
58
|
+
|
|
59
|
+
export default createPreset({
|
|
60
|
+
engine: 'lightningcss', // replaces preset-env + autoprefixer + cssnano with one lightningcss pass
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Note: `lightningcss` targets browsers directly (not CSS stages), so `postcss-preset-env` stage polyfills are not applied. Nesting, prefixing, and minification are all handled by lightningcss.
|
|
65
|
+
|
|
66
|
+
### RTL/LTR direction-aware CSS
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { createPreset } from '@bhooai/nexus-postcss';
|
|
70
|
+
|
|
71
|
+
export default createPreset({
|
|
72
|
+
logical: true, // polyfills margin-inline, padding-block, inset-inline, etc.
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
32
76
|
## Plugin chain (in order)
|
|
33
77
|
|
|
78
|
+
**Default (`engine: 'postcss'`):**
|
|
79
|
+
|
|
80
|
+
1. **postcss-import** — resolve `@import` statements
|
|
81
|
+
2. **postcss-nested** (or **postcss-nesting** when `nestingMode: 'modern'`) — CSS nesting
|
|
82
|
+
3. **tailwindcss** — base/components/utilities + content scanning
|
|
83
|
+
4. **postcss-logical** (when `logical: true`) — direction-aware properties
|
|
84
|
+
5. **postcss-preset-env** (stage 2) — future CSS features today
|
|
85
|
+
6. **autoprefixer** — vendor prefixes
|
|
86
|
+
7. **cssnano** — minification (only when `NODE_ENV=production` or `minify: true`)
|
|
87
|
+
|
|
88
|
+
**Lightning CSS (`engine: 'lightningcss'`):**
|
|
89
|
+
|
|
34
90
|
1. **postcss-import** — resolve `@import` statements
|
|
35
|
-
2. **
|
|
91
|
+
2. **postcss-nested** (or **postcss-nesting** when `nestingMode: 'modern'`) — CSS nesting
|
|
36
92
|
3. **tailwindcss** — base/components/utilities + content scanning
|
|
37
|
-
4. **postcss-
|
|
38
|
-
5. **autoprefixer** — vendor prefixes
|
|
39
|
-
6. **cssnano** — minification (only when `NODE_ENV=production` or `minify: true`)
|
|
93
|
+
4. **postcss-lightningcss** — prefixing + minification + future CSS (replaces preset-env + autoprefixer + cssnano)
|
|
40
94
|
|
|
41
95
|
## Options
|
|
42
96
|
|
|
@@ -45,18 +99,44 @@ export default createPreset({
|
|
|
45
99
|
| `content` | `string[]` | `['./index.html', './src/**/*.{ts,tsx}']` | Tailwind content scan paths |
|
|
46
100
|
| `extraContent` | `string[]` | `[]` | Additional content paths to merge |
|
|
47
101
|
| `theme` | `object` | `{}` | Tailwind theme extensions |
|
|
48
|
-
| `tailwindPlugins` | `array` | `[]` | Tailwind plugins |
|
|
102
|
+
| `tailwindPlugins` | `array` | `[]` | Tailwind plugins (e.g. `@tailwindcss/forms`, `@tailwindcss/typography`) |
|
|
49
103
|
| `import` | `boolean` | `true` | Enable postcss-import |
|
|
50
|
-
| `nested` | `boolean` | `true` | Enable
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
104
|
+
| `nested` | `boolean` | `true` | Enable CSS nesting |
|
|
105
|
+
| `nestingMode` | `'classic' \| 'modern'` | `'classic'` | `'modern'` uses postcss-nesting (real CSS Nesting spec); `'classic'` uses postcss-nested |
|
|
106
|
+
| `logical` | `boolean \| object` | `false` | Enable postcss-logical for RTL/LTR direction-aware CSS |
|
|
107
|
+
| `presetEnv` | `boolean \| 'stage2' \| 'stage3' \| 'stage4'` | `true` (stage2) | Enable postcss-preset-env (ignored when `engine: 'lightningcss'`) |
|
|
108
|
+
| `autoprefixer` | `boolean \| object` | `true` | Enable autoprefixer (ignored when `engine: 'lightningcss'`) |
|
|
109
|
+
| `minify` | `boolean` | `NODE_ENV === 'production'` | Enable minification (cssnano or lightningcss) |
|
|
110
|
+
| `sourcemap` | `boolean` | `undefined` | Explicit source map control: `true` = inline + annotation, `false` = disabled, `undefined` = let PostCSS/Vite decide |
|
|
111
|
+
| `engine` | `'postcss' \| 'lightningcss'` | `'postcss'` | CSS processing backend. `'lightningcss'` is experimental and ~100x faster |
|
|
54
112
|
| `plugins` | `Array<[string, any] \| string>` | `[]` | Custom PostCSS plugins to append |
|
|
55
113
|
|
|
114
|
+
## Theme tokens
|
|
115
|
+
|
|
116
|
+
Two token stylesheets ship with the preset:
|
|
117
|
+
|
|
118
|
+
### Dark-only (default)
|
|
119
|
+
|
|
120
|
+
```css
|
|
121
|
+
@import '@bhooai/nexus-postcss/theme.css';
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
22 CSS custom properties (`--nexus-bg`, `--nexus-ink`, `--nexus-surface`, `--nexus-accent`, etc.) on `:root`, plus 15 `--admin-*` aliases for backwards compatibility.
|
|
125
|
+
|
|
126
|
+
### Light/dark dual theme
|
|
127
|
+
|
|
128
|
+
```css
|
|
129
|
+
@import '@bhooai/nexus-postcss/theme-light-dark.css';
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Uses the CSS `light-dark()` function so every token adapts to the user's `prefers-color-scheme`. Sets `color-scheme: light dark` on `:root`. `postcss-preset-env` (stage 2, in the default chain) polyfills `light-dark()` for browsers without native support.
|
|
133
|
+
|
|
56
134
|
## Tailwind config
|
|
57
135
|
|
|
58
136
|
`tailwind.config.js` is kept in each app — the preset only injects `content` paths and the plugin chain. Theme extensions and Tailwind plugins stay in your `tailwind.config.js`.
|
|
59
137
|
|
|
138
|
+
Note: Tailwind v3.4+ enables container queries by default — the `@container` utility is available out of the box.
|
|
139
|
+
|
|
60
140
|
## License
|
|
61
141
|
|
|
62
142
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bhooai/nexus-postcss",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Opinionated PostCSS preset for BhooAI Nexus apps — Tailwind, nesting, future CSS, autoprefixing, and minification in one curated pipeline.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./src/index.js",
|
|
10
10
|
"./theme.css": "./src/theme.css",
|
|
11
|
+
"./theme-light-dark.css": "./src/theme-light-dark.css",
|
|
11
12
|
"./package.json": "./package.json"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
@@ -18,11 +19,17 @@
|
|
|
18
19
|
"test": "vitest run"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
22
|
+
"@tailwindcss/forms": "^0.5.9",
|
|
23
|
+
"@tailwindcss/typography": "^0.5.15",
|
|
21
24
|
"autoprefixer": "^10.4.20",
|
|
22
25
|
"cssnano": "^7.0.6",
|
|
26
|
+
"lightningcss": "^1.26.0",
|
|
23
27
|
"postcss": "^8.4.47",
|
|
24
28
|
"postcss-import": "^16.1.0",
|
|
29
|
+
"postcss-lightningcss": "^1.0.1",
|
|
30
|
+
"postcss-logical": "^8.0.0",
|
|
25
31
|
"postcss-nested": "^6.2.0",
|
|
32
|
+
"postcss-nesting": "^12.1.5",
|
|
26
33
|
"postcss-preset-env": "^9.6.0",
|
|
27
34
|
"tailwindcss": "^3.4.13"
|
|
28
35
|
},
|
package/src/plugins.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import postcssImport from 'postcss-import';
|
|
2
2
|
import postcssNested from 'postcss-nested';
|
|
3
|
+
import postcssNesting from 'postcss-nesting';
|
|
4
|
+
import postcssLogical from 'postcss-logical';
|
|
3
5
|
import tailwindcss from 'tailwindcss';
|
|
4
6
|
import postcssPresetEnv from 'postcss-preset-env';
|
|
5
7
|
import autoprefixer from 'autoprefixer';
|
|
6
8
|
import cssnano from 'cssnano';
|
|
9
|
+
import postcssLightningcss from 'postcss-lightningcss';
|
|
7
10
|
|
|
8
11
|
export function createPreset(options = {}) {
|
|
9
12
|
const DEFAULT_CONTENT = ['./index.html', './src/**/*.{ts,tsx}'];
|
|
@@ -17,6 +20,8 @@ export function createPreset(options = {}) {
|
|
|
17
20
|
const enableImport = options.import ?? true;
|
|
18
21
|
const enableNested = options.nested ?? true;
|
|
19
22
|
const enableAutoprefixer = options.autoprefixer !== false;
|
|
23
|
+
const useModernNesting = options.nestingMode === 'modern';
|
|
24
|
+
const useLightningcss = options.engine === 'lightningcss';
|
|
20
25
|
|
|
21
26
|
const content = [...(options.content ?? DEFAULT_CONTENT), ...(options.extraContent ?? [])];
|
|
22
27
|
const tailwindOpts = {
|
|
@@ -27,14 +32,28 @@ export function createPreset(options = {}) {
|
|
|
27
32
|
|
|
28
33
|
const plugins = [];
|
|
29
34
|
if (enableImport) plugins.push(postcssImport({}));
|
|
30
|
-
if (enableNested)
|
|
35
|
+
if (enableNested) {
|
|
36
|
+
plugins.push(useModernNesting ? postcssNesting() : postcssNested());
|
|
37
|
+
}
|
|
31
38
|
plugins.push(tailwindcss(tailwindOpts));
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
|
|
40
|
+
if (useLightningcss) {
|
|
41
|
+
// lightningcss handles prefixing + minification + some future CSS in one pass.
|
|
42
|
+
// It replaces postcss-preset-env + autoprefixer + cssnano.
|
|
43
|
+
plugins.push(postcssLightningcss({ minify: shouldMinify }));
|
|
44
|
+
} else {
|
|
45
|
+
if (options.logical) {
|
|
46
|
+
const logicalOpts = typeof options.logical === 'object' ? options.logical : {};
|
|
47
|
+
plugins.push(postcssLogical(logicalOpts));
|
|
48
|
+
}
|
|
49
|
+
if (enablePresetEnv) plugins.push(postcssPresetEnv({ stage: presetEnvStage }));
|
|
50
|
+
if (enableAutoprefixer) {
|
|
51
|
+
const apOpts = typeof options.autoprefixer === 'object' ? options.autoprefixer : {};
|
|
52
|
+
plugins.push(autoprefixer(apOpts));
|
|
53
|
+
}
|
|
54
|
+
if (shouldMinify) plugins.push(cssnano({ preset: 'default' }));
|
|
36
55
|
}
|
|
37
|
-
|
|
56
|
+
|
|
38
57
|
if (options.plugins) {
|
|
39
58
|
for (const p of options.plugins) {
|
|
40
59
|
if (typeof p === 'string') plugins.push(p);
|
|
@@ -42,5 +61,11 @@ export function createPreset(options = {}) {
|
|
|
42
61
|
}
|
|
43
62
|
}
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
const map = options.sourcemap === true
|
|
65
|
+
? { inline: true, annotation: true }
|
|
66
|
+
: options.sourcemap === false
|
|
67
|
+
? false
|
|
68
|
+
: undefined;
|
|
69
|
+
|
|
70
|
+
return { plugins, ...(map !== undefined && { map }) };
|
|
46
71
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bhooai/nexus-postcss — theme-light-dark.css
|
|
3
|
+
*
|
|
4
|
+
* Dual-theme variant of theme.css using the CSS `light-dark()` function.
|
|
5
|
+
* Opt in with:
|
|
6
|
+
* @import '@bhooai/nexus-postcss/theme-light-dark.css';
|
|
7
|
+
*
|
|
8
|
+
* Requires `color-scheme: light dark` on :root (set below) so the browser
|
|
9
|
+
* knows to honor both palettes. `postcss-preset-env` (stage 2, already in the
|
|
10
|
+
* preset) polyfills `light-dark()` for browsers without native support.
|
|
11
|
+
*
|
|
12
|
+
* Override any token in your own :root block to retheme either side.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
color-scheme: light dark;
|
|
17
|
+
|
|
18
|
+
/* ---- base surface ---- */
|
|
19
|
+
--nexus-bg: light-dark(#ffffff, #050817);
|
|
20
|
+
--nexus-bg-alt: light-dark(#f4f6fb, #0b0d1a);
|
|
21
|
+
--nexus-ink: light-dark(#0b0d1a, #eef6ff);
|
|
22
|
+
--nexus-muted: light-dark(#475569, #8496ad);
|
|
23
|
+
--nexus-surface: light-dark(rgba(241, 245, 249, 0.82), rgba(10, 24, 45, 0.78));
|
|
24
|
+
--nexus-surface-strong: light-dark(rgba(226, 232, 240, 0.78), rgba(8, 25, 48, 0.68));
|
|
25
|
+
--nexus-border: light-dark(rgba(15, 23, 42, 0.16), rgba(125, 174, 235, 0.2));
|
|
26
|
+
--nexus-border-bright: light-dark(rgba(15, 23, 42, 0.22), rgba(112, 168, 228, 0.17));
|
|
27
|
+
|
|
28
|
+
/* ---- accent palette ---- */
|
|
29
|
+
--nexus-accent: light-dark(#0891b2, #67e8f9);
|
|
30
|
+
--nexus-accent-soft: light-dark(rgba(8, 145, 178, 0.08), rgba(103, 232, 249, 0.08));
|
|
31
|
+
--nexus-blue: light-dark(rgba(37, 99, 235, 0.45), rgba(38, 130, 225, 0.55));
|
|
32
|
+
--nexus-violet: light-dark(rgba(124, 58, 237, 0.35), rgba(90, 67, 183, 0.45));
|
|
33
|
+
--nexus-pink: #f43f5e;
|
|
34
|
+
--nexus-emerald: light-dark(#059669, #34d399);
|
|
35
|
+
|
|
36
|
+
/* ---- geometry ---- */
|
|
37
|
+
--nexus-radius: 0.7rem;
|
|
38
|
+
--nexus-radius-lg: 1rem;
|
|
39
|
+
--nexus-shell-width: 1280px;
|
|
40
|
+
|
|
41
|
+
/* ---- ambient mesh ---- */
|
|
42
|
+
--nexus-mesh:
|
|
43
|
+
radial-gradient(54rem 42rem at 84% -12%, light-dark(rgba(124, 58, 237, 0.10), rgba(91, 33, 182, 0.32)), transparent 67%),
|
|
44
|
+
radial-gradient(48rem 38rem at -8% 58%, light-dark(rgba(8, 145, 178, 0.08), rgba(8, 145, 178, 0.2)), transparent 68%),
|
|
45
|
+
radial-gradient(42rem 36rem at 56% 44%, light-dark(rgba(30, 64, 175, 0.06), rgba(30, 64, 175, 0.16)), transparent 72%);
|
|
46
|
+
--nexus-mesh-opacity: 0.27;
|
|
47
|
+
|
|
48
|
+
/* ---- selection + scrollbars ---- */
|
|
49
|
+
--nexus-selection: light-dark(rgba(37, 99, 235, 0.25), rgba(129, 140, 248, 0.35));
|
|
50
|
+
--nexus-scrollbar: light-dark(rgba(15, 23, 42, 0.18), rgba(255, 255, 255, 0.18));
|
|
51
|
+
--nexus-scrollbar-thumb: light-dark(rgba(15, 23, 42, 0.14), rgba(255, 255, 255, 0.14));
|
|
52
|
+
|
|
53
|
+
/* ---- aliases for existing admin consumers ---- */
|
|
54
|
+
--admin-bg: var(--nexus-bg);
|
|
55
|
+
--admin-ink: var(--nexus-ink);
|
|
56
|
+
--admin-muted: var(--nexus-muted);
|
|
57
|
+
--admin-surface: var(--nexus-surface);
|
|
58
|
+
--admin-surface-strong: var(--nexus-surface-strong);
|
|
59
|
+
--admin-border: var(--nexus-border);
|
|
60
|
+
--admin-border-bright: var(--nexus-border-bright);
|
|
61
|
+
--admin-blue: var(--nexus-blue);
|
|
62
|
+
--admin-violet: var(--nexus-violet);
|
|
63
|
+
--admin-pink: var(--nexus-pink);
|
|
64
|
+
--admin-radius: var(--nexus-radius);
|
|
65
|
+
--admin-shell-width: var(--nexus-shell-width);
|
|
66
|
+
--admin-mesh: var(--nexus-mesh);
|
|
67
|
+
--admin-mesh-opacity: var(--nexus-mesh-opacity);
|
|
68
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -5,8 +5,12 @@ export interface NexusPostcssOptions {
|
|
|
5
5
|
tailwindPlugins?: any[];
|
|
6
6
|
import?: boolean;
|
|
7
7
|
nested?: boolean;
|
|
8
|
+
nestingMode?: 'classic' | 'modern';
|
|
8
9
|
presetEnv?: boolean | 'stage2' | 'stage3' | 'stage4';
|
|
9
10
|
autoprefixer?: boolean | Record<string, string>;
|
|
11
|
+
logical?: boolean | Record<string, any>;
|
|
10
12
|
minify?: boolean;
|
|
13
|
+
sourcemap?: boolean;
|
|
14
|
+
engine?: 'postcss' | 'lightningcss';
|
|
11
15
|
plugins?: Array<[string, any] | string>;
|
|
12
16
|
}
|