{"_id":"@caava-ai/ui","name":"@caava-ai/ui","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"@caava-ai/ui","version":"0.1.1","description":"UI components for Akili AI SDK","main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"vite build","dev":"vite build --watch","test":"vitest","lint":"eslint \"src/**/*.js\"","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"dependencies":{"@caava-ai/core":"^0.1.1","class-variance-authority":"^0.7.0","clsx":"^2.0.0","tailwind-merge":"^2.0.0"},"devDependencies":{"@types/react":"^18.2.0","@types/node":"^20.10.0","typescript":"^5.3.0","vite":"^5.0.0","vitest":"^1.0.0","eslint":"^8.55.0","tailwindcss":"^3.4.0","autoprefixer":"^10.4.0","postcss":"^8.4.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint-plugin-react":"^7.33.0","eslint-plugin-react-hooks":"^4.6.0"},"peerDependencies":{"react":">=16.8.0","react-dom":">=16.8.0"},"publishConfig":{"access":"public"},"_id":"@caava-ai/ui@0.1.1","gitHead":"5248c307de17d26519d9c4ed0a425544eab4f58b","_nodeVersion":"22.8.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-GyRYuwawlTNDX7Ayikep2zEtyReriUY3HMZ/MQYkAaSD20ILwBQB3AhvODhnF0Lt/jfk3mys0c+wNxVaguTamg==","shasum":"32d4f8975923c5c9a00cb56de200055285cd4dad","tarball":"https://registry.npmjs.org/@caava-ai/ui/-/ui-0.1.1.tgz","fileCount":6,"unpackedSize":12564,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDirXjT5zSJY6bxtquAIaERciJrj3zqr82E9sstlnIShAIgPhDeeyrsFNoWLyA802ViRVIszWvXSi3i03wt2L7XtVo="}]},"_npmUser":{"name":"r1gan","email":"rigan.gor@turnkeyafrica.com"},"directories":{},"maintainers":[{"name":"r1gan","email":"rigan.gor@turnkeyafrica.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ui_0.1.1_1753997305902_0.2605355481808975"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-31T21:28:25.824Z","0.1.1":"2025-07-31T21:28:26.094Z","modified":"2025-07-31T21:28:26.365Z"},"maintainers":[{"name":"r1gan","email":"rigan.gor@turnkeyafrica.com"}],"description":"UI components for Akili AI SDK","readme":"# @caava-ai/ui\r\n\r\nReusable UI components and utilities for building consistent interfaces with the Caava AI SDK.\r\n\r\n## Features\r\n\r\n- 🎨 **Utility Functions** - Class management and styling utilities\r\n- 🎯 **TypeScript** - Full type safety\r\n- 🧩 **Framework Agnostic** - Core utilities work with any framework\r\n- 🎨 **Tailwind Compatible** - Designed to work with Tailwind CSS\r\n- 📦 **Lightweight** - Minimal bundle size\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @caava-ai/ui\r\n```\r\n\r\n## Utilities\r\n\r\nThis package currently provides core styling utilities. UI components will be added in future releases.\r\n\r\n### Class Management\r\n\r\n```typescript\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\n// Combine classes conditionally\r\nconst className = cn(\r\n  \"base-class\",\r\n  \"conditional-class\",\r\n  isActive && \"active-class\",\r\n  isDisabled && \"disabled-class\"\r\n);\r\n\r\n// Works great with Tailwind CSS\r\nconst buttonClass = cn(\r\n  \"px-4 py-2 rounded-md font-medium\",\r\n  variant === \"primary\" && \"bg-blue-500 text-white\",\r\n  variant === \"secondary\" && \"bg-gray-200 text-gray-900\",\r\n  size === \"sm\" && \"text-sm px-3 py-1\",\r\n  size === \"lg\" && \"text-lg px-6 py-3\",\r\n  disabled && \"opacity-50 cursor-not-allowed\"\r\n);\r\n```\r\n\r\n## Usage Examples\r\n\r\n### React Component Styling\r\n\r\n```tsx\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\ninterface ButtonProps {\r\n  variant?: \"primary\" | \"secondary\" | \"outline\";\r\n  size?: \"sm\" | \"md\" | \"lg\";\r\n  disabled?: boolean;\r\n  className?: string;\r\n  children: React.ReactNode;\r\n}\r\n\r\nfunction Button({\r\n  variant = \"primary\",\r\n  size = \"md\",\r\n  disabled = false,\r\n  className,\r\n  children,\r\n  ...props\r\n}: ButtonProps) {\r\n  return (\r\n    <button\r\n      className={cn(\r\n        // Base styles\r\n        \"font-medium rounded-md transition-colors focus:outline-none focus:ring-2\",\r\n\r\n        // Variant styles\r\n        variant === \"primary\" &&\r\n          \"bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500\",\r\n        variant === \"secondary\" &&\r\n          \"bg-gray-200 text-gray-900 hover:bg-gray-300 focus:ring-gray-500\",\r\n        variant === \"outline\" &&\r\n          \"border border-gray-300 bg-white text-gray-700 hover:bg-gray-50\",\r\n\r\n        // Size styles\r\n        size === \"sm\" && \"px-3 py-1.5 text-sm\",\r\n        size === \"md\" && \"px-4 py-2 text-base\",\r\n        size === \"lg\" && \"px-6 py-3 text-lg\",\r\n\r\n        // State styles\r\n        disabled && \"opacity-50 cursor-not-allowed pointer-events-none\",\r\n\r\n        // Custom className\r\n        className\r\n      )}\r\n      disabled={disabled}\r\n      {...props}\r\n    >\r\n      {children}\r\n    </button>\r\n  );\r\n}\r\n```\r\n\r\n### Chat Message Components\r\n\r\n```tsx\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\ninterface MessageProps {\r\n  role: \"user\" | \"assistant\";\r\n  content: string;\r\n  isOptimistic?: boolean;\r\n  className?: string;\r\n}\r\n\r\nfunction ChatMessage({ role, content, isOptimistic, className }: MessageProps) {\r\n  return (\r\n    <div\r\n      className={cn(\r\n        \"flex mb-4\",\r\n        role === \"user\" ? \"justify-end\" : \"justify-start\",\r\n        className\r\n      )}\r\n    >\r\n      <div\r\n        className={cn(\r\n          \"max-w-xs lg:max-w-md px-4 py-2 rounded-lg\",\r\n          role === \"user\" && [\"bg-blue-500 text-white\", \"rounded-br-none\"],\r\n          role === \"assistant\" && [\r\n            \"bg-gray-200 text-gray-900\",\r\n            \"rounded-bl-none\",\r\n          ],\r\n          isOptimistic && \"opacity-70\"\r\n        )}\r\n      >\r\n        {content}\r\n      </div>\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n### Widget Container\r\n\r\n```tsx\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\ninterface WidgetContainerProps {\r\n  children: React.ReactNode;\r\n  position?: \"fixed\" | \"embedded\";\r\n  theme?: \"light\" | \"dark\";\r\n  className?: string;\r\n}\r\n\r\nfunction WidgetContainer({\r\n  children,\r\n  position = \"fixed\",\r\n  theme = \"light\",\r\n  className,\r\n}: WidgetContainerProps) {\r\n  return (\r\n    <div\r\n      className={cn(\r\n        \"border border-gray-200 rounded-lg shadow-lg overflow-hidden\",\r\n\r\n        // Position styles\r\n        position === \"fixed\" && [\"fixed bottom-4 right-4 w-80 h-96\", \"z-50\"],\r\n        position === \"embedded\" && [\"w-full h-full\"],\r\n\r\n        // Theme styles\r\n        theme === \"light\" && \"bg-white\",\r\n        theme === \"dark\" && \"bg-gray-900 border-gray-700\",\r\n\r\n        className\r\n      )}\r\n    >\r\n      {children}\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n## Design Tokens\r\n\r\nWhile this package focuses on utilities, you can establish design tokens using CSS variables:\r\n\r\n```css\r\n:root {\r\n  /* Colors */\r\n  --color-primary: #3b82f6;\r\n  --color-primary-hover: #2563eb;\r\n  --color-secondary: #6b7280;\r\n  --color-background: #ffffff;\r\n  --color-surface: #f9fafb;\r\n  --color-text: #1f2937;\r\n  --color-text-muted: #6b7280;\r\n\r\n  /* Spacing */\r\n  --spacing-xs: 0.25rem;\r\n  --spacing-sm: 0.5rem;\r\n  --spacing-md: 1rem;\r\n  --spacing-lg: 1.5rem;\r\n  --spacing-xl: 2rem;\r\n\r\n  /* Typography */\r\n  --font-size-sm: 0.875rem;\r\n  --font-size-base: 1rem;\r\n  --font-size-lg: 1.125rem;\r\n  --font-size-xl: 1.25rem;\r\n\r\n  /* Border Radius */\r\n  --radius-sm: 0.25rem;\r\n  --radius-md: 0.375rem;\r\n  --radius-lg: 0.5rem;\r\n  --radius-xl: 0.75rem;\r\n\r\n  /* Shadows */\r\n  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\r\n  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\r\n  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);\r\n}\r\n\r\n/* Dark theme */\r\n[data-theme=\"dark\"] {\r\n  --color-background: #1f2937;\r\n  --color-surface: #374151;\r\n  --color-text: #f9fafb;\r\n  --color-text-muted: #d1d5db;\r\n}\r\n```\r\n\r\n## Framework Integration\r\n\r\n### React\r\n\r\n```tsx\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\n// Use with React components as shown in examples above\r\n```\r\n\r\n### Vue.js\r\n\r\n```vue\r\n<template>\r\n  <div :class=\"buttonClass\">\r\n    <slot />\r\n  </div>\r\n</template>\r\n\r\n<script setup>\r\nimport { computed } from \"vue\";\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\nconst props = defineProps({\r\n  variant: { type: String, default: \"primary\" },\r\n  size: { type: String, default: \"md\" },\r\n  disabled: Boolean,\r\n});\r\n\r\nconst buttonClass = computed(() =>\r\n  cn(\r\n    \"font-medium rounded-md transition-colors\",\r\n    props.variant === \"primary\" && \"bg-blue-600 text-white\",\r\n    props.variant === \"secondary\" && \"bg-gray-200 text-gray-900\",\r\n    props.size === \"sm\" && \"px-3 py-1.5 text-sm\",\r\n    props.size === \"md\" && \"px-4 py-2 text-base\",\r\n    props.disabled && \"opacity-50 cursor-not-allowed\"\r\n  )\r\n);\r\n</script>\r\n```\r\n\r\n### Angular\r\n\r\n```typescript\r\nimport { Component, Input } from \"@angular/core\";\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\n@Component({\r\n  selector: \"app-button\",\r\n  template: `\r\n    <button [class]=\"buttonClass\" [disabled]=\"disabled\">\r\n      <ng-content></ng-content>\r\n    </button>\r\n  `,\r\n})\r\nexport class ButtonComponent {\r\n  @Input() variant: \"primary\" | \"secondary\" = \"primary\";\r\n  @Input() size: \"sm\" | \"md\" | \"lg\" = \"md\";\r\n  @Input() disabled = false;\r\n\r\n  get buttonClass() {\r\n    return cn(\r\n      \"font-medium rounded-md transition-colors\",\r\n      this.variant === \"primary\" && \"bg-blue-600 text-white\",\r\n      this.variant === \"secondary\" && \"bg-gray-200 text-gray-900\",\r\n      this.size === \"sm\" && \"px-3 py-1.5 text-sm\",\r\n      this.size === \"md\" && \"px-4 py-2 text-base\",\r\n      this.disabled && \"opacity-50 cursor-not-allowed\"\r\n    );\r\n  }\r\n}\r\n```\r\n\r\n### Vanilla JavaScript\r\n\r\n```javascript\r\nimport { cn } from \"@caava-ai/ui\";\r\n\r\nfunction createButton({\r\n  variant = \"primary\",\r\n  size = \"md\",\r\n  disabled = false,\r\n  text,\r\n}) {\r\n  const button = document.createElement(\"button\");\r\n\r\n  button.className = cn(\r\n    \"font-medium rounded-md transition-colors\",\r\n    variant === \"primary\" && \"bg-blue-600 text-white hover:bg-blue-700\",\r\n    variant === \"secondary\" && \"bg-gray-200 text-gray-900 hover:bg-gray-300\",\r\n    size === \"sm\" && \"px-3 py-1.5 text-sm\",\r\n    size === \"md\" && \"px-4 py-2 text-base\",\r\n    disabled && \"opacity-50 cursor-not-allowed\"\r\n  );\r\n\r\n  button.textContent = text;\r\n  button.disabled = disabled;\r\n\r\n  return button;\r\n}\r\n```\r\n\r\n## Best Practices\r\n\r\n### Component Composition\r\n\r\n```tsx\r\n// Base component with utilities\r\nfunction BaseButton({ className, ...props }) {\r\n  return (\r\n    <button\r\n      className={cn(\r\n        \"font-medium rounded-md transition-colors focus:outline-none focus:ring-2\",\r\n        className\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\n// Specialized components\r\nfunction PrimaryButton({ className, ...props }) {\r\n  return (\r\n    <BaseButton\r\n      className={cn(\r\n        \"bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500\",\r\n        className\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction SecondaryButton({ className, ...props }) {\r\n  return (\r\n    <BaseButton\r\n      className={cn(\r\n        \"bg-gray-200 text-gray-900 hover:bg-gray-300 focus:ring-gray-500\",\r\n        className\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n```\r\n\r\n### Responsive Design\r\n\r\n```tsx\r\nfunction ResponsiveWidget({ className, ...props }) {\r\n  return (\r\n    <div\r\n      className={cn(\r\n        // Mobile: full screen overlay\r\n        \"fixed inset-0 bg-white z-50\",\r\n\r\n        // Tablet: bottom sheet\r\n        \"md:fixed md:bottom-0 md:left-0 md:right-0 md:top-auto md:h-2/3\",\r\n        \"md:rounded-t-lg md:shadow-xl\",\r\n\r\n        // Desktop: floating widget\r\n        \"lg:relative lg:inset-auto lg:w-80 lg:h-96\",\r\n        \"lg:rounded-lg lg:shadow-lg\",\r\n\r\n        className\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n```\r\n\r\n## Future Components\r\n\r\nPlanned UI components for future releases:\r\n\r\n- **Button** - Various button styles and sizes\r\n- **Input** - Text inputs with validation states\r\n- **Card** - Container component for content\r\n- **Avatar** - User avatar component\r\n- **Badge** - Status and notification badges\r\n- **Spinner** - Loading indicators\r\n- **Toast** - Notification messages\r\n- **Modal** - Overlay dialogs\r\n- **Dropdown** - Select and menu components\r\n\r\n## API Reference\r\n\r\n### Functions\r\n\r\n- `cn(...inputs: ClassValue[]): string` - Combines class names conditionally\r\n\r\n### Types\r\n\r\n```typescript\r\ntype ClassValue =\r\n  | string\r\n  | number\r\n  | boolean\r\n  | undefined\r\n  | null\r\n  | ClassValue[]\r\n  | Record<string, any>;\r\n```\r\n\r\n## Dependencies\r\n\r\n- `clsx` - Conditional class name utility\r\n- `tailwind-merge` - Tailwind CSS class merging\r\n- `class-variance-authority` - Component variant handling\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md","_rev":"1-81dffbb4be71dccf7cb41348825339e9"}