@ceed/cds 1.40.3 → 1.40.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.
@@ -37,8 +37,8 @@ export type AutocompleteProps<T extends AutocompleteOption | string = string, Mu
37
37
  };
38
38
  }) => void;
39
39
  } & Omit<JoyAutocompleteProps<AutocompleteOption, Multiple, boolean, boolean>, 'onChange' | 'value' | 'options' | 'defaultValue'>;
40
- declare function Autocomplete<T extends AutocompleteOption | string, Multiple extends boolean | undefined = false>(props: AutocompleteProps<T, Multiple>): React.JSX.Element;
41
- declare namespace Autocomplete {
42
- var displayName: string;
43
- }
40
+ export declare function AutocompleteInner<T extends AutocompleteOption | string, Multiple extends boolean | undefined = false>(props: AutocompleteProps<T, Multiple>, ref: React.Ref<HTMLInputElement>): React.JSX.Element;
41
+ declare const Autocomplete: <T extends string | AutocompleteOption = string, Multiple extends boolean | undefined = false>(props: AutocompleteProps<T, Multiple> & {
42
+ ref?: React.Ref<HTMLInputElement>;
43
+ }) => React.ReactElement;
44
44
  export { Autocomplete };
@@ -1,3 +1,4 @@
1
1
  import { Autocomplete } from './Autocomplete';
2
- export * from './Autocomplete';
2
+ export { Autocomplete } from './Autocomplete';
3
+ export type { AutocompleteOption, AutocompleteValue, AutocompleteProps } from './Autocomplete';
3
4
  export default Autocomplete;
@@ -1,10 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import type { ObjectLike, ColumnDef, DataTableProps, Sort, InferredIdType } from './types';
3
- export declare function useColumnWidths<T>(columnsByField: {
4
- [K in keyof T]: {
5
- headerRef: React.RefObject<HTMLTableCellElement>;
6
- };
7
- }): Record<string, number>;
3
+ export declare function useColumnWidths(columnsByField: Record<string, {
4
+ headerRef: React.RefObject<HTMLTableCellElement>;
5
+ }>): Record<string, number>;
8
6
  export declare function useDataTableRenderer<T extends Record<PropertyKey, unknown>, GetId extends ((row: T) => any) | undefined = undefined>({ rows: _rows, columns: columnsProp, pinnedColumns, rowCount: totalRowsProp, initialState, pagination, paginationMode, paginationModel, onPaginationModelChange, sortModel: controlledSortModel, sortOrder: _sortOrder, selectionModel, onSortModelChange, onSelectionModelChange, editMode, getId: _getId, isTotalSelected: _isTotalSelected, isRowSelectable, columnGroupingModel, columnVisibilityModel, onColumnVisibilityModelChange, checkboxSelection, }: DataTableProps<T, GetId>): {
9
7
  rowCount: number;
10
8
  selectableRowCount: number;
@@ -72,6 +72,7 @@ export type FlattenedColumn<T extends Record<PropertyKey, any>, ID> = ColumnDef<
72
72
  };
