@idds/vue 1.4.4 → 1.4.5

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
@@ -2,38 +2,59 @@
2
2
 
3
3
  Vue 3 UI component library for INA Digital Design System.
4
4
 
5
+ This package provides a comprehensive set of Vue 3 components built with TypeScript. All styles are managed centrally in `@idds/styles` package and are **not dependent on Tailwind CSS classes**. Components use pure CSS with BEM-like naming conventions.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
8
10
  npm install @idds/vue
9
11
  ```
10
12
 
11
- ## Usage
13
+ ## Peer Dependencies
14
+
15
+ ```bash
16
+ npm install vue@^3.4.0
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Import CSS
22
+
23
+ Import the styles in your application entry point:
24
+
25
+ ```js
26
+ // src/main.js or src/main.ts
27
+ import '@idds/vue/index.css';
28
+ ```
12
29
 
13
- ### Basic Setup
30
+ ### 2. Import and Use Components
14
31
 
15
32
  ```vue
16
33
  <template>
17
34
  <div>
18
- <Button variant="primary" size="md">Click me</Button>
19
- <TextField v-model="value" label="Name" placeholder="Enter your name" />
35
+ <Button variant="primary" size="md" @click="handleClick"> Click me </Button>
36
+ <TextField v-model="value" label="Email" placeholder="Enter your email" />
20
37
  </div>
21
38
  </template>
22
39
 
23
40
  <script setup>
24
41
  import { ref } from 'vue';
25
42
  import { Button, TextField } from '@idds/vue';
26
- import '@idds/vue/index.css';
27
43
 
28
44
  const value = ref('');
45
+ const handleClick = () => {
46
+ console.log('Button clicked');
47
+ };
29
48
  </script>
30
49
  ```
31
50
 
51
+ ## Usage
52
+
32
53
  ### Import Individual Components
33
54
 
34
55
  ```vue
35
56
  <script setup>
36
- import { Button, TextField, SelectDropdown } from '@idds/vue';
57
+ import { Button, TextField, SelectDropdown, Modal } from '@idds/vue';
37
58
  </script>
38
59
  ```
39
60
 
@@ -48,245 +69,496 @@ const { Button, TextField, SelectDropdown } = InaDigitalUI;
48
69
  </script>
49
70
  ```
50
71
 
51
- ## Components
72
+ ### Import Color Tokens (Optional - for Tailwind CSS integration)
52
73
 
53
- ### Button
74
+ If you want to use INA Digital color tokens with Tailwind CSS in your project:
75
+
76
+ #### Tailwind CSS v3
77
+
78
+ For Tailwind CSS v3, import the TypeScript token files:
79
+
80
+ ```js
81
+ // tailwind.config.js
82
+ import iddsColorTokens from '@idds/vue';
83
+ import bgnColorTokens from '@idds/vue'; // Brand-specific tokens
84
+
85
+ export default {
86
+ theme: {
87
+ extend: {
88
+ colors: {
89
+ ...iddsColorTokens,
90
+ ...bgnColorTokens,
91
+ },
92
+ },
93
+ },
94
+ };
95
+ ```
96
+
97
+ #### Tailwind CSS v4
98
+
99
+ For Tailwind CSS v4, import the CSS theme files directly in your main CSS file:
100
+
101
+ ```css
102
+ /* src/index.css or your main CSS file */
103
+
104
+ /* Tailwind CSS v4 */
105
+ @import 'tailwindcss';
106
+
107
+ /* INA Digital color tokens */
108
+ @import '@idds/styles/tailwind/css/idds.css';
109
+ @import '@idds/styles/tailwind/css/bgn.css'; /* Optional: brand theme */
110
+ ```
111
+
112
+ Or use minified versions for production:
113
+
114
+ ```css
115
+ @import 'tailwindcss';
116
+ @import '@idds/styles/tailwind/css/idds.min.css';
117
+ @import '@idds/styles/tailwind/css/bgn.min.css';
118
+ ```
119
+
120
+ Then you can use Tailwind utility classes with INA Digital colors:
54
121
 
55
122
  ```vue
