@udixio/tailwind 0.5.3 → 1.1.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/.eslintrc.mjs ADDED
@@ -0,0 +1,22 @@
1
+ import baseConfig from '../../eslint.config.mjs';
2
+
3
+ export default [
4
+ ...baseConfig,
5
+ {
6
+ files: ['**/*.json'],
7
+ rules: {
8
+ '@nx/dependency-checks': [
9
+ 'error',
10
+ {
11
+ ignoredFiles: [
12
+ '{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
13
+ '{projectRoot}/vite.config.{js,ts,mjs,mts}',
14
+ ],
15
+ },
16
+ ],
17
+ },
18
+ languageOptions: {
19
+ parser: await import('jsonc-eslint-parser'),
20
+ },
21
+ },
22
+ ];
package/CHANGELOG.md CHANGED
@@ -1,3 +1,68 @@
1
+ ## 1.1.0 (2025-08-21)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **doc:** integrate Udixio ecosystem into Astro project ([ca6b750](https://github.com/Udixio/UI/commit/ca6b750))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - Joël VIGREUX
10
+
11
+ # 1.0.0 (2025-08-04)
12
+
13
+ ### 🚀 Features
14
+
15
+ - **tailwind:** readapts tailwind plugin ([5639159](https://github.com/Udixio/UI/commit/5639159))
16
+ - **theme:** add vite adapter ([0857e3e](https://github.com/Udixio/UI/commit/0857e3e))
17
+ - ⚠️ **theme:** replace `ConfigService` with abstract adapter-based architecture ([bf01991](https://github.com/Udixio/UI/commit/bf01991))
18
+ - **theme:** introduce `VitePlugin` and enhance plugin system ([8989e95](https://github.com/Udixio/UI/commit/8989e95))
19
+ - **theme:** migrate build system from Rollup to Vite for improved performance and configuration ([3f33657](https://github.com/Udixio/UI/commit/3f33657))
20
+ - **tailwind:** migrate build system to Vite for improved developer experience ([ae0fe46](https://github.com/Udixio/UI/commit/ae0fe46))
21
+ - **package:** add `publishConfig` to package.json for public npm publishing ([40307c0](https://github.com/Udixio/UI/commit/40307c0))
22
+ - **package:** add `repository` field to package.json files ([a05ca80](https://github.com/Udixio/UI/commit/a05ca80))
23
+ - **tailwind:** restructure packages and update dependencies ([0f62e58](https://github.com/Udixio/UI/commit/0f62e58))
24
+ - **tailwind:** refactor package structure and dependencies ([81b4640](https://github.com/Udixio/UI/commit/81b4640))
25
+ - **tailwind:** refactor plugin and integrate theme dependencies ([34501e3](https://github.com/Udixio/UI/commit/34501e3))
26
+ - **tailwind:** remove Tailwind library and update dependencies ([bd84038](https://github.com/Udixio/UI/commit/bd84038))
27
+ - **tailwind:** add initial Tailwind library setup ([8fd43f0](https://github.com/Udixio/UI/commit/8fd43f0))
28
+
29
+ ### 🩹 Fixes
30
+
31
+ - error lint ([33670ea](https://github.com/Udixio/UI/commit/33670ea))
32
+ - **dependencies:** update `pnpm-lock.yaml` for lockfile version and dependency adjustments ([22bb1a8](https://github.com/Udixio/UI/commit/22bb1a8))
33
+ - add `types` field to package exports and correct file extensions ([6b8ce9c](https://github.com/Udixio/UI/commit/6b8ce9c))
34
+ - **theme:** make config loading asynchronous to improve initialization flow ([d5de04f](https://github.com/Udixio/UI/commit/d5de04f))
35
+ - **dependencies:** update `pnpm-lock.yaml` for consistency and compatibility ([e6dfc9d](https://github.com/Udixio/UI/commit/e6dfc9d))
36
+ - **tailwind:** enable SSR in Vite build configuration ([d85e3a9](https://github.com/Udixio/UI/commit/d85e3a9))
37
+ - **theme:** switch to ES module exports and adjust package type ([7314ded](https://github.com/Udixio/UI/commit/7314ded))
38
+ - **tailwind:** update `main` field in package.json and clean up index export ([14f3b7a](https://github.com/Udixio/UI/commit/14f3b7a))
39
+
40
+ ### ⚠️ Breaking Changes
41
+
42
+ - ⚠️ **theme:** replace `ConfigService` with abstract adapter-based architecture ([bf01991](https://github.com/Udixio/UI/commit/bf01991))
43
+
44
+ ### 🧱 Updated Dependencies
45
+
46
+ - Updated @udixio/theme to 1.0.0
47
+
48
+ ### ❤️ Thank You
49
+
50
+ - Joël VIGREUX
51
+
52
+ ## 0.5.3 (2025-07-25)
53
+
54
+ ### 🩹 Fixes
55
+
56
+ - add `types` field to package exports and correct file extensions ([6b8ce9c](https://github.com/Udixio/UI/commit/6b8ce9c))
57
+
58
+ ### 🧱 Updated Dependencies
59
+
60
+ - Updated theme to 0.5.3
61
+
62
+ ### ❤️ Thank You
63
+
64
+ - Joël VIGREUX
65
+
1
66
  ## 0.5.2 (2025-07-25)
2
67
 
3
68
  ### 🧱 Updated Dependencies
@@ -1,5 +1,6 @@
1
1
  export declare const createOrUpdateFile: (filePath: string, content: string) => void;
2
2
  export declare const getFileContent: (filePath: string, searchPattern?: RegExp | string) => string | false | null;
3
3
  export declare const replaceFileContent: (filePath: string, searchPattern: RegExp | string, replacement: string) => void;
4
- export declare const findTailwindCssFile: (startDir: string, searchPattern: string) => string | null;
4
+ export declare const findTailwindCssFile: (startDir: string, searchPattern: RegExp | string) => string | never;
5
+ export declare function findProjectRoot(startPath: any): any;
5
6
  //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,EAAE,SAAS,MAAM,KAAG,IAmBtE,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,EAChB,gBAAgB,MAAM,GAAG,MAAM,KAC9B,MAAM,GAAG,KAAK,GAAG,IA4CnB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,EAChB,eAAe,MAAM,GAAG,MAAM,EAC9B,aAAa,MAAM,KAClB,IAkBF,CAAC;AACF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,MAAM,EAChB,eAAe,MAAM,GAAG,MAAM,KAC7B,MAAM,GAAG,KA8CX,CAAC;AAEF,wBAAgB,eAAe,CAAC,SAAS,KAAA,OAaxC"}
package/dist/index.cjs ADDED
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
6
+ const plugin = require("tailwindcss/plugin");
7
+ const fs = require("fs");
8
+ const path = require("path");
9
+ const replaceInFile = require("replace-in-file");
10
+ const console = require("node:console");
11
+ const theme = require("@udixio/theme");
12
+ function _interopNamespaceDefault(e) {
13
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
14
+ if (e) {
15
+ for (const k in e) {
16
+ if (k !== "default") {
17
+ const d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: () => e[k]
21
+ });
22
+ }
23
+ }
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+ const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
29
+ const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
30
+ const console__namespace = /* @__PURE__ */ _interopNamespaceDefault(console);
31
+ const defaultConfig = {
32
+ statePrefix: "state",
33
+ disabledStyles: {
34
+ textOpacity: 0.38,
35
+ backgroundOpacity: 0.12
36
+ },
37
+ transition: {
38
+ duration: 150
39
+ }
40
+ };
41
+ const state = plugin.withOptions(({ colorKeys }) => {
42
+ const resolved = {
43
+ ...defaultConfig,
44
+ disabledStyles: {
45
+ ...defaultConfig.disabledStyles,
46
+ ...{}
47
+ },
48
+ transition: {
49
+ ...defaultConfig.transition,
50
+ ...{}
51
+ }
52
+ };
53
+ return ({ addComponents }) => {
54
+ const newComponents = {};
55
+ for (const isGroup of [false, true]) {
56
+ const group = isGroup ? "group-" : "";
57
+ for (const colorName of colorKeys) {
58
+ const className = `.${group}${resolved.statePrefix}-${colorName}`;
59
+ newComponents[className] = {
60
+ [`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
61
+ [`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
62
+ [`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {},
63
+ [`@apply transition-colors`]: {},
64
+ [`@apply duration-${resolved.transition.duration}`]: {},
65
+ [`@apply ${group}disabled:text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
66
+ [`@apply ${group}disabled:bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
67
+ };
68
+ }
69
+ }
70
+ for (const colorName of colorKeys) {
71
+ for (const stateName of ["hover", "active", "focus", "disabled"]) {
72
+ const className = `.${stateName}-${resolved.statePrefix}-${colorName}`;
73
+ if (stateName === "disabled") {
74
+ newComponents[className] = {
75
+ [`@apply text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
76
+ [`@apply bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
77
+ };
78
+ } else {
79
+ const opacity = stateName === "hover" ? 0.08 : 0.12;
80
+ newComponents[className] = {
81
+ [`@apply bg-${colorName}/[${opacity}]`]: {}
82
+ };
83
+ }
84
+ }
85
+ }
86
+ addComponents(newComponents);
87
+ };
88
+ });
89
+ const font = plugin.withOptions((options) => {
90
+ return ({
91
+ addUtilities,
92
+ theme: theme2
93
+ }) => {
94
+ const { fontStyles, responsiveBreakPoints } = options;
95
+ const pixelUnit = "rem";
96
+ const newUtilities = {};
97
+ const baseTextStyle = (sizeValue) => ({
98
+ fontSize: sizeValue.fontSize + pixelUnit,
99
+ fontWeight: sizeValue.fontWeight,
100
+ lineHeight: sizeValue.lineHeight + pixelUnit,
101
+ letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
102
+ fontFamily: theme2("fontFamily." + sizeValue.fontFamily)
103
+ });
104
+ const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
105
+ [`@media (min-width: ${theme2("screens." + breakPointName, {})})`]: {
106
+ fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
107
+ lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
108
+ }
109
+ });
110
+ for (const [roleName, roleValue] of Object.entries(fontStyles)) {
111
+ for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
112
+ newUtilities[`.text-${roleName}-${sizeName}`] = {
113
+ ...baseTextStyle(sizeValue),
114
+ ...Object.entries(responsiveBreakPoints).reduce(
115
+ (acc, [breakPointName, breakPointRatio]) => ({
116
+ ...acc,
117
+ ...responsiveTextStyle(
118
+ sizeValue,
119
+ breakPointName,
120
+ breakPointRatio
121
+ )
122
+ }),
123
+ {}
124
+ )
125
+ };
126
+ }
127
+ }
128
+ addUtilities(newUtilities);
129
+ };
130
+ });
131
+ const main = plugin.withOptions((args) => {
132
+ const configCss = args;
133
+ const fontStyles = {};
134
+ configCss.fontStyles.forEach((line) => {
135
+ const [styleToken, ...properties] = line.split(" ");
136
+ const [roleToken, sizeToken] = styleToken.split("-");
137
+ fontStyles[roleToken] ?? (fontStyles[roleToken] = {});
138
+ properties.forEach((properties2) => {
139
+ var _a;
140
+ (_a = fontStyles[roleToken])[sizeToken] ?? (_a[sizeToken] = {});
141
+ const [key, value] = properties2.slice(0, -1).split("[");
142
+ fontStyles[roleToken][sizeToken][key] = value;
143
+ });
144
+ });
145
+ let breakPointsCss = configCss.responsiveBreakPoints;
146
+ if (!Array.isArray(breakPointsCss)) {
147
+ breakPointsCss = [breakPointsCss];
148
+ }
149
+ const responsiveBreakPoints = {};
150
+ breakPointsCss.forEach(([key, value]) => {
151
+ responsiveBreakPoints[key] = value;
152
+ });
153
+ const options = {
154
+ colorKeys: configCss.colorKeys,
155
+ fontStyles,
156
+ responsiveBreakPoints
157
+ };
158
+ return (api) => {
159
+ font(options).handler(api);
160
+ state(options).handler(api);
161
+ };
162
+ });
163
+ const createOrUpdateFile = (filePath, content) => {
164
+ try {
165
+ if (!fs__namespace.existsSync(filePath)) {
166
+ const dirPath = path__namespace.dirname(filePath);
167
+ if (!fs__namespace.existsSync(dirPath)) {
168
+ fs__namespace.mkdirSync(dirPath, { recursive: true });
169
+ }
170
+ fs__namespace.writeFileSync(filePath, content);
171
+ console__namespace.log(`✅ File successfully created: ${filePath}`);
172
+ } else {
173
+ console__namespace.log(`⚠️ File already exists: ${filePath}`);
174
+ replaceFileContent(filePath, /[\s\S]*/, content);
175
+ }
176
+ } catch (error) {
177
+ console__namespace.error("❌ Error while creating the file:", error);
178
+ }
179
+ };
180
+ const getFileContent = (filePath, searchPattern) => {
181
+ try {
182
+ if (!fs__namespace.existsSync(filePath)) {
183
+ console__namespace.error(`❌ The specified file does not exist: ${filePath}`);
184
+ return null;
185
+ }
186
+ const fileContent = fs__namespace.readFileSync(filePath, "utf8");
187
+ if (searchPattern) {
188
+ if (typeof searchPattern === "string") {
189
+ const found = fileContent.includes(searchPattern) ? searchPattern : false;
190
+ console__namespace.log(
191
+ found ? `✅ The file contains the specified string: "${searchPattern}"` : `⚠️ The file does NOT contain the specified string: "${searchPattern}"`
192
+ );
193
+ return found;
194
+ } else {
195
+ const match = fileContent.match(searchPattern);
196
+ if (match) {
197
+ console__namespace.log(`✅ Found match: "${match[0]}"`);
198
+ return match[0];
199
+ } else {
200
+ console__namespace.log(
201
+ `⚠️ No match found for the pattern: "${searchPattern.toString()}"`
202
+ );
203
+ return false;
204
+ }
205
+ }
206
+ }
207
+ console__namespace.log(`✅ File content successfully retrieved.`);
208
+ return fileContent;
209
+ } catch (error) {
210
+ console__namespace.error("❌ An error occurred while processing the file:", error);
211
+ return null;
212
+ }
213
+ };
214
+ const replaceFileContent = (filePath, searchPattern, replacement) => {
215
+ try {
216
+ const results = replaceInFile.replaceInFileSync({
217
+ files: filePath,
218
+ from: searchPattern,
219
+ to: replacement
220
+ });
221
+ if (results.length > 0 && results[0].hasChanged) {
222
+ console__namespace.log(`✅ Content successfully replaced in the file: ${filePath}`);
223
+ } else {
224
+ console__namespace.log(
225
+ `⚠️ No replacement made. Here are some possible reasons:
226
+ - The pattern ${searchPattern} was not found.
227
+ - The file might already contain the expected content.`
228
+ );
229
+ }
230
+ } catch (error) {
231
+ console__namespace.error("❌ Error while replacing the file content:", error);
232
+ }
233
+ };
234
+ const findTailwindCssFile = (startDir, searchPattern) => {
235
+ console__namespace.log("Recherche du fichier contenant le motif...", startDir);
236
+ const stack = [startDir];
237
+ while (stack.length > 0) {
238
+ const currentDir = stack.pop();
239
+ const files = fs__namespace.readdirSync(currentDir);
240
+ for (const file of files) {
241
+ const filePath = path__namespace.join(currentDir, file);
242
+ let stats;
243
+ try {
244
+ stats = fs__namespace.statSync(filePath);
245
+ } catch (error) {
246
+ console__namespace.error(`Erreur lors de l'accès à ${filePath}:`, error);
247
+ continue;
248
+ }
249
+ if (stats.isDirectory()) {
250
+ if (file !== "node_modules") stack.push(filePath);
251
+ } else if (stats.isFile() && (file.endsWith(".css") || file.endsWith(".scss") || file.endsWith(".sass"))) {
252
+ try {
253
+ console__namespace.log(`Analyse du fichier : ${filePath}`);
254
+ const content = fs__namespace.readFileSync(filePath, "utf8");
255
+ if (content.match(searchPattern)) {
256
+ console__namespace.log("Fichier trouvé :", filePath);
257
+ return filePath;
258
+ }
259
+ } catch (readError) {
260
+ console__namespace.error(`Erreur lors de la lecture de ${filePath}:`, readError);
261
+ }
262
+ }
263
+ }
264
+ }
265
+ throw new Error(
266
+ `Impossible de trouver un fichier contenant "${searchPattern}" dans "${startDir}".`
267
+ );
268
+ };
269
+ function findProjectRoot(startPath) {
270
+ let currentPath = startPath;
271
+ while (!fs__namespace.existsSync(path__namespace.join(currentPath, "package.json"))) {
272
+ const parentPath = path__namespace.dirname(currentPath);
273
+ if (currentPath === parentPath) {
274
+ throw new Error("Impossible de localiser la racine du projet.");
275
+ }
276
+ currentPath = parentPath;
277
+ }
278
+ return currentPath;
279
+ }
280
+ class TailwindPlugin extends theme.PluginAbstract {
281
+ constructor() {
282
+ super(...arguments);
283
+ __publicField(this, "dependencies", [theme.FontPlugin]);
284
+ __publicField(this, "name", "tailwind");
285
+ __publicField(this, "pluginClass", TailwindImplPlugin);
286
+ }
287
+ }
288
+ class TailwindImplPlugin extends theme.PluginImplAbstract {
289
+ onInit() {
290
+ var _a;
291
+ (_a = this.options).responsiveBreakPoints ?? (_a.responsiveBreakPoints = {
292
+ lg: 1.125
293
+ });
294
+ }
295
+ onLoad() {
296
+ let udixioCssPath = this.options.styleFilePath;
297
+ const projectRoot = findProjectRoot(path.resolve());
298
+ if (!udixioCssPath) {
299
+ const searchPattern = /@import ["']tailwindcss["'];/;
300
+ const replacement = `@import 'tailwindcss';
301
+ @import "./udixio.css";`;
302
+ const tailwindCssPath = findTailwindCssFile(projectRoot, searchPattern);
303
+ udixioCssPath = path.join(tailwindCssPath, "../udixio.css");
304
+ console__namespace.log("rrgfgt", tailwindCssPath, udixioCssPath);
305
+ if (!getFileContent(tailwindCssPath, /@import\s+"\.\/udixio\.css";/)) {
306
+ replaceFileContent(tailwindCssPath, searchPattern, replacement);
307
+ }
308
+ }
309
+ const colors = {};
310
+ for (const isDark of [false, true]) {
311
+ this.api.themes.update({ isDark });
312
+ for (const [key, value] of this.api.colors.getColors().entries()) {
313
+ const newKey = key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
314
+ colors[newKey] ?? (colors[newKey] = { light: "", dark: "" });
315
+ colors[newKey][isDark ? "dark" : "light"] = value.getHex();
316
+ }
317
+ }
318
+ const { fontStyles, fontFamily } = this.api.plugins.getPlugin(theme.FontPlugin).getInstance().getFonts();
319
+ const configCss = {
320
+ colorKeys: Object.keys(colors).join(", "),
321
+ fontStyles: Object.entries(fontStyles).map(
322
+ ([fontRole, fontStyle]) => Object.entries(fontStyle).map(
323
+ ([fontSize, fontStyle2]) => `${fontRole}-${fontSize} ${Object.entries(fontStyle2).map(([name, value]) => `${name}[${value}]`).join(" ")}`
324
+ ).join(", ")
325
+ ).join(", "),
326
+ responsiveBreakPoints: Object.entries(
327
+ this.options.responsiveBreakPoints ?? {}
328
+ ).map(([key, value]) => `${key} ${value}`).join(", ")
329
+ };
330
+ createOrUpdateFile(
331
+ udixioCssPath,
332
+ `
333
+ @plugin "@udixio/tailwind" {
334
+ colorKeys: ${configCss.colorKeys};
335
+ fontStyles: ${configCss.fontStyles};
336
+ responsiveBreakPoints: ${configCss.responsiveBreakPoints};
337
+ }
338
+ @custom-variant dark (&:where(.dark, .dark *));
339
+ @theme {
340
+ --color-*: initial;
341
+ ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.light};`).join("\n ")}
342
+ }
343
+ @layer theme {
344
+ .dark {
345
+ ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.dark};`).join("\n ")}
346
+ }
347
+ }
348
+ @theme {
349
+ ${Object.entries(fontFamily).map(
350
+ ([key, values]) => `--font-${key}: ${values.map((value) => `"${value}"`).join(", ")};`
351
+ ).join("\n ")}
352
+ }
353
+ `
354
+ );
355
+ }
356
+ }
357
+ exports.TailwindPlugin = TailwindPlugin;
358
+ exports.default = main;
359
+ exports.font = font;
360
+ exports.state = state;
@@ -0,0 +1,5 @@
1
+ import { main } from './main';
2
+ export * from './plugins-tailwind';
3
+ export * from './tailwind.plugin';
4
+ export default main;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,eAAe,IAAI,CAAC"}