73
73
  export type BaseColumnDef<T extends Record<PropertyKey, V>, V, ID> = {
74
74
  [K in keyof T]: {
75
+ /** 컬럼의 고유 식별자. 한 테이블 안에서 중복되면 throw 한다. */
75
76
  field: K;
76
77
  headerName?: string;
77
78
  headerRef?: React.RefObject<HTMLTableCellElement>;
@@ -20,3 +20,14 @@ export declare function computeAutoFitWidth(params: {
20
20
  field: string;
21
21
  dataInPage: Record<string, unknown>[];
22
22
  }): number | null;
23
+ /**
24
+ * 헤더 셀의 DOM id. `<td headers>`가 이 값을 가리키므로 두 곳이 같은 규칙을 써야 한다.
25
+ * 컬럼마다 달라야 하므로 `headerName`이 아니라 고유한 `field`로 만든다.
26
+ */
27
+ export declare function getHeaderCellId(tableId: string, field: PropertyKey): string;
28
+ /**
29
+ * `field`를 DOM id로 쓸 수 있게 정규화한다.
30
+ * `field`는 임의의 object key라 공백이 들어올 수 있는데, 공백이 남으면 `<td headers>`가 다중 IDREF로
31
+ * 파싱되어 헤더-셀 연결이 끊긴다. 중복 검사도 이 값으로 한다 — `'a b'`와 `'a_b'`는 같은 id가 되기 때문이다.
32
+ */
33
+ export declare function sanitizeColumnId(field: PropertyKey): string;
@@ -1,10 +1,10 @@
1
- import React, { AriaAttributes, ComponentProps, ElementType, ReactNode } from 'react';
2
- import { MenuButtonProps as JoyMenuButtonProps } from '@mui/joy';
1
+ import React, { AriaAttributes, ComponentProps, ComponentRef, ElementType, ReactNode } from 'react';
2
+ import { MenuButtonProps as JoyMenuButtonProps, IconButtonProps as JoyIconButtonProps, MenuItemProps as JoyMenuItemProps } from '@mui/joy';
3
3
  export interface IconMenuButtonProps<T extends ElementType = 'button', P extends ElementType = 'li'> {
4
4
  size?: JoyMenuButtonProps<T, P>['size'];
5
5
  icon: ReactNode;
6
6
  buttonComponent?: T;
7
- buttonComponentProps?: ComponentProps<T> & AriaAttributes;
7
+ buttonComponentProps?: ComponentProps<T> & AriaAttributes & Pick<JoyIconButtonProps, 'sx'>;
8
8
  disabled?: boolean;
9
9
  loading?: boolean;
10
10
  color?: JoyMenuButtonProps<T, P>['color'];
@@ -12,12 +12,13 @@ export interface IconMenuButtonProps<T extends ElementType = 'button', P extends
12
12
  items?: {
13
13
  text: string;
14
14
  component?: P;
15
- componentProps?: ComponentProps<P>;
15
+ componentProps?: ComponentProps<P> & Pick<JoyMenuItemProps, 'disabled'>;
16
16
  }[];
17
17
  placement?: 'bottom-start' | 'bottom' | 'bottom-end';
18
18
  }
19
- declare function IconMenuButton<T extends ElementType, P extends ElementType>(props: IconMenuButtonProps<T, P>): React.JSX.Element;
20
- declare namespace IconMenuButton {
21
- var displayName: string;
22
- }
19
+ type IconMenuButtonRef<T extends ElementType> = React.Ref<ComponentRef<T>>;
20
+ export declare function IconMenuButtonInner<T extends ElementType, P extends ElementType>(props: IconMenuButtonProps<T, P>, ref: IconMenuButtonRef<T>): React.JSX.Element;
21
+ declare const IconMenuButton: <T extends React.ElementType = "button", P extends React.ElementType = "li">(props: IconMenuButtonProps<T, P> & {
22
+ ref?: IconMenuButtonRef<T>;
23
+ }) => React.ReactElement;
23
24
  export { IconMenuButton };
@@ -0,0 +1,5 @@
1
+ import type { IconMenuButtonProps } from './IconMenuButton';
2
+ type Assert<T extends true> = T;
3
+ export type ButtonComponentPropsAcceptsSx = Assert<'sx' extends keyof NonNullable<IconMenuButtonProps['buttonComponentProps']> ? true : false>;
4
+ export type ItemComponentPropsAcceptsDisabled = Assert<'disabled' extends keyof NonNullable<NonNullable<IconMenuButtonProps['items']>[number]['componentProps']> ? true : false>;
5
+ export {};
@@ -1,3 +1,4 @@
1
1
  import { IconMenuButton } from './IconMenuButton';
2
- export * from './IconMenuButton';
2
+ export { IconMenuButton } from './IconMenuButton';
3
+ export type { IconMenuButtonProps } from './IconMenuButton';
3
4
  export default IconMenuButton;
@@ -36,8 +36,5 @@ export type ModalFrameProps = {
36
36
  titleStartDecorator?: React.ReactNode;
37
37
  onClose?: () => void;
38
38
  } & React.ComponentProps<typeof ModalDialog>;
39
- declare function ModalFrame(props: ModalFrameProps): React.JSX.Element;
40
- declare namespace ModalFrame {
41
- var displayName: string;
42
- }
39
+ declare const ModalFrame: React.ForwardRefExoticComponent<Omit<ModalFrameProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
43
40
  export { ModalFrame };
@@ -46,8 +46,11 @@ export interface SelectProps<OptionValue extends OptionType, Multiple extends bo
46
46
  }, newValue: InferOptionValue<OptionValue>) => void;
47
47
  multiple?: Multiple;
48
48
  }
