@opencxh/ui-kit 1.0.0 → 3.5.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.
@@ -17,6 +17,8 @@ export interface CommandPaletteProps {
17
17
  close?: string;
18
18
  noCommandsFound?: string;
19
19
  };
20
+ initialCommandPath?: string[];
21
+ initialActiveIndex?: number;
20
22
  }
21
23
  declare const CommandPalette: React.FC<CommandPaletteProps>;
22
24
  export default CommandPalette;
@@ -35,6 +35,10 @@ export interface PageHeaderProps {
35
35
  onBack?: () => void;
36
36
  /** Back button class name */
37
37
  backClassName?: string;
38
+ /** Whether the title is editable */
39
+ editable?: boolean;
40
+ /** Callback when title is changed */
41
+ onTitleChange?: (newTitle: string) => void;
38
42
  }
39
43
  export declare const ChevronLeftIcon: () => import("react/jsx-runtime").JSX.Element;
40
44
  /**
@@ -15,9 +15,9 @@ export interface TableColumn<T = any> {
15
15
  /** Whether column is searchable */
16
16
  searchable?: boolean;
17
17
  /** Column alignment */
18
- align?: 'left' | 'center' | 'right';
18
+ align?: "left" | "center" | "right";
19
19
  /** Whether column is sticky */
20
- sticky?: 'left' | 'right';
20
+ sticky?: "left" | "right";
21
21
  /** Custom header renderer */
22
22
  headerCell?: () => React.ReactNode;
23
23
  }
@@ -33,7 +33,7 @@ export interface TableAction<T = any> {
33
33
  /** Whether action is disabled for this row */
34
34
  disabled?: (row: T) => boolean;
35
35
  /** Action variant */
36
- variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive';
36
+ variant?: "primary" | "secondary" | "outline" | "ghost" | "destructive";
37
37
  }
