npm package: @idds/vue
Description: Vue 3 UI component library for INA Digital Design System
Author: INA Digital
Latest version: 1.6.11

# @idds/vue

Vue 3 UI component library for INA Digital Design System.

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.

## Installation

```bash
npm install @idds/vue
```

## Peer Dependencies

```bash
npm install vue@^3.4.0
```

## Quick Start

### 1. Import CSS

Import the styles in your application entry point:

```js
// src/main.js or src/main.ts
import '@idds/vue/index.css';
```

### 2. Import and Use Components

```vue
<template>
  <div>
    <Button variant="primary" size="md" @click="handleClick"> Click me </Button>
    <TextField v-model="value" label="Email" placeholder="Enter your email" />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { Button, TextField } from '@idds/vue';

const value = ref('');
const handleClick = () => {
  console.log('Button clicked');
};
</script>
```

## Usage

### Import Individual Components

```vue
<script setup>
import { Button, TextField, SelectDropdown, Modal } from '@idds/vue';
</script>
```

### Import All Components

```vue
<script setup>
import InaDigitalUI from '@idds/vue';

// Use components
const { Button, TextField, SelectDropdown } = InaDigitalUI;
</script>
```

### Import Color Tokens (Optional - for Tailwind CSS integration)

If you want to use INA Digital color tokens with Tailwind CSS in your project:

#### Tailwind CSS v3

For Tailwind CSS v3, import the TypeScript token files:

```js
// tailwind.config.js
import iddsColorTokens from '@idds/vue';
import bgnColorTokens from '@idds/vue'; // Brand-specific tokens

export default {
  theme: {
    extend: {
      colors: {
        ...iddsColorTokens,
        ...bgnColorTokens,
      },
    },
  },
};
```

#### Tailwind CSS v4

For Tailwind CSS v4, import the CSS theme files directly in your main CSS file:

```css
/* src/index.css or your main CSS file */

/* Tailwind CSS v4 */
@import 'tailwindcss';

/* INA Digital color tokens */
@import '@idds/styles/tailwind/css/idds.css';
@import '@idds/styles/tailwind/css/bgn.css'; /* Optional: brand theme */
```

Or use minified versions for production:

```css
@import 'tailwindcss';
@import '@idds/styles/tailwind/css/idds.min.css';
@import '@idds/styles/tailwind/css/bgn.min.css';
```

Then you can use Tailwind utility classes with INA Digital colors:

```vue
<template>
  <div class="bg-blue-500 text-white p-4">
    <p class="text-guide-500">This text uses guide-500 color</p>
    <p class="text-neutral-500">This text uses neutral-500 color</p>
  </div>
</template>
```

**Available brand theme files:**

- `@idds/styles/tailwind/css/idds.css` - Default theme
- `@idds/styles/tailwind/css/inagov.css` - INAGov brand
- `@idds/styles/tailwind/css/inaku.css` - INAKu brand
- `@idds/styles/tailwind/css/inapas.css` - INAPas brand
- `@idds/styles/tailwind/css/bgn.css` - BGN brand
- `@idds/styles/tailwind/css/bkn.css` - BKN brand
- `@idds/styles/tailwind/css/lan.css` - LAN brand
- `@idds/styles/tailwind/css/panrb.css` - panrb brand

## Available Components

### Form Components

- **TextField** - Text input with validation, clear button, and character count
- **TextArea** - Multi-line text input with autosize
- **PasswordInput** - Password input with show/hide toggle
- **SelectDropdown** - Dropdown select with search and multi-select support
- **Checkbox** - Checkbox input
- **RadioInput** - Radio button input
- **DatePicker** - Date picker with single, range, and multiple modes
- **TimePicker** - Time picker
- **YearPicker** - Year picker
- **MonthPicker** - Month picker
- **PhoneInput** - Phone number input with country selector
- **OneTimePassword** - OTP input component
- **FileUpload** - File upload with drag & drop and validation
- **SingleFileUpload** - Single file upload component
- **Toggle** - Toggle switch component

### Layout Components

