# @gomeniucivan/ui — Component Reference

> **Package:** `@gomeniucivan/ui`
> Use this document as the single source of truth for every exported component and its props.

---

## Setup & Providers

### ConfigProvider

Wraps the app to provide CDN config, i18n resources, and the motion library.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | App content |
| `config` | `Config` | CDN/proxy configuration object |
| `locale` | `string` | Active locale code (default `'en'`) |
| `motion` | `MotionComponentType` | **Required.** Pass `motion` from `motion/react` or `motion/react-m` |
| `resources` | `TranslationResourcesInput` | Translation resources (object or Promise) |

#### Config object

| Prop | Type | Description |
|---|---|---|
| `aAs` | `ElementType` | Custom element for `<A>` links |
| `imgAs` | `ElementType` | Custom element for images |
| `imgUnoptimized` | `boolean` | Disable image optimisation |
| `proxy` | `CDN \| 'custom'` | CDN proxy |
| `customCdnFn` | `CdnFn` | Custom CDN URL builder |

### ThemeProvider

Wraps the app with antd-style theming, global styles, and custom tokens.

| Prop | Type | Default | Description |
|---|---|---|---|
| `className` | `string` | | Root class |
| `cy` | `boolean` | | When `true`, components with a `cy` prop render a `data-cy` attribute for Cypress / testing selectors |
| `customFonts` | `string[]` | | Additional font families |
| `customStylish` | `(theme) => object` | | Custom stylish tokens |
| `customTheme` | `{ neutralColor?, primaryColor? }` | | Override neutral/primary colours |
| `customToken` | `(theme) => object` | | Custom design tokens |
| `enableCustomFonts` | `boolean` | | Load custom fonts |
| `enableGlobalStyle` | `boolean` | | Inject global styles |
| `isMobile` | `boolean` | | Global mobile mode; components with `isMobile` prop inherit this |
| `style` | `CSSProperties` | | Inline style |

### Cypress Test Selectors (`cy`)

All components accept an optional `cy?: string` prop. When the `ThemeProvider` has `cy={true}`, components render a `data-cy` attribute with the provided value. When `cy` is `false` or omitted on the provider, `data-cy` attributes are never rendered — zero overhead in production.

**Standalone components:** pass `cy="my-button"` → renders `data-cy="my-button"`.

**Form fields:** `Form` accepts a `cy` prop that acts as a prefix. Each field component auto-computes `data-cy` from `<form cy>-<field name>`. For example:

```tsx
<ThemeProvider cy>
  <Form cy="profile" form={form}>
    <FormInput name="firstName" />   {/* data-cy="profile-firstName" */}
    <FormSelect name="country" />    {/* data-cy="profile-country" */}
  </Form>
  <Button cy="submit-btn">Save</Button> {/* data-cy="submit-btn" */}
</ThemeProvider>
```

Field-level `cy` overrides the auto-computed value: `<FormInput name="firstName" cy="custom" />` → `data-cy="custom"`.

**Hook:** `useCy(cy?: string)` returns `{ 'data-cy': cy }` when the provider flag is on, or `{}` otherwise. Useful for custom components.

### Meta

SEO meta helper rendered inside `ThemeProvider`.

| Prop | Type | Description |
|---|---|---|
| `title` | `string` | Page title |
| `description` | `string` | Meta description |
| `withManifest` | `boolean` | Include manifest link |

---

## Layout Components

### Flex

Extended Ant Design `Flex` with extra convenience props.

| Prop | Type | Description |
|---|---|---|
| `as` | `ElementType` | Render as custom element |
| `direction` | `'vertical' \| 'vertical-reverse' \| 'horizontal' \| 'horizontal-reverse'` | Flex direction shorthand |
| `horizontal` | `boolean` | Shorthand for `direction="horizontal"` |
| `vertical` | `boolean` | Shorthand for vertical (default) |
| `distribution` | `CSSProperties['justifyContent']` | Alias for `justify` |
| `padding` | `number \| string` | CSS padding |
| `paddingBlock` | `number \| string` | Block padding |
| `paddingInline` | `number \| string` | Inline padding |
| `width` | `number \| string` | Width |
| `height` | `number \| string` | Height |
| `allowShrink` | `boolean` | Sets `minWidth: 0` |
| `visible` | `boolean` | When `false`, sets `display: none` |
| `ref` | `Ref<HTMLElement>` | Ref |

### Grid

CSS grid wrapper built on `Flex`.

| Prop | Type | Description |
|---|---|---|
| `gap` | `string \| number` | Grid gap |
| `maxItemWidth` | `string \| number` | Max width per grid item |
| `rows` | `number` | Number of rows |
| `ref` | `Ref<HTMLDivElement>` | Ref |

### Layout

Full-page layout with header, sidebar, content, toc, and footer slots.

| Prop | Type | Description |
|---|---|---|
| `asideWidth` | `number` | Sidebar width |
| `children` | `ReactNode` | Content |
| `content` | `ReactNode` | Main content area |
| `footer` | `ReactNode` | Footer slot |
| `header` | `ReactNode` | Header slot |
| `headerHeight` | `number` | Header height |
| `helmet` | `ReactNode` | Head/meta slot |
| `sidebar` | `ReactNode` | Sidebar slot |
| `toc` | `ReactNode` | Table of contents slot |
| `tocWidth` | `number` | TOC width |

Sub-components: `LayoutHeader`, `LayoutFooter`, `LayoutMain`, `LayoutSidebar`, `LayoutSidebarInner`, `LayoutToc` — each accepts `DivProps` plus layout-specific sizing props (`headerHeight`, `tocWidth`).

### Header

| Prop | Type | Description |
|---|---|---|
| `actions` | `ReactNode` | Actions area |
| `logo` | `ReactNode` | Logo |
| `nav` | `ReactNode` | Navigation |
| `actionsClassName/Style` | `string / CSSProperties` | Actions styling |
| `logoClassName/Style` | `string / CSSProperties` | Logo styling |
| `navClassName/Style` | `string / CSSProperties` | Nav styling |

### Footer

| Prop | Type | Description |
|---|---|---|
| `bottom` | `ReactNode` | Bottom content |
| `columns` | `RcFooter columns` | Footer link columns |
| `contentMaxWidth` | `number` | Max content width |
| `theme` | `'light' \| 'dark'` | Footer theme |

### SideNav

| Prop | Type | Description |
|---|---|---|
| `avatar` | `ReactNode` | Avatar slot |
| `bottomActions` | `ReactNode` | **Required.** Bottom action buttons |
| `topActions` | `ReactNode` | Top action buttons |

### DraggablePanel

Resizable panel with drag handle.

| Prop | Type | Default | Description |
|---|---|---|---|
| `placement` | `'right' \| 'left' \| 'top' \| 'bottom'` | | **Required.** Panel placement |
| `defaultExpand` | `boolean` | | Default expand state |
| `expand` | `boolean` | | Controlled expand |
| `expandable` | `boolean` | | Can expand/collapse |
| `mode` | `'fixed' \| 'float'` | | Panel mode |
| `defaultSize` | `Partial<Size>` | | Default size |
| `size` | `Partial<Size>` | | Controlled size |
| `minWidth/minHeight` | `number` | | Minimum dimensions |
| `maxWidth/maxHeight` | `number` | | Maximum dimensions |
| `pin` | `boolean` | | Pin panel |
| `showBorder` | `boolean` | `true` | Show border |
| `showHandleHighlight` | `boolean` | | Highlight handle on hover |
| `showHandleWhenCollapsed` | `boolean` | | Show handle when collapsed |
| `showHandleWideArea` | `boolean` | | Wide handle area |
| `onExpandChange` | `(expand: boolean) => void` | | Expand callback |
| `onSizeChange` | `(delta, size?) => void` | | Size change callback |
| `onSizeDragging` | `(delta, size?) => void` | | Active drag callback |

Sub-components: `DraggablePanelBody`, `DraggablePanelContainer`, `DraggablePanelFooter`, `DraggablePanelHeader`.

### DraggableSideNav

Full sidebar with resizable body, header, footer, and expand/collapse.

| Prop | Type | Default | Description |
|---|---|---|---|
| `body` | `(expand: boolean) => ReactNode` | | **Required.** Main content |
| `header` | `ReactNode \| (expand: boolean) => ReactNode` | | Header |
| `footer` | `ReactNode \| (expand: boolean) => ReactNode` | | Footer |
| `defaultExpand` | `boolean` | `true` | Default expand state |
| `expand` | `boolean` | | Controlled expand |
| `expandable` | `boolean` | `true` | Can expand/collapse |
| `defaultWidth` | `number` | | Default width |
| `width` | `number` | | Controlled expand width |
| `minWidth` | `number` | `64` | Min width when expanded |
| `maxWidth` | `number` | | Max width |
| `placement` | `'left' \| 'right'` | `'left'` | Placement |
| `resizable` | `boolean` | `true` | Enable resize |
| `showBorder` | `boolean` | `true` | Show border |
| `showHandle` | `boolean` | `true` | Show toggle handle |
| `showHandleWhenCollapsed` | `boolean` | `false` | Handle visibility when collapsed |
| `onExpandChange` | `(expand: boolean) => void` | | Expand callback |
| `onWidthChange` | `(delta, width) => void` | | Width change callback |
| `onSelect` | `(key: string) => void` | | Menu select callback |

### ScrollArea

Styled scroll area. Exports atomic sub-components: `ScrollAreaRoot`, `ScrollAreaViewport`, `ScrollAreaContent`, `ScrollAreaScrollbar`, `ScrollAreaThumb`, `ScrollAreaCorner`.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | Content |
| `corner` | `boolean` | Show corner |
| `scrollFade` | `boolean` | Fade edges |
| `contentProps` | `ScrollAreaContentProps` | Content props |
| `scrollbarProps` | `ScrollAreaScrollbarProps` | Scrollbar props |
| `thumbProps` | `ScrollAreaThumbProps` | Thumb props |
| `viewportProps` | `ScrollAreaViewportProps` | Viewport props |
| `cornerProps` | `ScrollAreaCornerProps` | Corner props |