49
- declare function Select<OptionValue extends OptionType, Multiple extends boolean = false>(props: SelectProps<OptionValue, Multiple>): React.JSX.Element;
50
- declare namespace Select {
51
- var displayName: string;
52
- }
49
+ /**
50
+ * @visibleName Select
51
+ */
52
+ export declare function SelectInner<OptionValue extends OptionType, Multiple extends boolean = false>(props: SelectProps<OptionValue, Multiple>, ref: React.Ref<HTMLButtonElement>): React.JSX.Element;
53
+ declare const Select: <OptionValue extends OptionType, Multiple extends boolean = false>(props: SelectProps<OptionValue, Multiple> & {
54
+ ref?: React.Ref<HTMLButtonElement>;
55
+ }) => React.ReactElement;
53
56
  export { Select };
@@ -1,3 +1,4 @@
1
1
  import { Select } from './Select';
2
- export * from './Select';
2
+ export { Select, Option } from './Select';
3
+ export type { SelectProps, OptionType, InferOptionValue, OptionProps, JoySelectProps } from './Select';
3
4
  export default Select;
@@ -7,8 +7,5 @@ export type TextareaProps = {
7
7
  error?: boolean;
8
8
  helperText?: React.ReactNode;
9
9
  } & JoyTextareaProps & MotionProps;
10
- declare const Textarea: {
11
- (props: TextareaProps): React.JSX.Element;
12
- displayName: string;
13
- };
10
+ declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
14
11
  export { Textarea };
@@ -1,3 +1,4 @@
1
1
  import { Textarea } from './Textarea';
2
- export * from './Textarea';
2
+ export { Textarea } from './Textarea';
3
+ export type { TextareaProps, JoyTextareaProps } from './Textarea';
3
4
  export default Textarea;
