@neoptocom/neopto-ui 0.5.1 → 0.6.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/CONSUMER_SETUP.md CHANGED
@@ -6,7 +6,7 @@ This component library uses **Tailwind CSS v4 utility classes** directly in the
6
6
 
7
7
  ---
8
8
 
9
- ## 📦 Quick Setup (Recommended)
9
+ ## 📦 Installation
10
10
 
11
11
  ### Step 1: Install dependencies
12
12
 
@@ -15,20 +15,39 @@ npm install @neoptocom/neopto-ui
15
15
  npm install -D tailwindcss@latest @tailwindcss/postcss
16
16
  ```
17
17
 
18
- ### Step 2: Run the init command
18
+ ### Step 2: Configure PostCSS
19
19
 
20
- After installing the package, run:
20
+ Create `postcss.config.js` in your project root:
21
21
 
22
- ```bash
23
- npx neopto-ui
22
+ ```js
23
+ export default {
24
+ plugins: {
25
+ "@tailwindcss/postcss": {},
26
+ },
27
+ };
24
28
  ```
25
29
 
26
- This will automatically:
27
- - ✅ Create `postcss.config.js` if needed
28
- - ✅ Update your CSS file with required imports
29
- - ✅ Configure Tailwind to scan the library components
30
+ ### Step 3: Setup your CSS file
30
31
 
31
- ### Step 3: Use the components!
32
+ In your main CSS file (e.g., `src/index.css`):
33
+
34
+ ```css
35
+ @import "tailwindcss";
36
+
37
+ /* Scan the component library source files */
38
+ @source "../node_modules/@neoptocom/neopto-ui/src";
39
+
40
+ /* Import library tokens and styles */
41
+ @import "@neoptocom/neopto-ui/styles";
42
+ ```
43
+
44
+ Then import your CSS in `src/main.tsx`:
45
+
46
+ ```tsx
47
+ import "./index.css";
48
+ ```
49
+
50
+ ### Step 4: Use the components!
32
51
 
33
52
  ```tsx
34
53
  import { Button, Input, Typo } from "@neoptocom/neopto-ui";
@@ -75,51 +94,9 @@ document.documentElement.classList.toggle("dark");
75
94
  - `Chip` - Tags and labels
76
95
  - `Modal` - Dialog modals
77
96
  - `Skeleton` - Loading placeholders
78
-
79
- ---
80
-
81
- ## 🛠️ Manual Setup (Alternative)
82
-
83
- If you prefer to set up manually or the init script didn't work:
84
-
85
- ### Step 1: Install dependencies
86
-
87
- ```bash
88
- npm install @neoptocom/neopto-ui
89
- npm install -D tailwindcss@latest @tailwindcss/postcss
90
- ```
91
-
92
- ### Step 2: Configure PostCSS
93
-
94
- Create `postcss.config.js` in your project root:
95
-
96
- ```js
97
- export default {
98
- plugins: {
99
- "@tailwindcss/postcss": {},
100
- },
101
- };
102
- ```
103
-
104
- ### Step 3: Setup your CSS file
105
-
106
- In your main CSS file (e.g., `src/index.css`):
107
-
108
- ```css
109
- @import "tailwindcss";
110
-
111
- /* Scan the component library source files */
112
- @source "../node_modules/@neoptocom/neopto-ui/src";
113
-
114
- /* Import library tokens and styles */
115
- @import "@neoptocom/neopto-ui/styles";
116
- ```
117
-
118
- Then import your CSS in `src/main.tsx`:
119
-
120
- ```tsx
121
- import "./index.css";
122
- ```
97
+ - `Counter` - Number stepper
98
+ - `IconButton` - Icon-only buttons
99
+ - `ChatButton` - Animated chat button
123
100
 
124
101
  ---
125
102
 
@@ -131,9 +108,9 @@ import "./index.css";
131
108
 
132
109
  **Solution:** Make sure you:
133
110
 
134
- 1. ✅ Imported the library CSS: `import '@neoptocom/neopto-ui/styles'`
135
- 2. ✅ Added the library path to `tailwind.config.js` content array
136
- 3. ✅ Have Tailwind CSS installed and configured
111
+ 1. ✅ Imported the library CSS: `@import "@neoptocom/neopto-ui/styles"`
112
+ 2. ✅ Added the `@source` directive to scan the library source files
113
+ 3. ✅ Have Tailwind CSS v4 installed and configured with `@tailwindcss/postcss`
137
114
 
138
115
  ### CSS custom properties not working
139
116
 
@@ -141,6 +118,12 @@ import "./index.css";
141
118
 
142
119
  **Solution:** Make sure the library CSS is imported **before** your app styles so the CSS custom properties are defined.
143
120
 
121
+ ### Tailwind classes not being generated
122
+
123
+ **Problem:** Some component styles are missing.
124
+
125
+ **Solution:** Ensure the `@source` directive points to the library's **source files** (`/src`), not the compiled dist folder. The source files contain all the Tailwind utility classes that need to be scanned.
126
+
144
127
  ---
145
128
 
146
129
  ## 📚 Full Documentation
package/README.md CHANGED
@@ -13,28 +13,9 @@ A modern React component library built with Tailwind CSS v4 and TypeScript. Feat
13
13
  - **Tree Shakable**: Optimized bundle size with tree shaking
14
14
  - **Storybook**: Comprehensive documentation and testing environment
15
15
 
16
- ## 📦 Quick Start
16
+ ## 📦 Installation
17
17
 
18
- ```bash
19
- # Install the library and Tailwind CSS v4
20
- npm install @neoptocom/neopto-ui
21
- npm install -D tailwindcss@latest @tailwindcss/postcss
22
-
23
- # Run the init command - it handles everything automatically!
24
- npx neopto-ui
25
- ```
26
-
27
- The init command will:
28
- - ✅ Create `postcss.config.js` if needed
29
- - ✅ Update your CSS file with required imports
30
- - ✅ Configure Tailwind to scan the library components
31
-
32
- ### Manual Setup (if needed)
33
-
34
- <details>
35
- <summary>Click to expand manual installation steps</summary>
36
-
37
- ### Step 1: Install dependencies
18
+ ### Step 1: Install the library and Tailwind CSS v4
38
19
 
39
20
  ```bash