### ScrollShadow

| Prop | Type | Description |
|---|---|---|
| `hideScrollBar` | `boolean` | Hide scrollbar |
| `isEnabled` | `boolean` | Enable shadow |
| `offset` | `number` | Offset |
| `orientation` | `'vertical' \| 'horizontal'` | Scroll direction |
| `size` | `number` | Shadow size |
| `visibility` | `'auto' \| 'always' \| 'never'` | Shadow visibility |
| `onVisibilityChange` | `({ top?, bottom?, left?, right? }) => void` | Visibility callback |

### MaskShadow

| Prop | Type | Description |
|---|---|---|
| `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | Shadow position |
| `size` | `number` | Shadow size |
| `visibility` | `'auto' \| 'always' \| 'never'` | Visibility mode |

---

## General UI

### Button

Extends Ant Design `Button`.

| Prop | Type | Description |
|---|---|---|
| `glass` | `boolean` | Glassmorphism style |
| `icon` | `IconProps['icon']` | Lucide icon |
| `iconProps` | `Partial<IconProps>` | Icon customisation |
| `shadow` | `boolean` | Drop shadow |

### ActionIcon

Icon-only button with tooltip.

| Prop | Type | Description |
|---|---|---|
| `icon` | `IconProps['icon'] \| ReactNode` | Icon |
| `active` | `boolean` | Active state |
| `danger` | `boolean` | Danger style |
| `disabled` | `boolean` | Disabled |
| `glass` | `boolean` | Glass effect |
| `loading` | `boolean` | Loading state |
| `shadow` | `boolean` | Shadow |
| `size` | `ActionIconSize` | Size (number, `'large'`, `'middle'`, `'small'`, or config object) |
| `spin` | `boolean` | Spin icon |
| `title` | `TooltipProps['title']` | Tooltip title |
| `tooltipProps` | `Omit<TooltipProps, 'children' \| 'title'>` | Tooltip config |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | Visual variant |

### ActionIconGroup

Group of action icon buttons.

| Prop | Type | Description |
|---|---|---|
| `items` | `MenuItemType[]` | Action items |
| `menu` | `DropdownMenuProps['items']` | Overflow menu items |
| `onActionClick` | `(action) => void` | Action click handler |
| `size` | `ActionIconSize` | Icon size |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Visual variant |
| `disabled` | `boolean` | Disabled |
| `glass` | `boolean` | Glass effect |
| `shadow` | `boolean` | Shadow |

### Icon

Renders Lucide icons or custom icon components.

| Prop | Type | Description |
|---|---|---|
| `icon` | `LucideIcon \| FC \| ReactNode` | **Required.** Icon component/element |
| `size` | `IconSize` | Size (number, `'large'`/`'middle'`/`'small'`, or config) |
| `spin` | `boolean` | Spin animation |
| `color` | `string` | Icon colour |
| `fill` | `string` | Fill colour |

### Tag

| Prop | Type | Description |
|---|---|---|
| `color` | `AntTagProps['color'] \| 'info'` | Tag colour |
| `size` | `'small' \| 'middle' \| 'large'` | Size |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### Text

Typography text component.

| Prop | Type | Description |
|---|---|---|
| `as` | `ElementType` | Render element |
| `type` | `'secondary' \| 'success' \| 'warning' \| 'danger' \| 'info'` | Text type |
| `fontSize` | `number \| string` | Font size |
| `weight` | `'bold' \| 'bolder' \| number` | Font weight |
| `color` | `string` | Text colour |
| `align` | `'left' \| 'center' \| 'right'` | Text align |
| `lineHeight` | `CSSProperties['lineHeight']` | Line height |
| `lineClamp` | `number` | CSS line-clamp |
| `noWrap` | `boolean` | Disable wrapping |
| `ellipsis` | `boolean \| { rows?, tooltip?, tooltipWhenOverflow? }` | Ellipsis config |
| `strong` | `boolean` | Bold |
| `italic` | `boolean` | Italic |
| `underline` | `boolean` | Underline |
| `delete` | `boolean` | Strikethrough |
| `mark` | `boolean` | Highlight |
| `code` | `boolean` | Code style |
| `disabled` | `boolean` | Disabled style |
| `textTransform` | `CSSProperties['textTransform']` | Transform |
| `textDecoration` | `CSSProperties['textDecoration']` | Decoration |
| `whiteSpace` | `CSSProperties['whiteSpace']` | White space |
| `wordBreak` | `CSSProperties['wordBreak']` | Word break |

### Block

Container with card-like variants.

| Prop | Type | Description |
|---|---|---|
| `clickable` | `boolean` | Clickable hover effect |
| `glass` | `boolean` | Glass effect |
| `shadow` | `boolean` | Shadow |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### Empty

Empty state placeholder.

| Prop | Type | Description |
|---|---|---|
| `title` | `ReactNode` | Title |
| `description` | `ReactNode` | Description |
| `icon` | `IconProps['icon']` | Icon |
| `iconColor` | `IconProps['color']` | Icon colour |
| `emoji` | `string` | Emoji character |
| `image` | `ReactNode` | Image |
| `imageSize` | `number` | Image size |
| `action` | `ReactNode` | Action buttons |
| `type` | `'default' \| 'page'` | Layout type |

### Skeleton

Loading skeleton. Sub-components: `SkeletonAvatar`, `SkeletonBlock`, `SkeletonButton`, `SkeletonParagraph`, `SkeletonTags`, `SkeletonTitle`.

| Prop | Type | Description |
|---|---|---|
| `active` | `boolean` | Animated shimmer |
| `avatar` | `SkeletonAvatarProps \| boolean` | Avatar skeleton |
| `title` | `SkeletonTitleProps \| boolean` | Title skeleton |
| `paragraph` | `SkeletonParagraphProps \| boolean` | Paragraph skeleton |
| `gap` | `number` | Gap between sections |

---

## Data Entry

### CardForm

Card wrapper for long forms with a sticky header action bar (`Back`, `Save`, `Save and Continue Edit`).

| Prop | Type | Default | Description |
|---|---|---|---|
| `actions` | `ReactNode` | | Custom right-side actions. When provided, default Save buttons are not rendered |
| `backButtonProps` | `Omit<ActionIconProps, 'icon' \| 'onClick'>` | | Back button props |
| `backIcon` | `ActionIconProps['icon']` | `ArrowLeft` | Back icon |
| `title` | `ReactNode` | | Header title |
| `onBack` | `ActionIconProps['onClick']` | | Back click handler |
| `onSave` | `ButtonProps['onClick']` | | Save click handler |
| `onSaveAndContinue` | `ButtonProps['onClick']` | | Save-and-continue click handler |
| `saveText` | `ReactNode` | `'Save'` | Save button label |
| `continueText` | `ReactNode` | `'Save and Continue Edit'` | Continue button label |
| `saveButtonProps` | `Omit<ButtonProps, 'children' \| 'onClick'>` | | Save button props |
| `continueButtonProps` | `Omit<ButtonProps, 'children' \| 'onClick'>` | | Continue button props |
| `showSave` | `boolean` | `true` | Show Save button |
| `showContinue` | `boolean` | `true` | Show Continue button |
| `sticky` | `boolean` | `true` | Make header sticky inside the scrolling container |
| `stickyOffset` | `number \| string` | `0` | Sticky top offset |
| `headerClassName` | `string` | | Header class name |
| `headerStyle` | `CSSProperties` | | Header style |
| `contentClassName` | `string` | | Content class name |
| `contentStyle` | `CSSProperties` | | Content style |

Also accepts `FlexProps` (except `title`, which is reserved by `CardForm`).

### Input

Extends Ant Design `Input`. Also exports: `TextArea`, `InputNumber`, `InputPassword`, `InputOPT`, `InputMask`.

| Prop | Type | Description |
|---|---|---|
| `shadow` | `boolean` | Shadow effect |

**TextArea** adds `resize?: boolean`. **InputMask** adds `mask`, `maskChar`, `maskPlaceholder`, `alwaysShowMask`.

### Select

Custom select built on Base UI.

| Prop | Type | Default | Description |
|---|---|---|---|
| `options` | `SelectOptions<Value>` | | Options array (flat or grouped) |
| `value` | `Value \| Value[] \| null` | | Controlled value |
| `defaultValue` | `Value \| Value[] \| null` | | Default value |
| `onChange` | `(value, option?) => void` | | Change handler |
| `onSelect` | `(value, option?) => void` | | Select handler |
| `mode` | `'multiple' \| 'tags'` | | Multi-select mode |
| `size` | `'large' \| 'middle' \| 'small'` | | Size |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | | Visual variant |
| `placeholder` | `ReactNode` | | Placeholder |
| `disabled` | `boolean` | | Disabled |
| `loading` | `boolean` | | Loading |
| `allowClear` | `boolean` | | Show clear button |
| `showSearch` | `boolean` | | Enable search |
| `isMobile` | `boolean` | `false` | Mobile drawer picker |
| `behaviorVariant` | `'default' \| 'item-aligned'` | `'default'` | Dropdown positioning |
| `selectedIndicatorVariant` | `'check' \| 'bold'` | `'check'` | Selected item indicator style |
| `prefix` | `ReactNode \| IconProps['icon']` | | Prefix element |
| `suffixIcon` | `IconProps['icon'] \| ReactNode` | | Suffix icon |
| `shadow` | `boolean` | | Shadow |
| `open` | `boolean` | | Controlled open |
| `onOpenChange` | `(open: boolean) => void` | | Open change callback |
| `labelRender` | `(option) => ReactNode` | | Custom label renderer |
| `optionRender` | `(option, info) => ReactNode` | | Custom option renderer |
| `listHeight` | `number` | `256` | Popup scroll height |
| `virtual` | `boolean` | | Virtual scrolling |
| `popupMatchSelectWidth` | `boolean \| number` | | Match popup to trigger width |

### Checkbox / CheckboxGroup

| Prop (Checkbox) | Type | Description |
|---|---|---|
| `checked` | `boolean` | Controlled |
| `defaultChecked` | `boolean` | Default |
| `disabled` | `boolean` | Disabled |
| `indeterminate` | `boolean` | Indeterminate state |
| `onChange` | `(checked: boolean) => void` | Change handler |
| `shape` | `'square' \| 'circle'` | Shape |
| `size` | `number` | Size |
| `backgroundColor` | `string` | Checked colour |

**CheckboxGroup**: `options`, `value`, `defaultValue`, `onChange`, `disabled`, `shape`, `size`.

### Radio

Wraps Ant Design `Radio`. Supports `Radio.Group` and `Radio.Button`.

| Prop | Type | Description |
|---|---|---|
| `checked` | `boolean` | Controlled checked state |
| `disabled` | `boolean` | Disabled |
| `value` | `any` | Radio value |
| `onChange` | `(e: RadioChangeEvent) => void` | Change handler |

**Radio.Group**: `value`, `defaultValue`, `onChange`, `disabled`, `options`, `optionType` (`'default' | 'button'`), `buttonStyle` (`'outline' | 'solid'`), `size`.

**Radio.Button**: Same props as Radio, rendered as a button style option within `Radio.Group`.

```tsx
<Radio.Group value={value} onChange={(e) => setValue(e.target.value)}>
  <Radio value={1}>Option A</Radio>
  <Radio value={2}>Option B</Radio>
  <Radio value={3}>Option C</Radio>
