@idds/vue 1.4.3 → 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 +469 -197
- package/dist/components/AccordionGroup.vue.d.ts.map +1 -1
- package/dist/components/FileUpload.vue.d.ts +2 -1
- package/dist/components/FileUpload.vue.d.ts.map +1 -1
- package/dist/components/SingleFileUpload.vue.d.ts.map +1 -1
- package/dist/components/TextArea.vue.d.ts +2 -1
- package/dist/components/TextArea.vue.d.ts.map +1 -1
- package/dist/index.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.es.js +158 -109
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
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
|
-
##
|
|
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
|
-
###
|
|
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="
|
|
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
|
-
|
|
72
|
+
### Import Color Tokens (Optional - for Tailwind CSS integration)
|
|
52
73
|
|
|
53
|
-
|
|
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
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
**
|
|
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
|
-
|
|
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
|
-
###
|
|
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
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
###
|
|
432
|
+
### Table
|
|
169
433
|
|
|
170
434
|
```vue
|
|
171
|
-
<
|
|
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
|
-
|
|
454
|
+
## Utilities
|
|
175
455
|
|
|
176
|
-
|
|
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
|
-
|
|
458
|
+
```js
|
|
459
|
+
import {
|
|
460
|
+
sanitizeInput,
|
|
461
|
+
validateInput,
|
|
462
|
+
encodeHtmlEntities,
|
|
463
|
+
decodeHtmlEntities,
|
|
464
|
+
} from '@idds/vue';
|
|
187
465
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
:
|
|
195
|
-
|
|
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
|
-
|
|
476
|
+
### File Validation
|
|
202
477
|
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
481
|
+
// Validate file
|
|
482
|
+
const result = validateFile(file, {
|
|
483
|
+
allowedTypes: 'image/*',
|
|
484
|
+
maxSize: 5 * 1024 * 1024, // 5MB
|
|
485
|
+
});
|
|
218
486
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
494
|
+
## Styling
|
|
231
495
|
|
|
232
|
-
|
|
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
|
-
|
|
498
|
+
Components use BEM-like naming conventions:
|
|
245
499
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
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
|
-
|
|
519
|
+
If you want to use Tailwind CSS utility classes alongside the design system:
|
|
279
520
|
|
|
280
|
-
|
|
521
|
+
1. Install Tailwind CSS in your project
|
|
522
|
+
2. Import color tokens:
|
|
281
523
|
|
|
282
|
-
```
|
|
283
|
-
|
|
524
|
+
```js
|
|
525
|
+
// tailwind.config.js
|
|
526
|
+
import iddsColorTokens from '@idds/vue';
|
|
284
527
|
|
|
285
|
-
|
|
286
|
-
|
|
528
|
+
export default {
|
|
529
|
+
theme: {
|
|
530
|
+
extend: {
|
|
531
|
+
colors: iddsColorTokens,
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
};
|
|
535
|
+
```
|
|
287
536
|
|
|
288
|
-
|
|
289
|
-
|
|
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
|