pure-react-ui 1.3.0 → 1.4.1

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
@@ -1,321 +1,73 @@
1
- # Advanced Professional Button Component
2
-
3
- A modern, fully-featured React button component with TypeScript support, multiple variants, sizes, and advanced features like ripple effects, loading states, and elevation shadows.
4
-
5
- ## Features
6
-
7
- **Multiple Variants**: Solid, Outline, Ghost, and Gradient styles
8
- 🎨 **6 Color Schemes**: Primary, Secondary, Success, Danger, Warning, Info
9
- 📏 **5 Size Options**: Extra Small, Small, Medium, Large, Extra Large
10
- 🎭 **Advanced Effects**: Ripple animation, Elevation shadows, Smooth transitions
11
- ♿ **Accessible**: ARIA attributes, Keyboard navigation, Focus states
12
- 🔄 **Loading States**: Built-in spinner with disabled interaction
13
- 🎯 **Icon Support**: Left and right icon positioning
14
- 📱 **Responsive**: Mobile-friendly with adaptive sizing
15
- ⚡ **TypeScript**: Full type safety and IntelliSense support
16
- 🎪 **2px Border Radius**: Sharp, professional appearance
17
-
18
- ## Installation
19
-
20
- ```bash
21
- # Copy these files to your project:
22
- # - Button.tsx
23
- # - Button.css
24
- ```
25
-
26
- ## Basic Usage
27
-
28
- ```tsx
29
- import { Button } from './components/Button';
30
- import './components/Button.css';
31
-
32
- function App() {
33
- return (
34
- <Button variant="primary" size="medium">
35
- Click Me
36
- </Button>
37
- );
38
- }
39
- ```
40
-
41
- ## Props
42
-
43
- | Prop | Type | Default | Description |
44
- |------|------|---------|-------------|
45
- | `children` | `ReactNode` | - | Button content (required) |
46
- | `variant` | `string` | `'primary'` | Button style variant |
47
- | `size` | `'xs' \| 'small' \| 'medium' \| 'large' \| 'xl'` | `'medium'` | Button size |
48
- | `loading` | `boolean` | `false` | Show loading spinner |
49
- | `disabled` | `boolean` | `false` | Disable button interaction |
50
- | `iconLeft` | `ReactNode` | - | Icon before text |
51
- | `iconRight` | `ReactNode` | - | Icon after text |
52
- | `fullWidth` | `boolean` | `false` | Make button full width |
53
- | `rounded` | `boolean` | `false` | Use pill-shaped border radius |
54
- | `elevation` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'none'` | Shadow elevation level |
55
- | `ripple` | `boolean` | `true` | Enable ripple effect on click |
56
- | `className` | `string` | `''` | Additional CSS classes |
57
- | `onClick` | `function` | - | Click handler |
58
-
59
- Plus all standard HTML button attributes.
60
-
61
- ## Variants
62
-
63
- ### Solid Variants
64
- ```tsx
65
- <Button variant="primary">Primary</Button>
66
- <Button variant="secondary">Secondary</Button>
67
- <Button variant="success">Success</Button>
68
- <Button variant="danger">Danger</Button>
69
- <Button variant="warning">Warning</Button>
70
- <Button variant="info">Info</Button>
71
- ```
72
-
73
- ### Outline Variants
74
- ```tsx
75
- <Button variant="outline-primary">Primary</Button>
76
- <Button variant="outline-secondary">Secondary</Button>
77
- <Button variant="outline-success">Success</Button>
78
- <Button variant="outline-danger">Danger</Button>
79
- <Button variant="outline-warning">Warning</Button>
80
- <Button variant="outline-info">Info</Button>
81
- ```
82
-
83
- ### Ghost Variants
84
- ```tsx
85
- <Button variant="ghost-primary">Primary</Button>
86
- <Button variant="ghost-secondary">Secondary</Button>
87
- <Button variant="ghost-success">Success</Button>
88
- <Button variant="ghost-danger">Danger</Button>
89
- <Button variant="ghost-warning">Warning</Button>
90
- <Button variant="ghost-info">Info</Button>
91
- ```
92
-
93
- ### Gradient Variants
94
- ```tsx
95
- <Button variant="gradient-primary">Gradient Primary</Button>
96
- <Button variant="gradient-success">Gradient Success</Button>
97
- <Button variant="gradient-danger">Gradient Danger</Button>
98
- ```
99
-
100
- ## Examples
101
-
102
- ### With Icons
103
-
104
- ```tsx
105
- import { Download, Check, Search } from 'lucide-react';
106
-
107
- <Button variant="primary" iconLeft={<Download />}>
108
- Download
109
- </Button>
110
-
111
- <Button variant="success" iconRight={<Check />}>
112
- Confirm
113
- </Button>
114
-
115
- <Button variant="outline-primary" iconLeft={<Search />}>
116
- Search
117
- </Button>
118
- ```
119
-
120
- ### Loading State
121
-
122
- ```tsx
123
- const [loading, setLoading] = useState(false);
124
-
125
- const handleSubmit = async () => {
126
- setLoading(true);
127
- await someAsyncOperation();
128
- setLoading(false);
129
- };
130
-
131
- <Button
132
- variant="primary"
133
- loading={loading}
134
- onClick={handleSubmit}
135
- >
136
- {loading ? 'Processing...' : 'Submit'}
137
- </Button>
138
- ```
139
-
140
- ### Different Sizes
141
-
142
- ```tsx
143
- <Button size="xs">Extra Small</Button>
144
- <Button size="small">Small</Button>
145
- <Button size="medium">Medium</Button>
146
- <Button size="large">Large</Button>
147
- <Button size="xl">Extra Large</Button>
148
- ```
149
-
150
- ### With Elevation
151
-
152
- ```tsx
153
- <Button variant="primary" elevation="sm">Small Shadow</Button>
154
- <Button variant="primary" elevation="md">Medium Shadow</Button>
155
- <Button variant="primary" elevation="lg">Large Shadow</Button>
156
- ```
157
-
158
- ### Rounded Buttons
159
-
160
- ```tsx
161
- <Button variant="primary" rounded>
162
- Rounded Button
163
- </Button>
164
-
165
- <Button variant="outline-success" rounded elevation="md">
166
- Rounded with Shadow
167
- </Button>
168
- ```
169
-
170
- ### Full Width
171
-
172
- ```tsx
173
- <Button variant="gradient-primary" fullWidth size="large">
174
- Full Width Button
175
- </Button>
176
- ```
177
-
178
- ### Disabled State
179
-
180
- ```tsx
181
- <Button variant="primary" disabled>
182
- Disabled Button
183
- </Button>
184
- ```
185
-
186
- ### Advanced Combinations
187
-
188
- ```tsx
189
- <Button
190
- variant="gradient-primary"
191
- size="large"
192
- rounded
193
- elevation="lg"
194
- iconLeft={<Download />}
195
- >
196
- Premium Action
197
- </Button>
198
-
199
- <Button
200
- variant="outline-success"
201
- size="large"
202
- rounded
203
- iconRight={<Check />}
204
- onClick={handleConfirm}
205
- >
206
- Confirm Choice
207
- </Button>
208
- ```
209
-
210
- ## Styling Customization
211
-
212
- ### Override Styles
213
-
214
- You can override default styles by targeting CSS classes:
215
-
216
- ```css
217
- /* Custom primary color */
218
- .pru-btn-primary {
219
- background-color: #your-color;
220
- }
221
-
222
- .pru-btn-primary:hover:not(:disabled) {
223
- background-color: #your-hover-color;
224
- }
225
-
226
- /* Custom size */
227
- .pru-btn-custom {
228
- padding: 12px 24px;
229
- font-size: 15px;
230
- }
231
-
232
- /* Custom border radius */
233
- .pru-btn {
234
- border-radius: 4px; /* Override default 2px */
235
- }
236
- ```
237
-
238
- ### Additional Classes
239
-
240
- ```tsx
241
- <Button
242
- variant="primary"
243
- className="my-custom-class"
244
- >
245
- Custom Button
246
- </Button>
247
- ```
248
-
249
- ## Accessibility
250
-
251
- The button component includes:
252
-
253
- - ✅ Proper ARIA attributes (`aria-disabled`, `aria-busy`)
254
- - ✅ Keyboard navigation support
255
- - ✅ Focus visible states
256
- - ✅ Screen reader friendly loading states
257
- - ✅ Disabled state handling
258
- - ✅ Semantic HTML button element
259
-
260
- ## Best Practices
261
-
262
- 1. **Use appropriate variants** for different actions:
263
- - `primary` for main actions
264
- - `secondary` for secondary actions
265
- - `success` for confirmations
266
- - `danger` for destructive actions
267
- - `outline` for less prominent actions
268
- - `ghost` for tertiary actions
269
-
270
- 2. **Choose the right size**:
271
- - `xs` for compact UIs
272
- - `small` for inline actions
273
- - `medium` for most use cases
274
- - `large` for CTAs
275
- - `xl` for hero sections
276
-
277
- 3. **Loading states**: Always show loading feedback for async operations
278
-
279
- 4. **Icons**: Use meaningful icons that enhance understanding
280
-
281
- 5. **Elevation**: Use shadows to create visual hierarchy
282
-
283
- ## Browser Support
284
-
285
- - ✅ Chrome (latest)
286
- - ✅ Firefox (latest)
287
- - ✅ Safari (latest)
288
- - ✅ Edge (latest)
289
- - ✅ Mobile browsers
290
-
291
- ## Performance
292
-
293
- - Lightweight CSS with efficient selectors
294
- - Optimized animations using transform and opacity
295
- - Minimal JavaScript overhead
296
- - No external dependencies (except React)
297
-
298
- ## TypeScript Support
299
-
300
- Full TypeScript support with:
301
- - Type-safe props
302
- - IntelliSense autocomplete
303
- - Type checking for variants and sizes
304
- - Proper event typing
305
-
306
- ## License
307
-
308
- MIT License - Feel free to use in your projects!
309
-
310
- ## Contributing
311
-
312
- Contributions are welcome! Please feel free to submit issues or pull requests.
313
-
314
- ## Credits
315
-
316
- Created with ❤️ for professional React applications.
317
-
318
- ---
319
-
320
- **Version**: 1.0.0
321
- **Last Updated**: 2024
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
+
18
+ ```js
19
+ export default defineConfig([
20
+ globalIgnores(['dist']),
21
+ {
22
+ files: ['**/*.{ts,tsx}'],
23
+ extends: [
24
+ // Other configs...
25
+
26
+ // Remove tseslint.configs.recommended and replace with this
27
+ tseslint.configs.recommendedTypeChecked,
28
+ // Alternatively, use this for stricter rules
29
+ tseslint.configs.strictTypeChecked,
30
+ // Optionally, add this for stylistic rules
31
+ tseslint.configs.stylisticTypeChecked,
32
+
33
+ // Other configs...
34
+ ],
35
+ languageOptions: {
36
+ parserOptions: {
37
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
+ tsconfigRootDir: import.meta.dirname,
39
+ },
40
+ // other options...
41
+ },
42
+ },
43
+ ])
44
+ ```
45
+
46
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
+
48
+ ```js
49
+ // eslint.config.js
50
+ import reactX from 'eslint-plugin-react-x'
51
+ import reactDom from 'eslint-plugin-react-dom'
52
+
53
+ export default defineConfig([
54
+ globalIgnores(['dist']),
55
+ {
56
+ files: ['**/*.{ts,tsx}'],
57
+ extends: [
58
+ // Other configs...
59
+ // Enable lint rules for React
60
+ reactX.configs['recommended-typescript'],
61
+ // Enable lint rules for React DOM
62
+ reactDom.configs.recommended,
63
+ ],
64
+ languageOptions: {
65
+ parserOptions: {
66
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
+ tsconfigRootDir: import.meta.dirname,
68
+ },
69
+ // other options...
70
+ },
71
+ },
72
+ ])
73
+ ```
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ee=require("react");var v={exports:{}},_={};var I;function re(){if(I)return _;I=1;var u=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function l(c,o,s){var i=null;if(s!==void 0&&(i=""+s),o.key!==void 0&&(i=""+o.key),"key"in o){s={};for(var f in o)f!=="key"&&(s[f]=o[f])}else s=o;return o=s.ref,{$$typeof:u,type:c,key:i,ref:o!==void 0?o:null,props:s}}return _.Fragment=d,_.jsx=l,_.jsxs=l,_}var E={};var F;function te(){return F||(F=1,process.env.NODE_ENV!=="production"&&(function(){function u(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===Z?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case T:return"Fragment";case q:return"Profiler";case U:return"StrictMode";case G:return"Suspense";case X:return"SuspenseList";case H:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case W:return"Portal";case V:return e.displayName||"Context";case J:return(e._context.displayName||"Context")+".Consumer";case z:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case B:return r=e.displayName||null,r!==null?r:u(e.type)||"Memo";case k:r=e._payload,e=e._init;try{return u(e(r))}catch{}}return null}function d(e){return""+e}function l(e){try{d(e);var r=!1}catch{r=!0}if(r){r=console;var t=r.error,n=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return t.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",n),d(e)}}function c(e){if(e===T)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===k)return"<...>";try{var r=u(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function o(){var e=O.A;return e===null?null:e.getOwner()}function s(){return Error("react-stack-top-frame")}function i(e){if(h.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function f(e,r){function t(){g||(g=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}t.isReactWarning=!0,Object.defineProperty(e,"key",{get:t,configurable:!0})}function M(){var e=u(this.type);return N[e]||(N[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function L(e,r,t,n,R,S){var a=t.ref;return e={$$typeof:w,type:e,key:r,props:t,_owner:n},(a!==void 0?a:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:M}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:R}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:S}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function j(e,r,t,n,R,S){var a=r.children;if(a!==void 0)if(n)if(Q(a)){for(n=0;n<a.length;n++)x(a[n]);Object.freeze&&Object.freeze(a)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else x(a);if(h.call(r,"key")){a=u(e);var m=Object.keys(r).filter(function(K){return K!=="key"});n=0<m.length?"{key: someKey, "+m.join(": ..., ")+": ...}":"{key: someKey}",$[a+n]||(m=0<m.length?"{"+m.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
2
+ let props = %s;
3
+ <%s {...props} />
4
+ React keys must be passed directly to JSX without using spread:
5
+ let props = %s;
6
+ <%s key={someKey} {...props} />`,n,a,m,a),$[a+n]=!0)}if(a=null,t!==void 0&&(l(t),a=""+t),i(r)&&(l(r.key),a=""+r.key),"key"in r){t={};for(var A in r)A!=="key"&&(t[A]=r[A])}else t=r;return a&&f(t,typeof e=="function"?e.displayName||e.name||"Unknown":e),L(e,a,t,o(),R,S)}function x(e){y(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===k&&(e._payload.status==="fulfilled"?y(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function y(e){return typeof e=="object"&&e!==null&&e.$$typeof===w}var b=ee,w=Symbol.for("react.transitional.element"),W=Symbol.for("react.portal"),T=Symbol.for("react.fragment"),U=Symbol.for("react.strict_mode"),q=Symbol.for("react.profiler"),J=Symbol.for("react.consumer"),V=Symbol.for("react.context"),z=Symbol.for("react.forward_ref"),G=Symbol.for("react.suspense"),X=Symbol.for("react.suspense_list"),B=Symbol.for("react.memo"),k=Symbol.for("react.lazy"),H=Symbol.for("react.activity"),Z=Symbol.for("react.client.reference"),O=b.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,h=Object.prototype.hasOwnProperty,Q=Array.isArray,P=console.createTask?console.createTask:function(){return null};b={react_stack_bottom_frame:function(e){return e()}};var g,N={},C=b.react_stack_bottom_frame.bind(b,s)(),Y=P(c(s)),$={};E.Fragment=T,E.jsx=function(e,r,t){var n=1e4>O.recentlyCreatedOwnerStacks++;return j(e,r,t,!1,n?Error("react-stack-top-frame"):C,n?P(c(e)):Y)},E.jsxs=function(e,r,t){var n=1e4>O.recentlyCreatedOwnerStacks++;return j(e,r,t,!0,n?Error("react-stack-top-frame"):C,n?P(c(e)):Y)}})()),E}var D;function ne(){return D||(D=1,process.env.NODE_ENV==="production"?v.exports=re():v.exports=te()),v.exports}var p=ne();const ae=({variant:u="solid",size:d="md",loading:l=!1,icon:c,children:o,className:s="",disabled:i,...f})=>p.jsxs("button",{className:`pure-btn ${u}-btn ${d}-btn ${s}`,disabled:i||l,...f,children:[l&&p.jsx("span",{className:"loader"}),c&&p.jsx("span",{className:"btn-icon",children:c}),p.jsx("span",{className:c||l?"btn-text":"",children:o})]});exports.PureButton=ae;