</Radio.Group>
```

### Switch

| Prop | Type | Default | Description |
|---|---|---|---|
| `checked` / `value` | `boolean` | | Controlled checked state |
| `defaultChecked` / `defaultValue` | `boolean` | | Uncontrolled |
| `disabled` | `boolean` | | Disabled |
| `loading` | `boolean` | | Loading indicator |
| `size` | `'default' \| 'small'` | `'default'` | Size |
| `onChange` | `SwitchChangeEventHandler` | | Change handler |
| `onClick` | `SwitchClickEventHandler` | | Click handler |
| `checkedChildren` | `ReactNode` | | Checked icon/label |
| `unCheckedChildren` | `ReactNode` | | Unchecked icon/label |
| `autoFocus` | `boolean` | | Auto focus |

### DatePicker

Extends Ant Design `DatePicker`.

| Prop | Type | Description |
|---|---|---|
| `shadow` | `boolean` | Shadow |
| `isMobile` | `boolean` | Force mobile drawer UI |
| `min` | `ConfigType` | Lower bound date |
| `max` | `ConfigType` | Upper bound date |
| `revertYear` | `boolean` | Ascending year order |

### TimePicker

| Prop | Type | Description |
|---|---|---|
| `value` | `string \| null` | Controlled value |
| `defaultValue` | `string \| null` | Default value |
| `onChange` | `(value, formatted) => void` | Change handler |
| `format` | `string \| (value) => string` | Display format |
| `use12Hours` | `boolean` | 12-hour mode |
| `hourStep` | `number` | Hour increment |
| `minuteStep` | `number` | Minute increment |
| `isMobile` | `boolean` | Mobile drawer UI |
| `size` | `SelectSize` | Size |
| `allowClear` | `boolean` | Clearable |
| `open` | `boolean` | Controlled open |
| `onOpenChange` | `(open: boolean) => void` | Open callback |
| `inputReadOnly` | `boolean` | Read-only input |

### AutoComplete

Extends Ant Design `AutoComplete`. Adds `shadow?: boolean`.

### Segmented

Extends Ant Design `Segmented`.

| Prop | Type | Description |
|---|---|---|
| `glass` | `boolean` | Glass effect |
| `padding` | `string \| number` | Padding |
| `shadow` | `boolean` | Shadow |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### SliderWithInput

Slider + InputNumber combo.

| Prop | Type | Description |
|---|---|---|
| `changeOnWheel` | `boolean` | Scroll to change |
| `controls` | `InputNumberProps['controls']` | Input controls |
| `gap` | `FlexProps['gap']` | Gap |
| `size` | `InputNumberProps['size']` | Size |
| `unlimitedInput` | `boolean` | Unlimited max in input |
| `variant` | `InputNumberProps['variant']` | Input variant |

### ColorSwatches

| Prop | Type | Description |
|---|---|---|
| `colors` | `{ color, key?, title? }[]` | **Required.** Colour options |
| `value` | `string` | Controlled value |
| `defaultValue` | `string` | Default |
| `onChange` | `(color?) => void` | Change handler |
| `shape` | `'circle' \| 'square'` | Swatch shape |
| `size` | `number` | Swatch size |
| `enableColorPicker` | `boolean` | Show picker |
| `enableColorSwatches` | `boolean` | Show swatches |

### EditableText

| Prop | Type | Description |
|---|---|---|
| `value` | `string` | Controlled value |
| `onChange` | `(value) => void` | Change handler |
| `onChangeEnd` | callback | Confirmed change |
| `editing` | `boolean` | Controlled editing state |
| `onEditingChange` | `(editing: boolean) => void` | Editing callback |
| `showEditIcon` | `boolean` | Show edit icon |
| `variant` | string | Visual variant |
| `size` | any | Size |

### HotkeyInput

| Prop | Type | Description |
|---|---|---|
| `value` | `string` | Controlled value |
| `defaultValue` | `string` | Default |
| `onChange` | `(value: string) => void` | Change handler |
| `allowReset` | `boolean` | Show reset |
| `resetValue` | `string` | Reset target |
| `hotkeyConflicts` | `string[]` | Conflicting keys |
| `onConflict` | `(key) => void` | Conflict callback |
| `disabled` | `boolean` | Disabled |
| `shadow` | `boolean` | Shadow |
| `variant` | `'filled' \| 'borderless' \| 'outlined'` | Variant |

### ImageSelect

| Prop | Type | Description |
|---|---|---|
| `options` | `ImageSelectItem[]` | Options with `img`, `label`, `value` |
| `value` | `SelectProps['value']` | Controlled |
| `defaultValue` | `SelectProps['defaultValue']` | Default |
| `onChange` | `(value) => void` | Change |
| `width` | `number` | Image width |
| `height` | `number` | Image height |

---

## Form

### Form

| Prop | Type | Default | Description |
|---|---|---|---|
| `children` | `ReactNode` | | **Required.** Form content |
| `cy` | `string` | | Cypress test-id prefix. Field components emit `data-cy="<cy>-<name>"` when ThemeProvider `cy` is enabled |
| `onSubmit` | `(values: T) => void \| Promise` | | Submit handler |
| `form` | `FormInstance<T>` | | External form instance (from `useForm`, destructure as `const { form } = useForm(...)`) |
| `initialValues` | `T` | | Initial field values |
| `validate` | `(values: T) => Partial<Record<keyof T, string>>` | | Validation function |
| `layout` | `'vertical' \| 'horizontal'` | `'vertical'` | Form layout. Automatically forced to `'vertical'` when `ThemeProvider.isMobile` is `true` or viewport width < 880px |
| `labelWidth` | `string \| number` | `'200px'` | Label width (horizontal layout) |
| `fieldMinWidth` | `string \| number` | | Min field width |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | `'borderless'` | Form variant |

**Responsive layout:** When `isMobile` from `ThemeProvider` is `true` or the viewport is narrower than 880px, the form automatically switches to `vertical` layout regardless of the `layout` prop.

**Label click behaviour:** Clicking a field label focuses/activates the associated control — focuses the input for `FormInput`/`FormTextarea`, opens the dropdown for `FormSelect`, toggles the switch for `FormSwitch` (unless disabled), toggles the checkbox for `FormCheckbox` (unless disabled), opens the picker for `FormDatePicker`/`FormTimePicker`, focuses the control for `FormSegment`, and focuses the radio group for `FormRadio`.

Sub-components: `Form.Input` (`FormInput`), `Form.Textarea` (`FormTextarea`), `Form.Block` (`FormBlock`), `Form.Label` (`FormLabel`), `Form.Description` (`FormDescription`), `Form.Error` (`FormError`), `Form.TimePicker` (`FormTimePicker`), `Form.Checkbox` (`FormCheckbox`), `Form.Switch` (`FormSwitch`), `Form.DatePicker` (`FormDatePicker`), `Form.Select` (`FormSelect`), `Form.Segment` (`FormSegment`) — form-bound Segmented control, `Form.Group` (`FormGroup`) — visual grouping section, `Form.InputNumber` (`FormInputNumber`) — numeric input, `Form.InputPassword` (`FormInputPassword`) — password input with visibility toggle, `Form.InputMask` (`FormInputMask`) — masked input (requires `mask` prop), `Form.ColorPicker` (`FormColorPicker`) — color picker, `Form.Radio` (`FormRadio`) — radio button group.

### FormLabel (Form.Label)

Reusable form field label used by form controls.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | **Required.** Label content |
| `htmlFor` | `string` | Associated input id |
| `description` | `ReactNode` | Optional description shown below label |
| `required` | `boolean` | Shows required marker (`*`) |
| `onLabelClick` | `() => void` | Optional custom label click handler |
| `className` | `string` | Custom class |

### FormDescription (Form.Description)

Reusable description text primitive used below labels/fields.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | Description content |
| `className` | `string` | Custom class |
| `style` | `CSSProperties` | Inline style |

### FormError (Form.Error)

Reusable field error primitive rendered as alert text.

| Prop | Type | Description |
|---|---|---|
| `message` | `string` | Error message |
| `className` | `string` | Custom class |
| `style` | `CSSProperties` | Inline style |

### FormBlock (Form.Block)

Reusable form field wrapper for custom controls, while preserving the same label/control/error layout used by built-in form fields.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | **Required.** Custom control content |
| `label` | `ReactNode` | Field label |
| `description` | `ReactNode` | Description below label |
| `error` | `ReactNode` | Error content rendered below control |
| `helperText` | `ReactNode` | Helper text below control |
| `required` | `boolean` | Shows required marker on label |
| `htmlFor` | `string` | Optional target id for label `htmlFor` |
| `onLabelClick` | `() => void` | Optional custom label click handler |
| `className` | `string` | Wrapper class |
| `style` | `CSSProperties` | Wrapper style |
| `labelClassName` | `string` | Label area class |
| `labelStyle` | `CSSProperties` | Label area style |
| `controlClassName` | `string` | Control area class |
| `controlStyle` | `CSSProperties` | Control area style |

### FormGroup

| Prop | Type | Description |
|---|---|---|
| `title` | `ReactNode` | Group title |
| `description` | `ReactNode` | Group description |
| `icon` | `any` | Group icon |
| `extra` | `ReactNode` | Extra content |
| `children` | `ReactNode` | Fields |
| `collapsible` | `boolean` | Collapsible |
| `defaultCollapsed` | `boolean` | Default collapsed |
| `variant` | `FormVariant` | Variant |

### FormSegment (Form.Segment)

Form-bound Segmented control. Wraps the `Segmented` component and connects it to form state. Accepts all `SegmentedProps` plus form-binding props.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `options` | `SegmentedProps['options']` | **Required.** Segment options (from antd `Segmented`) |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `block` | `boolean` | Full width |
| `size` | `'large' \| 'middle' \| 'small'` | Size |
| `disabled` | `boolean` | Disabled |

### FormTextarea (Form.Textarea)

Form-bound multiline input. Wraps `TextArea` and connects it to form state. Accepts all `TextAreaProps` (Ant Design `Input.TextArea`) plus form-binding props.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `required` | `boolean` | Required marker |
| `helperText` | `ReactNode` | Helper text below input |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `...TextAreaProps` | `TextAreaProps` | All textarea props (e.g. `maxLength`, `rows`, `autoSize`, `showCount`, `allowClear`) |

### FormInputNumber (Form.InputNumber)

Form-bound numeric input. Wraps `InputNumber` and connects it to form state.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `required` | `boolean` | Required marker |
| `helperText` | `ReactNode` | Helper text below input |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `min` | `number` | Minimum value |
| `max` | `number` | Maximum value |
| `step` | `number` | Step increment |
| `precision` | `number` | Decimal precision |
| `prefix` | `ReactNode` | Prefix element |
| `suffix` | `ReactNode` | Suffix element |
| `disabled` | `boolean` | Disabled |

### FormInputPassword (Form.InputPassword)

Form-bound password input with visibility toggle. Wraps `InputPassword` and connects it to form state.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `required` | `boolean` | Required marker |
| `helperText` | `ReactNode` | Helper text below input |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `placeholder` | `string` | Placeholder text |
| `disabled` | `boolean` | Disabled |

### FormInputMask (Form.InputMask)

Form-bound masked input. Wraps `InputMask` and connects it to form state. Requires the `mask` prop.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `required` | `boolean` | Required marker |
| `helperText` | `ReactNode` | Helper text below input |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `mask` | `string \| Inputmask.Options['mask']` | **Required.** Input mask pattern (`X`/`x` = digit placeholder) |
| `maskChar` | `string \| null` | Mask placeholder character |
| `maskPlaceholder` | `string \| null` | Mask placeholder string |
| `alwaysShowMask` | `boolean` | Always show the mask |
| `placeholder` | `string` | Placeholder text |
| `disabled` | `boolean` | Disabled |

### FormColorPicker (Form.ColorPicker)

Form-bound color picker. Wraps the antd `ColorPicker` and connects it to form state. Stores the selected color as a CSS string (e.g. `'#1677ff'`).

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `string` | Field label |
| `description` | `ReactNode` | Field description |
| `required` | `boolean` | Required marker |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `showText` | `boolean \| ((color) => ReactNode)` | Show color value text next to swatch |
| `format` | `'hex' \| 'rgb' \| 'hsb'` | Color format |
| `presets` | `PresetsItem[]` | Preset color palettes |
| `allowClear` | `boolean` | Allow clearing the color |
| `disabledAlpha` | `boolean` | Disable alpha channel |
| `size` | `'large' \| 'middle' \| 'small'` | Size |
| `disabled` | `boolean` | Disabled |

### FormRadio (Form.Radio)

Form-bound radio group. Wraps antd `Radio.Group` and connects it to form state. Supports `Radio` children or `options` prop.

| Prop | Type | Description |
|---|---|---|
| `name` | `keyof T & string` | **Required.** Field name |
| `form` | `FormInstance<T>` | Form instance |
| `label` | `ReactNode` | Field label |
| `description` | `ReactNode` | Field description |
| `rules` | `FormFieldRules<T>` | Inline validation rules |
| `options` | `RadioGroupProps['options']` | Options array (alternative to children) |
| `optionType` | `'default' \| 'button'` | Option render type |
| `disabled` | `boolean` | Disabled |

```tsx
<FormRadio form={form} name="contactMethod" label="Preferred Contact">
  <Radio value="email">Email</Radio>
  <Radio value="phone">Phone</Radio>
  <Radio value="sms">SMS</Radio>