@@ -2363,29 +2363,29 @@ interface DataTableApi {
2363
2363
 
2364
2364
  All column types extend `BaseColumnDef` with shared properties:
2365
2365
 
2366
- | Prop | Type | Default | Description |
2367
- | ----------------- | --------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------ |
2368
- | `field` | `keyof T` | (required) | Row data field to display |
2369
- | `headerName` | `string` | - | Column header text |
2370
- | `type` | `'text' \| 'number' \| 'currency' \| 'date' \| 'select' \| 'autocomplete' \| 'longText' \| 'link' \| 'actions'` | `'text'` | Column type (determines edit UI) |
2371
- | `width` | `string` | - | Column width (e.g., `'200px'`, `'30%'`) |
2372
- | `minWidth` | `string` | - | Minimum column width |
2373
- | `maxWidth` | `string` | - | Maximum column width |
2374
- | `resizable` | `boolean` | `false` | Enables column resizing by dragging |
2375
- | `sortable` | `boolean` | `true` | Enables sorting for this column |
2376
- | `sortComparator` | `(params: { rowA, rowB }) => number` | - | Custom sort logic |
2377
- | `sortOrder` | `('asc' \| 'desc' \| null)[]` | - | Column-specific sort direction cycle |
2378
- | `required` | `boolean` | `false` | Shows required indicator (\*) in header |
2379
- | `headerLineClamp` | `1 \| 2` | `1` | Max header text lines before truncation |
2380
- | `description` | `string` | - | Tooltip text for the column header |
2381
- | `cellClassName` | `string \| ((params: { row, value }) => string)` | - | Dynamic cell CSS class |
2382
- | `headerClassName` | `string \| ((params) => string)` | - | Dynamic header CSS class |
2383
- | `renderCell` | `(params: { row, value, rowIndex, colIndex, id }) => ReactNode` | - | Custom cell renderer |
2384
- | `renderEditCell` | `(params) => ReactNode` | - | Custom edit cell renderer |
2385
- | `isCellEditable` | `boolean \| ((params: { row, value, id }) => boolean)` | `true` | Whether a cell is editable |
2386
- | `componentProps` | `object \| ((params: { row, id }) => object)` | - | Props passed to the column type's edit component |
2387
- | `onCellEditStart` | `(params: { row, originalRow, value }) => void` | - | Callback when cell editing begins |
2388
- | `onCellEditStop` | `(params: { row, originalRow, value }) => void` | - | Callback when cell editing ends |
2366
+ | Prop | Type | Default | Description |
2367
+ | ----------------- | --------------------------------------------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------- |
2368
+ | `field` | `keyof T` | (required) | Row data field to display. Must be unique within the table. |
2369
+ | `headerName` | `string` | - | Column header text |
2370
+ | `type` | `'text' \| 'number' \| 'currency' \| 'date' \| 'select' \| 'autocomplete' \| 'longText' \| 'link' \| 'actions'` | `'text'` | Column type (determines edit UI) |
2371
+ | `width` | `string` | - | Column width (e.g., `'200px'`, `'30%'`) |
2372
+ | `minWidth` | `string` | - | Minimum column width |
2373
+ | `maxWidth` | `string` | - | Maximum column width |
2374
+ | `resizable` | `boolean` | `false` | Enables column resizing by dragging |
2375
+ | `sortable` | `boolean` | `true` | Enables sorting for this column |
2376
+ | `sortComparator` | `(params: { rowA, rowB }) => number` | - | Custom sort logic |
2377
+ | `sortOrder` | `('asc' \| 'desc' \| null)[]` | - | Column-specific sort direction cycle |
2378
+ | `required` | `boolean` | `false` | Shows required indicator (\*) in header |
2379
+ | `headerLineClamp` | `1 \| 2` | `1` | Max header text lines before truncation |
2380
+ | `description` | `string` | - | Tooltip text for the column header |
2381
+ | `cellClassName` | `string \| ((params: { row, value }) => string)` | - | Dynamic cell CSS class |
2382
+ | `headerClassName` | `string \| ((params) => string)` | - | Dynamic header CSS class |
2383
+ | `renderCell` | `(params: { row, value, rowIndex, colIndex, id }) => ReactNode` | - | Custom cell renderer |
2384
+ | `renderEditCell` | `(params) => ReactNode` | - | Custom edit cell renderer |
2385
+ | `isCellEditable` | `boolean \| ((params: { row, value, id }) => boolean)` | `true` | Whether a cell is editable |
2386
+ | `componentProps` | `object \| ((params: { row, id }) => object)` | - | Props passed to the column type's edit component |
2387
+ | `onCellEditStart` | `(params: { row, originalRow, value }) => void` | - | Callback when cell editing begins |
2388
+ | `onCellEditStop` | `(params: { row, originalRow, value }) => void` | - | Callback when cell editing ends |
2389
2389
 
2390
2390
  ### ActionsColumnDef
2391
2391
 
@@ -2424,6 +2424,8 @@ interface DataTableApi {
2424
2424
  ### Feature Combination Constraints
2425
2425
 
2426
2426
  - `pinnedColumns` and `columnGroupingModel` cannot be used simultaneously.
2427
+ - `field` must be unique within a table. DataTable throws when two columns share one, because duplicates would collide on the header/`<col>` element, the measured width, and the header `id`. Whitespace is collapsed before the check, so `'order total'` and `'order_total'` also count as duplicates. To render several values in one cell, map them into `rows` first; to render a cell with no backing data, reference a `field` that is not in `rows` and draw it with `renderCell`.
2428
+ - The header cell `id` (`<th id>`, referenced by each `<td headers>`) is derived from `field`, with whitespace collapsed. It is an implementation detail — do not target it from external selectors, CSS, or `aria-labelledby`. The same applies to `data-field` on the header cell.
2427
2429
  - `editMode` must be `true` for editing-related UI to be active.
2428
2430
  - When `paginationMode="server"`, `rowCount` must be specified.
2429
2431
 
@@ -305,23 +305,23 @@ const shouldDisableDate = useCallback(
305
305
 
306
306
  ### Key Props
307
307
 
308
- | Prop | Type | Default | Description |
309
- | ------------------- | ------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |
310
- | `value` | `[Date, Date \| undefined]` | - | Selected date(s) for controlled mode. Single date: `[date, undefined]` |
311
- | `defaultValue` | `[Date, Date \| undefined]` | - | Initial date(s) for uncontrolled mode |
312
- | `onChange` | `(date: [Date, Date \| undefined]) => void` | - | Callback when date selection changes |
313
- | `view` | `'month' \| 'day'` | `'day'` | Active calendar view |
314
- | `views` | `('month' \| 'day')[]` | `['month', 'day']` | Available views for navigation |
315
- | `onViewChange` | `(view: 'month' \| 'day') => void` | - | Callback when view changes |
316
- | `onMonthChange` | `(newMonth: Date) => void` | - | Callback when the displayed month changes |
317
- | `rangeSelection` | `boolean` | `false` | Enable date range selection (two dates) |
318
- | `locale` | `string` | `'default'` | Locale for month/day names (BCP 47 format) |
319
- | `minDate` | `Date` | - | Minimum selectable date |
320
- | `maxDate` | `Date` | - | Maximum selectable date |
321
- | `disableFuture` | `boolean` | `false` | Disable all future dates |
322
- | `disablePast` | `boolean` | `false` | Disable all past dates |
323
- | `shouldDisableDate` | `(date: Date) => boolean` | - | Custom function to disable specific dates |
324
- | `slots` | `{ day?, monthButton?, yearButton? }` | - | Custom component slots for calendar elements |
308
+ | Prop | Type | Default | Description |
309
+ | ------------------- | -------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |
310
+ | `value` | `[Date, Date \| undefined]` | - | Selected date(s) for controlled mode. Single date: `[date, undefined]` |
311
+ | `defaultValue` | `[Date, Date \| undefined]` | - | Initial date(s) for uncontrolled mode |
312
+ | `onChange` | `(date: [Date, Date \| undefined]) => void` | - | Callback when date selection changes |
313
+ | `view` | `'month' \| 'day'` | `'day'` | Active calendar view |
314
+ | `views` | `('month' \| 'day')[]` | `['month', 'day']` | Available views for navigation |
315
+ | `onViewChange` | `(view: 'month' \| 'day') => void` | - | Callback when view changes |
316
+ | `onMonthChange` | `(newMonth: Date) => void` | - | Callback when the displayed month changes |
317
+ | `rangeSelection` | `boolean` | `false` | Enable date range selection (two dates) |
318
+ | `locale` | `string` | `'default'` | Locale for month/day names (BCP 47 format) |
319
+ | `minDate` | `Date` | - | Minimum selectable date |
320
+ | `maxDate` | `Date` | - | Maximum selectable date |
321
+ | `disableFuture` | `boolean` | `false` | Disable all future dates |
322
+ | `disablePast` | `boolean` | `false` | Disable all past dates |
323
+ | `shouldDisableDate` | `(date: Date) => boolean` | - | Custom function to disable specific dates |
324
+ | `slots` | `Partial<Record<CalendarSlot, ElementType>>` | - | Not implemented. The prop is accepted but no slot is overridable yet |
325
325
 
326
326
  ## Accessibility
327
327
 
@@ -233,18 +233,23 @@ function EditorToolbar({ onAction }) {
233
233
 
234
234
  ### Key Props
235
235
 
236
- | Prop | Type | Default | Description |
237
- | ---------------------- | ---------------------------------------------------------------------- | ----------- | -------------------------------------------- |
238
- | `icon` | `ReactNode` | (required) | Icon element to render in the trigger button |
239
- | `items` | `{ text: string; component?: ElementType; componentProps?: object }[]` | - | Menu items |
240
- | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
241
- | `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Button color |
242
- | `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | `'plain'` | Button visual style |
243
- | `disabled` | `boolean` | `false` | Disables the button |
244
- | `loading` | `boolean` | `false` | Shows loading indicator |
245
- | `placement` | `Placement` | `'bottom'` | Menu position |
246
- | `buttonComponent` | `ElementType` | - | Custom trigger element |
247
- | `buttonComponentProps` | `object` | - | Props passed to custom trigger |
236
+ | Prop | Type | Default | Description |
237
+ | ---------------------- | ---------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------ |
238
+ | `icon` | `ReactNode` | (required) | Icon element to render in the trigger button |
239
+ | `items` | `{ text: string; component?: ElementType; componentProps?: object }[]` | - | Menu items. `componentProps` reaches Joy `MenuItem`, so `disabled` works |
240
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
241
+ | `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Button color |
242
+ | `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | `'plain'` | Button visual style |
243
+ | `disabled` | `boolean` | `false` | Disables the button |
244
+ | `loading` | `boolean` | `false` | Shows loading indicator |
245
+ | `placement` | `Placement` | `'bottom'` | Menu position |
246
+ | `buttonComponent` | `ElementType` | - | Custom trigger element |
247
+ | `buttonComponentProps` | `object` | - | Props passed to the trigger. Reaches Joy `IconButton`, so `sx` works |
248
+
249
+ > **Note**: `buttonComponentProps` is typed as `ComponentProps<buttonComponent> & AriaAttributes` plus an explicit
250
+ > allow-list of Joy `IconButton` props — currently only `sx`. `items[].componentProps` works the same way against Joy
251
+ > `MenuItem` — currently only `disabled`. Every other Joy prop still reaches the underlying Joy component at runtime,
252
+ > but it does not type-check: extend the `Pick<...>` in `IconMenuButton.tsx` when you need one.
248
253
 
249
254
  ## Best Practices
250
255