40
21
  npm install @neoptocom/neopto-ui
@@ -73,8 +54,6 @@ Then import this CSS in your `src/main.tsx`:
73
54
  import "./index.css";
74
55
  ```
75
56
 
76
- </details>
77
-
78
57
  ## 🎨 Usage
79
58
 
80
59
  ### Basic Example
package/dist/index.cjs CHANGED
@@ -3,7 +3,6 @@
3
3
  var React2 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var reactDom = require('react-dom');
6
- var tailwindVariants = require('tailwind-variants');
7
6
 
8
7
  function _interopNamespace(e) {
9
8
  if (e && e.__esModule) return e;
@@ -115,41 +114,40 @@ function Modal({
115
114
  const container = document.body;
116
115
  return reactDom.createPortal(overlay, container);
117
116
  }
118
- var styles = tailwindVariants.tv({
119
- base: "text-current",
120
- variants: {
121
- variant: {
122
- "display-lg": "text-5xl leading-tight",
123
- "display-md": "text-4xl leading-tight",
124
- "display-sm": "text-4xl leading-tight",
125
- "headline-lg": "text-3xl leading-tight",
126
- "headline-md": "text-3xl leading-tight",
127
- "headline-sm": "text-3xl leading-tight",
128
- "title-lg": "text-xl leading-tight",
129
- "title-md": "text-lg leading-tight",
130
- "title-sm": "text-base leading-tight",
131
- "label-lg": "text-sm leading-tight",
132
- "label-md": "text-xs leading-tight",
133
- "label-sm": "text-xs leading-tight",
134
- "body-lg": "text-base leading-relaxed",
135
- "body-md": "text-sm leading-relaxed",
136
- "body-sm": "text-xs leading-relaxed",
137
- "button": "text-base leading-normal"
138
- },
139
- weight: {
140
- normal: "font-normal",
141
- medium: "font-medium",
142
- semibold: "font-semibold",
143
- bold: "font-bold"
144
- },
145
- muted: {
146
- true: "text-[var(--muted-fg)]"
147
- }
148
- },
149
- defaultVariants: {
150
- weight: "normal"
151
- }
152
- });
117
+ function getTypoClasses(variant, weight = "normal", muted, className) {
118
+ const base = "text-current";
119
+ const variants = {
120
+ "display-lg": "text-5xl leading-tight",
121
+ "display-md": "text-4xl leading-tight",
122
+ "display-sm": "text-4xl leading-tight",
123
+ "headline-lg": "text-3xl leading-tight",
124
+ "headline-md": "text-3xl leading-tight",
125
+ "headline-sm": "text-3xl leading-tight",
126
+ "title-lg": "text-xl leading-tight",
127
+ "title-md": "text-lg leading-tight",
128
+ "title-sm": "text-base leading-tight",
129
+ "label-lg": "text-sm leading-tight",
130
+ "label-md": "text-xs leading-tight",
131
+ "label-sm": "text-xs leading-tight",
132
+ "body-lg": "text-base leading-relaxed",
133
+ "body-md": "text-sm leading-relaxed",
134
+ "body-sm": "text-xs leading-relaxed",
135
+ "button": "text-base leading-normal"
136
+ };
137
+ const weights = {
138
+ normal: "font-normal",
139
+ medium: "font-medium",
140
+ semibold: "font-semibold",
141
+ bold: "font-bold"
142
+ };
143
+ return [
144
+ base,
145
+ variants[variant],
146
+ weights[weight],
147
+ muted ? "text-[var(--muted-fg)]" : "",
148
+ className
149
+ ].filter(Boolean).join(" ");
150
+ }
153
151
  function Typo({
154
152
  variant,
155
153
  bold,
@@ -169,23 +167,21 @@ function Typo({
169
167
  return /* @__PURE__ */ jsxRuntime.jsx(
170
168
  Component,
171
169
  {
172
- className: styles({ variant, weight: bold, muted, className }),
170
+ className: getTypoClasses(variant, bold, muted, className),
173
171
  style: { fontFamily: getFontFamily(variant) },
174
172
  ...props,
175
173
  children
176
174
  }
177
175
  );
178
176
  }
179
- var avatarStyles = tailwindVariants.tv({
180
- base: "relative box-border flex items-center justify-center overflow-hidden rounded-full border border-[var(--border)] bg-[var(--muted)] text-[var(--fg)] select-none",
181
- variants: {
182
- size: {
183
- sm: "w-[28px] h-[28px]",
184
- md: "w-[60px] h-[60px]"
185
- }
186
- },
187
- defaultVariants: { size: "sm" }
188
- });
177
+ function getAvatarClasses(size = "sm", className) {
178
+ const base = "relative box-border flex items-center justify-center overflow-hidden rounded-full border border-[var(--border)] bg-[var(--muted)] text-[var(--fg)] select-none";
179
+ const sizes = {
180
+ sm: "w-[28px] h-[28px]",
181
+ md: "w-[60px] h-[60px]"
182
+ };
183
+ return [base, sizes[size], className].filter(Boolean).join(" ");
184
+ }
189
185
  function getInitials(name) {
190
186
  if (!name) return "\u2026";
191
187
  const words = name.trim().split(/\s+/);
@@ -214,7 +210,7 @@ function Avatar({
214
210
  return /* @__PURE__ */ jsxRuntime.jsx(
215
211
  "div",
216
212
  {
217
- className: avatarStyles({ size, className }),
213
+ className: getAvatarClasses(size, className),
218
214
  "aria-label": alt ?? name,
219
215
  role: "img",
220
216
  ...props,
@@ -326,29 +322,20 @@ function Icon({
326
322
  }
327
323
  );
328
324
  }
329
- var iconButtonStyles = tailwindVariants.tv({
330
- base: [
331
- "flex items-center justify-center rounded-full flex-shrink-0",
332
- "transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
333
- "focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50"
334
- ].join(" "),
335
- variants: {
336
- variant: {
337
- ghost: "bg-transparent hover:bg-[var(--muted)] active:bg-[var(--muted)]",
338
- primary: "bg-cyan-500 text-white hover:bg-cyan-400 active:bg-cyan-600",
339
- secondary: "border border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--muted)] active:bg-[var(--muted)]"
340
- },
341
- size: {
342
- sm: "w-8 h-8",
343
- md: "w-10 h-10",
344
- lg: "w-12 h-12"
345
- }
346
- },
347
- defaultVariants: {
348
- variant: "ghost",
349
- size: "md"
350
- }
351
- });
325
+ function getIconButtonClasses(variant = "ghost", size = "md", className) {
326
+ const base = "flex items-center justify-center rounded-full flex-shrink-0 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50";
327
+ const variants = {
328
+ ghost: "bg-transparent hover:bg-[var(--muted)] active:bg-[var(--muted)]",
329
+ primary: "bg-cyan-500 text-white hover:bg-cyan-400 active:bg-cyan-600",
330
+ secondary: "border border-[var(--border)] bg-[var(--surface)] hover:bg-[var(--muted)] active:bg-[var(--muted)]"
331
+ };
332
+ const sizes = {
333
+ sm: "w-8 h-8",
334
+ md: "w-10 h-10",
335
+ lg: "w-12 h-12"
336
+ };
337
+ return [base, variants[variant], sizes[size], className].filter(Boolean).join(" ");
338
+ }
352
339
  var IconButton = React2__namespace.forwardRef(
353
340
  ({
354
341
  variant,
@@ -368,7 +355,7 @@ var IconButton = React2__namespace.forwardRef(
368
355
  "button",
369
356
  {
370
357
  ref,
371
- className: iconButtonStyles({ variant, size, className }),
358
+ className: getIconButtonClasses(variant, size, className),
372
359
  ...props,
373
360
  children: /* @__PURE__ */ jsxRuntime.jsx(
374
361
  Icon,
@@ -782,35 +769,33 @@ function Search({
782
769
  }
783
770
  );
784
771
  }
785
- var buttonStyles = tailwindVariants.tv({
786
- base: "cursor-pointer inline-flex items-center justify-center gap-2 rounded-[var(--radius-2xl)] px-[18px] h-12 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50",
787
- variants: {
788
- variant: {
789
- primary: "bg-cyan-500 text-white hover:bg-cyan-400 active:bg-cyan-600 disabled:bg-neutral-400",
790
- secondary: "border border-cyan-500 text-cyan-500 bg-transparent hover:bg-cyan-50 active:bg-cyan-100 disabled:border-neutral-400 disabled:text-neutral-400",
791
- ghost: "bg-transparent text-cyan-500 hover:bg-cyan-50 active:bg-cyan-100 disabled:text-neutral-400"
792
- },
793
- size: {
794
- sm: "h-9 px-3",
795
- md: "h-12 px-[18px]",
796
- lg: "h-14 px-6"
797
- },
798
- fullWidth: {
799
- true: "w-full"
800
- }
801
- },
802
- defaultVariants: {
803
- variant: "primary",
804
- size: "md"
805
- }
806
- });
772
+ function getButtonClasses(variant = "primary", size = "md", fullWidth, className) {
773
+ const base = "cursor-pointer inline-flex items-center justify-center gap-2 rounded-[var(--radius-2xl)] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50";
774
+ const variants = {
775
+ primary: "bg-cyan-500 text-white hover:bg-cyan-400 active:bg-cyan-600 disabled:bg-neutral-400",
776
+ secondary: "border border-cyan-500 text-cyan-500 bg-transparent hover:bg-cyan-50 active:bg-cyan-100 disabled:border-neutral-400 disabled:text-neutral-400",
777
+ ghost: "bg-transparent text-cyan-500 hover:bg-cyan-50 active:bg-cyan-100 disabled:text-neutral-400"
778
+ };
779
+ const sizes = {
780
+ sm: "h-9 px-3",
781
+ md: "h-12 px-[18px]",
782
+ lg: "h-14 px-6"
783
+ };
784
+ return [
785
+ base,
786
+ variants[variant],
787
+ sizes[size],
788
+ fullWidth ? "w-full" : "",
789
+ className
790
+ ].filter(Boolean).join(" ");
791
+ }
807
792
  var Button = React2__namespace.forwardRef(
808
793
  ({ variant, size, fullWidth, className, children, icon, ...props }, ref) => {
809
794
  return /* @__PURE__ */ jsxRuntime.jsx(
810
795
  "button",
811
796
  {
812
797
  ref,
813
- className: buttonStyles({ variant, size, fullWidth, className }),
798
+ className: getButtonClasses(variant, size, fullWidth, className),
814
799
  ...props,
815
800
  children
816
801
  }