</FormRadio>
```

### useForm Hook

```tsx
const { values, errors, touched, isSubmitting, isValid, form, setFieldValue, handleSubmit, resetForm } = useForm({
  initialValues: { name: '' },
  onSubmit: (values) => { ... },
  validate: (values) => ({ name: values.name ? undefined : 'Required' }),
});
```

### FormModal

A modal dialog with an embedded `Form`. The footer (submit button) is always visible while the body scrolls. Supports all Form layout props.

| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | Form content |
| `title` | `ReactNode` | Modal title |
| `form` | `FormInstance<T>` | Form instance |
| `initialValues` | `T` | Initial values |
| `onSubmit` | `FormProps['onSubmit']` | Submit handler |
| `validate` | `FormProps['validate']` | Validation |
| `submitText` | `string` | Submit button text |
| `submitButtonProps` | `ButtonProps` | Submit button props |
| `loading` | `boolean` | Loading state |
| `layout` | `'vertical' \| 'horizontal'` | Form field layout direction |
| `labelWidth` | `string \| number` | Label column width when horizontal (default `'200px'`) |
| `fieldMinWidth` | `string \| number` | Minimum width for field controls |
| `maxWidth` | `string \| number` | Maximum width of the form inside the modal |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | Visual style for form fields |

### Form Usage Examples

#### Basic Form (Vertical Layout)

```tsx
import { Form, useForm, Button } from '@gomeniucivan/ui';

interface MyFormValues {
  name: string;
  email: string;
  role: string;
  notifications: boolean;
  agreeToTerms: boolean;
}

function MyPage() {
  const { form } = useForm<MyFormValues>({
    initialValues: {
      name: '',
      email: '',
      role: '',
      notifications: false,
      agreeToTerms: false,
    },
    onSubmit: async (values) => {
      console.log('Submitted:', values);
    },
    validate: (values) => {
      const errors: Partial<Record<keyof MyFormValues, string>> = {};
      if (!values.name) errors.name = 'Name is required';
      if (!values.email) errors.email = 'Email is required';
      if (values.email && !/\S+@\S+\.\S+/.test(values.email)) errors.email = 'Invalid email';
      if (!values.role) errors.role = 'Please select a role';
      if (!values.agreeToTerms) errors.agreeToTerms = 'You must agree to the terms';
      return errors;
    },
  });

  return (
    <Form form={form} variant="outlined">
      <Form.Input
        name="name"
        label="Full Name"
        description="Enter your full name"
        form={form}
        required
        placeholder="John Doe"
      />

      <Form.Input
        name="email"
        label="Email"
        form={form}
        required
        placeholder="john@example.com"
      />

      <Form.Select
        name="role"
        label="Role"
        description="Select your role in the organization"
        form={form}
        required
        options={[
          { label: 'Admin', value: 'admin' },
          { label: 'Editor', value: 'editor' },
          { label: 'Viewer', value: 'viewer' },
        ]}
        placeholder="Select a role..."
      />

      <Form.Switch
        name="notifications"
        label="Enable Notifications"
        description="Receive email notifications for updates"
        form={form}
      />

      <Form.Checkbox
        name="agreeToTerms"
        label="I agree to the Terms & Conditions"
        form={form}
      />

      <Button type="primary" onClick={form.handleSubmit}>
        Submit
      </Button>
    </Form>
  );
}
```

#### Horizontal Layout with FormGroup

```tsx
import { Form, useForm, Button, Flex } from '@gomeniucivan/ui';
import { Settings, Bell } from 'lucide-react';

interface SettingsValues {
  displayName: string;
  bio: string;
  theme: string;
  language: string;
  emailNotifications: boolean;
  pushNotifications: boolean;
  startDate: any;
  meetingTime: string;
}

