tailwind-style-sheets 0.0.1 → 0.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 +25 -21
- package/dist/chunk-OFTF64MC.mjs +31 -0
- package/dist/index.d.mts +38 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +10 -0
- package/dist/index.mjs +42 -0
- package/dist/loader.js +32 -3
- package/dist/vite.d.mts +5 -0
- package/dist/vite.mjs +39 -0
- package/package.json +25 -4
- package/src/index.ts +1 -0
- package/src/loader.ts +3 -11
- package/src/parse.ts +13 -0
- package/src/twcn.ts +10 -0
- package/src/vite-plugin.ts +28 -0
- package/src/vite.ts +1 -0
- package/tsconfig.json +2 -2
- package/tsup.config.ts +6 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# tailwind-style-sheets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use standard CSS class names in your components — `.twss` files map them to Tailwind utilities at build time.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Define your class names and their Tailwind mappings in `.twss` files using familiar CSS syntax with `@apply`:
|
|
8
8
|
|
|
9
9
|
```css
|
|
10
10
|
/* Button.styles.twss */
|
|
@@ -43,22 +43,13 @@ Inline is also valid:
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
import styles from "./Button.styles.twss";
|
|
50
|
-
// styles.button → "cursor-pointer px-4 py-2 rounded-full text-sm font-medium transition-all active:scale-95"
|
|
51
|
-
// styles["button--primary"] → "bg-blue-600 text-white hover:bg-blue-700"
|
|
52
|
-
// styles["button--ghost"] → "bg-transparent text-blue-600 hover:bg-blue-50"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Pair it with [`@michalshelenberg/modcn`](https://www.npmjs.com/package/@michalshelenberg/modcn) to compose BEM classes ergonomically:
|
|
46
|
+
## Usage
|
|
56
47
|
|
|
57
48
|
```tsx
|
|
58
|
-
import {
|
|
49
|
+
import { twcn } from "tailwind-style-sheets";
|
|
59
50
|
import styles from "./Button.styles.twss";
|
|
60
51
|
|
|
61
|
-
const cn =
|
|
52
|
+
const cn = twcn(styles);
|
|
62
53
|
|
|
63
54
|
export function Button({ variant = "primary", className, children, ...props }) {
|
|
64
55
|
return (
|
|
@@ -69,6 +60,8 @@ export function Button({ variant = "primary", className, children, ...props }) {
|
|
|
69
60
|
}
|
|
70
61
|
```
|
|
71
62
|
|
|
63
|
+
`twcn` takes the imported styles object, and returns a function that resolves class names with `tailwind-merge` — pass it style keys, modifiers, and an optional `className` override.
|
|
64
|
+
|
|
72
65
|
## Installation
|
|
73
66
|
|
|
74
67
|
```bash
|
|
@@ -83,9 +76,10 @@ This scaffolds all required files and installs the package.
|
|
|
83
76
|
npm install tailwind-style-sheets
|
|
84
77
|
```
|
|
85
78
|
|
|
86
|
-
###
|
|
79
|
+
### Next.js (Turbopack)
|
|
87
80
|
|
|
88
81
|
```ts
|
|
82
|
+
// next.config.ts
|
|
89
83
|
import type { NextConfig } from "next";
|
|
90
84
|
import path from "path";
|
|
91
85
|
import { withTwssPlugin } from "tailwind-style-sheets";
|
|
@@ -107,6 +101,22 @@ export default withTwssPlugin(nextConfig, {
|
|
|
107
101
|
|
|
108
102
|
Both options are optional. Omitting them disables the HMR watcher (the loader still works).
|
|
109
103
|
|
|
104
|
+
### Vite
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// vite.config.ts
|
|
108
|
+
import { defineConfig } from "vite";
|
|
109
|
+
import react from "@vitejs/plugin-react";
|
|
110
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
111
|
+
import { twssVitePlugin } from "tailwind-style-sheets/vite";
|
|
112
|
+
|
|
113
|
+
export default defineConfig({
|
|
114
|
+
plugins: [react(), tailwindcss(), twssVitePlugin()],
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The Vite plugin transforms `.twss` files and handles HMR automatically — no additional options needed.
|
|
119
|
+
|
|
110
120
|
### TypeScript
|
|
111
121
|
|
|
112
122
|
Add a declaration file so TypeScript knows `.twss` imports return `Record<string, string>`:
|
|
@@ -133,9 +143,3 @@ Add to `.vscode/settings.json` to get CSS syntax highlighting and silence the `@
|
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
145
|
```
|
|
136
|
-
|
|
137
|
-
## How it works
|
|
138
|
-
|
|
139
|
-
1. **Loader** (`loader.ts`) — Turbopack passes the raw `.twss` file content through the loader. A regex extracts each `.className { @apply ... }` block and converts it to `export default { className: "class1 class2 ..." }`.
|
|
140
|
-
|
|
141
|
-
2. **HMR watcher** (`plugin.ts`) — In development, `fs.watch` monitors `watchDir` for `.twss` changes. When a change is detected, it touches `globalsCSS`, which causes Next.js to re-run Tailwind's class scan and hot-reload styles.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
21
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
22
|
+
}) : x)(function(x) {
|
|
23
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
24
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
__spreadValues,
|
|
29
|
+
__spreadProps,
|
|
30
|
+
__require
|
|
31
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NextConfig } from 'next';
|
|
2
|
+
import { modcn } from 'modcn';
|
|
3
|
+
|
|
4
|
+
interface TwssPluginOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Absolute path to your global CSS file (e.g. `src/app/globals.css`).
|
|
7
|
+
* Touched on `.twss` file changes to trigger Tailwind's class scan and HMR.
|
|
8
|
+
*/
|
|
9
|
+
globalsCSS?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Directory to watch recursively for `.twss` file changes.
|
|
12
|
+
* Only active in `development`. Omit to disable the HMR watcher.
|
|
13
|
+
*/
|
|
14
|
+
watchDir?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Next.js plugin that enables `.twss` file imports as Tailwind class maps.
|
|
18
|
+
*
|
|
19
|
+
* Registers the Turbopack loader for `*.twss` files and, in development,
|
|
20
|
+
* watches `watchDir` for changes — touching `globalsCSS` on each change
|
|
21
|
+
* so Next.js re-runs Tailwind's class scan and hot-reloads styles.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // next.config.ts
|
|
25
|
+
* import path from "path";
|
|
26
|
+
* import { withTwssPlugin } from "tailwind-style-sheets";
|
|
27
|
+
*
|
|
28
|
+
* export default withTwssPlugin({}, {
|
|
29
|
+
* globalsCSS: path.resolve(__dirname, "src/app/globals.css"),
|
|
30
|
+
* watchDir: path.resolve(__dirname, "src"),
|
|
31
|
+
* });
|
|
32
|
+
*/
|
|
33
|
+
declare function withTwssPlugin(nextConfig: NextConfig, options?: TwssPluginOptions): NextConfig;
|
|
34
|
+
|
|
35
|
+
type StylesMap = Record<string, string>;
|
|
36
|
+
declare function twcn(styles: StylesMap): (...inputs: Parameters<ReturnType<typeof modcn>>) => string;
|
|
37
|
+
|
|
38
|
+
export { type TwssPluginOptions, twcn, withTwssPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextConfig } from 'next';
|
|
2
|
+
import { modcn } from 'modcn';
|
|
2
3
|
|
|
3
4
|
interface TwssPluginOptions {
|
|
4
5
|
/**
|
|
@@ -31,4 +32,7 @@ interface TwssPluginOptions {
|
|
|
31
32
|
*/
|
|
32
33
|
declare function withTwssPlugin(nextConfig: NextConfig, options?: TwssPluginOptions): NextConfig;
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
type StylesMap = Record<string, string>;
|
|
36
|
+
declare function twcn(styles: StylesMap): (...inputs: Parameters<ReturnType<typeof modcn>>) => string;
|
|
37
|
+
|
|
38
|
+
export { type TwssPluginOptions, twcn, withTwssPlugin };
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
47
47
|
// src/index.ts
|
|
48
48
|
var index_exports = {};
|
|
49
49
|
__export(index_exports, {
|
|
50
|
+
twcn: () => twcn,
|
|
50
51
|
withTwssPlugin: () => withTwssPlugin
|
|
51
52
|
});
|
|
52
53
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -75,7 +76,16 @@ function withTwssPlugin(nextConfig, options = {}) {
|
|
|
75
76
|
})
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
|
|
80
|
+
// src/twcn.ts
|
|
81
|
+
var import_modcn = require("modcn");
|
|
82
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
83
|
+
function twcn(styles) {
|
|
84
|
+
const cn = (0, import_modcn.modcn)(styles);
|
|
85
|
+
return (...inputs) => (0, import_tailwind_merge.twMerge)(cn(...inputs));
|
|
86
|
+
}
|
|
78
87
|
// Annotate the CommonJS export names for ESM import in node:
|
|
79
88
|
0 && (module.exports = {
|
|
89
|
+
twcn,
|
|
80
90
|
withTwssPlugin
|
|
81
91
|
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require,
|
|
3
|
+
__spreadProps,
|
|
4
|
+
__spreadValues
|
|
5
|
+
} from "./chunk-OFTF64MC.mjs";
|
|
6
|
+
|
|
7
|
+
// src/plugin.ts
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
function withTwssPlugin(nextConfig, options = {}) {
|
|
10
|
+
var _a;
|
|
11
|
+
const { globalsCSS, watchDir } = options;
|
|
12
|
+
if (process.env.NODE_ENV === "development" && globalsCSS && watchDir) {
|
|
13
|
+
fs.watch(watchDir, { recursive: true }, (_, filename) => {
|
|
14
|
+
if (filename == null ? void 0 : filename.endsWith(".twss")) {
|
|
15
|
+
const now = /* @__PURE__ */ new Date();
|
|
16
|
+
fs.utimesSync(globalsCSS, now, now);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return __spreadProps(__spreadValues({}, nextConfig), {
|
|
21
|
+
turbopack: __spreadProps(__spreadValues({}, nextConfig.turbopack), {
|
|
22
|
+
rules: __spreadProps(__spreadValues({}, (_a = nextConfig.turbopack) == null ? void 0 : _a.rules), {
|
|
23
|
+
"*.twss": {
|
|
24
|
+
loaders: [__require.resolve("./loader")],
|
|
25
|
+
as: "*.js"
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/twcn.ts
|
|
33
|
+
import { modcn } from "modcn";
|
|
34
|
+
import { twMerge } from "tailwind-merge";
|
|
35
|
+
function twcn(styles) {
|
|
36
|
+
const cn = modcn(styles);
|
|
37
|
+
return (...inputs) => twMerge(cn(...inputs));
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
twcn,
|
|
41
|
+
withTwssPlugin
|
|
42
|
+
};
|
package/dist/loader.js
CHANGED
|
@@ -1,14 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
19
|
|
|
3
20
|
// src/loader.ts
|
|
21
|
+
var loader_exports = {};
|
|
22
|
+
__export(loader_exports, {
|
|
23
|
+
default: () => loader_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(loader_exports);
|
|
26
|
+
|
|
27
|
+
// src/parse.ts
|
|
4
28
|
var BLOCK_REGEX = /\.(\w[\w-]*)\s*\{\s*@apply\s+([\s\S]*?)\s*\}/g;
|
|
5
|
-
|
|
29
|
+
function parseTwss(source) {
|
|
6
30
|
const styles = {};
|
|
7
31
|
let match;
|
|
8
32
|
while ((match = BLOCK_REGEX.exec(source)) !== null) {
|
|
9
33
|
const [, className, classes] = match;
|
|
10
34
|
styles[className] = classes.trim().replace(/\s+/g, " ");
|
|
11
35
|
}
|
|
12
|
-
return
|
|
36
|
+
return styles;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/loader.ts
|
|
40
|
+
var twssLoader = function(source) {
|
|
41
|
+
return `export default ${JSON.stringify(parseTwss(source))};`;
|
|
13
42
|
};
|
|
14
|
-
|
|
43
|
+
var loader_default = twssLoader;
|
package/dist/vite.d.mts
ADDED
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import "./chunk-OFTF64MC.mjs";
|
|
2
|
+
|
|
3
|
+
// src/parse.ts
|
|
4
|
+
var BLOCK_REGEX = /\.(\w[\w-]*)\s*\{\s*@apply\s+([\s\S]*?)\s*\}/g;
|
|
5
|
+
function parseTwss(source) {
|
|
6
|
+
const styles = {};
|
|
7
|
+
let match;
|
|
8
|
+
while ((match = BLOCK_REGEX.exec(source)) !== null) {
|
|
9
|
+
const [, className, classes] = match;
|
|
10
|
+
styles[className] = classes.trim().replace(/\s+/g, " ");
|
|
11
|
+
}
|
|
12
|
+
return styles;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/vite-plugin.ts
|
|
16
|
+
function twssVitePlugin() {
|
|
17
|
+
return {
|
|
18
|
+
name: "tailwind-style-sheets",
|
|
19
|
+
transform(code, id) {
|
|
20
|
+
if (!id.endsWith(".twss")) return null;
|
|
21
|
+
const styles = parseTwss(code);
|
|
22
|
+
return {
|
|
23
|
+
code: `export default ${JSON.stringify(styles)};`,
|
|
24
|
+
map: null
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
handleHotUpdate({ file, server }) {
|
|
28
|
+
if (!file.endsWith(".twss")) return;
|
|
29
|
+
const mod = server.moduleGraph.getModuleById(file);
|
|
30
|
+
if (mod) {
|
|
31
|
+
server.moduleGraph.invalidateModule(mod);
|
|
32
|
+
server.hot.send({ type: "full-reload" });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
twssVitePlugin
|
|
39
|
+
};
|
package/package.json
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-style-sheets",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./vite": {
|
|
13
|
+
"types": "./dist/vite.d.mts",
|
|
14
|
+
"import": "./dist/vite.mjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
6
17
|
"bin": {
|
|
7
18
|
"tailwind-style-sheets": "./dist/cli.js"
|
|
8
19
|
},
|
|
9
20
|
"scripts": {
|
|
10
|
-
"build": "tsup",
|
|
21
|
+
"build": "rm -rf dist && tsup",
|
|
11
22
|
"dev": "tsup --watch"
|
|
12
23
|
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"tailwind-merge": "^3.5.0"
|
|
26
|
+
},
|
|
13
27
|
"peerDependencies": {
|
|
14
|
-
"
|
|
28
|
+
"modcn": "^0.0.1",
|
|
29
|
+
"next": ">=15",
|
|
30
|
+
"vite": ">=5"
|
|
31
|
+
},
|
|
32
|
+
"peerDependenciesMeta": {
|
|
33
|
+
"next": { "optional": true },
|
|
34
|
+
"vite": { "optional": true }
|
|
15
35
|
},
|
|
16
36
|
"publishConfig": {
|
|
17
37
|
"access": "public"
|
|
@@ -20,6 +40,7 @@
|
|
|
20
40
|
"@types/node": "^20",
|
|
21
41
|
"next": "16.2.1",
|
|
22
42
|
"tsup": "^8.5.1",
|
|
23
|
-
"typescript": "^5"
|
|
43
|
+
"typescript": "^5",
|
|
44
|
+
"vite": "^8.0.1"
|
|
24
45
|
}
|
|
25
46
|
}
|
package/src/index.ts
CHANGED
package/src/loader.ts
CHANGED
|
@@ -15,18 +15,10 @@
|
|
|
15
15
|
* Output (JS module):
|
|
16
16
|
* export default { base: "px-4 py-2 rounded font-semibold", primary: "bg-blue-600 text-white hover:bg-blue-700" }
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
import { parseTwss } from "./parse";
|
|
19
19
|
|
|
20
20
|
const twssLoader: (source: string) => string = function (source) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let match: RegExpExecArray | null;
|
|
24
|
-
while ((match = BLOCK_REGEX.exec(source)) !== null) {
|
|
25
|
-
const [, className, classes] = match;
|
|
26
|
-
styles[className] = classes.trim().replace(/\s+/g, " ");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return `export default ${JSON.stringify(styles)};`;
|
|
21
|
+
return `export default ${JSON.stringify(parseTwss(source))};`;
|
|
30
22
|
};
|
|
31
23
|
|
|
32
|
-
export
|
|
24
|
+
export default twssLoader;
|
package/src/parse.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const BLOCK_REGEX = /\.(\w[\w-]*)\s*\{\s*@apply\s+([\s\S]*?)\s*\}/g;
|
|
2
|
+
|
|
3
|
+
export function parseTwss(source: string): Record<string, string> {
|
|
4
|
+
const styles: Record<string, string> = {};
|
|
5
|
+
|
|
6
|
+
let match: RegExpExecArray | null;
|
|
7
|
+
while ((match = BLOCK_REGEX.exec(source)) !== null) {
|
|
8
|
+
const [, className, classes] = match;
|
|
9
|
+
styles[className] = classes.trim().replace(/\s+/g, " ");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return styles;
|
|
13
|
+
}
|
package/src/twcn.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { modcn } from "modcn";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
type StylesMap = Record<string, string>;
|
|
5
|
+
|
|
6
|
+
export function twcn(styles: StylesMap) {
|
|
7
|
+
const cn = modcn(styles);
|
|
8
|
+
return (...inputs: Parameters<ReturnType<typeof modcn>>) =>
|
|
9
|
+
twMerge(cn(...inputs));
|
|
10
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { parseTwss } from "./parse";
|
|
2
|
+
import type { Plugin } from "vite";
|
|
3
|
+
|
|
4
|
+
export function twssVitePlugin(): Plugin {
|
|
5
|
+
return {
|
|
6
|
+
name: "tailwind-style-sheets",
|
|
7
|
+
|
|
8
|
+
transform(code, id) {
|
|
9
|
+
if (!id.endsWith(".twss")) return null;
|
|
10
|
+
|
|
11
|
+
const styles = parseTwss(code);
|
|
12
|
+
return {
|
|
13
|
+
code: `export default ${JSON.stringify(styles)};`,
|
|
14
|
+
map: null,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
handleHotUpdate({ file, server }) {
|
|
19
|
+
if (!file.endsWith(".twss")) return;
|
|
20
|
+
|
|
21
|
+
const mod = server.moduleGraph.getModuleById(file);
|
|
22
|
+
if (mod) {
|
|
23
|
+
server.moduleGraph.invalidateModule(mod);
|
|
24
|
+
server.hot.send({ type: "full-reload" });
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
package/src/vite.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { twssVitePlugin } from "./vite-plugin";
|
package/tsconfig.json
CHANGED
package/tsup.config.ts
CHANGED