@rovula/ui 0.1.20 → 0.1.22
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/dist/cjs/bundle.css +316 -43
- package/dist/cjs/bundle.js +675 -675
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Badge/Badge.d.ts +40 -0
- package/dist/cjs/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/cjs/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/cjs/types/components/Badge/index.d.ts +2 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/cjs/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/cjs/types/components/Form/Form.d.ts +2 -1
- package/dist/cjs/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/cjs/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/cjs/types/index.d.ts +4 -1
- package/dist/cjs/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/cjs/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/cjs/types/utils/mergeRefs.d.ts +20 -0
- package/dist/components/Avatar/Avatar.styles.js +2 -2
- package/dist/components/Badge/Badge.js +36 -0
- package/dist/components/Badge/Badge.stories.js +51 -0
- package/dist/components/Badge/Badge.styles.js +62 -0
- package/dist/components/Badge/index.js +2 -0
- package/dist/components/Dropdown/Dropdown.js +54 -163
- package/dist/components/Dropdown/Dropdown.stories.js +29 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +24 -13
- package/dist/components/DropdownMenu/DropdownMenu.stories.js +120 -88
- package/dist/components/Form/Form.js +11 -4
- package/dist/components/Form/Form.stories.js +27 -0
- package/dist/components/ScrollArea/ScrollArea.js +50 -0
- package/dist/components/ScrollArea/ScrollArea.stories.js +56 -0
- package/dist/components/TextInput/TextInput.js +6 -3
- package/dist/esm/bundle.css +316 -43
- package/dist/esm/bundle.js +1545 -1545
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Badge/Badge.d.ts +40 -0
- package/dist/esm/types/components/Badge/Badge.stories.d.ts +295 -0
- package/dist/esm/types/components/Badge/Badge.styles.d.ts +7 -0
- package/dist/esm/types/components/Badge/index.d.ts +2 -0
- package/dist/esm/types/components/Dropdown/Dropdown.d.ts +4 -8
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
- package/dist/esm/types/components/DropdownMenu/DropdownMenu.stories.d.ts +45 -30
- package/dist/esm/types/components/Form/Form.d.ts +2 -1
- package/dist/esm/types/components/Form/Form.stories.d.ts +4 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.d.ts +38 -0
- package/dist/esm/types/components/ScrollArea/ScrollArea.stories.d.ts +301 -0
- package/dist/esm/types/index.d.ts +4 -1
- package/dist/esm/types/patterns/menu/Menu.d.ts +70 -0
- package/dist/esm/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +17 -10
- package/dist/esm/types/utils/mergeRefs.d.ts +20 -0
- package/dist/index.d.ts +156 -74
- package/dist/index.js +3 -1
- package/dist/patterns/menu/Menu.js +95 -0
- package/dist/patterns/menu/Menu.stories.js +611 -0
- package/dist/src/theme/global.css +485 -57
- package/dist/utils/mergeRefs.js +42 -0
- package/package.json +1 -1
- package/src/components/Avatar/Avatar.styles.ts +2 -2
- package/src/components/Badge/Badge.stories.tsx +128 -0
- package/src/components/Badge/Badge.styles.ts +70 -0
- package/src/components/Badge/Badge.tsx +103 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +170 -1
- package/src/components/Dropdown/Dropdown.tsx +186 -276
- package/src/components/DropdownMenu/DropdownMenu.stories.tsx +1375 -253
- package/src/components/DropdownMenu/DropdownMenu.tsx +118 -55
- package/src/components/Form/Form.stories.tsx +70 -0
- package/src/components/Form/Form.tsx +23 -0
- package/src/components/ScrollArea/ScrollArea.stories.tsx +229 -0
- package/src/components/ScrollArea/ScrollArea.tsx +72 -0
- package/src/components/TextInput/TextInput.tsx +6 -3
- package/src/index.ts +4 -1
- package/src/patterns/menu/Menu.stories.tsx +1100 -0
- package/src/patterns/menu/Menu.tsx +282 -0
- package/src/theme/global.css +84 -11
- package/src/theme/themes/xspector/baseline.css +1 -1
- package/src/theme/themes/xspector/components/scrollbar.css +12 -0
- package/src/theme/tokens/baseline.css +3 -1
- package/src/theme/tokens/components/badge.css +54 -0
- package/src/theme/tokens/components/dropdown-menu.css +16 -5
- package/src/theme/tokens/components/scrollbar.css +18 -0
- package/src/utils/mergeRefs.ts +46 -0
- package/dist/cjs/types/components/Menu/Menu.d.ts +0 -65
- package/dist/cjs/types/components/Menu/helpers.d.ts +0 -19
- package/dist/cjs/types/components/Menu/index.d.ts +0 -4
- package/dist/components/Menu/Menu.js +0 -64
- package/dist/components/Menu/Menu.stories.js +0 -406
- package/dist/components/Menu/helpers.js +0 -28
- package/dist/components/Menu/index.js +0 -3
- package/dist/esm/types/components/Menu/Menu.d.ts +0 -65
- package/dist/esm/types/components/Menu/helpers.d.ts +0 -19
- package/dist/esm/types/components/Menu/index.d.ts +0 -4
- package/src/components/Menu/Menu.stories.tsx +0 -586
- package/src/components/Menu/Menu.tsx +0 -235
- package/src/components/Menu/helpers.ts +0 -45
- package/src/components/Menu/index.ts +0 -7
- package/src/theme/themes/xspector/components/dropdown-menu.css +0 -28
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import React__default, { ReactElement, ReactNode,
|
|
2
|
+
import React__default, { ReactElement, ReactNode, FC, ComponentPropsWithoutRef, CSSProperties, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
|
|
3
3
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
4
4
|
import * as class_variance_authority_dist_types from 'class-variance-authority/dist/types';
|
|
5
5
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
@@ -17,7 +17,7 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
|
17
17
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
18
18
|
import { ToastProviderProps } from '@radix-ui/react-toast';
|
|
19
19
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
20
|
-
import { FieldValues, UseFormReturn, DefaultValues, SubmitHandler, SubmitErrorHandler, Resolver, Mode, FieldPath, RegisterOptions, FieldPathValue } from 'react-hook-form';
|
|
20
|
+
import { FieldValues, UseFormReturn, DefaultValues, SubmitHandler, SubmitErrorHandler, FormState, Resolver, Mode, FieldPath, RegisterOptions, FieldPathValue } from 'react-hook-form';
|
|
21
21
|
import * as yup from 'yup';
|
|
22
22
|
import Button$1 from '@/components/Button/Button';
|
|
23
23
|
import { ClassValue } from 'clsx';
|
|
@@ -376,70 +376,6 @@ type TabsProps = {
|
|
|
376
376
|
};
|
|
377
377
|
declare const Tabs: React__default.FC<TabsProps>;
|
|
378
378
|
|
|
379
|
-
type MenuOption = {
|
|
380
|
-
value: string;
|
|
381
|
-
label: ReactNode;
|
|
382
|
-
/**
|
|
383
|
-
* Visual type - กำหนดว่าจะแสดง icon อะไร
|
|
384
|
-
* - "default": ไม่มี icon (แค่ highlight background)
|
|
385
|
-
* - "checkbox": แสดง ✓ icon
|
|
386
|
-
* - "radio": แสดง ● icon
|
|
387
|
-
*/
|
|
388
|
-
type?: "default" | "checkbox" | "radio";
|
|
389
|
-
icon?: ReactNode;
|
|
390
|
-
disabled?: boolean;
|
|
391
|
-
danger?: boolean;
|
|
392
|
-
checked?: boolean;
|
|
393
|
-
onClick?: () => void;
|
|
394
|
-
};
|
|
395
|
-
type MenuItemType = {
|
|
396
|
-
type: "item";
|
|
397
|
-
item: MenuOption;
|
|
398
|
-
} | {
|
|
399
|
-
type: "separator";
|
|
400
|
-
} | {
|
|
401
|
-
type: "label";
|
|
402
|
-
label: string;
|
|
403
|
-
} | {
|
|
404
|
-
type: "custom";
|
|
405
|
-
render: () => ReactNode;
|
|
406
|
-
};
|
|
407
|
-
type MenuProps = {
|
|
408
|
-
items: MenuItemType[];
|
|
409
|
-
/**
|
|
410
|
-
* Selected values - ใช้กับ type="item"
|
|
411
|
-
*/
|
|
412
|
-
selectedValues?: string[];
|
|
413
|
-
/**
|
|
414
|
-
* Callback เมื่อเลือก item
|
|
415
|
-
* - ถ้า item.type="checkbox" → toggle checked state
|
|
416
|
-
* - ถ้า item.type="radio" → single select (clear others)
|
|
417
|
-
* - ถ้า item.type="default" หรือไม่ระบุ → ตาม selectedValues
|
|
418
|
-
*/
|
|
419
|
-
onSelect?: (value: string, item: MenuOption) => void;
|
|
420
|
-
className?: string;
|
|
421
|
-
style?: CSSProperties;
|
|
422
|
-
isAbove?: boolean;
|
|
423
|
-
};
|
|
424
|
-
declare const Menu: React__default.ForwardRefExoticComponent<MenuProps & React__default.RefAttributes<HTMLDivElement>>;
|
|
425
|
-
type MenuItemProps = {
|
|
426
|
-
option: MenuOption;
|
|
427
|
-
visualType: "default" | "checkbox" | "radio";
|
|
428
|
-
isChecked: boolean;
|
|
429
|
-
onSelect: () => void;
|
|
430
|
-
className?: string;
|
|
431
|
-
};
|
|
432
|
-
declare const MenuItem: React__default.ForwardRefExoticComponent<MenuItemProps & React__default.RefAttributes<HTMLDivElement>>;
|
|
433
|
-
type MenuSeparatorProps = {
|
|
434
|
-
className?: string;
|
|
435
|
-
};
|
|
436
|
-
declare const MenuSeparator: React__default.ForwardRefExoticComponent<MenuSeparatorProps & React__default.RefAttributes<HTMLDivElement>>;
|
|
437
|
-
type MenuLabelProps = {
|
|
438
|
-
children: ReactNode;
|
|
439
|
-
className?: string;
|
|
440
|
-
};
|
|
441
|
-
declare const MenuLabel: React__default.ForwardRefExoticComponent<MenuLabelProps & React__default.RefAttributes<HTMLDivElement>>;
|
|
442
|
-
|
|
443
379
|
type RenderLabelCallbackArg$1 = {
|
|
444
380
|
value: string;
|
|
445
381
|
label: string;
|
|
@@ -457,7 +393,6 @@ type DropdownProps = {
|
|
|
457
393
|
size?: "sm" | "md" | "lg";
|
|
458
394
|
rounded?: "none" | "normal" | "full";
|
|
459
395
|
variant?: "flat" | "outline" | "underline";
|
|
460
|
-
defaultMenuItemType?: MenuOption["type"];
|
|
461
396
|
helperText?: string;
|
|
462
397
|
errorMessage?: string;
|
|
463
398
|
filterMode?: boolean;
|
|
@@ -465,6 +400,7 @@ type DropdownProps = {
|
|
|
465
400
|
disabled?: boolean;
|
|
466
401
|
error?: boolean;
|
|
467
402
|
required?: boolean;
|
|
403
|
+
/** @deprecated no longer needed */
|
|
468
404
|
modal?: boolean;
|
|
469
405
|
className?: string;
|
|
470
406
|
optionContainerClassName?: string;
|
|
@@ -479,8 +415,6 @@ type DropdownProps = {
|
|
|
479
415
|
optionsFiltered: Options$1[];
|
|
480
416
|
selectedOption: Options$1 | null | undefined;
|
|
481
417
|
onClick: (option: Options$1) => void;
|
|
482
|
-
style?: CSSProperties;
|
|
483
|
-
dropdownRef?: React__default.RefObject<HTMLUListElement>;
|
|
484
418
|
}) => ReactNode;
|
|
485
419
|
} & Omit<InputProps, "value" | "onSelect">;
|
|
486
420
|
declare const Dropdown: React__default.ForwardRefExoticComponent<{
|
|
@@ -489,7 +423,6 @@ declare const Dropdown: React__default.ForwardRefExoticComponent<{
|
|
|
489
423
|
size?: "sm" | "md" | "lg";
|
|
490
424
|
rounded?: "none" | "normal" | "full";
|
|
491
425
|
variant?: "flat" | "outline" | "underline";
|
|
492
|
-
defaultMenuItemType?: MenuOption["type"];
|
|
493
426
|
helperText?: string;
|
|
494
427
|
errorMessage?: string;
|
|
495
428
|
filterMode?: boolean;
|
|
@@ -497,6 +430,7 @@ declare const Dropdown: React__default.ForwardRefExoticComponent<{
|
|
|
497
430
|
disabled?: boolean;
|
|
498
431
|
error?: boolean;
|
|
499
432
|
required?: boolean;
|
|
433
|
+
/** @deprecated no longer needed */
|
|
500
434
|
modal?: boolean;
|
|
501
435
|
className?: string;
|
|
502
436
|
optionContainerClassName?: string;
|
|
@@ -511,8 +445,6 @@ declare const Dropdown: React__default.ForwardRefExoticComponent<{
|
|
|
511
445
|
optionsFiltered: Options$1[];
|
|
512
446
|
selectedOption: Options$1 | null | undefined;
|
|
513
447
|
onClick: (option: Options$1) => void;
|
|
514
|
-
style?: CSSProperties;
|
|
515
|
-
dropdownRef?: React__default.RefObject<HTMLUListElement>;
|
|
516
448
|
}) => ReactNode;
|
|
517
449
|
} & Omit<InputProps, "onSelect" | "value"> & React__default.RefAttributes<HTMLInputElement>>;
|
|
518
450
|
|
|
@@ -626,6 +558,45 @@ type AvatarGroupProps = {
|
|
|
626
558
|
};
|
|
627
559
|
declare const AvatarGroup: FC<AvatarGroupProps>;
|
|
628
560
|
|
|
561
|
+
type BadgeColor = "default" | "success" | "warning" | "info" | "error";
|
|
562
|
+
type BadgeProps = {
|
|
563
|
+
/** Badge text label */
|
|
564
|
+
label: string;
|
|
565
|
+
/** Color variant */
|
|
566
|
+
color?: BadgeColor;
|
|
567
|
+
/**
|
|
568
|
+
* Show a dropdown chevron — use when the badge acts as a clickable trigger.
|
|
569
|
+
* Automatically adds a border to indicate interactivity.
|
|
570
|
+
*/
|
|
571
|
+
clickable?: boolean;
|
|
572
|
+
/** Optional percentage value shown below the label */
|
|
573
|
+
percent?: number;
|
|
574
|
+
className?: string;
|
|
575
|
+
} & React.HTMLAttributes<HTMLSpanElement>;
|
|
576
|
+
declare const Badge: React.ForwardRefExoticComponent<{
|
|
577
|
+
/** Badge text label */
|
|
578
|
+
label: string;
|
|
579
|
+
/** Color variant */
|
|
580
|
+
color?: BadgeColor;
|
|
581
|
+
/**
|
|
582
|
+
* Show a dropdown chevron — use when the badge acts as a clickable trigger.
|
|
583
|
+
* Automatically adds a border to indicate interactivity.
|
|
584
|
+
*/
|
|
585
|
+
clickable?: boolean;
|
|
586
|
+
/** Optional percentage value shown below the label */
|
|
587
|
+
percent?: number;
|
|
588
|
+
className?: string;
|
|
589
|
+
} & React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
|
|
590
|
+
type SeverityLevel = "highest" | "high" | "medium" | "low" | "lowest";
|
|
591
|
+
type SeverityBadgeProps = {
|
|
592
|
+
severity: SeverityLevel;
|
|
593
|
+
className?: string;
|
|
594
|
+
} & React.HTMLAttributes<HTMLSpanElement>;
|
|
595
|
+
declare const SeverityBadge: React.ForwardRefExoticComponent<{
|
|
596
|
+
severity: SeverityLevel;
|
|
597
|
+
className?: string;
|
|
598
|
+
} & React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
|
|
599
|
+
|
|
629
600
|
declare const CollapsibleButton: React__default.ForwardRefExoticComponent<{
|
|
630
601
|
children: React__default.ReactNode;
|
|
631
602
|
className?: string;
|
|
@@ -942,9 +913,13 @@ declare const DropdownMenuSubContent: React.ForwardRefExoticComponent<Omit<Dropd
|
|
|
942
913
|
declare const DropdownMenuContent: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
943
914
|
declare const DropdownMenuItem: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
944
915
|
inset?: boolean;
|
|
916
|
+
selected?: boolean;
|
|
917
|
+
icon?: React.ReactNode;
|
|
945
918
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
946
919
|
declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
947
|
-
declare const DropdownMenuRadioItem: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> &
|
|
920
|
+
declare const DropdownMenuRadioItem: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
921
|
+
icon?: React.ReactNode;
|
|
922
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
948
923
|
declare const DropdownMenuLabel: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
949
924
|
inset?: boolean;
|
|
950
925
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -1166,6 +1141,44 @@ type FocusedScrollViewProps = {
|
|
|
1166
1141
|
};
|
|
1167
1142
|
declare const FocusedScrollView: React__default.FC<FocusedScrollViewProps>;
|
|
1168
1143
|
|
|
1144
|
+
type ScrollbarSize = "m" | "s" | "xs";
|
|
1145
|
+
interface ScrollAreaProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
1146
|
+
/**
|
|
1147
|
+
* Scrollbar thickness.
|
|
1148
|
+
* - `m` — 12 px (shows track border)
|
|
1149
|
+
* - `s` — 6 px (default, shows no track border)
|
|
1150
|
+
* - `xs` — 2 px (shows no track border)
|
|
1151
|
+
*/
|
|
1152
|
+
scrollbarSize?: ScrollbarSize;
|
|
1153
|
+
/**
|
|
1154
|
+
* Direction(s) the area can scroll.
|
|
1155
|
+
* Defaults to `"vertical"`.
|
|
1156
|
+
*/
|
|
1157
|
+
direction?: "vertical" | "horizontal" | "both";
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* ScrollArea
|
|
1161
|
+
*
|
|
1162
|
+
* A thin wrapper that applies the design-system scrollbar style to any
|
|
1163
|
+
* scrollable container. Use `scrollbarSize` to pick the Figma size variant
|
|
1164
|
+
* and `direction` to control which axis scrolls.
|
|
1165
|
+
*
|
|
1166
|
+
* **Client usage:**
|
|
1167
|
+
* ```tsx
|
|
1168
|
+
* <ScrollArea className="max-h-[270px]">
|
|
1169
|
+
* {items.map(item => <div key={item.id}>{item.label}</div>)}
|
|
1170
|
+
* </ScrollArea>
|
|
1171
|
+
* ```
|
|
1172
|
+
*
|
|
1173
|
+
* For a double-scroll layout (two independent sections inside one dropdown),
|
|
1174
|
+
* wrap each section individually:
|
|
1175
|
+
* ```tsx
|
|
1176
|
+
* <ScrollArea className="max-h-[160px]">...section A items...</ScrollArea>
|
|
1177
|
+
* <ScrollArea className="max-h-[160px]">...section B items...</ScrollArea>
|
|
1178
|
+
* ```
|
|
1179
|
+
*/
|
|
1180
|
+
declare const ScrollArea: React.ForwardRefExoticComponent<ScrollAreaProps & React.RefAttributes<HTMLDivElement>>;
|
|
1181
|
+
|
|
1169
1182
|
declare const RadioGroup: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
1170
1183
|
declare const RadioGroupItem: React.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
1171
1184
|
|
|
@@ -1184,6 +1197,7 @@ type FormProps<TFieldValues extends FieldValues> = Omit<FormHTMLAttributes<HTMLF
|
|
|
1184
1197
|
controllerRef?: React__default.MutableRefObject<FormController<TFieldValues> | null>;
|
|
1185
1198
|
onSubmit: SubmitHandler<TFieldValues>;
|
|
1186
1199
|
onInvalidSubmit?: SubmitErrorHandler<TFieldValues>;
|
|
1200
|
+
onFormStateChange?: (formState: FormState<TFieldValues>) => void;
|
|
1187
1201
|
resolver?: Resolver<TFieldValues>;
|
|
1188
1202
|
validationSchema?: yup.ObjectSchema<any>;
|
|
1189
1203
|
mode?: Mode;
|
|
@@ -1350,6 +1364,74 @@ type FormDialogProps = {
|
|
|
1350
1364
|
};
|
|
1351
1365
|
declare const FormDialog: React.FC<FormDialogProps>;
|
|
1352
1366
|
|
|
1367
|
+
type MenuOption = {
|
|
1368
|
+
value: string;
|
|
1369
|
+
label: ReactNode;
|
|
1370
|
+
/**
|
|
1371
|
+
* Visual type of the item
|
|
1372
|
+
* - "default": selected indicator (check icon on left)
|
|
1373
|
+
* - "checkbox": visual checkbox
|
|
1374
|
+
* - "radio": radio selection (single-select in group)
|
|
1375
|
+
*/
|
|
1376
|
+
type?: "default" | "checkbox" | "radio";
|
|
1377
|
+
icon?: ReactNode;
|
|
1378
|
+
disabled?: boolean;
|
|
1379
|
+
danger?: boolean;
|
|
1380
|
+
checked?: boolean;
|
|
1381
|
+
onClick?: () => void;
|
|
1382
|
+
};
|
|
1383
|
+
type MenuItemType = {
|
|
1384
|
+
type: "item";
|
|
1385
|
+
item: MenuOption;
|
|
1386
|
+
} | {
|
|
1387
|
+
type: "separator";
|
|
1388
|
+
} | {
|
|
1389
|
+
type: "label";
|
|
1390
|
+
label: string;
|
|
1391
|
+
} | {
|
|
1392
|
+
type: "custom";
|
|
1393
|
+
render: () => ReactNode;
|
|
1394
|
+
} | {
|
|
1395
|
+
type: "submenu";
|
|
1396
|
+
label: string;
|
|
1397
|
+
icon?: ReactNode;
|
|
1398
|
+
disabled?: boolean;
|
|
1399
|
+
/** Nested items — rendered via DropdownMenuSub */
|
|
1400
|
+
items: MenuItemType[];
|
|
1401
|
+
};
|
|
1402
|
+
type MenuProps = {
|
|
1403
|
+
/** Trigger element — optional, ถ้าไม่ส่งให้ใช้ open/onOpenChange ควบคุมเอง */
|
|
1404
|
+
trigger?: ReactNode;
|
|
1405
|
+
items: MenuItemType[];
|
|
1406
|
+
selectedValues?: string[];
|
|
1407
|
+
/**
|
|
1408
|
+
* Callback on item select
|
|
1409
|
+
* - "checkbox" → caller toggles in selectedValues
|
|
1410
|
+
* - "radio" → caller sets single value in selectedValues
|
|
1411
|
+
* - "default" → same
|
|
1412
|
+
*/
|
|
1413
|
+
onSelect?: (value: string, item: MenuOption) => void;
|
|
1414
|
+
/**
|
|
1415
|
+
* Optional header rendered above the item list — stays fixed while list scrolls.
|
|
1416
|
+
* ใช้สำหรับ pattern เช่น "Change Status" (title + close button)
|
|
1417
|
+
* หรือ "Manage Column" (title + Hide all / Show all / Done)
|
|
1418
|
+
*/
|
|
1419
|
+
header?: ReactNode;
|
|
1420
|
+
/** Controlled open state */
|
|
1421
|
+
open?: boolean;
|
|
1422
|
+
/** Called when open state changes (controlled or uncontrolled) */
|
|
1423
|
+
onOpenChange?: (open: boolean) => void;
|
|
1424
|
+
/** Alignment of the menu content relative to the trigger */
|
|
1425
|
+
align?: "start" | "center" | "end";
|
|
1426
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
1427
|
+
sideOffset?: number;
|
|
1428
|
+
contentClassName?: string;
|
|
1429
|
+
};
|
|
1430
|
+
declare const Menu: {
|
|
1431
|
+
({ trigger, items, selectedValues, onSelect, header, open, onOpenChange, align, side, sideOffset, contentClassName, }: MenuProps): react_jsx_runtime.JSX.Element;
|
|
1432
|
+
displayName: string;
|
|
1433
|
+
};
|
|
1434
|
+
|
|
1353
1435
|
declare const resloveTimestamp: (timestamp: number) => number;
|
|
1354
1436
|
declare const getStartDateOfDay: (date: Date) => Date;
|
|
1355
1437
|
declare const getEndDateOfDay: (date: Date) => Date;
|
|
@@ -1789,4 +1871,4 @@ declare const srgbToHex: (color: string) => string;
|
|
|
1789
1871
|
*/
|
|
1790
1872
|
declare function getLucideIconNames(): Promise<string[]>;
|
|
1791
1873
|
|
|
1792
|
-
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, ConfirmDialog, type ConfirmDialogProps, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, FormDialog, type FormDialogAction, type FormDialogProps, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, MenuItem, type MenuItemType, MenuLabel, type MenuOption, type MenuProps, MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, Search, type SearchProps, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
|
|
1874
|
+
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Badge, type BadgeColor, type BadgeProps, Button, type ButtonProps, Calendar, Checkbox, Collapsible, ConfirmDialog, type ConfirmDialogProps, type ControlledFormFactoryOptions, type CustomSliderProps, DataTable, type DataTableProps, DatePicker, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type DropdownProps, Field, FieldMessage, type FieldMessageProps, type FieldProps, FocusedScrollView, Footer, type FooterProps, type FooterVariant, Form, type FormController, FormDialog, type FormDialogAction, type FormDialogProps, type FormProps, Icon, Input, InputFilter, type InputFilterProps, type InputProps, Label, Loading, type MaskRule, MaskedTextInput, type MaskedTextInputProps, Menu, DropdownMenuItem as MenuItem, type MenuItemType, DropdownMenuLabel as MenuLabel, type MenuOption, type MenuProps, DropdownMenuSeparator as MenuSeparator, Navbar, type NavbarProps, type NavbarVariant, NumberInput, type NumberInputProps, type OptionLike, type Options$1 as Options, OtpInput, OtpInputGroup, type OtpInputGroupProps, type OtpInputProps, PasswordInput, type PasswordInputProps, Popover, PopoverContent, PopoverTrigger, ProgressBar, RadioGroup, RadioGroupItem, ScrollArea, type ScrollAreaProps, type ScrollbarSize, Search, type SearchProps, SeverityBadge, type SeverityBadgeProps, type SeverityLevel, Slider, type SliderProps, Switch, THEME_COLOR_KEYS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextArea, type TextAreaProps, TextInput, type ThemeColorKey, Toast$1 as Toast, ToastAction, type ToastActionElement, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipSimple, TooltipTrigger, Tree, type TreeData, TreeItem, type TreeItemProps, type TreeProps, type UseControlledFormOptions, type UseOptionBridgeOptions, ValidationHintList, type ValidationHintListProps, type ValidationHintMode, type ValidationHintRule, type ValidationHintState, cn, createControlledForm, createYupResolver, getEndDateOfDay, getLucideIconNames, getStartDateOfDay, getStartEndTimestampOfDay, getThemeColor, getThemeColors, getTimestampUTC, reducer, resloveTimestamp, srgbToHex, toast, useControlledForm, useOptionBridge, usePrevious, useToast };
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export { Navbar } from "./components/Navbar";
|
|
|
18
18
|
export { Footer } from "./components/Footer";
|
|
19
19
|
export { default as ActionButton } from "./components/ActionButton/ActionButton";
|
|
20
20
|
export { Avatar, AvatarGroup } from "./components/Avatar";
|
|
21
|
+
export { Badge, SeverityBadge } from "./components/Badge";
|
|
21
22
|
export { Collapsible } from "./components/Collapsible";
|
|
22
23
|
export { Calendar } from "./components/Calendar";
|
|
23
24
|
export { default as DatePicker } from "./components/DatePicker/DatePicker";
|
|
@@ -36,7 +37,6 @@ export * from "./components/InputFilter/InputFilter";
|
|
|
36
37
|
export * from "./components/Slider/Slider";
|
|
37
38
|
export * from "./components/Switch/Switch";
|
|
38
39
|
export * from "./components/DropdownMenu/DropdownMenu";
|
|
39
|
-
export * from "./components/Menu/Menu";
|
|
40
40
|
export * from "./components/Tooltip/Tooltip";
|
|
41
41
|
export * from "./components/Tooltip/TooltipSimple";
|
|
42
42
|
export * from "./components/Toast/Toast";
|
|
@@ -44,11 +44,13 @@ export * from "./components/Toast/Toaster";
|
|
|
44
44
|
export * from "./components/Toast/useToast";
|
|
45
45
|
export * from "./components/Tree";
|
|
46
46
|
export * from "./components/FocusedScrollView/FocusedScrollView";
|
|
47
|
+
export * from "./components/ScrollArea/ScrollArea";
|
|
47
48
|
export * from "./components/RadioGroup/RadioGroup";
|
|
48
49
|
export * from "./components/Form";
|
|
49
50
|
// Patterns
|
|
50
51
|
export * from "./patterns/confirm-dialog/ConfirmDialog";
|
|
51
52
|
export * from "./patterns/form-dialog/FormDialog";
|
|
53
|
+
export * from "./patterns/menu/Menu";
|
|
52
54
|
// UTILS
|
|
53
55
|
export { resloveTimestamp, getStartDateOfDay, getEndDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, } from "./utils/datetime";
|
|
54
56
|
// Hooks
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { cn } from "@/utils/cn";
|
|
5
|
+
import { DropdownMenu as DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, } from "../../components/DropdownMenu/DropdownMenu";
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// renderMenuItems — recursive, used for both root and submenu levels
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
function renderMenuItems(items, selectedValues, onSelect) {
|
|
10
|
+
const result = [];
|
|
11
|
+
let radioBuffer = [];
|
|
12
|
+
const flushRadioBuffer = (key) => {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
if (radioBuffer.length === 0)
|
|
15
|
+
return;
|
|
16
|
+
const buffer = radioBuffer;
|
|
17
|
+
radioBuffer = [];
|
|
18
|
+
const radioValue = (_b = (_a = buffer.find((o) => selectedValues.includes(o.value))) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "";
|
|
19
|
+
result.push(_jsx(DropdownMenuRadioGroup, { value: radioValue, onValueChange: (val) => {
|
|
20
|
+
var _a;
|
|
21
|
+
const opt = buffer.find((o) => o.value === val);
|
|
22
|
+
if (opt) {
|
|
23
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(val, opt);
|
|
24
|
+
(_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
|
|
25
|
+
}
|
|
26
|
+
}, children: buffer.map((opt) => (_jsx(DropdownMenuRadioItem, { value: opt.value, disabled: opt.disabled, icon: opt.icon, children: opt.label }, opt.value))) }, key));
|
|
27
|
+
};
|
|
28
|
+
items.forEach((item, index) => {
|
|
29
|
+
var _a;
|
|
30
|
+
// Accumulate consecutive radio items
|
|
31
|
+
if (item.type === "item" && item.item.type === "radio") {
|
|
32
|
+
radioBuffer.push(item.item);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Flush radio buffer before non-radio item
|
|
36
|
+
flushRadioBuffer(`radio-${index}`);
|
|
37
|
+
if (item.type === "separator") {
|
|
38
|
+
result.push(_jsx(DropdownMenuSeparator, {}, `sep-${index}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (item.type === "label") {
|
|
42
|
+
result.push(_jsx(DropdownMenuLabel, { children: item.label }, `lbl-${index}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (item.type === "custom") {
|
|
46
|
+
result.push(_jsx(React.Fragment, { children: item.render() }, `custom-${index}`));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (item.type === "submenu") {
|
|
50
|
+
result.push(_jsxs(DropdownMenuSub, { children: [_jsxs(DropdownMenuSubTrigger, { disabled: item.disabled, children: [_jsxs("div", { className: "flex shrink-0 flex-row gap-1", children: [_jsx("span", { className: "size-4" }), item.icon] }), item.label] }), _jsx(DropdownMenuSubContent, { children: renderMenuItems(item.items, selectedValues, onSelect) })] }, `sub-${index}`));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (item.type === "item") {
|
|
54
|
+
const opt = item.item;
|
|
55
|
+
const isSelected = (_a = opt.checked) !== null && _a !== void 0 ? _a : selectedValues.includes(opt.value);
|
|
56
|
+
if (opt.type === "checkbox") {
|
|
57
|
+
result.push(_jsx(DropdownMenuCheckboxItem, { checked: isSelected, disabled: opt.disabled, onCheckedChange: () => {
|
|
58
|
+
var _a;
|
|
59
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt.value, opt);
|
|
60
|
+
(_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
|
|
61
|
+
}, children: opt.label }, opt.value));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// default item
|
|
65
|
+
result.push(_jsx(DropdownMenuItem, { selected: isSelected, icon: opt.icon, disabled: opt.disabled, className: cn(opt.danger && "text-red-500"), onSelect: () => {
|
|
66
|
+
var _a;
|
|
67
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(opt.value, opt);
|
|
68
|
+
(_a = opt.onClick) === null || _a === void 0 ? void 0 : _a.call(opt);
|
|
69
|
+
}, children: opt.label }, opt.value));
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
flushRadioBuffer("radio-end");
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Menu — top-level pattern component built on DropdownMenu
|
|
77
|
+
//
|
|
78
|
+
// ใช้งาน:
|
|
79
|
+
// <Menu trigger={<Button>Open</Button>} items={[...]} onSelect={...} />
|
|
80
|
+
//
|
|
81
|
+
// ได้ของฟรีจาก DropdownMenu:
|
|
82
|
+
// - Radix positioning (flip, scroll, sideOffset)
|
|
83
|
+
// - Portal (z-index, escape stacking context)
|
|
84
|
+
// - Escape to close, click-outside to close
|
|
85
|
+
// - Keyboard navigation (Arrow, Enter, Escape)
|
|
86
|
+
// - Full a11y / WAI-ARIA
|
|
87
|
+
// - Sub-menu support via DropdownMenuSub
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
export const Menu = ({ trigger, items, selectedValues = [], onSelect, header, open, onOpenChange, align = "start", side = "bottom", sideOffset = 4, contentClassName, }) => (_jsxs(DropdownMenuRoot, { open: open, onOpenChange: onOpenChange, children: [trigger && (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsxs(DropdownMenuContent, { align: align, side: side, sideOffset: sideOffset, className: contentClassName, children: [header && (_jsx("div", { className: "sticky top-0 z-10 bg-modal-surface border-b border-[var(--dropdown-menu-seperator-bg)]", children: header })), renderMenuItems(items, selectedValues, onSelect)] })] }));
|
|
90
|
+
Menu.displayName = "Menu";
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Re-exports — backward compat for consumers using Menu's sub-components
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
export { DropdownMenuItem as MenuItem, DropdownMenuSeparator as MenuSeparator, DropdownMenuLabel as MenuLabel, } from "../../components/DropdownMenu/DropdownMenu";
|
|
95
|
+
export default Menu;
|