function SettingsPage() {
  const { form } = useForm<SettingsValues>({
    initialValues: {
      displayName: 'John Doe',
      bio: '',
      theme: 'dark',
      language: 'en',
      emailNotifications: true,
      pushNotifications: false,
      startDate: null,
      meetingTime: '',
    },
    onSubmit: async (values) => {
      await saveSettings(values);
    },
  });

  return (
    <Form form={form} layout="horizontal" labelWidth="220px" variant="borderless">
      <Form.Group title="Profile" description="Manage your profile settings" icon={Settings}>
        <Form.Input
          name="displayName"
          label="Display Name"
          form={form}
          required
        />

        <Form.Textarea
          name="bio"
          label="Bio"
          description="Short description about yourself"
          form={form}
          maxLength={280}
          showCount
          autoSize={{ minRows: 3, maxRows: 6 }}
        />

        <Form.Segment
          name="theme"
          label="Theme"
          form={form}
          options={[
            { label: 'Light', value: 'light' },
            { label: 'Dark', value: 'dark' },
            { label: 'System', value: 'system' },
          ]}
        />

        <Form.Select
          name="language"
          label="Language"
          form={form}
          options={[
            { label: 'English', value: 'en' },
            { label: 'Spanish', value: 'es' },
            { label: 'French', value: 'fr' },
          ]}
        />
      </Form.Group>

      <Form.Group title="Notifications" description="Configure notifications" icon={Bell} collapsible>
        <Form.Switch
          name="emailNotifications"
          label="Email Notifications"
          description="Receive updates via email"
          form={form}
        />

        <Form.Switch
          name="pushNotifications"
          label="Push Notifications"
          form={form}
        />
      </Form.Group>

      <Form.Group title="Schedule">
        <Form.DatePicker
          name="startDate"
          label="Start Date"
          form={form}
        />

        <Form.TimePicker
          name="meetingTime"
          label="Meeting Time"
          form={form}
          use12Hours
        />
      </Form.Group>

      <Flex horizontal gap={8} justify="flex-end">
        <Button onClick={form.resetForm}>Reset</Button>
        <Button type="primary" onClick={form.handleSubmit}>
          Save Settings
        </Button>
      </Flex>
    </Form>
  );
}
```

#### Inline Validation Rules (per-field)

Instead of a global `validate` function, you can use `rules` on each field:

```tsx
<Form.Input
  name="username"
  label="Username"
  form={form}
  rules={{
    required: 'Username is required',
    minLength: { value: 3, message: 'Must be at least 3 characters' },
    maxLength: { value: 20, message: 'Must be 20 characters or less' },
    pattern: { value: /^[a-zA-Z0-9_]+$/, message: 'Only letters, numbers, and underscores' },
  }}
/>

<Form.Input
  name="email"
  label="Email"
  form={form}
  rules={{
    required: 'Email is required',
    validate: (value) => {
      if (!/\S+@\S+\.\S+/.test(value)) return 'Invalid email format';
    },
  }}
/>

{/* Shorthand — just a required message string */}
<Form.Input
  name="phone"
  label="Phone"
  form={form}
  rules="Phone number is required"
/>
```

#### FormModal Example

```tsx
import { FormModal, useForm, Button } from '@gomeniucivan/ui';
import { useState } from 'react';

interface CreateUserValues {
  name: string;
  email: string;
  role: string;
}

function UserManagement() {
  const [open, setOpen] = useState(false);

  const { form } = useForm<CreateUserValues>({
    initialValues: { name: '', email: '', role: 'viewer' },
    onSubmit: async (values) => {
      await createUser(values);
      setOpen(false);
    },
    validate: (values) => {
      const errors: Partial<Record<keyof CreateUserValues, string>> = {};
      if (!values.name) errors.name = 'Required';
      if (!values.email) errors.email = 'Required';
      return errors;
    },
  });

  return (
    <>
      <Button type="primary" onClick={() => setOpen(true)}>
        Add User
      </Button>

      <FormModal
        title="Create User"
        open={open}
        onCancel={() => setOpen(false)}
        form={form}
        submitText="Create"
        layout="horizontal"
        labelWidth="120px"
        variant="outlined"
      >
        <Form.Input name="name" label="Name" form={form} required />
        <Form.Input name="email" label="Email" form={form} required />
        <Form.Select
          name="role"
          label="Role"
          form={form}
          options={[
            { label: 'Admin', value: 'admin' },
            { label: 'Editor', value: 'editor' },
            { label: 'Viewer', value: 'viewer' },
          ]}
        />
      </FormModal>
    </>
  );
}
```

#### All Form Imports

```tsx
// Core Form
import { Form, useForm } from '@gomeniucivan/ui';
import type { FormProps, FormConfig, FormState, UseFormReturn } from '@gomeniucivan/ui';

// Individual sub-components (also available as Form.Input, Form.Select, etc.)
import {
  FormInput,
  FormTextarea,
  FormBlock,
  FormLabel,
  FormDescription,
  FormError,
  FormSelect,
  FormCheckbox,
  FormSwitch,
  FormDatePicker,
  FormTimePicker,
  FormSegment,
  FormGroup,
  FormInputNumber,
  FormInputPassword,
  FormInputMask,
  FormColorPicker,
  FormRadio,
} from '@gomeniucivan/ui';

// Radio
import { Radio } from '@gomeniucivan/ui';
import type { RadioProps, RadioGroupProps } from '@gomeniucivan/ui';

// ColorPicker (standalone)
import { ColorPicker } from '@gomeniucivan/ui';
import type { ColorPickerProps } from '@gomeniucivan/ui';

// Validation helpers
import { runRules } from '@gomeniucivan/ui';
import type { FormFieldRules } from '@gomeniucivan/ui';

