@opencxh/ui-kit 3.103.0 → 3.106.0

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.
@@ -34,16 +34,10 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
34
34
  *
35
35
  * @example
36
36
  * ```tsx
37
- * <Button variant="primary" size="md">
38
- * Click me
39
- * </Button>
40
- *
41
- * <Button variant="outline" leftIcon={<PlusIcon />}>
42
- * Add item
43
- * </Button>
44
- *
45
- * <Button iconOnly variant="ghost" size="sm">
46
- * <SearchIcon />
37
+ * <Button variant="primary" size="md">Click me</Button>
38
+ * <Button variant="outline" leftIcon={<Icon name={Plus} />}>Add item</Button>
39
+ * <Button iconOnly variant="ghost" size="sm" aria-label="Zoeken">
40
+ * <Icon name={Search} />
47
41
  * </Button>
48
42
  * ```
49
43
  */
@@ -13,7 +13,7 @@ export interface FilterChipProps {
13
13
  }
14
14
  /**
15
15
  * Filter chip — the inbox filter bar and the thread priority/assign/inbox/tags
16
- * menus. Presentational: it renders the chip (active = filled dark, inactive =
16
+ * menus. Presentational: it renders the chip (active = filled accent, inactive =
17
17
  * outlined) with an optional caret + clear; the consumer wires the actual menu
18
18
  * with the existing `Dropdown` / `Popover`.
19
19
  *
@@ -23,4 +23,4 @@ export interface FilterChipProps {
23
23
  * active={!!status} onClick={openMenu} onClear={() => setStatus(null)} />
24
24
  * ```
25
25
  */
26
- export declare function FilterChip({ label, active, caret, onClear, onClick, className }: FilterChipProps): React.JSX.Element;
26
+ export declare function FilterChip({ label, active, caret, onClear, onClick, className, }: FilterChipProps): React.JSX.Element;
@@ -16,6 +16,7 @@ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement>
16
16
  children: React.ReactNode;
17
17
  }
18
18
  /**
19
- * Link component with theme integration and accessibility features
19
+ * Link component with theme integration and accessibility features.
20
+ * Use for navigation; use Button for actions.
20
21
  */
21
22
  export declare const Link: React.FC<LinkProps>;
@@ -15,7 +15,7 @@ export interface SegmentedToggleProps<T extends string> {
15
15
  }
16
16
  /**
17
17
  * Segmented pill toggle (focus "Feed / Eén tegelijk", settings "Persoonlijk /
18
- * Bedrijf"). The active segment lifts with a subtle shadow. Token-driven.
18
+ * Bedrijf"). Track = surface-hover, active segment = surface. No shadow.
19
19
  *
20
20
  * @example
21
21
  * ```tsx
@@ -2,7 +2,7 @@ import { default as React } from 'react';
2
2
  export interface AssistantCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
3
3
  /** Card heading (e.g. "Briefing van je assistent", "Voorstel van de assistent"). */
4
4
  title: React.ReactNode;
5
- /** Leading glyph; defaults to the sparkle. */
5
+ /** Leading icon; defaults to the lucide Sparkles icon. */
6
6
  icon?: React.ReactNode;
7
7
  /** Optional action rendered on the header's right (e.g. a "Gebruiken" button). */
8
8
  action?: React.ReactNode;
@@ -10,7 +10,7 @@ export interface AssistantCardProps extends Omit<React.HTMLAttributes<HTMLDivEle
10
10
  children?: React.ReactNode;
11
11
  }
12
12
  /**
13
- * AI-assistant card shell — the tinted "Briefing / Voorstel van de assistent"
13
+ * AI-assistant card shell — the tinted "Briefing / Voorstel van de assistent"
14
14
  * surface used on Mijn dag and in the Focus queue. Uses the `--assistant-*`
15
15
  * design-system tokens so the tint is mode-aware.
16
16
  *
@@ -15,7 +15,4 @@ export interface IconProps {
15
15
  /** Accessibility label */
16
16
  'aria-label'?: string;
17
17
  }
18
- /**
19
- * Icon component that works with Lucide React icons and provides theme integration
20
- */
21
18
  export declare const Icon: React.FC<IconProps>;
