@gomeniucivan/ui 1.0.69 → 1.0.72

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.
package/INSTRUCTION.md ADDED
@@ -0,0 +1,2166 @@
1
+ # @gomeniucivan/ui — Component Reference
2
+
3
+ > **Package:** `@gomeniucivan/ui`
4
+ > Use this document as the single source of truth for every exported component and its props.
5
+
6
+ ---
7
+
8
+ ## Setup & Providers
9
+
10
+ ### ConfigProvider
11
+
12
+ Wraps the app to provide CDN config, i18n resources, and the motion library.
13
+
14
+ | Prop | Type | Description |
15
+ |---|---|---|
16
+ | `children` | `ReactNode` | App content |
17
+ | `config` | `Config` | CDN/proxy configuration object |
18
+ | `locale` | `string` | Active locale code (default `'en'`) |
19
+ | `motion` | `MotionComponentType` | **Required.** Pass `motion` from `motion/react` or `motion/react-m` |
20
+ | `resources` | `TranslationResourcesInput` | Translation resources (object or Promise) |
21
+
22
+ #### Config object
23
+
24
+ | Prop | Type | Description |
25
+ |---|---|---|
26
+ | `aAs` | `ElementType` | Custom element for `<A>` links |
27
+ | `imgAs` | `ElementType` | Custom element for images |
28
+ | `imgUnoptimized` | `boolean` | Disable image optimisation |
29
+ | `proxy` | `CDN \| 'custom'` | CDN proxy |
30
+ | `customCdnFn` | `CdnFn` | Custom CDN URL builder |
31
+
32
+ ### ThemeProvider
33
+
34
+ Wraps the app with antd-style theming, global styles, and custom tokens.
35
+
36
+ | Prop | Type | Default | Description |
37
+ |---|---|---|---|
38
+ | `className` | `string` | | Root class |
39
+ | `cy` | `boolean` | | When `true`, components with a `cy` prop render a `data-cy` attribute for Cypress / testing selectors |
40
+ | `customFonts` | `string[]` | | Additional font families |
41
+ | `customStylish` | `(theme) => object` | | Custom stylish tokens |
42
+ | `customTheme` | `{ neutralColor?, primaryColor? }` | | Override neutral/primary colours |
43
+ | `customToken` | `(theme) => object` | | Custom design tokens |
44
+ | `enableCustomFonts` | `boolean` | | Load custom fonts |
45
+ | `enableGlobalStyle` | `boolean` | | Inject global styles |
46
+ | `isMobile` | `boolean` | | Global mobile mode; components with `isMobile` prop inherit this |
47
+ | `style` | `CSSProperties` | | Inline style |
48
+
49
+ ### Cypress Test Selectors (`cy`)
50
+
51
+ 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.
52
+
53
+ **Standalone components:** pass `cy="my-button"` → renders `data-cy="my-button"`.
54
+
55
+ **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:
56
+
57
+ ```tsx
58
+ <ThemeProvider cy>
59
+ <Form cy="profile" form={form}>
60
+ <FormInput name="firstName" /> {/* data-cy="profile-firstName" */}
61
+ <FormSelect name="country" /> {/* data-cy="profile-country" */}
62
+ </Form>
63
+ <Button cy="submit-btn">Save</Button> {/* data-cy="submit-btn" */}
64
+ </ThemeProvider>
65
+ ```
66
+
67
+ Field-level `cy` overrides the auto-computed value: `<FormInput name="firstName" cy="custom" />` → `data-cy="custom"`.
68
+
69
+ **Hook:** `useCy(cy?: string)` returns `{ 'data-cy': cy }` when the provider flag is on, or `{}` otherwise. Useful for custom components.
70
+
71
+ ### Meta
72
+
73
+ SEO meta helper rendered inside `ThemeProvider`.
74
+
75
+ | Prop | Type | Description |
76
+ |---|---|---|
77
+ | `title` | `string` | Page title |
78
+ | `description` | `string` | Meta description |
79
+ | `withManifest` | `boolean` | Include manifest link |
80
+
81
+ ---
82
+
83
+ ## Layout Components
84
+
85
+ ### Flex
86
+
87
+ Extended Ant Design `Flex` with extra convenience props.
88
+
89
+ | Prop | Type | Description |
90
+ |---|---|---|
91
+ | `as` | `ElementType` | Render as custom element |
92
+ | `direction` | `'vertical' \| 'vertical-reverse' \| 'horizontal' \| 'horizontal-reverse'` | Flex direction shorthand |
93
+ | `horizontal` | `boolean` | Shorthand for `direction="horizontal"` |
94
+ | `vertical` | `boolean` | Shorthand for vertical (default) |
95
+ | `distribution` | `CSSProperties['justifyContent']` | Alias for `justify` |
96
+ | `padding` | `number \| string` | CSS padding |
97
+ | `paddingBlock` | `number \| string` | Block padding |
98
+ | `paddingInline` | `number \| string` | Inline padding |
99
+ | `width` | `number \| string` | Width |
100
+ | `height` | `number \| string` | Height |
101
+ | `allowShrink` | `boolean` | Sets `minWidth: 0` |
102
+ | `visible` | `boolean` | When `false`, sets `display: none` |
103
+ | `ref` | `Ref<HTMLElement>` | Ref |
104
+
105
+ ### Grid
106
+
107
+ CSS grid wrapper built on `Flex`.
108
+
109
+ | Prop | Type | Description |
110
+ |---|---|---|
111
+ | `gap` | `string \| number` | Grid gap |
112
+ | `maxItemWidth` | `string \| number` | Max width per grid item |
113
+ | `rows` | `number` | Number of rows |
114
+ | `ref` | `Ref<HTMLDivElement>` | Ref |
115
+
116
+ ### Layout
117
+
118
+ Full-page layout with header, sidebar, content, toc, and footer slots.
119
+
120
+ | Prop | Type | Description |
121
+ |---|---|---|
122
+ | `asideWidth` | `number` | Sidebar width |
123
+ | `children` | `ReactNode` | Content |
124
+ | `content` | `ReactNode` | Main content area |
125
+ | `footer` | `ReactNode` | Footer slot |
126
+ | `header` | `ReactNode` | Header slot |
127
+ | `headerHeight` | `number` | Header height |
128
+ | `helmet` | `ReactNode` | Head/meta slot |
129
+ | `sidebar` | `ReactNode` | Sidebar slot |
130
+ | `toc` | `ReactNode` | Table of contents slot |
131
+ | `tocWidth` | `number` | TOC width |
132
+
133
+ Sub-components: `LayoutHeader`, `LayoutFooter`, `LayoutMain`, `LayoutSidebar`, `LayoutSidebarInner`, `LayoutToc` — each accepts `DivProps` plus layout-specific sizing props (`headerHeight`, `tocWidth`).
134
+
135
+ ### Header
136
+
137
+ | Prop | Type | Description |
138
+ |---|---|---|
139
+ | `actions` | `ReactNode` | Actions area |
140
+ | `logo` | `ReactNode` | Logo |
141
+ | `nav` | `ReactNode` | Navigation |
142
+ | `actionsClassName/Style` | `string / CSSProperties` | Actions styling |
143
+ | `logoClassName/Style` | `string / CSSProperties` | Logo styling |
144
+ | `navClassName/Style` | `string / CSSProperties` | Nav styling |
145
+
146
+ ### Footer
147
+
148
+ | Prop | Type | Description |
149
+ |---|---|---|
150
+ | `bottom` | `ReactNode` | Bottom content |
151
+ | `columns` | `RcFooter columns` | Footer link columns |
152
+ | `contentMaxWidth` | `number` | Max content width |
153
+ | `theme` | `'light' \| 'dark'` | Footer theme |
154
+
155
+ ### SideNav
156
+
157
+ | Prop | Type | Description |
158
+ |---|---|---|
159
+ | `avatar` | `ReactNode` | Avatar slot |
160
+ | `bottomActions` | `ReactNode` | **Required.** Bottom action buttons |
161
+ | `topActions` | `ReactNode` | Top action buttons |
162
+
163
+ ### DraggablePanel
164
+
165
+ Resizable panel with drag handle.
166
+
167
+ | Prop | Type | Default | Description |
168
+ |---|---|---|---|
169
+ | `placement` | `'right' \| 'left' \| 'top' \| 'bottom'` | | **Required.** Panel placement |
170
+ | `defaultExpand` | `boolean` | | Default expand state |
171
+ | `expand` | `boolean` | | Controlled expand |
172
+ | `expandable` | `boolean` | | Can expand/collapse |
173
+ | `mode` | `'fixed' \| 'float'` | | Panel mode |
174
+ | `defaultSize` | `Partial<Size>` | | Default size |
175
+ | `size` | `Partial<Size>` | | Controlled size |
176
+ | `minWidth/minHeight` | `number` | | Minimum dimensions |
177
+ | `maxWidth/maxHeight` | `number` | | Maximum dimensions |
178
+ | `pin` | `boolean` | | Pin panel |
179
+ | `showBorder` | `boolean` | `true` | Show border |
180
+ | `showHandleHighlight` | `boolean` | | Highlight handle on hover |
181
+ | `showHandleWhenCollapsed` | `boolean` | | Show handle when collapsed |
182
+ | `showHandleWideArea` | `boolean` | | Wide handle area |
183
+ | `onExpandChange` | `(expand: boolean) => void` | | Expand callback |
184
+ | `onSizeChange` | `(delta, size?) => void` | | Size change callback |
185
+ | `onSizeDragging` | `(delta, size?) => void` | | Active drag callback |
186
+
187
+ Sub-components: `DraggablePanelBody`, `DraggablePanelContainer`, `DraggablePanelFooter`, `DraggablePanelHeader`.
188
+
189
+ ### DraggableSideNav
190
+
191
+ Full sidebar with resizable body, header, footer, and expand/collapse.
192
+
193
+ | Prop | Type | Default | Description |
194
+ |---|---|---|---|
195
+ | `body` | `(expand: boolean) => ReactNode` | | **Required.** Main content |
196
+ | `header` | `ReactNode \| (expand: boolean) => ReactNode` | | Header |
197
+ | `footer` | `ReactNode \| (expand: boolean) => ReactNode` | | Footer |
198
+ | `defaultExpand` | `boolean` | `true` | Default expand state |
199
+ | `expand` | `boolean` | | Controlled expand |
200
+ | `expandable` | `boolean` | `true` | Can expand/collapse |
201
+ | `defaultWidth` | `number` | | Default width |
202
+ | `width` | `number` | | Controlled expand width |
203
+ | `minWidth` | `number` | `64` | Min width when expanded |
204
+ | `maxWidth` | `number` | | Max width |
205
+ | `placement` | `'left' \| 'right'` | `'left'` | Placement |
206
+ | `resizable` | `boolean` | `true` | Enable resize |
207
+ | `showBorder` | `boolean` | `true` | Show border |
208
+ | `showHandle` | `boolean` | `true` | Show toggle handle |
209
+ | `showHandleWhenCollapsed` | `boolean` | `false` | Handle visibility when collapsed |
210
+ | `onExpandChange` | `(expand: boolean) => void` | | Expand callback |
211
+ | `onWidthChange` | `(delta, width) => void` | | Width change callback |
212
+ | `onSelect` | `(key: string) => void` | | Menu select callback |
213
+
214
+ ### ScrollArea
215
+
216
+ Styled scroll area. Exports atomic sub-components: `ScrollAreaRoot`, `ScrollAreaViewport`, `ScrollAreaContent`, `ScrollAreaScrollbar`, `ScrollAreaThumb`, `ScrollAreaCorner`.
217
+
218
+ | Prop | Type | Description |
219
+ |---|---|---|
220
+ | `children` | `ReactNode` | Content |
221
+ | `corner` | `boolean` | Show corner |
222
+ | `scrollFade` | `boolean` | Fade edges |
223
+ | `contentProps` | `ScrollAreaContentProps` | Content props |
224
+ | `scrollbarProps` | `ScrollAreaScrollbarProps` | Scrollbar props |
225
+ | `thumbProps` | `ScrollAreaThumbProps` | Thumb props |
226
+ | `viewportProps` | `ScrollAreaViewportProps` | Viewport props |
227
+ | `cornerProps` | `ScrollAreaCornerProps` | Corner props |
228
+
229
+ ### ScrollShadow
230
+
231
+ | Prop | Type | Description |
232
+ |---|---|---|
233
+ | `hideScrollBar` | `boolean` | Hide scrollbar |
234
+ | `isEnabled` | `boolean` | Enable shadow |
235
+ | `offset` | `number` | Offset |
236
+ | `orientation` | `'vertical' \| 'horizontal'` | Scroll direction |
237
+ | `size` | `number` | Shadow size |
238
+ | `visibility` | `'auto' \| 'always' \| 'never'` | Shadow visibility |
239
+ | `onVisibilityChange` | `({ top?, bottom?, left?, right? }) => void` | Visibility callback |
240
+
241
+ ### MaskShadow
242
+
243
+ | Prop | Type | Description |
244
+ |---|---|---|
245
+ | `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | Shadow position |
246
+ | `size` | `number` | Shadow size |
247
+ | `visibility` | `'auto' \| 'always' \| 'never'` | Visibility mode |
248
+
249
+ ---
250
+
251
+ ## General UI
252
+
253
+ ### Button
254
+
255
+ Extends Ant Design `Button`.
256
+
257
+ | Prop | Type | Description |
258
+ |---|---|---|
259
+ | `glass` | `boolean` | Glassmorphism style |
260
+ | `icon` | `IconProps['icon']` | Lucide icon |
261
+ | `iconProps` | `Partial<IconProps>` | Icon customisation |
262
+ | `shadow` | `boolean` | Drop shadow |
263
+
264
+ ### ActionIcon
265
+
266
+ Icon-only button with tooltip.
267
+
268
+ | Prop | Type | Description |
269
+ |---|---|---|
270
+ | `icon` | `IconProps['icon'] \| ReactNode` | Icon |
271
+ | `active` | `boolean` | Active state |
272
+ | `danger` | `boolean` | Danger style |
273
+ | `disabled` | `boolean` | Disabled |
274
+ | `glass` | `boolean` | Glass effect |
275
+ | `loading` | `boolean` | Loading state |
276
+ | `shadow` | `boolean` | Shadow |
277
+ | `size` | `ActionIconSize` | Size (number, `'large'`, `'middle'`, `'small'`, or config object) |
278
+ | `spin` | `boolean` | Spin icon |
279
+ | `title` | `TooltipProps['title']` | Tooltip title |
280
+ | `tooltipProps` | `Omit<TooltipProps, 'children' \| 'title'>` | Tooltip config |
281
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | Visual variant |
282
+
283
+ ### ActionIconGroup
284
+
285
+ Group of action icon buttons.
286
+
287
+ | Prop | Type | Description |
288
+ |---|---|---|
289
+ | `items` | `MenuItemType[]` | Action items |
290
+ | `menu` | `DropdownMenuProps['items']` | Overflow menu items |
291
+ | `onActionClick` | `(action) => void` | Action click handler |
292
+ | `size` | `ActionIconSize` | Icon size |
293
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Visual variant |
294
+ | `disabled` | `boolean` | Disabled |
295
+ | `glass` | `boolean` | Glass effect |
296
+ | `shadow` | `boolean` | Shadow |
297
+
298
+ ### Icon
299
+
300
+ Renders Lucide icons or custom icon components.
301
+
302
+ | Prop | Type | Description |
303
+ |---|---|---|
304
+ | `icon` | `LucideIcon \| FC \| ReactNode` | **Required.** Icon component/element |
305
+ | `size` | `IconSize` | Size (number, `'large'`/`'middle'`/`'small'`, or config) |
306
+ | `spin` | `boolean` | Spin animation |
307
+ | `color` | `string` | Icon colour |
308
+ | `fill` | `string` | Fill colour |
309
+
310
+ ### Tag
311
+
312
+ | Prop | Type | Description |
313
+ |---|---|---|
314
+ | `color` | `AntTagProps['color'] \| 'info'` | Tag colour |
315
+ | `size` | `'small' \| 'middle' \| 'large'` | Size |
316
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
317
+
318
+ ### Text
319
+
320
+ Typography text component.
321
+
322
+ | Prop | Type | Description |
323
+ |---|---|---|
324
+ | `as` | `ElementType` | Render element |
325
+ | `type` | `'secondary' \| 'success' \| 'warning' \| 'danger' \| 'info'` | Text type |
326
+ | `fontSize` | `number \| string` | Font size |
327
+ | `weight` | `'bold' \| 'bolder' \| number` | Font weight |
328
+ | `color` | `string` | Text colour |
329
+ | `align` | `'left' \| 'center' \| 'right'` | Text align |
330
+ | `lineHeight` | `CSSProperties['lineHeight']` | Line height |
331
+ | `lineClamp` | `number` | CSS line-clamp |
332
+ | `noWrap` | `boolean` | Disable wrapping |
333
+ | `ellipsis` | `boolean \| { rows?, tooltip?, tooltipWhenOverflow? }` | Ellipsis config |
334
+ | `strong` | `boolean` | Bold |
335
+ | `italic` | `boolean` | Italic |
336
+ | `underline` | `boolean` | Underline |
337
+ | `delete` | `boolean` | Strikethrough |
338
+ | `mark` | `boolean` | Highlight |
339
+ | `code` | `boolean` | Code style |
340
+ | `disabled` | `boolean` | Disabled style |
341
+ | `textTransform` | `CSSProperties['textTransform']` | Transform |
342
+ | `textDecoration` | `CSSProperties['textDecoration']` | Decoration |
343
+ | `whiteSpace` | `CSSProperties['whiteSpace']` | White space |
344
+ | `wordBreak` | `CSSProperties['wordBreak']` | Word break |
345
+
346
+ ### Block
347
+
348
+ Container with card-like variants.
349
+
350
+ | Prop | Type | Description |
351
+ |---|---|---|
352
+ | `clickable` | `boolean` | Clickable hover effect |
353
+ | `glass` | `boolean` | Glass effect |
354
+ | `shadow` | `boolean` | Shadow |
355
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
356
+
357
+ ### Empty
358
+
359
+ Empty state placeholder.
360
+
361
+ | Prop | Type | Description |
362
+ |---|---|---|
363
+ | `title` | `ReactNode` | Title |
364
+ | `description` | `ReactNode` | Description |
365
+ | `icon` | `IconProps['icon']` | Icon |
366
+ | `iconColor` | `IconProps['color']` | Icon colour |
367
+ | `emoji` | `string` | Emoji character |
368
+ | `image` | `ReactNode` | Image |
369
+ | `imageSize` | `number` | Image size |
370
+ | `action` | `ReactNode` | Action buttons |
371
+ | `type` | `'default' \| 'page'` | Layout type |
372
+
373
+ ### Skeleton
374
+
375
+ Loading skeleton. Sub-components: `SkeletonAvatar`, `SkeletonBlock`, `SkeletonButton`, `SkeletonParagraph`, `SkeletonTags`, `SkeletonTitle`.
376
+
377
+ | Prop | Type | Description |
378
+ |---|---|---|
379
+ | `active` | `boolean` | Animated shimmer |
380
+ | `avatar` | `SkeletonAvatarProps \| boolean` | Avatar skeleton |
381
+ | `title` | `SkeletonTitleProps \| boolean` | Title skeleton |
382
+ | `paragraph` | `SkeletonParagraphProps \| boolean` | Paragraph skeleton |
383
+ | `gap` | `number` | Gap between sections |
384
+
385
+ ---
386
+
387
+ ## Data Entry
388
+
389
+ ### CardForm
390
+
391
+ Card wrapper for long forms with a sticky header action bar (`Back`, `Save`, `Save and Continue Edit`).
392
+
393
+ | Prop | Type | Default | Description |
394
+ |---|---|---|---|
395
+ | `actions` | `ReactNode` | | Custom right-side actions. When provided, default Save buttons are not rendered |
396
+ | `backButtonProps` | `Omit<ActionIconProps, 'icon' \| 'onClick'>` | | Back button props |
397
+ | `backIcon` | `ActionIconProps['icon']` | `ArrowLeft` | Back icon |
398
+ | `title` | `ReactNode` | | Header title |
399
+ | `onBack` | `ActionIconProps['onClick']` | | Back click handler |
400
+ | `onSave` | `ButtonProps['onClick']` | | Save click handler |
401
+ | `onSaveAndContinue` | `ButtonProps['onClick']` | | Save-and-continue click handler |
402
+ | `saveText` | `ReactNode` | `'Save'` | Save button label |
403
+ | `continueText` | `ReactNode` | `'Save and Continue Edit'` | Continue button label |
404
+ | `saveButtonProps` | `Omit<ButtonProps, 'children' \| 'onClick'>` | | Save button props |
405
+ | `continueButtonProps` | `Omit<ButtonProps, 'children' \| 'onClick'>` | | Continue button props |
406
+ | `showSave` | `boolean` | `true` | Show Save button |
407
+ | `showContinue` | `boolean` | `true` | Show Continue button |
408
+ | `sticky` | `boolean` | `true` | Make header sticky inside the scrolling container |
409
+ | `stickyOffset` | `number \| string` | `0` | Sticky top offset |
410
+ | `headerClassName` | `string` | | Header class name |
411
+ | `headerStyle` | `CSSProperties` | | Header style |
412
+ | `contentClassName` | `string` | | Content class name |
413
+ | `contentStyle` | `CSSProperties` | | Content style |
414
+
415
+ Also accepts `FlexProps` (except `title`, which is reserved by `CardForm`).
416
+
417
+ ### Input
418
+
419
+ Extends Ant Design `Input`. Also exports: `TextArea`, `InputNumber`, `InputPassword`, `InputOPT`, `InputMask`.
420
+
421
+ | Prop | Type | Description |
422
+ |---|---|---|
423
+ | `shadow` | `boolean` | Shadow effect |
424
+
425
+ **TextArea** adds `resize?: boolean`. **InputMask** adds `mask`, `maskChar`, `maskPlaceholder`, `alwaysShowMask`.
426
+
427
+ ### Select
428
+
429
+ Custom select built on Base UI.
430
+
431
+ | Prop | Type | Default | Description |
432
+ |---|---|---|---|
433
+ | `options` | `SelectOptions<Value>` | | Options array (flat or grouped) |
434
+ | `value` | `Value \| Value[] \| null` | | Controlled value |
435
+ | `defaultValue` | `Value \| Value[] \| null` | | Default value |
436
+ | `onChange` | `(value, option?) => void` | | Change handler |
437
+ | `onSelect` | `(value, option?) => void` | | Select handler |
438
+ | `mode` | `'multiple' \| 'tags'` | | Multi-select mode |
439
+ | `size` | `'large' \| 'middle' \| 'small'` | | Size |
440
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | | Visual variant |
441
+ | `placeholder` | `ReactNode` | | Placeholder |
442
+ | `disabled` | `boolean` | | Disabled |
443
+ | `loading` | `boolean` | | Loading |
444
+ | `allowClear` | `boolean` | | Show clear button |
445
+ | `showSearch` | `boolean` | | Enable search |
446
+ | `isMobile` | `boolean` | `false` | Mobile drawer picker |
447
+ | `behaviorVariant` | `'default' \| 'item-aligned'` | `'default'` | Dropdown positioning |
448
+ | `selectedIndicatorVariant` | `'check' \| 'bold'` | `'check'` | Selected item indicator style |
449
+ | `prefix` | `ReactNode \| IconProps['icon']` | | Prefix element |
450
+ | `suffixIcon` | `IconProps['icon'] \| ReactNode` | | Suffix icon |
451
+ | `shadow` | `boolean` | | Shadow |
452
+ | `open` | `boolean` | | Controlled open |
453
+ | `onOpenChange` | `(open: boolean) => void` | | Open change callback |
454
+ | `labelRender` | `(option) => ReactNode` | | Custom label renderer |
455
+ | `optionRender` | `(option, info) => ReactNode` | | Custom option renderer |
456
+ | `listHeight` | `number` | `256` | Popup scroll height |
457
+ | `virtual` | `boolean` | | Virtual scrolling |
458
+ | `popupMatchSelectWidth` | `boolean \| number` | | Match popup to trigger width |
459
+
460
+ ### Checkbox / CheckboxGroup
461
+
462
+ | Prop (Checkbox) | Type | Description |
463
+ |---|---|---|
464
+ | `checked` | `boolean` | Controlled |
465
+ | `defaultChecked` | `boolean` | Default |
466
+ | `disabled` | `boolean` | Disabled |
467
+ | `indeterminate` | `boolean` | Indeterminate state |
468
+ | `onChange` | `(checked: boolean) => void` | Change handler |
469
+ | `shape` | `'square' \| 'circle'` | Shape |
470
+ | `size` | `number` | Size |
471
+ | `backgroundColor` | `string` | Checked colour |
472
+
473
+ **CheckboxGroup**: `options`, `value`, `defaultValue`, `onChange`, `disabled`, `shape`, `size`.
474
+
475
+ ### Radio
476
+
477
+ Wraps Ant Design `Radio`. Supports `Radio.Group` and `Radio.Button`.
478
+
479
+ | Prop | Type | Description |
480
+ |---|---|---|
481
+ | `checked` | `boolean` | Controlled checked state |
482
+ | `disabled` | `boolean` | Disabled |
483
+ | `value` | `any` | Radio value |
484
+ | `onChange` | `(e: RadioChangeEvent) => void` | Change handler |
485
+
486
+ **Radio.Group**: `value`, `defaultValue`, `onChange`, `disabled`, `options`, `optionType` (`'default' | 'button'`), `buttonStyle` (`'outline' | 'solid'`), `size`.
487
+
488
+ **Radio.Button**: Same props as Radio, rendered as a button style option within `Radio.Group`.
489
+
490
+ ```tsx
491
+ <Radio.Group value={value} onChange={(e) => setValue(e.target.value)}>
492
+ <Radio value={1}>Option A</Radio>
493
+ <Radio value={2}>Option B</Radio>
494
+ <Radio value={3}>Option C</Radio>
495
+ </Radio.Group>
496
+ ```
497
+
498
+ ### Switch
499
+
500
+ | Prop | Type | Default | Description |
501
+ |---|---|---|---|
502
+ | `checked` / `value` | `boolean` | | Controlled checked state |
503
+ | `defaultChecked` / `defaultValue` | `boolean` | | Uncontrolled |
504
+ | `disabled` | `boolean` | | Disabled |
505
+ | `loading` | `boolean` | | Loading indicator |
506
+ | `size` | `'default' \| 'small'` | `'default'` | Size |
507
+ | `onChange` | `SwitchChangeEventHandler` | | Change handler |
508
+ | `onClick` | `SwitchClickEventHandler` | | Click handler |
509
+ | `checkedChildren` | `ReactNode` | | Checked icon/label |
510
+ | `unCheckedChildren` | `ReactNode` | | Unchecked icon/label |
511
+ | `autoFocus` | `boolean` | | Auto focus |
512
+
513
+ ### DatePicker
514
+
515
+ Extends Ant Design `DatePicker`.
516
+
517
+ | Prop | Type | Description |
518
+ |---|---|---|
519
+ | `shadow` | `boolean` | Shadow |
520
+ | `isMobile` | `boolean` | Force mobile drawer UI |
521
+ | `min` | `ConfigType` | Lower bound date |
522
+ | `max` | `ConfigType` | Upper bound date |
523
+ | `revertYear` | `boolean` | Ascending year order |
524
+
525
+ ### TimePicker
526
+
527
+ | Prop | Type | Description |
528
+ |---|---|---|
529
+ | `value` | `string \| null` | Controlled value |
530
+ | `defaultValue` | `string \| null` | Default value |
531
+ | `onChange` | `(value, formatted) => void` | Change handler |
532
+ | `format` | `string \| (value) => string` | Display format |
533
+ | `use12Hours` | `boolean` | 12-hour mode |
534
+ | `hourStep` | `number` | Hour increment |
535
+ | `minuteStep` | `number` | Minute increment |
536
+ | `isMobile` | `boolean` | Mobile drawer UI |
537
+ | `size` | `SelectSize` | Size |
538
+ | `allowClear` | `boolean` | Clearable |
539
+ | `open` | `boolean` | Controlled open |
540
+ | `onOpenChange` | `(open: boolean) => void` | Open callback |
541
+ | `inputReadOnly` | `boolean` | Read-only input |
542
+
543
+ ### AutoComplete
544
+
545
+ Extends Ant Design `AutoComplete`. Adds `shadow?: boolean`.
546
+
547
+ ### Segmented
548
+
549
+ Extends Ant Design `Segmented`.
550
+
551
+ | Prop | Type | Description |
552
+ |---|---|---|
553
+ | `glass` | `boolean` | Glass effect |
554
+ | `padding` | `string \| number` | Padding |
555
+ | `shadow` | `boolean` | Shadow |
556
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
557
+
558
+ ### SliderWithInput
559
+
560
+ Slider + InputNumber combo.
561
+
562
+ | Prop | Type | Description |
563
+ |---|---|---|
564
+ | `changeOnWheel` | `boolean` | Scroll to change |
565
+ | `controls` | `InputNumberProps['controls']` | Input controls |
566
+ | `gap` | `FlexProps['gap']` | Gap |
567
+ | `size` | `InputNumberProps['size']` | Size |
568
+ | `unlimitedInput` | `boolean` | Unlimited max in input |
569
+ | `variant` | `InputNumberProps['variant']` | Input variant |
570
+
571
+ ### ColorSwatches
572
+
573
+ | Prop | Type | Description |
574
+ |---|---|---|
575
+ | `colors` | `{ color, key?, title? }[]` | **Required.** Colour options |
576
+ | `value` | `string` | Controlled value |
577
+ | `defaultValue` | `string` | Default |
578
+ | `onChange` | `(color?) => void` | Change handler |
579
+ | `shape` | `'circle' \| 'square'` | Swatch shape |
580
+ | `size` | `number` | Swatch size |
581
+ | `enableColorPicker` | `boolean` | Show picker |
582
+ | `enableColorSwatches` | `boolean` | Show swatches |
583
+
584
+ ### EditableText
585
+
586
+ | Prop | Type | Description |
587
+ |---|---|---|
588
+ | `value` | `string` | Controlled value |
589
+ | `onChange` | `(value) => void` | Change handler |
590
+ | `onChangeEnd` | callback | Confirmed change |
591
+ | `editing` | `boolean` | Controlled editing state |
592
+ | `onEditingChange` | `(editing: boolean) => void` | Editing callback |
593
+ | `showEditIcon` | `boolean` | Show edit icon |
594
+ | `variant` | string | Visual variant |
595
+ | `size` | any | Size |
596
+
597
+ ### HotkeyInput
598
+
599
+ | Prop | Type | Description |
600
+ |---|---|---|
601
+ | `value` | `string` | Controlled value |
602
+ | `defaultValue` | `string` | Default |
603
+ | `onChange` | `(value: string) => void` | Change handler |
604
+ | `allowReset` | `boolean` | Show reset |
605
+ | `resetValue` | `string` | Reset target |
606
+ | `hotkeyConflicts` | `string[]` | Conflicting keys |
607
+ | `onConflict` | `(key) => void` | Conflict callback |
608
+ | `disabled` | `boolean` | Disabled |
609
+ | `shadow` | `boolean` | Shadow |
610
+ | `variant` | `'filled' \| 'borderless' \| 'outlined'` | Variant |
611
+
612
+ ### ImageSelect
613
+
614
+ | Prop | Type | Description |
615
+ |---|---|---|
616
+ | `options` | `ImageSelectItem[]` | Options with `img`, `label`, `value` |
617
+ | `value` | `SelectProps['value']` | Controlled |
618
+ | `defaultValue` | `SelectProps['defaultValue']` | Default |
619
+ | `onChange` | `(value) => void` | Change |
620
+ | `width` | `number` | Image width |
621
+ | `height` | `number` | Image height |
622
+
623
+ ---
624
+
625
+ ## Form
626
+
627
+ ### Form
628
+
629
+ | Prop | Type | Default | Description |
630
+ |---|---|---|---|
631
+ | `children` | `ReactNode` | | **Required.** Form content |
632
+ | `cy` | `string` | | Cypress test-id prefix. Field components emit `data-cy="<cy>-<name>"` when ThemeProvider `cy` is enabled |
633
+ | `onSubmit` | `(values: T) => void \| Promise` | | Submit handler |
634
+ | `form` | `FormInstance<T>` | | External form instance (from `useForm`, destructure as `const { form } = useForm(...)`) |
635
+ | `initialValues` | `T` | | Initial field values |
636
+ | `validate` | `(values: T) => Partial<Record<keyof T, string>>` | | Validation function |
637
+ | `layout` | `'vertical' \| 'horizontal'` | `'vertical'` | Form layout. Automatically forced to `'vertical'` when `ThemeProvider.isMobile` is `true` or viewport width < 880px |
638
+ | `labelWidth` | `string \| number` | `'200px'` | Label width (horizontal layout) |
639
+ | `fieldMinWidth` | `string \| number` | | Min field width |
640
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | `'borderless'` | Form variant |
641
+
642
+ **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.
643
+
644
+ **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`.
645
+
646
+ 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.
647
+
648
+ ### FormLabel (Form.Label)
649
+
650
+ Reusable form field label used by form controls.
651
+
652
+ | Prop | Type | Description |
653
+ |---|---|---|
654
+ | `children` | `ReactNode` | **Required.** Label content |
655
+ | `htmlFor` | `string` | Associated input id |
656
+ | `description` | `ReactNode` | Optional description shown below label |
657
+ | `required` | `boolean` | Shows required marker (`*`) |
658
+ | `onLabelClick` | `() => void` | Optional custom label click handler |
659
+ | `className` | `string` | Custom class |
660
+
661
+ ### FormDescription (Form.Description)
662
+
663
+ Reusable description text primitive used below labels/fields.
664
+
665
+ | Prop | Type | Description |
666
+ |---|---|---|
667
+ | `children` | `ReactNode` | Description content |
668
+ | `className` | `string` | Custom class |
669
+ | `style` | `CSSProperties` | Inline style |
670
+
671
+ ### FormError (Form.Error)
672
+
673
+ Reusable field error primitive rendered as alert text.
674
+
675
+ | Prop | Type | Description |
676
+ |---|---|---|
677
+ | `message` | `string` | Error message |
678
+ | `className` | `string` | Custom class |
679
+ | `style` | `CSSProperties` | Inline style |
680
+
681
+ ### FormBlock (Form.Block)
682
+
683
+ Reusable form field wrapper for custom controls, while preserving the same label/control/error layout used by built-in form fields.
684
+
685
+ | Prop | Type | Description |
686
+ |---|---|---|
687
+ | `children` | `ReactNode` | **Required.** Custom control content |
688
+ | `label` | `ReactNode` | Field label |
689
+ | `description` | `ReactNode` | Description below label |
690
+ | `error` | `ReactNode` | Error content rendered below control |
691
+ | `helperText` | `ReactNode` | Helper text below control |
692
+ | `required` | `boolean` | Shows required marker on label |
693
+ | `htmlFor` | `string` | Optional target id for label `htmlFor` |
694
+ | `onLabelClick` | `() => void` | Optional custom label click handler |
695
+ | `className` | `string` | Wrapper class |
696
+ | `style` | `CSSProperties` | Wrapper style |
697
+ | `labelClassName` | `string` | Label area class |
698
+ | `labelStyle` | `CSSProperties` | Label area style |
699
+ | `controlClassName` | `string` | Control area class |
700
+ | `controlStyle` | `CSSProperties` | Control area style |
701
+
702
+ ### FormGroup
703
+
704
+ | Prop | Type | Description |
705
+ |---|---|---|
706
+ | `title` | `ReactNode` | Group title |
707
+ | `description` | `ReactNode` | Group description |
708
+ | `icon` | `any` | Group icon |
709
+ | `extra` | `ReactNode` | Extra content |
710
+ | `children` | `ReactNode` | Fields |
711
+ | `collapsible` | `boolean` | Collapsible |
712
+ | `defaultCollapsed` | `boolean` | Default collapsed |
713
+ | `variant` | `FormVariant` | Variant |
714
+
715
+ ### FormSegment (Form.Segment)
716
+
717
+ Form-bound Segmented control. Wraps the `Segmented` component and connects it to form state. Accepts all `SegmentedProps` plus form-binding props.
718
+
719
+ | Prop | Type | Description |
720
+ |---|---|---|
721
+ | `name` | `keyof T & string` | **Required.** Field name |
722
+ | `form` | `FormInstance<T>` | Form instance |
723
+ | `label` | `string` | Field label |
724
+ | `description` | `ReactNode` | Field description |
725
+ | `options` | `SegmentedProps['options']` | **Required.** Segment options (from antd `Segmented`) |
726
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
727
+ | `block` | `boolean` | Full width |
728
+ | `size` | `'large' \| 'middle' \| 'small'` | Size |
729
+ | `disabled` | `boolean` | Disabled |
730
+
731
+ ### FormTextarea (Form.Textarea)
732
+
733
+ Form-bound multiline input. Wraps `TextArea` and connects it to form state. Accepts all `TextAreaProps` (Ant Design `Input.TextArea`) plus form-binding props.
734
+
735
+ | Prop | Type | Description |
736
+ |---|---|---|
737
+ | `name` | `keyof T & string` | **Required.** Field name |
738
+ | `form` | `FormInstance<T>` | Form instance |
739
+ | `label` | `string` | Field label |
740
+ | `description` | `ReactNode` | Field description |
741
+ | `required` | `boolean` | Required marker |
742
+ | `helperText` | `ReactNode` | Helper text below input |
743
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
744
+ | `...TextAreaProps` | `TextAreaProps` | All textarea props (e.g. `maxLength`, `rows`, `autoSize`, `showCount`, `allowClear`) |
745
+
746
+ ### FormInputNumber (Form.InputNumber)
747
+
748
+ Form-bound numeric input. Wraps `InputNumber` and connects it to form state.
749
+
750
+ | Prop | Type | Description |
751
+ |---|---|---|
752
+ | `name` | `keyof T & string` | **Required.** Field name |
753
+ | `form` | `FormInstance<T>` | Form instance |
754
+ | `label` | `string` | Field label |
755
+ | `description` | `ReactNode` | Field description |
756
+ | `required` | `boolean` | Required marker |
757
+ | `helperText` | `ReactNode` | Helper text below input |
758
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
759
+ | `min` | `number` | Minimum value |
760
+ | `max` | `number` | Maximum value |
761
+ | `step` | `number` | Step increment |
762
+ | `precision` | `number` | Decimal precision |
763
+ | `prefix` | `ReactNode` | Prefix element |
764
+ | `suffix` | `ReactNode` | Suffix element |
765
+ | `disabled` | `boolean` | Disabled |
766
+
767
+ ### FormInputPassword (Form.InputPassword)
768
+
769
+ Form-bound password input with visibility toggle. Wraps `InputPassword` and connects it to form state.
770
+
771
+ | Prop | Type | Description |
772
+ |---|---|---|
773
+ | `name` | `keyof T & string` | **Required.** Field name |
774
+ | `form` | `FormInstance<T>` | Form instance |
775
+ | `label` | `string` | Field label |
776
+ | `description` | `ReactNode` | Field description |
777
+ | `required` | `boolean` | Required marker |
778
+ | `helperText` | `ReactNode` | Helper text below input |
779
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
780
+ | `placeholder` | `string` | Placeholder text |
781
+ | `disabled` | `boolean` | Disabled |
782
+
783
+ ### FormInputMask (Form.InputMask)
784
+
785
+ Form-bound masked input. Wraps `InputMask` and connects it to form state. Requires the `mask` prop.
786
+
787
+ | Prop | Type | Description |
788
+ |---|---|---|
789
+ | `name` | `keyof T & string` | **Required.** Field name |
790
+ | `form` | `FormInstance<T>` | Form instance |
791
+ | `label` | `string` | Field label |
792
+ | `description` | `ReactNode` | Field description |
793
+ | `required` | `boolean` | Required marker |
794
+ | `helperText` | `ReactNode` | Helper text below input |
795
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
796
+ | `mask` | `string \| Inputmask.Options['mask']` | **Required.** Input mask pattern (`X`/`x` = digit placeholder) |
797
+ | `maskChar` | `string \| null` | Mask placeholder character |
798
+ | `maskPlaceholder` | `string \| null` | Mask placeholder string |
799
+ | `alwaysShowMask` | `boolean` | Always show the mask |
800
+ | `placeholder` | `string` | Placeholder text |
801
+ | `disabled` | `boolean` | Disabled |
802
+
803
+ ### FormColorPicker (Form.ColorPicker)
804
+
805
+ 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'`).
806
+
807
+ | Prop | Type | Description |
808
+ |---|---|---|
809
+ | `name` | `keyof T & string` | **Required.** Field name |
810
+ | `form` | `FormInstance<T>` | Form instance |
811
+ | `label` | `string` | Field label |
812
+ | `description` | `ReactNode` | Field description |
813
+ | `required` | `boolean` | Required marker |
814
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
815
+ | `showText` | `boolean \| ((color) => ReactNode)` | Show color value text next to swatch |
816
+ | `format` | `'hex' \| 'rgb' \| 'hsb'` | Color format |
817
+ | `presets` | `PresetsItem[]` | Preset color palettes |
818
+ | `allowClear` | `boolean` | Allow clearing the color |
819
+ | `disabledAlpha` | `boolean` | Disable alpha channel |
820
+ | `size` | `'large' \| 'middle' \| 'small'` | Size |
821
+ | `disabled` | `boolean` | Disabled |
822
+
823
+ ### FormRadio (Form.Radio)
824
+
825
+ Form-bound radio group. Wraps antd `Radio.Group` and connects it to form state. Supports `Radio` children or `options` prop.
826
+
827
+ | Prop | Type | Description |
828
+ |---|---|---|
829
+ | `name` | `keyof T & string` | **Required.** Field name |
830
+ | `form` | `FormInstance<T>` | Form instance |
831
+ | `label` | `ReactNode` | Field label |
832
+ | `description` | `ReactNode` | Field description |
833
+ | `rules` | `FormFieldRules<T>` | Inline validation rules |
834
+ | `options` | `RadioGroupProps['options']` | Options array (alternative to children) |
835
+ | `optionType` | `'default' \| 'button'` | Option render type |
836
+ | `disabled` | `boolean` | Disabled |
837
+
838
+ ```tsx
839
+ <FormRadio form={form} name="contactMethod" label="Preferred Contact">
840
+ <Radio value="email">Email</Radio>
841
+ <Radio value="phone">Phone</Radio>
842
+ <Radio value="sms">SMS</Radio>
843
+ </FormRadio>
844
+ ```
845
+
846
+ ### useForm Hook
847
+
848
+ ```tsx
849
+ const { values, errors, touched, isSubmitting, isValid, form, setFieldValue, handleSubmit, resetForm } = useForm({
850
+ initialValues: { name: '' },
851
+ onSubmit: (values) => { ... },
852
+ validate: (values) => ({ name: values.name ? undefined : 'Required' }),
853
+ });
854
+ ```
855
+
856
+ ### FormModal
857
+
858
+ A modal dialog with an embedded `Form`. The footer (submit button) is always visible while the body scrolls. Supports all Form layout props.
859
+
860
+ | Prop | Type | Description |
861
+ |---|---|---|
862
+ | `children` | `ReactNode` | Form content |
863
+ | `title` | `ReactNode` | Modal title |
864
+ | `form` | `FormInstance<T>` | Form instance |
865
+ | `initialValues` | `T` | Initial values |
866
+ | `onSubmit` | `FormProps['onSubmit']` | Submit handler |
867
+ | `validate` | `FormProps['validate']` | Validation |
868
+ | `submitText` | `string` | Submit button text |
869
+ | `submitButtonProps` | `ButtonProps` | Submit button props |
870
+ | `loading` | `boolean` | Loading state |
871
+ | `layout` | `'vertical' \| 'horizontal'` | Form field layout direction |
872
+ | `labelWidth` | `string \| number` | Label column width when horizontal (default `'200px'`) |
873
+ | `fieldMinWidth` | `string \| number` | Minimum width for field controls |
874
+ | `maxWidth` | `string \| number` | Maximum width of the form inside the modal |
875
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | Visual style for form fields |
876
+
877
+ ### Form Usage Examples
878
+
879
+ #### Basic Form (Vertical Layout)
880
+
881
+ ```tsx
882
+ import { Form, useForm, Button } from '@gomeniucivan/ui';
883
+
884
+ interface MyFormValues {
885
+ name: string;
886
+ email: string;
887
+ role: string;
888
+ notifications: boolean;
889
+ agreeToTerms: boolean;
890
+ }
891
+
892
+ function MyPage() {
893
+ const { form } = useForm<MyFormValues>({
894
+ initialValues: {
895
+ name: '',
896
+ email: '',
897
+ role: '',
898
+ notifications: false,
899
+ agreeToTerms: false,
900
+ },
901
+ onSubmit: async (values) => {
902
+ console.log('Submitted:', values);
903
+ },
904
+ validate: (values) => {
905
+ const errors: Partial<Record<keyof MyFormValues, string>> = {};
906
+ if (!values.name) errors.name = 'Name is required';
907
+ if (!values.email) errors.email = 'Email is required';
908
+ if (values.email && !/\S+@\S+\.\S+/.test(values.email)) errors.email = 'Invalid email';
909
+ if (!values.role) errors.role = 'Please select a role';
910
+ if (!values.agreeToTerms) errors.agreeToTerms = 'You must agree to the terms';
911
+ return errors;
912
+ },
913
+ });
914
+
915
+ return (
916
+ <Form form={form} variant="outlined">
917
+ <Form.Input
918
+ name="name"
919
+ label="Full Name"
920
+ description="Enter your full name"
921
+ form={form}
922
+ required
923
+ placeholder="John Doe"
924
+ />
925
+
926
+ <Form.Input
927
+ name="email"
928
+ label="Email"
929
+ form={form}
930
+ required
931
+ placeholder="john@example.com"
932
+ />
933
+
934
+ <Form.Select
935
+ name="role"
936
+ label="Role"
937
+ description="Select your role in the organization"
938
+ form={form}
939
+ required
940
+ options={[
941
+ { label: 'Admin', value: 'admin' },
942
+ { label: 'Editor', value: 'editor' },
943
+ { label: 'Viewer', value: 'viewer' },
944
+ ]}
945
+ placeholder="Select a role..."
946
+ />
947
+
948
+ <Form.Switch
949
+ name="notifications"
950
+ label="Enable Notifications"
951
+ description="Receive email notifications for updates"
952
+ form={form}
953
+ />
954
+
955
+ <Form.Checkbox
956
+ name="agreeToTerms"
957
+ label="I agree to the Terms & Conditions"
958
+ form={form}
959
+ />
960
+
961
+ <Button type="primary" onClick={form.handleSubmit}>
962
+ Submit
963
+ </Button>
964
+ </Form>
965
+ );
966
+ }
967
+ ```
968
+
969
+ #### Horizontal Layout with FormGroup
970
+
971
+ ```tsx
972
+ import { Form, useForm, Button, Flex } from '@gomeniucivan/ui';
973
+ import { Settings, Bell } from 'lucide-react';
974
+
975
+ interface SettingsValues {
976
+ displayName: string;
977
+ bio: string;
978
+ theme: string;
979
+ language: string;
980
+ emailNotifications: boolean;
981
+ pushNotifications: boolean;
982
+ startDate: any;
983
+ meetingTime: string;
984
+ }
985
+
986
+ function SettingsPage() {
987
+ const { form } = useForm<SettingsValues>({
988
+ initialValues: {
989
+ displayName: 'John Doe',
990
+ bio: '',
991
+ theme: 'dark',
992
+ language: 'en',
993
+ emailNotifications: true,
994
+ pushNotifications: false,
995
+ startDate: null,
996
+ meetingTime: '',
997
+ },
998
+ onSubmit: async (values) => {
999
+ await saveSettings(values);
1000
+ },
1001
+ });
1002
+
1003
+ return (
1004
+ <Form form={form} layout="horizontal" labelWidth="220px" variant="borderless">
1005
+ <Form.Group title="Profile" description="Manage your profile settings" icon={Settings}>
1006
+ <Form.Input
1007
+ name="displayName"
1008
+ label="Display Name"
1009
+ form={form}
1010
+ required
1011
+ />
1012
+
1013
+ <Form.Textarea
1014
+ name="bio"
1015
+ label="Bio"
1016
+ description="Short description about yourself"
1017
+ form={form}
1018
+ maxLength={280}
1019
+ showCount
1020
+ autoSize={{ minRows: 3, maxRows: 6 }}
1021
+ />
1022
+
1023
+ <Form.Segment
1024
+ name="theme"
1025
+ label="Theme"
1026
+ form={form}
1027
+ options={[
1028
+ { label: 'Light', value: 'light' },
1029
+ { label: 'Dark', value: 'dark' },
1030
+ { label: 'System', value: 'system' },
1031
+ ]}
1032
+ />
1033
+
1034
+ <Form.Select
1035
+ name="language"
1036
+ label="Language"
1037
+ form={form}
1038
+ options={[
1039
+ { label: 'English', value: 'en' },
1040
+ { label: 'Spanish', value: 'es' },
1041
+ { label: 'French', value: 'fr' },
1042
+ ]}
1043
+ />
1044
+ </Form.Group>
1045
+
1046
+ <Form.Group title="Notifications" description="Configure notifications" icon={Bell} collapsible>
1047
+ <Form.Switch
1048
+ name="emailNotifications"
1049
+ label="Email Notifications"
1050
+ description="Receive updates via email"
1051
+ form={form}
1052
+ />
1053
+
1054
+ <Form.Switch
1055
+ name="pushNotifications"
1056
+ label="Push Notifications"
1057
+ form={form}
1058
+ />
1059
+ </Form.Group>
1060
+
1061
+ <Form.Group title="Schedule">
1062
+ <Form.DatePicker
1063
+ name="startDate"
1064
+ label="Start Date"
1065
+ form={form}
1066
+ />
1067
+
1068
+ <Form.TimePicker
1069
+ name="meetingTime"
1070
+ label="Meeting Time"
1071
+ form={form}
1072
+ use12Hours
1073
+ />
1074
+ </Form.Group>
1075
+
1076
+ <Flex horizontal gap={8} justify="flex-end">
1077
+ <Button onClick={form.resetForm}>Reset</Button>
1078
+ <Button type="primary" onClick={form.handleSubmit}>
1079
+ Save Settings
1080
+ </Button>
1081
+ </Flex>
1082
+ </Form>
1083
+ );
1084
+ }
1085
+ ```
1086
+
1087
+ #### Inline Validation Rules (per-field)
1088
+
1089
+ Instead of a global `validate` function, you can use `rules` on each field:
1090
+
1091
+ ```tsx
1092
+ <Form.Input
1093
+ name="username"
1094
+ label="Username"
1095
+ form={form}
1096
+ rules={{
1097
+ required: 'Username is required',
1098
+ minLength: { value: 3, message: 'Must be at least 3 characters' },
1099
+ maxLength: { value: 20, message: 'Must be 20 characters or less' },
1100
+ pattern: { value: /^[a-zA-Z0-9_]+$/, message: 'Only letters, numbers, and underscores' },
1101
+ }}
1102
+ />
1103
+
1104
+ <Form.Input
1105
+ name="email"
1106
+ label="Email"
1107
+ form={form}
1108
+ rules={{
1109
+ required: 'Email is required',
1110
+ validate: (value) => {
1111
+ if (!/\S+@\S+\.\S+/.test(value)) return 'Invalid email format';
1112
+ },
1113
+ }}
1114
+ />
1115
+
1116
+ {/* Shorthand — just a required message string */}
1117
+ <Form.Input
1118
+ name="phone"
1119
+ label="Phone"
1120
+ form={form}
1121
+ rules="Phone number is required"
1122
+ />
1123
+ ```
1124
+
1125
+ #### FormModal Example
1126
+
1127
+ ```tsx
1128
+ import { FormModal, useForm, Button } from '@gomeniucivan/ui';
1129
+ import { useState } from 'react';
1130
+
1131
+ interface CreateUserValues {
1132
+ name: string;
1133
+ email: string;
1134
+ role: string;
1135
+ }
1136
+
1137
+ function UserManagement() {
1138
+ const [open, setOpen] = useState(false);
1139
+
1140
+ const { form } = useForm<CreateUserValues>({
1141
+ initialValues: { name: '', email: '', role: 'viewer' },
1142
+ onSubmit: async (values) => {
1143
+ await createUser(values);
1144
+ setOpen(false);
1145
+ },
1146
+ validate: (values) => {
1147
+ const errors: Partial<Record<keyof CreateUserValues, string>> = {};
1148
+ if (!values.name) errors.name = 'Required';
1149
+ if (!values.email) errors.email = 'Required';
1150
+ return errors;
1151
+ },
1152
+ });
1153
+
1154
+ return (
1155
+ <>
1156
+ <Button type="primary" onClick={() => setOpen(true)}>
1157
+ Add User
1158
+ </Button>
1159
+
1160
+ <FormModal
1161
+ title="Create User"
1162
+ open={open}
1163
+ onCancel={() => setOpen(false)}
1164
+ form={form}
1165
+ submitText="Create"
1166
+ layout="horizontal"
1167
+ labelWidth="120px"
1168
+ variant="outlined"
1169
+ >
1170
+ <Form.Input name="name" label="Name" form={form} required />
1171
+ <Form.Input name="email" label="Email" form={form} required />
1172
+ <Form.Select
1173
+ name="role"
1174
+ label="Role"
1175
+ form={form}
1176
+ options={[
1177
+ { label: 'Admin', value: 'admin' },
1178
+ { label: 'Editor', value: 'editor' },
1179
+ { label: 'Viewer', value: 'viewer' },
1180
+ ]}
1181
+ />
1182
+ </FormModal>
1183
+ </>
1184
+ );
1185
+ }
1186
+ ```
1187
+
1188
+ #### All Form Imports
1189
+
1190
+ ```tsx
1191
+ // Core Form
1192
+ import { Form, useForm } from '@gomeniucivan/ui';
1193
+ import type { FormProps, FormConfig, FormState, UseFormReturn } from '@gomeniucivan/ui';
1194
+
1195
+ // Individual sub-components (also available as Form.Input, Form.Select, etc.)
1196
+ import {
1197
+ FormInput,
1198
+ FormTextarea,
1199
+ FormBlock,
1200
+ FormLabel,
1201
+ FormDescription,
1202
+ FormError,
1203
+ FormSelect,
1204
+ FormCheckbox,
1205
+ FormSwitch,
1206
+ FormDatePicker,
1207
+ FormTimePicker,
1208
+ FormSegment,
1209
+ FormGroup,
1210
+ FormInputNumber,
1211
+ FormInputPassword,
1212
+ FormInputMask,
1213
+ FormColorPicker,
1214
+ FormRadio,
1215
+ } from '@gomeniucivan/ui';
1216
+
1217
+ // Radio
1218
+ import { Radio } from '@gomeniucivan/ui';
1219
+ import type { RadioProps, RadioGroupProps } from '@gomeniucivan/ui';
1220
+
1221
+ // ColorPicker (standalone)
1222
+ import { ColorPicker } from '@gomeniucivan/ui';
1223
+ import type { ColorPickerProps } from '@gomeniucivan/ui';
1224
+
1225
+ // Validation helpers
1226
+ import { runRules } from '@gomeniucivan/ui';
1227
+ import type { FormFieldRules } from '@gomeniucivan/ui';
1228
+
1229
+ // FormModal
1230
+ import { FormModal } from '@gomeniucivan/ui';
1231
+ import type { FormModalProps } from '@gomeniucivan/ui';
1232
+ ```
1233
+
1234
+ ---
1235
+
1236
+ ## Data Display
1237
+
1238
+ ### FolderTree
1239
+
1240
+ Hierarchical folder tree for displaying nested categories with expand/collapse, folder icons, tags, and customisable colours.
1241
+
1242
+ | Prop | Type | Default | Description |
1243
+ |---|---|---|---|
1244
+ | `data` | `FolderTreeNode[]` | **Required** | Tree data |
1245
+ | `folderColor` | `string` | `'#66bb6a'` | Default folder icon colour |
1246
+ | `leafColor` | `string` | `'#90a4ae'` | Leaf icon colour |
1247
+ | `expandedKeys` | `Key[]` | | Controlled expanded keys |
1248
+ | `defaultExpandedKeys` | `Key[]` | | Default expanded keys |
1249
+ | `onExpandedKeysChange` | `(keys: Key[]) => void` | | Callback on expand/collapse |
1250
+ | `onNodeClick` | `(node: FolderTreeNode) => void` | | Callback on node click |
1251
+ | `showCount` | `boolean` | `true` | Show child count next to folders |
1252
+ | `indent` | `number` | `24` | Indent per nesting level (px) |
1253
+ | `iconSize` | `number` | `18` | Folder/leaf icon size (px) |
1254
+ | `fontSize` | `number \| string` | `14` | Label font size |
1255
+
1256
+ **FolderTreeNode shape:** `{ key, label, tag?, icon?, folderColor?, children?, disabled?, count? }`
1257
+
1258
+ - `count` — explicit count displayed next to the label, overrides `children.length`. Useful for server-side totals.
1259
+ - `icon` — custom `ReactNode` icon (e.g. `<Icon icon={Star} size={18} />`), replaces the default folder icon.
1260
+ - Nodes support arbitrary nesting depth (children of children of children…).
1261
+
1262
+ Also exports: `FolderIcon` — standalone folder SVG icon with `color`, `open`, `size` props.
1263
+
1264
+ ### Accordion / AccordionItem
1265
+
1266
+ **AccordionProps:**
1267
+
1268
+ | Prop | Type | Default | Description |
1269
+ |---|---|---|---|
1270
+ | `accordion` | `boolean` | `false` | Single item expand |
1271
+ | `children` | `ReactNode` | | AccordionItem children |
1272
+ | `defaultExpandedKeys` | `Key[]` | | Default expanded |
1273
+ | `expandedKeys` | `Key[]` | | Controlled expanded |
1274
+ | `onExpandedChange` | `(keys: Key[]) => void` | | Change callback |
1275
+ | `gap` | `number` | | Item gap |
1276
+ | `showDivider` | `boolean` | `false` | Show dividers |
1277
+ | `hideIndicator` | `boolean` | `false` | Hide chevron |
1278
+ | `indicatorPlacement` | `'end' \| 'start'` | `'start'` | Indicator position |
1279
+ | `keepContentMounted` | `boolean` | `true` | Keep content mounted |
1280
+ | `disableAnimation` | `boolean` | `false` | Disable animation |
1281
+ | `variant` | `BlockProps['variant']` | | Visual variant |
1282
+
1283
+ **AccordionItemProps:**
1284
+
1285
+ | Prop | Type | Description |
1286
+ |---|---|---|
1287
+ | `itemKey` | `Key` | **Required.** Unique key |
1288
+ | `title` | `ReactNode` | **Required.** Item title |
1289
+ | `children` | `ReactNode` | Content |
1290
+ | `expand` | `boolean` | Controlled expand |
1291
+ | `defaultExpand` | `boolean` | Default expand |
1292
+ | `onExpandChange` | `(expanded: boolean) => void` | Callback |
1293
+ | `disabled` | `boolean` | Disabled |
1294
+ | `allowExpand` | `boolean` | Allow expanding (default `true`) |
1295
+ | `hideIndicator` | `boolean` | Hide indicator |
1296
+ | `indicator` | `ReactNode \| (props) => ReactNode` | Custom indicator |
1297
+ | `indicatorPlacement` | `'end' \| 'start'` | Indicator position |
1298
+ | `action` | `ReactNode` | Hover action |
1299
+ | `variant` | `BlockProps['variant']` | Variant |
1300
+
1301
+ ### Collapse
1302
+
1303
+ Extends Ant Design `Collapse`.
1304
+
1305
+ | Prop | Type | Description |
1306
+ |---|---|---|
1307
+ | `items` | `CollapseItemType[]` | **Required.** Items with `desc`, `icon` |
1308
+ | `collapsible` | `boolean` | Enable collapse |
1309
+ | `gap` | `number` | Gap |
1310
+ | `padding` | `number \| string \| { body?, header? }` | Padding |
1311
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1312
+
1313
+ ### List / ListItem
1314
+
1315
+ | Prop (ListItem) | Type | Description |
1316
+ |---|---|---|
1317
+ | `key` | `string` | **Required.** Unique key |
1318
+ | `title` | `ReactNode` | **Required.** Title |
1319
+ | `description` | `ReactNode` | Description |
1320
+ | `avatar` | `ReactNode` | Avatar |
1321
+ | `actions` | `ReactNode` | Actions |
1322
+ | `addon` | `ReactNode` | Additional content |
1323
+ | `active` | `boolean` | Active state |
1324
+ | `date` | `number` | Timestamp |
1325
+ | `loading` | `boolean` | Loading |
1326
+ | `pin` | `boolean` | Pinned |
1327
+ | `showAction` | `boolean` | Always show actions |
1328
+
1329
+ **ListProps:** `items`, `activeKey`, `onClick`.
1330
+
1331
+ ### Table
1332
+
1333
+ | Prop | Type | Description |
1334
+ |---|---|---|
1335
+ | `data` | `{ bind?: T[], read?: TableReadConfig }` | **Required.** Data source (local array or remote API) |
1336
+ | `columns` | `TableColumn<T>[]` | **Required.** Column definitions with `key`, `title`, `item`, `func`, `sortable`, `width`, `align`, `fixed` |
1337
+ | `pagination` | `boolean` | Enable pagination |
1338
+ | `sortable` | `boolean` | Enable sorting |
1339
+ | `filterable` | `boolean` | Enable filter |
1340
+ | `selectable` | `boolean` | Enable row selection |
1341
+ | `reload` | `boolean` | Show reload button |
1342
+ | `height` | `number \| string` | Fixed height |
1343
+ | `rowHeight` | `number` | Row height |
1344
+ | `overscan` | `number` | Virtual scroll overscan |
1345
+ | `defaultPageSize` | `number` | Initial page size |
1346
+ | `pageSize` | `{ visible?, count?, options? }` | Page size config |
1347
+ | `emptyState` | `ReactNode` | Custom empty state |
1348
+ | `onDataChange` | `(rows: T[]) => void` | Data change callback |
1349
+
1350
+ ### SortableList
1351
+
1352
+ Drag-and-drop sortable list.
1353
+
1354
+ | Prop | Type | Description |
1355
+ |---|---|---|
1356
+ | `items` | `SortableListItem[]` | **Required.** Items with `id` |
1357
+ | `onChange` | `(items) => void` | **Required.** Reorder handler |
1358
+ | `renderItem` | `(item) => ReactNode` | **Required.** Item renderer |
1359
+
1360
+ ### Tabs
1361
+
1362
+ Extends Ant Design `Tabs`.
1363
+
1364
+ | Prop | Type | Description |
1365
+ |---|---|---|
1366
+ | `compact` | `boolean` | Compact mode |
1367
+ | `variant` | `'square' \| 'rounded' \| 'point'` | Tab style |
1368
+
1369
+ ### Toc
1370
+
1371
+ Table of contents navigation.
1372
+
1373
+ | Prop | Type | Description |
1374
+ |---|---|---|
1375
+ | `items` | `TocItemType[]` | **Required.** TOC items with `id`, `title`, `children` |
1376
+ | `activeKey` | `string` | Active item |
1377
+ | `onChange` | `(activeKey) => void` | Change callback |
1378
+ | `headerHeight` | `number` | Scroll offset |
1379
+ | `tocWidth` | `number` | Width |
1380
+ | `isMobile` | `boolean` | Mobile mode |
1381
+
1382
+ ---
1383
+
1384
+ ## Overlays
1385
+
1386
+ ### Modal
1387
+
1388
+ Extends Ant Design `Modal`. Also exports `createModal`, `createRawModal`, `ModalProvider`, `ModalHost`, `useModalContext`.
1389
+
1390
+ | Prop | Type | Description |
1391
+ |---|---|---|
1392
+ | `allowFullscreen` | `boolean` | Fullscreen button |
1393
+ | `enableResponsive` | `boolean` | Responsive mode |
1394
+ | `paddings` | `{ desktop?, mobile? }` | Padding config |
1395
+
1396
+ ### ConfirmationModal
1397
+
1398
+ Imperative confirmation API built on top of `antd` `Modal.confirm`.
1399
+
1400
+ Also exports: `confirmConfirmationModal`.
1401
+
1402
+ #### Methods
1403
+
1404
+ | Method | Description | Type |
1405
+ |---|---|---|
1406
+ | `ConfirmationModal.confirm` | Open a confirmation modal with full config | `(props: ConfirmationModalProps) => { destroy; update }` |
1407
+ | `ConfirmationModal.danger` | Open danger-style confirmation (danger icon + danger OK button) | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
1408
+ | `ConfirmationModal.error` | Alias of `danger` | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
1409
+ | `ConfirmationModal.warning` | Open warning-style confirmation | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
1410
+ | `ConfirmationModal.info` | Open info-style confirmation | `(props: Omit<ConfirmationModalProps, 'type'>) => { destroy; update }` |
1411
+
1412
+ #### ConfirmationModalProps
1413
+
1414
+ Extends Ant Design `ModalFuncProps` with additional type mapping:
1415
+
1416
+ | Prop | Type | Description |
1417
+ |---|---|---|
1418
+ | `type` | `'danger' \| 'info' \| 'warning' \| 'error'` | Visual variant that controls icon and OK button danger state |
1419
+ | `okType` | `ModalFuncProps['okType'] \| 'danger'` | Accepts `'danger'` shortcut (mapped to primary + `danger: true`) |
1420
+ | `icon` | `ReactNode` | Custom icon override |
1421
+ | `okButtonProps` | `ButtonProps` | OK button props (danger auto-applied for `danger`/`error`) |
1422
+ | `...rest` | `ModalFuncProps` | All native `Modal.confirm` options (`title`, `content`, `onOk`, etc.) |
1423
+
1424
+ ### Drawer
1425
+
1426
+ Extends Ant Design `Drawer`.
1427
+
1428
+ | Prop | Type | Description |
1429
+ |---|---|---|
1430
+ | `sidebar` | `ReactNode` | Sidebar panel |
1431
+ | `sidebarWidth` | `number` | Sidebar width |
1432
+ | `noHeader` | `boolean` | Hide header |
1433
+ | `containerMaxWidth` | `number \| string` | Body max width |
1434
+ | `closeIconProps` | `ActionIconProps` | Close icon config |
1435
+
1436
+ ### Popover
1437
+
1438
+ Built on Base UI Popover.
1439
+
1440
+ | Prop | Type | Default | Description |
1441
+ |---|---|---|---|
1442
+ | `content` | `ReactNode` | | **Required.** Popup content |
1443
+ | `children` | `ReactElement \| ReactNode` | | **Required.** Trigger |
1444
+ | `trigger` | `Trigger` | `'hover'` | Trigger mode |
1445
+ | `placement` | `PopoverPlacement` | `'top'` | Placement |
1446
+ | `arrow` | `boolean` | `false` | Show arrow |
1447
+ | `open` | `boolean` | | Controlled |
1448
+ | `defaultOpen` | `boolean` | `false` | Default open |
1449
+ | `onOpenChange` | `(open) => void` | | Callback |
1450
+ | `disabled` | `boolean` | | Disabled |
1451
+ | `inset` | `boolean` | `false` | Inset display |
1452
+ | `standalone` | `boolean` | | Ignore PopoverGroup |
1453
+ | `mouseEnterDelay` | `number` | `0.1` | Enter delay (seconds) |
1454
+ | `mouseLeaveDelay` | `number` | `0.1` | Leave delay (seconds) |
1455
+ | `openDelay` | `number` | | Open delay (ms, overrides mouseEnterDelay) |
1456
+ | `closeDelay` | `number` | | Close delay (ms) |
1457
+ | `zIndex` | `number` | | Z-index |
1458
+
1459
+ ### Tooltip
1460
+
1461
+ Built on Base UI Tooltip. Also exports `TooltipGroup`.
1462
+
1463
+ | Prop | Type | Default | Description |
1464
+ |---|---|---|---|
1465
+ | `title` | `ReactNode` | | **Required.** Tooltip content |
1466
+ | `children` | `ReactElement \| ReactNode` | | **Required.** Trigger |
1467
+ | `placement` | `TooltipPlacement` | | Placement |
1468
+ | `arrow` | `boolean` | `false` | Show arrow |
1469
+ | `open` | `boolean` | | Controlled |
1470
+ | `defaultOpen` | `boolean` | | Default open |
1471
+ | `onOpenChange` | `(open) => void` | | Callback |
1472
+ | `disabled` | `boolean` | | Disabled |
1473
+ | `hotkey` | `string` | | Hotkey hint |
1474
+ | `hotkeyProps` | `Omit<HotkeyProps, 'keys'>` | | Hotkey config |
1475
+ | `standalone` | `boolean` | | Ignore TooltipGroup |
1476
+ | `mouseEnterDelay` | `number` | | Enter delay (seconds) |
1477
+ | `mouseLeaveDelay` | `number` | | Leave delay (seconds) |
1478
+ | `openDelay` | `number` | | Open delay (ms) |
1479
+ | `closeDelay` | `number` | | Close delay (ms) |
1480
+ | `zIndex` | `number` | | Z-index |
1481
+
1482
+ ### Dropdown
1483
+
1484
+ Extends Ant Design `Dropdown` with custom `Menu`.
1485
+
1486
+ | Prop | Type | Description |
1487
+ |---|---|---|
1488
+ | `menu` | `MenuProps` | **Required.** Menu configuration |
1489
+ | `iconProps` | `IconContentConfig` | Icon config |
1490
+
1491
+ ### DropdownMenu
1492
+
1493
+ Built on Base UI Menu. Includes many atomic sub-components.
1494
+
1495
+ | Prop | Type | Default | Description |
1496
+ |---|---|---|---|
1497
+ | `children` | `ReactNode` | | **Required.** Trigger element |
1498
+ | `items` | `DropdownItem[] \| () => DropdownItem[]` | | **Required.** Menu items |
1499
+ | `placement` | `DropdownMenuPlacement` | | Placement |
1500
+ | `trigger` | `Trigger` | `'click'` | Trigger mode |
1501
+ | `iconSpaceMode` | `'global' \| 'group'` | `'global'` | Icon space reservation |
1502
+ | `nativeButton` | `boolean` | | Use native button trigger |
1503
+
1504
+ ### ContextMenu
1505
+
1506
+ Right-click context menu. Exports `ContextMenuHost`, `ContextMenuTrigger`, `showContextMenu`, `closeContextMenu`, `updateContextMenuItems`.
1507
+
1508
+ ### Toast
1509
+
1510
+ Toast notification system. Exports `toast` API, `ToastHost`, `useToast`.
1511
+
1512
+ **toast API methods:** `toast(options)`, `toast.success(...)`, `toast.error(...)`, `toast.info(...)`, `toast.warning(...)`, `toast.loading(...)`, `toast.promise(...)`, `toast.dismiss(id?)`.
1513
+
1514
+ | Prop (ToastOptions) | Type | Default | Description |
1515
+ |---|---|---|---|
1516
+ | `title` | `ReactNode` | | Toast title |
1517
+ | `description` | `ReactNode` | | Description |
1518
+ | `type` | `'success' \| 'info' \| 'warning' \| 'error' \| 'loading' \| 'default'` | `'default'` | Type |
1519
+ | `duration` | `number` | `5000` | Duration (ms) |
1520
+ | `icon` | `IconProps['icon']` | | Custom icon |
1521
+ | `closable` | `boolean` | `true` | Can close |
1522
+ | `placement` | `ToastPosition` | | Position override |
1523
+ | `actions` | `ToastAction[]` | | Action buttons |
1524
+ | `onClose` | `() => void` | | Close callback |
1525
+
1526
+ **ToastHost Props:**
1527
+
1528
+ | Prop | Type | Default | Description |
1529
+ |---|---|---|---|
1530
+ | `position` | `ToastPosition` | `'bottom-right'` | Default toast position |
1531
+ | `duration` | `number` | `5000` | Default duration (ms) |
1532
+ | `limit` | `number` | `5` | Max visible toasts |
1533
+ | `swipeDirection` | `('left' \| 'right' \| 'up' \| 'down')[]` | `['down', 'right']` | Swipe to dismiss direction |
1534
+ | `root` | `HTMLElement \| ShadowRoot \| null` | | Portal root |
1535
+ | `className` | `string` | | Custom class |
1536
+
1537
+ ### Toast Usage Examples
1538
+
1539
+ #### 1. Setup — Add `ToastHost` to your app root
1540
+
1541
+ `ToastHost` must be rendered once at the top level of your app. Without it, toasts will not appear.
1542
+
1543
+ ```tsx
1544
+ import { ThemeProvider, ToastHost } from '@gomeniucivan/ui';
1545
+
1546
+ function App() {
1547
+ return (
1548
+ <ThemeProvider>
1549
+ {/* Your app content */}
1550
+ <MyRoutes />
1551
+
1552
+ {/* Render once at the root — configures default position, duration, etc. */}
1553
+ <ToastHost position="bottom-right" duration={5000} limit={5} />
1554
+ </ThemeProvider>
1555
+ );
1556
+ }
1557
+ ```
1558
+
1559
+ #### 2. Simple toasts (string shorthand)
1560
+
1561
+ ```tsx
1562
+ import { toast } from '@gomeniucivan/ui';
1563
+
1564
+ // Each method accepts a string (used as description) or a full options object
1565
+ toast.success('Changes saved successfully');
1566
+ toast.error('Something went wrong');
1567
+ toast.info('New version available');
1568
+ toast.warning('Your session will expire soon');
1569
+ ```
1570
+
1571
+ #### 3. Toast with full options
1572
+
1573
+ ```tsx
1574
+ import { toast } from '@gomeniucivan/ui';
1575
+ import { Rocket } from 'lucide-react';
1576
+
1577
+ toast.success({
1578
+ title: 'Deployment Complete',
1579
+ description: 'Your app has been deployed to production.',
1580
+ icon: Rocket,
1581
+ duration: 8000,
1582
+ placement: 'top-right', // override default position for this toast
1583
+ closable: true,
1584
+ onClose: () => console.log('Toast closed'),
1585
+ });
1586
+ ```
1587
+
1588
+ #### 4. Loading + Promise pattern
1589
+
1590
+ ```tsx
1591
+ import { toast } from '@gomeniucivan/ui';
1592
+
1593
+ // Option A: Manual loading toast
1594
+ const loadingToast = toast.loading('Uploading file...');
1595
+ try {
1596
+ await uploadFile(file);
1597
+ loadingToast.close();
1598
+ toast.success('File uploaded!');
1599
+ } catch (err) {
1600
+ loadingToast.close();
1601
+ toast.error('Upload failed');
1602
+ }
1603
+
1604
+ // Option B: Promise helper (handles loading → success/error automatically)
1605
+ toast.promise(
1606
+ fetch('/api/data').then(res => res.json()),
1607
+ {
1608
+ loading: 'Fetching data...',
1609
+ success: (data) => `Loaded ${data.length} items`,
1610
+ error: (err) => `Error: ${err.message}`,
1611
+ }
1612
+ );
1613
+
1614
+ // Promise helper with full options objects
1615
+ toast.promise(saveSettings(values), {
1616
+ loading: { title: 'Saving', description: 'Applying your settings...' },
1617
+ success: { title: 'Saved', description: 'Settings updated successfully.' },
1618
+ error: { title: 'Error', description: 'Failed to save settings.' },
1619
+ });
1620
+ ```
1621
+
1622
+ #### 5. Toast with action buttons
1623
+
1624
+ ```tsx
1625
+ import { toast } from '@gomeniucivan/ui';
1626
+
1627
+ toast({
1628
+ type: 'info',
1629
+ title: 'Item Deleted',
1630
+ description: 'The item has been moved to trash.',
1631
+ actions: [
1632
+ {
1633
+ label: 'Undo',
1634
+ variant: 'primary',
1635
+ onClick: () => restoreItem(itemId),
1636
+ },
1637
+ {
1638
+ label: 'Dismiss',
1639
+ variant: 'ghost',
1640
+ },
1641
+ ],
1642
+ });
1643
+ ```
1644
+
1645
+ #### 6. Update & dismiss toasts
1646
+
1647
+ ```tsx
1648
+ import { toast } from '@gomeniucivan/ui';
1649
+
1650
+ // Create a toast and get the instance
1651
+ const instance = toast.info({ title: 'Processing...', duration: 0 });
1652
+
1653
+ // Update it later
1654
+ instance.update({ title: 'Almost done...', description: '90% complete' });
1655
+
1656
+ // Close a specific toast
1657
+ instance.close();
1658
+
1659
+ // Dismiss all toasts
1660
+ toast.dismiss();
1661
+
1662
+ // Dismiss a specific toast by ID
1663
+ toast.dismiss(instance.id);
1664
+ ```
1665
+
1666
+ #### 7. Using `useToast` hook (inside components)
1667
+
1668
+ ```tsx
1669
+ import { useToast, Button } from '@gomeniucivan/ui';
1670
+
1671
+ function SaveButton({ onSave }: { onSave: () => Promise<void> }) {
1672
+ const toast = useToast();
1673
+
1674
+ const handleSave = async () => {
1675
+ try {
1676
+ await onSave();
1677
+ toast.success('Saved!');
1678
+ } catch {
1679
+ toast.error('Save failed');
1680
+ }
1681
+ };
1682
+
1683
+ return <Button onClick={handleSave}>Save</Button>;
1684
+ }
1685
+ ```
1686
+
1687
+ #### All Toast Imports
1688
+
1689
+ ```tsx
1690
+ // Toast API (imperative, works anywhere)
1691
+ import { toast, ToastHost, useToast } from '@gomeniucivan/ui';
1692
+
1693
+ // Types
1694
+ import type {
1695
+ ToastAPI,
1696
+ ToastOptions,
1697
+ ToastInstance,
1698
+ ToastHostProps,
1699
+ ToastPosition,
1700
+ ToastType,
1701
+ ToastAction,
1702
+ ToastPromiseOptions,
1703
+ ToastProps,
1704
+ } from '@gomeniucivan/ui';
1705
+ ```
1706
+
1707
+ ---
1708
+
1709
+ ## Media
1710
+
1711
+ ### Avatar / AvatarGroup
1712
+
1713
+ | Prop (Avatar) | Type | Description |
1714
+ |---|---|---|
1715
+ | `avatar` | `string \| ReactNode` | Avatar content |
1716
+ | `size` | `number` | Size in px |
1717
+ | `shape` | `'circle' \| 'square'` | Shape |
1718
+ | `title` | `string` | Tooltip title |
1719
+ | `animation` | `boolean` | Hover animation |
1720
+ | `background` | `string` | Background colour |
1721
+ | `bordered` | `boolean` | Show border |
1722
+ | `borderedColor` | `string` | Border colour |
1723
+ | `loading` | `boolean` | Loading skeleton |
1724
+ | `shadow` | `boolean` | Shadow |
1725
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | Variant |
1726
+ | `tooltipProps` | `Omit<TooltipProps, 'children' \| 'title'>` | Tooltip config |
1727
+
1728
+ **AvatarGroup:** `items`, `max`, `onClick`, `zIndexReverse`.
1729
+
1730
+ ### GroupAvatar
1731
+
1732
+ Grid-based group avatar.
1733
+
1734
+ | Prop | Type | Description |
1735
+ |---|---|---|
1736
+ | `avatars` | `(string \| AvatarProps)[]` | Avatar list |
1737
+ | `size` | `number` | Container size |
1738
+ | `grid` | `2 \| 3 \| 'auto'` | Grid layout |
1739
+ | `avatarShape` | `'circle' \| 'square'` | Individual shape |
1740
+ | `cornerShape` | `string` | Smooth corner mask |
1741
+
1742
+ ### Image / PreviewGroup
1743
+
1744
+ Extends Ant Design `Image`. **PreviewGroup** enables gallery mode.
1745
+
1746
+ | Prop (Image) | Type | Description |
1747
+ |---|---|---|
1748
+ | `actions` | `ReactNode` | Overlay actions |
1749
+ | `alwaysShowActions` | `boolean` | Always show actions |
1750
+ | `preview` | `boolean \| ImagePreviewOptions` | Preview config |
1751
+ | `toolbarAddon` | `ReactNode` | Extra toolbar items |
1752
+ | `objectFit` | `'cover' \| 'contain'` | Object fit |
1753
+ | `size` | `number \| string` | Shorthand size |
1754
+ | `maxWidth/maxHeight/minWidth/minHeight` | `number \| string` | Dimension constraints |
1755
+ | `isLoading` | `boolean` | Loading state |
1756
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | Variant |
1757
+
1758
+ ### Video
1759
+
1760
+ | Prop | Type | Default | Description |
1761
+ |---|---|---|---|
1762
+ | `src` | `string` | | **Required.** Video source |
1763
+ | `autoPlay` | `boolean` | | Auto play |
1764
+ | `loop` | `boolean` | | Loop |
1765
+ | `muted` | `boolean` | | Muted |
1766
+ | `poster` | `string` | | Poster image |
1767
+ | `preview` | `boolean` | `true` | Show play overlay |
1768
+ | `preload` | `string` | `'auto'` | Preload |
1769
+ | `isLoading` | `boolean` | | Loading skeleton |
1770
+ | `variant` | `'borderless' \| 'filled' \| 'outlined'` | `'filled'` | Variant |
1771
+ | `width/height` | `number \| string` | | Dimensions |
1772
+ | `maxWidth/maxHeight/minWidth/minHeight` | `number \| string` | | Constraints |
1773
+ | `size` | `number \| string` | | Shorthand size |
1774
+
1775
+ ### FluentEmoji
1776
+
1777
+ | Prop | Type | Description |
1778
+ |---|---|---|
1779
+ | `emoji` | `string` | **Required.** Emoji character |
1780
+ | `size` | `number` | Size |
1781
+ | `type` | `EmojiType` | Emoji style type |
1782
+ | `unoptimized` | `boolean` | Disable optimization |
1783
+
1784
+ ### EmojiPicker
1785
+
1786
+ Avatar/emoji picker with popover.
1787
+
1788
+ | Prop | Type | Description |
1789
+ |---|---|---|
1790
+ | `value` | `string` | Selected emoji/avatar |
1791
+ | `defaultAvatar` | `string` | Default avatar |
1792
+ | `onChange` | `(emoji: string) => void` | Change handler |
1793
+ | `allowUpload` | `boolean \| { enableEmoji? }` | Enable upload |
1794
+ | `allowDelete` | `boolean` | Enable delete |
1795
+ | `onUpload` | `(file: File) => void` | Upload handler |
1796
+ | `onDelete` | `() => void` | Delete handler |
1797
+ | `customEmojis` | `EmojiPickerCustomEmoji[]` | Custom emojis |
1798
+ | `customTabs` | `EmojiPickerCustomTab[]` | Custom tabs |
1799
+ | `locale` | `string` | Locale |
1800
+ | `size` | `number` | Avatar size |
1801
+ | `open` | `boolean` | Controlled open |
1802
+ | `onOpenChange` | `(open) => void` | Open callback |
1803
+ | `loading` | `boolean` | Loading |
1804
+
1805
+ ### FileTypeIcon
1806
+
1807
+ | Prop | Type | Description |
1808
+ |---|---|---|
1809
+ | `filetype` | `string` | File extension |
1810
+ | `type` | `'file' \| 'folder'` | Icon type |
1811
+ | `size` | `number` | Size |
1812
+ | `color` | `string` | Colour |
1813
+ | `icon` | `ReactNode` | Custom icon |
1814
+ | `variant` | `'color' \| 'mono'` | Style |
1815
+
1816
+ ### MaterialFileTypeIcon
1817
+
1818
+ | Prop | Type | Description |
1819
+ |---|---|---|
1820
+ | `filename` | `string` | **Required.** File name |
1821
+ | `type` | `'file' \| 'folder'` | Type |
1822
+ | `size` | `number` | Size |
1823
+ | `open` | `boolean` | Folder open state |
1824
+ | `variant` | `'raw' \| 'file' \| 'folder'` | Display mode |
1825
+ | `fallbackUnknownType` | `boolean` | Fallback for unknown types |
1826
+
1827
+ ---
1828
+
1829
+ ## Code & Markdown
1830
+
1831
+ ### Highlighter / SyntaxHighlighter
1832
+
1833
+ | Prop (Highlighter) | Type | Description |
1834
+ |---|---|---|
1835
+ | `children` | `string` | **Required.** Code content |
1836
+ | `language` | `string` | **Required.** Language |
1837
+ | `theme` | `'lobe-theme' \| BuiltinTheme` | Syntax theme |
1838
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1839
+ | `animated` | `boolean` | Stream animation |
1840
+ | `copyable` | `boolean` | Copy button |
1841
+ | `fileName` | `string` | File name display |
1842
+ | `showLanguage` | `boolean` | Show language label |
1843
+ | `fullFeatured` | `boolean` | Full featured mode (expand/collapse, etc.) |
1844
+ | `defaultExpand` | `boolean` | Default expand |
1845
+ | `wrap` | `boolean` | Word wrap |
1846
+ | `shadow` | `boolean` | Shadow |
1847
+ | `enableTransformer` | `boolean` | Enable Shiki transformers |
1848
+ | `allowChangeLanguage` | `boolean` | Allow language change |
1849
+ | `icon` | `ReactNode` | Custom icon |
1850
+
1851
+ ### CodeDiff / PatchDiff
1852
+
1853
+ | Prop (CodeDiff) | Type | Default | Description |
1854
+ |---|---|---|---|
1855
+ | `oldContent` | `string` | | **Required.** Before |
1856
+ | `newContent` | `string` | | **Required.** After |
1857
+ | `language` | `string` | | Language |
1858
+ | `fileName` | `string` | | File name |
1859
+ | `viewMode` | `'split' \| 'unified'` | `'split'` | View mode |
1860
+ | `showHeader` | `boolean` | `true` | Show header |
1861
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | `'filled'` | Variant |
1862
+
1863
+ **PatchDiff** takes `patch: string` instead of `oldContent`/`newContent`.
1864
+
1865
+ ### CodeEditor
1866
+
1867
+ | Prop | Type | Description |
1868
+ |---|---|---|
1869
+ | `value` | `string` | **Required.** Code value |
1870
+ | `onValueChange` | `(value: string) => void` | **Required.** Change handler |
1871
+ | `language` | `string` | **Required.** Language |
1872
+ | `defaultValue` | `string` | Default value |
1873
+ | `placeholder` | `string` | Placeholder |
1874
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1875
+
1876
+ ### Markdown / Typography
1877
+
1878
+ | Prop (Markdown) | Type | Description |
1879
+ |---|---|---|
1880
+ | `children` | `string` | **Required.** Markdown content |
1881
+ | `variant` | `'default' \| 'chat'` | Render mode |
1882
+ | `animated` | `boolean` | Stream animation |
1883
+ | `enableLatex` | `boolean` | Enable LaTeX |
1884
+ | `enableMermaid` | `boolean` | Enable Mermaid diagrams |
1885
+ | `enableGithubAlert` | `boolean` | GitHub-style alerts |
1886
+ | `enableStream` | `boolean` | Stream mode |
1887
+ | `enableImageGallery` | `boolean` | Image gallery |
1888
+ | `enableCustomFootnotes` | `boolean` | Custom footnotes |
1889
+ | `allowHtml` | `boolean` | Allow raw HTML |
1890
+ | `fullFeaturedCodeBlock` | `boolean` | Full code blocks |
1891
+ | `showFootnotes` | `boolean` | Show footnotes |
1892
+ | `fontSize` | `number` | Font size |
1893
+ | `lineHeight` | `number` | Line height |
1894
+ | `headerMultiple` | `number` | Header size multiplier |
1895
+ | `customRender` | `(dom, context) => ReactNode` | Custom renderer |
1896
+ | `onDoubleClick` | `() => void` | Double click handler |
1897
+ | `componentProps` | `{ a?, highlight?, img?, mermaid?, pre?, video? }` | Component overrides |
1898
+ | `components` | `Components & Record<string, FC>` | Custom MDX components |
1899
+ | `remarkPlugins` | `Pluggable[]` | Remark plugins |
1900
+ | `rehypePlugins` | `Pluggable[]` | Rehype plugins |
1901
+ | `citations` | `CitationItem[]` | Citation data |
1902
+
1903
+ ### Mermaid / SyntaxMermaid
1904
+
1905
+ | Prop (Mermaid) | Type | Description |
1906
+ |---|---|---|
1907
+ | `children` | `string` | **Required.** Mermaid definition |
1908
+ | `theme` | `'lobe-theme' \| MermaidConfig['theme']` | Theme |
1909
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1910
+ | `animated` | `boolean` | Animation |
1911
+ | `copyable` | `boolean` | Copy button |
1912
+ | `fullFeatured` | `boolean` | Full featured |
1913
+ | `fileName` | `string` | File name |
1914
+ | `showLanguage` | `boolean` | Show language |
1915
+ | `shadow` | `boolean` | Shadow |
1916
+
1917
+ ### Snippet
1918
+
1919
+ | Prop | Type | Description |
1920
+ |---|---|---|
1921
+ | `children` | `string` | **Required.** Command text |
1922
+ | `copyable` | `boolean` | Copy button |
1923
+ | `language` | `string` | Language |
1924
+ | `prefix` | `string` | Prefix symbol |
1925
+ | `shadow` | `boolean` | Shadow |
1926
+ | `spotlight` | `boolean` | Spotlight effect |
1927
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1928
+
1929
+ ---
1930
+
1931
+ ## Navigation
1932
+
1933
+ ### Menu
1934
+
1935
+ Extends Ant Design Menu.
1936
+
1937
+ | Prop | Type | Description |
1938
+ |---|---|---|
1939
+ | `items` | `GenericItemType[]` | **Required.** Menu items |
1940
+ | `compact` | `boolean` | Compact mode |
1941
+ | `shadow` | `boolean` | Shadow |
1942
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1943
+ | `iconProps` | `IconContentConfig` | Icon config |
1944
+
1945
+ ### Burger
1946
+
1947
+ Mobile hamburger menu.
1948
+
1949
+ | Prop | Type | Description |
1950
+ |---|---|---|
1951
+ | `opened` | `boolean` | **Required.** Open state |
1952
+ | `setOpened` | `(state: boolean) => void` | **Required.** Toggle handler |
1953
+ | `items` | `MenuProps['items']` | **Required.** Menu items |
1954
+ | `onClick` | `MenuProps['onClick']` | Click handler |
1955
+ | `selectedKeys` | `MenuProps['selectedKeys']` | Selected keys |
1956
+ | `openKeys` | `MenuProps['openKeys']` | Open sub-menu keys |
1957
+ | `fullscreen` | `boolean` | Fullscreen drawer |
1958
+ | `headerHeight` | `number` | Header height offset |
1959
+ | `size` | `ActionIconProps['size']` | Icon size |
1960
+ | `variant` | `ActionIconProps['variant']` | Icon variant |
1961
+
1962
+ ### Hotkey
1963
+
1964
+ Display keyboard shortcuts.
1965
+
1966
+ | Prop | Type | Description |
1967
+ |---|---|---|
1968
+ | `keys` | `string` | **Required.** Key combination |
1969
+ | `compact` | `boolean` | Compact layout |
1970
+ | `inverseTheme` | `boolean` | Inverse colours |
1971
+ | `isApple` | `boolean` | Use macOS symbols |
1972
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1973
+
1974
+ ### EditorSlashMenu
1975
+
1976
+ Autocomplete slash-command menu.
1977
+
1978
+ Items are typed as `EditorSlashMenuOption` with: `value`, `label`, `icon?`, `extra?`, `keywords?`, `disabled?`, `danger?`. Groups: `EditorSlashMenuGroup` with `label?` and `items`.
1979
+
1980
+ ---
1981
+
1982
+ ## Misc
1983
+
1984
+ ### Alert
1985
+
1986
+ Extends Ant Design `Alert`.
1987
+
1988
+ | Prop | Type | Description |
1989
+ |---|---|---|
1990
+ | `type` | `'success' \| 'info' \| 'warning' \| 'error' \| 'secondary'` | Alert type |
1991
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
1992
+ | `icon` | `IconProps['icon']` | Custom icon |
1993
+ | `iconProps` | `Omit<IconProps, 'icon'>` | Icon config |
1994
+ | `glass` | `boolean` | Glass effect |
1995
+ | `colorfulText` | `boolean` | Coloured text |
1996
+ | `extra` | `ReactNode` | Extra content |
1997
+ | `extraDefaultExpand` | `boolean` | Expand extra by default |
1998
+ | `extraIsolate` | `boolean` | Isolate extra section |
1999
+
2000
+ ### GuideCard
2001
+
2002
+ | Prop | Type | Description |
2003
+ |---|---|---|
2004
+ | `title` | `ReactNode` | Title |
2005
+ | `desc` | `ReactNode` | Description |
2006
+ | `cover` | `string` | Cover image URL |
2007
+ | `closable` | `boolean` | Closable |
2008
+ | `onClose` | `ActionIconProps['onClick']` | Close handler |
2009
+ | `afterClose` | `() => void` | After close callback |
2010
+ | `shadow` | `boolean` | Shadow |
2011
+ | `variant` | `'filled' \| 'outlined' \| 'borderless'` | Variant |
2012
+ | `width` | `number` | Width |
2013
+ | `height` | `number` | Height |
2014
+
2015
+ ### CopyButton
2016
+
2017
+ Extends `ActionIcon`. Copies text to clipboard on click.
2018
+
2019
+ | Prop | Type | Description |
2020
+ |---|---|---|
2021
+ | `content` | `string \| () => string` | **Required.** Content to copy |
2022
+
2023
+ ### DownloadButton
2024
+
2025
+ Extends `ActionIcon`. Downloads a file on click.
2026
+
2027
+ | Prop | Type | Description |
2028
+ |---|---|---|
2029
+ | `blobUrl` | `string` | Blob URL |
2030
+ | `fileName` | `string` | File name |
2031
+ | `fileType` | `string` | MIME type |
2032
+
2033
+ ### SearchBar
2034
+
2035
+ Search input with optional modal.
2036
+
2037
+ | Prop | Type | Description |
2038
+ |---|---|---|
2039
+ | `defaultValue` | `string` | Default search |
2040
+ | `value` | `string` | Controlled value |
2041
+ | `onSearch` | `(value: string) => void` | Search handler |
2042
+ | `onInputChange` | `(value: string) => void` | Input change |
2043
+ | `enableShortKey` | `boolean` | Enable shortcut |
2044
+ | `shortKey` | `string` | Shortcut key |
2045
+ | `spotlight` | `boolean` | Spotlight mode |
2046
+ | `loading` | `boolean` | Loading |
2047
+ | `modal` | `boolean` | Modal mode |
2048
+ | `modalTitle` | `ReactNode` | Modal title |
2049
+ | `modalContent` | `ReactNode \| (value, close) => ReactNode` | Modal content |
2050
+ | `open` | `boolean` | Controlled open |
2051
+ | `onOpenChange` | `(open) => void` | Open change |
2052
+
2053
+ ### ThemeSwitch
2054
+
2055
+ | Prop | Type | Description |
2056
+ |---|---|---|
2057
+ | `themeMode` | `ThemeMode` | **Required.** Current theme |
2058
+ | `onThemeSwitch` | `(themeMode) => void` | **Required.** Switch handler |
2059
+ | `type` | `'icon' \| 'select'` | Switch type |
2060
+ | `size` | `ActionIconProps['size']` | Size |
2061
+ | `variant` | `ActionIconProps['variant']` | Variant |
2062
+ | `labels` | `{ auto, dark, light }` | Labels |
2063
+
2064
+ ### FontLoader
2065
+
2066
+ Loads an external font stylesheet.
2067
+
2068
+ | Prop | Type | Description |
2069
+ |---|---|---|
2070
+ | `url` | `string` | **Required.** Font stylesheet URL |
2071
+
2072
+ ### A
2073
+
2074
+ Anchor element that respects `ConfigProvider.aAs`.
2075
+
2076
+ ---
2077
+
2078
+ ## Exported Utilities
2079
+
2080
+ | Export | Description |
2081
+ |---|---|
2082
+ | `createStyles` | Re-exported from `antd-style`. Create scoped CSS-in-JS styles with full access to the antd theme token. |
2083
+ | `cx` | Re-exported from `antd-style`. Utility to merge class names (like `classnames`/`clsx`). |
2084
+ | `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. |
2085
+ | `copyToClipboard(text)` | Copy text to clipboard |
2086
+ | `preventDefault`, `stopPropagation`, `preventDefaultAndStopPropagation` | DOM event helpers |
2087
+ | `genCdnUrl({ pkg, version, path, proxy })` | Generate CDN URL |
2088
+ | `placementMap`, `toFloatingUIPlacement` | Placement utilities |
2089
+ | `combineKeys`, `KeyMapEnum` | Hotkey utilities |
2090
+ | `preprocessMarkdownContent` | Markdown preprocessing |
2091
+ | `highlighterThemes`, `mermaidThemes` | Theme objects |
2092
+ | `menuSharedStyles` | Shared menu styles |
2093
+ | `CLASSNAMES` | Global CSS class names |
2094
+ | `ErrorBoundary` | Re-exported from `react-error-boundary` |
2095
+ | `ShikiLobeTheme` | Shiki code theme |
2096
+
2097
+ ### Hooks
2098
+
2099
+ | Hook | Description |
2100
+ |---|---|
2101
+ | `useToken()` | Returns the full antd design token enriched with `isMobile` from `ThemeProvider`. Use `const { colorPrimary, isMobile } = useToken();`. |
2102
+ | `useForm(config)` | Form state management |
2103
+ | `useToast()` | Toast API access |
2104
+ | `useCdnFn()` | Get CDN URL builder |
2105
+ | `useModalContext()` | Modal context |
2106
+ | `usePopoverContext()` | Popover context |
2107
+ | `useSwitchContext()` | Switch context |
2108
+ | `useMotionComponent()` | Get motion library |
2109
+ | `useTranslation()` | i18n translation hook |
2110
+ | `usePopoverPortalContainer()` | Popover portal container |
2111
+
2112
+ ### Styling Utilities
2113
+
2114
+ #### `createStyles`
2115
+
2116
+ Create scoped CSS-in-JS styles with access to the antd theme token:
2117
+
2118
+ ```tsx
2119
+ import { createStyles } from '@gomeniucivan/ui';
2120
+
2121
+ const useStyles = createStyles(({ token, css }) => ({
2122
+ container: css`
2123
+ background: ${token.colorBgContainer};
2124
+ border-radius: ${token.borderRadiusLG}px;
2125
+ padding: ${token.paddingLG}px;
2126
+ `,
2127
+ }));
2128
+
2129
+ function MyComponent() {
2130
+ const { styles } = useStyles();
2131
+ return <div className={styles.container}>...</div>;
2132
+ }
2133
+ ```
2134
+
2135
+ #### `cx`
2136
+
2137
+ Merge class names (like `classnames`/`clsx`):
2138
+
2139
+ ```tsx
2140
+ import { cx } from '@gomeniucivan/ui';
2141
+
2142
+ <div className={cx('base', isActive && 'active', className)} />
2143
+ ```
2144
+
2145
+ #### `useToken`
2146
+
2147
+ Get the full antd design token enriched with `isMobile` from `ThemeProvider`, without the verbose `theme.useToken()` pattern:
2148
+
2149
+ ```tsx
2150
+ // ❌ Before (verbose)
2151
+ import { theme } from 'antd';
2152
+ const { useToken } = theme;
2153
+ const { token } = useToken();
2154
+
2155
+ // ✅ After (simple)
2156
+ import { useToken } from '@gomeniucivan/ui';
2157
+ const { colorPrimary, borderRadiusLG, isMobile } = useToken();
2158
+
2159
+ // Use token values
2160
+ <div style={{ color: colorPrimary, borderRadius: borderRadiusLG }} />
2161
+
2162
+ // Use isMobile (reads from ThemeProvider's isMobile prop)
2163
+ if (isMobile) {
2164
+ // render mobile layout
2165
+ }
2166
+ ```