// FormModal
import { FormModal } from '@gomeniucivan/ui';
import type { FormModalProps } from '@gomeniucivan/ui';
```

---

## Data Display

### FolderTree

Hierarchical folder tree for displaying nested categories with expand/collapse, folder icons, tags, and customisable colours.

| Prop | Type | Default | Description |
|---|---|---|---|
| `data` | `FolderTreeNode[]` | **Required** | Tree data |
| `folderColor` | `string` | `'#66bb6a'` | Default folder icon colour |
| `leafColor` | `string` | `'#90a4ae'` | Leaf icon colour |
| `expandedKeys` | `Key[]` | | Controlled expanded keys |
| `defaultExpandedKeys` | `Key[]` | | Default expanded keys |
| `onExpandedKeysChange` | `(keys: Key[]) => void` | | Callback on expand/collapse |
| `onNodeClick` | `(node: FolderTreeNode) => void` | | Callback on node click |
| `showCount` | `boolean` | `true` | Show child count next to folders |
| `indent` | `number` | `24` | Indent per nesting level (px) |
| `iconSize` | `number` | `18` | Folder/leaf icon size (px) |
| `fontSize` | `number \| string` | `14` | Label font size |

**FolderTreeNode shape:** `{ key, label, tag?, icon?, folderColor?, children?, disabled?, count? }`

- `count` — explicit count displayed next to the label, overrides `children.length`. Useful for server-side totals.
- `icon` — custom `ReactNode` icon (e.g. `<Icon icon={Star} size={18} />`), replaces the default folder icon.
- Nodes support arbitrary nesting depth (children of children of children…).

Also exports: `FolderIcon` — standalone folder SVG icon with `color`, `open`, `size` props.

### Accordion / AccordionItem

**AccordionProps:**

| Prop | Type | Default | Description |
|---|---|---|---|
| `accordion` | `boolean` | `false` | Single item expand |
| `children` | `ReactNode` | | AccordionItem children |
| `defaultExpandedKeys` | `Key[]` | | Default expanded |
| `expandedKeys` | `Key[]` | | Controlled expanded |
| `onExpandedChange` | `(keys: Key[]) => void` | | Change callback |
| `gap` | `number` | | Item gap |
| `showDivider` | `boolean` | `false` | Show dividers |
| `hideIndicator` | `boolean` | `false` | Hide chevron |
| `indicatorPlacement` | `'end' \| 'start'` | `'start'` | Indicator position |
| `keepContentMounted` | `boolean` | `true` | Keep content mounted |
| `disableAnimation` | `boolean` | `false` | Disable animation |
| `variant` | `BlockProps['variant']` | | Visual variant |

**AccordionItemProps:**

| Prop | Type | Description |
|---|---|---|
| `itemKey` | `Key` | **Required.** Unique key |
| `title` | `ReactNode` | **Required.** Item title |
| `children` | `ReactNode` | Content |
| `expand` | `boolean` | Controlled expand |
| `defaultExpand` | `boolean` | Default expand |
| `onExpandChange` | `(expanded: boolean) => void` | Callback |
| `disabled` | `boolean` | Disabled |
| `allowExpand` | `boolean` | Allow expanding (default `true`) |
| `hideIndicator` | `boolean` | Hide indicator |
| `indicator` | `ReactNode \| (props) => ReactNode` | Custom indicator |
| `indicatorPlacement` | `'end' \| 'start'` | Indicator position |
| `action` | `ReactNode` | Hover action |
| `variant` | `BlockProps['variant']` | Variant |

### Collapse

Extends Ant Design `Collapse`.

| Prop | Type | Description |
|---|---|---|
| `items` | `CollapseItemType[]` | **Required.** Items with `desc`, `icon` |
| `collapsible` | `boolean` | Enable collapse |
| `gap` | `number` | Gap |
| `padding` | `number \| string \| { body?, header? }` | Padding |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### List / ListItem

| Prop (ListItem) | Type | Description |
|---|---|---|
| `key` | `string` | **Required.** Unique key |
| `title` | `ReactNode` | **Required.** Title |
| `description` | `ReactNode` | Description |
| `avatar` | `ReactNode` | Avatar |
| `actions` | `ReactNode` | Actions |
| `addon` | `ReactNode` | Additional content |
| `active` | `boolean` | Active state |
| `date` | `number` | Timestamp |
| `loading` | `boolean` | Loading |
| `pin` | `boolean` | Pinned |
| `showAction` | `boolean` | Always show actions |

**ListProps:** `items`, `activeKey`, `onClick`.

### Table

| Prop | Type | Description |
|---|---|---|
| `data` | `{ bind?: T[], read?: TableReadConfig }` | **Required.** Data source (local array or remote API) |
| `columns` | `TableColumn<T>[]` | **Required.** Column definitions with `key`, `title`, `item`, `func`, `sortable`, `width`, `align`, `fixed` |
| `pagination` | `boolean` | Enable pagination |
| `sortable` | `boolean` | Enable sorting |
| `filterable` | `boolean` | Enable filter |
| `selectable` | `boolean` | Enable row selection |
| `reload` | `boolean` | Show reload button |
| `height` | `number \| string` | Fixed height |
| `rowHeight` | `number` | Row height |
| `overscan` | `number` | Virtual scroll overscan |
| `defaultPageSize` | `number` | Initial page size |
| `pageSize` | `{ visible?, count?, options? }` | Page size config |
| `emptyState` | `ReactNode` | Custom empty state |
| `onDataChange` | `(rows: T[]) => void` | Data change callback |

### SortableList

Drag-and-drop sortable list.

| Prop | Type | Description |
|---|---|---|
| `items` | `SortableListItem[]` | **Required.** Items with `id` |
| `onChange` | `(items) => void` | **Required.** Reorder handler |
| `renderItem` | `(item) => ReactNode` | **Required.** Item renderer |

### Tabs

Extends Ant Design `Tabs`.

| Prop | Type | Description |
|---|---|---|
| `compact` | `boolean` | Compact mode |
| `variant` | `'square' \| 'rounded' \| 'point'` | Tab style |

### Toc

Table of contents navigation.

| Prop | Type | Description |
|---|---|---|
| `items` | `TocItemType[]` | **Required.** TOC items with `id`, `title`, `children` |
| `activeKey` | `string` | Active item |
| `onChange` | `(activeKey) => void` | Change callback |
| `headerHeight` | `number` | Scroll offset |
| `tocWidth` | `number` | Width |
| `isMobile` | `boolean` | Mobile mode |

---

## Overlays

### Modal

Extends Ant Design `Modal`. Also exports `createModal`, `createRawModal`, `ModalProvider`, `ModalHost`, `useModalContext`.

| Prop | Type | Description |
|---|---|---|
| `allowFullscreen` | `boolean` | Fullscreen button |
| `enableResponsive` | `boolean` | Responsive mode |
| `paddings` | `{ desktop?, mobile? }` | Padding config |

### ConfirmationModal

Imperative confirmation API built on top of `antd` `Modal.confirm`.

Also exports: `confirmConfirmationModal`.

#### Methods

| Method | Description | Type |
|---|---|---|
| `ConfirmationModal.confirm` | Open a confirmation modal with full config | `(props: ConfirmationModalProps) => { destroy; update }` |
| `ConfirmationModal.danger` | Open danger-style confirmation (danger icon + danger OK button) | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
| `ConfirmationModal.error` | Alias of `danger` | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
| `ConfirmationModal.warning` | Open warning-style confirmation | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
| `ConfirmationModal.info` | Open info-style confirmation | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |

#### ConfirmationModalProps

Extends Ant Design `ModalFuncProps` with additional type mapping:

| Prop | Type | Description |
|---|---|---|
| `type` | `'danger' \| 'info' \| 'warning' \| 'error'` | Visual variant that controls icon and OK button danger state |
| `okType` | `ModalFuncProps['okType'] \| 'danger'` | Accepts `'danger'` shortcut (mapped to primary + `danger: true`) |
| `icon` | `ReactNode` | Custom icon override |
| `okButtonProps` | `ButtonProps` | OK button props (danger auto-applied for `danger`/`error`) |
| `...rest` | `ModalFuncProps` | All native `Modal.confirm` options (`title`, `content`, `onOk`, etc.) |

### Drawer

Extends Ant Design `Drawer`.

| Prop | Type | Description |
|---|---|---|
| `sidebar` | `ReactNode` | Sidebar panel |
| `sidebarWidth` | `number` | Sidebar width |
| `noHeader` | `boolean` | Hide header |
| `containerMaxWidth` | `number \| string` | Body max width |
| `closeIconProps` | `ActionIconProps` | Close icon config |

### Popover

Built on Base UI Popover.

| Prop | Type | Default | Description |
|---|---|---|---|
| `content` | `ReactNode` | | **Required.** Popup content |
| `children` | `ReactElement \| ReactNode` | | **Required.** Trigger |
| `trigger` | `Trigger` | `'hover'` | Trigger mode |
| `placement` | `PopoverPlacement` | `'top'` | Placement |
| `arrow` | `boolean` | `false` | Show arrow |
| `open` | `boolean` | | Controlled |
| `defaultOpen` | `boolean` | `false` | Default open |
| `onOpenChange` | `(open) => void` | | Callback |
| `disabled` | `boolean` | | Disabled |
| `inset` | `boolean` | `false` | Inset display |
| `standalone` | `boolean` | | Ignore PopoverGroup |
| `mouseEnterDelay` | `number` | `0.1` | Enter delay (seconds) |
| `mouseLeaveDelay` | `number` | `0.1` | Leave delay (seconds) |
| `openDelay` | `number` | | Open delay (ms, overrides mouseEnterDelay) |
| `closeDelay` | `number` | | Close delay (ms) |
| `zIndex` | `number` | | Z-index |

### Tooltip

Built on Base UI Tooltip. Also exports `TooltipGroup`.

| Prop | Type | Default | Description |
|---|---|---|---|
| `title` | `ReactNode` | | **Required.** Tooltip content |
| `children` | `ReactElement \| ReactNode` | | **Required.** Trigger |
| `placement` | `TooltipPlacement` | | Placement |
| `arrow` | `boolean` | `false` | Show arrow |
| `open` | `boolean` | | Controlled |
| `defaultOpen` | `boolean` | | Default open |
| `onOpenChange` | `(open) => void` | | Callback |
| `disabled` | `boolean` | | Disabled |
| `hotkey` | `string` | | Hotkey hint |
| `hotkeyProps` | `Omit<HotkeyProps, 'keys'>` | | Hotkey config |
| `standalone` | `boolean` | | Ignore TooltipGroup |
| `mouseEnterDelay` | `number` | | Enter delay (seconds) |
| `mouseLeaveDelay` | `number` | | Leave delay (seconds) |
| `openDelay` | `number` | | Open delay (ms) |
| `closeDelay` | `number` | | Close delay (ms) |
| `zIndex` | `number` | | Z-index |

### Dropdown

Extends Ant Design `Dropdown` with custom `Menu`.

| Prop | Type | Description |
|---|---|---|
| `menu` | `MenuProps` | **Required.** Menu configuration |
| `iconProps` | `IconContentConfig` | Icon config |

### DropdownMenu

Built on Base UI Menu. Includes many atomic sub-components.

| Prop | Type | Default | Description |
|---|---|---|---|
| `children` | `ReactNode` | | **Required.** Trigger element |
| `items` | `DropdownItem[] \| () => DropdownItem[]` | | **Required.** Menu items |
| `placement` | `DropdownMenuPlacement` | | Placement |
| `trigger` | `Trigger` | `'click'` | Trigger mode |
| `iconSpaceMode` | `'global' \| 'group'` | `'global'` | Icon space reservation |
| `nativeButton` | `boolean` | | Use native button trigger |

### ContextMenu

Right-click context menu. Exports `ContextMenuHost`, `ContextMenuTrigger`, `showContextMenu`, `closeContextMenu`, `updateContextMenuItems`.

### Toast

Toast notification system. Exports `toast` API, `ToastHost`, `useToast`.

**toast API methods:** `toast(options)`, `toast.success(...)`, `toast.error(...)`, `toast.info(...)`, `toast.warning(...)`, `toast.loading(...)`, `toast.promise(...)`, `toast.dismiss(id?)`.

| Prop (ToastOptions) | Type | Default | Description |
|---|---|---|---|
| `title` | `ReactNode` | | Toast title |
| `description` | `ReactNode` | | Description |
| `type` | `'success' \| 'info' \| 'warning' \| 'error' \| 'loading' \| 'default'` | `'default'` | Type |
| `duration` | `number` | `5000` | Duration (ms) |
| `icon` | `IconProps['icon']` | | Custom icon |
| `closable` | `boolean` | `true` | Can close |
| `placement` | `ToastPosition` | | Position override |
| `actions` | `ToastAction[]` | | Action buttons |
| `onClose` | `() => void` | | Close callback |

**ToastHost Props:**

| Prop | Type | Default | Description |
|---|---|---|---|
| `position` | `ToastPosition` | `'bottom-right'` | Default toast position |
| `duration` | `number` | `5000` | Default duration (ms) |
| `limit` | `number` | `5` | Max visible toasts |
| `swipeDirection` | `('left' \| 'right' \| 'up' \| 'down')[]` | `['down', 'right']` | Swipe to dismiss direction |
| `root` | `HTMLElement \| ShadowRoot \| null` | | Portal root |
| `className` | `string` | | Custom class |

### Toast Usage Examples

#### 1. Setup — Add `ToastHost` to your app root

`ToastHost` must be rendered once at the top level of your app. Without it, toasts will not appear.

```tsx
import { ThemeProvider, ToastHost } from '@gomeniucivan/ui';

function App() {
  return (
    <ThemeProvider>
      {/* Your app content */}
      <MyRoutes />

      {/* Render once at the root — configures default position, duration, etc. */}
      <ToastHost position="bottom-right" duration={5000} limit={5} />
    </ThemeProvider>
  );
}
```

#### 2. Simple toasts (string shorthand)

```tsx
import { toast } from '@gomeniucivan/ui';

// Each method accepts a string (used as description) or a full options object
toast.success('Changes saved successfully');
toast.error('Something went wrong');
toast.info('New version available');
toast.warning('Your session will expire soon');
```

#### 3. Toast with full options

```tsx
import { toast } from '@gomeniucivan/ui';
import { Rocket } from 'lucide-react';

