@camtomlabs/malix-design-system 0.1.2 → 0.1.3

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.
Files changed (56) hide show
  1. package/LICENSE +19 -5
  2. package/dist/index.cjs +2338 -0
  3. package/dist/index.d.cts +524 -0
  4. package/dist/index.d.ts +524 -0
  5. package/dist/index.js +2251 -0
  6. package/package.json +21 -8
  7. package/src/components/Accordion.tsx +0 -52
  8. package/src/components/Avatar.tsx +0 -18
  9. package/src/components/Badge.tsx +0 -27
  10. package/src/components/Banner.tsx +0 -75
  11. package/src/components/Breadcrumb.tsx +0 -58
  12. package/src/components/Button.tsx +0 -47
  13. package/src/components/Card.tsx +0 -34
  14. package/src/components/ChatInput.tsx +0 -53
  15. package/src/components/Checkbox.tsx +0 -85
  16. package/src/components/CreditsIndicator.tsx +0 -41
  17. package/src/components/DataTable.tsx +0 -75
  18. package/src/components/DateInput.tsx +0 -57
  19. package/src/components/Divider.tsx +0 -12
  20. package/src/components/Dropzone.tsx +0 -94
  21. package/src/components/EmptyState.tsx +0 -65
  22. package/src/components/FileCard.tsx +0 -78
  23. package/src/components/FilterTabs.tsx +0 -49
  24. package/src/components/FlyoutMenu.tsx +0 -36
  25. package/src/components/GlassPopover.tsx +0 -38
  26. package/src/components/Header.tsx +0 -22
  27. package/src/components/Input.tsx +0 -18
  28. package/src/components/InputGroup.tsx +0 -37
  29. package/src/components/LanguageSelector.tsx +0 -81
  30. package/src/components/Modal.tsx +0 -104
  31. package/src/components/OnboardingPopover.tsx +0 -61
  32. package/src/components/OperationStatus.tsx +0 -73
  33. package/src/components/Overlay.tsx +0 -66
  34. package/src/components/Pagination.tsx +0 -89
  35. package/src/components/Pill.tsx +0 -19
  36. package/src/components/PricingCard.tsx +0 -74
  37. package/src/components/ProgressBar.tsx +0 -47
  38. package/src/components/Radio.tsx +0 -56
  39. package/src/components/SectionHeader.tsx +0 -32
  40. package/src/components/SegmentedControl.tsx +0 -42
  41. package/src/components/Select.tsx +0 -62
  42. package/src/components/SelectGroup.tsx +0 -32
  43. package/src/components/SelectionCard.tsx +0 -47
  44. package/src/components/SidebarItem.tsx +0 -27
  45. package/src/components/SidebarPanel.tsx +0 -84
  46. package/src/components/SplitPane.tsx +0 -85
  47. package/src/components/StatCard.tsx +0 -64
  48. package/src/components/StatusDot.tsx +0 -26
  49. package/src/components/Stepper.tsx +0 -40
  50. package/src/components/TabBar.tsx +0 -45
  51. package/src/components/Textarea.tsx +0 -43
  52. package/src/components/Toggle.tsx +0 -50
  53. package/src/components/Tooltip.tsx +0 -33
  54. package/src/components/UserProfilePopover.tsx +0 -100
  55. package/src/components/ValidationAlert.tsx +0 -72
  56. package/src/index.ts +0 -177
