@bug-on/md3-react 0.1.0

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.
Files changed (96) hide show
  1. package/README.md +215 -0
  2. package/dist/assets/fonts/GoogleSansFlex-VariableFont.woff2 +0 -0
  3. package/dist/assets/fonts/MaterialSymbolsOutlined-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
  4. package/dist/assets/fonts/MaterialSymbolsRounded-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
  5. package/dist/assets/fonts/MaterialSymbolsSharp-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
  6. package/dist/assets/loading-indicator.svg +19 -0
  7. package/dist/assets/material-symbols-cdn.css +65 -0
  8. package/dist/assets/material-symbols-self-hosted.css +109 -0
  9. package/dist/hooks/index.d.ts +3 -0
  10. package/dist/hooks/useMediaQuery.d.ts +11 -0
  11. package/dist/hooks/useRipple.d.ts +26 -0
  12. package/dist/index.d.ts +65 -0
  13. package/dist/index.js +9059 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/index.mjs +8929 -0
  16. package/dist/index.mjs.map +1 -0
  17. package/dist/lib/material-symbols-preconnect.d.ts +42 -0
  18. package/dist/lib/theme-utils.d.ts +63 -0
  19. package/dist/lib/utils.d.ts +2 -0
  20. package/dist/material-symbols-cdn.css +65 -0
  21. package/dist/material-symbols-self-hosted.css +109 -0
  22. package/dist/types/index.d.ts +1 -0
  23. package/dist/types/md3.d.ts +14 -0
  24. package/dist/typography.css +22 -0
  25. package/dist/ui/badge.d.ts +125 -0
  26. package/dist/ui/button-group.d.ts +59 -0
  27. package/dist/ui/button.d.ts +148 -0
  28. package/dist/ui/card.d.ts +62 -0
  29. package/dist/ui/checkbox.d.ts +82 -0
  30. package/dist/ui/chip.d.ts +110 -0
  31. package/dist/ui/code-block.d.ts +14 -0
  32. package/dist/ui/dialog.d.ts +111 -0
  33. package/dist/ui/divider.d.ts +164 -0
  34. package/dist/ui/drawer.d.ts +39 -0
  35. package/dist/ui/dropdown.d.ts +29 -0
  36. package/dist/ui/fab-menu.d.ts +204 -0
  37. package/dist/ui/fab.d.ts +162 -0
  38. package/dist/ui/icon-button.d.ts +131 -0
  39. package/dist/ui/icon.d.ts +88 -0
  40. package/dist/ui/loading-indicator.d.ts +42 -0
  41. package/dist/ui/navigation-rail.d.ts +29 -0
  42. package/dist/ui/progress-indicator/circular.d.ts +3 -0
  43. package/dist/ui/progress-indicator/hooks.d.ts +3 -0
  44. package/dist/ui/progress-indicator/index.d.ts +21 -0
  45. package/dist/ui/progress-indicator/linear-flat.d.ts +10 -0
  46. package/dist/ui/progress-indicator/linear-wavy.d.ts +18 -0
  47. package/dist/ui/progress-indicator/linear.d.ts +3 -0
  48. package/dist/ui/progress-indicator/types.d.ts +151 -0
  49. package/dist/ui/progress-indicator/utils.d.ts +3 -0
  50. package/dist/ui/radio-button.d.ts +106 -0
  51. package/dist/ui/ripple.d.ts +126 -0
  52. package/dist/ui/scroll-area.d.ts +27 -0
  53. package/dist/ui/shared/constants.d.ts +86 -0
  54. package/dist/ui/shared/touch-target.d.ts +38 -0
  55. package/dist/ui/snackbar/index.d.ts +6 -0
  56. package/dist/ui/snackbar/snackbar.d.ts +196 -0
  57. package/dist/ui/switch/index.d.ts +7 -0
  58. package/dist/ui/switch/switch.d.ts +30 -0
  59. package/dist/ui/switch/switch.stories.d.ts +48 -0
  60. package/dist/ui/switch/switch.tokens.d.ts +67 -0
  61. package/dist/ui/switch/switch.types.d.ts +59 -0
  62. package/dist/ui/tabs/index.d.ts +10 -0
  63. package/dist/ui/tabs/tab.d.ts +43 -0
  64. package/dist/ui/tabs/tabs-content.d.ts +36 -0
  65. package/dist/ui/tabs/tabs-list.d.ts +40 -0
  66. package/dist/ui/tabs/tabs.d.ts +60 -0
  67. package/dist/ui/tabs/tabs.tokens.d.ts +94 -0
  68. package/dist/ui/tabs/tabs.types.d.ts +172 -0
  69. package/dist/ui/text-field/index.d.ts +11 -0
  70. package/dist/ui/text-field/subcomponents/active-indicator.d.ts +24 -0
  71. package/dist/ui/text-field/subcomponents/floating-label.d.ts +43 -0
  72. package/dist/ui/text-field/subcomponents/leading-icon.d.ts +23 -0
  73. package/dist/ui/text-field/subcomponents/outline-container.d.ts +42 -0
  74. package/dist/ui/text-field/subcomponents/prefix-suffix.d.ts +24 -0
  75. package/dist/ui/text-field/subcomponents/supporting-text.d.ts +37 -0
  76. package/dist/ui/text-field/subcomponents/trailing-icon.d.ts +41 -0
  77. package/dist/ui/text-field/text-field.d.ts +49 -0
  78. package/dist/ui/text-field/text-field.tokens.d.ts +76 -0
  79. package/dist/ui/text-field/text-field.types.d.ts +126 -0
  80. package/dist/ui/theme-provider/index.d.ts +18 -0
  81. package/dist/ui/toc.d.ts +74 -0
  82. package/dist/ui/tooltip/index.d.ts +8 -0
  83. package/dist/ui/tooltip/plain-tooltip.d.ts +2 -0
  84. package/dist/ui/tooltip/rich-tooltip.d.ts +2 -0
  85. package/dist/ui/tooltip/tooltip-box.d.ts +2 -0
  86. package/dist/ui/tooltip/tooltip-caret-shape.d.ts +9 -0
  87. package/dist/ui/tooltip/tooltip.tokens.d.ts +26 -0
  88. package/dist/ui/tooltip/tooltip.types.d.ts +56 -0
  89. package/dist/ui/tooltip/use-tooltip-position.d.ts +8 -0
  90. package/dist/ui/tooltip/use-tooltip-state.d.ts +2 -0
  91. package/dist/ui/typography/index.d.ts +16 -0
  92. package/dist/ui/typography/type-scale-tokens.d.ts +162 -0
  93. package/dist/ui/typography/typography-key-tokens.d.ts +40 -0
  94. package/dist/ui/typography/typography-tokens.d.ts +220 -0
  95. package/dist/ui/typography/typography.d.ts +265 -0
  96. package/package.json +80 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @file card.tsx
