@emporix/cockpit-component-library 0.0.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 +567 -0
- package/dist/components/buttons/PrimaryButton.d.ts +29 -0
- package/dist/components/buttons/PrimaryButton.d.ts.map +1 -0
- package/dist/components/buttons/SecondaryButton.d.ts +25 -0
- package/dist/components/buttons/SecondaryButton.d.ts.map +1 -0
- package/dist/components/dropdown/Dropdown.d.ts +107 -0
- package/dist/components/dropdown/Dropdown.d.ts.map +1 -0
- package/dist/components/input/InputText.d.ts +37 -0
- package/dist/components/input/InputText.d.ts.map +1 -0
- package/dist/components/selectbutton/SelectButton.d.ts +63 -0
- package/dist/components/selectbutton/SelectButton.d.ts.map +1 -0
- package/dist/components/tabs/Tabs.d.ts +39 -0
- package/dist/components/tabs/Tabs.d.ts.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +938 -0
- package/dist/index.umd.js +22 -0
- package/dist/style.css +1 -0
- package/dist/styles.d.ts +4 -0
- package/package.json +101 -0
package/README.md
ADDED
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
# Emporix Cockpit Component Library
|
|
2
|
+
|
|
3
|
+
A modern React component library built with TypeScript, Vite, and SCSS modules.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ๐ **Modern Stack**: Built with Vite, TypeScript, and React 18
|
|
8
|
+
- ๐จ **Styled Components**: SCSS modules for component styling
|
|
9
|
+
- ๐ **Storybook**: Interactive component documentation
|
|
10
|
+
- ๐งช **Testing**: Comprehensive test suite with Vitest and React Testing Library
|
|
11
|
+
- ๐ฆ **Library Build**: Optimized for npm package distribution
|
|
12
|
+
- ๐ **CI/CD**: Automated testing and publishing pipeline
|
|
13
|
+
- ๐จ **CSS Variables**: Global theming system with CSS custom properties
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @emporix/cockpit-component-library
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Usage
|
|
24
|
+
|
|
25
|
+
**Important:** Import the library styles in your app so component layout and appearance stay consistent. If you skip this step, components may be unstyled or layout may break.
|
|
26
|
+
|
|
27
|
+
#### Method 1: Import styles in your main CSS file (Recommended)
|
|
28
|
+
|
|
29
|
+
```css
|
|
30
|
+
/* In your main CSS file (e.g., index.css, App.css) */
|
|
31
|
+
@import '@emporix/cockpit-component-library/styles';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { PrimaryButton } from '@emporix/cockpit-component-library'
|
|
36
|
+
|
|
37
|
+
const MyComponent = () => {
|
|
38
|
+
return (
|
|
39
|
+
<PrimaryButton onClick={() => console.log('Clicked!')}>
|
|
40
|
+
Click me
|
|
41
|
+
</PrimaryButton>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Method 2: Import styles in your main JavaScript/TypeScript file
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { PrimaryButton } from '@emporix/cockpit-component-library'
|
|
50
|
+
import '@emporix/cockpit-component-library/styles'
|
|
51
|
+
|
|
52
|
+
const MyComponent = () => {
|
|
53
|
+
return (
|
|
54
|
+
<PrimaryButton onClick={() => console.log('Clicked!')}>
|
|
55
|
+
Click me
|
|
56
|
+
</PrimaryButton>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Method 3: Copy CSS file manually (Fallback)
|
|
62
|
+
|
|
63
|
+
If the above methods don't work, copy the CSS file from `node_modules/@emporix/cockpit-component-library/dist/style.css` to your project and import it directly.
|
|
64
|
+
|
|
65
|
+
## Components
|
|
66
|
+
|
|
67
|
+
### PrimaryButton
|
|
68
|
+
|
|
69
|
+
A simple, focused button component for primary actions.
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { PrimaryButton } from '@emporix/cockpit-component-library'
|
|
73
|
+
|
|
74
|
+
// Basic usage
|
|
75
|
+
<PrimaryButton label="Click me" />
|
|
76
|
+
|
|
77
|
+
// With disabled state
|
|
78
|
+
<PrimaryButton label="Disabled Button" disabled />
|
|
79
|
+
|
|
80
|
+
// With click handler
|
|
81
|
+
<PrimaryButton label="Confirm Action" onClick={() => alert('Confirmed!')} />
|
|
82
|
+
|
|
83
|
+
// Loading state
|
|
84
|
+
<PrimaryButton label="Saving..." loading />
|
|
85
|
+
|
|
86
|
+
// With icon
|
|
87
|
+
<PrimaryButton label="Download" icon={<FiDownload />} iconPos="left" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Props
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Default | Description |
|
|
93
|
+
| ----------- | ------------------------- | ------- | ------------------------------------------------ |
|
|
94
|
+
| label | string | - | Text label displayed inside the button |
|
|
95
|
+
| disabled | boolean | false | Whether button is disabled |
|
|
96
|
+
| loading | boolean | false | Shows loading spinner and disables the button |
|
|
97
|
+
| icon | ReactNode | - | Optional icon shown next to the label or alone |
|
|
98
|
+
| iconPos | `'left' \| 'right'` | 'left' | Icon position relative to the label |
|
|
99
|
+
| onClick | () => void | - | Click handler |
|
|
100
|
+
| className | string | - | Additional CSS class |
|
|
101
|
+
| data-testid | string | - | Test ID for testing |
|
|
102
|
+
|
|
103
|
+
### InputText
|
|
104
|
+
|
|
105
|
+
A text input with optional label and tooltip. Hover and focus styles match the Dropdown component.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { InputText } from '@emporix/cockpit-component-library'
|
|
109
|
+
|
|
110
|
+
// With label and info tooltip
|
|
111
|
+
<InputText
|
|
112
|
+
label="Id"
|
|
113
|
+
tooltip="Unique identifier for this record"
|
|
114
|
+
placeholder="Enter id"
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
// Required field
|
|
118
|
+
<InputText label="Name" required placeholder="Enter name" />
|
|
119
|
+
|
|
120
|
+
// Disabled
|
|
121
|
+
<InputText label="Id" placeholder="Enter id" disabled />
|
|
122
|
+
|
|
123
|
+
// Multiline (textarea)
|
|
124
|
+
<InputText
|
|
125
|
+
label="Description"
|
|
126
|
+
textarea
|
|
127
|
+
rows={4}
|
|
128
|
+
placeholder="Enter a longer description"
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Props
|
|
133
|
+
|
|
134
|
+
| Prop | Type | Default | Description |
|
|
135
|
+
| ----------- | --------- | ------- | ----------------------------------------------------------------------- |
|
|
136
|
+
| label | ReactNode | - | Label text above the input |
|
|
137
|
+
| tooltip | string | - | If set, shows info icon with this tooltip |
|
|
138
|
+
| required | boolean | false | Shows asterisk on label |
|
|
139
|
+
| inputId | string | - | id for the input (for label association) |
|
|
140
|
+
| textarea | boolean | false | When true, renders a `<textarea>` instead of `<input>` |
|
|
141
|
+
| rows | number | 3 | Number of visible rows (textarea only) |
|
|
142
|
+
| disabled | boolean | false | Whether the input is disabled |
|
|
143
|
+
| className | string | - | Additional CSS class for the root |
|
|
144
|
+
| data-testid | string | - | Test ID for root and input (input gets suffix `-input`) |
|
|
145
|
+
|
|
146
|
+
All standard HTML input/textarea attributes (placeholder, value, onChange, etc.) are supported.
|
|
147
|
+
|
|
148
|
+
### SelectButton
|
|
149
|
+
|
|
150
|
+
Choose single or multiple options using buttons. API inspired by [PrimeReact SelectButton](https://primereact.org/selectbutton/). Selected state uses project primary colors.
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
import { SelectButton } from '@emporix/cockpit-component-library'
|
|
154
|
+
|
|
155
|
+
const options = [
|
|
156
|
+
{ label: 'Off', value: 'off' },
|
|
157
|
+
{ label: 'On', value: 'on' },
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
// Single selection
|
|
161
|
+
<SelectButton
|
|
162
|
+
value={value}
|
|
163
|
+
onChange={(e) => setValue(e.value)}
|
|
164
|
+
options={options}
|
|
165
|
+
/>
|
|
166
|
+
|
|
167
|
+
// Multiple selection
|
|
168
|
+
<SelectButton
|
|
169
|
+
value={selected}
|
|
170
|
+
onChange={(e) => setSelected(e.value)}
|
|
171
|
+
options={options}
|
|
172
|
+
multiple
|
|
173
|
+
/>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### Props
|
|
177
|
+
|
|
178
|
+
| Prop | Type | Default | Description |
|
|
179
|
+
| -------------- | ------------------------ | ------- | --------------------------------------- |
|
|
180
|
+
| value | unknown | - | Selected value (or array when multiple) |
|
|
181
|
+
| onChange | (e: ChangeEvent) => void | - | Callback when selection changes |
|
|
182
|
+
| options | T[] | - | Array of options |
|
|
183
|
+
| optionLabel | string | "label" | Property name for option label |
|
|
184
|
+
| optionValue | string | "value" | Property name for option value |
|
|
185
|
+
| optionDisabled | string | - | Property name for disabled flag |
|
|
186
|
+
| multiple | boolean | false | Allow multiple selection |
|
|
187
|
+
| itemTemplate | (option) => ReactNode | - | Custom render for each option |
|
|
188
|
+
| disabled | boolean | false | Disable the whole component |
|
|
189
|
+
| invalid | boolean | false | Validation invalid state |
|
|
190
|
+
| className | string | - | Additional CSS class |
|
|
191
|
+
| data-testid | string | - | Test ID for root and option buttons |
|
|
192
|
+
|
|
193
|
+
### Tabs
|
|
194
|
+
|
|
195
|
+
A flexible tabs component for organizing content into multiple panels.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { Tabs, TabItem } from '@emporix/cockpit-component-library'
|
|
199
|
+
|
|
200
|
+
const tabs: TabItem[] = [
|
|
201
|
+
{
|
|
202
|
+
id: 'tab1',
|
|
203
|
+
label: 'First Tab',
|
|
204
|
+
content: <div>First tab content</div>,
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: 'tab2',
|
|
208
|
+
label: 'Second Tab',
|
|
209
|
+
content: <div>Second tab content</div>,
|
|
210
|
+
},
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
// Basic usage
|
|
214
|
+
<Tabs
|
|
215
|
+
tabs={tabs}
|
|
216
|
+
activeTabId="tab1"
|
|
217
|
+
onTabChange={(tabId) => setActiveTab(tabId)}
|
|
218
|
+
/>
|
|
219
|
+
|
|
220
|
+
// With custom styling and test ID
|
|
221
|
+
<Tabs
|
|
222
|
+
tabs={tabs}
|
|
223
|
+
activeTabId="tab1"
|
|
224
|
+
onTabChange={(tabId) => setActiveTab(tabId)}
|
|
225
|
+
className="custom-tabs"
|
|
226
|
+
data-testid="my-tabs"
|
|
227
|
+
/>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Props
|
|
231
|
+
|
|
232
|
+
| Prop | Type | Default | Description |
|
|
233
|
+
| ----------- | ----------------------- | ------- | ------------------------------ |
|
|
234
|
+
| tabs | TabItem[] | - | Array of tab items |
|
|
235
|
+
| activeTabId | string | - | ID of the currently active tab |
|
|
236
|
+
| onTabChange | (tabId: string) => void | - | Callback when tab is changed |
|
|
237
|
+
| className | string | - | Additional CSS class |
|
|
238
|
+
| data-testid | string | - | Test ID for testing |
|
|
239
|
+
|
|
240
|
+
#### TabItem Interface
|
|
241
|
+
|
|
242
|
+
| Prop | Type | Description |
|
|
243
|
+
| ------- | --------- | ------------------------------ |
|
|
244
|
+
| id | string | Unique identifier for the tab |
|
|
245
|
+
| label | string | Display label for the tab |
|
|
246
|
+
| content | ReactNode | Content to display when active |
|
|
247
|
+
|
|
248
|
+
## Theming with CSS Variables
|
|
249
|
+
|
|
250
|
+
The component library uses CSS variables for easy theming. You can customize the appearance by overriding these variables:
|
|
251
|
+
|
|
252
|
+
```css
|
|
253
|
+
:root {
|
|
254
|
+
--color-primary: #your-primary-color;
|
|
255
|
+
--color-primary-hover: #your-primary-hover-color;
|
|
256
|
+
--border-radius-md: 0.5rem;
|
|
257
|
+
--font-size-lg: 1.2rem;
|
|
258
|
+
/* ... other variables */
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Available CSS Variables
|
|
263
|
+
|
|
264
|
+
The component library provides a minimal set of CSS variables that are actually used in the codebase. These variables are primarily used for the showcase page styling and can be customized for theming.
|
|
265
|
+
|
|
266
|
+
#### Colors
|
|
267
|
+
|
|
268
|
+
```css
|
|
269
|
+
--color-primary: #0E99C6;
|
|
270
|
+
--color-primary-hover: #0E87B3;
|
|
271
|
+
--color-dark: #27313B;
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Text Colors
|
|
275
|
+
|
|
276
|
+
```css
|
|
277
|
+
--color-text-primary: #FFFFFF;
|
|
278
|
+
--color-text-secondary: #999999;
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### Background Colors
|
|
282
|
+
|
|
283
|
+
```css
|
|
284
|
+
--color-bg-primary: #ffffff;
|
|
285
|
+
--color-bg-secondary: #f8f9fa;
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### Border Colors
|
|
289
|
+
|
|
290
|
+
```css
|
|
291
|
+
--color-border-light: #CAD0D6;
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Focus Ring
|
|
295
|
+
|
|
296
|
+
Reusable focus outline for inputs, dropdowns, SelectButton, etc. Override to change focus appearance globally.
|
|
297
|
+
|
|
298
|
+
```css
|
|
299
|
+
--focus-ring-box-shadow: 0 0 0 2px rgba(38, 101, 183, 0.35);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### Spacing
|
|
303
|
+
|
|
304
|
+
```css
|
|
305
|
+
--spacing-sm: 0.5rem; /* 8px */
|
|
306
|
+
--spacing-md: 1rem; /* 16px */
|
|
307
|
+
--spacing-lg: 1.5rem; /* 24px */
|
|
308
|
+
--spacing-xl: 3rem; /* 48px */
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### Border Radius
|
|
312
|
+
|
|
313
|
+
```css
|
|
314
|
+
--border-radius-sm: 0.25rem; /* 4px */
|
|
315
|
+
--border-radius-md: 0.375rem; /* 6px */
|
|
316
|
+
--border-radius-lg: 0.5rem; /* 8px */
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### Typography
|
|
320
|
+
|
|
321
|
+
**Font Sizes:**
|
|
322
|
+
|
|
323
|
+
```css
|
|
324
|
+
--font-size-sm: 0.875rem; /* 14px */
|
|
325
|
+
--font-size-base: 0.875rem; /* 14px */
|
|
326
|
+
--font-size-lg: 1.125rem; /* 18px */
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Font Weights:**
|
|
330
|
+
|
|
331
|
+
```css
|
|
332
|
+
--font-weight-normal: 400;
|
|
333
|
+
--font-weight-medium: 500;
|
|
334
|
+
--font-weight-semibold: 600;
|
|
335
|
+
--font-weight-bold: 700;
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Line Height:**
|
|
339
|
+
|
|
340
|
+
```css
|
|
341
|
+
--line-height-base: 1rem;
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Theming Examples
|
|
345
|
+
|
|
346
|
+
#### Basic Theming
|
|
347
|
+
|
|
348
|
+
```css
|
|
349
|
+
:root {
|
|
350
|
+
--color-primary: #your-brand-color;
|
|
351
|
+
--color-primary-hover: #your-brand-hover-color;
|
|
352
|
+
--border-radius-md: 0.5rem;
|
|
353
|
+
--font-size-lg: 1.2rem;
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Dark Theme
|
|
358
|
+
|
|
359
|
+
```css
|
|
360
|
+
:root {
|
|
361
|
+
--color-bg-primary: #1a1a1a;
|
|
362
|
+
--color-bg-secondary: #2d2d2d;
|
|
363
|
+
--color-text-primary: #ffffff;
|
|
364
|
+
--color-text-secondary: #cccccc;
|
|
365
|
+
--color-border-light: #404040;
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Custom Component Styling
|
|
370
|
+
|
|
371
|
+
```css
|
|
372
|
+
.my-custom-component {
|
|
373
|
+
padding: var(--spacing-md);
|
|
374
|
+
border-radius: var(--border-radius-lg);
|
|
375
|
+
background-color: var(--color-bg-primary);
|
|
376
|
+
color: var(--color-text-primary);
|
|
377
|
+
border: 1px solid var(--color-border-light);
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Development
|
|
382
|
+
|
|
383
|
+
### Prerequisites
|
|
384
|
+
|
|
385
|
+
- Node.js 18+
|
|
386
|
+
- npm or yarn
|
|
387
|
+
|
|
388
|
+
### Setup
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
# Clone the repository
|
|
392
|
+
git clone <repository-url>
|
|
393
|
+
cd cockpit-component-library
|
|
394
|
+
|
|
395
|
+
# Install dependencies
|
|
396
|
+
npm install
|
|
397
|
+
|
|
398
|
+
# Start development server
|
|
399
|
+
npm run dev
|
|
400
|
+
|
|
401
|
+
# Start Storybook
|
|
402
|
+
npm run storybook
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Available Scripts
|
|
406
|
+
|
|
407
|
+
- `npm run dev` - Start development server with showcase
|
|
408
|
+
- `npm run build` - Build the development version
|
|
409
|
+
- `npm run build:lib` - Build the library for distribution
|
|
410
|
+
- `npm run test` - Run tests
|
|
411
|
+
- `npm run test:ui` - Run tests with UI
|
|
412
|
+
- `npm run test:coverage` - Run tests with coverage
|
|
413
|
+
- `npm run storybook` - Start Storybook
|
|
414
|
+
- `npm run build-storybook` - Build Storybook
|
|
415
|
+
- `npm run lint` - Run ESLint
|
|
416
|
+
- `npm run lint:fix` - Fix ESLint issues
|
|
417
|
+
- `npm run type-check` - Run TypeScript type checking
|
|
418
|
+
- `npm run format` - Format code with Prettier
|
|
419
|
+
- `npm run format:check` - Check code formatting
|
|
420
|
+
|
|
421
|
+
## Testing
|
|
422
|
+
|
|
423
|
+
The library includes comprehensive tests using Vitest and React Testing Library.
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# Run all tests
|
|
427
|
+
npm test
|
|
428
|
+
|
|
429
|
+
# Run tests with coverage
|
|
430
|
+
npm run test:coverage
|
|
431
|
+
|
|
432
|
+
# Run tests with UI
|
|
433
|
+
npm run test:ui
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
## Storybook
|
|
437
|
+
|
|
438
|
+
Interactive component documentation is available in Storybook.
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
# Start Storybook
|
|
442
|
+
npm run storybook
|
|
443
|
+
|
|
444
|
+
# Build Storybook
|
|
445
|
+
npm run build-storybook
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Building for Distribution
|
|
449
|
+
|
|
450
|
+
The library is built using Vite with optimized settings for npm distribution.
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# Build the library
|
|
454
|
+
npm run build:lib
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
The build output includes:
|
|
458
|
+
|
|
459
|
+
- ES modules (`index.es.js`)
|
|
460
|
+
- UMD bundle (`index.umd.js`)
|
|
461
|
+
- TypeScript declarations (`index.d.ts`)
|
|
462
|
+
- CSS styles (`styles.css`)
|
|
463
|
+
|
|
464
|
+
## Code Formatting
|
|
465
|
+
|
|
466
|
+
This project uses Prettier for consistent code formatting. The configuration is defined in `.prettierrc`.
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
# Format all files
|
|
470
|
+
npm run format
|
|
471
|
+
|
|
472
|
+
# Check if files are formatted correctly
|
|
473
|
+
npm run format:check
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
The project also includes pre-commit hooks that automatically format staged files before commits.
|
|
477
|
+
|
|
478
|
+
## Contributing
|
|
479
|
+
|
|
480
|
+
1. Fork the repository
|
|
481
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
482
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
483
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
484
|
+
5. Open a Pull Request
|
|
485
|
+
|
|
486
|
+
### Development Guidelines
|
|
487
|
+
|
|
488
|
+
- Follow TypeScript best practices
|
|
489
|
+
- Write tests for new components
|
|
490
|
+
- Add Storybook stories for components
|
|
491
|
+
- Follow the existing code style
|
|
492
|
+
- Update documentation as needed
|
|
493
|
+
- Use arrow functions for React components (enforced by ESLint)
|
|
494
|
+
- Avoid using `React.FC` type annotation (redundant with modern TypeScript)
|
|
495
|
+
- Use CSS variables for all styling values
|
|
496
|
+
- Follow the established naming conventions for CSS classes
|
|
497
|
+
|
|
498
|
+
## Troubleshooting
|
|
499
|
+
|
|
500
|
+
### Import Issues
|
|
501
|
+
|
|
502
|
+
If you encounter import errors like "Failed to resolve entry for package", ensure:
|
|
503
|
+
|
|
504
|
+
1. The package is properly installed: `npm install @emporix/cockpit-component-library`
|
|
505
|
+
2. You're using the correct import syntax:
|
|
506
|
+
```tsx
|
|
507
|
+
import { PrimaryButton } from '@emporix/cockpit-component-library'
|
|
508
|
+
import '@emporix/cockpit-component-library/styles'
|
|
509
|
+
```
|
|
510
|
+
3. Your bundler supports ES modules and the package.json exports field
|
|
511
|
+
|
|
512
|
+
### Styling Issues
|
|
513
|
+
|
|
514
|
+
If the PrimaryButton component appears unstyled or you get "styles not found" errors:
|
|
515
|
+
|
|
516
|
+
1. **Try Method 1 (Recommended):** Import styles in your main CSS file:
|
|
517
|
+
|
|
518
|
+
```css
|
|
519
|
+
@import '@emporix/cockpit-component-library/styles';
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
2. **Try Method 2:** Import styles in your main JavaScript/TypeScript file:
|
|
523
|
+
|
|
524
|
+
```tsx
|
|
525
|
+
import '@emporix/cockpit-component-library/styles'
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
3. **If both methods fail:** Copy the CSS file manually:
|
|
529
|
+
- Copy `node_modules/@emporix/cockpit-component-library/dist/style.css` to your project
|
|
530
|
+
- Import it in your main CSS file: `@import './path/to/style.css';`
|
|
531
|
+
|
|
532
|
+
4. **Check your bundler configuration:** Ensure your bundler (Vite, Webpack, etc.) is configured to handle CSS imports from node_modules
|
|
533
|
+
|
|
534
|
+
5. **Verify the CSS classes:** The component uses SCSS modules with hashed class names (e.g., `_primaryButton_1d0ha_1`, `_primaryButtonDisabled_1d0ha_53`) and CSS variables for theming
|
|
535
|
+
|
|
536
|
+
### TypeScript Issues
|
|
537
|
+
|
|
538
|
+
If TypeScript can't find types, make sure:
|
|
539
|
+
|
|
540
|
+
1. The `@types/react` package is installed
|
|
541
|
+
2. Your `tsconfig.json` includes the library in `node_modules`
|
|
542
|
+
|
|
543
|
+
### Bundler-Specific Notes
|
|
544
|
+
|
|
545
|
+
#### Vite
|
|
546
|
+
|
|
547
|
+
All methods should work with Vite. Method 1 (CSS import) is recommended.
|
|
548
|
+
|
|
549
|
+
#### Webpack
|
|
550
|
+
|
|
551
|
+
Method 1 and Method 2 should work. If you encounter issues, try Method 3.
|
|
552
|
+
|
|
553
|
+
#### Create React App
|
|
554
|
+
|
|
555
|
+
Method 1 and Method 2 should work. If you encounter issues, try Method 3.
|
|
556
|
+
|
|
557
|
+
#### Next.js
|
|
558
|
+
|
|
559
|
+
Method 1 (CSS import) is recommended. Import the CSS in your `_app.tsx` or `_app.js` file.
|
|
560
|
+
|
|
561
|
+
## License
|
|
562
|
+
|
|
563
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
564
|
+
|
|
565
|
+
## Support
|
|
566
|
+
|
|
567
|
+
For support and questions, please open an issue in the repository.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface PrimaryButtonProps {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the button
|
|
5
|
+
*/
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the button is disabled
|
|
9
|
+
*/
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the button is loading
|
|
13
|
+
*/
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Click handler
|
|
17
|
+
*/
|
|
18
|
+
onClick?: () => void;
|
|
19
|
+
/**
|
|
20
|
+
* Additional CSS class name
|
|
21
|
+
*/
|
|
22
|
+
className?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Test ID for testing
|
|
25
|
+
*/
|
|
26
|
+
'data-testid'?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const PrimaryButton: ({ children, disabled, loading, onClick, className, "data-testid": testId, ...props }: PrimaryButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=PrimaryButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrimaryButton.d.ts","sourceRoot":"","sources":["../../../src/components/buttons/PrimaryButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,aAAa,GAAI,sFAQ3B,kBAAkB,4CAsBpB,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface SecondaryButtonProps {
|
|
3
|
+
/**
|
|
4
|
+
* The content of the button
|
|
5
|
+
*/
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the button is disabled
|
|
9
|
+
*/
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Click handler
|
|
13
|
+
*/
|
|
14
|
+
onClick?: () => void;
|
|
15
|
+
/**
|
|
16
|
+
* Additional CSS class name
|
|
17
|
+
*/
|
|
18
|
+
className?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Test ID for testing
|
|
21
|
+
*/
|
|
22
|
+
'data-testid'?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const SecondaryButton: ({ children, disabled, onClick, className, "data-testid": testId, ...props }: SecondaryButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
//# sourceMappingURL=SecondaryButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecondaryButton.d.ts","sourceRoot":"","sources":["../../../src/components/buttons/SecondaryButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,eAAe,GAAI,6EAO7B,oBAAoB,4CAqBtB,CAAA"}
|