@camtomlabs/malix-design-system 0.1.3 → 0.1.4

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
@@ -1,38 +1,169 @@
1
1
  # @camtomlabs/malix-design-system
2
2
 
3
- Malix Design System combined package.
3
+ Malix Design System a React component library by [Camtom Labs](https://camtomx.com). Ships pre-built with full TypeScript types, design tokens, and ready-to-use CSS.
4
4
 
5
- ## Install
5
+ ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @camtomlabs/malix-design-system
9
+ # or
10
+ pnpm add @camtomlabs/malix-design-system
11
+ # or
12
+ yarn add @camtomlabs/malix-design-system
9
13
  ```
10
14
 
11
- ## Usage
15
+ **Peer dependencies** — make sure your project has these installed:
16
+
17
+ ```bash
18
+ npm install react react-dom
19
+ ```
12
20
 
13
- Import the bundled styles once:
21
+ ## Setup
22
+
23
+ Import the bundled stylesheet once in your app's entry point (e.g. `main.tsx`, `layout.tsx`, or `_app.tsx`):
14
24
 
15
25
  ```ts
16
26
  import '@camtomlabs/malix-design-system/styles.css';
17
27
  ```
18
28
 
19
- Import components from the combined entrypoint:
29
+ That's it. All components are styled and ready to use.
30
+
31
+ ## Usage
20
32
 
21
33
  ```tsx
22
34
  import { Button, Input, Card } from '@camtomlabs/malix-design-system';
35
+
36
+ export function MyPage() {
37
+ return (
38
+ <Card>
39
+ <Input placeholder="Enter your email" />
40
+ <Button hierarchy="primary">Continue</Button>
41
+ </Card>
42
+ );
43
+ }
23
44
  ```
24
45
 
25
- You can also read the token registry:
46
+ ## Design Tokens
47
+
48
+ Malix uses a CSS custom-property token system for colors, spacing, typography, and radius. You can also import the tokens stylesheet separately:
49
+
50
+ ```ts
51
+ import '@camtomlabs/malix-design-system/tokens.css';
52
+ ```
53
+
54
+ Or access the token registry programmatically:
26
55
 
27
56
  ```ts
28
57
  import { tokenRegistry } from '@camtomlabs/malix-design-system';
29
58
  ```
30
59
 
31
- ## Note
60
+ ## Components
61
+
62
+ ### Atoms
63
+ | Component | Description |
64
+ |-----------|-------------|
65
+ | `Avatar` | User avatar with image or initials fallback |
66
+ | `Badge` | Status or count indicator |
67
+ | `Divider` | Horizontal or vertical separator |
68
+ | `Pill` | Compact label/tag element |
69
+ | `StatusDot` | Small colored status indicator |
70
+
71
+ ### Buttons
72
+ | Component | Description |
73
+ |-----------|-------------|
74
+ | `Button` | Primary action button with hierarchy and variant props |
75
+
76
+ ### Form Inputs
77
+ | Component | Description |
78
+ |-----------|-------------|
79
+ | `Checkbox` | Checkbox input with label |
80
+ | `DateInput` | Date picker input |
81
+ | `Input` | Text input field |
82
+ | `InputGroup` | Grouped inputs with shared label/error |
83
+ | `Radio` | Radio button input |
84
+ | `SearchInput` | Input with built-in search icon |
85
+ | `Select` | Dropdown select |
86
+ | `SelectGroup` | Grouped select options |
87
+ | `Textarea` | Multi-line text input |
88
+ | `Toggle` | On/off toggle switch |
89
+
90
+ ### Navigation
91
+ | Component | Description |
92
+ |-----------|-------------|
93
+ | `Breadcrumb` | Breadcrumb trail navigation |
94
+ | `FilterTabs` | Horizontal tab filters |
95
+ | `FlyoutMenu` | Flyout dropdown navigation menu |
96
+ | `Header` | Top-level app header |
97
+ | `SidebarItem` | Individual sidebar navigation item |
98
+ | `SidebarPanel` | Full sidebar navigation panel |
99
+ | `TabBar` | Tab bar with multiple items |
100
+
101
+ ### Layout
102
+ | Component | Description |
103
+ |-----------|-------------|
104
+ | `Card` | Surface container with elevation levels |
105
+ | `SectionHeader` | Page section heading with optional action |
106
+ | `SplitPane` | Resizable two-panel layout |
107
+
108
+ ### Data Display
109
+ | Component | Description |
110
+ |-----------|-------------|
111
+ | `DataTable` | Sortable data table with columns/rows |
112
+ | `FileCard` | File attachment preview card |
113
+ | `Pagination` | Page navigation controls |
114
+ | `StatCard` | Metric card with change indicator |
115
+ | `Stepper` | Multi-step progress tracker |
116
+
117
+ ### Feedback
118
+ | Component | Description |
119
+ |-----------|-------------|
120
+ | `Banner` | Full-width informational banner |
121
+ | `EmptyState` | Placeholder for empty content areas |
122
+ | `OperationStatus` | Async operation status display |
123
+ | `ProgressBar` | Linear progress indicator |
124
+ | `Tooltip` | Contextual hover tooltip |
125
+ | `ValidationAlert` | Inline form validation message |
126
+
127
+ ### Overlays
128
+ | Component | Description |
129
+ |-----------|-------------|
130
+ | `GlassPopover` | Glassmorphism-styled popover |
131
+ | `Modal` | Full-screen modal dialog |
132
+ | `OnboardingPopover` | Guided onboarding popover |
133
+ | `Overlay` | Backdrop overlay layer |
134
+
135
+ ### Interactive / Composite
136
+ | Component | Description |
137
+ |-----------|-------------|
138
+ | `Accordion` | Collapsible content sections |
139
+ | `ChatInput` | Rich chat message input |
140
+ | `CreditsIndicator` | Usage credits display |
141
+ | `Dropzone` | File drag-and-drop upload area |
142
+ | `LanguageSelector` | Locale/language switcher |
143
+ | `PricingCard` | Subscription plan pricing card |
144
+ | `SegmentedControl` | Multi-option segmented selector |
145
+ | `SelectionCard` | Selectable card option |
146
+ | `UserProfilePopover` | User profile menu popover |
147
+ | `ChatBubble` | AI/user message bubble for chat UIs |
148
+ | `AIAssistantPanel` | Full AI chat panel with messages and input |
149
+
150
+ ## TypeScript
151
+
152
+ All components ship with TypeScript declarations. Named types are also exported for use in your own code:
153
+
154
+ ```ts
155
+ import type { ButtonProps, ButtonHierarchy, ButtonVariant } from '@camtomlabs/malix-design-system';
156
+ ```
157
+
158
+ ## Package Exports
32
159
 
33
- This package publishes raw TypeScript source. Configure your bundler to transpile the package in
34
- frameworks like Next.js.
160
+ | Import path | Description |
161
+ |-------------|-------------|
162
+ | `@camtomlabs/malix-design-system` | All components and types |
163
+ | `@camtomlabs/malix-design-system/styles.css` | Full component stylesheet |
164
+ | `@camtomlabs/malix-design-system/tokens.css` | Design tokens only |
165
+ | `@camtomlabs/malix-design-system/tokens.registry.json` | Token registry JSON |
35
166
 
36
167
  ## License
37
168
 
38
- `UNLICENSED`
169
+ MIT © [Camtom Labs](https://camtomx.com)
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AIAssistantPanel: () => AIAssistantPanel,
33
34
  Accordion: () => Accordion,
34
35
  Avatar: () => Avatar,
35
36
  Badge: () => Badge,
@@ -37,6 +38,7 @@ __export(index_exports, {
37
38
  Breadcrumb: () => Breadcrumb,
38
39
  Button: () => Button,
39
40
  Card: () => Card,
41
+ ChatBubble: () => ChatBubble,
40
42
  ChatInput: () => ChatInput,
41
43
  Checkbox: () => Checkbox,
42
44
  CreditsIndicator: () => CreditsIndicator,
@@ -2282,8 +2284,123 @@ function UserProfilePopover({
2282
2284
  }
2283
2285
  );
2284
2286
  }
2287
+
2288
+ // src/components/ChatBubble.tsx
2289
+ var import_jsx_runtime50 = require("react/jsx-runtime");
2290
+ function ChatBubble({
2291
+ variant,
2292
+ message,
2293
+ avatarInitials,
2294
+ children,
2295
+ className
2296
+ }) {
2297
+ const content = children ?? message;
2298
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
2299
+ "div",
2300
+ {
2301
+ className: `malix-chat-bubble-row${className ? ` ${className}` : ""}`,
2302
+ "data-variant": variant,
2303
+ children: [
2304
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "malix-chat-bubble", "data-variant": variant, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "malix-chat-bubble__text", children: content }) }),
2305
+ variant === "user" && avatarInitials ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "malix-chat-bubble__avatar", children: avatarInitials }) : null
2306
+ ]
2307
+ }
2308
+ );
2309
+ }
2310
+
2311
+ // src/components/AIAssistantPanel.tsx
2312
+ var import_react13 = require("react");
2313
+ var import_jsx_runtime51 = require("react/jsx-runtime");
2314
+ function AIAssistantPanel({
2315
+ title = "AI Assistant",
2316
+ messages,
2317
+ onSend,
2318
+ onClose,
2319
+ placeholder = "Ask the AI assistant...",
2320
+ userInitials,
2321
+ disabled,
2322
+ className
2323
+ }) {
2324
+ const [draft, setDraft] = (0, import_react13.useState)("");
2325
+ const bodyRef = (0, import_react13.useRef)(null);
2326
+ (0, import_react13.useEffect)(() => {
2327
+ if (bodyRef.current) {
2328
+ bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
2329
+ }
2330
+ }, [messages]);
2331
+ const handleSend = () => {
2332
+ const text = draft.trim();
2333
+ if (!text) return;
2334
+ onSend(text);
2335
+ setDraft("");
2336
+ };
2337
+ const handleKeyDown = (e) => {
2338
+ if (e.key === "Enter" && !e.shiftKey && draft.trim()) {
2339
+ e.preventDefault();
2340
+ handleSend();
2341
+ }
2342
+ };
2343
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: `malix-ai-panel${className ? ` ${className}` : ""}`, children: [
2344
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "malix-ai-panel__header", children: [
2345
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "malix-ai-panel__logo", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" }) }) }),
2346
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "malix-ai-panel__title", children: title }),
2347
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2348
+ "button",
2349
+ {
2350
+ type: "button",
2351
+ className: "malix-ai-panel__close",
2352
+ onClick: onClose,
2353
+ "aria-label": "Close assistant",
2354
+ children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2355
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: "M18 6 6 18" }),
2356
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: "m6 6 12 12" })
2357
+ ] })
2358
+ }
2359
+ ) : null
2360
+ ] }),
2361
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "malix-ai-panel__body", ref: bodyRef, children: messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2362
+ ChatBubble,
2363
+ {
2364
+ variant: msg.variant,
2365
+ message: msg.content,
2366
+ avatarInitials: msg.variant === "user" ? userInitials : void 0
2367
+ },
2368
+ msg.id
2369
+ )) }),
2370
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "malix-ai-panel__footer", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "malix-ai-panel__input-row", children: [
2371
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2372
+ "input",
2373
+ {
2374
+ type: "text",
2375
+ className: "malix-ai-panel__input",
2376
+ value: draft,
2377
+ onChange: (e) => setDraft(e.target.value),
2378
+ onKeyDown: handleKeyDown,
2379
+ placeholder,
2380
+ disabled,
2381
+ "aria-label": placeholder
2382
+ }
2383
+ ),
2384
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2385
+ "button",
2386
+ {
2387
+ type: "button",
2388
+ className: "malix-ai-panel__send",
2389
+ onClick: handleSend,
2390
+ disabled: disabled || !draft.trim(),
2391
+ "aria-label": "Send message",
2392
+ children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2393
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: "M12 19V5" }),
2394
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("path", { d: "m5 12 7-7 7 7" })
2395
+ ] })
2396
+ }
2397
+ )
2398
+ ] }) })
2399
+ ] });
2400
+ }
2285
2401
  // Annotate the CommonJS export names for ESM import in node:
2286
2402
  0 && (module.exports = {
2403
+ AIAssistantPanel,
2287
2404
  Accordion,
2288
2405
  Avatar,
2289
2406
  Badge,
@@ -2291,6 +2408,7 @@ function UserProfilePopover({
2291
2408
  Breadcrumb,
2292
2409
  Button,
2293
2410
  Card,
2411
+ ChatBubble,
2294
2412
  ChatInput,
2295
2413
  Checkbox,
2296
2414
  CreditsIndicator,
package/dist/index.d.cts CHANGED
@@ -521,4 +521,42 @@ type UserProfilePopoverProps = React.HTMLAttributes<HTMLDivElement> & {
521
521
  };
522
522
  declare function UserProfilePopover({ name, email, avatar, menuItems, onLogout, credits, className, ...props }: UserProfilePopoverProps): react_jsx_runtime.JSX.Element;
523
523
 
524
- export { Accordion, type AccordionProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeVariant, Banner, type BannerProps, type BannerVariant, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonHierarchy, type ButtonProps, type ButtonVariant, Card, type CardLevel, type CardProps, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CreditsIndicator, type CreditsIndicatorProps, DataTable, type DataTableProps, DateInput, type DateInputProps, Divider, type DividerProps, Dropzone, type DropzoneProps, EmptyState, type EmptyStateProps, FileCard, type FileCardProps, type FilterTabItem, FilterTabs, type FilterTabsProps, FlyoutMenu, type FlyoutMenuItem, type FlyoutMenuProps, GlassPopover, type GlassPopoverProps, Header, type HeaderProps, Input, InputGroup, type InputGroupProps, type InputProps, LanguageSelector, type LanguageSelectorOption, type LanguageSelectorProps, Modal, type ModalProps, OnboardingPopover, type OnboardingPopoverProps, OperationStatus, type OperationStatusProps, type OperationStatusType, Overlay, type OverlayProps, Pagination, type PaginationProps, type PaginationVariant, Pill, type PillProps, type PillVariant, PricingCard, type PricingCardProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, Radio, type RadioProps, SearchInput, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, Select, SelectGroup, type SelectGroupProps, type SelectOption, type SelectProps, SelectionCard, type SelectionCardProps, SidebarItem, type SidebarItemProps, SidebarPanel, type SidebarPanelProps, SplitPane, type SplitPaneProps, StatCard, type StatCardChangeType, type StatCardProps, StatusDot, type StatusDotProps, type StatusDotVariant, type StepItem, type StepStatus, Stepper, type StepperProps, TabBar, type TabBarProps, type TabItem, type TableColumn, type TableRow, Textarea, type TextareaProps, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, type UserProfileMenuItem, UserProfilePopover, type UserProfilePopoverProps, ValidationAlert, type ValidationAlertProps, type ValidationAlertVariant, tokens_registry as tokenRegistry };
524
+ type ChatBubbleVariant = 'ai' | 'user';
525
+ type ChatBubbleProps = {
526
+ /** Which side of the conversation this bubble represents. */
527
+ variant: ChatBubbleVariant;
528
+ /** Text content of the message. */
529
+ message?: string;
530
+ /** Optional user initials shown as avatar next to user messages. */
531
+ avatarInitials?: string;
532
+ /** Override content via children instead of message prop. */
533
+ children?: React.ReactNode;
534
+ className?: string;
535
+ };
536
+ declare function ChatBubble({ variant, message, avatarInitials, children, className, }: ChatBubbleProps): react_jsx_runtime.JSX.Element;
537
+
538
+ type AIAssistantMessage = {
539
+ id: string;
540
+ variant: 'ai' | 'user';
541
+ content: string;
542
+ };
543
+ type AIAssistantPanelProps = {
544
+ /** Title shown in the header. */
545
+ title?: string;
546
+ /** Conversation messages. */
547
+ messages: AIAssistantMessage[];
548
+ /** Called when the user sends a new message. */
549
+ onSend: (message: string) => void;
550
+ /** Called when the close button is pressed. */
551
+ onClose?: () => void;
552
+ /** Placeholder text for the input field. */
553
+ placeholder?: string;
554
+ /** User initials shown next to user messages. */
555
+ userInitials?: string;
556
+ /** Disable input and send button. */
557
+ disabled?: boolean;
558
+ className?: string;
559
+ };
560
+ declare function AIAssistantPanel({ title, messages, onSend, onClose, placeholder, userInitials, disabled, className, }: AIAssistantPanelProps): react_jsx_runtime.JSX.Element;
561
+
562
+ export { type AIAssistantMessage, AIAssistantPanel, type AIAssistantPanelProps, Accordion, type AccordionProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeVariant, Banner, type BannerProps, type BannerVariant, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonHierarchy, type ButtonProps, type ButtonVariant, Card, type CardLevel, type CardProps, ChatBubble, type ChatBubbleProps, type ChatBubbleVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CreditsIndicator, type CreditsIndicatorProps, DataTable, type DataTableProps, DateInput, type DateInputProps, Divider, type DividerProps, Dropzone, type DropzoneProps, EmptyState, type EmptyStateProps, FileCard, type FileCardProps, type FilterTabItem, FilterTabs, type FilterTabsProps, FlyoutMenu, type FlyoutMenuItem, type FlyoutMenuProps, GlassPopover, type GlassPopoverProps, Header, type HeaderProps, Input, InputGroup, type InputGroupProps, type InputProps, LanguageSelector, type LanguageSelectorOption, type LanguageSelectorProps, Modal, type ModalProps, OnboardingPopover, type OnboardingPopoverProps, OperationStatus, type OperationStatusProps, type OperationStatusType, Overlay, type OverlayProps, Pagination, type PaginationProps, type PaginationVariant, Pill, type PillProps, type PillVariant, PricingCard, type PricingCardProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, Radio, type RadioProps, SearchInput, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, Select, SelectGroup, type SelectGroupProps, type SelectOption, type SelectProps, SelectionCard, type SelectionCardProps, SidebarItem, type SidebarItemProps, SidebarPanel, type SidebarPanelProps, SplitPane, type SplitPaneProps, StatCard, type StatCardChangeType, type StatCardProps, StatusDot, type StatusDotProps, type StatusDotVariant, type StepItem, type StepStatus, Stepper, type StepperProps, TabBar, type TabBarProps, type TabItem, type TableColumn, type TableRow, Textarea, type TextareaProps, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, type UserProfileMenuItem, UserProfilePopover, type UserProfilePopoverProps, ValidationAlert, type ValidationAlertProps, type ValidationAlertVariant, tokens_registry as tokenRegistry };
package/dist/index.d.ts CHANGED
@@ -521,4 +521,42 @@ type UserProfilePopoverProps = React.HTMLAttributes<HTMLDivElement> & {
521
521
  };
522
522
  declare function UserProfilePopover({ name, email, avatar, menuItems, onLogout, credits, className, ...props }: UserProfilePopoverProps): react_jsx_runtime.JSX.Element;
523
523
 
524
- export { Accordion, type AccordionProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeVariant, Banner, type BannerProps, type BannerVariant, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonHierarchy, type ButtonProps, type ButtonVariant, Card, type CardLevel, type CardProps, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CreditsIndicator, type CreditsIndicatorProps, DataTable, type DataTableProps, DateInput, type DateInputProps, Divider, type DividerProps, Dropzone, type DropzoneProps, EmptyState, type EmptyStateProps, FileCard, type FileCardProps, type FilterTabItem, FilterTabs, type FilterTabsProps, FlyoutMenu, type FlyoutMenuItem, type FlyoutMenuProps, GlassPopover, type GlassPopoverProps, Header, type HeaderProps, Input, InputGroup, type InputGroupProps, type InputProps, LanguageSelector, type LanguageSelectorOption, type LanguageSelectorProps, Modal, type ModalProps, OnboardingPopover, type OnboardingPopoverProps, OperationStatus, type OperationStatusProps, type OperationStatusType, Overlay, type OverlayProps, Pagination, type PaginationProps, type PaginationVariant, Pill, type PillProps, type PillVariant, PricingCard, type PricingCardProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, Radio, type RadioProps, SearchInput, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, Select, SelectGroup, type SelectGroupProps, type SelectOption, type SelectProps, SelectionCard, type SelectionCardProps, SidebarItem, type SidebarItemProps, SidebarPanel, type SidebarPanelProps, SplitPane, type SplitPaneProps, StatCard, type StatCardChangeType, type StatCardProps, StatusDot, type StatusDotProps, type StatusDotVariant, type StepItem, type StepStatus, Stepper, type StepperProps, TabBar, type TabBarProps, type TabItem, type TableColumn, type TableRow, Textarea, type TextareaProps, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, type UserProfileMenuItem, UserProfilePopover, type UserProfilePopoverProps, ValidationAlert, type ValidationAlertProps, type ValidationAlertVariant, tokens_registry as tokenRegistry };
524
+ type ChatBubbleVariant = 'ai' | 'user';
525
+ type ChatBubbleProps = {
526
+ /** Which side of the conversation this bubble represents. */
527
+ variant: ChatBubbleVariant;
528
+ /** Text content of the message. */
529
+ message?: string;
530
+ /** Optional user initials shown as avatar next to user messages. */
531
+ avatarInitials?: string;
532
+ /** Override content via children instead of message prop. */
533
+ children?: React.ReactNode;
534
+ className?: string;
535
+ };
536
+ declare function ChatBubble({ variant, message, avatarInitials, children, className, }: ChatBubbleProps): react_jsx_runtime.JSX.Element;
537
+
538
+ type AIAssistantMessage = {
539
+ id: string;
540
+ variant: 'ai' | 'user';
541
+ content: string;
542
+ };
543
+ type AIAssistantPanelProps = {
544
+ /** Title shown in the header. */
545
+ title?: string;
546
+ /** Conversation messages. */
547
+ messages: AIAssistantMessage[];
548
+ /** Called when the user sends a new message. */
549
+ onSend: (message: string) => void;
550
+ /** Called when the close button is pressed. */
551
+ onClose?: () => void;
552
+ /** Placeholder text for the input field. */
553
+ placeholder?: string;
554
+ /** User initials shown next to user messages. */
555
+ userInitials?: string;
556
+ /** Disable input and send button. */
557
+ disabled?: boolean;
558
+ className?: string;
559
+ };
560
+ declare function AIAssistantPanel({ title, messages, onSend, onClose, placeholder, userInitials, disabled, className, }: AIAssistantPanelProps): react_jsx_runtime.JSX.Element;
561
+
562
+ export { type AIAssistantMessage, AIAssistantPanel, type AIAssistantPanelProps, Accordion, type AccordionProps, Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeVariant, Banner, type BannerProps, type BannerVariant, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonHierarchy, type ButtonProps, type ButtonVariant, Card, type CardLevel, type CardProps, ChatBubble, type ChatBubbleProps, type ChatBubbleVariant, ChatInput, type ChatInputProps, Checkbox, type CheckboxProps, CreditsIndicator, type CreditsIndicatorProps, DataTable, type DataTableProps, DateInput, type DateInputProps, Divider, type DividerProps, Dropzone, type DropzoneProps, EmptyState, type EmptyStateProps, FileCard, type FileCardProps, type FilterTabItem, FilterTabs, type FilterTabsProps, FlyoutMenu, type FlyoutMenuItem, type FlyoutMenuProps, GlassPopover, type GlassPopoverProps, Header, type HeaderProps, Input, InputGroup, type InputGroupProps, type InputProps, LanguageSelector, type LanguageSelectorOption, type LanguageSelectorProps, Modal, type ModalProps, OnboardingPopover, type OnboardingPopoverProps, OperationStatus, type OperationStatusProps, type OperationStatusType, Overlay, type OverlayProps, Pagination, type PaginationProps, type PaginationVariant, Pill, type PillProps, type PillVariant, PricingCard, type PricingCardProps, ProgressBar, type ProgressBarProps, type ProgressBarVariant, Radio, type RadioProps, SearchInput, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, Select, SelectGroup, type SelectGroupProps, type SelectOption, type SelectProps, SelectionCard, type SelectionCardProps, SidebarItem, type SidebarItemProps, SidebarPanel, type SidebarPanelProps, SplitPane, type SplitPaneProps, StatCard, type StatCardChangeType, type StatCardProps, StatusDot, type StatusDotProps, type StatusDotVariant, type StepItem, type StepStatus, Stepper, type StepperProps, TabBar, type TabBarProps, type TabItem, type TableColumn, type TableRow, Textarea, type TextareaProps, Toggle, type ToggleProps, Tooltip, type TooltipPlacement, type TooltipProps, type UserProfileMenuItem, UserProfilePopover, type UserProfilePopoverProps, ValidationAlert, type ValidationAlertProps, type ValidationAlertVariant, tokens_registry as tokenRegistry };
package/dist/index.js CHANGED
@@ -2196,7 +2196,122 @@ function UserProfilePopover({
2196
2196
  }
2197
2197
  );
2198
2198
  }
2199
+
2200
+ // src/components/ChatBubble.tsx
2201
+ import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
2202
+ function ChatBubble({
2203
+ variant,
2204
+ message,
2205
+ avatarInitials,
2206
+ children,
2207
+ className
2208
+ }) {
2209
+ const content = children ?? message;
2210
+ return /* @__PURE__ */ jsxs45(
2211
+ "div",
2212
+ {
2213
+ className: `malix-chat-bubble-row${className ? ` ${className}` : ""}`,
2214
+ "data-variant": variant,
2215
+ children: [
2216
+ /* @__PURE__ */ jsx50("div", { className: "malix-chat-bubble", "data-variant": variant, children: /* @__PURE__ */ jsx50("span", { className: "malix-chat-bubble__text", children: content }) }),
2217
+ variant === "user" && avatarInitials ? /* @__PURE__ */ jsx50("span", { className: "malix-chat-bubble__avatar", children: avatarInitials }) : null
2218
+ ]
2219
+ }
2220
+ );
2221
+ }
2222
+
2223
+ // src/components/AIAssistantPanel.tsx
2224
+ import { useState as useState6, useRef as useRef5, useEffect as useEffect4 } from "react";
2225
+ import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
2226
+ function AIAssistantPanel({
2227
+ title = "AI Assistant",
2228
+ messages,
2229
+ onSend,
2230
+ onClose,
2231
+ placeholder = "Ask the AI assistant...",
2232
+ userInitials,
2233
+ disabled,
2234
+ className
2235
+ }) {
2236
+ const [draft, setDraft] = useState6("");
2237
+ const bodyRef = useRef5(null);
2238
+ useEffect4(() => {
2239
+ if (bodyRef.current) {
2240
+ bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
2241
+ }
2242
+ }, [messages]);
2243
+ const handleSend = () => {
2244
+ const text = draft.trim();
2245
+ if (!text) return;
2246
+ onSend(text);
2247
+ setDraft("");
2248
+ };
2249
+ const handleKeyDown = (e) => {
2250
+ if (e.key === "Enter" && !e.shiftKey && draft.trim()) {
2251
+ e.preventDefault();
2252
+ handleSend();
2253
+ }
2254
+ };
2255
+ return /* @__PURE__ */ jsxs46("div", { className: `malix-ai-panel${className ? ` ${className}` : ""}`, children: [
2256
+ /* @__PURE__ */ jsxs46("div", { className: "malix-ai-panel__header", children: [
2257
+ /* @__PURE__ */ jsx51("span", { className: "malix-ai-panel__logo", children: /* @__PURE__ */ jsx51("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx51("path", { d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" }) }) }),
2258
+ /* @__PURE__ */ jsx51("span", { className: "malix-ai-panel__title", children: title }),
2259
+ onClose ? /* @__PURE__ */ jsx51(
2260
+ "button",
2261
+ {
2262
+ type: "button",
2263
+ className: "malix-ai-panel__close",
2264
+ onClick: onClose,
2265
+ "aria-label": "Close assistant",
2266
+ children: /* @__PURE__ */ jsxs46("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2267
+ /* @__PURE__ */ jsx51("path", { d: "M18 6 6 18" }),
2268
+ /* @__PURE__ */ jsx51("path", { d: "m6 6 12 12" })
2269
+ ] })
2270
+ }
2271
+ ) : null
2272
+ ] }),
2273
+ /* @__PURE__ */ jsx51("div", { className: "malix-ai-panel__body", ref: bodyRef, children: messages.map((msg) => /* @__PURE__ */ jsx51(
2274
+ ChatBubble,
2275
+ {
2276
+ variant: msg.variant,
2277
+ message: msg.content,
2278
+ avatarInitials: msg.variant === "user" ? userInitials : void 0
2279
+ },
2280
+ msg.id
2281
+ )) }),
2282
+ /* @__PURE__ */ jsx51("div", { className: "malix-ai-panel__footer", children: /* @__PURE__ */ jsxs46("div", { className: "malix-ai-panel__input-row", children: [
2283
+ /* @__PURE__ */ jsx51(
2284
+ "input",
2285
+ {
2286
+ type: "text",
2287
+ className: "malix-ai-panel__input",
2288
+ value: draft,
2289
+ onChange: (e) => setDraft(e.target.value),
2290
+ onKeyDown: handleKeyDown,
2291
+ placeholder,
2292
+ disabled,
2293
+ "aria-label": placeholder
2294
+ }
2295
+ ),
2296
+ /* @__PURE__ */ jsx51(
2297
+ "button",
2298
+ {
2299
+ type: "button",
2300
+ className: "malix-ai-panel__send",
2301
+ onClick: handleSend,
2302
+ disabled: disabled || !draft.trim(),
2303
+ "aria-label": "Send message",
2304
+ children: /* @__PURE__ */ jsxs46("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2305
+ /* @__PURE__ */ jsx51("path", { d: "M12 19V5" }),
2306
+ /* @__PURE__ */ jsx51("path", { d: "m5 12 7-7 7 7" })
2307
+ ] })
2308
+ }
2309
+ )
2310
+ ] }) })
2311
+ ] });
2312
+ }
2199
2313
  export {
2314
+ AIAssistantPanel,
2200
2315
  Accordion,
2201
2316
  Avatar,
2202
2317
  Badge,
@@ -2204,6 +2319,7 @@ export {
2204
2319
  Breadcrumb,
2205
2320
  Button,
2206
2321
  Card,
2322
+ ChatBubble,
2207
2323
  ChatInput,
2208
2324
  Checkbox,
2209
2325
  CreditsIndicator,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camtomlabs/malix-design-system",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Malix Design System combined package with components, tokens, and bundled styles.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
package/src/styles.css CHANGED
@@ -3235,3 +3235,189 @@ a.malix-breadcrumb__label:hover {
3235
3235
  height: 16px;
3236
3236
  flex-shrink: 0;
3237
3237
  }
3238
+
3239
+ /* ═══════════════════════════════════════════════
3240
+ CHAT BUBBLE — Pencil: gNrQK, dqzNT
3241
+ AI: surface-secondary bg, foreground text
3242
+ User: cta-primary bg, primary-foreground text
3243
+ ═══════════════════════════════════════════════ */
3244
+
3245
+ .malix-chat-bubble-row {
3246
+ display: flex;
3247
+ align-items: flex-end;
3248
+ gap: var(--malix-space-sm);
3249
+ width: 100%;
3250
+ }
3251
+
3252
+ .malix-chat-bubble-row[data-variant="user"] {
3253
+ justify-content: flex-end;
3254
+ }
3255
+
3256
+ .malix-chat-bubble {
3257
+ padding: 10px 14px;
3258
+ font-family: var(--malix-font-body);
3259
+ font-size: var(--malix-text-sm);
3260
+ font-weight: var(--malix-weight-normal);
3261
+ line-height: 1.45;
3262
+ max-width: 280px;
3263
+ word-wrap: break-word;
3264
+ }
3265
+
3266
+ .malix-chat-bubble[data-variant="ai"] {
3267
+ background: var(--malix-surface-secondary);
3268
+ color: var(--malix-foreground);
3269
+ border-radius: 8px 8px 8px 2px;
3270
+ }
3271
+
3272
+ .malix-chat-bubble[data-variant="user"] {
3273
+ background: var(--malix-cta-primary-bg);
3274
+ color: var(--malix-primary-foreground);
3275
+ border-radius: 8px 8px 2px 8px;
3276
+ }
3277
+
3278
+ .malix-chat-bubble__avatar {
3279
+ display: inline-flex;
3280
+ align-items: center;
3281
+ justify-content: center;
3282
+ width: 28px;
3283
+ height: 28px;
3284
+ min-width: 28px;
3285
+ border-radius: 50%;
3286
+ background: var(--malix-background-main);
3287
+ border: 1px solid var(--malix-border);
3288
+ font-family: var(--malix-font-body);
3289
+ font-size: var(--malix-text-xs);
3290
+ font-weight: var(--malix-weight-semibold);
3291
+ color: var(--malix-foreground-secondary);
3292
+ }
3293
+
3294
+ /* ═══════════════════════════════════════════════
3295
+ AI ASSISTANT PANEL — Pencil: MtZxU
3296
+ 380×500 panel, border+radius-lg, vertical flex
3297
+ ═══════════════════════════════════════════════ */
3298
+
3299
+ .malix-ai-panel {
3300
+ display: flex;
3301
+ flex-direction: column;
3302
+ width: 380px;
3303
+ height: 500px;
3304
+ border-radius: var(--malix-radius-lg);
3305
+ background: var(--malix-background-main);
3306
+ border: 1px solid var(--malix-border);
3307
+ overflow: hidden;
3308
+ font-family: var(--malix-font-body);
3309
+ }
3310
+
3311
+ /* Header */
3312
+ .malix-ai-panel__header {
3313
+ display: flex;
3314
+ align-items: center;
3315
+ gap: 10px;
3316
+ padding: 14px 16px;
3317
+ border-bottom: 1px solid var(--malix-border);
3318
+ }
3319
+
3320
+ .malix-ai-panel__logo {
3321
+ display: inline-flex;
3322
+ align-items: center;
3323
+ justify-content: center;
3324
+ width: 28px;
3325
+ height: 28px;
3326
+ min-width: 28px;
3327
+ border-radius: var(--malix-radius-pill);
3328
+ background: var(--malix-cta-primary-bg);
3329
+ color: var(--malix-primary-foreground);
3330
+ }
3331
+
3332
+ .malix-ai-panel__title {
3333
+ font-size: var(--malix-text-base);
3334
+ font-weight: var(--malix-weight-semibold);
3335
+ color: var(--malix-foreground);
3336
+ flex: 1;
3337
+ }
3338
+
3339
+ .malix-ai-panel__close {
3340
+ display: inline-flex;
3341
+ align-items: center;
3342
+ justify-content: center;
3343
+ background: none;
3344
+ border: none;
3345
+ padding: 0;
3346
+ cursor: pointer;
3347
+ color: var(--malix-foreground-secondary);
3348
+ transition: color 120ms ease;
3349
+ }
3350
+
3351
+ .malix-ai-panel__close:hover {
3352
+ color: var(--malix-foreground);
3353
+ }
3354
+
3355
+ /* Body */
3356
+ .malix-ai-panel__body {
3357
+ flex: 1;
3358
+ overflow-y: auto;
3359
+ padding: 12px 16px;
3360
+ display: flex;
3361
+ flex-direction: column;
3362
+ gap: var(--malix-space-md);
3363
+ }
3364
+
3365
+ /* Footer */
3366
+ .malix-ai-panel__footer {
3367
+ padding: 12px 16px;
3368
+ border-top: 1px solid var(--malix-border);
3369
+ }
3370
+
3371
+ .malix-ai-panel__input-row {
3372
+ display: flex;
3373
+ align-items: center;
3374
+ gap: var(--malix-space-sm);
3375
+ padding: 10px 12px 10px 16px;
3376
+ border-radius: var(--malix-radius-lg);
3377
+ border: 1px solid var(--malix-border);
3378
+ background: var(--malix-background-main);
3379
+ transition: border-color 120ms ease;
3380
+ }
3381
+
3382
+ .malix-ai-panel__input-row:focus-within {
3383
+ border-color: var(--malix-border-focus);
3384
+ }
3385
+
3386
+ .malix-ai-panel__input {
3387
+ flex: 1;
3388
+ border: none;
3389
+ outline: none;
3390
+ background: transparent;
3391
+ font-family: var(--malix-font-body);
3392
+ font-size: var(--malix-text-base);
3393
+ color: var(--malix-foreground);
3394
+ padding: 0;
3395
+ }
3396
+
3397
+ .malix-ai-panel__input::placeholder {
3398
+ color: var(--malix-foreground-tertiary);
3399
+ }
3400
+
3401
+ .malix-ai-panel__send {
3402
+ display: inline-flex;
3403
+ align-items: center;
3404
+ justify-content: center;
3405
+ width: 32px;
3406
+ height: 32px;
3407
+ min-width: 32px;
3408
+ border-radius: var(--malix-radius-md);
3409
+ background: var(--malix-cta-primary-bg);
3410
+ color: var(--malix-primary-foreground);
3411
+ border: none;
3412
+ cursor: pointer;
3413
+ transition: background-color 120ms ease;
3414
+ }
3415
+
3416
+ .malix-ai-panel__send:hover:not(:disabled) {
3417
+ background: var(--malix-primary-hover);
3418
+ }
3419
+
3420
+ .malix-ai-panel__send:disabled {
3421
+ opacity: 0.5;
3422
+ cursor: not-allowed;
3423
+ }