@@ -0,0 +1,105 @@
1
+ import { default as React } from 'react';
2
+ export interface ListGroup {
3
+ /** Group key — must match what `groupBy` returns */
4
+ id: string;
5
+ /** Header label; defaults to `id` */
6
+ title?: string;
7
+ /** Override the row count shown on the right */
8
+ count?: number;
9
+ /** Start collapsed (only with `collapsible`) */
10
+ defaultCollapsed?: boolean;
11
+ }
12
+ export interface ListProps<T> {
13
+ /** Rows to render */
14
+ items: T[];
15
+ /** Stable key per row */
16
+ getRowKey?: (item: T, index: number) => string | number;
17
+ /** Row separation */
18
+ variant?: "plain" | "divided" | "bulleted";
19
+ /** Leading slot — channel tile, avatar, status dot */
20
+ leading?: (item: T, index: number) => React.ReactNode;
21
+ /** Main content; defaults to `String(item)` */
22
+ renderItem?: (item: T, index: number) => React.ReactNode;
23
+ /** Trailing slot — timestamp, badge, counter */
24
+ trailing?: (item: T, index: number) => React.ReactNode;
25
+ /** Row click */
26
+ onSelect?: (item: T, index: number) => void;
27
+ /** Highlighted row (accent wash) */
28
+ isActive?: (item: T, index: number) => boolean;
29
+ /** Bold + accent dot */
30
+ unread?: (item: T, index: number) => boolean;
31
+ /** Deprioritised noise (opacity) */
32
+ dimmed?: (item: T, index: number) => boolean;
33
+ /** Group rows under headers. Return the group id for each row. */
34
+ groupBy?: (item: T, index: number) => string;
35
+ /**
36
+ * Group order and labels. Groups missing here are appended in order of first
37
+ * appearance; groups listed here but empty are skipped.
38
+ */
39
+ groups?: ListGroup[];
40
+ /** Header renderer; defaults to label + count */
41
+ renderGroupHeader?: (group: ListGroup, items: T[]) => React.ReactNode;
42
+ /** Headers stick to the top of the scroll container */
43
+ stickyGroupHeaders?: boolean;
44
+ /** Headers become a toggle that folds the group */
45
+ collapsibleGroups?: boolean;
46
+ /** Hide the count on the right of the header */
47
+ hideGroupCount?: boolean;
48
+ /** Checkbox column + bulk bar */
49
+ selectable?: boolean;
50
+ /** Selected rows (controlled) */
51
+ selectedItems?: T[];
52
+ /** Selection handler */
53
+ onSelectionChange?: (selected: T[]) => void;
54
+ /** Actions shown in the bulk bar when a selection exists */
55
+ bulkActions?: React.ReactNode;
56
+ /**
57
+ * Column-label strip above the rows ("Van · Gesprek · tijd"), like the inbox.
58
+ * Align it with the row by reusing the same widths as `renderItem`.
59
+ */
60
+ header?: React.ReactNode;
61
+ /** Keep the column-label strip visible while scrolling */
62
+ stickyHeader?: boolean;
63
+ /** Wrap the list in a bordered container */
64
+ bordered?: boolean;
65
+ /** Empty state content */
66
+ emptyContent?: React.ReactNode;
67
+ /** Loading state */
68
+ loading?: boolean;
69
+ /** Number of skeleton rows while loading */
70
+ loadingRows?: number;
71
+ className?: string;
72
+ "aria-label"?: string;
73
+ }
74
+ /**
75
+ * List — one row is one object you open, with content of varying length
76
+ * (inbox conversations, notifications, search results). No column headers:
77
+ * hierarchy lives inside the row.
78
+ *
79
+ * Use `Table` instead when you compare values between rows (sortable columns,
80
+ * aligned amounts, select-all in a header).
81
+ *
82
+ * Grouped, like the inbox and task views:
83
+ *
84
+ * @example
85
+ * ```tsx
86
+ * <List
87
+ * items={tasks}
88
+ * getRowKey={(t) => t.id}
89
+ * bordered
90
+ * groupBy={(t) => t.bucket} // "today" | "tomorrow" | "later"
91
+ * groups={[
92
+ * { id: "today", title: "Vandaag" },
93
+ * { id: "tomorrow", title: "Morgen" },
94
+ * { id: "later", title: "Later" },
95
+ * ]}
96
+ * stickyGroupHeaders
97
+ * collapsibleGroups
98
+ * leading={(t) => <ChannelBadge channel={t.channel} size="sm" />}
99
+ * renderItem={(t) => <span className="truncate">{t.title}</span>}
100
+ * trailing={(t) => t.due}
101
+ * unread={(t) => !t.read}
102
+ * />
103
+ * ```
104
+ */
105
+ export declare function List<T>({ items, getRowKey, variant, leading, renderItem, trailing, onSelect, isActive, unread, dimmed, groupBy, groups, renderGroupHeader, stickyGroupHeaders, collapsibleGroups, hideGroupCount, selectable, selectedItems, onSelectionChange, bulkActions, header, stickyHeader, bordered, emptyContent, loading, loadingRows, className, "aria-label": ariaLabel, }: ListProps<T>): React.JSX.Element;
@@ -18,7 +18,7 @@ export interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLDivElemen
18
18
  *
19
19
  * @example