3
+ *
4
+ * Thẻ Card của bộ khung MD3 Expressive.
5
+ *
6
+ * Phân chia làm hai khía cạnh chức năng (cấu trúc tham khảo từ con ruột Android Card.kt):
7
+ * - **Tĩnh Lặng (Static)** → đơn thuần mang thẻ `<div>`, yên tĩnh và không hề mảy may phản hồi có tương tác nào.
8
+ * - **Có phản ứng (Interactive)** → được phù phép bằng `<motion.button>` hoặc `<motion.a>`, mang bùa Ripple vẫy sống cùng khả năng nhảy vọt elevation khi lướt lên.
9
+ *
10
+ * Nấc độ bóng Elevation levels (dịch từ các file mã ElevatedCardTokens / FilledCardTokens / OutlinedCardTokens / Elevation.kt):
11
+ * - Level 0 = "none" (Bằng phẳng)
12
+ * - Level 1 = box-shadow ~1dp (Hơi nhỉnh nổi nhẹ)
13
+ * - Level 2 = box-shadow ~2dp (Bay lên cao xíu)
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * // Card tĩnh
18
+ * <Card variant="elevated">
19
+ * <div className="p-4">Nội dung thẻ Card nhẹ nhàng</div>
20
+ * </Card>
21
+ *
22
+ * // Card button tương tác
23
+ * <Card variant="filled" onClick={() => alert('Đã nhấn!')}>
24
+ * <div className="p-4">Click vào đây em ei</div>
25
+ * </Card>
26
+ *
27
+ * // Card làm thẻ Link a
28
+ * <Card variant="outlined" href="/home">
29
+ * <div className="p-4">Click để chuyển trang</div>
30
+ * </Card>
31
+ * ```
32
+ *
33
+ * @see https://m3.material.io/components/cards/overview
34
+ */
35
+ import { type VariantProps } from "class-variance-authority";
36
+ import type { HTMLMotionProps } from "motion/react";
37
+ import * as React from "react";
38
+ declare const cardVariants: (props?: ({
39
+ variant?: "outlined" | "elevated" | "filled" | null | undefined;
40
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
41
+ type MotionDivProps = Omit<HTMLMotionProps<"button">, "children" | "color">;
42
+ export interface CardProps extends MotionDivProps, VariantProps<typeof cardVariants> {
43
+ /** Vô hiệu hóa tương tác và giảm opacity (MD3 disabled state). */
44
+ disabled?: boolean;
45
+ /**
46
+ * Buộc card trở thành interactive dù không có `onClick`.
47
+ * Hữu ích khi card chứa các element con là interactive.
48
+ */
49
+ interactive?: boolean;
50
+ /**
51
+ * Nếu có, card render thành thẻ `<a>`. Tự động kích hoạt interactive mode.
52
+ * Ưu tiên dùng `href` thay vì `onClick` khi điều hướng trang.
53
+ */
54
+ href?: string;
55
+ /** Target cho thẻ `<a>` (chỉ có hiệu lực khi `href` được cung cấp). */
56
+ target?: React.AnchorHTMLAttributes<HTMLAnchorElement>["target"];
57
+ /** rel cho thẻ `<a>` (tự động thêm `noreferrer` khi `target="_blank"`). */
58
+ rel?: string;
59
+ children?: React.ReactNode;
60
+ }
61
+ export declare const Card: React.NamedExoticComponent<Omit<CardProps, "ref"> & React.RefAttributes<HTMLElement>>;
62
+ export {};
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @file checkbox.tsx
3
+ * MD3 Expressive Checkbox — 2-state and tri-state support.
4
+ * Spec: https://m3.material.io/components/checkbox/overview
5
+ */
6
+ import * as React from "react";
7
+ /**
8
+ * Tri-state value: `"unchecked"` | `"checked"` | `"indeterminate"`.
9
+ */
10
+ export type CheckboxState = "unchecked" | "checked" | "indeterminate";
11
+ /**
12
+ * Props for `Checkbox`. Supports boolean (`checked`/`onCheckedChange`)
13
+ * and tri-state (`state`/`onStateChange`) modes.
14
+ */
15
+ export interface CheckboxProps {
16
+ /** Controlled checked value (2-state mode). */
17
+ checked?: boolean;
18
+ /** Initial value for uncontrolled mode. @default false */
19
+ defaultChecked?: boolean;
20
+ /** Forces indeterminate rendering regardless of `checked`. */
21
+ indeterminate?: boolean;
22
+ /** Fired on checked change (simple mode). Not called when disabled. */
23
+ onCheckedChange?: (checked: boolean) => void;
24
+ /** Controlled tri-state value. Takes priority over `checked`/`indeterminate`. */
25
+ state?: CheckboxState;
26
+ /** Fired on tri-state change. Cycles: unchecked → checked → indeterminate. */
27
+ onStateChange?: (state: CheckboxState) => void;
28
+ /** Disables interaction and applies 0.38 opacity. */
29
+ disabled?: boolean;
30
+ /** Error state — changes colors to `m3-error` and sets `aria-invalid`. */
31
+ error?: boolean;
32
+ /** Adjacent label text. Wraps checkbox + span in `<label>`. */
33
+ label?: string;
34
+ "aria-label"?: string;
35
+ "aria-labelledby"?: string;
36
+ "aria-describedby"?: string;
37
+ "aria-required"?: boolean;
38
+ /** Passed to the hidden `<input>` for form submission. */
39
+ name?: string;
40
+ /** Passed to the hidden `<input>` for form submission. */
41
+ value?: string;
42
+ /** ID for the hidden `<input>`. Auto-generated when `label` is set. */
43
+ id?: string;
44
+ /** Extra class names on the outermost wrapper. */
45
+ className?: string;
46
+ /** Ref pointing to the hidden `<input type="checkbox">`. */
47
+ ref?: React.Ref<HTMLInputElement>;
48
+ }
49
+ /**
50
+ * `TriStateCheckbox` props — requires `state` + `onStateChange`.
51
+ */
52
+ export interface TriStateCheckboxProps extends Omit<CheckboxProps, "checked" | "defaultChecked" | "onCheckedChange"> {
53
+ state: CheckboxState;
54
+ onStateChange: (state: CheckboxState) => void;
55
+ }
56
+ /**
57
+ * MD3 Expressive Checkbox component.
58
+ *
59
+ * Supports 2-state and tri-state patterns. Fully animated per MD3 spec:
60
+ * checkmark draw, indeterminate dash morph, container fill, state layer, and ripple.
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * <Checkbox checked={isChecked} onCheckedChange={setIsChecked} label="Accept terms" />
65
+ * <Checkbox state={parentState} onStateChange={setParentState} label="Select all" />
66
+ * <Checkbox error label="Required field" aria-describedby="err-msg" />
67
+ * ```
68
+ * @see https://m3.material.io/components/checkbox/overview
69
+ */
70
+ export declare const Checkbox: React.NamedExoticComponent<Omit<CheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
71
+ /**
72
+ * MD3 Expressive Tri-State Checkbox.
73
+ *
74
+ * Convenience wrapper around `Checkbox` that enforces `state` + `onStateChange`.
75
+ * Ideal for parent-child selection patterns.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * <TriStateCheckbox state={parentState} onStateChange={setParentState} label="Select all" />
80
+ * ```
81
+ */
82
+ export declare const TriStateCheckbox: React.NamedExoticComponent<Omit<TriStateCheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @file chip.tsx
3
+ *
4
+ * MD3 Expressive Chip component — 4 variants.
5
+ *
6
+ * - `assist` → Triggered actions spanning multiple apps. Flat (bordered) or Elevated.
7
+ * - `filter` → Toggleable selections. Animated checkmark on select.
8
+ * - `input` → Entities/tags with optional avatar and a dedicated remove button.
9
+ * - `suggestion` → Contextual dynamic recommendations. Flat (bordered) or Elevated.
10
+ *
11
+ * @remarks
12
+ * Token references (Kotlin source):
13
+ * AssistChipTokens, FilterChipTokens, InputChipTokens, SuggestionChipTokens
14
+ *
15
+ * Architecture:
16
+ * - Styling: `cva` + `cn` (clsx/tailwind-merge)
17
+ * - Animation: Framer Motion (`LazyMotion` + `domMax`) for animated checkmark
18
+ * - Ripple: `Ripple` + `useRippleState` from `./ripple.tsx`
19
+ * - A11y: `role="checkbox"` (filter), `role="button"` (others); full keyboard support
20
+ *
21
+ * @see https://m3.material.io/components/chips/overview
22
+ */
23
+ import { type VariantProps } from "class-variance-authority";
24
+ import * as React from "react";
25
+ declare const chipVariants: (props?: ({
26
+ variant?: "input" | "filter" | "assist" | "suggestion" | null | undefined;
27
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
28
+ export interface ChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
29
+ /**
30
+ * Chip variant.
31
+ * - `assist` → Smart/automated actions. Flat by default, can be elevated.
32
+ * - `filter` → Toggleable tag/filter. Shows animated checkmark when selected.
33
+ * - `input` → Entity representation (tag, contact). Has optional avatar + remove button.
34
+ * - `suggestion` → Contextual suggestions. Like assist, flat by default, can be elevated.
35
+ * @default 'assist'
36
+ */
37
+ variant?: VariantProps<typeof chipVariants>["variant"];
38
+ /**
39
+ * Renders with elevation shadow (Level 1) and fills background with `surface-container-low`.
40
+ * Applicable to `assist`, `filter` (unselected), and `suggestion` variants.
41
+ * Source: AssistChipTokens.ElevatedContainerColor / SuggestionChipTokens.ElevatedContainerColor
42
+ */
43
+ elevated?: boolean;
44
+ /**
45
+ * Toggle/selection state.
46
+ * - `filter`: selected → bg `secondary-container`, animated checkmark appears.
47
+ * - `input`: selected → bg `secondary-container`.
48
+ * Used for `role="checkbox"` (filter) / `aria-pressed` (input).
49
+ */
50
+ selected?: boolean;
51
+ /**
52
+ * Disables the chip. Applies:
53
+ * - `pointer-events-none` – no mouse/touch interaction
54
+ * - `opacity-[0.38]` – DisabledLabelTextOpacity (0.38) per MD3 tokens
55
+ * - `aria-disabled="true"`
56
+ * - `tabIndex={-1}`
57
+ */
58
+ disabled?: boolean;
59
+ /**
60
+ * Visible label. Required. Can be a string or ReactNode.
61
+ */
62
+ label: React.ReactNode;
63
+ /**
64
+ * Optional leading icon element (18×18px recommended).
65
+ * For `filter` chips with `selected=true`, this is replaced by an animated checkmark.
66
+ * For `assist`/`suggestion`: icon color → `primary`
67
+ * For `input` (unselected): icon color → `on-surface-variant`
68
+ */
69
+ leadingIcon?: React.ReactNode;
70
+ /**
71
+ * Optional trailing icon element (18×18px recommended).
72
+ * Color: `on-surface-variant` (unselected) / `on-secondary-container` (selected).
73
+ */
74
+ trailingIcon?: React.ReactNode;
75
+ /**
76
+ * Avatar element for `input` chips. Takes priority over `leadingIcon`.
77
+ * Rendered as a 24×24px circle (InputChipTokens: AvatarSize = 24.dp, AvatarShape = CornerFull).
78
+ */
79
+ avatar?: React.ReactNode;
80
+ /**
81
+ * Callback when the trailing remove (×) button is activated on `input` chips.
82
+ * When provided, a dedicated tabbable close button with `aria-label="Remove {label}"` is rendered.
83
+ */
84
+ onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;
85
+ }
86
+ /**
87
+ * MD3 Expressive Chip — 4-variant interactive tag component.
88
+ *
89
+ * @remarks
90
+ * - `filter` chips accept `selected` and render an animated checkmark.
91
+ * - `input` chips accept `onRemove` to render a compound close button.
92
+ * - `elevated` is supported on `assist`, `filter` (unselected), and `suggestion`.
93
+ * - Fully accessible: `role="checkbox"` for filter, `role="group"` for compound chips.
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * // Assist chip
98
+ * <Chip variant="assist" label="Share" onClick={share} />
99
+ *
100
+ * // Filter chip
101
+ * <Chip variant="filter" label="Unread" selected={showUnread} onClick={toggle} />
102
+ *
103
+ * // Input chip with remove
104
+ * <Chip variant="input" label="React" onRemove={() => removeTag("React")} />
105
+ * ```
106
+ *
107
+ * @see https://m3.material.io/components/chips/overview
108
+ */
109
+ export declare const Chip: React.NamedExoticComponent<ChipProps & React.RefAttributes<HTMLButtonElement>>;
110
+ export {};
@@ -0,0 +1,14 @@
1
+ export interface CodeBlockProps {
2
+ /** Raw code string to display and copy. */
3
+ code: string;
4
+ /** Language label in the header (presentational only). @default "React" */
5
+ language?: string;
6
+ /** Additional CSS classes for the outer wrapper. */
7
+ className?: string;
8
+ /**
9
+ * Pre-highlighted HTML from Shiki SSR.
10
+ * Use `codeToHtml` with `themes: { light, dark }` for dual-theme support.
11
+ */
12
+ html?: string;
13
+ }
14
+ export declare function CodeBlock({ code, language, className, html, }: CodeBlockProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @file dialog.tsx
3
+ *
4
+ * Sub-system Component Dialog theo phong cách hiển thị MD3 Expressive.
5
+ *
6
+ * Được kế thừa trên nền lõi của hệ mã Radix UI Dialog primitives đi kèm gói kén Framer Motion dùng vào việc bổ sung
7
+ * nhip điệu đẩy Spring ở hướng hiện vào (Entrance) cũng như bay lên (Exit); ăn liền với bản thiết kế specs MD3 Expressive siêu quyến rũ.
8
+ * Phục vụ cả ở chế độ Standard (Tiêu chuẩn lọt thỏm) và phiên bản Full-Screen tràn viền toàn diện.
9
+ *
10
+ * @see https://m3.material.io/components/dialogs/overview
11
+ */
12
+ import * as RadixDialog from "@radix-ui/react-dialog";
13
+ import * as React from "react";
14
+ /**
15
+ * Thuộc tính của cội gốc Root `Dialog`. Chức năng làm gương phản hồi của Radix `Dialog.Root` qua dạng controlled state đóng hay mở.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const [open, setOpen] = React.useState(false);
20
+ *
21
+ * <Dialog open={open} onOpenChange={setOpen}>
22
+ * <DialogTrigger asChild>
23
+ * <Button>Bấm Mở Dialog</Button>
24
+ * </DialogTrigger>
25
+ * <DialogContent>
26
+ * <DialogHeader>
27
+ * <DialogTitle>Bạn có muốn phiêu lưu không?</DialogTitle>
28
+ * </DialogHeader>
29
+ * <DialogBody>Chuẩn bị lên đồ rời khỏi hang nào.</DialogBody>
30
+ * <DialogFooter>
31
+ * <Button onClick={() => setOpen(false)} variant="text">Đóng</Button>
32
+ * </DialogFooter>
33
+ * </DialogContent>
34
+ * </Dialog>
35
+ * ```
36
+ */
37
+ export interface DialogProps {
38
+ /** Whether the dialog is open (controlled). Omit for uncontrolled. */
39
+ open?: boolean;
40
+ /** Called when the open state should change. */
41
+ onOpenChange?: (open: boolean) => void;
42
+ /** Dialog trigger + content. */
43
+ children: React.ReactNode;
44
+ }
45
+ /**
46
+ * Các props được tiêm vào component bao ngoài Container `DialogContent` thuộc dạng Normal Standard.
47
+ *
48
+ * @see {@link DialogContent}
49
+ */
50
+ export interface DialogContentProps extends React.ComponentPropsWithoutRef<typeof RadixDialog.Content> {
51
+ /** Vô hình đi đi nút Close dấu (X) góc phải trên. @default false */
52
+ hideCloseButton?: boolean;
53
+ className?: string;
54
+ }
55
+ /**
56
+ * Thuộc tính Props của biến thể `DialogFullScreenContent` chuyên dụng dành riêng cho Mode Full-Screen tràn màn hình.
57
+ *
58
+ * @remarks
59
+ * Những hộp thoại Full-screen có biệt tài tự nới rộng và xâm chiếm cả bề ngang dọc nguyên thiết bị. Nó còn thiết lập một đường Top App bar (thanh ngang đỉnh)
60
+ * kẹp chung cả 1 nhãn title mô tả đỉnh, một nút icon X dẹp ở rìa, thêm luôn hẳn cái nút Confirm cực xịn xò.
61
+ *
62
+ * @see {@link DialogFullScreenContent}
63
+ * @see https://m3.material.io/components/dialogs/guidelines#full-screen
64
+ */
65
+ export interface DialogFullScreenContentProps extends React.ComponentPropsWithoutRef<typeof RadixDialog.Content> {
66
+ /** Nhãn Title nằm vùng khu vực thanh ngang Top Bar. */
67
+ title?: string;
68
+ /** Chữ viết đính kèm bên trong cục Nút nhấn thao tác ngay trên góc Top App bar đó (VD: "Lưu lại", "Save"). */
69
+ actionLabel?: string;
70
+ /** Hàm handler phát động cờ để kích chạy tính năng lưu, xác nhận kia. */
71
+ onAction?: () => void;
72
+ /** Rạch một làn kẻ chia cách thân body nội dung cuộn bên dưới và dòng App bar cố thủ bên trên. @default false */
73
+ showDivider?: boolean;
74
+ className?: string;
75
+ }
76
+ /**
77
+ * Gốc rễ Root của Component Dialog — trạc lấp lên cái module `Dialog.Root` của nhà Radix.
78
+ *
79
+ * @remarks Cơ năng hoạt động ở chế độ Controlled (kiểm soát vòng đời ở Client) xài mảng `open`/`onOpenChange`.
80
+ * Tuy thế bạn nếu không thích thì đừng có xài truyền mấy cái Props tay đôi trên, mà bỏ xài kiểu Untracked thông qua cái cục `DialogTrigger` là đủ.
81
+ */
82
+ declare const Dialog: {
83
+ ({ open, onOpenChange, children }: DialogProps): import("react/jsx-runtime").JSX.Element;
84
+ displayName: string;
85
+ };
86
+ /** Bộ Trigger gieo phát đà giúp tắt bật cờ State đóng mở của Dialog con, dùng kèm kĩ năng nhét thông qua cái cầu `asChild`. */
87
+ declare const DialogTrigger: React.ForwardRefExoticComponent<RadixDialog.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
88
+ declare const DialogPortal: {
89
+ ({ open, children, }: {
90
+ open?: boolean;
91
+ children: React.ReactNode;
92
+ }): import("react/jsx-runtime").JSX.Element;
93
+ displayName: string;
94
+ };
95
+ declare const DialogOverlay: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
96
+ declare const DialogContent: React.ForwardRefExoticComponent<DialogContentProps & React.RefAttributes<HTMLDivElement>>;
97
+ declare const DialogIcon: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
98
+ declare const DialogHeader: {
99
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
100
+ displayName: string;
101
+ };
102
+ declare const DialogTitle: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
103
+ declare const DialogDescription: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
104
+ declare const DialogBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
105
+ declare const DialogFooter: {
106
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
107
+ displayName: string;
108
+ };
109
+ declare const DialogClose: React.ForwardRefExoticComponent<RadixDialog.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
110
+ declare const DialogFullScreenContent: React.ForwardRefExoticComponent<DialogFullScreenContentProps & React.RefAttributes<HTMLDivElement>>;
111
+ export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogFullScreenContent, DialogHeader, DialogIcon, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @file divider.tsx
3
+ *
4
+ * MD3 Expressive Divider component.
5
+ *
6
+ * - `Divider` → A thin line that groups content in lists and layouts.
7
+ *
8
+ * @remarks
9
+ * Token references (Kotlin source — DividerTokens.kt v0_117):
10
+ * Color = ColorSchemeKeyTokens.OutlineVariant → bg-m3-outline-variant / text-m3-outline-variant
11
+ * Thickness = 1.0.dp → h-px (flat horizontal) | w-px (flat vertical) | strokeWidth={1} (wavy SVG)
12
+ *
13
+ * Variants:
14
+ * - "full-bleed" → spans full width, no indent
15
+ * - "inset" → leading indent (16dp standard / 72dp after-icon via insetStart)
16
+ * - "middle-inset" → 16dp indent both sides
17
+ * - "subheader" → same as full-bleed (label provided externally)
18
+ *
19
+ * Shapes:
20
+ * - "flat" → straight 1px line rendered as <m.div> (default)
21
+ * - "wavy" → sinusoidal SVG wave via <m.svg> + buildWavePath helper (horizontal only)
22
+ *
23
+ * Architecture:
24
+ * - Styling: `cn` (clsx/tailwind-merge) + static Tailwind classes only
25
+ * - Animation: Framer Motion LazyMotion/domMax, scaleX/scaleY spring entrance
26
+ * - Wavy: SVG path generated by pure-JS `buildWavePath()` (cubic Bézier sine approx)
27
+ * Uses ResizeObserver (via useContainerWidth) to measure container width so
28
+ * the path has precise bounds and leading/trailing ends are properly rounded.
29
+ * - A11y: role="separator", aria-orientation, aria-hidden when decorative
30
+ *
31
+ * @see https://m3.material.io/components/divider/overview
32
+ */
33
+ import * as React from "react";
34
+ type SafeHTMLDivAttrs = Omit<React.HTMLAttributes<HTMLDivElement>, "onDrag" | "onDragStart" | "onDragEnd" | "onDragEnter" | "onDragLeave" | "onDragOver" | "onDrop">;
35
+ export interface DividerProps extends SafeHTMLDivAttrs {
36
+ /**
37
+ * Visual variant controlling indentation.
38
+ * - "full-bleed" → no indent, spans full container width/height (default)
39
+ * - "inset" → leading indent only (use `insetStart` to control amount)
40
+ * - "middle-inset" → 16px indent on both sides
41
+ * - "subheader" → alias for full-bleed, used before section labels
42
+ * @default "full-bleed"
43
+ */
44
+ variant?: "full-bleed" | "inset" | "middle-inset" | "subheader";
45
+ /**
46
+ * Orientation of the divider line.
47
+ * - "horizontal" → renders as `h-px w-full` bar (default)
48
+ * - "vertical" → renders as `w-px h-full` column
49
+ * Note: `shape="wavy"` is not supported with orientation="vertical".
50
+ * @default "horizontal"
51
+ */
52
+ orientation?: "horizontal" | "vertical";
53
+ /**
54
+ * Shape of the divider line.
55
+ * - "flat" → straight 1px line rendered as `<div>` (default)
56
+ * - "wavy" → sinusoidal SVG wave (horizontal orientation only)
57
+ *
58
+ * When `shape="wavy"` and `orientation="vertical"`, silently falls back to
59
+ * `shape="flat"` and emits a `console.warn`.
60
+ * @default "flat"
61
+ */
62
+ shape?: "flat" | "wavy";
63
+ /**
64
+ * Leading inset size for the "inset" variant.
65
+ * - "standard" → 16px (`ml-4`)
66
+ * - "icon" → 72px (`ml-[72px]`) — use when list items have leading icons/avatars
67
+ * Only applies when `variant="inset"`.
68
+ * @default "standard"
69
+ */
70
+ insetStart?: "standard" | "icon";
71
+ /**
72
+ * Wavy shape visual parameters. Only applies when `shape="wavy"`.
73
+ * All values are in pixels.
74
+ */
75
+ waveConfig?: {
76
+ /**
77
+ * Peak displacement from the center line.
78
+ * @default 2
79
+ */
80
+ amplitude?: number;
81
+ /**
82
+ * Pixels per full sine cycle.
83
+ * @default 32
84
+ */
85
+ wavelength?: number;
86
+ /**
87
+ * Thickness of the wave stroke in pixels.
88
+ * @default 1
89
+ */
90
+ strokeWidth?: number;
91
+ };
92
+ /**
93
+ * When true, marks the divider as decorative (`aria-hidden="true"`).
94
+ * Use when the divider is purely visual with no semantic meaning.
95
+ * @default false
96
+ */
97
+ decorative?: boolean;
98
+ /**
99
+ * When true, plays an entrance animation (scaleX/scaleY from 0→1).
100
+ * Automatically disabled when user prefers reduced motion.
101
+ * @default true
102
+ */
103
+ animate?: boolean;
104
+ }
105
+ /**
106
+ * Generates an SVG path `d` string for a sinusoidal wave between two X bounds.
107
+ * Uses cubic Bézier approximation of a sine curve for smooth rendering.
108
+ * The error vs. a true sine is < 0.2%.
109
+ *
110
+ * Each half-cycle alternates between crest (+amplitude) and trough (-amplitude).
111
+ * Control points are placed at 1/3 and 2/3 of each half-cycle for accuracy.
112
+ *
113
+ * @param startX - X coordinate where the path begins (e.g. capWidth = strokeWidth/2)
114
+ * @param endX - X coordinate where the path ends (e.g. containerWidth - capWidth)
115
+ * @param amplitude - Peak displacement from center line (px). Default: 2
116
+ * @param wavelength - Pixels per full sine cycle. Default: 32
117
+ * @param yCenter - Y coordinate of the wave center line. Default: 4
118
+ * @returns SVG path `d` attribute string, or "" when startX >= endX
119
+ *
120
+ * @example
121
+ * buildWavePath(0.5, 499.5, 2, 32, 4)
122
+ * // → "M 0.5,4 C 11.17,... 500,4 ..."
123
+ */
124
+ export declare function buildWavePath(startX: number, endX: number, amplitude?: number, wavelength?: number, yCenter?: number): string;
125
+ /**
126
+ * MD3 Expressive Divider — a thin line that groups content in lists and layouts.
127
+ *
128
+ * Supports four layout variants (full-bleed, inset, middle-inset, subheader),
129
+ * two orientations (horizontal, vertical), and two shape modes (flat, wavy).
130
+ *
131
+ * The wavy shape renders a sinusoidal SVG wave and is only supported with
132
+ * `orientation="horizontal"`.
133
+ *
134
+ * @example
135
+ * ```tsx
136
+ * // Default flat full-bleed horizontal divider
137
+ * <Divider />
138
+ *
139
+ * // Inset after icon list items
140
+ * <Divider variant="inset" insetStart="icon" />
141
+ *
142
+ * // Vertical separator between panes
143
+ * <Divider orientation="vertical" />
144
+ *
145
+ * // Wavy expressive divider
146
+ * <Divider shape="wavy" />
147
+ *
148
+ * // Wavy with custom wave config
149
+ * <Divider shape="wavy" waveConfig={{ amplitude: 5, wavelength: 24 }} />
150
+ *
151
+ * // Decorative (no a11y semantics)
152
+ * <Divider decorative />
153
+ *
154
+ * // No entrance animation
155
+ * <Divider animate={false} />
156
+ *
157
+ * // Middle-inset wavy divider
158
+ * <Divider variant="middle-inset" shape="wavy" />
159
+ * ```
160
+ *
161
+ * @see https://m3.material.io/components/divider/overview
162
+ */
163
+ export declare const Divider: React.NamedExoticComponent<DividerProps & React.RefAttributes<HTMLDivElement>>;
164
+ export {};
@@ -0,0 +1,39 @@
1
+ import * as RadixDialog from "@radix-ui/react-dialog";
2
+ import * as React from "react";
3
+ export interface DrawerProps {
4
+ open?: boolean;
5
+ onOpenChange?: (open: boolean) => void;
6
+ children: React.ReactNode;
7
+ }
8
+ export interface DrawerContentProps extends Omit<React.ComponentPropsWithoutRef<typeof RadixDialog.Content>, "asChild"> {
9
+ /** Chiều cao tối đa (vh). Mặc định 90vh */
10
+ maxHeight?: string;
11
+ /** Ẩn drag handle */
12
+ hideHandle?: boolean;
13
+ /** Ẩn nút đóng */
14
+ hideCloseButton?: boolean;
15
+ className?: string;
16
+ }
17
+ declare const Drawer: {
18
+ ({ open, onOpenChange, children }: DrawerProps): import("react/jsx-runtime").JSX.Element;
19
+ displayName: string;
20
+ };
21
+ declare const DrawerTrigger: React.ForwardRefExoticComponent<RadixDialog.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
22
+ declare const DrawerClose: React.ForwardRefExoticComponent<RadixDialog.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
23
+ declare const DrawerPortal: ({ open, children, }: {
24
+ open?: boolean;
25
+ children: React.ReactNode;
26
+ }) => import("react/jsx-runtime").JSX.Element;
27
+ declare const DrawerOverlay: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
28
+ declare const DrawerContent: React.ForwardRefExoticComponent<DrawerContentProps & React.RefAttributes<HTMLDivElement>>;
29
+ declare const DrawerHeader: {
30
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
31
+ displayName: string;
32
+ };
33
+ declare const DrawerFooter: {
34
+ ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
35
+ displayName: string;
36
+ };
37
+ declare const DrawerTitle: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
38
+ declare const DrawerDescription: React.ForwardRefExoticComponent<Omit<RadixDialog.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
39
+ export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, };
@@ -0,0 +1,29 @@
1
+ import * as RadixDropdown from "@radix-ui/react-dropdown-menu";
2
+ import * as React from "react";
3
+ export type DropdownMenuProps = React.ComponentPropsWithoutRef<typeof RadixDropdown.Root>;
4
+ export type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<typeof RadixDropdown.Trigger>;
5
+ declare const DropdownMenu: React.FC<RadixDropdown.DropdownMenuProps>;
6
+ declare const DropdownMenuTrigger: React.ForwardRefExoticComponent<RadixDropdown.DropdownMenuTriggerProps & React.RefAttributes<HTMLButtonElement>>;
7
+ declare const DropdownMenuGroup: React.ForwardRefExoticComponent<RadixDropdown.DropdownMenuGroupProps & React.RefAttributes<HTMLDivElement>>;
8
+ declare const DropdownMenuPortal: React.FC<RadixDropdown.DropdownMenuPortalProps>;
9
+ declare const DropdownMenuSub: React.FC<RadixDropdown.DropdownMenuSubProps>;
10
+ declare const DropdownMenuRadioGroup: React.ForwardRefExoticComponent<RadixDropdown.DropdownMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
11
+ declare const DropdownMenuContent: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
12
+ declare const DropdownMenuSubContent: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
13
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
14
+ inset?: boolean;
15
+ } & React.RefAttributes<HTMLDivElement>>;
16
+ declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
17
+ declare const DropdownMenuRadioItem: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuRadioItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
18
+ declare const DropdownMenuSeparator: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
19
+ declare const DropdownMenuLabel: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
20
+ inset?: boolean;
21
+ } & React.RefAttributes<HTMLDivElement>>;
22
+ declare const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<Omit<RadixDropdown.DropdownMenuSubTriggerProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
23
+ inset?: boolean;
24
+ } & React.RefAttributes<HTMLDivElement>>;
25
+ declare const DropdownMenuShortcut: {
26
+ ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): import("react/jsx-runtime").JSX.Element;
27
+ displayName: string;
28
+ };
29
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, };