@rovula/ui 0.1.21 → 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 +175 -26
- 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 +16 -0
- package/dist/cjs/types/index.d.ts +3 -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 +22 -9
- package/dist/components/DropdownMenu/DropdownMenu.stories.js +54 -10
- package/dist/components/TextInput/TextInput.js +6 -3
- package/dist/esm/bundle.css +175 -26
- 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 +16 -0
- package/dist/esm/types/index.d.ts +3 -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 +116 -73
- package/dist/index.js +2 -1
- package/dist/patterns/menu/Menu.js +95 -0
- package/dist/patterns/menu/Menu.stories.js +611 -0
- package/dist/src/theme/global.css +289 -37
- 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 +1050 -113
- package/src/components/DropdownMenu/DropdownMenu.tsx +116 -52
- package/src/components/TextInput/TextInput.tsx +6 -3
- package/src/index.ts +3 -1
- package/src/patterns/menu/Menu.stories.tsx +1100 -0
- package/src/patterns/menu/Menu.tsx +282 -0
- package/src/theme/themes/xspector/baseline.css +0 -1
- package/src/theme/tokens/baseline.css +2 -1
- package/src/theme/tokens/components/badge.css +54 -0
- package/src/theme/tokens/components/dropdown-menu.css +15 -4
- 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
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Merges multiple refs into a single callback ref.
|
|
4
|
+
* NOTE: This creates a new function on every call — do NOT use inline in render.
|
|
5
|
+
* Use `useStableMergedRef` instead when you need a stable ref identity.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mergeRefs<T>(...refs: (React.Ref<T> | undefined | null)[]): React.RefCallback<T>;
|
|
8
|
+
/**
|
|
9
|
+
* Returns a **stable** callback ref (never changes identity) that forwards the
|
|
10
|
+
* node to all given refs. Safe to use inline in JSX — will not cause
|
|
11
|
+
* detach/re-attach loops in libraries like Headless UI that watch refs.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const MyInput = forwardRef((props, ref) => {
|
|
15
|
+
* const internalRef = useRef(null);
|
|
16
|
+
* const stableRef = useStableMergedRef(ref, internalRef);
|
|
17
|
+
* return <input ref={stableRef} />;
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
export declare function useStableMergedRef<T>(...refs: (React.Ref<T> | undefined | null)[]): React.RefCallback<T>;
|
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';
|
|
@@ -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>>;
|
|
@@ -1389,6 +1364,74 @@ type FormDialogProps = {
|
|
|
1389
1364
|
};
|
|
1390
1365
|
declare const FormDialog: React.FC<FormDialogProps>;
|
|
1391
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
|
+
|
|
1392
1435
|
declare const resloveTimestamp: (timestamp: number) => number;
|
|
1393
1436
|
declare const getStartDateOfDay: (date: Date) => Date;
|
|
1394
1437
|
declare const getEndDateOfDay: (date: Date) => Date;
|
|
@@ -1828,4 +1871,4 @@ declare const srgbToHex: (color: string) => string;
|
|
|
1828
1871
|
*/
|
|
1829
1872
|
declare function getLucideIconNames(): Promise<string[]>;
|
|
1830
1873
|
|
|
1831
|
-
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, ScrollArea, type ScrollAreaProps, type ScrollbarSize, 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";
|
|
@@ -50,6 +50,7 @@ export * from "./components/Form";
|
|
|
50
50
|
// Patterns
|
|
51
51
|
export * from "./patterns/confirm-dialog/ConfirmDialog";
|
|
52
52
|
export * from "./patterns/form-dialog/FormDialog";
|
|
53
|
+
export * from "./patterns/menu/Menu";
|
|
53
54
|
// UTILS
|
|
54
55
|
export { resloveTimestamp, getStartDateOfDay, getEndDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, } from "./utils/datetime";
|
|
55
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;
|