@udixio/tailwind 0.5.2 → 1.0.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,64 @@
1
+ # 1.0.0 (2025-08-04)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **tailwind:** readapts tailwind plugin ([5639159](https://github.com/Udixio/UI/commit/5639159))
6
+ - **theme:** add vite adapter ([0857e3e](https://github.com/Udixio/UI/commit/0857e3e))
7
+ - ⚠️ **theme:** replace `ConfigService` with abstract adapter-based architecture ([bf01991](https://github.com/Udixio/UI/commit/bf01991))
8
+ - **theme:** introduce `VitePlugin` and enhance plugin system ([8989e95](https://github.com/Udixio/UI/commit/8989e95))
9
+ - **theme:** migrate build system from Rollup to Vite for improved performance and configuration ([3f33657](https://github.com/Udixio/UI/commit/3f33657))
10
+ - **tailwind:** migrate build system to Vite for improved developer experience ([ae0fe46](https://github.com/Udixio/UI/commit/ae0fe46))
11
+ - **package:** add `publishConfig` to package.json for public npm publishing ([40307c0](https://github.com/Udixio/UI/commit/40307c0))
12
+ - **package:** add `repository` field to package.json files ([a05ca80](https://github.com/Udixio/UI/commit/a05ca80))
13
+ - **tailwind:** restructure packages and update dependencies ([0f62e58](https://github.com/Udixio/UI/commit/0f62e58))
14
+ - **tailwind:** refactor package structure and dependencies ([81b4640](https://github.com/Udixio/UI/commit/81b4640))
15
+ - **tailwind:** refactor plugin and integrate theme dependencies ([34501e3](https://github.com/Udixio/UI/commit/34501e3))
16
+ - **tailwind:** remove Tailwind library and update dependencies ([bd84038](https://github.com/Udixio/UI/commit/bd84038))
17
+ - **tailwind:** add initial Tailwind library setup ([8fd43f0](https://github.com/Udixio/UI/commit/8fd43f0))
18
+
19
+ ### 🩹 Fixes
20
+
21
+ - error lint ([33670ea](https://github.com/Udixio/UI/commit/33670ea))
22
+ - **dependencies:** update `pnpm-lock.yaml` for lockfile version and dependency adjustments ([22bb1a8](https://github.com/Udixio/UI/commit/22bb1a8))
23
+ - add `types` field to package exports and correct file extensions ([6b8ce9c](https://github.com/Udixio/UI/commit/6b8ce9c))
24
+ - **theme:** make config loading asynchronous to improve initialization flow ([d5de04f](https://github.com/Udixio/UI/commit/d5de04f))
25
+ - **dependencies:** update `pnpm-lock.yaml` for consistency and compatibility ([e6dfc9d](https://github.com/Udixio/UI/commit/e6dfc9d))
26
+ - **tailwind:** enable SSR in Vite build configuration ([d85e3a9](https://github.com/Udixio/UI/commit/d85e3a9))
27
+ - **theme:** switch to ES module exports and adjust package type ([7314ded](https://github.com/Udixio/UI/commit/7314ded))
28
+ - **tailwind:** update `main` field in package.json and clean up index export ([14f3b7a](https://github.com/Udixio/UI/commit/14f3b7a))
29
+
30
+ ### ⚠️ Breaking Changes
31
+
32
+ - ⚠️ **theme:** replace `ConfigService` with abstract adapter-based architecture ([bf01991](https://github.com/Udixio/UI/commit/bf01991))
33
+
34
+ ### 🧱 Updated Dependencies
35
+
36
+ - Updated @udixio/theme to 1.0.0
37
+
38
+ ### ❤️ Thank You
39
+
40
+ - Joël VIGREUX
41
+
42
+ ## 0.5.3 (2025-07-25)
43
+
44
+ ### 🩹 Fixes
45
+
46
+ - add `types` field to package exports and correct file extensions ([6b8ce9c](https://github.com/Udixio/UI/commit/6b8ce9c))
47
+
48
+ ### 🧱 Updated Dependencies
49
+
50
+ - Updated theme to 0.5.3
51
+
52
+ ### ❤️ Thank You
53
+
54
+ - Joël VIGREUX
55
+
56
+ ## 0.5.2 (2025-07-25)
57
+
58
+ ### 🧱 Updated Dependencies
59
+
60
+ - Updated theme to 0.5.2
61
+
1
62
  ## 0.5.1 (2025-07-25)
2
63
 
3
64
  ### 🩹 Fixes
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAIA,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,KACpB,MAAM,GAAG,IAyBX,CAAC"}
@@ -1,10 +1,13 @@
1
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);
2
5
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const theme = require("@udixio/theme");
4
6
  const plugin = require("tailwindcss/plugin");
5
7
  const fs = require("fs");
6
8
  const path = require("path");
7
9
  const replaceInFile = require("replace-in-file");
10
+ const theme = require("@udixio/theme");
8
11
  function _interopNamespaceDefault(e) {
9
12
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
10
13
  if (e) {
@@ -23,6 +26,138 @@ function _interopNamespaceDefault(e) {
23
26
  }
24
27
  const fs__namespace = /* @__PURE__ */ _interopNamespaceDefault(fs);
25
28
  const path__namespace = /* @__PURE__ */ _interopNamespaceDefault(path);
29
+ const defaultConfig = {
30
+ statePrefix: "state",
31
+ disabledStyles: {
32
+ textOpacity: 0.38,
33
+ backgroundOpacity: 0.12
34
+ },
35
+ transition: {
36
+ duration: 150
37
+ }
38
+ };
39
+ const state = plugin.withOptions(({ colorKeys }) => {
40
+ const resolved = {
41
+ ...defaultConfig,
42
+ disabledStyles: {
43
+ ...defaultConfig.disabledStyles,
44
+ ...{}
45
+ },
46
+ transition: {
47
+ ...defaultConfig.transition,
48
+ ...{}
49
+ }
50
+ };
51
+ return ({ addComponents }) => {
52
+ const newComponents = {};
53
+ for (const isGroup of [false, true]) {
54
+ const group = isGroup ? "group-" : "";
55
+ for (const colorName of colorKeys) {
56
+ const className = `.${group}${resolved.statePrefix}-${colorName}`;
57
+ newComponents[className] = {
58
+ [`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
59
+ [`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
60
+ [`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {},
61
+ [`@apply transition-colors`]: {},
62
+ [`@apply duration-${resolved.transition.duration}`]: {},
63
+ [`@apply ${group}disabled:text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
64
+ [`@apply ${group}disabled:bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
65
+ };
66
+ }
67
+ }
68
+ for (const colorName of colorKeys) {
69
+ for (const stateName of ["hover", "active", "focus", "disabled"]) {
70
+ const className = `.${stateName}-${resolved.statePrefix}-${colorName}`;
71
+ if (stateName === "disabled") {
72
+ newComponents[className] = {
73
+ [`@apply text-on-surface/[${resolved.disabledStyles.textOpacity}]`]: {},
74
+ [`@apply bg-on-surface/[${resolved.disabledStyles.backgroundOpacity}]`]: {}
75
+ };
76
+ } else {
77
+ const opacity = stateName === "hover" ? 0.08 : 0.12;
78
+ newComponents[className] = {
79
+ [`@apply bg-${colorName}/[${opacity}]`]: {}
80
+ };
81
+ }
82
+ }
83
+ }
84
+ addComponents(newComponents);
85
+ };
86
+ });
87
+ const font = plugin.withOptions((options) => {
88
+ return ({
89
+ addUtilities,
90
+ theme: theme2
91
+ }) => {
92
+ const { fontStyles, responsiveBreakPoints } = options;
93
+ const pixelUnit = "rem";
94
+ const newUtilities = {};
95
+ const baseTextStyle = (sizeValue) => ({
96
+ fontSize: sizeValue.fontSize + pixelUnit,
97
+ fontWeight: sizeValue.fontWeight,
98
+ lineHeight: sizeValue.lineHeight + pixelUnit,
99
+ letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
100
+ fontFamily: theme2("fontFamily." + sizeValue.fontFamily)
101
+ });
102
+ const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
103
+ [`@media (min-width: ${theme2("screens." + breakPointName, {})})`]: {
104
+ fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
105
+ lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
106
+ }
107
+ });
108
+ for (const [roleName, roleValue] of Object.entries(fontStyles)) {
109
+ for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
110
+ newUtilities[`.text-${roleName}-${sizeName}`] = {
111
+ ...baseTextStyle(sizeValue),
112
+ ...Object.entries(responsiveBreakPoints).reduce(
113
+ (acc, [breakPointName, breakPointRatio]) => ({
114
+ ...acc,
115
+ ...responsiveTextStyle(
116
+ sizeValue,
117
+ breakPointName,
118
+ breakPointRatio
119
+ )
120
+ }),
121
+ {}
122
+ )
123
+ };
124
+ }
125
+ }
126
+ addUtilities(newUtilities);
127
+ };
128
+ });
129
+ const main = plugin.withOptions((args) => {
130
+ const configCss = args;
131
+ const fontStyles = {};
132
+ configCss.fontStyles.forEach((line) => {
133
+ const [styleToken, ...properties] = line.split(" ");
134
+ const [roleToken, sizeToken] = styleToken.split("-");
135
+ fontStyles[roleToken] ?? (fontStyles[roleToken] = {});
136
+ properties.forEach((properties2) => {
137
+ var _a;
138
+ (_a = fontStyles[roleToken])[sizeToken] ?? (_a[sizeToken] = {});
139
+ const [key, value] = properties2.slice(0, -1).split("[");
140
+ fontStyles[roleToken][sizeToken][key] = value;
141
+ });
142
+ });
143
+ let breakPointsCss = configCss.responsiveBreakPoints;
144
+ if (!Array.isArray(breakPointsCss)) {
145
+ breakPointsCss = [breakPointsCss];
146
+ }
147
+ const responsiveBreakPoints = {};
148
+ breakPointsCss.forEach(([key, value]) => {
149
+ responsiveBreakPoints[key] = value;
150
+ });
151
+ const options = {
152
+ colorKeys: configCss.colorKeys,
153
+ fontStyles,
154
+ responsiveBreakPoints
155
+ };
156
+ return (api) => {
157
+ font(options).handler(api);
158
+ state(options).handler(api);
159
+ };
160
+ });
26
161
  const createOrUpdateFile = (filePath, content) => {
27
162
  try {
28
163
  if (!fs__namespace.existsSync(filePath)) {
@@ -112,122 +247,12 @@ const findTailwindCssFile = (startDir, searchPattern) => {
112
247
  }
113
248
  return null;
114
249
  };
115
- const state = (colorKeys) => plugin((pluginArgs) => {
116
- addAllNewComponents(
117
- pluginArgs,
118
- {
119
- statePrefix: "state",
120
- disabledStyles: {
121
- textOpacity: 0.38,
122
- backgroundOpacity: 0.12
123
- },
124
- transition: {
125
- duration: 150
126
- }
127
- },
128
- colorKeys
129
- );
130
- }, {});
131
- const addAllNewComponents = ({ addComponents }, { statePrefix, disabledStyles, transition }, colorKeys) => {
132
- const newComponents = {};
133
- for (const isGroup of [false, true]) {
134
- const group = isGroup ? "group-" : "";
135
- for (const colorName of colorKeys) {
136
- const className = `.${group}${statePrefix}-${colorName}`;
137
- newComponents[className] = {
138
- [`@apply ${group}hover:bg-${colorName}/[0.08]`]: {},
139
- [`@apply ${group}active:bg-${colorName}/[0.12]`]: {},
140
- [`@apply ${group}focus-visible:bg-${colorName}/[0.12]`]: {}
141
- };
142
- if (transition) {
143
- newComponents[className][`@apply transition-colors`] = {};
144
- newComponents[className][`@apply duration-${transition.duration}`] = {};
145
- }
146
- if (disabledStyles) {
147
- newComponents[className][`@apply ${group}disabled:text-on-surface/[${disabledStyles.textOpacity}]`] = {};
148
- newComponents[className][`@apply ${group}disabled:bg-on-surface/[${disabledStyles.backgroundOpacity}]`] = {};
149
- }
150
- }
151
- }
152
- for (const colorName of colorKeys) {
153
- for (const stateName of ["hover", "active", "focus", "disabled"]) {
154
- const className = `.${stateName}-${statePrefix}-${colorName}`;
155
- if (stateName === "active" || stateName === "focus") {
156
- newComponents[className] = {
157
- [`@apply bg-${colorName}/[0.12]`]: {}
158
- };
159
- } else if (stateName === "hover") {
160
- newComponents[className] = {
161
- [`@apply bg-${colorName}/[0.08]`]: {}
162
- };
163
- } else if (stateName === "disabled") {
164
- newComponents[className] = {
165
- [`@apply text-on-surface/[${disabledStyles.textOpacity}]`]: {}
166
- };
167
- newComponents[className] = {
168
- [`@apply bg-on-surface/[${disabledStyles.backgroundOpacity}]`]: {}
169
- };
170
- }
171
- }
172
- }
173
- addComponents(newComponents);
174
- };
175
- const font = (fontStyles, responsiveBreakPoints) => {
176
- const createUtilities = ({ theme: theme2 }) => {
177
- const pixelUnit = "rem";
178
- const newUtilities = {};
179
- const baseTextStyle = (sizeValue) => ({
180
- fontSize: sizeValue.fontSize + pixelUnit,
181
- fontWeight: sizeValue.fontWeight,
182
- lineHeight: sizeValue.lineHeight + pixelUnit,
183
- letterSpacing: sizeValue.letterSpacing ? sizeValue.letterSpacing + pixelUnit : null,
184
- fontFamily: theme2("fontFamily." + sizeValue.fontFamily)
185
- });
186
- const responsiveTextStyle = (sizeValue, breakPointName, breakPointRatio) => ({
187
- [`@media (min-width: ${theme2("screens." + breakPointName, {})})`]: {
188
- fontSize: sizeValue.fontSize * breakPointRatio + pixelUnit,
189
- lineHeight: sizeValue.lineHeight * breakPointRatio + pixelUnit
190
- }
191
- });
192
- for (const [roleName, roleValue] of Object.entries(fontStyles)) {
193
- for (const [sizeName, sizeValue] of Object.entries(roleValue)) {
194
- newUtilities[".text-" + roleName + "-" + sizeName] = {
195
- ...baseTextStyle(sizeValue),
196
- ...Object.entries(responsiveBreakPoints).reduce(
197
- (acc, [breakPointName, breakPointRatio]) => {
198
- acc = {
199
- ...acc,
200
- ...responsiveTextStyle(
201
- sizeValue,
202
- breakPointName,
203
- breakPointRatio
204
- )
205
- };
206
- return acc;
207
- },
208
- {}
209
- )
210
- };
211
- }
212
- }
213
- return newUtilities;
214
- };
215
- return plugin(
216
- ({
217
- addUtilities,
218
- theme: theme2
219
- }) => {
220
- const newUtilities = createUtilities({ theme: theme2 });
221
- addUtilities(newUtilities);
222
- }
223
- );
224
- };
225
250
  class TailwindPlugin extends theme.PluginAbstract {
226
251
  constructor() {
227
252
  super(...arguments);
228
- this.dependencies = [theme.FontPlugin];
229
- this.name = "tailwind";
230
- this.pluginClass = TailwindImplPlugin;
253
+ __publicField(this, "dependencies", [theme.FontPlugin]);
254
+ __publicField(this, "name", "tailwind");
255
+ __publicField(this, "pluginClass", TailwindImplPlugin);
231
256
  }
232
257
  }
233
258
  class TailwindImplPlugin extends theme.PluginImplAbstract {
@@ -237,13 +262,11 @@ class TailwindImplPlugin extends theme.PluginImplAbstract {
237
262
  lg: 1.125
238
263
  });
239
264
  }
240
- load() {
241
- const searchKeyword = '@plugin "@udixio/tailwind"';
265
+ onLoad() {
266
+ const searchKeyword = "@import 'tailwindcss';";
242
267
  const tailwindCssPath = this.options.styleFilePath ?? findTailwindCssFile(process.cwd(), searchKeyword);
243
268
  if (!tailwindCssPath) {
244
- throw new Error(
245
- 'The style file containing the Udixio plugin was not found.\n Please use it first. (@plugin "@udixio/tailwind")'
246
- );
269
+ throw new Error("The style file containing tailwind was not found.");
247
270
  }
248
271
  const searchPattern = /@import ["']tailwindcss["'];/;
249
272
  const replacement = `@import 'tailwindcss';
@@ -262,12 +285,28 @@ class TailwindImplPlugin extends theme.PluginImplAbstract {
262
285
  }
263
286
  }
264
287
  const { fontStyles, fontFamily } = this.api.plugins.getPlugin(theme.FontPlugin).getInstance().getFonts();
288
+ const configCss = {
289
+ colorKeys: Object.keys(colors).join(", "),
290
+ fontStyles: Object.entries(fontStyles).map(
291
+ ([fontRole, fontStyle]) => Object.entries(fontStyle).map(
292
+ ([fontSize, fontStyle2]) => `${fontRole}-${fontSize} ${Object.entries(fontStyle2).map(([name, value]) => `${name}[${value}]`).join(" ")}`
293
+ ).join(", ")
294
+ ).join(", "),
295
+ responsiveBreakPoints: Object.entries(
296
+ this.options.responsiveBreakPoints ?? {}
297
+ ).map(([key, value]) => `${key} ${value}`).join(", ")
298
+ };
265
299
  createOrUpdateFile(
266
300
  path.join(cssFilePath, "udixio.css"),
267
301
  `
302
+ @plugin "@udixio/tailwind" {
303
+ colorKeys: ${configCss.colorKeys};
304
+ fontStyles: ${configCss.fontStyles};
305
+ responsiveBreakPoints: ${configCss.responsiveBreakPoints};
306
+ }
268
307
  @custom-variant dark (&:where(.dark, .dark *));
269
308
  @theme {
270
- --color-*: initial;
309
+ --color-*: initial;
271
310
  ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.light};`).join("\n ")}
272
311
  }
273
312
  @layer theme {
@@ -275,39 +314,16 @@ class TailwindImplPlugin extends theme.PluginImplAbstract {
275
314
  ${Object.entries(colors).map(([key, value]) => `--color-${key}: ${value.dark};`).join("\n ")}
276
315
  }
277
316
  }
317
+ @theme {
318
+ ${Object.entries(fontFamily).map(
319
+ ([key, values]) => `--font-${key}: ${values.map((value) => `"${value}"`).join(", ")};`
320
+ ).join("\n ")}
321
+ }
278
322
  `
279
323
  );
280
- const plugins = [
281
- state(Object.keys(colors)),
282
- font(fontStyles, this.options.responsiveBreakPoints)
283
- ];
284
- return plugin.withOptions(
285
- // 1) factory(options) → la fonction “handler” du plugin
286
- (options = {}) => {
287
- return async function(api) {
288
- plugins.forEach((plugin2) => {
289
- plugin2.handler(api);
290
- });
291
- };
292
- },
293
- // 2) config(options) → objet à merger dans tailwind.config
294
- (options = {}) => {
295
- return {
296
- theme: {
297
- fontFamily
298
- }
299
- };
300
- }
301
- );
302
324
  }
303
325
  }
304
- const createTheme = async () => {
305
- const app = await theme.bootstrapFromConfig();
306
- const plugin2 = app.plugins.getPlugin(TailwindPlugin).getInstance();
307
- return plugin2.load();
308
- };
309
326
  exports.TailwindPlugin = TailwindPlugin;
310
- exports.createTheme = createTheme;
311
- exports.default = createTheme;
327
+ exports.default = main;
312
328
  exports.font = font;
313
329
  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"}