- **Card** - Card container component
- **Accordion** - Collapsible accordion component
- **AccordionCard** - Accordion with card styling
- **AccordionGroup** - Group of accordions
- **Divider** - Horizontal or vertical divider
- **Stepper** - Step indicator component
- **Breadcrumb** - Breadcrumb navigation
- **TabHorizontal** - Horizontal tabs
- **TabVertical** - Vertical tabs

### Feedback Components

- **Alert** - Alert message component
- **Toast** - Toast notification (use with ToastProvider)
- **ToastProvider** - Provider for toast notifications
- **Modal** - Modal dialog component
- **Drawer** - Side drawer component
- **BottomSheet** - Bottom sheet component
- **Tooltip** - Tooltip component
- **Skeleton** - Loading skeleton component
- **Spinner** - Loading spinner component
- **ProgressBar** - Progress bar component
- **LinearProgressIndicator** - Linear progress indicator
- **TableProgressBar** - Progress bar for tables

### Data Display Components

- **Table** - Advanced table with sorting, pagination, and editing
- **FieldInputTable** - Table with inline input fields
- **MultipleChoiceGrid** - Grid for multiple choice questions
- **Avatar** - Avatar component
- **Badge** - Badge component
- **Chip** - Chip component

### Navigation Components

- **Button** - Button component with multiple variants
- **ButtonGroup** - Group of buttons
- **ActionDropdown** - Dropdown menu for actions
- **Dropdown** - General dropdown component
- **Pagination** - Pagination component
- **InputSearch** - Search input component

### Other Components

- **ThemeToggle** - Dark/light theme toggle
- **Collapse** - Collapsible content component

## Theme System

### Setting Brand Theme

The design system supports multiple brand themes. You can switch between them programmatically:

```js
import { setBrandTheme } from '@idds/vue';

// Set brand theme
setBrandTheme('bgn'); // or 'inagov', 'inaku', 'inapas', 'bkn', 'lan', 'panrb'

// Use default theme
setBrandTheme('default');

// Remove brand theme (use default)
setBrandTheme(null);
```

### Available Brand Themes

- `'default'` - Default INA Digital theme
- `'inagov'` - INAGov brand theme
- `'inaku'` - INAKu brand theme
- `'inapas'` - INAPas brand theme
- `'bgn'` - BGN brand theme
- `'bkn'` - BKN brand theme
- `'lan'` - LAN brand theme
- `'panrb'` - panrb brand theme

### Custom Theme

You can also set a custom theme:

```js
import { setCustomTheme } from '@idds/vue';

setCustomTheme({
  name: 'custom',
  colors: {
    primary500: '#0968f6',
    primary600: '#0754c4',
    // ... other color tokens
  },
});
```

### Theme Utilities

```js
import {
  getCurrentTheme,
  getAvailableBrands,
  resetTheme,
  isValidBrand,
} from '@idds/vue';

// Get current active theme
const currentTheme = getCurrentTheme();

// Get available brand names
const brands = getAvailableBrands();

// Reset to default theme
resetTheme();

// Validate brand name
if (isValidBrand('bgn')) {
  setBrandTheme('bgn');
}
```

## Composables

### Toast Notifications

```vue
<template>
  <ToastProvider>
    <App />
  </ToastProvider>
</template>

<script setup>
import { ToastProvider, useToast } from '@idds/vue';

const toast = useToast();

const showSuccess = () => {
  toast.success('Operation completed successfully!');
};

const showError = () => {
  toast.error('An error occurred');
};
</script>
```

### Confirmation Dialog

```vue
<template>
  <ConfirmationProvider>
    <App />
  </ConfirmationProvider>
</template>

<script setup>
import { ConfirmationProvider, useConfirmation } from '@idds/vue';

const confirm = useConfirmation();

const handleDelete = async () => {
  const result = await confirm({
    title: 'Delete Item',
    message: 'Are you sure you want to delete this item?',
  });

  if (result) {
    // User confirmed
  }
};
</script>
```

## Component Examples

### TextField