38
38
  export interface TableFilter {
39
39
  /** Filter identifier */
@@ -41,7 +41,7 @@ export interface TableFilter {
41
41
  /** Filter label */
42
42
  label: string;
43
43
  /** Filter type */
44
- type?: 'select' | 'date' | 'dateRange';
44
+ type?: "select" | "date" | "dateRange";
45
45
  /** Filter options (for select type) */
46
46
  options?: Array<{
47
47
  value: string;
@@ -90,7 +90,7 @@ export interface TableProps<T = any> {
90
90
  /** Empty state content */
91
91
  emptyContent?: React.ReactNode;
92
92
  /** Table size */
93
- size?: 'sm' | 'md' | 'lg';
93
+ size?: "sm" | "md" | "lg";
94
94
  /** Whether to show row hover */
95
95
  hoverable?: boolean;
96
96
  /** Whether to show row borders */
@@ -0,0 +1,66 @@
1
+ import { default as React } from 'react';
2
+ export type ViewFieldType = "text" | "email" | "password" | "number" | "tel" | "url" | "textarea" | "select" | "checkbox" | "radio" | "date" | "custom" | "array";
3
+ type NestedKeys<T> = {
4
+ [K in keyof T]: T[K] extends object ? `${K & string}.${NestedKeys<T[K]>}` : K & string;
5
+ }[keyof T];
6
+ export interface ViewGroupItem<T = any> {
7
+ /** Field name (key in data) */
8
+ name: NestedKeys<T>;
9
+ /** Field label */
10
+ label: string;
11
+ /** Field type */
12
+ type: ViewFieldType;
13
+ /** Field width (CSS width value or grid columns) */
14
+ width?: string | number;
15
+ /** Options for select/radio/checkbox types */
16
+ options?: Array<{
17
+ value: string | number;
18
+ label: string;
19
+ }>;
20
+ /** Conditional function to show/hide field */
21
+ conditional?: (data: T) => boolean;
22
+ /** Whether field is hidden */
23
+ hidden?: boolean;
24
+ /** Custom component renderer */
25
+ customComponent?: (props: {
26
+ value: any;
27
+ }) => React.ReactNode;
28
+ /** Format function for display value */
29
+ format?: (value: any, data: T) => string | React.ReactNode;
30
+ /** For 'array' type, defines the fields for each item in the array */
31
+ arrayFields?: ViewGroupItem<any>[];
32
+ }
33
+ export interface ViewGroup<T = any> {
34
+ /** Group identifier */
35
+ id: string;
36
+ /** Group title */
37
+ title: string;
38
+ /** Group description */
39
+ description?: string;
40
+ /** Group items */
41
+ items: ViewGroupItem<T>[];
42
+ /** Conditional function to show/hide group */
43
+ conditional?: (data: T) => boolean;
44
+ /** Group layout */
45
+ layout?: "grid" | "flex";
46
+ /** Number of columns for grid layout */
47
+ columns?: number;
48
+ /** Additional CSS classes */
49
+ className?: string;
50
+ }
51
+ export interface ViewProps<T = Record<string, any>> {
52
+ /** View groups */
53
+ groups: ViewGroup<T>[];
54
+ /** Data to display */
55
+ data: T;
56
+ /** View size */
57
+ size?: "sm" | "md" | "lg" | "full";
58
+ /** Additional CSS classes */
59
+ className?: string;
60
+ }
61
+ /**
62
+ * Generic View component with groups and conditional rendering
63
+ * Displays data in a read-only format matching the Form component layout
64
+ */
65
+ export declare const View: <T extends Record<string, any>>({ groups, data, size, className, }: ViewProps<T>) => import("react/jsx-runtime").JSX.Element;
66
+ export {};
@@ -0,0 +1,17 @@
1
+ import { ErrorInfo, ReactNode, Component } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ fallback?: ReactNode;
5
+ name?: string;
6
+ }
7
+ interface State {
8
+ hasError: boolean;
9
+ error: Error | null;
10
+ }
11
+ export declare class ErrorBoundary extends Component<Props, State> {
12
+ state: State;
13
+ static getDerivedStateFromError(error: Error): State;
14
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
15
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
16
+ }
17
+ export {};
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ interface FederatedResourceProps {
3
+ identifier: string;
4
+ resourceLoader: () => Promise<any>;
5
+ framework?: 'react' | 'svelte' | 'vanilla';
6
+ fallback?: React.ReactNode;
7
+ componentProps?: Record<string, any>;
8
+ className?: string;
9
+ }
10
+ export declare function FederatedResource({ identifier, resourceLoader, framework, fallback, componentProps, className, }: FederatedResourceProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -1,8 +1,12 @@
1
+ import { InternalSDK } from '@opencxh/domain';
1
2
  import { default as React } from 'react';
2
- export type FormFieldType = "text" | "email" | "password" | "number" | "tel" | "url" | "textarea" | "select" | "checkbox" | "radio" | "date" | "custom" | "array";
3
+ export type FormFieldType = "text" | "email" | "password" | "number" | "tel" | "url" | "textarea" | "select" | "checkbox" | "radio" | "date" | "file" | "custom" | "array";
4
+ type NestedKeys<T> = {
5
+ [K in keyof T]: T[K] extends object ? `${K & string}.${NestedKeys<T[K]>}` : K & string;
6
+ }[keyof T];
3
7
  export interface FormGroupItem<T = any> {
4
8
  /** Field name (key in form data) */
5
- name: keyof T;
9
+ name: NestedKeys<T>;
6
10
  /** Field label */
7
11
  label: string;
8
12
  /** Field type */
@@ -50,6 +54,7 @@ export interface FormGroupItem<T = any> {
50
54
  searchable?: boolean;
51
55
  /** For 'select' type, whether the select should be multiple */
52
56
  multiple?: boolean;
57
+ allowCreate?: boolean;
53
58
  }
54
59
  export interface FormGroup<T = any> {
55
60
  /** Group identifier */
@@ -112,8 +117,11 @@ export interface FormProps<T = Record<string, any>> {
112
117
  className?: string;
113
118
  /** Form ref */
114
119
  ref?: React.RefObject<HTMLFormElement>;
120
+ /** SDK instance */
121
+ sdk?: InternalSDK<any>;
115
122
  }
116
123
  /**
117
124
  * Generic Form component with groups, validation, and conditional rendering
118
125
  */
119
- export declare const Form: <T extends Record<string, any>>({ groups, data: externalData, onSubmit, onCancel, onChange, transform, validate, submitButton, cancelButton, showButtons, layout, size, loading, className, ref, }: FormProps<T>) => import("react/jsx-runtime").JSX.Element;
126
+ export declare const Form: <T extends Record<string, any>>({ groups, data: externalData, onSubmit, onCancel, onChange, transform, validate, submitButton, cancelButton, showButtons, layout, size, loading, className, ref, sdk, }: FormProps<T>) => import("react/jsx-runtime").JSX.Element;
127
+ export {};
@@ -4,19 +4,22 @@ export { ButtonGroup, type ButtonGroupProps } from './action/ButtonGroup';
4
4
  export { Link, type LinkProps } from './action/Link';
5
5
  export { Checkbox, type CheckboxProps } from './input/Checkbox';
6
6
  export { DatePicker, type DatePickerProps } from './input/DatePicker';
7
+ export { SearchableTextField, type SearchableTextFieldProps } from './input/SearchableTextField';
7
8
  export { Select, type SelectOption, type SelectProps } from './input/Select';
8
9
  export { TextArea, type TextAreaProps } from './input/TextArea';
9
10
  export { TextField, type TextFieldProps } from './input/TextField';
10
- export { Form, type FormButtonProps, type FormFieldType, type FormGroup, type FormGroupItem, type FormProps, } from './forms/Form';
11
- export { Dropdown, type DropdownOption, type DropdownProps, } from './overlays/Dropdown';
11
+ export { StorageInput, type StorageInputProps } from './input/StorageInput';
12
+ export { Form, type FormButtonProps, type FormFieldType, type FormGroup, type FormGroupItem, type FormProps } from './forms/Form';
13
+ export { Dropdown, type DropdownOption, type DropdownProps } from './overlays/Dropdown';
12
14
  export { Modal, type ModalProps } from './overlays/Modal';
13
15
  export { Badge, type BadgeProps } from './feedback/Badge';
14
16
  export { ContentLoading } from './feedback/ContentLoading';
15
17
  export { Spinner, type SpinnerProps } from './feedback/Spinner';
16
18
  export { Icon, type IconProps } from './content/Icon';
17
19
  export { Image, type ImageProps } from './content/Image';
18
- export { PageHeader, type PageHeaderAction, type PageHeaderProps, } from './content/PageHeader';
19
- export { Table, type TableAction, type TableColumn, type TableFilter, type TableProps, } from './content/Table';
20
+ export { PageHeader, type PageHeaderAction, type PageHeaderProps } from './content/PageHeader';
21
+ export { Table, type TableAction, type TableColumn, type TableFilter, type TableProps } from './content/Table';
22
+ export { View, type ViewGroup, type ViewProps } from './content/View';
20
23
  export { SidebarMenu, type MenuItem } from './navigation/Sidebar';
21
24
  export { TabBar, Tabs, type TabItem, type TabsProps } from './navigation/Tabs';
22
25
  export { Heading, type HeadingProps } from './typography/Heading';
@@ -26,3 +29,5 @@ export * from './command-palette';
26
29
  export * from './primitives/Box';
27
30
  export * from './primitives/Card';
28
31
  export * from './typography/Text';
32
+ export { FederatedResource } from './federated-resource/index';
33
+ export { ErrorBoundary } from './error-boundary/index';
@@ -0,0 +1,21 @@
1
+ import { default as React } from 'react';
2
+ export interface SearchableTextFieldOption {
3
+ value: string;
4
+ label: string;
5
+ }
6
+ export interface SearchableTextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "onSelect"> {
7
+ label?: string;
8
+ helperText?: string;
9
+ error?: string;
10
+ size?: "sm" | "md" | "lg" | "full";
11
+ fullWidth?: boolean;
12
+ startIcon?: React.ReactNode;
13
+ loading?: boolean;
14
+ containerClassName?: string;
15
+ labelClassName?: string;
16
+ options: SearchableTextFieldOption[];
17
+ onRemoteSearch?: (searchTerm: string) => Promise<void>;
18
+ onSelect?: (value: string) => void;
19
+ debounceTime?: number;
20
+ }
21
+ export declare const SearchableTextField: React.ForwardRefExoticComponent<SearchableTextFieldProps & React.RefAttributes<HTMLInputElement>>;
@@ -5,85 +5,22 @@ export interface SelectOption {
5
5
  disabled?: boolean;
6
6
  }
7
7
  export interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
8
- /**
9
- * The value of the select field.
10
- * For multi-select, this is an array of strings.
11
- */
12
8
  value?: string | string[];
13
- /**
14
- * Callback function when the value changes.
15
- * For multi-select, this returns an array of strings.
16
- */
17
9
  onChange?: (value: string | string[]) => void;
18
- /**
19
- * The label for the select field
20
- */
21
10
  label?: string;
22
- /**
23
- * Helper text to display below the select
24
- */
25
11
  helperText?: string;
26
- /**
27
- * Error message to display when the select is invalid
28
- */
29
12
  error?: string;
30
- /**
31
- * The size of the select field
32
- */
33
13
  size?: "sm" | "md" | "lg" | "full";
34
- /**
35
- * Whether the select should take the full width of its container
36
- */
37
14
  fullWidth?: boolean;
38
- /**
39
- * The options for the select
40
- */
41
15
  options: SelectOption[];
42
- /**
43
- * Placeholder text when no option is selected
44
- */
45
16
  placeholder?: string;
46
- /**
47
- * Additional class name for the container
48
- */
49
17
  containerClassName?: string;
50
- /**
51
- * Additional class name for the label
52
- */
53
18
  labelClassName?: string;
54
- /**
55
- * Whether the select should be searchable
56
- */
57
19
  searchable?: boolean;
58
- /**
59
- * Multiple select
60
- */
61
20
  multiple?: boolean;
21
+ /** Vrije invoer toestaan (Enter of klik op “Voeg toe…”) */
22
+ allowCreate?: boolean;
23
+ /** Optioneel: zelf bepalen hoe een nieuwe optie eruit ziet */
24
+ onCreateOption?: (label: string) => SelectOption;
62
25
  }
63
- /**
64
- * Select component with theme integration
65
- *
66
- * @example
67
- * ```tsx
68
- * <Select
69
- * label="Country"
70
- * placeholder="Select a country"
71
- * options={[
72
- * { value: 'us', label: 'United States' },
73
- * { value: 'ca', label: 'Canada' },
74
- * { value: 'uk', label: 'United Kingdom' }
75
- * ]}
76
- * />
77
- *
78
- * <Select
79
- * label="Priority"
80
- * error="Priority is required"
81
- * options={[
82
- * { value: 'low', label: 'Low' },
83
- * { value: 'medium', label: 'Medium' },
84
- * { value: 'high', label: 'High' }
85
- * ]}
86
- * />
87
- * ```
88
- */
89
26
  export declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,36 @@
1
+ import { FilePointer, VirtualMount } from '@opencxh/domain';
2
+ import { default as React } from 'react';
3
+ export interface StorageInputProps {
4
+ value?: string | FilePointer;
5
+ onChange: (value: FilePointer | null, content?: Uint8Array) => void;
6
+ label?: string;
7
+ placeholder?: string;
8
+ error?: string;
9
+ disabled?: boolean;
10
+ accept?: string;
11
+ onListFiles?: (filters?: {
12
+ name?: string;
13
+ mimeType?: string;
14
+ mountId?: string;
15
+ path?: string;
16
+ }) => Promise<{
17
+ data: FilePointer[];
18
+ }> | undefined;
19
+ onListMounts?: () => Promise<{
20
+ data: VirtualMount[];
21
+ }> | undefined;
22
+ onUploadFile?: (payload: {
23
+ file: Uint8Array;
24
+ filename: string;
25
+ mimeType: string;
26
+ mountId?: string;
27
+ path?: string;
28
+ }) => Promise<{
29
+ data: FilePointer;
30
+ }> | undefined;
31
+ onDownloadFile?: (fileId: string) => Promise<Uint8Array> | undefined;
32
+ onRegisterFile?: (payload: Omit<FilePointer, 'id'>) => Promise<{
33
+ data: FilePointer;
34
+ }> | undefined;
35
+ }
36
+ export declare const StorageInput: React.FC<StorageInputProps>;
@@ -12,6 +12,7 @@ interface SidebarMenuProps {
12
12
  items: MenuItem[];
13
13
  isSelectedHandler: (path: string | undefined) => boolean;
14
14
  onClick?: (path: string | undefined) => void;
15
+ preMenuItemsComponent?: React.ReactNode;
15
16
  }
16
17
  export declare const SidebarMenu: React.FC<SidebarMenuProps>;
17
18
  export default SidebarMenu;
@@ -33,7 +33,7 @@ export interface DropdownProps {
33
33
  /** Show check mark for selected option */
34
34
  showCheck?: boolean;
35
35
  /** Header text for the dropdown */
36
- header?: string;
36
+ header?: string | React.ReactNode;
37
37
  }
38
38
  /**
39
39
  * Dropdown component for menus and select-like interfaces
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@opencxh/ui-kit",
3
- "version": "1.0.0",
3
+ "version": "3.5.0",
4
4
  "description": "Theme-aware UI component library for OpenCXH platform",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
8
+ "types": "./dist/index.d.ts",
8
9
  "import": "./dist/index.js",
9
- "require": "./dist/index.cjs",
10
- "types": "./dist/index.d.ts"
10
+ "require": "./dist/index.cjs"
11
11
  },
12
12
  "./styles": "./dist/styles.css"
13
13
  },
@@ -28,26 +28,27 @@
28
28
  "dependencies": {
29
29
  "clsx": "^2.1.0",
30
30
  "lucide-react": "^0.460.0",
31
- "react": "^19.1.0",
32
- "react-dom": "^19.1.0"
31
+ "react": "^19.2.4",
32
+ "react-dom": "^19.2.4",
33
+ "@opencxh/domain": "workspace:*"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@types/react": "^19.1.8",
36
- "@types/react-dom": "^19.1.6",
37
+ "@types/react-dom": "^19.2.3",
37
38
  "@typescript-eslint/eslint-plugin": "^8.15.0",
38
39
  "@typescript-eslint/parser": "^8.15.0",
39
- "@vitejs/plugin-react": "^4.3.4",
40
+ "@vitejs/plugin-react": "^5.0.4",
40
41
  "eslint": "^9.15.0",
41
42
  "eslint-plugin-react": "^7.37.2",
42
43
  "eslint-plugin-react-hooks": "^5.0.0",
43
44
  "typescript": "^5.6.3",
44
- "vite": "^6.0.1",
45
- "vite-plugin-dts": "^4.3.0",
45
+ "vite": "7.1.7",
46
+ "vite-plugin-dts": "^4.5.4",
46
47
  "vitest": "^2.1.8"
47
48
  },
48
49
  "peerDependencies": {
49
- "react": ">=19.1.0",
50
- "react-dom": ">=19.1.0"
50
+ "react": ">=19.2.4",
51
+ "react-dom": ">=19.2.4"
51
52
  },
52
53
  "keywords": [
53
54
  "react",