npm package: @risalabs_frontend_org/oasis-ui-kit
Description: RISA Oasis UI
Author: Deepak Prasad
Latest version: 0.89.0

# RISA Oasis UI Kit

A comprehensive React UI component library built with TypeScript and SCSS, featuring 35+ production-ready components for building modern web applications.

## Installation

```bash
npm install @risalabs_frontend_org/oasis-ui-kit
```

## ⚠️ Important Notes

- **DO NOT** increase build number in `package.json`
- **DO NOT** publish manually - the CI/CD pipeline handles publishing

---

## Development

### Prerequisites

- Node.js (v18 or higher recommended)
- npm

### Getting Started

```bash
# Install dependencies
npm install

# Start Storybook development server
npm run storybook
```

Open [http://localhost:6006](http://localhost:6006) to view the component library in your browser.

### Available Scripts

| Command | Description |
|---------|-------------|
| `npm run storybook` | Start Storybook dev server on port 6006 |
| `npm run build-storybook` | Build static Storybook site |
| `npm run build` | Build the library for production |
| `npm run test` | Run unit tests with Jest |
| `npm run chromatic` | Run visual regression tests with Chromatic |

---

## Components

### Form Controls

#### `Button`
A versatile button component with multiple variants and sizes.

```tsx
import { Button } from '@risalabs_frontend_org/oasis-ui-kit';

<Button
  buttonType="primary" // "primary" | "secondary" | "tertiary" | "danger"
  size="medium"        // "small" | "medium" | "large"
  disabled={false}
  onClick={() => {}}
>
  Click Me
</Button>
```

#### `ButtonWithDropdown`
A split button with dropdown menu functionality.

```tsx
import { ButtonWithDropdown } from '@risalabs_frontend_org/oasis-ui-kit';

<ButtonWithDropdown
  buttonType="primary"
  size="medium"
  disabled={false}
  menuData={[
    { label: 'Option 1', onClick: (item) => console.log(item) },
    { label: 'Option 2', onClick: (item) => console.log(item), color: '#ff0000' }
  ]}
  alwaysOpenDropdown={false} // If false, content and chevron act independently
  onButtonClick={() => {}}   // Called when content area is clicked (split mode)
>
  Actions
</ButtonWithDropdown>
```

#### `TextInput`
A flexible text input with label, validation, formatting, and password visibility toggle.

```tsx
import { TextInput } from '@risalabs_frontend_org/oasis-ui-kit';

<TextInput
  id="username"
  label="Username"
  placeholder="Enter username"
  required={true}
  type="text"              // "text" | "number"
  textHidden={false}       // Enable password mode
  error="Invalid username"
  onChange={(data) => console.log(data)}
  onBlur={(data) => console.log(data)}
  formatInput={(value) => value.toUpperCase()} // Custom formatting
/>
```

#### `Select`
A custom dropdown select component with search and validation.

```tsx
import { Select } from '@risalabs_frontend_org/oasis-ui-kit';

<Select
  id="country"
  label="Country"
  placeholder="Select a country"
  options={[
    { value: 'us', label: 'United States' },
    { value: 'uk', label: 'United Kingdom' }
  ]}
  required={true}
  onOptionChange={(data) => console.log(data)}
/>
```

#### `CheckBox`
A styled checkbox component.

```tsx
import { CheckBox } from '@risalabs_frontend_org/oasis-ui-kit';

<CheckBox
  id="terms"
  label="I agree to the terms"
  defaultValue={false}
  isDisabled={false}
  onCheckBoxValueChange={(data) => console.log(data)}
/>
```

#### `Toggle` & `ToggleSwitch`
Toggle switch components for boolean settings.

```tsx
import { Toggle, ToggleSwitch } from '@risalabs_frontend_org/oasis-ui-kit';

// Toggle with label
<Toggle
  id="notifications"
  label="Enable Notifications"
  defaultValue={true}
  onChange={(data) => console.log(data)}
/>

// Standalone toggle switch
<ToggleSwitch
  id="darkMode"
  defaultChecked={false}
  onChangeEmit={(data) => console.log(data)}
/>
```

#### `RadioButton`
A radio button group supporting vertical/horizontal layout with customizable selected color.

```tsx
import { RadioButton } from '@risalabs_frontend_org/oasis-ui-kit';

<RadioButton
  name="plan"
  options={[
    { label: 'Basic', value: 'basic' },
    { label: 'Premium', value: 'premium' },
    { label: 'Enterprise', value: 'enterprise', disabled: true }
  ]}
  value="basic"
  onChange={(value) => console.log(value)}
  direction="vertical"    // "vertical" | "horizontal"
  gap="0.75rem"           // Custom gap between options
  selectedColor="#1e69da"  // Custom selection color
/>
```

#### `SelectInput`
A lightweight select component using the native `<select>` element with custom styling.

```tsx
import { SelectInput } from '@risalabs_frontend_org/oasis-ui-kit';

<SelectInput
  label="Organization"
  options={[
    { label: 'Acme Corp', value: 'acme' },
    { label: 'Globex Inc', value: 'globex' }
  ]}
  defaultValue="acme"
  placeholder="Select..."
  onChange={(value, option) => console.log(value, option)}
  focusBorderWidth="2px"
/>
```

#### `CustomDropdown`
A fully custom dropdown with viewport-aware positioning, portal support, validation, and keyboard navigation.

```tsx
import { CustomDropdown } from '@risalabs_frontend_org/oasis-ui-kit';

<CustomDropdown
  label="Organization"
  options={[
    { label: 'Acme Corp', value: 'acme' },
    { label: 'Globex Inc', value: 'globex' }
  ]}
  defaultValue="acme"
  placeholder="Select..."
  onChange={(value, option) => console.log(value, option)}
  required={true}
  error="This field is required" // Shows red border and error message
  hint="Choose your organization"
  shouldUsePortal={false}        // Render via React portal to escape overflow:hidden
  focusBorderWidth="1px"
/>
```

#### `ActionInput`
A text input with an adjacent action button and dirty-state detection. The icon color changes when the value differs from the initial value.

```tsx
import { ActionInput } from '@risalabs_frontend_org/oasis-ui-kit';

<ActionInput
  value="BMKYUTS8"
  onChange={(value) => console.log(value)}
  onAction={(value) => console.log('Submitted:', value)}
  placeholder="Enter code..."
  readOnly={false}
  disabled={false}
  iconColor="#6B6B6B"   // Default icon color
  iconSize={16}         // Icon size in px
  height="2rem"         // Container height
  dirtyColor="#0056D6"  // Icon color when value is modified
/>
```

### Date & Time Components

#### `DateInput`
A date input with custom format support using moment.js.

```tsx
import { DateInput } from '@risalabs_frontend_org/oasis-ui-kit';

<DateInput
  id="birthdate"
  label="Date of Birth"
  placeholder="Select date"
  format="DD/MM/YYYY"    // Custom display format
  required={true}
  onChange={(data) => console.log(data)}
  onBlur={(data) => console.log(data)}
/>
```

#### `DatePicker`
A calendar-based date picker component.

```tsx
import { DatePicker } from '@risalabs_frontend_org/oasis-ui-kit';

<DatePicker
  initialDate={new Date()}
  onDateChange={(date) => console.log(date)}
/>
```

#### `DateRangeCalendar`
A calendar for selecting date ranges with month/year selectors.

```tsx
import { DateRangeCalendar } from '@risalabs_frontend_org/oasis-ui-kit';

<DateRangeCalendar
  initialStartDate={new Date()}
  initialEndDate={new Date()}
  onDateRangeChange={(startDate, endDate) => console.log(startDate, endDate)}
  resetSelection={false}
/>
```

#### `TimeDue`
Component for displaying time-related information.

```tsx
import { TimeDue } from '@risalabs_frontend_org/oasis-ui-kit';

<TimeDue {...props} />
```

### File Handling

#### `FileUpload`
A file upload component with preview and delete functionality.

```tsx
import { FileUpload } from '@risalabs_frontend_org/oasis-ui-kit';

<FileUpload
  id="documents"
  deleteUploadedFile={() => {}}
/>
```

#### `AttachmentCard`
Display uploaded files with upload progress indicator.

```tsx
import { AttachmentCard } from '@risalabs_frontend_org/oasis-ui-kit';

<AttachmentCard
  title="document.pdf"
  isUploading={true}
  uploadProgress={65}
  onDelete={() => {}}
/>
```

#### `UploadedFileBanner`
Banner display for uploaded files.

```tsx
import { UploadedFileBanner } from '@risalabs_frontend_org/oasis-ui-kit';

<UploadedFileBanner {...props} />
```

### Navigation

#### `SideNavigation`
A vertical side navigation with tab-style content switching.

```tsx
import { SideNavigation } from '@risalabs_frontend_org/oasis-ui-kit';

<SideNavigation
  sideTabContent={[
    { id: 'profile', label: 'Profile', sideNavContent: ProfileComponent },
    { id: 'settings', label: 'Settings', sideNavContent: SettingsComponent }
  ]}
/>
```

#### `HorizontalNavigationTab`
A horizontal tab navigation bar with active indicator, custom colors, and keyboard navigation.

```tsx
import { HorizontalNavigationTab } from '@risalabs_frontend_org/oasis-ui-kit';

<HorizontalNavigationTab
  tabs={[
    { label: 'Overview', value: 'overview' },
    { label: 'Details', value: 'details' },
    { label: 'History', value: 'history', disabled: true }
  ]}
  value="overview"
  onChange={(value) => console.log(value)}
  activeColor="#1E69DA"          // Active tab text & border color
  backgroundColor="#F5F5F5"     // Tab background
  activeBackgroundColor="#FFF"  // Active tab background
  rounded={true}                // Rounded top corners
/>
```

#### `TabContainer` & `SingleTab`
Horizontal tab navigation components.

```tsx
import { TabContainer, SingleTab } from '@risalabs_frontend_org/oasis-ui-kit';

<TabContainer {...props} />
```

#### `Pagination`
A pagination control with prev/next buttons.

```tsx
import { Pagination } from '@risalabs_frontend_org/oasis-ui-kit';

<Pagination
  currentPage={1}
  totalPages={10}
  onPrevious={() => {}}
  onNext={() => {}}
  disabled={false}
/>
```

#### `Stepper`
A vertical stepper for multi-step processes.

```tsx
import { Stepper } from '@risalabs_frontend_org/oasis-ui-kit';

<Stepper
  id={0}
  currentActiveIndex={1}
  label="Step 1: Personal Info"
  stepperText="1"
  showDashedLine={true}
/>
```

### Feedback & Overlays

#### `Modal`
A customizable modal dialog with header, body, and footer.

```tsx
import { Modal, openModal, closeModal } from '@risalabs_frontend_org/oasis-ui-kit';

<Modal
  dialogId="myModal"
  title="Confirm Action"
  saveButtonText="Confirm"
  cancelText="Cancel"
  onSave={() => {}}
  onCancel={() => {}}
  onClose={() => {}}
  showSingleButton={false}
  hideFooter={false}
  disableSave={false}
>
  <p>Are you sure you want to continue?</p>
</Modal>

// Control modal visibility
openModal('myModal');
closeModal('myModal');
```

#### `Toast`
Notification toast for success/error messages. Uses a simple imperative API.

```tsx
import { ToastContainer, toast } from '@risalabs_frontend_org/oasis-ui-kit';

// 1. Add ToastContainer once in your app root (e.g., App.tsx)
function App() {
  return (
    <>
      <ToastContainer />
      {/* rest of your app */}
    </>
  );
}

// 2. Call toast.success or toast.error anywhere in your app
toast.success("Changes saved!");
toast.error("Something went wrong");

// With optional header
toast.success("Your file has been uploaded", "Upload Complete");

// With custom duration (default: 3000ms)
toast.error("Connection failed", "Network Error", 5000);
```

**API:**
| Method | Parameters | Description |
|--------|------------|-------------|
| `toast.success(message, header?, duration?)` | `message: string`, `header?: string`, `duration?: number` | Show success toast |
| `toast.error(message, header?, duration?)` | `message: string`, `header?: string`, `duration?: number` | Show error toast |

#### `InfoIconWithTooltip`
An info icon with popover tooltip.

```tsx
import { InfoIconWithTooltip } from '@risalabs_frontend_org/oasis-ui-kit';

<InfoIconWithTooltip
  content={<p>This is helpful information</p>}
  directionToDisplay="bottom" // "left" | "right" | "top" | "bottom"
  maxWidth={20}  // in rem
  maxHeight={10} // in rem
/>
```

### Layout & Display

#### `HeaderCard`
A card component for headers/titles.

```tsx
import { HeaderCard } from '@risalabs_frontend_org/oasis-ui-kit';

<HeaderCard {...props} />
```

#### `Footer`
A footer component.

```tsx
import { Footer } from '@risalabs_frontend_org/oasis-ui-kit';

<Footer {...props} />
```

#### `NotificationCard`
A card for displaying notifications.

```tsx
import { NotificationCard } from '@risalabs_frontend_org/oasis-ui-kit';

<NotificationCard {...props} />
```

#### `StatusText`
Display status text with styling.

```tsx
import { StatusText } from '@risalabs_frontend_org/oasis-ui-kit';

<StatusText {...props} />
```

#### `Tags`
A styled tag component with optional dropdown selection. Options are displayed as styled tags. Supports portal rendering for overflow-hidden containers.

```tsx
import { Tags } from '@risalabs_frontend_org/oasis-ui-kit';

<Tags
  label="Financial"
  backgroundColor="#FFFCD6"
  textColor="#665D00"
  showBorder={false}
  shouldUsePortal={false}
  options={[
    { label: 'Financial', value: 'financial', backgroundColor: '#FFFCD6', textColor: '#665D00' },
    { label: 'Medical', value: 'medical', backgroundColor: '#eefcf4', textColor: '#007028' },
    { label: 'Clinical', value: 'clinical', backgroundColor: '#eaf2ff', textColor: '#002152' }
  ]}
  onSelect={(option) => console.log(option)}
/>
```

#### `Badge`
A styled badge with optional left/right icons, tooltip, and customizable colors.

```tsx
import { Badge } from '@risalabs_frontend_org/oasis-ui-kit';

<Badge
  text="Active"
  backgroundColor="#eefcf4"
  textColor="#007028"
  size="medium"         // "small" | "medium" | "large"
  maxWidth="200px"
  borderColor="#007028"
  showTooltip={true}
  leftIcon={<SomeIcon />}
  onLeftIconClick={(e) => {}}
/>
```

#### `BadgeGroup`
Displays a collection of badges with overflow handling, showing a "+N more" indicator for hidden items.

```tsx
import { BadgeGroup } from '@risalabs_frontend_org/oasis-ui-kit';

<BadgeGroup
  badges={[
    { text: 'React', backgroundColor: '#e0f2fe', textColor: '#0369a1' },
    { text: 'TypeScript', backgroundColor: '#ede9fe', textColor: '#6d28d9' },
    { text: 'SCSS', backgroundColor: '#fce7f3', textColor: '#be185d' }
  ]}
  maxVisible={2}
  size="medium"
  showBadgeTooltips={true}
  showOverflowTooltip={true}
  onOverflowClick={(hiddenBadges) => console.log(hiddenBadges)}
/>
```

#### `RuleCard`
A card for displaying text rules with optional numbered index and edit/delete action buttons.

```tsx
import { RuleCard } from '@risalabs_frontend_org/oasis-ui-kit';

<RuleCard
  content="Patient must have a valid prescription before dispensing."
  index={1}                      // Optional numbered badge
  onEdit={() => console.log('edit')}
  onDelete={() => console.log('delete')}
  editIconColor="#0056D6"
  deleteIconColor="#F50400"
  iconSize={12}
  contentClassName="custom-text"
/>
```

#### `MultiLineTextWithCopy`
Displays primary and secondary text with a copy-to-clipboard button for the secondary value.

```tsx
import { MultiLineTextWithCopy } from '@risalabs_frontend_org/oasis-ui-kit';

<MultiLineTextWithCopy
  primaryText="John Doe"
  secondaryText="NPI-1234567890"
  copyValue="1234567890"      // Optional: overrides secondaryText for clipboard
  onCopy={(value) => console.log('Copied:', value)}
  copyIconColor="#0056D6"
  copyIconSize={16}
  shouldTruncate={false}      // Truncate primary text with ellipsis
/>
```

#### `ThreeDotButton`
A three-dot (kebab) menu button with a dropdown options list and viewport-aware positioning.

```tsx
import { ThreeDotButton } from '@risalabs_frontend_org/oasis-ui-kit';

<ThreeDotButton
  options={[
    { id: 'edit', text: 'Edit' },
    { id: 'delete', text: 'Delete' },
    { id: 'archive', text: 'Archive' }
  ]}
  onOptionClick={(optionId) => console.log(optionId)}
/>
```

#### `PopOverWithClickableOptions`
A popover menu displaying a list of clickable options with optional icons.

```tsx
import { PopOverWithClickableOptions } from '@risalabs_frontend_org/oasis-ui-kit';

<PopOverWithClickableOptions
  options={[
    { id: 'view', text: 'View Details', icon: <ViewIcon /> },
    { id: 'download', text: 'Download' }
  ]}
  onClick={(id) => console.log(id)}
/>
```

#### `ProfileButton`
A user profile button with avatar and dropdown indicator.

```tsx
import { ProfileButton } from '@risalabs_frontend_org/oasis-ui-kit';

<ProfileButton
  name="John Doe"
  initials="JD"
  imageUrl="/avatar.jpg"        // Optional: use image instead of initials
  avatarBackgroundColor="#007028"
  onClick={() => {}}
/>
```

### Loaders

#### `SpinningLoader`
A simple spinning loading indicator.

```tsx
import { SpinningLoader } from '@risalabs_frontend_org/oasis-ui-kit';

<SpinningLoader />
```

#### `ProgressLoaderWithText`
A loader with text description.

```tsx
import { ProgressLoaderWithText } from '@risalabs_frontend_org/oasis-ui-kit';

<ProgressLoaderWithText {...props} />
```

### Search

#### `SearchComponent`
A search input with button.

```tsx
import { SearchComponent } from '@risalabs_frontend_org/oasis-ui-kit';

<SearchComponent
  placeholder="Search..."
  onSearch={(query) => console.log(query)}
/>
```

---

## Types & Utilities

The library exports a comprehensive color palette and types:

```tsx
import { Colors, productWidgetColors, WidgetType } from '@risalabs_frontend_org/oasis-ui-kit';

// Color palette includes:
// - Primary Green (primaryGreen1-11)
// - Primary Gray (primaryGray1-16)
// - Secondary Purple, Yellow, Orange
// - Tertiary Red, Magenta, Cyan, Lime, Blue
// - Grayscale Black
```

---

## Tech Stack

- **React** 18.x
- **TypeScript** 5.x
- **SCSS** for styling
- **Storybook** 7.x for component documentation
- **Jest** + React Testing Library for testing
- **Webpack** for bundling
- **Moment.js** & **date-fns** for date handling
- **Ant Design Icons** for icons
- **React Feather** for additional icons

---

## Project Structure

```
oasis-ui/
├── src/
│   ├── components/       # All UI components
│   ├── shared/           # Shared styles, types, and utilities
│   ├── stories/          # Additional Storybook stories
│   └── SVG/              # SVG icon components
├── stories/              # Main Storybook stories
├── public/
│   └── icons/            # Static SVG icons
├── index.ts              # Main entry point (exports)
└── index.d.ts            # TypeScript declarations
```

---

## Contributing

1. Create a feature branch from `main`
2. Make your changes
3. Add/update Storybook stories for your components
4. Add/update unit tests
5. Submit a pull request

---

## License

Proprietary - RISA Labs