@officesdk/design 0.1.6 → 0.1.9

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.
@@ -1,11 +1,14 @@
1
1
  import React from 'react';
2
2
  import { TooltipProps as TooltipProps$1 } from 'rc-tooltip/lib/Tooltip';
3
- import { Theme } from '@officesdk/design-theme';
3
+ import { DropdownProps as DropdownProps$1 } from 'rc-dropdown';
4
+ import * as styled_components from 'styled-components';
4
5
  import { ThemedStyledInterface } from 'styled-components';
6
+ import { Theme } from '@officesdk/design-theme';
5
7
 
6
8
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
7
9
  /**
8
10
  * Button variant type
11
+ * - 'icon': Square icon button without padding, size based on iconSize
9
12
  */
10
13
  variant?: 'solid' | 'outlined' | 'text' | 'icon';
11
14
  /**
@@ -30,13 +33,15 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
30
33
  */
31
34
  fullWidth?: boolean;
32
35
  /**
33
- * Icon to display before the button text
36
+ * Icon to display with the button text
37
+ * - If string: treated as icon src URL, rendered using Icon component
38
+ * - If ReactNode: rendered directly
34
39
  */
35
- iconBefore?: React.ReactNode;
40
+ icon?: string | React.ReactNode;
36
41
  /**
37
- * Icon to display after the button text
42
+ * Icon placement relative to text (only for text buttons)
38
43
  */
39
- iconAfter?: React.ReactNode;
44
+ iconPlacement?: 'before' | 'after';
40
45
  /**
41
46
  * Whether the icon button should have a border (only for variant='icon')
42
47
  */
@@ -50,12 +55,20 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
50
55
  * <Button>button</Button>
51
56
  *
52
57
  * @example
53
- * // Button with icons
54
- * <Button iconBefore={<Icon />}>button</Button>
58
+ * // Button with icon (string URL)
59
+ * <Button icon="https://example.com/icon.svg" iconPlacement="before">button</Button>
60
+ *
61
+ * @example
62
+ * // Button with icon (ReactNode)
63
+ * <Button icon={<CustomIcon />} iconPlacement="after">button</Button>
55
64
  *
56
65
  * @example
57
- * // Icon-only button
58
- * <Button variant="icon" iconBordered><Icon /></Button>
66
+ * // Icon variant button (square, no padding)
67
+ * <Button variant="icon" icon={<CustomIcon />} iconBordered />
68
+ *
69
+ * @example
70
+ * // Icon variant button without border
71
+ * <Button variant="icon" icon={<CustomIcon />} />
59
72
  */
60
73
  declare const Button: React.FC<ButtonProps>;
61
74
 