```vue
<template>
  <TextField
    v-model="email"
    label="Email"
    placeholder="Enter your email"
    type="email"
    :required="true"
    :show-clear-button="true"
    :max-length="100"
    :show-char-count="true"
    @input="handleInput"
  />
</template>

<script setup>
import { ref } from 'vue';
import { TextField } from '@idds/vue';

const email = ref('');
const handleInput = (event) => {
  console.log('Input event:', event);
};
</script>
```

### Button

```vue
<template>
  <Button variant="primary" size="md" @click="handleClick"> Submit </Button>
</template>

<script setup>
import { Button } from '@idds/vue';

const handleClick = () => {
  console.log('Button clicked');
};
</script>
```

### SelectDropdown

```vue
<template>
  <SelectDropdown
    v-model="selected"
    :options="options"
    label="Select Option"
    placeholder="Choose an option"
    :searchable="true"
    :clearable="true"
  />
</template>

<script setup>
import { ref } from 'vue';
import { SelectDropdown } from '@idds/vue';

const selected = ref(null);
const options = [
  { value: '1', label: 'Option 1' },
  { value: '2', label: 'Option 2' },
];
</script>
```

### DatePicker

```vue
<template>
  <DatePicker
    v-model="date"
    mode="single"
    label="Select Date"
    placeholder="Choose a date"
    date-format="DD/MM/YYYY"
    :show-icon="true"
    :show-clear-button="true"
  />
</template>

<script setup>
import { ref } from 'vue';
import { DatePicker } from '@idds/vue';

const date = ref('');
</script>
```

### Table

```vue
<template>
  <Table :columns="columns" :data="data" />
</template>

<script setup>
import { Table } from '@idds/vue';

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
];

const data = [
  { id: 1, name: 'John', email: 'john@example.com' },
  { id: 2, name: 'Jane', email: 'jane@example.com' },
];
</script>
```

## Utilities

### Security Utilities

```js
import {
  sanitizeInput,
  validateInput,
  encodeHtmlEntities,
  decodeHtmlEntities,
} from '@idds/vue';

// Sanitize user input
const sanitized = sanitizeInput(userInput);

// Validate input for XSS
const validation = validateInput(userInput);
if (!validation.isValid) {
  console.warn('Security threat detected:', validation.threats);
}
```

### File Validation

```js
import { validateFile, validateMagicNumber, formatFileSize } from '@idds/vue';

// Validate file
const result = validateFile(file, {
  allowedTypes: 'image/*',
  maxSize: 5 * 1024 * 1024, // 5MB
});

// Validate magic number (file signature)
const magicResult = await validateMagicNumber(file, 'image/png');

// Format file size
const formatted = formatFileSize(1024 * 1024); // "1 MB"
```

## Styling

### CSS Classes

Components use BEM-like naming conventions:

- `ina-button` - Base button class
- `ina-button--primary` - Primary variant
- `ina-button--disabled` - Disabled state
- `ina-text-field` - Text field component
- `ina-text-field__input` - Input element
- `ina-text-field__label` - Label element

### Custom Styling

You can override component styles using CSS:

```css
.ina-button--primary {
  background-color: your-custom-color;
}
```

### Using with Tailwind CSS (Optional)

If you want to use Tailwind CSS utility classes alongside the design system:

1. Install Tailwind CSS in your project
2. Import color tokens:

```js
// tailwind.config.js
import iddsColorTokens from '@idds/vue';

export default {
  theme: {
    extend: {
      colors: iddsColorTokens,
    },
  },
};
```

3. Use Tailwind classes for custom styling:

```vue
<template>
  <div class="bg-blue-500 text-white p-4">
    <Button>Click me</Button>
  </div>
</template>
```

> **Note:** Tailwind CSS is **optional**. The design system works perfectly without it. Components are fully styled and functional using only the included CSS.

## TypeScript Support

All components are fully typed with TypeScript:

```vue
<script setup lang="ts">
import { TextField, type TextFieldProps } from '@idds/vue';

const props: TextFieldProps = {
  modelValue: '',
  label: 'Email',
};
</script>
```

## Development

```bash
# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Type checking
npm run type-check

# Linting
npm run lint
```

## License

MIT