56
- <Button
57
- variant="primary"
58
- size="md"
59
- :disabled="false"
60
- :loading="false"
61
- @click="handleClick"
62
- >
63
- Button Text
64
- </Button>
123
+ <template>
124
+ <div class="bg-blue-500 text-white p-4">
125
+ <p class="text-guide-500">This text uses guide-500 color</p>
126
+ <p class="text-neutral-500">This text uses neutral-500 color</p>
127
+ </div>
128
+ </template>
65
129
  ```
66
130
 
67
- **Props:**
131
+ **Available brand theme files:**
132
+
133
+ - `@idds/styles/tailwind/css/idds.css` - Default theme
134
+ - `@idds/styles/tailwind/css/inagov.css` - INAGov brand
135
+ - `@idds/styles/tailwind/css/inaku.css` - INAKu brand
136
+ - `@idds/styles/tailwind/css/inapas.css` - INAPas brand
137
+ - `@idds/styles/tailwind/css/bgn.css` - BGN brand
138
+ - `@idds/styles/tailwind/css/bkn.css` - BKN brand
139
+ - `@idds/styles/tailwind/css/lan.css` - LAN brand
140
+ - `@idds/styles/tailwind/css/panrb.css` - panrb brand
141
+
142
+ ## Available Components
143
+
144
+ ### Form Components
145
+
146
+ - **TextField** - Text input with validation, clear button, and character count
147
+ - **TextArea** - Multi-line text input with autosize
148
+ - **PasswordInput** - Password input with show/hide toggle
149
+ - **SelectDropdown** - Dropdown select with search and multi-select support
150
+ - **Checkbox** - Checkbox input
151
+ - **RadioInput** - Radio button input
152
+ - **DatePicker** - Date picker with single, range, and multiple modes
153
+ - **TimePicker** - Time picker
154
+ - **YearPicker** - Year picker
155
+ - **MonthPicker** - Month picker
156
+ - **PhoneInput** - Phone number input with country selector
157
+ - **OneTimePassword** - OTP input component
158
+ - **FileUpload** - File upload with drag & drop and validation
159
+ - **SingleFileUpload** - Single file upload component
160
+ - **Toggle** - Toggle switch component
161
+
162
+ ### Layout Components
163
+
164
+ - **Card** - Card container component
165
+ - **Accordion** - Collapsible accordion component
166
+ - **AccordionCard** - Accordion with card styling
167
+ - **AccordionGroup** - Group of accordions
168
+ - **Divider** - Horizontal or vertical divider
169
+ - **Stepper** - Step indicator component
170
+ - **Breadcrumb** - Breadcrumb navigation
171
+ - **TabHorizontal** - Horizontal tabs
172
+ - **TabVertical** - Vertical tabs
173
+
174
+ ### Feedback Components
175
+
176
+ - **Alert** - Alert message component
177
+ - **Toast** - Toast notification (use with ToastProvider)
178
+ - **ToastProvider** - Provider for toast notifications
179
+ - **Modal** - Modal dialog component
180
+ - **Drawer** - Side drawer component
181
+ - **BottomSheet** - Bottom sheet component
182
+ - **Tooltip** - Tooltip component
183
+ - **Skeleton** - Loading skeleton component
184
+ - **Spinner** - Loading spinner component
185
+ - **ProgressBar** - Progress bar component
186
+ - **LinearProgressIndicator** - Linear progress indicator
187
+ - **TableProgressBar** - Progress bar for tables
188
+
189
+ ### Data Display Components
190
+
191
+ - **Table** - Advanced table with sorting, pagination, and editing
192
+ - **FieldInputTable** - Table with inline input fields
193
+ - **MultipleChoiceGrid** - Grid for multiple choice questions
194
+ - **Avatar** - Avatar component
195
+ - **Badge** - Badge component
196
+ - **Chip** - Chip component
197
+
198
+ ### Navigation Components
199
+
200
+ - **Button** - Button component with multiple variants
201
+ - **ButtonGroup** - Group of buttons
202
+ - **ActionDropdown** - Dropdown menu for actions
203
+ - **Dropdown** - General dropdown component
204
+ - **Pagination** - Pagination component
205
+ - **InputSearch** - Search input component
206
+
207
+ ### Other Components
208
+
209
+ - **ThemeToggle** - Dark/light theme toggle
210
+ - **Collapse** - Collapsible content component
68
211
 
69
- - `variant`: 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'danger'
70
- - `size`: 'sm' | 'md' | 'lg'
71
- - `disabled`: boolean
72
- - `loading`: boolean
73
- - `type`: 'button' | 'submit' | 'reset'
74
- - `tag`: string
212
+ ## Theme System
75
213
 
76
- ### TextField
214
+ ### Setting Brand Theme
215
+
216
+ The design system supports multiple brand themes. You can switch between them programmatically:
217
+
218
+ ```js
219
+ import { setBrandTheme } from '@idds/vue';
220
+
221
+ // Set brand theme
222
+ setBrandTheme('bgn'); // or 'inagov', 'inaku', 'inapas', 'bkn', 'lan', 'panrb'
223
+
224
+ // Use default theme
225
+ setBrandTheme('default');
226
+
227
+ // Remove brand theme (use default)
228
+ setBrandTheme(null);
229
+ ```
230
+
231
+ ### Available Brand Themes
232
+
233
+ - `'default'` - Default INA Digital theme
234
+ - `'inagov'` - INAGov brand theme
235
+ - `'inaku'` - INAKu brand theme
236
+ - `'inapas'` - INAPas brand theme
237
+ - `'bgn'` - BGN brand theme
238
+ - `'bkn'` - BKN brand theme
239
+ - `'lan'` - LAN brand theme
240
+ - `'panrb'` - panrb brand theme
241
+
242
+ ### Custom Theme
243
+
244
+ You can also set a custom theme:
245
+
246
+ ```js
247
+ import { setCustomTheme } from '@idds/vue';
248
+
249
+ setCustomTheme({
250
+ name: 'custom',
251
+ colors: {
252
+ primary500: '#0968f6',
253
+ primary600: '#0754c4',
254
+ // ... other color tokens
255
+ },
256
+ });
257
+ ```
258
+
259
+ ### Theme Utilities
260
+
261
+ ```js
262
+ import {
263
+ getCurrentTheme,
264
+ getAvailableBrands,
265
+ resetTheme,
266
+ isValidBrand,
267
+ } from '@idds/vue';
268
+
269
+ // Get current active theme
270
+ const currentTheme = getCurrentTheme();
271
+
272
+ // Get available brand names
273
+ const brands = getAvailableBrands();
274
+
275
+ // Reset to default theme
276
+ resetTheme();
277
+
278
+ // Validate brand name
279
+ if (isValidBrand('bgn')) {
280
+ setBrandTheme('bgn');
281
+ }
282
+ ```
283
+
284
+ ## Composables
285
+
286
+ ### Toast Notifications
77
287
 
78
288
  ```vue