toast.success({
  title: 'Deployment Complete',
  description: 'Your app has been deployed to production.',
  icon: Rocket,
  duration: 8000,
  placement: 'top-right',   // override default position for this toast
  closable: true,
  onClose: () => console.log('Toast closed'),
});
```

#### 4. Loading + Promise pattern

```tsx
import { toast } from '@gomeniucivan/ui';

// Option A: Manual loading toast
const loadingToast = toast.loading('Uploading file...');
try {
  await uploadFile(file);
  loadingToast.close();
  toast.success('File uploaded!');
} catch (err) {
  loadingToast.close();
  toast.error('Upload failed');
}

// Option B: Promise helper (handles loading → success/error automatically)
toast.promise(
  fetch('/api/data').then(res => res.json()),
  {
    loading: 'Fetching data...',
    success: (data) => `Loaded ${data.length} items`,
    error: (err) => `Error: ${err.message}`,
  }
);

// Promise helper with full options objects
toast.promise(saveSettings(values), {
  loading: { title: 'Saving', description: 'Applying your settings...' },
  success: { title: 'Saved', description: 'Settings updated successfully.' },
  error: { title: 'Error', description: 'Failed to save settings.' },
});
```

#### 5. Toast with action buttons

```tsx
import { toast } from '@gomeniucivan/ui';

toast({
  type: 'info',
  title: 'Item Deleted',
  description: 'The item has been moved to trash.',
  actions: [
    {
      label: 'Undo',
      variant: 'primary',
      onClick: () => restoreItem(itemId),
    },
    {
      label: 'Dismiss',
      variant: 'ghost',
    },
  ],
});
```

#### 6. Update & dismiss toasts

```tsx
import { toast } from '@gomeniucivan/ui';

// Create a toast and get the instance
const instance = toast.info({ title: 'Processing...', duration: 0 });

// Update it later
instance.update({ title: 'Almost done...', description: '90% complete' });

// Close a specific toast
instance.close();

// Dismiss all toasts
toast.dismiss();

// Dismiss a specific toast by ID
toast.dismiss(instance.id);
```

#### 7. Using `useToast` hook (inside components)

```tsx
import { useToast, Button } from '@gomeniucivan/ui';

function SaveButton({ onSave }: { onSave: () => Promise<void> }) {
  const toast = useToast();

  const handleSave = async () => {
    try {
      await onSave();
      toast.success('Saved!');
    } catch {
      toast.error('Save failed');
    }
  };

  return <Button onClick={handleSave}>Save</Button>;
}
```

#### All Toast Imports

```tsx
// Toast API (imperative, works anywhere)
import { toast, ToastHost, useToast } from '@gomeniucivan/ui';

// Types
import type {
  ToastAPI,
  ToastOptions,
  ToastInstance,
  ToastHostProps,
  ToastPosition,
  ToastType,
  ToastAction,
  ToastPromiseOptions,
  ToastProps,
} from '@gomeniucivan/ui';
```

---

## Media

### Avatar / AvatarGroup

| Prop (Avatar) | Type | Description |
|---|---|---|
| `avatar` | `string \| ReactNode` | Avatar content |
| `size` | `number` | Size in px |
| `shape` | `'circle' \| 'square'` | Shape |
| `title` | `string` | Tooltip title |
| `animation` | `boolean` | Hover animation |
| `background` | `string` | Background colour |
| `bordered` | `boolean` | Show border |
| `borderedColor` | `string` | Border colour |
| `loading` | `boolean` | Loading skeleton |
| `shadow` | `boolean` | Shadow |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | Variant |
| `tooltipProps` | `Omit<TooltipProps, 'children' \| 'title'>` | Tooltip config |

**AvatarGroup:** `items`, `max`, `onClick`, `zIndexReverse`.

### GroupAvatar

Grid-based group avatar.

| Prop | Type | Description |
|---|---|---|
| `avatars` | `(string \| AvatarProps)[]` | Avatar list |
| `size` | `number` | Container size |
| `grid` | `2 \| 3 \| 'auto'` | Grid layout |
| `avatarShape` | `'circle' \| 'square'` | Individual shape |
| `cornerShape` | `string` | Smooth corner mask |

### Image / PreviewGroup

Extends Ant Design `Image`. **PreviewGroup** enables gallery mode.

| Prop (Image) | Type | Description |
|---|---|---|
| `actions` | `ReactNode` | Overlay actions |
| `alwaysShowActions` | `boolean` | Always show actions |
| `preview` | `boolean \| ImagePreviewOptions` | Preview config |
| `toolbarAddon` | `ReactNode` | Extra toolbar items |
| `objectFit` | `'cover' \| 'contain'` | Object fit |
| `size` | `number \| string` | Shorthand size |
| `maxWidth/maxHeight/minWidth/minHeight` | `number \| string` | Dimension constraints |
| `isLoading` | `boolean` | Loading state |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | Variant |

### Video

| Prop | Type | Default | Description |
|---|---|---|---|
| `src` | `string` | | **Required.** Video source |
| `autoPlay` | `boolean` | | Auto play |
| `loop` | `boolean` | | Loop |
| `muted` | `boolean` | | Muted |
| `poster` | `string` | | Poster image |
| `preview` | `boolean` | `true` | Show play overlay |
| `preload` | `string` | `'auto'` | Preload |
| `isLoading` | `boolean` | | Loading skeleton |
| `variant` | `'borderless' \| 'filled' \| 'outlined'` | `'filled'` | Variant |
| `width/height` | `number \| string` | | Dimensions |
| `maxWidth/maxHeight/minWidth/minHeight` | `number \| string` | | Constraints |
| `size` | `number \| string` | | Shorthand size |

### FluentEmoji

| Prop | Type | Description |
|---|---|---|
| `emoji` | `string` | **Required.** Emoji character |
| `size` | `number` | Size |
| `type` | `EmojiType` | Emoji style type |
| `unoptimized` | `boolean` | Disable optimization |

### EmojiPicker

Avatar/emoji picker with popover.

| Prop | Type | Description |
|---|---|---|
| `value` | `string` | Selected emoji/avatar |
| `defaultAvatar` | `string` | Default avatar |
| `onChange` | `(emoji: string) => void` | Change handler |
| `allowUpload` | `boolean \| { enableEmoji? }` | Enable upload |
| `allowDelete` | `boolean` | Enable delete |
| `onUpload` | `(file: File) => void` | Upload handler |
| `onDelete` | `() => void` | Delete handler |
| `customEmojis` | `EmojiPickerCustomEmoji[]` | Custom emojis |
| `customTabs` | `EmojiPickerCustomTab[]` | Custom tabs |
| `locale` | `string` | Locale |
| `size` | `number` | Avatar size |
| `open` | `boolean` | Controlled open |
| `onOpenChange` | `(open) => void` | Open callback |
| `loading` | `boolean` | Loading |

### FileTypeIcon

| Prop | Type | Description |
|---|---|---|
| `filetype` | `string` | File extension |
| `type` | `'file' \| 'folder'` | Icon type |
| `size` | `number` | Size |
| `color` | `string` | Colour |
| `icon` | `ReactNode` | Custom icon |
| `variant` | `'color' \| 'mono'` | Style |

### MaterialFileTypeIcon

| Prop | Type | Description |
|---|---|---|
| `filename` | `string` | **Required.** File name |
| `type` | `'file' \| 'folder'` | Type |
| `size` | `number` | Size |
| `open` | `boolean` | Folder open state |
| `variant` | `'raw' \| 'file' \| 'folder'` | Display mode |
| `fallbackUnknownType` | `boolean` | Fallback for unknown types |

---

## Code & Markdown

### Highlighter / SyntaxHighlighter

| Prop (Highlighter) | Type | Description |
|---|---|---|
| `children` | `string` | **Required.** Code content |
| `language` | `string` | **Required.** Language |
| `theme` | `'lobe-theme' \| BuiltinTheme` | Syntax theme |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
| `animated` | `boolean` | Stream animation |
| `copyable` | `boolean` | Copy button |
| `fileName` | `string` | File name display |
| `showLanguage` | `boolean` | Show language label |
| `fullFeatured` | `boolean` | Full featured mode (expand/collapse, etc.) |
| `defaultExpand` | `boolean` | Default expand |
| `wrap` | `boolean` | Word wrap |
| `shadow` | `boolean` | Shadow |
| `enableTransformer` | `boolean` | Enable Shiki transformers |
| `allowChangeLanguage` | `boolean` | Allow language change |
| `icon` | `ReactNode` | Custom icon |

### CodeDiff / PatchDiff

| Prop (CodeDiff) | Type | Default | Description |
|---|---|---|---|
| `oldContent` | `string` | | **Required.** Before |
| `newContent` | `string` | | **Required.** After |
| `language` | `string` | | Language |
| `fileName` | `string` | | File name |
| `viewMode` | `'split' \| 'unified'` | `'split'` | View mode |
| `showHeader` | `boolean` | `true` | Show header |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | `'filled'` | Variant |

**PatchDiff** takes `patch: string` instead of `oldContent`/`newContent`.

### CodeEditor

| Prop | Type | Description |
|---|---|---|
| `value` | `string` | **Required.** Code value |
| `onValueChange` | `(value: string) => void` | **Required.** Change handler |
| `language` | `string` | **Required.** Language |
| `defaultValue` | `string` | Default value |
| `placeholder` | `string` | Placeholder |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### Markdown / Typography

| Prop (Markdown) | Type | Description |
|---|---|---|
| `children` | `string` | **Required.** Markdown content |
| `variant` | `'default' \| 'chat'` | Render mode |
| `animated` | `boolean` | Stream animation |
| `enableLatex` | `boolean` | Enable LaTeX |
| `enableMermaid` | `boolean` | Enable Mermaid diagrams |
| `enableGithubAlert` | `boolean` | GitHub-style alerts |
| `enableStream` | `boolean` | Stream mode |
| `enableImageGallery` | `boolean` | Image gallery |
| `enableCustomFootnotes` | `boolean` | Custom footnotes |
| `allowHtml` | `boolean` | Allow raw HTML |
| `fullFeaturedCodeBlock` | `boolean` | Full code blocks |
| `showFootnotes` | `boolean` | Show footnotes |
| `fontSize` | `number` | Font size |
| `lineHeight` | `number` | Line height |
| `headerMultiple` | `number` | Header size multiplier |
| `customRender` | `(dom, context) => ReactNode` | Custom renderer |
| `onDoubleClick` | `() => void` | Double click handler |
| `componentProps` | `{ a?, highlight?, img?, mermaid?, pre?, video? }` | Component overrides |
| `components` | `Components & Record<string, FC>` | Custom MDX components |
| `remarkPlugins` | `Pluggable[]` | Remark plugins |
| `rehypePlugins` | `Pluggable[]` | Rehype plugins |
| `citations` | `CitationItem[]` | Citation data |

### Mermaid / SyntaxMermaid

| Prop (Mermaid) | Type | Description |
|---|---|---|
| `children` | `string` | **Required.** Mermaid definition |
| `theme` | `'lobe-theme' \| MermaidConfig['theme']` | Theme |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
| `animated` | `boolean` | Animation |
| `copyable` | `boolean` | Copy button |
| `fullFeatured` | `boolean` | Full featured |
| `fileName` | `string` | File name |
| `showLanguage` | `boolean` | Show language |
| `shadow` | `boolean` | Shadow |

### Snippet

| Prop | Type | Description |
|---|---|---|
| `children` | `string` | **Required.** Command text |
| `copyable` | `boolean` | Copy button |
| `language` | `string` | Language |
| `prefix` | `string` | Prefix symbol |
| `shadow` | `boolean` | Shadow |
| `spotlight` | `boolean` | Spotlight effect |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

---

## Navigation

### Menu

Extends Ant Design Menu.

| Prop | Type | Description |
|---|---|---|
| `items` | `GenericItemType[]` | **Required.** Menu items |
| `compact` | `boolean` | Compact mode |
| `shadow` | `boolean` | Shadow |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
| `iconProps` | `IconContentConfig` | Icon config |

### Burger

Mobile hamburger menu.

| Prop | Type | Description |
|---|---|---|
| `opened` | `boolean` | **Required.** Open state |
| `setOpened` | `(state: boolean) => void` | **Required.** Toggle handler |
| `items` | `MenuProps['items']` | **Required.** Menu items |
| `onClick` | `MenuProps['onClick']` | Click handler |
| `selectedKeys` | `MenuProps['selectedKeys']` | Selected keys |
| `openKeys` | `MenuProps['openKeys']` | Open sub-menu keys |
| `fullscreen` | `boolean` | Fullscreen drawer |
| `headerHeight` | `number` | Header height offset |
| `size` | `ActionIconProps['size']` | Icon size |
| `variant` | `ActionIconProps['variant']` | Icon variant |

### Hotkey

Display keyboard shortcuts.

| Prop | Type | Description |
|---|---|---|
| `keys` | `string` | **Required.** Key combination |
| `compact` | `boolean` | Compact layout |
| `inverseTheme` | `boolean` | Inverse colours |
| `isApple` | `boolean` | Use macOS symbols |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |

### EditorSlashMenu

Autocomplete slash-command menu.

Items are typed as `EditorSlashMenuOption` with: `value`, `label`, `icon?`, `extra?`, `keywords?`, `disabled?`, `danger?`. Groups: `EditorSlashMenuGroup` with `label?` and `items`.

---

## Misc

### Alert

Extends Ant Design `Alert`.

| Prop | Type | Description |
|---|---|---|
| `type` | `'success' \| 'info' \| 'warning' \| 'error' \| 'secondary'` | Alert type |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
| `icon` | `IconProps['icon']` | Custom icon |
| `iconProps` | `Omit<IconProps, 'icon'>` | Icon config |
| `glass` | `boolean` | Glass effect |
| `colorfulText` | `boolean` | Coloured text |
| `extra` | `ReactNode` | Extra content |
| `extraDefaultExpand` | `boolean` | Expand extra by default |
| `extraIsolate` | `boolean` | Isolate extra section |

### GuideCard

| Prop | Type | Description |
|---|---|---|
| `title` | `ReactNode` | Title |
| `desc` | `ReactNode` | Description |
| `cover` | `string` | Cover image URL |
| `closable` | `boolean` | Closable |
| `onClose` | `ActionIconProps['onClick']` | Close handler |
| `afterClose` | `() => void` | After close callback |
| `shadow` | `boolean` | Shadow |
| `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
| `width` | `number` | Width |
| `height` | `number` | Height |