20
20
  * ```tsx
21
- * <EmptyState card tone="success" icon=""
21
+ * <EmptyState card tone="success" icon={<Icon icon={Check} size="lg" />}
22
22
  * title="Wachtrij leeg — 7 afgehandeld"
23
23
  * description="Nieuwe gesprekken verschijnen hier vanzelf."
24
24
  * actions={<Button>Terug naar Mijn dag</Button>} />
@@ -6,16 +6,16 @@ export { Button, type ButtonProps } from './action/Button';
6
6
  export { ButtonGroup, type ButtonGroupProps } from './action/ButtonGroup';
7
7
  export { FilterChip, type FilterChipProps } from './action/FilterChip';
8
8
  export { Link, type LinkProps } from './action/Link';
9
- export { SegmentedToggle, type SegmentedToggleProps, type SegmentedOption } from './action/SegmentedToggle';
10
- export { SplitButton, type SplitButtonProps, type SplitButtonOption } from './action/SplitButton';
9
+ export { SegmentedToggle, type SegmentedOption, type SegmentedToggleProps } from './action/SegmentedToggle';
10
+ export { SplitButton, type SplitButtonOption, type SplitButtonProps } from './action/SplitButton';
11
11
  export { Checkbox, type CheckboxProps } from './input/Checkbox';
12
12
  export { DatePicker, type DatePickerProps } from './input/DatePicker';
13
+ export { FolderSelect, type FolderDestination, type FolderSelectProps } from './input/FolderSelect';
13
14
  export { SearchableTextField, type SearchableTextFieldProps } from './input/SearchableTextField';
14
15
  export { Select, type SelectOption, type SelectProps } from './input/Select';
16
+ export { StorageInput, type StorageInputProps } from './input/StorageInput';
15
17
  export { TextArea, type TextAreaProps } from './input/TextArea';
16
18
  export { TextField, type TextFieldProps } from './input/TextField';
17
- export { StorageInput, type StorageInputProps } from './input/StorageInput';
18
- export { FolderSelect, type FolderSelectProps, type FolderDestination } from './input/FolderSelect';
19
19
  export { Form, type FormButtonProps, type FormFieldType, type FormGroup, type FormGroupItem, type FormProps } from './forms/Form';
20
20
  export { Dropdown, type DropdownOption, type DropdownProps } from './overlays/Dropdown';
21
21
  export { Modal, type ModalProps } from './overlays/Modal';
@@ -28,20 +28,20 @@ export { ProgressBar, type ProgressBarProps } from './feedback/ProgressBar';
28
28
  export { Spinner, type SpinnerProps } from './feedback/Spinner';
29
29
  export { AssistantCard, type AssistantCardProps } from './content/AssistantCard';
30
30
  export { Avatar, type AvatarProps } from './content/Avatar';
31
- export { AvatarStack, type AvatarStackProps, type AvatarStackPerson } from './content/AvatarStack';
31
+ export { AvatarStack, type AvatarStackPerson, type AvatarStackProps } from './content/AvatarStack';
32
32
  export { ChannelBadge, type ChannelBadgeProps, type ChannelKey } from './content/ChannelBadge';
33
33
  export { Icon, type IconProps } from './content/Icon';
34
- export { KpiCard, type KpiCardProps } from './content/KpiCard';
35
- export { SourceChip, type SourceChipProps } from './content/SourceChip';
36
34
  export { Image, type ImageProps } from './content/Image';
35
+ export { List, type ListProps } from './content/List';
36
+ export { KpiCard, type KpiCardProps } from './content/KpiCard';
37
37
  export { PageHeader, type PageHeaderAction, type PageHeaderProps } from './content/PageHeader';
38
38
  export { PageToolbar, type PageToolbarProps } from './content/PageToolbar';
39
+ export { SourceChip, type SourceChipProps } from './content/SourceChip';
39
40
  export { Table, type TableAction, type TableColumn, type TableFilter, type TableProps } from './content/Table';
40
41
  export { View, type ViewGroup, type ViewProps } from './content/View';
41
42
  export { SidebarMenu, type MenuItem } from './navigation/Sidebar';
42
43
  export { TabBar, Tabs, type TabItem, type TabsProps } from './navigation/Tabs';
43
44
  export { Heading, type HeadingProps } from './typography/Heading';
44
- export { List, type ListItem, type ListProps } from './typography/List';
45
45
  export { Text, type TextProps } from './typography/Text';
46
46
  export * from './command-palette';
47
47
  export * from './primitives/Box';
@@ -30,26 +30,15 @@ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputE
30
30
  labelClassName?: string;
31
31
  }
32
32
  /**
33
- * Checkbox component with theme integration
33
+ * Checkbox component with theme integration.
34
+ *
35
+ * Uses the native input with `accent-color`, so the checked fill is the accent
36
+ * token and dark mode needs no extra classes.
34
37
  *
35
38
  * @example
36
39
  * ```tsx
