@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 +141 -10
- package/dist/index.cjs +118 -0
- package/dist/index.d.cts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +116 -0
- package/package.json +1 -1
- package/src/styles.css +186 -0
package/README.md
CHANGED
|
@@ -1,38 +1,169 @@
|
|
|
1
1
|
# @camtomlabs/malix-design-system
|
|
2
2
|
|
|
3
|
-
Malix Design System
|
|
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
|
-
##
|
|
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
|
-
|
|
15
|
+
**Peer dependencies** — make sure your project has these installed:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install react react-dom
|
|
19
|
+
```
|
|
12
20
|
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
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
|
+
}
|