79
- <TextField
80
- v-model="value"
81
- label="Email"
82
- placeholder="Enter your email"
83
- type="email"
84
- size="md"
85
- :disabled="false"
86
- :readonly="false"
87
- :required="true"
88
- :show-clear-button="true"
89
- @input="handleInput"
90
- />
289
+ <template>
290
+ <ToastProvider>
291
+ <App />
292
+ </ToastProvider>
293
+ </template>
294
+
295
+ <script setup>
296
+ import { ToastProvider, useToast } from '@idds/vue';
297
+
298
+ const toast = useToast();
299
+
300
+ const showSuccess = () => {
301
+ toast.success('Operation completed successfully!');
302
+ };
303
+
304
+ const showError = () => {
305
+ toast.error('An error occurred');
306
+ };
307
+ </script>
91
308
  ```
92
309
 
93
- **Props:**
94
-
95
- - `modelValue`: string
96
- - `label`: string
97
- - `placeholder`: string
98
- - `type`: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url'
99
- - `size`: 'sm' | 'md' | 'lg'
100
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
101
- - `statusMessage`: string
102
- - `disabled`: boolean
103
- - `readonly`: boolean
104
- - `required`: boolean
105
- - `maxLength`: number
106
- - `showCharCount`: boolean
107
- - `showClearButton`: boolean
108
- - `prefixIcon`: Component
109
- - `debounce`: number
110
-
111
- ### PasswordInput
310
+ ### Confirmation Dialog
112
311
 
113
312
  ```vue