@@ -331,8 +344,13 @@ interface SliderProps {
331
344
  */
332
345
  declare const Slider: React.FC<SliderProps>;
333
346
 
334
- type InputSize = 'small' | 'medium' | 'large' | 'extraLarge';
347
+ type InputSize = 'mini' | 'small' | 'medium' | 'large';
348
+ type LineType = 'outlined' | 'underlined';
335
349
  interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size' | 'prefix'> {
350
+ /**
351
+ * Input line type
352
+ */
353
+ lineType?: LineType;
336
354
  /**
337
355
  * Input size
338
356
  */
@@ -353,6 +371,18 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, '
353
371
  * Node to display after the input
354
372
  */
355
373
  suffixNode?: React.ReactNode;
374
+ /**
375
+ * Whether to show clear button when input has value
376
+ */
377
+ clearable?: boolean;
378
+ /**
379
+ * Clear button click handler
380
+ */
381
+ onClear?: () => void;
382
+ /**
383
+ * Custom clear icon
384
+ */
385
+ clearIcon?: React.ReactNode;
356
386
  /**
357
387
  * Custom className
358
388
  */
@@ -366,12 +396,20 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, '
366
396
  * Input Component
367
397
  *
368
398
  * @example
369
- * // Basic input
399
+ * // Basic outlined input (default)
370
400
  * <Input placeholder="Enter text" />
371
401
  *
372
402
  * @example
403
+ * // Underlined input
404
+ * <Input lineType="underlined" placeholder="Enter text" />
405
+ *
406
+ * @example
373
407
  * // Input with prefix and suffix
374
- * <Input prefixNode={<SearchIcon />} suffixNode={<CloseIcon />} />
408
+ * <Input prefixNode={<SearchIcon />} suffixNode={<Icon />} />
409
+ *
410
+ * @example
411
+ * // Input with clearable
412
+ * <Input clearable onClear={() => console.log('cleared')} />
375
413
  *
376
414
  * @example
377
415
  * // Input with error state
@@ -379,11 +417,15 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, '
379
417
  */
380
418
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
381
419
 
382
- interface SearchInputProps extends Omit<InputProps, 'size' | 'prefixNode'> {
420
+ interface SearchInputProps extends Omit<InputProps, 'prefixNode' | 'suffixNode'> {
421
+ /**
422
+ * Line type (outlined or underlined)
423
+ */
424
+ lineType?: 'outlined' | 'underlined';
383
425
  /**
384
- * SearchInput size (only medium and large)
426
+ * SearchInput size
385
427
  */
386
- size?: 'extraLarge' | 'large';
428
+ size?: 'mini' | 'small' | 'medium' | 'large';
387
429
  /**
388
430
  * Whether to show the clear button when input has value
389
431
  */
@@ -393,27 +435,52 @@ interface SearchInputProps extends Omit<InputProps, 'size' | 'prefixNode'> {
393
435
  */
394
436
  onClear?: () => void;
395
437
  /**
396
- * Custom search icon
438
+ * Custom search icon (URL string or React node)
397
439
  */
398
- searchIcon?: React.ReactNode;
440
+ searchIcon?: string | React.ReactNode;
399
441
  }
400
442
  /**
401
443
  * SearchInput Component
402
444
  *
445
+ * A wrapper around Input component with search icon and clear functionality
446
+ *
403
447
  * @example
404
448
  * // Basic search input
405
449
  * <SearchInput placeholder="Search..." />
406
450
  *
407
451
  * @example
408
- * // Search input with clearable
409
- * <SearchInput clearable onClear={() => console.log('cleared')} />
452
+ * // Underlined search input
453
+ * <SearchInput lineType="underlined" placeholder="Search..." />
454
+ *
455
+ * @example
456
+ * // Search input without clearable
457
+ * <SearchInput clearable={false} placeholder="Search..." />
410
458
  *
411
459
  * @example
412
- * // Large search input
460
+ * // Different sizes
461
+ * <SearchInput size="small" placeholder="Search..." />
462
+ * <SearchInput size="medium" placeholder="Search..." />
413
463
  * <SearchInput size="large" placeholder="Search..." />
414
464
  */
415
465
  declare const SearchInput: React.ForwardRefExoticComponent<SearchInputProps & React.RefAttributes<HTMLInputElement>>;
416
466
 
467
+ /**
468
+ * UnderlinedInput Component
469
+ *
470
+ * @deprecated Use <Input lineType="underlined" /> instead
471
+ *
472
+ * This component is a simple alias for Input with lineType="underlined"
473
+ * and will be removed in a future version.
474
+ *
475
+ * @example
476
+ * // Old way (deprecated)
477
+ * <UnderlinedInput placeholder="Search..." />
478
+ *
479
+ * // New way (recommended)
480
+ * <Input lineType="underlined" placeholder="Search..." />
481
+ */
482
+ declare const UnderlinedInput: React.ForwardRefExoticComponent<Omit<InputProps, "lineType"> & React.RefAttributes<HTMLInputElement>>;
483
+
417
484
  interface NumberInputProps {
418
485
  /**
419
486
  * Current value
@@ -586,17 +653,29 @@ interface ToastProps {
586
653
  */
587
654
  variant?: 'success' | 'info' | 'error' | 'warn';
588
655
  /**
589
- * Toast message content
656
+ * Toast message content (main text)
590
657
  */
591
658
  message: string;
592
659
  /**
593
- * Optional action button text
660
+ * Optional description text (shows below message in multiline mode)
661
+ */
662
+ description?: string;
663
+ /**
664
+ * Main action button text (blue color)
594
665
  */
595
- actionText?: string;
666
+ mainButtonText?: string;
596
667
  /**
597
- * Action button click handler
668
+ * Main action button click handler
598
669
  */
599
- onAction?: () => void;
670
+ onMainButtonClick?: () => void;
671
+ /**
672
+ * Secondary action button text (gray color)
673
+ */
674
+ secondaryButtonText?: string;
675
+ /**
676
+ * Secondary action button click handler
677
+ */
678
+ onSecondaryButtonClick?: () => void;
600
679
  /**
601
680
  * Whether to show close button
602
681
  */
@@ -632,14 +711,28 @@ interface ToastProps {
632
711
  * A notification message component with different variants
633
712
  *
634
713
  * @example
635
- * <Toast variant="success" message="Operation successful!" />
714
+ * // Single line toast
715
+ * <Toast variant="success" message="信息反馈" />
636
716
  *
637
717
  * @example
718
+ * // Toast with buttons
638
719
  * <Toast
639
720
  * variant="info"
640
- * message="New update available"
641
- * actionText="Update"
642
- * onAction={() => console.log('Update clicked')}
721
+ * message="信息反馈"
722
+ * mainButtonText="按钮名称"
723
+ * onMainButtonClick={() => console.log('Main clicked')}
724
+ * secondaryButtonText="按钮名称"
725
+ * onSecondaryButtonClick={() => console.log('Secondary clicked')}
726
+ * closable
727
+ * />
728
+ *
729
+ * @example
730
+ * // Multi-line toast with description
731
+ * <Toast
732
+ * variant="success"
733
+ * message="信息反馈"
734
+ * description="信息具体说明"
735
+ * mainButtonText="按钮名称"
643
736
  * closable
644
737
  * />
645
738
  */
@@ -654,6 +747,7 @@ interface ToastContextValue {
654
747
  warn: (message: string, options?: Partial<ToastProps>) => string;
655
748
  }
656
749
  interface ToastContainerProps {
750
+ placement?: 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center';
657
751
  /**
658
752
  * Maximum number of toasts to show at once
659
753
  */
@@ -688,6 +782,48 @@ declare const ToastContainer: React.FC<ToastContainerProps>;
688
782
  */
689
783
  declare const useToast: () => ToastContextValue;
690
784
 
785
+ type ToastPlacement = 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left' | 'bottom-center';
786
+ interface ToastContainerConfig {
787
+ placement?: ToastPlacement;
788
+ maxCount?: number;
789
+ defaultDuration?: number;
790
+ }
791
+ /**
792
+ * Global toast object that can be used anywhere
793
+ * No need to render ToastContainer component manually
794
+ *
795
+ * @example
796
+ * import { toast } from '@officesdk/design';
797
+ *
798
+ * // Configure (optional)
799
+ * toast.configure({
800
+ * placement: 'top-right',
801
+ * maxCount: 5,
802
+ * defaultDuration: 3000,
803
+ * });
804
+ *
805
+ * // Show toasts
806
+ * toast.success('Operation successful!');
807
+ * toast.error('Something went wrong');
808
+ * toast.info('Info message', { duration: 5000 });
809
+ * toast.warn('Warning message');
810
+ *
811
+ * const id = toast.show({ variant: 'info', message: 'Custom toast' });
812
+ * toast.hide(id);
813
+ * toast.hideAll();
814
+ */
815
+ declare const toast: {
816
+ configure: (config: ToastContainerConfig) => void;
817
+ show: (props: Omit<ToastProps, "onClose">) => string;
818
+ hide: (id: string) => void;
819
+ hideAll: () => void;
820
+ success: (message: string, options?: Partial<ToastProps>) => string;
821
+ info: (message: string, options?: Partial<ToastProps>) => string;
822
+ error: (message: string, options?: Partial<ToastProps>) => string;
823
+ warn: (message: string, options?: Partial<ToastProps>) => string;
824
+ destroy: () => void;
825
+ };
826
+
691
827
  interface TabItem {
692
828
  /**
693
829
  * Unique key for the tab
@@ -873,6 +1009,276 @@ interface ToolbarButtonProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
873
1009
  */
874
1010
  declare const ToolbarButton: React.FC<ToolbarButtonProps>;
875
1011
 
1012
+ type DropdownButtonSize = 'large' | 'medium';
1013
+ type DropdownButtonVariant = 'framed' | 'frameless';
1014
+ interface DropdownButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {
1015
+ /**
1016
+ * Button variant
1017
+ * - framed: with border (40px large)
1018
+ * - frameless: without border (28px medium)
1019
+ */
1020
+ variant?: DropdownButtonVariant;
1021
+ /**
1022
+ * Button size
1023
+ */
1024
+ size?: DropdownButtonSize;
1025
+ /**
1026
+ * Display value/label
1027
+ */
1028
+ value?: string;
1029
+ /**
1030
+ * Placeholder when no value
1031
+ */
1032
+ placeholder?: string;
1033
+ /**
1034
+ * Optional icon (URL string or ReactNode)
1035
+ */
1036
+ icon?: string | React.ReactNode;
1037
+ /**
1038
+ * Custom indicator/arrow icon
1039
+ */
1040
+ indicatorIcon?: React.ReactNode;
1041
+ /**
1042
+ * Whether the dropdown is open (controls arrow rotation)
1043
+ */
1044
+ open?: boolean;
1045
+ /**
1046
+ * Whether the button is disabled
1047
+ */
1048
+ disabled?: boolean;
1049
+ /**
1050
+ * Error state
1051
+ */
1052
+ error?: boolean;
1053
+ /**
1054
+ * Custom className
1055
+ */
1056
+ className?: string;
1057
+ /**
1058
+ * Custom style
1059
+ */
1060
+ style?: React.CSSProperties;
1061
+ /**
1062
+ * Custom text style
1063
+ */
1064
+ textStyle?: React.CSSProperties;
1065
+ }
1066
+ /**
1067
+ * DropdownButton Component
1068
+ *
1069
+ * A button component for triggering dropdown menus
1070
+ *
1071
+ * @example
1072
+ * // Framed dropdown button (with border, 40px)
1073
+ * <DropdownButton variant="framed" value="Option 1" />
1074
+ *
1075
+ * @example
1076
+ * // Frameless dropdown button (no border, 28px)
1077
+ * <DropdownButton variant="frameless" value="Option 1" />
1078
+ *
1079
+ * @example
1080
+ * // With icon
1081
+ * <DropdownButton icon={<CustomIcon />} value="Option 1" />
1082
+ *
1083
+ * @example
1084
+ * // Open state (arrow rotated)
1085
+ * <DropdownButton open value="Option 1" />
1086
+ */
1087
+ declare const DropdownButton: React.ForwardRefExoticComponent<DropdownButtonProps & React.RefAttributes<HTMLButtonElement>>;
1088
+
1089
+ interface MenuItem {
1090
+ type?: 'item';
1091
+ key: string;
1092
+ label: string;
1093
+ description?: string;
1094
+ icon?: string | React.ReactNode;
1095
+ disabled?: boolean;
1096
+ selected?: boolean;
1097
+ selectable?: boolean;
1098
+ children?: MenuItem[];
1099
+ onClick?: (key: string) => void;
1100
+ }
1101
+ interface MenuGroup {
1102
+ type: 'group';
1103
+ key: string;
1104
+ label: string;
1105
+ children: MenuItem[];
1106
+ }
1107
+ interface MenuDivider {
1108
+ type: 'divider';
1109
+ key: string;
1110
+ }
1111
+ type MenuItemType = MenuItem | MenuGroup | MenuDivider;
1112
+ interface MenuProps {
1113
+ /**
1114
+ * Menu items
1115
+ */
1116
+ items: MenuItemType[];
1117
+ /**
1118
+ * Currently selected key(s)
1119
+ */
1120
+ selectedKeys?: string[];
1121
+ /**
1122
+ * Open submenu keys (controlled)
1123
+ */
1124
+ openKeys?: string[];
1125
+ /**
1126
+ * Menu size
1127
+ */
1128
+ size?: 'medium' | 'large';
1129
+ /**
1130
+ * Whether to show search box
1131
+ */
1132
+ searchable?: boolean;
1133
+ /**
1134
+ * Search placeholder
1135
+ */
1136
+ searchPlaceholder?: string;
1137
+ /**
1138
+ * Max height for scrolling
1139
+ */
1140
+ maxHeight?: number;
1141
+ /**
1142
+ * Enable virtual scrolling
1143
+ */
1144
+ virtual?: boolean;
1145
+ /**
1146
+ * Whether to always reserve space for active icon (for description alignment)
1147
+ */
1148
+ reserveActiveIconSpace?: boolean;
1149
+ /**
1150
+ * Select handler
1151
+ */
1152
+ onSelect?: (key: string) => void;
1153
+ /**
1154
+ * Search handler
1155
+ */
1156
+ onSearch?: (value: string) => void;
1157
+ /**
1158
+ * Open keys change handler
1159
+ */
1160
+ onOpenChange?: (keys: string[]) => void;
1161
+ /**
1162
+ * Custom className
1163
+ */
1164
+ className?: string;
1165
+ /**
1166
+ * Custom style
1167
+ */
1168
+ style?: React.CSSProperties;
1169
+ }
1170
+ /**
1171
+ * Menu Component
1172
+ *
1173
+ * A menu component based on rc-menu with virtual scrolling support
1174
+ *
1175
+ * @example
1176
+ * // Basic menu
1177
+ * <Menu
1178
+ * items={[
1179
+ * { key: '1', label: 'Option 1' },
1180
+ * { key: '2', label: 'Option 2' },
1181
+ * ]}
1182
+ * onSelect={(key) => console.log(key)}
1183
+ * />
1184
+ *
1185
+ * @example
1186
+ * // Menu with groups and dividers
1187
+ * <Menu
1188
+ * items={[
1189
+ * { type: 'group', key: 'g1', label: 'Group A', children: [...] },
1190
+ * { type: 'divider', key: 'd1' },
1191
+ * { key: '1', label: 'Option 1' },
1192
+ * ]}
1193
+ * />
1194
+ *
1195
+ * @example
1196
+ * // Menu with search
1197
+ * <Menu
1198
+ * searchable
1199
+ * items={items}
1200
+ * onSearch={(value) => console.log(value)}
1201
+ * />
1202
+ */
1203
+ declare const Menu: React.FC<MenuProps>;
1204
+
1205
+ interface DropdownProps extends Omit<Partial<DropdownProps$1>, 'prefixCls' | 'placement'> {
1206
+ /**
1207
+ * Dropdown overlay content (usually a Menu component)
1208
+ */
1209
+ overlay?: React.ReactElement | (() => React.ReactElement);
1210
+ /**
1211
+ * Trigger action (click, hover, contextMenu)
1212
+ */
1213
+ trigger?: ('click' | 'hover' | 'contextMenu')[];
1214
+ /**
1215
+ * Placement of dropdown
1216
+ */
1217
+ placement?: 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight';
1218
+ /**
1219
+ * Whether dropdown is visible (controlled)
1220
+ */
1221
+ visible?: boolean;
1222
+ /**
1223
+ * Default visibility (uncontrolled)
1224
+ */
1225
+ defaultVisible?: boolean;
1226
+ /**
1227
+ * Callback when visibility changes
1228
+ */
1229
+ onVisibleChange?: (visible: boolean) => void;
1230
+ /**
1231
+ * Children element that triggers the dropdown
1232
+ */
1233
+ children: React.ReactElement;
1234
+ /**
1235
+ * Dropdown container class name
1236
+ */
1237
+ overlayClassName?: string;
1238
+ /**
1239
+ * Function to get the container element for the dropdown
1240
+ */
1241
+ getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
1242
+ }
1243
+ /**
1244
+ * Dropdown Component
1245
+ *
1246
+ * A dropdown container component based on rc-dropdown
1247
+ *
1248
+ * @example
1249
+ * // Basic dropdown with menu
1250
+ * <Dropdown
1251
+ * overlay={<Menu items={items} />}
1252
+ * trigger={['click']}
1253
+ * >
1254
+ * <DropdownButton value="Select" />
1255
+ * </Dropdown>
1256
+ *
1257
+ * @example
1258
+ * // Controlled dropdown
1259
+ * <Dropdown
1260
+ * visible={open}
1261
+ * onVisibleChange={setOpen}
1262
+ * overlay={<Menu items={items} />}
1263
+ * >
1264
+ * <Button>Click me</Button>
1265
+ * </Dropdown>
1266
+ *
1267
+ * @example
1268
+ * // Custom trigger
1269
+ * <Dropdown
1270
+ * overlay={<Menu items={items} />}
1271
+ * trigger={['hover']}
1272
+ * placement="bottomLeft"
1273
+ * >
1274
+ * <span>Hover me</span>
1275
+ * </Dropdown>
1276
+ */
1277
+ declare const Dropdown: React.FC<DropdownProps>;
1278
+
1279
+ declare const DropdownGlobalStyles: styled_components.GlobalStyleComponent<{}, styled_components.DefaultTheme>;
1280
+ declare const MenuGlobalStyles: styled_components.GlobalStyleComponent<{}, styled_components.DefaultTheme>;
1281
+
876
1282
  type ToastPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center';
877
1283
  interface ToastConfig {
878
1284
  /**
@@ -1067,4 +1473,4 @@ declare const styled: ThemedStyledInterface<Theme>;
1067
1473
 
1068
1474
  declare const getGlobalTheme: () => Theme;
1069
1475
 
1070
- export { type A11yConfig, type AnimationConfig, Button, type ButtonProps, Checkbox, type CheckboxProps, type I18nConfig, Icon, type IconComponent, type IconProps, IconProvider, type IconProviderProps, type IconRegistry, Input, type InputProps, NumberInput, type NumberInputProps, Radio, type RadioProps, SearchInput, type SearchInputProps, Slider, type SliderProps, SpinButton, type SpinButtonProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Toast, type ToastConfig, ToastContainer, type ToastContainerProps, type ToastPosition, type ToastProps, ToolbarButton, type ToolbarButtonProps, Tooltip, type TooltipProps, type UIConfig, UIConfigProvider, type UIConfigProviderProps, type ZIndexConfig, createUIConfig, getGlobalTheme, mergeUIConfig, styled, useIconRegistry, useToast, useUIConfig };
1476
+ export { type A11yConfig, type AnimationConfig, Button, type ButtonProps, Checkbox, type CheckboxProps, Dropdown, DropdownButton, type DropdownButtonProps, DropdownGlobalStyles, type DropdownProps, type I18nConfig, Icon, type IconComponent, type IconProps, IconProvider, type IconProviderProps, type IconRegistry, Input, type InputProps, Menu, type MenuDivider, MenuGlobalStyles, type MenuGroup, type MenuItem, type MenuItemType, type MenuProps, NumberInput, type NumberInputProps, Radio, type RadioProps, SearchInput, type SearchInputProps, Slider, type SliderProps, SpinButton, type SpinButtonProps, Switch, type SwitchProps, type TabItem, Tabs, type TabsProps, Toast, type ToastConfig, ToastContainer, type ToastContainerConfig, type ToastContainerProps, type ToastPosition, type ToastProps, ToolbarButton, type ToolbarButtonProps, Tooltip, type TooltipProps, type UIConfig, UIConfigProvider, type UIConfigProviderProps, UnderlinedInput, type InputProps as UnderlinedInputProps, type ZIndexConfig, createUIConfig, getGlobalTheme, mergeUIConfig, styled, toast, useIconRegistry, useToast, useUIConfig };