### CopyButton

Extends `ActionIcon`. Copies text to clipboard on click.

| Prop | Type | Description |
|---|---|---|
| `content` | `string \| () => string` | **Required.** Content to copy |

### DownloadButton

Extends `ActionIcon`. Downloads a file on click.

| Prop | Type | Description |
|---|---|---|
| `blobUrl` | `string` | Blob URL |
| `fileName` | `string` | File name |
| `fileType` | `string` | MIME type |

### SearchBar

Search input with optional modal.

| Prop | Type | Description |
|---|---|---|
| `defaultValue` | `string` | Default search |
| `value` | `string` | Controlled value |
| `onSearch` | `(value: string) => void` | Search handler |
| `onInputChange` | `(value: string) => void` | Input change |
| `enableShortKey` | `boolean` | Enable shortcut |
| `shortKey` | `string` | Shortcut key |
| `spotlight` | `boolean` | Spotlight mode |
| `loading` | `boolean` | Loading |
| `modal` | `boolean` | Modal mode |
| `modalTitle` | `ReactNode` | Modal title |
| `modalContent` | `ReactNode \| (value, close) => ReactNode` | Modal content |
| `open` | `boolean` | Controlled open |
| `onOpenChange` | `(open) => void` | Open change |

### ThemeSwitch

| Prop | Type | Description |
|---|---|---|
| `themeMode` | `ThemeMode` | **Required.** Current theme |
| `onThemeSwitch` | `(themeMode) => void` | **Required.** Switch handler |
| `type` | `'icon' \| 'select'` | Switch type |
| `size` | `ActionIconProps['size']` | Size |
| `variant` | `ActionIconProps['variant']` | Variant |
| `labels` | `{ auto, dark, light }` | Labels |

### FontLoader

Loads an external font stylesheet.

| Prop | Type | Description |
|---|---|---|
| `url` | `string` | **Required.** Font stylesheet URL |

### A

Anchor element that respects `ConfigProvider.aAs`.

---

## Exported Utilities

| Export | Description |
|---|---|
| `createStyles` | Re-exported from `antd-style`. Create scoped CSS-in-JS styles with full access to the antd theme token. |
| `cx` | Re-exported from `antd-style`. Utility to merge class names (like `classnames`/`clsx`). |
| `useToken` | Custom hook that returns the full antd design token enriched with `isMobile` from `ThemeProvider`. Call `const { colorPrimary, isMobile } = useToken();`. No need for the verbose `theme.useToken()` pattern. |
| `copyToClipboard(text)` | Copy text to clipboard |
| `preventDefault`, `stopPropagation`, `preventDefaultAndStopPropagation` | DOM event helpers |
| `genCdnUrl({ pkg, version, path, proxy })` | Generate CDN URL |
| `placementMap`, `toFloatingUIPlacement` | Placement utilities |
| `combineKeys`, `KeyMapEnum` | Hotkey utilities |
| `preprocessMarkdownContent` | Markdown preprocessing |
| `highlighterThemes`, `mermaidThemes` | Theme objects |
| `menuSharedStyles` | Shared menu styles |
| `CLASSNAMES` | Global CSS class names |
| `ErrorBoundary` | Re-exported from `react-error-boundary` |
| `ShikiLobeTheme` | Shiki code theme |

### Hooks

| Hook | Description |
|---|---|
| `useToken()` | Returns the full antd design token enriched with `isMobile` from `ThemeProvider`. Use `const { colorPrimary, isMobile } = useToken();`. |
| `useForm(config)` | Form state management |
| `useToast()` | Toast API access |
| `useCdnFn()` | Get CDN URL builder |
| `useModalContext()` | Modal context |
| `usePopoverContext()` | Popover context |
| `useSwitchContext()` | Switch context |
| `useMotionComponent()` | Get motion library |
| `useTranslation()` | i18n translation hook |
| `usePopoverPortalContainer()` | Popover portal container |

### Styling Utilities

#### `createStyles`

Create scoped CSS-in-JS styles with access to the antd theme token:

```tsx
import { createStyles } from '@gomeniucivan/ui';

const useStyles = createStyles(({ token, css }) => ({
  container: css`
    background: ${token.colorBgContainer};
    border-radius: ${token.borderRadiusLG}px;
    padding: ${token.paddingLG}px;
  `,
}));

function MyComponent() {
  const { styles } = useStyles();
  return <div className={styles.container}>...</div>;
}
```

#### `cx`

Merge class names (like `classnames`/`clsx`):

```tsx
import { cx } from '@gomeniucivan/ui';

<div className={cx('base', isActive && 'active', className)} />
```

#### `useToken`

Get the full antd design token enriched with `isMobile` from `ThemeProvider`, without the verbose `theme.useToken()` pattern:

```tsx
// ❌ Before (verbose)
import { theme } from 'antd';
const { useToken } = theme;
const { token } = useToken();

// ✅ After (simple)
import { useToken } from '@gomeniucivan/ui';
const { colorPrimary, borderRadiusLG, isMobile } = useToken();

// Use token values
<div style={{ color: colorPrimary, borderRadius: borderRadiusLG }} />

// Use isMobile (reads from ThemeProvider's isMobile prop)
if (isMobile) {
  // render mobile layout
}
```