114
- <PasswordInput
115
- v-model="password"
116
- label="Password"
117
- placeholder="Enter your password"
118
- size="md"
119
- :show-char-count="true"
120
- :max-length="20"
121
- />
313
+ <template>
314
+ <ConfirmationProvider>
315
+ <App />
316
+ </ConfirmationProvider>
317
+ </template>
318
+
319
+ <script setup>
320
+ import { ConfirmationProvider, useConfirmation } from '@idds/vue';
321
+
322
+ const confirm = useConfirmation();
323
+
324
+ const handleDelete = async () => {
325
+ const result = await confirm({
326
+ title: 'Delete Item',
327
+ message: 'Are you sure you want to delete this item?',
328
+ });
329
+
330
+ if (result) {
331
+ // User confirmed
332
+ }
333
+ };
334
+ </script>
122
335
  ```
123
336
 
124
- **Props:**
337
+ ## Component Examples
338
+
339
+ ### TextField
340
+
341
+ ```vue
342
+ <template>
343
+ <TextField
344
+ v-model="email"
345
+ label="Email"
346
+ placeholder="Enter your email"
347
+ type="email"
348
+ :required="true"
349
+ :show-clear-button="true"
350
+ :max-length="100"
351
+ :show-char-count="true"
352
+ @input="handleInput"
353
+ />
354
+ </template>
355
+
356
+ <script setup>
357
+ import { ref } from 'vue';
358
+ import { TextField } from '@idds/vue';
359
+
360
+ const email = ref('');
361
+ const handleInput = (event) => {
362
+ console.log('Input event:', event);
363
+ };
364
+ </script>
365
+ ```
366
+
367
+ ### Button
368
+
369
+ ```vue
370
+ <template>
371
+ <Button variant="primary" size="md" @click="handleClick"> Submit </Button>
372
+ </template>
373
+
374
+ <script setup>
375
+ import { Button } from '@idds/vue';
125
376
 
126
- - `modelValue`: string
127
- - `label`: string
128
- - `placeholder`: string
129
- - `size`: 'sm' | 'md' | 'lg'
130
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
131
- - `statusMessage`: string
132
- - `disabled`: boolean
133
- - `readonly`: boolean
134
- - `required`: boolean
135
- - `maxLength`: number
136
- - `showCharCount`: boolean
377
+ const handleClick = () => {
378
+ console.log('Button clicked');
379
+ };
380
+ </script>
381
+ ```
137
382
 
138
383
  ### SelectDropdown
139
384
 
140
385
  ```vue
141
- <SelectDropdown
142
- v-model="selected"
143
- :options="options"
144
- label="Select Option"
145
- placeholder="Choose an option"
146
- size="md"
147
- :multiple="false"
148
- indicator="check"
149
- />
386
+ <template>
387
+ <SelectDropdown
388
+ v-model="selected"
389
+ :options="options"
390
+ label="Select Option"
391
+ placeholder="Choose an option"
392
+ :searchable="true"
393
+ :clearable="true"
394
+ />
395
+ </template>
396
+
397
+ <script setup>
398
+ import { ref } from 'vue';
399
+ import { SelectDropdown } from '@idds/vue';
400
+
401
+ const selected = ref(null);
402
+ const options = [
403
+ { value: '1', label: 'Option 1' },
404
+ { value: '2', label: 'Option 2' },
405
+ ];
406
+ </script>
150
407
  ```
151
408
 
152
- **Props:**
409
+ ### DatePicker
410
+
411
+ ```vue
412
+ <template>
413
+ <DatePicker
414
+ v-model="date"
415
+ mode="single"
416
+ label="Select Date"
417
+ placeholder="Choose a date"
418
+ date-format="DD/MM/YYYY"
419
+ :show-icon="true"
420
+ :show-clear-button="true"
421
+ />
422
+ </template>
423
+
424
+ <script setup>
425
+ import { ref } from 'vue';
426
+ import { DatePicker } from '@idds/vue';
153
427
 