@@ -1,61 +0,0 @@
1
- import React from 'react';
2
-
3
- export type OnboardingPopoverProps = React.HTMLAttributes<HTMLDivElement> & {
4
- step: number;
5
- totalSteps: number;
6
- title: string;
7
- description: string;
8
- onNext?: () => void;
9
- onSkip?: () => void;
10
- nextLabel?: string;
11
- };
12
-
13
- export function OnboardingPopover({
14
- step,
15
- totalSteps,
16
- title,
17
- description,
18
- onNext,
19
- onSkip,
20
- nextLabel = 'Next',
21
- className,
22
- ...props
23
- }: OnboardingPopoverProps) {
24
- return (
25
- <div
26
- className={`malix-onboarding-popover${className ? ` ${className}` : ''}`}
27
- role="dialog"
28
- aria-label={`Step ${step} of ${totalSteps}: ${title}`}
29
- {...props}
30
- >
31
- <span className="malix-onboarding-popover__step">
32
- Step {step} of {totalSteps}
33
- </span>
34
-
35
- <h3 className="malix-onboarding-popover__title">{title}</h3>
36
-
37
- <p className="malix-onboarding-popover__description">{description}</p>
38
-
39
- <div className="malix-onboarding-popover__actions">
40
- {onSkip ? (
41
- <button
42
- type="button"
43
- className="malix-onboarding-popover__skip"
44
- onClick={onSkip}
45
- >
46
- Skip
47
- </button>
48
- ) : null}
49
- {onNext ? (
50
- <button
51
- type="button"
52
- className="malix-onboarding-popover__next-btn"
53
- onClick={onNext}
54
- >
55
- {nextLabel}
56
- </button>
57
- ) : null}
58
- </div>
59
- </div>
60
- );
61
- }
@@ -1,73 +0,0 @@
1
- import React from 'react';
2
-
3
- export type OperationStatusType = 'active' | 'completed' | 'failed' | 'pending';
4
-
5
- export type OperationStatusProps = React.HTMLAttributes<HTMLSpanElement> & {
6
- status: OperationStatusType;
7
- label?: string;
8
- };
9
-
10
- const DEFAULT_LABELS: Record<OperationStatusType, string> = {
11
- active: 'Active',
12
- completed: 'Completed',
13
- failed: 'Failed',
14
- pending: 'Pending',
15
- };
16
-
17
- function StatusIcon({ status }: { status: OperationStatusType }) {
18
- const shared = { width: 14, height: 14, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
19
-
20
- switch (status) {
21
- case 'active':
22
- // Blinking dot - filled circle, no stroke
23
- return (
24
- <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
25
- <circle cx="7" cy="7" r="4" />
26
- </svg>
27
- );
28
- case 'completed':
29
- return (
30
- <svg {...shared}>
31
- <circle cx="12" cy="12" r="10" />
32
- <path d="m9 12 2 2 4-4" />
33
- </svg>
34
- );
35
- case 'failed':
36
- return (
37
- <svg {...shared}>
38
- <circle cx="12" cy="12" r="10" />
39
- <path d="m15 9-6 6" />
40
- <path d="m9 9 6 6" />
41
- </svg>
42
- );
43
- case 'pending':
44
- return (
45
- <svg {...shared}>
46
- <circle cx="12" cy="12" r="10" />
47
- <polyline points="12 6 12 12 16 14" />
48
- </svg>
49
- );
50
- }
51
- }
52
-
53
- export function OperationStatus({
54
- status,
55
- label,
56
- className,
57
- ...props
58
- }: OperationStatusProps) {
59
- return (
60
- <span
61
- className={`malix-op-status${className ? ` ${className}` : ''}`}
62
- data-status={status}
63
- {...props}
64
- >
65
- <span className="malix-op-status__icon">
66
- <StatusIcon status={status} />
67
- </span>
68
- <span className="malix-op-status__label">
69
- {label ?? DEFAULT_LABELS[status]}
70
- </span>
71
- </span>
72
- );
73
- }
@@ -1,66 +0,0 @@
1
- import React, { useEffect, useRef } from 'react';
2
-
3
- const FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
4
-
5
- export type OverlayProps = {
6
- open: boolean;
7
- title: string;
8
- onClose: () => void;
9
- children: React.ReactNode;
10
- };
11
-
12
- export function Overlay({ open, title, onClose, children }: OverlayProps) {
13
- const panelRef = useRef<HTMLDivElement | null>(null);
14
-
15
- useEffect(() => {
16
- if (!open || !panelRef.current) return;
17
-
18
- const panel = panelRef.current;
19
- const focusables = Array.from(panel.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));
20
- const first = focusables[0];
21
- const last = focusables[focusables.length - 1];
22
-
23
- first?.focus();
24
-
25
- function onKeyDown(event: KeyboardEvent) {
26
- if (event.key === 'Escape') {
27
- event.preventDefault();
28
- onClose();
29
- }
30
-
31
- if (event.key === 'Tab' && focusables.length > 0) {
32
- if (event.shiftKey && document.activeElement === first) {
33
- event.preventDefault();
34
- last?.focus();
35
- } else if (!event.shiftKey && document.activeElement === last) {
36
- event.preventDefault();
37
- first?.focus();
38
- }
39
- }
40
- }
41
-
42
- document.addEventListener('keydown', onKeyDown);
43
- return () => document.removeEventListener('keydown', onKeyDown);
44
- }, [open, onClose]);
45
-
46
- if (!open) return null;
47
-
48
- return (
49
- <div className="malix-overlay-backdrop" onMouseDown={onClose}>
50
- <div
51
- ref={panelRef}
52
- className="malix-overlay-panel"
53
- role="dialog"
54
- aria-modal="true"
55
- aria-label={title}
56
- onMouseDown={(event) => event.stopPropagation()}
57
- >
58
- <h2 className="malix-overlay-title">{title}</h2>
59
- {children}
60
- <button type="button" className="malix-button malix-overlay-close" data-hierarchy="secondary" onClick={onClose}>
61
- Close
62
- </button>
63
- </div>
64
- </div>
65
- );
66
- }
@@ -1,89 +0,0 @@
1
- import React from 'react';
2
-
3
- export type PaginationVariant = 'full' | 'mini';
4
-
5
- export type PaginationProps = {
6
- currentPage: number;
7
- totalPages: number;
8
- onPageChange: (page: number) => void;
9
- variant?: PaginationVariant;
10
- className?: string;
11
- };
12
-
13
- function ChevronLeft() {
14
- return (
15
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
16
- <path d="M10 12L6 8L10 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
17
- </svg>
18
- );
19
- }
20
-
21
- function ChevronRight() {
22
- return (
23
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
24
- <path d="M6 4L10 8L6 12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
25
- </svg>
26
- );
27
- }
28
-
29
- export function Pagination({
30
- currentPage,
31
- totalPages,
32
- onPageChange,
33
- variant = 'full',
34
- className,
35
- }: PaginationProps) {
36
- const isFirstPage = currentPage <= 1;
37
- const isLastPage = currentPage >= totalPages;
38
-
39
- const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
40
-
41
- return (
42
- <nav
43
- className={`malix-pagination${className ? ` ${className}` : ''}`}
44
- data-variant={variant}
45
- aria-label="Pagination"
46
- >
47
- <button
48
- type="button"
49
- className="malix-pagination__arrow"
50
- data-disabled={isFirstPage || undefined}
51
- disabled={isFirstPage}
52
- onClick={() => onPageChange(currentPage - 1)}
53
- aria-label="Previous page"
54
- >
55
- <ChevronLeft />
56
- </button>
57
-
58
- {variant === 'full' ? (
59
- pages.map((page) => (
60
- <button
61
- key={page}
62
- type="button"
63
- className="malix-pagination__item"
64
- data-active={page === currentPage || undefined}
65
- aria-current={page === currentPage ? 'page' : undefined}
66
- onClick={() => onPageChange(page)}
67
- >
68
- {page}
69
- </button>
70
- ))
71
- ) : (
72
- <span className="malix-pagination__label">
73
- {currentPage} of {totalPages}
74
- </span>
75
- )}
76
-
77
- <button
78
- type="button"
79
- className="malix-pagination__arrow"
80
- data-disabled={isLastPage || undefined}
81
- disabled={isLastPage}
82
- onClick={() => onPageChange(currentPage + 1)}
83
- aria-label="Next page"
84
- >
85
- <ChevronRight />
86
- </button>
87
- </nav>
88
- );
89
- }
@@ -1,19 +0,0 @@
1
- import React from 'react';
2
-
3
- export type PillVariant = 'default' | 'primary' | 'success' | 'error' | 'warning' | 'info';
4
-
5
- export type PillProps = React.HTMLAttributes<HTMLSpanElement> & {
6
- variant?: PillVariant;
7
- };
8
-
9
- export function Pill({ variant = 'default', children, className, ...props }: PillProps) {
10
- return (
11
- <span
12
- className={`malix-pill${className ? ` ${className}` : ''}`}
13
- data-variant={variant}
14
- {...props}
15
- >
16
- {children}
17
- </span>
18
- );
19
- }
@@ -1,74 +0,0 @@
1
- import React from 'react';
2
-
3
- export type PricingCardProps = React.HTMLAttributes<HTMLDivElement> & {
4
- planName: string;
5
- price: string;
6
- period?: string;
7
- description?: string;
8
- features: string[];
9
- ctaLabel?: string;
10
- onCtaClick?: () => void;
11
- highlighted?: boolean;
12
- };
13
-
14
- export function PricingCard({
15
- planName,
16
- price,
17
- period = '/month',
18
- description,
19
- features,
20
- ctaLabel = 'Get Started',
21
- onCtaClick,
22
- highlighted = false,
23
- className,
24
- ...props
25
- }: PricingCardProps) {
26
- return (
27
- <div
28
- className={`malix-pricing-card${className ? ` ${className}` : ''}`}
29
- data-highlighted={highlighted || undefined}
30
- {...props}
31
- >
32
- <span className="malix-pricing-card__badge">{planName}</span>
33
-
34
- <div className="malix-pricing-card__price-row">
35
- <span className="malix-pricing-card__price">{price}</span>
36
- <span className="malix-pricing-card__period">{period}</span>
37
- </div>
38
-
39
- {description ? (
40
- <p className="malix-pricing-card__description">{description}</p>
41
- ) : null}
42
-
43
- <ul className="malix-pricing-card__features">
44
- {features.map((feature, i) => (
45
- <li key={i} className="malix-pricing-card__feature-item">
46
- <svg
47
- className="malix-pricing-card__check-icon"
48
- width="16"
49
- height="16"
50
- viewBox="0 0 24 24"
51
- fill="none"
52
- stroke="currentColor"
53
- strokeWidth="2"
54
- strokeLinecap="round"
55
- strokeLinejoin="round"
56
- aria-hidden="true"
57
- >
58
- <polyline points="20 6 9 17 4 12" />
59
- </svg>
60
- <span>{feature}</span>
61
- </li>
62
- ))}
63
- </ul>
64
-
65
- <button
66
- type="button"
67
- className="malix-pricing-card__cta"
68
- onClick={onCtaClick}
69
- >
70
- {ctaLabel}
71
- </button>
72
- </div>
73
- );
74
- }
@@ -1,47 +0,0 @@
1
- import React from 'react';
2
-
3
- export type ProgressBarVariant = 'default' | 'success';
4
-
5
- export type ProgressBarProps = React.HTMLAttributes<HTMLDivElement> & {
6
- value: number;
7
- label?: string;
8
- showPercent?: boolean;
9
- variant?: ProgressBarVariant;
10
- };
11
-
12
- export function ProgressBar({
13
- value,
14
- label,
15
- showPercent = true,
16
- variant = 'default',
17
- className,
18
- ...props
19
- }: ProgressBarProps) {
20
- const clampedValue = Math.max(0, Math.min(100, value));
21
-
22
- return (
23
- <div
24
- className={`malix-progress-bar${className ? ` ${className}` : ''}`}
25
- data-variant={variant}
26
- role="progressbar"
27
- aria-valuenow={clampedValue}
28
- aria-valuemin={0}
29
- aria-valuemax={100}
30
- aria-label={label}
31
- {...props}
32
- >
33
- {(label || showPercent) ? (
34
- <div className="malix-progress-bar__label-row">
35
- {label ? <span className="malix-progress-bar__label">{label}</span> : null}
36
- {showPercent ? <span className="malix-progress-bar__percent">{clampedValue}%</span> : null}
37
- </div>
38
- ) : null}
39
- <div className="malix-progress-bar__track">
40
- <div
41
- className="malix-progress-bar__fill"
42
- style={{ width: `${clampedValue}%` }}
43
- />
44
- </div>
45
- </div>
46
- );
47
- }
@@ -1,56 +0,0 @@
1
- import React from 'react';
2
-
3
- export type RadioProps = Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange'> & {
4
- checked?: boolean;
5
- onChange?: (value: string) => void;
6
- disabled?: boolean;
7
- label?: string;
8
- name?: string;
9
- value: string;
10
- };
11
-
12
- export function Radio({
13
- checked = false,
14
- onChange,
15
- disabled = false,
16
- label,
17
- name,
18
- value,
19
- className,
20
- ...props
21
- }: RadioProps) {
22
- const handleClick = () => {
23
- if (!disabled && onChange) {
24
- onChange(value);
25
- }
26
- };
27
-
28
- const radio = (
29
- <button
30
- type="button"
31
- role="radio"
32
- className={`malix-radio${className ? ` ${className}` : ''}`}
33
- data-checked={checked}
34
- data-disabled={disabled}
35
- aria-checked={checked}
36
- disabled={disabled}
37
- data-name={name}
38
- data-value={value}
39
- onClick={handleClick}
40
- {...props}
41
- >
42
- <span className="malix-radio__dot" />
43
- </button>
44
- );
45
-
46
- if (label) {
47
- return (
48
- <label className="malix-radio-row">
49
- {radio}
50
- <span className="malix-radio-row__label">{label}</span>
51
- </label>
52
- );
53
- }
54
-
55
- return radio;
56
- }
@@ -1,32 +0,0 @@
1
- import React from 'react';
2
-
3
- export type SectionHeaderProps = React.HTMLAttributes<HTMLDivElement> & {
4
- title: string;
5
- description?: string;
6
- actions?: React.ReactNode;
7
- };
8
-
9
- export function SectionHeader({
10
- title,
11
- description,
12
- actions,
13
- className,
14
- ...props
15
- }: SectionHeaderProps) {
16
- return (
17
- <div
18
- className={`malix-section-header${className ? ` ${className}` : ''}`}
19
- {...props}
20
- >
21
- <div className="malix-section-header__left">
22
- <h2 className="malix-section-header__title">{title}</h2>
23
- {description ? (
24
- <p className="malix-section-header__description">{description}</p>
25
- ) : null}
26
- </div>
27
- {actions ? (
28
- <div className="malix-section-header__actions">{actions}</div>
29
- ) : null}
30
- </div>
31
- );
32
- }
@@ -1,42 +0,0 @@
1
- import React from 'react';
2
-
3
- export type SegmentedControlItem = {
4
- label: string;
5
- value: string;
6
- };
7
-
8
- export type SegmentedControlProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
9
- items: SegmentedControlItem[];
10
- value: string;
11
- onChange: (value: string) => void;
12
- };
13
-
14
- export function SegmentedControl({
15
- items,
16
- value,
17
- onChange,
18
- className,
19
- ...props
20
- }: SegmentedControlProps) {
21
- return (
22
- <div
23
- className={`malix-segmented-control${className ? ` ${className}` : ''}`}
24
- role="radiogroup"
25
- {...props}
26
- >
27
- {items.map((item) => (
28
- <button
29
- key={item.value}
30
- type="button"
31
- className="malix-segmented-control__item"
32
- role="radio"
33
- aria-checked={item.value === value}
34
- data-active={item.value === value || undefined}
35
- onClick={() => onChange(item.value)}
36
- >
37
- {item.label}
38
- </button>
39
- ))}
40
- </div>
41
- );
42
- }
@@ -1,62 +0,0 @@
1
- import React from 'react';
2
-
3
- export type SelectOption = {
4
- value: string;
5
- label: string;
6
- };
7
-
8
- export type SelectProps = Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'onChange'> & {
9
- placeholder?: string;
10
- options?: SelectOption[];
11
- onChange?: (value: string) => void;
12
- filled?: boolean;
13
- };
14
-
15
- export function Select({
16
- value,
17
- placeholder,
18
- options = [],
19
- onChange,
20
- disabled,
21
- filled,
22
- className,
23
- ...props
24
- }: SelectProps) {
25
- return (
26
- <div
27
- className={`malix-select${className ? ` ${className}` : ''}`}
28
- data-filled={filled || undefined}
29
- data-disabled={disabled || undefined}
30
- >
31
- <select
32
- className="malix-select__native"
33
- value={value}
34
- disabled={disabled}
35
- onChange={(e) => onChange?.(e.target.value)}
36
- {...props}
37
- >
38
- {placeholder ? (
39
- <option value="" disabled>
40
- {placeholder}
41
- </option>
42
- ) : null}
43
- {options.map((opt) => (
44
- <option key={opt.value} value={opt.value}>
45
- {opt.label}
46
- </option>
47
- ))}
48
- </select>
49
- <span className="malix-select__icon">
50
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
51
- <path
52
- d="M4 6L8 10L12 6"
53
- stroke="currentColor"
54
- strokeWidth="1.5"
55
- strokeLinecap="round"
56
- strokeLinejoin="round"
57
- />
58
- </svg>
59
- </span>
60
- </div>
61
- );
62
- }
@@ -1,32 +0,0 @@
1
- import React from 'react';
2
-
3
- export type SelectGroupProps = React.HTMLAttributes<HTMLDivElement> & {
4
- label?: string;
5
- helperText?: string;
6
- error?: boolean;
7
- };
8
-
9
- export function SelectGroup({
10
- label,
11
- helperText,
12
- error,
13
- children,
14
- className,
15
- ...props
16
- }: SelectGroupProps) {
17
- return (
18
- <div
19
- className={`malix-select-group${className ? ` ${className}` : ''}`}
20
- data-error={error || undefined}
21
- {...props}
22
- >
23
- {label ? (
24
- <span className="malix-select-group__label">{label}</span>
25
- ) : null}
26
- {children}
27
- {helperText ? (
28
- <span className="malix-select-group__helper">{helperText}</span>
29
- ) : null}
30
- </div>
31
- );
32
- }