37
- * <Checkbox label="Accept terms and conditions" />
38
- *
39
- * <Checkbox
40
- * label="Subscribe to newsletter"
41
- * helperText="You can unsubscribe at any time"
42
- * />
43
- *
44
- * <Checkbox
45
- * label="Required field"
46
- * error="This field is required"
47
- * />
48
- *
49
- * <Checkbox
50
- * label="Select all"
51
- * indeterminate={true}
52
- * />
40
+ * <Checkbox label="Voorwaarden accepteren" />
41
+ * <Checkbox label="Alles selecteren" indeterminate />
53
42
  * ```
54
43
  */
55
44
  export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
@@ -41,28 +41,16 @@ export interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInput
41
41
  */
42
42
  labelClassName?: string;
43
43
  }
44
+ /** Shared with TextArea / Select / DatePicker: uppercase section label. */
45
+ export declare const fieldLabelClasses = "mb-1.5 block text-xs font-semibold uppercase tracking-label";
44
46
  /**
45
47
  * TextField component with theme integration and validation states
46
48
  *
47
49
  * @example
48
50
  * ```tsx
49
- * <TextField
50
- * label="Email"
51
- * placeholder="Enter your email"
52
- * type="email"
53
- * />
54
- *
55
- * <TextField
56
- * label="Search"
57
- * startIcon={<SearchIcon />}
58
- * placeholder="Search..."
59
- * />
60
- *
61
- * <TextField
62
- * label="Password"
63
- * type="password"
64
- * error="Password is required"
65
- * />
51
+ * <TextField label="E-mail" type="email" placeholder="naam@bedrijf.nl" />
52
+ * <TextField label="Zoeken" startIcon={<Icon icon={Search} />} />
53
+ * <TextField label="Wachtwoord" type="password" error="Verplicht veld" />
66
54
  * ```
67
55
  */
68
56
  export declare const TextField: React.ForwardRefExoticComponent<TextFieldProps & React.RefAttributes<HTMLInputElement>>;
@@ -34,14 +34,9 @@ export interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
34
34
  *
35
35
  * @example
36
36
  * ```tsx
37
- * <Box padding="md" background="primary" radius="lg">
37
+ * <Box padding="md" background="module" radius="lg" border="sm" borderColor="neutral">
38
38
  * Content
39
39
  * </Box>
40
- *
41
- * <Box as="section" padding="lg" shadow="md">
42
- * <h2>Section Title</h2>
43
- * <p>Section content</p>
44
- * </Box>
45
40
  * ```
46
41
  */
47
42
  export declare const Box: React.ForwardRefExoticComponent<BoxProps & React.RefAttributes<HTMLDivElement>>;
@@ -3,4 +3,7 @@ export interface CardProps extends BoxProps {
3
3
  children: React.ReactNode;
4
4
  title?: string;
5
5
  }
6
+ /**
7
+ * Card — panel on a page background. Border, never a shadow (radius-lg = 12px).
8
+ */
6
9
  export declare const Card: ({ children, title, ...props }: CardProps) => import("react").JSX.Element;
@@ -17,7 +17,4 @@ export interface HeadingProps {
17
17
  /** Child content */
18
18
  children: React.ReactNode;
19
19
  }
20
- /**
21
- * Heading component with semantic HTML and theme integration
22
- */
23
20
  export declare const Heading: React.FC<HeadingProps>;
@@ -25,7 +25,4 @@ export interface TextProps {
25
25
  /** Child content */
26
26
  children: React.ReactNode;
27
27
  }
28
- /**
29
- * Text component with theme integration and typography variants
30
- */
31
28
  export declare const Text: React.FC<TextProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/ui-kit",
3
- "version": "3.103.0",
3
+ "version": "3.106.0",
4
4
  "description": "Theme-aware UI component library for OpenCXH platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,31 +0,0 @@
1
- import { default as React } from 'react';
2
- export interface ListItem {
3
- /** Unique identifier */
4
- id?: string;
5
- /** List item content */
6
- content: React.ReactNode;
7
- /** Whether the item is disabled */
8
- disabled?: boolean;
9
- /** Click handler for interactive lists */
10
- onClick?: () => void;
11
- }
12
- export interface ListProps {
13
- /** List items */
14
- items: ListItem[];
15
- /** List type */
16
- type?: 'unordered' | 'ordered' | 'description';
17
- /** List variant */
18
- variant?: 'default' | 'flush' | 'bordered' | 'divided';
19
- /** List size */
20
- size?: 'sm' | 'md' | 'lg';
21
- /** Whether list items are interactive */
22
- interactive?: boolean;
23
- /** Additional CSS classes */
24
- className?: string;
25
- /** Additional CSS classes for list items */
26
- itemClassName?: string;
27
- }
28
- /**
29
- * List component with theme integration and multiple variants
30
- */
31
- export declare const List: React.FC<ListProps>;