154
- - `modelValue`: any | any[]
155
- - `options`: SelectOption[]
156
- - `label`: string
157
- - `placeholder`: string
158
- - `size`: 'sm' | 'md' | 'lg'
159
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
160
- - `statusMessage`: string
161
- - `disabled`: boolean
162
- - `required`: boolean
163
- - `multiple`: boolean
164
- - `indicator`: 'check' | 'radio'
165
- - `searchable`: boolean
166
- - `clearable`: boolean
428
+ const date = ref('');
429
+ </script>
430
+ ```
167
431
 
168
- ### TimePicker
432
+ ### Table
169
433
 
170
434
  ```vue
171
- <TimePicker v-model="time" label="Time" placeholder="Select time" size="md" />
435
+ <template>
436
+ <Table :columns="columns" :data="data" />
437
+ </template>
438
+
439
+ <script setup>
440
+ import { Table } from '@idds/vue';
441
+
442
+ const columns = [
443
+ { key: 'name', label: 'Name' },
444
+ { key: 'email', label: 'Email' },
445
+ ];
446
+
447
+ const data = [
448
+ { id: 1, name: 'John', email: 'john@example.com' },
449
+ { id: 2, name: 'Jane', email: 'jane@example.com' },
450
+ ];
451
+ </script>
172
452
  ```
173
453
 
174
- **Props:**
454
+ ## Utilities
175
455
 
176
- - `modelValue`: string
177
- - `label`: string
178
- - `placeholder`: string
179
- - `size`: 'sm' | 'md' | 'lg'
180
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
181
- - `statusMessage`: string
182
- - `disabled`: boolean
183
- - `readonly`: boolean
184
- - `required`: boolean
456
+ ### Security Utilities
185
457
 
186
- ### YearPicker
458
+ ```js
459
+ import {
460
+ sanitizeInput,
461
+ validateInput,
462
+ encodeHtmlEntities,
463
+ decodeHtmlEntities,
464
+ } from '@idds/vue';
187
465
 
188
- ```vue
189
- <YearPicker
190
- v-model="year"
191
- label="Year"
192
- placeholder="Select year"
193
- size="md"
194
- :min-year="2000"
195
- :max-year="2030"
196
- :show-icon="true"
197
- :show-clear-button="true"
198
- />
466
+ // Sanitize user input
467
+ const sanitized = sanitizeInput(userInput);
468
+
469
+ // Validate input for XSS
470
+ const validation = validateInput(userInput);
471
+ if (!validation.isValid) {
472
+ console.warn('Security threat detected:', validation.threats);
473
+ }
199
474
  ```
200
475
 
201
- **Props:**
476
+ ### File Validation
202
477
 
