shirkasoft-ui-components 1.0.22 → 1.0.24
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 +685 -0
- package/fesm2022/shirkasoft-ui-components.mjs +734 -722
- package/fesm2022/shirkasoft-ui-components.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
# Shirkasoft UI Components
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://github.com/Ansem13/shirkasoft-ui-components/releases"><img src="https://img.shields.io/npm/v/shirkasoft-ui-components?style=flat&logo=npm&label=version" alt="npm version" /></a>
|
|
5
|
+
<a href="https://github.com/Ansem13/shirkasoft-ui-components/issues"><img src="https://img.shields.io/github/issues/Ansem13/shirkasoft-ui-components?style=flat&logo=github" alt="GitHub issues" /></a>
|
|
6
|
+
<a href="https://github.com/Ansem13/shirkasoft-ui-components"><img src="https://img.shields.io/badge/source-github-181717?style=flat&logo=github" alt="GitHub source" /></a>
|
|
7
|
+
<a href="https://ansem13.github.io/shirkasoft-ui-components/"><img src="https://img.shields.io/badge/showcase-online-10b981?style=flat&logo=githubpages" alt="Showcase" /></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
Created by <a href="https://shirkasoft.com" target="_blank"><strong>Shirkasoft</strong></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
Angular 21+ UI components library built with **Tailwind CSS**, **standalone components**, **Angular signals**, and **light/dark theme** support via CSS custom properties.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add shirkasoft-ui-components
|
|
20
|
+
# or
|
|
21
|
+
npm install shirkasoft-ui-components
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Peer Dependencies
|
|
25
|
+
|
|
26
|
+
| Package | Minimum version |
|
|
27
|
+
|---|---|
|
|
28
|
+
| @angular/common | ^21.2.0 |
|
|
29
|
+
| @angular/core | ^21.2.0 |
|
|
30
|
+
| @angular/forms | ^21.2.0 |
|
|
31
|
+
| rxjs | ^7.8.0 |
|
|
32
|
+
| @jsverse/transloco | >= 8.0.0 |
|
|
33
|
+
| @lucide/angular | ^1.17.0 |
|
|
34
|
+
| chart.js | ^4.4.0 |
|
|
35
|
+
|
|
36
|
+
## Theme Setup
|
|
37
|
+
|
|
38
|
+
Import the theme in your global `styles.css`:
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
@import '@shirkasoft/ui-components/theme.css';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The theme is based on `--shk-*` CSS variables. To customize colors, override the variables in `:root` (light mode) and `.dark` (dark mode):
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
:root {
|
|
48
|
+
--shk-primary-500: #3b82f6;
|
|
49
|
+
--shk-primary-600: #2563eb;
|
|
50
|
+
/* ... */
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Dark mode
|
|
55
|
+
|
|
56
|
+
Add the `dark` class to the `<html>` element to enable dark mode.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
document.documentElement.classList.toggle('dark');
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Components
|
|
65
|
+
|
|
66
|
+
| # | Component | Selector | ControlValueAccessor | Associated service |
|
|
67
|
+
|---|---|---|---|---|
|
|
68
|
+
| 1 | TextField | `shk-text-field` | ✅ | — |
|
|
69
|
+
| 2 | Toggle | `shk-toggle` | ✅ | — |
|
|
70
|
+
| 3 | Select | `shk-select` | ✅ | — |
|
|
71
|
+
| 4 | DatePicker | `shk-date-picker` | ✅ | — |
|
|
72
|
+
| 5 | PriceInput | `shk-price-input` | — | — |
|
|
73
|
+
| 6 | FileUpload | `shk-file-upload` | — | — |
|
|
74
|
+
| 7 | Table | `shk-table` | — | — |
|
|
75
|
+
| 8 | Modal | `shk-modal` | — | `ModalService` |
|
|
76
|
+
| 9 | Notification | `shk-notification` | — | `NotificationService` |
|
|
77
|
+
| 10 | ConfirmDialog | `shk-confirm-dialog` | — | `ConfirmDialogService` |
|
|
78
|
+
| 11 | Chart | `shk-chart` | — | — |
|
|
79
|
+
| 12 | Tooltip | `shk-tooltip` | — | — |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### TextField (`shk-text-field`)
|
|
84
|
+
|
|
85
|
+
Text input with support for input, textarea, password, search, credit card formatting, and error validation. Implements `ControlValueAccessor`.
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<shk-text-field
|
|
89
|
+
[label]="'Name'"
|
|
90
|
+
[control]="myControl"
|
|
91
|
+
[type]="'text'"
|
|
92
|
+
[placeholder]="'Enter your name'"
|
|
93
|
+
[disabled]="false"
|
|
94
|
+
[errorMessages]="{ required: 'This field is required' }"
|
|
95
|
+
[isTextArea]="false"
|
|
96
|
+
[searchMode]="false"
|
|
97
|
+
(searchButtonClick)="onSearch()"
|
|
98
|
+
/>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Input | Type | Default |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `id` | `string` | `''` |
|
|
104
|
+
| `label` | `string` | `''` |
|
|
105
|
+
| `type` | `string` | `'text'` |
|
|
106
|
+
| `placeholder` | `string` | `''` |
|
|
107
|
+
| `disabled` | `boolean` | `false` |
|
|
108
|
+
| `control` | `FormControl` | `undefined` |
|
|
109
|
+
| `formGroup` | `FormGroup` | `undefined` |
|
|
110
|
+
| `errorMessage` | `string` | `''` |
|
|
111
|
+
| `errorMessages` | `{ [key: string]: string }` | `{}` |
|
|
112
|
+
| `isTextArea` | `boolean` | `false` |
|
|
113
|
+
| `textAreaHeight` | `string` | `'h-28'` |
|
|
114
|
+
| `searchMode` | `boolean` | `false` |
|
|
115
|
+
| `searchButtonClick` | `output<void>` | — |
|
|
116
|
+
| `numbersOnly` | `boolean` | `false` |
|
|
117
|
+
| `allowDecimals` | `boolean` | `false` |
|
|
118
|
+
| `maxLength` | `number` | `undefined` |
|
|
119
|
+
| `formatCard` | `boolean` | `false` |
|
|
120
|
+
| `preventNegative` | `boolean` | `false` |
|
|
121
|
+
| `displayValue` | `string` | `''` |
|
|
122
|
+
| `autocomplete` | `string` | `'new-password'` |
|
|
123
|
+
|
|
124
|
+
> Also exposes `inputElement` and `textareaElement` as `viewChild`.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Toggle (`shk-toggle`)
|
|
129
|
+
|
|
130
|
+
Switch or checkbox. Implements `ControlValueAccessor`.
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<shk-toggle
|
|
134
|
+
[label]="'Enable notifications'"
|
|
135
|
+
[mode]="'toggle'"
|
|
136
|
+
[(checked)]="isChecked"
|
|
137
|
+
(checkedChange)="onChange($event)"
|
|
138
|
+
/>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
| Input | Type | Default |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| `label` | `string` | `''` |
|
|
144
|
+
| `mode` | `'toggle' \| 'checkbox'` | `'toggle'` |
|
|
145
|
+
| `checked` | `boolean` | `undefined` |
|
|
146
|
+
|
|
147
|
+
| Output | Type |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `checkedChange` | `boolean` |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### Select (`shk-select`)
|
|
154
|
+
|
|
155
|
+
Searchable dropdown with pagination, multiple selection, custom options, and validation. Implements `ControlValueAccessor`.
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<shk-select
|
|
159
|
+
[options]="options"
|
|
160
|
+
[label]="'Country'"
|
|
161
|
+
[control]="countryControl"
|
|
162
|
+
[multiple]="false"
|
|
163
|
+
[isSearchable]="true"
|
|
164
|
+
[usePagination]="true"
|
|
165
|
+
[itemsPerPage]="10"
|
|
166
|
+
[allowCustomEntries]="false"
|
|
167
|
+
[placeholder]="'Select...'"
|
|
168
|
+
[isLoading]="false"
|
|
169
|
+
(selectionChange)="onSelect($event)"
|
|
170
|
+
(search)="onSearch($event)"
|
|
171
|
+
/>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
interface SelectOption {
|
|
176
|
+
label: string;
|
|
177
|
+
value: any;
|
|
178
|
+
custom?: boolean;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
| Input | Type | Default |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `options` | `SelectOption[]` | `[]` |
|
|
185
|
+
| `label` | `string` | `undefined` |
|
|
186
|
+
| `placeholder` | `string` | `'Select...'` |
|
|
187
|
+
| `disabled` | `boolean` | `false` |
|
|
188
|
+
| `control` | `FormControl` | `undefined` |
|
|
189
|
+
| `formGroup` | `FormGroup` | `undefined` |
|
|
190
|
+
| `multiple` | `boolean` | `false` |
|
|
191
|
+
| `isSearchable` | `boolean` | `false` |
|
|
192
|
+
| `usePagination` | `boolean` | `false` |
|
|
193
|
+
| `itemsPerPage` | `number` | `10` |
|
|
194
|
+
| `allowCustomEntries` | `boolean` | `false` |
|
|
195
|
+
| `isLoading` | `boolean` | `false` |
|
|
196
|
+
| `isAllDataLoaded` | `boolean` | `false` |
|
|
197
|
+
| `preserveSearchOnLoad` | `boolean` | `false` |
|
|
198
|
+
| `dropdownUpward` | `boolean` | `false` |
|
|
199
|
+
| `showEmptyOption` | `boolean` | `true` |
|
|
200
|
+
| `emptyMessageKey` | `string` | `'common.no_records'` |
|
|
201
|
+
| `validCombinations` | `string[][]` | `undefined` |
|
|
202
|
+
| `errorMessages` | `{ [key: string]: string }` | `{ required: 'This field is required' }` |
|
|
203
|
+
|
|
204
|
+
| Output | Type |
|
|
205
|
+
|---|---|
|
|
206
|
+
| `selectionChange` | `any` |
|
|
207
|
+
| `search` | `string` |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### DatePicker (`shk-date-picker`)
|
|
212
|
+
|
|
213
|
+
Date, month, or year picker. Implements `ControlValueAccessor`. Supports `'date'`, `'month'`, `'year'` views.
|
|
214
|
+
|
|
215
|
+
```html
|
|
216
|
+
<shk-date-picker
|
|
217
|
+
[label]="'Start date'"
|
|
218
|
+
[control]="dateControl"
|
|
219
|
+
[view]="'date'"
|
|
220
|
+
[locale]="'es'"
|
|
221
|
+
[minValue]="'2024-01-01'"
|
|
222
|
+
[maxValue]="'2026-12-31'"
|
|
223
|
+
/>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
| Input | Type | Default |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| `id` | `string` | `''` |
|
|
229
|
+
| `label` | `string` | `''` |
|
|
230
|
+
| `placeholder` | `string` | `''` |
|
|
231
|
+
| `view` | `'date' \| 'month' \| 'year'` | `'date'` |
|
|
232
|
+
| `control` | `FormControl` | `undefined` |
|
|
233
|
+
| `formGroup` | `FormGroup` | `undefined` |
|
|
234
|
+
| `disabled` | `boolean` | `false` |
|
|
235
|
+
| `errorMessage` | `string` | `''` |
|
|
236
|
+
| `errorMessages` | `{ [key: string]: string }` | `{}` |
|
|
237
|
+
| `minValue` | `string` | `''` |
|
|
238
|
+
| `maxValue` | `string` | `''` |
|
|
239
|
+
| `locale` | `string` | `'es'` |
|
|
240
|
+
|
|
241
|
+
**Return value** depends on `view`:
|
|
242
|
+
- `'date'` → `'YYYY-MM-DD'`
|
|
243
|
+
- `'month'` → `'YYYY-MM'`
|
|
244
|
+
- `'year'` → `'YYYY'`
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### PriceInput (`shk-price-input`)
|
|
249
|
+
|
|
250
|
+
Numeric input with toggle between amount (`$`) and percentage (`%`). Uses Angular `model()` for two-way binding.
|
|
251
|
+
|
|
252
|
+
```html
|
|
253
|
+
<shk-price-input
|
|
254
|
+
[(value)]="price"
|
|
255
|
+
[(isPercentage)]="isPercent"
|
|
256
|
+
[label]="'Price'"
|
|
257
|
+
[min]="0"
|
|
258
|
+
[max]="10000"
|
|
259
|
+
[required]="true"
|
|
260
|
+
[showError]="hasError"
|
|
261
|
+
[errorMessage]="'Invalid value'"
|
|
262
|
+
/>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
| Input | Type | Default |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `value` | `model<number>` | **required** |
|
|
268
|
+
| `isPercentage` | `model<boolean>` | `false` |
|
|
269
|
+
| `label` | `string` | `''` |
|
|
270
|
+
| `inputId` | `string` | `''` |
|
|
271
|
+
| `required` | `boolean` | `false` |
|
|
272
|
+
| `disabled` | `boolean` | `false` |
|
|
273
|
+
| `min` | `number` | `0` |
|
|
274
|
+
| `max` | `number` | `Infinity` |
|
|
275
|
+
| `showError` | `boolean` | `false` |
|
|
276
|
+
| `errorMessage` | `string` | `''` |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### FileUpload (`shk-file-upload`)
|
|
281
|
+
|
|
282
|
+
File upload with drag & drop, image preview, file type and size validation.
|
|
283
|
+
|
|
284
|
+
```html
|
|
285
|
+
<shk-file-upload
|
|
286
|
+
[label]="'Upload your photo'"
|
|
287
|
+
[accept]="'image/*'"
|
|
288
|
+
[maxFileSize]="5 * 1024 * 1024"
|
|
289
|
+
[maxFiles]="3"
|
|
290
|
+
[multiple]="true"
|
|
291
|
+
(fileSelected)="onFilesSelected($event)"
|
|
292
|
+
(fileRemoved)="onFileRemoved()"
|
|
293
|
+
(fileError)="onFileError($event)"
|
|
294
|
+
/>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
interface FileUploadError {
|
|
299
|
+
type: 'size' | 'type';
|
|
300
|
+
message: string;
|
|
301
|
+
file: File;
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
| Input | Type | Default |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| `label` | `string` | `'Upload file'` |
|
|
308
|
+
| `accept` | `string` | `'image/*'` |
|
|
309
|
+
| `maxFileSize` | `number` | `2 * 1024 * 1024` (2MB) |
|
|
310
|
+
| `maxFiles` | `number` | `0` (unlimited) |
|
|
311
|
+
| `multiple` | `boolean` | `false` |
|
|
312
|
+
| `fileUploadText` | `string` | `'Select file'` |
|
|
313
|
+
| `changeFilesText` | `string` | `'Change files'` |
|
|
314
|
+
| `fileRecommendation` | `string` | `''` |
|
|
315
|
+
|
|
316
|
+
| Output | Type |
|
|
317
|
+
|---|---|
|
|
318
|
+
| `fileSelected` | `File[]` |
|
|
319
|
+
| `fileRemoved` | `void` |
|
|
320
|
+
| `fileError` | `FileUploadError` |
|
|
321
|
+
| `fileWarning` | `FileUploadError` |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### Table (`shk-table`)
|
|
326
|
+
|
|
327
|
+
Data table with sorting, column filters, global search, pagination, row actions, and header actions. Supports client and server-side mode.
|
|
328
|
+
|
|
329
|
+
```html
|
|
330
|
+
<shk-table
|
|
331
|
+
[data]="users"
|
|
332
|
+
[columns]="columns"
|
|
333
|
+
[loading]="isLoading"
|
|
334
|
+
[serverSide]="true"
|
|
335
|
+
[totalRecords]="totalUsers"
|
|
336
|
+
[rowActions]="rowActions"
|
|
337
|
+
[headerActions]="headerActions"
|
|
338
|
+
[rowsPerPage]="25"
|
|
339
|
+
[showSearch]="true"
|
|
340
|
+
(pageChange)="onPageChange($event)"
|
|
341
|
+
(searchChange)="onSearch($event)"
|
|
342
|
+
(refresh)="loadData()"
|
|
343
|
+
/>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
interface Column {
|
|
348
|
+
field: string;
|
|
349
|
+
header: string;
|
|
350
|
+
sortable?: boolean;
|
|
351
|
+
filter?: boolean;
|
|
352
|
+
filterPlaceholder?: string;
|
|
353
|
+
width?: string;
|
|
354
|
+
defaultSort?: true;
|
|
355
|
+
filterType?: 'text' | 'exact' | 'select';
|
|
356
|
+
filterOptions?: { label: string; value: any }[];
|
|
357
|
+
template?: 'text' | 'tag';
|
|
358
|
+
format?: (row: any) => string;
|
|
359
|
+
tagValue?: (row: any) => string;
|
|
360
|
+
tagSeverity?: (row: any) => 'success' | 'danger' | 'warn' | 'info' | undefined;
|
|
361
|
+
tagStyle?: (row: any) => { [key: string]: string } | undefined;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
interface TableAction {
|
|
365
|
+
label: string;
|
|
366
|
+
icon: string;
|
|
367
|
+
onClick: () => void;
|
|
368
|
+
class?: string;
|
|
369
|
+
isVisible?: () => boolean;
|
|
370
|
+
isDisabled?: () => boolean;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
interface RowAction {
|
|
374
|
+
label: string | ((data: any) => string);
|
|
375
|
+
icon: string | ((data: any) => string);
|
|
376
|
+
onClick: (rowData: any) => void;
|
|
377
|
+
class?: string | ((data: any) => string);
|
|
378
|
+
isVisible?: (rowData: any) => boolean;
|
|
379
|
+
isDisabled?: (rowData: any) => boolean;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
interface PageChangeEvent {
|
|
383
|
+
first: number;
|
|
384
|
+
rows: number;
|
|
385
|
+
page: number;
|
|
386
|
+
pageCount: number;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
interface FilterChangeEvent {
|
|
390
|
+
filters: { [key: string]: any };
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
| Input | Type | Default |
|
|
395
|
+
|---|---|---|
|
|
396
|
+
| `data` | `any[]` | `[]` |
|
|
397
|
+
| `columns` | `Column[]` | `[]` |
|
|
398
|
+
| `rowsPerPage` | `number` | `10` |
|
|
399
|
+
| `rowsPerPageOptions` | `number[]` | `[10, 25, 50]` |
|
|
400
|
+
| `loading` | `boolean` | `false` |
|
|
401
|
+
| `showActionRow` | `boolean` | `true` |
|
|
402
|
+
| `headerActions` | `TableAction[]` | `[]` |
|
|
403
|
+
| `rowActions` | `RowAction[]` | `[]` |
|
|
404
|
+
| `hasShadow` | `boolean` | `true` |
|
|
405
|
+
| `defaultSortField` | `string` | `''` |
|
|
406
|
+
| `defaultSortOrder` | `number` | `1` |
|
|
407
|
+
| `showSearch` | `boolean` | `true` |
|
|
408
|
+
| `searchPlaceholder` | `string` | `''` |
|
|
409
|
+
| `emptyMessage` | `string` | `''` |
|
|
410
|
+
| `serverSide` | `boolean` | `false` |
|
|
411
|
+
| `totalRecords` | `number` | `0` |
|
|
412
|
+
| `filters` | `{ label: string; value: string }[]` | `[]` |
|
|
413
|
+
| `activeFilter` | `string` | `''` |
|
|
414
|
+
| `customTemplates` | `{ [key: string]: any }` | `{}` |
|
|
415
|
+
|
|
416
|
+
| Output | Type |
|
|
417
|
+
|---|---|
|
|
418
|
+
| `pageChange` | `PageChangeEvent` |
|
|
419
|
+
| `filterChange` | `FilterChangeEvent` |
|
|
420
|
+
| `searchChange` | `string` |
|
|
421
|
+
| `filterClick` | `string` |
|
|
422
|
+
| `refresh` | `void` |
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
### Modal (`shk-modal`)
|
|
427
|
+
|
|
428
|
+
Dynamic modal that loads components via `ModalService`. Supports forms, fullscreen expansion, and accept/cancel buttons.
|
|
429
|
+
|
|
430
|
+
```html
|
|
431
|
+
<shk-modal />
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
interface ModalConfig {
|
|
436
|
+
title: string;
|
|
437
|
+
component: Type<any>;
|
|
438
|
+
data?: Record<string, any>;
|
|
439
|
+
width?: string;
|
|
440
|
+
showButtons?: boolean;
|
|
441
|
+
showExpandButton?: boolean;
|
|
442
|
+
acceptLabel?: string;
|
|
443
|
+
cancelLabel?: string;
|
|
444
|
+
onClose?: () => void;
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
The injected component **must** expose:
|
|
449
|
+
- `form?: FormGroup` (optional, for validation)
|
|
450
|
+
- `onSubmit()` → calls `submitSuccess` or `submitError`
|
|
451
|
+
- `submitSuccess?: EventEmitter<void>` (optional)
|
|
452
|
+
- `submitError?: EventEmitter<void>` (optional)
|
|
453
|
+
- `handleCancel?: () => void` (optional)
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
constructor(private modalSrv: ModalService) {}
|
|
457
|
+
|
|
458
|
+
openModal() {
|
|
459
|
+
this.modalSrv.open({
|
|
460
|
+
title: 'Edit user',
|
|
461
|
+
component: EditUserComponent,
|
|
462
|
+
data: { userId: 123 },
|
|
463
|
+
width: '600px',
|
|
464
|
+
showButtons: true,
|
|
465
|
+
showExpandButton: true,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
closeModal() {
|
|
470
|
+
this.modalSrv.close();
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**Service methods:**
|
|
475
|
+
|
|
476
|
+
| Method | Description |
|
|
477
|
+
|---|---|
|
|
478
|
+
| `open(config: ModalConfig)` | Opens a new modal |
|
|
479
|
+
| `close()` | Closes the current modal |
|
|
480
|
+
| `accept()` | Closes the modal (alias for close) |
|
|
481
|
+
| `clear()` | Closes all modals |
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### Notification (`shk-notification`)
|
|
486
|
+
|
|
487
|
+
Toast notification system with configurable positions and optional progress bar.
|
|
488
|
+
|
|
489
|
+
```html
|
|
490
|
+
<shk-notification position="right-top" />
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
interface Notification {
|
|
495
|
+
id: string;
|
|
496
|
+
message: string;
|
|
497
|
+
type: 'success' | 'error' | 'warning' | 'info';
|
|
498
|
+
progress?: number;
|
|
499
|
+
showProgress?: boolean;
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
constructor(private notifSrv: NotificationService) {}
|
|
505
|
+
|
|
506
|
+
showNotif() {
|
|
507
|
+
const id = this.notifSrv.addNotification(
|
|
508
|
+
'Operation successful',
|
|
509
|
+
'success',
|
|
510
|
+
false, // showProgress
|
|
511
|
+
3000 // duration (ms)
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
updateProgress(id: string, progress: number) {
|
|
516
|
+
this.notifSrv.updateProgress(id, progress);
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
| Input | Type | Default |
|
|
521
|
+
|---|---|---|
|
|
522
|
+
| `position` | `'center-top' \| 'right-top' \| 'left-top'` | `'center-top'` |
|
|
523
|
+
|
|
524
|
+
**Service methods:**
|
|
525
|
+
|
|
526
|
+
| Method | Description |
|
|
527
|
+
|---|---|
|
|
528
|
+
| `addNotification(msg, type?, showProgress?, duration?)` | Adds a notification |
|
|
529
|
+
| `updateProgress(id, progress)` | Updates the progress bar |
|
|
530
|
+
| `removeNotification(notification)` | Removes a notification |
|
|
531
|
+
| `removeNotificationById(id)` | Removes by ID |
|
|
532
|
+
| `clearAll()` | Removes all notifications |
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### ConfirmDialog (`shk-confirm-dialog`)
|
|
537
|
+
|
|
538
|
+
Programmatic confirmation dialog. Used via `ConfirmDialogService` which dynamically creates it.
|
|
539
|
+
|
|
540
|
+
```html
|
|
541
|
+
<!-- No need to add it to the template -->
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
interface ConfirmConfig {
|
|
546
|
+
title?: string;
|
|
547
|
+
message: string;
|
|
548
|
+
confirmLabel?: string;
|
|
549
|
+
cancelLabel?: string;
|
|
550
|
+
loadingText?: string;
|
|
551
|
+
type?: 'danger' | 'info' | 'warning';
|
|
552
|
+
showCancel?: boolean;
|
|
553
|
+
loading?: boolean;
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
constructor(private confirmSrv: ConfirmDialogService) {}
|
|
559
|
+
|
|
560
|
+
async deleteItem() {
|
|
561
|
+
const confirmed = await this.confirmSrv.confirm({
|
|
562
|
+
title: 'Delete user',
|
|
563
|
+
message: 'Are you sure you want to delete this user?',
|
|
564
|
+
confirmLabel: 'Delete',
|
|
565
|
+
type: 'danger',
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
if (confirmed) {
|
|
569
|
+
// proceed with deletion
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
| Input | Type | Default |
|
|
575
|
+
|---|---|---|
|
|
576
|
+
| `title` | `string` | `'Confirm action'` |
|
|
577
|
+
| `message` | `string` | `'Are you sure you want to proceed?'` |
|
|
578
|
+
| `confirmLabel` | `string` | `'Confirm'` |
|
|
579
|
+
| `cancelLabel` | `string` | `'Cancel'` |
|
|
580
|
+
| `loadingText` | `string` | `'Processing…'` |
|
|
581
|
+
| `type` | `'danger' \| 'info' \| 'warning'` | `'danger'` |
|
|
582
|
+
| `loading` | `boolean` | `false` |
|
|
583
|
+
| `showCancel` | `boolean` | `true` |
|
|
584
|
+
|
|
585
|
+
| Output | Type |
|
|
586
|
+
|---|---|
|
|
587
|
+
| `closed` | `void` |
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
### Chart (`shk-chart`)
|
|
592
|
+
|
|
593
|
+
Chart.js wrapper supporting the main chart types.
|
|
594
|
+
|
|
595
|
+
```html
|
|
596
|
+
<shk-chart
|
|
597
|
+
[type]="'bar'"
|
|
598
|
+
[data]="chartData"
|
|
599
|
+
[options]="chartOptions"
|
|
600
|
+
/>
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
import { COLOR_PALETTE, readThemeColors } from 'shirkasoft-ui-components';
|
|
605
|
+
|
|
606
|
+
const colors = readThemeColors(); // current theme colors
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
| Input | Type | Default |
|
|
610
|
+
|---|---|---|
|
|
611
|
+
| `type` | `'line' \| 'bar' \| 'pie' \| 'doughnut' \| 'polarArea'` | `'bar'` |
|
|
612
|
+
| `data` | `any` | `{ datasets: [] }` |
|
|
613
|
+
| `options` | `any` | `{}` |
|
|
614
|
+
|
|
615
|
+
**Exported utils:**
|
|
616
|
+
|
|
617
|
+
| Export | Description |
|
|
618
|
+
|---|---|
|
|
619
|
+
| `COLOR_PALETTE` | Predefined color array (bg + border) |
|
|
620
|
+
| `readThemeColors()` | Reads current theme colors (`--shk-surface-*`) |
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
### Tooltip (`shk-tooltip`)
|
|
625
|
+
|
|
626
|
+
Tooltip with two modes: `hover` (CSS positioning) and `fixed` (JS-calculated positioning).
|
|
627
|
+
|
|
628
|
+
```html
|
|
629
|
+
<shk-tooltip [text]="'Additional info'" [position]="'bottom'" [mode]="'hover'">
|
|
630
|
+
<button>Hover me</button>
|
|
631
|
+
</shk-tooltip>
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
| Input | Type | Default |
|
|
635
|
+
|---|---|---|
|
|
636
|
+
| `text` | `string` | `''` |
|
|
637
|
+
| `position` | `'top' \| 'bottom' \| 'right'` | `'bottom'` |
|
|
638
|
+
| `mode` | `'hover' \| 'fixed'` | `'hover'` |
|
|
639
|
+
| `offset` | `number` | `8` |
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Development
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
# Build the library
|
|
647
|
+
pnpm build
|
|
648
|
+
|
|
649
|
+
# Serve the showcase (demo app)
|
|
650
|
+
pnpm serve
|
|
651
|
+
|
|
652
|
+
# Build the showcase
|
|
653
|
+
pnpm build:showcase
|
|
654
|
+
|
|
655
|
+
# Watch for library changes
|
|
656
|
+
pnpm watch
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Versioning
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
pnpm version:patch # 1.0.22 → 1.0.23
|
|
663
|
+
pnpm version:minor # 1.0.22 → 1.1.0
|
|
664
|
+
pnpm version:major # 1.0.22 → 2.0.0
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
## Publishing
|
|
670
|
+
|
|
671
|
+
CI/CD via GitHub Actions:
|
|
672
|
+
- Pushing a `v*` tag automatically publishes to npm.
|
|
673
|
+
- Pushing to `main`/`master` deploys the showcase to GitHub Pages.
|
|
674
|
+
|
|
675
|
+
Manual:
|
|
676
|
+
|
|
677
|
+
```bash
|
|
678
|
+
bash scripts/publish-lib.sh
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## License
|
|
684
|
+
|
|
685
|
+
MIT © Shirkasoft
|