@itamarshdev/reactwind 0.1.1 → 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/README.md CHANGED
@@ -12,11 +12,11 @@
12
12
  ## 📦 Installation
13
13
 
14
14
  ```bash
15
- npm install reactwind
15
+ npm install @itamarshdev/reactwind
16
16
  # or
17
- bun add reactwind
17
+ bun add @itamarshdev/reactwind
18
18
  # or
19
- yarn add reactwind
19
+ yarn add @itamarshdev/reactwind
20
20
  ```
21
21
 
22
22
 
@@ -86,6 +86,50 @@ export default defineConfig({
86
86
  </div>
87
87
  ```
88
88
 
89
+ ### 3. Modifier Props (Hover, Focus, Responsive, etc.)
90
+
91
+ ```tsx
92
+ // Hyphenated syntax
93
+ <button hover-bg="blue-700" hover-scale="105" focus-ring="2">
94
+ Hover Me
95
+ </button>
96
+
97
+ // Object syntax for multiple props per modifier
98
+ <button hover={{ bg: "blue-700", scale: "105", shadow: "lg" }}>
99
+ Hover Me
100
+ </button>
101
+
102
+ // Stacked modifiers via nesting
103
+ <div dark={{ hover: { bg: "slate-800", text: "white" } }}>
104
+ Dark mode hover styles
105
+ </div>
106
+
107
+ // Responsive breakpoints
108
+ <div md={{ flex: true, gap: "4" }} lg={{ gap: "8" }}>
109
+ Responsive layout
110
+ </div>
111
+ ```
112
+
113
+ ### 4. Position & Layout Props
114
+
115
+ ```tsx
116
+ <div absolute top="0" right="0" inset-x="4">
117
+ Positioned element
118
+ </div>
119
+
120
+ <div grid grid-cols="3" gap-x="4" gap-y="2">
121
+ Grid with different gaps
122
+ </div>
123
+ ```
124
+
125
+ ### 5. Gradient & Background Props
126
+
127
+ ```tsx
128
+ <div bg-gradient="to-r" from="blue-500" via="purple-500" to="pink-500">
129
+ Gradient background
130
+ </div>
131
+ ```
132
+
89
133
  ---
90
134
 
91
135
  ## 🎯 Goals
@@ -0,0 +1,232 @@
1
+ // src/runtime.ts
2
+ var LAYOUT_PROPS = [
3
+ "flex",
4
+ "grid",
5
+ "hidden",
6
+ "block",
7
+ "inline",
8
+ "inline-block",
9
+ "inline-flex",
10
+ "inline-grid",
11
+ "relative",
12
+ "absolute",
13
+ "fixed",
14
+ "sticky",
15
+ "static",
16
+ "flex-row",
17
+ "flex-col",
18
+ "flex-wrap",
19
+ "flex-nowrap",
20
+ "items-center",
21
+ "items-start",
22
+ "items-end",
23
+ "justify-center",
24
+ "justify-between",
25
+ "justify-start",
26
+ "justify-end",
27
+ "grow",
28
+ "shrink",
29
+ "italic",
30
+ "not-italic",
31
+ "underline",
32
+ "uppercase",
33
+ "lowercase",
34
+ "capitalize",
35
+ "truncate",
36
+ "visible",
37
+ "invisible",
38
+ "collapse",
39
+ "pointer-events-none",
40
+ "pointer-events-auto",
41
+ "sr-only",
42
+ "not-sr-only"
43
+ ];
44
+ var VALUE_PROPS_MAP = {
45
+ bg: "bg",
46
+ text: "text",
47
+ border: "border",
48
+ fill: "fill",
49
+ stroke: "stroke",
50
+ p: "p",
51
+ m: "m",
52
+ px: "px",
53
+ py: "py",
54
+ mx: "mx",
55
+ my: "my",
56
+ gap: "gap",
57
+ w: "w",
58
+ h: "h",
59
+ rounded: "rounded",
60
+ shadow: "shadow",
61
+ font: "font",
62
+ z: "z",
63
+ mb: "mb",
64
+ mt: "mt",
65
+ ml: "ml",
66
+ mr: "mr",
67
+ pb: "pb",
68
+ pt: "pt",
69
+ pl: "pl",
70
+ pr: "pr",
71
+ tracking: "tracking",
72
+ leading: "leading",
73
+ "max-w": "max-w",
74
+ "min-w": "min-w",
75
+ "min-h": "min-h",
76
+ "max-h": "max-h",
77
+ overflow: "overflow",
78
+ decoration: "decoration",
79
+ whitespace: "whitespace",
80
+ break: "break",
81
+ content: "content",
82
+ opacity: "opacity",
83
+ "bg-opacity": "bg-opacity",
84
+ ring: "ring",
85
+ "ring-offset": "ring-offset",
86
+ outline: "outline",
87
+ divide: "divide",
88
+ "mix-blend": "mix-blend",
89
+ "backdrop-blur": "backdrop-blur",
90
+ blur: "blur",
91
+ brightness: "brightness",
92
+ contrast: "contrast",
93
+ grayscale: "grayscale",
94
+ "hue-rotate": "hue-rotate",
95
+ invert: "invert",
96
+ saturate: "saturate",
97
+ sepia: "sepia",
98
+ "drop-shadow": "drop-shadow",
99
+ transition: "transition",
100
+ duration: "duration",
101
+ ease: "ease",
102
+ delay: "delay",
103
+ animate: "animate",
104
+ cursor: "cursor",
105
+ "pointer-events": "pointer-events",
106
+ resize: "resize",
107
+ select: "select",
108
+ scale: "scale",
109
+ rotate: "rotate",
110
+ translate: "translate",
111
+ skew: "skew",
112
+ origin: "origin"
113
+ };
114
+ var MODIFIERS = [
115
+ "hover",
116
+ "focus",
117
+ "active",
118
+ "visited",
119
+ "disabled",
120
+ "group-hover",
121
+ "group-focus",
122
+ "focus-within",
123
+ "focus-visible",
124
+ "target",
125
+ "first",
126
+ "last",
127
+ "only",
128
+ "odd",
129
+ "even",
130
+ "first-of-type",
131
+ "last-of-type",
132
+ "only-of-type",
133
+ "empty",
134
+ "checked",
135
+ "indeterminate",
136
+ "default",
137
+ "required",
138
+ "valid",
139
+ "invalid",
140
+ "in-range",
141
+ "out-of-range",
142
+ "placeholder-shown",
143
+ "autofill",
144
+ "read-only",
145
+ "open",
146
+ // Responsive breakpoints
147
+ "sm",
148
+ "md",
149
+ "lg",
150
+ "xl",
151
+ "2xl",
152
+ // Dark mode
153
+ "dark",
154
+ // Print
155
+ "print"
156
+ ];
157
+ var joinClassNames = (classNames) => {
158
+ if (!classNames || classNames.length === 0) {
159
+ return "";
160
+ }
161
+ return classNames.filter(Boolean).join(" ");
162
+ };
163
+ var withClassNames = (props) => {
164
+ if (!props) {
165
+ return props;
166
+ }
167
+ const hasClassNames = "classNames" in props;
168
+ const hasLayoutProps = LAYOUT_PROPS.some((k) => k in props);
169
+ const hasValueProps = Object.keys(VALUE_PROPS_MAP).some((k) => k in props);
170
+ const propsKeys = Object.keys(props);
171
+ const hasModifiers = propsKeys.some((key) => {
172
+ return MODIFIERS.some((mod) => key.startsWith(`${mod}-`));
173
+ });
174
+ if (!hasClassNames && !hasLayoutProps && !hasValueProps && !hasModifiers) {
175
+ return props;
176
+ }
177
+ const { classNames, className, ...rest } = props;
178
+ const generatedClasses = [];
179
+ const cleanRest = { ...rest };
180
+ for (const prop of LAYOUT_PROPS) {
181
+ if (prop in cleanRest && cleanRest[prop] === true) {
182
+ generatedClasses.push(prop);
183
+ delete cleanRest[prop];
184
+ }
185
+ }
186
+ for (const [prop, prefix] of Object.entries(VALUE_PROPS_MAP)) {
187
+ if (prop in cleanRest) {
188
+ const value = cleanRest[prop];
189
+ if (typeof value === "string" || typeof value === "number") {
190
+ generatedClasses.push(`${prefix}-${value}`);
191
+ delete cleanRest[prop];
192
+ } else if (value === true && (prop === "shadow" || prop === "rounded" || prop === "border" || prop === "transition")) {
193
+ generatedClasses.push(prop);
194
+ delete cleanRest[prop];
195
+ }
196
+ }
197
+ }
198
+ Object.keys(cleanRest).forEach((key) => {
199
+ const firstHyphenIndex = key.indexOf("-");
200
+ if (firstHyphenIndex === -1) return;
201
+ const modifier = key.substring(0, firstHyphenIndex);
202
+ if (MODIFIERS.includes(modifier)) {
203
+ const restKey = key.substring(firstHyphenIndex + 1);
204
+ const value = cleanRest[key];
205
+ if (restKey in VALUE_PROPS_MAP) {
206
+ const prefix = VALUE_PROPS_MAP[restKey];
207
+ if (typeof value === "string" || typeof value === "number") {
208
+ generatedClasses.push(`${modifier}:${prefix}-${value}`);
209
+ delete cleanRest[key];
210
+ } else if (value === true && (restKey === "shadow" || restKey === "rounded" || restKey === "border")) {
211
+ generatedClasses.push(`${modifier}:${restKey}`);
212
+ delete cleanRest[key];
213
+ }
214
+ } else if (LAYOUT_PROPS.includes(restKey)) {
215
+ if (value === true) {
216
+ generatedClasses.push(`${modifier}:${restKey}`);
217
+ delete cleanRest[key];
218
+ }
219
+ }
220
+ }
221
+ });
222
+ const joined = joinClassNames(classNames || []);
223
+ const merged = [className, ...generatedClasses, joined].filter(Boolean).join(" ");
224
+ return {
225
+ ...cleanRest,
226
+ ...merged ? { className: merged } : {}
227
+ };
228
+ };
229
+
230
+ export {
231
+ withClassNames
232
+ };
@@ -0,0 +1,341 @@
1
+ // src/runtime.ts
2
+ var LAYOUT_PROPS = [
3
+ "flex",
4
+ "grid",
5
+ "hidden",
6
+ "block",
7
+ "inline",
8
+ "inline-block",
9
+ "inline-flex",
10
+ "inline-grid",
11
+ "relative",
12
+ "absolute",
13
+ "fixed",
14
+ "sticky",
15
+ "static",
16
+ "flex-row",
17
+ "flex-col",
18
+ "flex-wrap",
19
+ "flex-nowrap",
20
+ "items-center",
21
+ "items-start",
22
+ "items-end",
23
+ "justify-center",
24
+ "justify-between",
25
+ "justify-start",
26
+ "justify-end",
27
+ "grow",
28
+ "shrink",
29
+ "italic",
30
+ "not-italic",
31
+ "underline",
32
+ "uppercase",
33
+ "lowercase",
34
+ "capitalize",
35
+ "truncate",
36
+ "visible",
37
+ "invisible",
38
+ "collapse",
39
+ "pointer-events-none",
40
+ "pointer-events-auto",
41
+ "sr-only",
42
+ "not-sr-only"
43
+ ];
44
+ var VALUE_PROPS_MAP = {
45
+ bg: "bg",
46
+ text: "text",
47
+ border: "border",
48
+ fill: "fill",
49
+ stroke: "stroke",
50
+ p: "p",
51
+ m: "m",
52
+ px: "px",
53
+ py: "py",
54
+ mx: "mx",
55
+ my: "my",
56
+ gap: "gap",
57
+ w: "w",
58
+ h: "h",
59
+ rounded: "rounded",
60
+ shadow: "shadow",
61
+ font: "font",
62
+ z: "z",
63
+ mb: "mb",
64
+ mt: "mt",
65
+ ml: "ml",
66
+ mr: "mr",
67
+ pb: "pb",
68
+ pt: "pt",
69
+ pl: "pl",
70
+ pr: "pr",
71
+ tracking: "tracking",
72
+ leading: "leading",
73
+ "max-w": "max-w",
74
+ "min-w": "min-w",
75
+ "min-h": "min-h",
76
+ "max-h": "max-h",
77
+ "grid-cols": "grid-cols",
78
+ "col-span": "col-span",
79
+ "row-span": "row-span",
80
+ "grid-rows": "grid-rows",
81
+ "items": "items",
82
+ "justify": "justify",
83
+ "self": "self",
84
+ "place-content": "place-content",
85
+ "place-items": "place-items",
86
+ "place-self": "place-self",
87
+ "order": "order",
88
+ overflow: "overflow",
89
+ decoration: "decoration",
90
+ whitespace: "whitespace",
91
+ break: "break",
92
+ content: "content",
93
+ opacity: "opacity",
94
+ "bg-opacity": "bg-opacity",
95
+ "text-opacity": "text-opacity",
96
+ "border-opacity": "border-opacity",
97
+ ring: "ring",
98
+ "ring-offset": "ring-offset",
99
+ outline: "outline",
100
+ divide: "divide",
101
+ "mix-blend": "mix-blend",
102
+ "backdrop-blur": "backdrop-blur",
103
+ blur: "blur",
104
+ brightness: "brightness",
105
+ contrast: "contrast",
106
+ grayscale: "grayscale",
107
+ "hue-rotate": "hue-rotate",
108
+ invert: "invert",
109
+ saturate: "saturate",
110
+ sepia: "sepia",
111
+ "drop-shadow": "drop-shadow",
112
+ transition: "transition",
113
+ duration: "duration",
114
+ ease: "ease",
115
+ delay: "delay",
116
+ animate: "animate",
117
+ cursor: "cursor",
118
+ "pointer-events": "pointer-events",
119
+ resize: "resize",
120
+ select: "select",
121
+ scale: "scale",
122
+ rotate: "rotate",
123
+ translate: "translate",
124
+ skew: "skew",
125
+ origin: "origin",
126
+ // Layout & Position
127
+ top: "top",
128
+ right: "right",
129
+ bottom: "bottom",
130
+ left: "left",
131
+ inset: "inset",
132
+ "inset-x": "inset-x",
133
+ "inset-y": "inset-y",
134
+ aspect: "aspect",
135
+ columns: "columns",
136
+ float: "float",
137
+ clear: "clear",
138
+ // Flexbox & Grid
139
+ basis: "basis",
140
+ "gap-x": "gap-x",
141
+ "gap-y": "gap-y",
142
+ "auto-cols": "auto-cols",
143
+ "auto-rows": "auto-rows",
144
+ "grid-flow": "grid-flow",
145
+ "space-x": "space-x",
146
+ "space-y": "space-y",
147
+ "justify-items": "justify-items",
148
+ "justify-self": "justify-self",
149
+ // Sizing
150
+ size: "size",
151
+ // Borders
152
+ "border-t": "border-t",
153
+ "border-r": "border-r",
154
+ "border-b": "border-b",
155
+ "border-l": "border-l",
156
+ "border-x": "border-x",
157
+ "border-y": "border-y",
158
+ "rounded-t": "rounded-t",
159
+ "rounded-r": "rounded-r",
160
+ "rounded-b": "rounded-b",
161
+ "rounded-l": "rounded-l",
162
+ "rounded-tl": "rounded-tl",
163
+ "rounded-tr": "rounded-tr",
164
+ "rounded-bl": "rounded-bl",
165
+ "rounded-br": "rounded-br",
166
+ "border-style": "border",
167
+ // Typography
168
+ "text-align": "text",
169
+ align: "align",
170
+ "line-clamp": "line-clamp",
171
+ list: "list",
172
+ indent: "indent",
173
+ // Backgrounds & Gradients
174
+ "bg-gradient": "bg-gradient",
175
+ from: "from",
176
+ via: "via",
177
+ to: "to",
178
+ "bg-size": "bg",
179
+ "bg-position": "bg",
180
+ "bg-repeat": "bg",
181
+ // Interactivity
182
+ scroll: "scroll",
183
+ snap: "snap",
184
+ touch: "touch",
185
+ "will-change": "will-change",
186
+ caret: "caret",
187
+ accent: "accent",
188
+ // SVG
189
+ "stroke-width": "stroke"
190
+ };
191
+ var MODIFIERS = [
192
+ "hover",
193
+ "focus",
194
+ "active",
195
+ "visited",
196
+ "disabled",
197
+ "group-hover",
198
+ "group-focus",
199
+ "focus-within",
200
+ "focus-visible",
201
+ "target",
202
+ "first",
203
+ "last",
204
+ "only",
205
+ "odd",
206
+ "even",
207
+ "first-of-type",
208
+ "last-of-type",
209
+ "only-of-type",
210
+ "empty",
211
+ "checked",
212
+ "indeterminate",
213
+ "default",
214
+ "required",
215
+ "valid",
216
+ "invalid",
217
+ "in-range",
218
+ "out-of-range",
219
+ "placeholder-shown",
220
+ "autofill",
221
+ "read-only",
222
+ "open",
223
+ // Responsive breakpoints
224
+ "sm",
225
+ "md",
226
+ "lg",
227
+ "xl",
228
+ "2xl",
229
+ // Dark mode
230
+ "dark",
231
+ // Print
232
+ "print"
233
+ ];
234
+ var BOOLEAN_VALUE_PROPS = ["shadow", "rounded", "border", "transition", "ring", "outline"];
235
+ var joinClassNames = (classNames) => {
236
+ if (!classNames || classNames.length === 0) {
237
+ return "";
238
+ }
239
+ return classNames.filter(Boolean).join(" ");
240
+ };
241
+ var processModifierObject = (modifier, obj, classes) => {
242
+ for (const [key, value] of Object.entries(obj)) {
243
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
244
+ if (MODIFIERS.includes(key)) {
245
+ processModifierObject(`${modifier}:${key}`, value, classes);
246
+ }
247
+ } else if (key in VALUE_PROPS_MAP) {
248
+ const prefix = VALUE_PROPS_MAP[key];
249
+ if (typeof value === "string" || typeof value === "number") {
250
+ classes.push(`${modifier}:${prefix}-${value}`);
251
+ } else if (value === true && BOOLEAN_VALUE_PROPS.includes(key)) {
252
+ classes.push(`${modifier}:${key}`);
253
+ }
254
+ } else if (LAYOUT_PROPS.includes(key) && value === true) {
255
+ classes.push(`${modifier}:${key}`);
256
+ }
257
+ }
258
+ };
259
+ var withClassNames = (props) => {
260
+ if (!props) {
261
+ return props;
262
+ }
263
+ const hasClassNames = "classNames" in props;
264
+ const hasLayoutProps = LAYOUT_PROPS.some((k) => k in props);
265
+ const hasValueProps = Object.keys(VALUE_PROPS_MAP).some((k) => k in props);
266
+ const propsKeys = Object.keys(props);
267
+ const hasHyphenatedModifiers = propsKeys.some((key) => {
268
+ return MODIFIERS.some((mod) => key.startsWith(`${mod}-`));
269
+ });
270
+ const hasObjectModifiers = propsKeys.some((key) => {
271
+ return MODIFIERS.includes(key) && typeof props[key] === "object" && props[key] !== null;
272
+ });
273
+ const hasModifiers = hasHyphenatedModifiers || hasObjectModifiers;
274
+ if (!hasClassNames && !hasLayoutProps && !hasValueProps && !hasModifiers) {
275
+ return props;
276
+ }
277
+ const { classNames, className, ...rest } = props;
278
+ const generatedClasses = [];
279
+ const cleanRest = { ...rest };
280
+ for (const prop of LAYOUT_PROPS) {
281
+ if (prop in cleanRest && cleanRest[prop] === true) {
282
+ generatedClasses.push(prop);
283
+ delete cleanRest[prop];
284
+ }
285
+ }
286
+ for (const [prop, prefix] of Object.entries(VALUE_PROPS_MAP)) {
287
+ if (prop in cleanRest) {
288
+ const value = cleanRest[prop];
289
+ if (typeof value === "string" || typeof value === "number") {
290
+ generatedClasses.push(`${prefix}-${value}`);
291
+ delete cleanRest[prop];
292
+ } else if (value === true && BOOLEAN_VALUE_PROPS.includes(prop)) {
293
+ generatedClasses.push(prop);
294
+ delete cleanRest[prop];
295
+ }
296
+ }
297
+ }
298
+ for (const modifier of MODIFIERS) {
299
+ if (modifier in cleanRest) {
300
+ const value = cleanRest[modifier];
301
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
302
+ processModifierObject(modifier, value, generatedClasses);
303
+ delete cleanRest[modifier];
304
+ }
305
+ }
306
+ }
307
+ Object.keys(cleanRest).forEach((key) => {
308
+ const firstHyphenIndex = key.indexOf("-");
309
+ if (firstHyphenIndex === -1) return;
310
+ const modifier = key.substring(0, firstHyphenIndex);
311
+ if (MODIFIERS.includes(modifier)) {
312
+ const restKey = key.substring(firstHyphenIndex + 1);
313
+ const value = cleanRest[key];
314
+ if (restKey in VALUE_PROPS_MAP) {
315
+ const prefix = VALUE_PROPS_MAP[restKey];
316
+ if (typeof value === "string" || typeof value === "number") {
317
+ generatedClasses.push(`${modifier}:${prefix}-${value}`);
318
+ delete cleanRest[key];
319
+ } else if (value === true && BOOLEAN_VALUE_PROPS.includes(restKey)) {
320
+ generatedClasses.push(`${modifier}:${restKey}`);
321
+ delete cleanRest[key];
322
+ }
323
+ } else if (LAYOUT_PROPS.includes(restKey)) {
324
+ if (value === true) {
325
+ generatedClasses.push(`${modifier}:${restKey}`);
326
+ delete cleanRest[key];
327
+ }
328
+ }
329
+ }
330
+ });
331
+ const joined = joinClassNames(classNames || []);
332
+ const merged = [className, ...generatedClasses, joined].filter(Boolean).join(" ");
333
+ return {
334
+ ...cleanRest,
335
+ ...merged ? { className: merged } : {}
336
+ };
337
+ };
338
+
339
+ export {
340
+ withClassNames
341
+ };