203
- - `modelValue`: number
204
- - `label`: string
205
- - `placeholder`: string
206
- - `size`: 'sm' | 'md' | 'lg'
207
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
208
- - `statusMessage`: string
209
- - `disabled`: boolean
210
- - `readonly`: boolean
211
- - `required`: boolean
212
- - `minYear`: number
213
- - `maxYear`: number
214
- - `showIcon`: boolean
215
- - `showClearButton`: boolean
478
+ ```js
479
+ import { validateFile, validateMagicNumber, formatFileSize } from '@idds/vue';
216
480
 
217
- ### MonthPicker
481
+ // Validate file
482
+ const result = validateFile(file, {
483
+ allowedTypes: 'image/*',
484
+ maxSize: 5 * 1024 * 1024, // 5MB
485
+ });
218
486
 
219
- ```vue
220
- <MonthPicker
221
- v-model="month"
222
- label="Month"
223
- placeholder="Select month"
224
- size="md"
225
- :show-icon="true"
226
- :show-clear-button="true"
227
- />
487
+ // Validate magic number (file signature)
488
+ const magicResult = await validateMagicNumber(file, 'image/png');
489
+
490
+ // Format file size
491
+ const formatted = formatFileSize(1024 * 1024); // "1 MB"
228
492
  ```
229
493
 
230
- **Props:**
494
+ ## Styling
231
495
 
232
- - `modelValue`: number
233
- - `label`: string
234
- - `placeholder`: string
235
- - `size`: 'sm' | 'md' | 'lg'
236
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
237
- - `statusMessage`: string
238
- - `disabled`: boolean
239
- - `readonly`: boolean
240
- - `required`: boolean
241
- - `showIcon`: boolean
242
- - `showClearButton`: boolean
496
+ ### CSS Classes
243
497
 
244
- ### DatePicker
498
+ Components use BEM-like naming conventions:
245
499
 
246
- ```vue
247
- <DatePicker
248
- v-model="date"
249
- mode="single"
250
- label="Date"
251
- placeholder="date picker"
252
- size="md"
253
- :show-icon="true"
254
- :show-clear-button="true"
255
- date-format="DD/MM/YYYY"
256
- />
500
+ - `ina-button` - Base button class
501
+ - `ina-button--primary` - Primary variant
502
+ - `ina-button--disabled` - Disabled state
503
+ - `ina-text-field` - Text field component
504
+ - `ina-text-field__input` - Input element
505
+ - `ina-text-field__label` - Label element
506
+
507
+ ### Custom Styling
508
+
509
+ You can override component styles using CSS:
510
+
511
+ ```css
512
+ .ina-button--primary {
513
+ background-color: your-custom-color;
514
+ }
257
515
  ```
258
516
 
259
- **Props:**
260
-
261
- - `modelValue`: string | [string, string] | string[]
262
- - `mode`: 'single' | 'range' | 'multiple'
263
- - `label`: string
264
- - `placeholder`: string
265
- - `size`: 'sm' | 'md' | 'lg'
266
- - `status`: 'neutral' | 'success' | 'error' | 'warning'
267
- - `statusMessage`: string
268
- - `disabled`: boolean
269
- - `readonly`: boolean
270
- - `required`: boolean
271
- - `showIcon`: boolean
272
- - `showClearButton`: boolean
273
- - `dateFormat`: string
274
- - `minDate`: Date
275
- - `maxDate`: Date
276
- - `disabledDates`: Date[]
517
+ ### Using with Tailwind CSS (Optional)
277
518
 
278
- ## Theme System
519
+ If you want to use Tailwind CSS utility classes alongside the design system:
279
520
 
280
- ### Setting Brand Theme
521
+ 1. Install Tailwind CSS in your project
522
+ 2. Import color tokens:
281
523
 
282
- ```javascript
283
- import { setBrandTheme } from '@idds/vue';
524
+ ```js
525
+ // tailwind.config.js
526
+ import iddsColorTokens from '@idds/vue';
284
527
 
285
- // Set brand theme
286
- setBrandTheme('brandname');
528
+ export default {
529
+ theme: {
530
+ extend: {
531
+ colors: iddsColorTokens,
532
+ },
533
+ },
534
+ };
535
+ ```
287
536
 
288
- // Remove brand theme (use default)
289
- setBrandTheme(null);
537
+ 3. Use Tailwind classes for custom styling:
538
+
539
+ ```vue
540
+ <template>
541
+ <div class="bg-blue-500 text-white p-4">
542
+ <Button>Click me</Button>
543
+ </div>
544
+ </template>
545
+ ```
546
+
547
+ > **Note:** Tailwind CSS is **optional**. The design system works perfectly without it. Components are fully styled and functional using only the included CSS.
548
+
549
+ ## TypeScript Support
550
+
551
+ All components are fully typed with TypeScript:
552
+
553
+ ```vue
554
+ <script setup lang="ts">
555
+ import { TextField, type TextFieldProps } from '@idds/vue';
556
+
557
+ const props: TextFieldProps = {
558
+ modelValue: '',
559
+ label: 'Email',
560
+ };
561
+ </script>
290
562
  ```
291
563
 
292
564
  ## Development