@emara/ui 1.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 (218) hide show
  1. package/components/ui/.gitkeep +0 -0
  2. package/components/ui/accordion.stories.tsx +231 -0
  3. package/components/ui/accordion.tsx +250 -0
  4. package/components/ui/app-shell.stories.tsx +270 -0
  5. package/components/ui/app-shell.tsx +491 -0
  6. package/components/ui/avatar.stories.tsx +174 -0
  7. package/components/ui/avatar.tsx +257 -0
  8. package/components/ui/badge.stories.tsx +127 -0
  9. package/components/ui/badge.tsx +146 -0
  10. package/components/ui/breadcrumb.stories.tsx +92 -0
  11. package/components/ui/breadcrumb.tsx +302 -0
  12. package/components/ui/button.stories.tsx +186 -0
  13. package/components/ui/button.tsx +128 -0
  14. package/components/ui/card.stories.tsx +279 -0
  15. package/components/ui/card.tsx +250 -0
  16. package/components/ui/checkbox.stories.tsx +93 -0
  17. package/components/ui/checkbox.tsx +131 -0
  18. package/components/ui/combobox.stories.tsx +489 -0
  19. package/components/ui/combobox.tsx +874 -0
  20. package/components/ui/context-menu.stories.tsx +202 -0
  21. package/components/ui/context-menu.tsx +309 -0
  22. package/components/ui/data-table.stories.tsx +227 -0
  23. package/components/ui/data-table.tsx +539 -0
  24. package/components/ui/date-picker.stories.tsx +225 -0
  25. package/components/ui/date-picker.tsx +597 -0
  26. package/components/ui/dialog.stories.tsx +193 -0
  27. package/components/ui/dialog.tsx +262 -0
  28. package/components/ui/divider.stories.tsx +84 -0
  29. package/components/ui/divider.tsx +135 -0
  30. package/components/ui/drawer.stories.tsx +218 -0
  31. package/components/ui/drawer.tsx +329 -0
  32. package/components/ui/dropdown-menu.stories.tsx +270 -0
  33. package/components/ui/dropdown-menu.tsx +353 -0
  34. package/components/ui/empty-state.stories.tsx +121 -0
  35. package/components/ui/empty-state.tsx +289 -0
  36. package/components/ui/field-group.stories.tsx +201 -0
  37. package/components/ui/field-group.tsx +276 -0
  38. package/components/ui/form.stories.tsx +219 -0
  39. package/components/ui/form.tsx +542 -0
  40. package/components/ui/input.stories.tsx +154 -0
  41. package/components/ui/input.tsx +208 -0
  42. package/components/ui/label.stories.tsx +84 -0
  43. package/components/ui/label.tsx +98 -0
  44. package/components/ui/page-header.stories.tsx +136 -0
  45. package/components/ui/page-header.tsx +315 -0
  46. package/components/ui/pagination.stories.tsx +136 -0
  47. package/components/ui/pagination.tsx +427 -0
  48. package/components/ui/popover.stories.tsx +212 -0
  49. package/components/ui/popover.tsx +167 -0
  50. package/components/ui/radio-group.stories.tsx +96 -0
  51. package/components/ui/radio-group.tsx +250 -0
  52. package/components/ui/select.stories.tsx +203 -0
  53. package/components/ui/select.tsx +318 -0
  54. package/components/ui/sidebar.stories.tsx +186 -0
  55. package/components/ui/sidebar.tsx +623 -0
  56. package/components/ui/skeleton.stories.tsx +131 -0
  57. package/components/ui/skeleton.tsx +311 -0
  58. package/components/ui/switch.stories.tsx +74 -0
  59. package/components/ui/switch.tsx +186 -0
  60. package/components/ui/table.stories.tsx +107 -0
  61. package/components/ui/table.tsx +285 -0
  62. package/components/ui/tabs.stories.tsx +222 -0
  63. package/components/ui/tabs.tsx +287 -0
  64. package/components/ui/textarea.stories.tsx +96 -0
  65. package/components/ui/textarea.tsx +182 -0
  66. package/components/ui/toast.stories.tsx +169 -0
  67. package/components/ui/toast.tsx +250 -0
  68. package/components/ui/tooltip.stories.tsx +146 -0
  69. package/components/ui/tooltip.tsx +156 -0
  70. package/components/ui/top-bar.stories.tsx +182 -0
  71. package/components/ui/top-bar.tsx +155 -0
  72. package/dist/components/ui/accordion.d.ts +45 -0
  73. package/dist/components/ui/accordion.d.ts.map +1 -0
  74. package/dist/components/ui/accordion.js +99 -0
  75. package/dist/components/ui/accordion.js.map +1 -0
  76. package/dist/components/ui/app-shell.d.ts +70 -0
  77. package/dist/components/ui/app-shell.d.ts.map +1 -0
  78. package/dist/components/ui/app-shell.js +199 -0
  79. package/dist/components/ui/app-shell.js.map +1 -0
  80. package/dist/components/ui/avatar.d.ts +41 -0
  81. package/dist/components/ui/avatar.d.ts.map +1 -0
  82. package/dist/components/ui/avatar.js +104 -0
  83. package/dist/components/ui/avatar.js.map +1 -0
  84. package/dist/components/ui/badge.d.ts +27 -0
  85. package/dist/components/ui/badge.d.ts.map +1 -0
  86. package/dist/components/ui/badge.js +65 -0
  87. package/dist/components/ui/badge.js.map +1 -0
  88. package/dist/components/ui/breadcrumb.d.ts +35 -0
  89. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  90. package/dist/components/ui/breadcrumb.js +88 -0
  91. package/dist/components/ui/breadcrumb.js.map +1 -0
  92. package/dist/components/ui/button.d.ts +26 -0
  93. package/dist/components/ui/button.d.ts.map +1 -0
  94. package/dist/components/ui/button.js +73 -0
  95. package/dist/components/ui/button.js.map +1 -0
  96. package/dist/components/ui/card.d.ts +52 -0
  97. package/dist/components/ui/card.d.ts.map +1 -0
  98. package/dist/components/ui/card.js +96 -0
  99. package/dist/components/ui/card.js.map +1 -0
  100. package/dist/components/ui/checkbox.d.ts +18 -0
  101. package/dist/components/ui/checkbox.d.ts.map +1 -0
  102. package/dist/components/ui/checkbox.js +59 -0
  103. package/dist/components/ui/checkbox.js.map +1 -0
  104. package/dist/components/ui/combobox.d.ts +194 -0
  105. package/dist/components/ui/combobox.d.ts.map +1 -0
  106. package/dist/components/ui/combobox.js +361 -0
  107. package/dist/components/ui/combobox.js.map +1 -0
  108. package/dist/components/ui/context-menu.d.ts +46 -0
  109. package/dist/components/ui/context-menu.d.ts.map +1 -0
  110. package/dist/components/ui/context-menu.js +95 -0
  111. package/dist/components/ui/context-menu.js.map +1 -0
  112. package/dist/components/ui/data-table.d.ts +53 -0
  113. package/dist/components/ui/data-table.d.ts.map +1 -0
  114. package/dist/components/ui/data-table.js +163 -0
  115. package/dist/components/ui/data-table.js.map +1 -0
  116. package/dist/components/ui/date-picker.d.ts +103 -0
  117. package/dist/components/ui/date-picker.d.ts.map +1 -0
  118. package/dist/components/ui/date-picker.js +306 -0
  119. package/dist/components/ui/date-picker.js.map +1 -0
  120. package/dist/components/ui/dialog.d.ts +40 -0
  121. package/dist/components/ui/dialog.d.ts.map +1 -0
  122. package/dist/components/ui/dialog.js +110 -0
  123. package/dist/components/ui/dialog.js.map +1 -0
  124. package/dist/components/ui/divider.d.ts +30 -0
  125. package/dist/components/ui/divider.d.ts.map +1 -0
  126. package/dist/components/ui/divider.js +62 -0
  127. package/dist/components/ui/divider.js.map +1 -0
  128. package/dist/components/ui/drawer.d.ts +56 -0
  129. package/dist/components/ui/drawer.d.ts.map +1 -0
  130. package/dist/components/ui/drawer.js +147 -0
  131. package/dist/components/ui/drawer.js.map +1 -0
  132. package/dist/components/ui/dropdown-menu.d.ts +63 -0
  133. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  134. package/dist/components/ui/dropdown-menu.js +116 -0
  135. package/dist/components/ui/dropdown-menu.js.map +1 -0
  136. package/dist/components/ui/empty-state.d.ts +43 -0
  137. package/dist/components/ui/empty-state.d.ts.map +1 -0
  138. package/dist/components/ui/empty-state.js +128 -0
  139. package/dist/components/ui/empty-state.js.map +1 -0
  140. package/dist/components/ui/field-group.d.ts +38 -0
  141. package/dist/components/ui/field-group.d.ts.map +1 -0
  142. package/dist/components/ui/field-group.js +107 -0
  143. package/dist/components/ui/field-group.js.map +1 -0
  144. package/dist/components/ui/form.d.ts +67 -0
  145. package/dist/components/ui/form.d.ts.map +1 -0
  146. package/dist/components/ui/form.js +286 -0
  147. package/dist/components/ui/form.js.map +1 -0
  148. package/dist/components/ui/input.d.ts +36 -0
  149. package/dist/components/ui/input.d.ts.map +1 -0
  150. package/dist/components/ui/input.js +99 -0
  151. package/dist/components/ui/input.js.map +1 -0
  152. package/dist/components/ui/label.d.ts +37 -0
  153. package/dist/components/ui/label.d.ts.map +1 -0
  154. package/dist/components/ui/label.js +34 -0
  155. package/dist/components/ui/label.js.map +1 -0
  156. package/dist/components/ui/page-header.d.ts +65 -0
  157. package/dist/components/ui/page-header.d.ts.map +1 -0
  158. package/dist/components/ui/page-header.js +140 -0
  159. package/dist/components/ui/page-header.js.map +1 -0
  160. package/dist/components/ui/pagination.d.ts +67 -0
  161. package/dist/components/ui/pagination.d.ts.map +1 -0
  162. package/dist/components/ui/pagination.js +109 -0
  163. package/dist/components/ui/pagination.js.map +1 -0
  164. package/dist/components/ui/popover.d.ts +28 -0
  165. package/dist/components/ui/popover.d.ts.map +1 -0
  166. package/dist/components/ui/popover.js +85 -0
  167. package/dist/components/ui/popover.js.map +1 -0
  168. package/dist/components/ui/radio-group.d.ts +35 -0
  169. package/dist/components/ui/radio-group.d.ts.map +1 -0
  170. package/dist/components/ui/radio-group.js +103 -0
  171. package/dist/components/ui/radio-group.js.map +1 -0
  172. package/dist/components/ui/select.d.ts +42 -0
  173. package/dist/components/ui/select.d.ts.map +1 -0
  174. package/dist/components/ui/select.js +86 -0
  175. package/dist/components/ui/select.js.map +1 -0
  176. package/dist/components/ui/sidebar.d.ts +59 -0
  177. package/dist/components/ui/sidebar.d.ts.map +1 -0
  178. package/dist/components/ui/sidebar.js +189 -0
  179. package/dist/components/ui/sidebar.js.map +1 -0
  180. package/dist/components/ui/skeleton.d.ts +77 -0
  181. package/dist/components/ui/skeleton.d.ts.map +1 -0
  182. package/dist/components/ui/skeleton.js +115 -0
  183. package/dist/components/ui/skeleton.js.map +1 -0
  184. package/dist/components/ui/switch.d.ts +26 -0
  185. package/dist/components/ui/switch.d.ts.map +1 -0
  186. package/dist/components/ui/switch.js +84 -0
  187. package/dist/components/ui/switch.js.map +1 -0
  188. package/dist/components/ui/table.d.ts +52 -0
  189. package/dist/components/ui/table.d.ts.map +1 -0
  190. package/dist/components/ui/table.js +109 -0
  191. package/dist/components/ui/table.js.map +1 -0
  192. package/dist/components/ui/tabs.d.ts +42 -0
  193. package/dist/components/ui/tabs.d.ts.map +1 -0
  194. package/dist/components/ui/tabs.js +163 -0
  195. package/dist/components/ui/tabs.js.map +1 -0
  196. package/dist/components/ui/textarea.d.ts +26 -0
  197. package/dist/components/ui/textarea.d.ts.map +1 -0
  198. package/dist/components/ui/textarea.js +96 -0
  199. package/dist/components/ui/textarea.js.map +1 -0
  200. package/dist/components/ui/toast.d.ts +77 -0
  201. package/dist/components/ui/toast.d.ts.map +1 -0
  202. package/dist/components/ui/toast.js +141 -0
  203. package/dist/components/ui/toast.js.map +1 -0
  204. package/dist/components/ui/tooltip.d.ts +31 -0
  205. package/dist/components/ui/tooltip.d.ts.map +1 -0
  206. package/dist/components/ui/tooltip.js +71 -0
  207. package/dist/components/ui/tooltip.js.map +1 -0
  208. package/dist/components/ui/top-bar.d.ts +30 -0
  209. package/dist/components/ui/top-bar.d.ts.map +1 -0
  210. package/dist/components/ui/top-bar.js +64 -0
  211. package/dist/components/ui/top-bar.js.map +1 -0
  212. package/dist/lib/utils.d.ts +3 -0
  213. package/dist/lib/utils.d.ts.map +1 -0
  214. package/dist/lib/utils.js +6 -0
  215. package/dist/lib/utils.js.map +1 -0
  216. package/lib/utils.ts +6 -0
  217. package/package.json +112 -0
  218. package/styles/globals.css +685 -0
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useId, useRef, useState } from "react";
4
+ import { Slot } from "@radix-ui/react-slot";
5
+ import { RiCloseLine, RiLoader2Line } from "@remixicon/react";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@/lib/utils";
8
+ // Per docs/emara-ui-phase-1-components.md §2.
9
+ const inputWrapperVariants = cva([
10
+ "relative flex items-center w-full gap-2 ps-3 pe-3",
11
+ "rounded-md border border-input bg-background text-foreground",
12
+ "transition-colors",
13
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background",
14
+ "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50",
15
+ ].join(" "), {
16
+ variants: {
17
+ size: {
18
+ xs: "h-7 text-xs",
19
+ sm: "h-8 text-xs",
20
+ md: "h-9 text-sm",
21
+ lg: "h-10 text-base",
22
+ xl: "h-12 text-base",
23
+ },
24
+ invalid: {
25
+ true: "border-destructive focus-within:ring-destructive",
26
+ false: "",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ size: "md",
31
+ invalid: false,
32
+ },
33
+ });
34
+ const inputFieldVariants = cva([
35
+ // The wrapper owns horizontal padding + gap. The field itself is flush
36
+ // inside the wrapper so adornments sit at the natural visual distance.
37
+ "block w-full min-w-0 bg-transparent text-foreground placeholder:text-muted-foreground",
38
+ "focus:outline-none disabled:cursor-not-allowed",
39
+ // Hide the spinner only for type=number. Other types keep their native
40
+ // chrome (search's clear button, date pickers, etc.).
41
+ "[&[type='number']]:[appearance:textfield]",
42
+ "[&[type='number']::-webkit-outer-spin-button]:appearance-none",
43
+ "[&[type='number']::-webkit-inner-spin-button]:appearance-none",
44
+ ].join(" "), {
45
+ variants: {
46
+ size: {
47
+ xs: "h-7",
48
+ sm: "h-8",
49
+ md: "h-9",
50
+ lg: "h-10",
51
+ xl: "h-12",
52
+ },
53
+ },
54
+ defaultVariants: {
55
+ size: "md",
56
+ },
57
+ });
58
+ const Input = forwardRef(function Input({ className, wrapperClassName, size, type = "text", invalid = false, startAdornment, endAdornment, clearable = false, loading = false, onClear, asChild = false, value, defaultValue, onChange, disabled, readOnly, id, children, "aria-describedby": ariaDescribedBy, ...props }, forwardedRef) {
59
+ const isControlled = value !== undefined;
60
+ const [uncontrolledValue, setUncontrolledValue] = useState(typeof defaultValue === "string" ? defaultValue : "");
61
+ const currentValue = isControlled ? String(value ?? "") : uncontrolledValue;
62
+ const showClear = clearable && !disabled && !readOnly && !loading && currentValue.length > 0;
63
+ const innerRef = useRef(null);
64
+ const setRefs = (node) => {
65
+ innerRef.current = node;
66
+ if (typeof forwardedRef === "function")
67
+ forwardedRef(node);
68
+ else if (forwardedRef)
69
+ forwardedRef.current = node;
70
+ };
71
+ const reactId = useId();
72
+ const inputId = id ?? reactId;
73
+ const handleChange = (e) => {
74
+ if (!isControlled)
75
+ setUncontrolledValue(e.target.value);
76
+ onChange?.(e);
77
+ };
78
+ const handleClear = () => {
79
+ if (!isControlled)
80
+ setUncontrolledValue("");
81
+ onClear?.();
82
+ const node = innerRef.current;
83
+ if (node) {
84
+ const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
85
+ nativeSetter?.call(node, "");
86
+ node.dispatchEvent(new Event("input", { bubbles: true }));
87
+ node.focus();
88
+ }
89
+ };
90
+ const hasEndContent = showClear || loading || endAdornment;
91
+ // When `asChild` is true the consumer provides their own input-like element
92
+ // as `children`; Slot forwards Input's props onto it. Otherwise we render a
93
+ // native <input>.
94
+ const Field = asChild ? Slot : "input";
95
+ return (_jsxs("div", { className: cn(inputWrapperVariants({ size, invalid }), wrapperClassName), children: [startAdornment ? (_jsx("span", { className: "text-muted-foreground pointer-events-none flex shrink-0 items-center [&_svg]:size-4 [&_svg]:shrink-0", "aria-hidden": typeof startAdornment !== "string", children: startAdornment })) : null, _jsx(Field, { ref: setRefs, id: inputId, type: type, className: cn(inputFieldVariants({ size }), className), disabled: disabled, readOnly: readOnly, "aria-invalid": invalid || undefined, "aria-describedby": ariaDescribedBy, value: isControlled ? currentValue : undefined, defaultValue: isControlled ? undefined : defaultValue, onChange: handleChange, ...props, children: asChild ? children : null }), hasEndContent ? (_jsxs("span", { className: "text-muted-foreground flex shrink-0 items-center gap-1 [&_svg]:size-4 [&_svg]:shrink-0", children: [showClear ? (_jsx("button", { type: "button", onClick: handleClear, "aria-label": "Clear", className: cn("inline-flex items-center justify-center rounded p-0.5", "text-muted-foreground hover:text-foreground", "focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none"), children: _jsx(RiCloseLine, {}) })) : null, loading ? _jsx(RiLoader2Line, { className: "animate-spin" }) : null, endAdornment ? (_jsx("span", { "aria-hidden": typeof endAdornment !== "string", children: endAdornment })) : null] })) : null] }));
96
+ });
97
+ Input.displayName = "Input";
98
+ export { Input, inputWrapperVariants, inputFieldVariants };
99
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../components/ui/input.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import * as LabelPrimitive from "@radix-ui/react-label";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const labelVariants: (props?: ({
4
+ size?: "sm" | "md" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ type LabelVariants = VariantProps<typeof labelVariants>;
7
+ type LabelProps = Omit<React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, "asChild"> & LabelVariants & {
8
+ required?: boolean;
9
+ optional?: boolean;
10
+ /**
11
+ * Localized text shown when `optional` is true. Defaults to "(optional)".
12
+ */
13
+ optionalText?: string;
14
+ /**
15
+ * Info-icon-with-tooltip rendered at the end of the label. The hint must
16
+ * itself sit inside a `<TooltipProvider>` somewhere up the tree —
17
+ * `AppShell` provides one for the whole app; otherwise wrap a section.
18
+ */
19
+ hint?: React.ReactNode;
20
+ };
21
+ declare const Label: import("react").ForwardRefExoticComponent<Omit<Omit<LabelPrimitive.LabelProps & import("react").RefAttributes<HTMLLabelElement>, "ref">, "asChild"> & LabelVariants & {
22
+ required?: boolean;
23
+ optional?: boolean;
24
+ /**
25
+ * Localized text shown when `optional` is true. Defaults to "(optional)".
26
+ */
27
+ optionalText?: string;
28
+ /**
29
+ * Info-icon-with-tooltip rendered at the end of the label. The hint must
30
+ * itself sit inside a `<TooltipProvider>` somewhere up the tree —
31
+ * `AppShell` provides one for the whole app; otherwise wrap a section.
32
+ */
33
+ hint?: React.ReactNode;
34
+ } & import("react").RefAttributes<HTMLLabelElement>>;
35
+ export { Label, labelVariants };
36
+ export type { LabelProps };
37
+ //# sourceMappingURL=label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../components/ui/label.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAOlE,QAAA,MAAM,aAAa;;8EAkBlB,CAAC;AAEF,KAAK,aAAa,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAExD,KAAK,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,cAAc,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,GAC3F,aAAa,GAAG;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB,CAAC;AAEJ,QAAA,MAAM,KAAK;eAdI,OAAO;eACP,OAAO;IAClB;;OAEG;mBACY,MAAM;IACrB;;;;OAIG;WACI,KAAK,CAAC,SAAS;oDA8CxB,CAAC;AAGH,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef } from "react";
4
+ import * as LabelPrimitive from "@radix-ui/react-label";
5
+ import { RiInformationLine } from "@remixicon/react";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@/lib/utils";
8
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip";
9
+ // Per docs/emara-ui-phase-1-components.md §4.
10
+ const labelVariants = cva([
11
+ "inline-flex items-center gap-1 font-medium text-foreground select-none",
12
+ // Inherits disabled appearance from the associated control.
13
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
14
+ "group-data-[disabled=true]:cursor-not-allowed group-data-[disabled=true]:opacity-50",
15
+ ].join(" "), {
16
+ variants: {
17
+ size: {
18
+ sm: "text-xs",
19
+ md: "text-sm",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ size: "md",
24
+ },
25
+ });
26
+ const Label = forwardRef(function Label({ className, size, required, optional, optionalText = "(optional)", hint, children, ...props }, ref) {
27
+ if (required && optional) {
28
+ throw new Error("Label: `required` and `optional` are mutually exclusive.");
29
+ }
30
+ return (_jsxs(LabelPrimitive.Root, { ref: ref, className: cn(labelVariants({ size }), className), ...props, children: [_jsx("span", { children: children }), required ? (_jsx("span", { "aria-hidden": "true", className: "text-destructive ms-0.5", children: "*" })) : null, optional ? (_jsx("span", { className: "text-muted-foreground ms-1 font-normal", children: optionalText })) : null, hint !== undefined && hint !== null ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", tabIndex: 0, "aria-label": "More info", className: cn("ms-1 inline-flex items-center justify-center rounded-full", "text-muted-foreground hover:text-foreground", "focus-visible:ring-ring focus-visible:ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none", "[&_svg]:size-3.5 [&_svg]:shrink-0"), children: _jsx(RiInformationLine, {}) }) }), _jsx(TooltipContent, { multiline: true, maxWidth: 240, children: hint })] })) : null] }));
31
+ });
32
+ Label.displayName = "Label";
33
+ export { Label, labelVariants };
34
+ //# sourceMappingURL=label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.js","sourceRoot":"","sources":["../../../components/ui/label.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEpE,8CAA8C;AAE9C,MAAM,aAAa,GAAG,GAAG,CACvB;IACE,wEAAwE;IACxE,4DAA4D;IAC5D,2DAA2D;IAC3D,qFAAqF;CACtF,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;IACE,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,EAAE,EAAE,SAAS;YACb,EAAE,EAAE,SAAS;SACd;KACF;IACD,eAAe,EAAE;QACf,IAAI,EAAE,IAAI;KACX;CACF,CACF,CAAC;AAoBF,MAAM,KAAK,GAAG,UAAU,CAA2D,SAAS,KAAK,CAC/F,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAC9F,GAAG;IAEH,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,CACL,MAAC,cAAc,CAAC,IAAI,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,KAAM,KAAK,aACzF,yBAAO,QAAQ,GAAQ,EACtB,QAAQ,CAAC,CAAC,CAAC,CACV,8BAAkB,MAAM,EAAC,SAAS,EAAC,yBAAyB,kBAErD,CACR,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,CAAC,CAAC,CAAC,CACV,eAAM,SAAS,EAAC,wCAAwC,YAAE,YAAY,GAAQ,CAC/E,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CACrC,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,iBACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,gBACA,WAAW,EACtB,SAAS,EAAE,EAAE,CACX,2DAA2D,EAC3D,6CAA6C,EAC7C,0IAA0I,EAC1I,mCAAmC,CACpC,YAED,KAAC,iBAAiB,KAAG,GACd,GACM,EACjB,KAAC,cAAc,IAAC,SAAS,QAAC,QAAQ,EAAE,GAAG,YACpC,IAAI,GACU,IACT,CACX,CAAC,CAAC,CAAC,IAAI,IACY,CACvB,CAAC;AACJ,CAAC,CAAC,CAAC;AACH,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC;AAE5B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ import { Button } from "./button";
3
+ declare const rootVariants: (props?: ({
4
+ variant?: "default" | "compact" | "splash" | null | undefined;
5
+ size?: "sm" | "md" | "lg" | null | undefined;
6
+ divider?: boolean | null | undefined;
7
+ sticky?: boolean | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ type RootVariants = VariantProps<typeof rootVariants>;
10
+ type PageHeaderProps = Omit<React.HTMLAttributes<HTMLElement>, "title"> & RootVariants & {
11
+ asChild?: boolean;
12
+ /** Convenience: rendered as PageHeaderTitle (with `as="h1"`). */
13
+ title?: React.ReactNode;
14
+ /** Convenience: rendered as PageHeaderDescription. */
15
+ description?: React.ReactNode;
16
+ /** Convenience: slot for breadcrumb (`<Breadcrumbs />` or primitives). */
17
+ breadcrumb?: React.ReactNode;
18
+ /** Convenience: rendered into PageHeaderActions. */
19
+ actions?: React.ReactNode;
20
+ /** Convenience: renders a default back button linking here. */
21
+ backHref?: string;
22
+ /** Localized aria-label for the auto-injected BackButton. Default "Back". */
23
+ backLabel?: string;
24
+ /** Convenience: rendered as PageHeaderTabs. */
25
+ tabs?: React.ReactNode;
26
+ };
27
+ declare const PageHeader: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<HTMLElement>, "title"> & RootVariants & {
28
+ asChild?: boolean;
29
+ /** Convenience: rendered as PageHeaderTitle (with `as="h1"`). */
30
+ title?: React.ReactNode;
31
+ /** Convenience: rendered as PageHeaderDescription. */
32
+ description?: React.ReactNode;
33
+ /** Convenience: slot for breadcrumb (`<Breadcrumbs />` or primitives). */
34
+ breadcrumb?: React.ReactNode;
35
+ /** Convenience: rendered into PageHeaderActions. */
36
+ actions?: React.ReactNode;
37
+ /** Convenience: renders a default back button linking here. */
38
+ backHref?: string;
39
+ /** Localized aria-label for the auto-injected BackButton. Default "Back". */
40
+ backLabel?: string;
41
+ /** Convenience: rendered as PageHeaderTabs. */
42
+ tabs?: React.ReactNode;
43
+ } & import("react").RefAttributes<HTMLElement>>;
44
+ declare const PageHeaderBreadcrumb: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
45
+ declare const PageHeaderTop: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
46
+ type PageHeaderBackButtonProps = Omit<React.ComponentProps<typeof Button>, "size"> & {
47
+ /** Required: where to go back to. */
48
+ href: string;
49
+ /** aria-label. Default "Back". */
50
+ label?: string;
51
+ };
52
+ declare const PageHeaderBackButton: import("react").ForwardRefExoticComponent<Omit<PageHeaderBackButtonProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
53
+ type PageHeaderTitleProps = React.HTMLAttributes<HTMLHeadingElement> & {
54
+ as?: "h1" | "h2";
55
+ };
56
+ declare const PageHeaderTitle: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLHeadingElement> & {
57
+ as?: "h1" | "h2";
58
+ } & import("react").RefAttributes<HTMLHeadingElement>>;
59
+ declare const PageHeaderBadge: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
60
+ declare const PageHeaderActions: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
61
+ declare const PageHeaderDescription: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
62
+ declare const PageHeaderTabs: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
63
+ export { PageHeader, PageHeaderBreadcrumb, PageHeaderTop, PageHeaderBackButton, PageHeaderTitle, PageHeaderBadge, PageHeaderActions, PageHeaderDescription, PageHeaderTabs, };
64
+ export type { PageHeaderProps, PageHeaderTitleProps, PageHeaderBackButtonProps };
65
+ //# sourceMappingURL=page-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../../../components/ui/page-header.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAsBlC,QAAA,MAAM,YAAY;;;;;8EA2BhB,CAAC;AAEH,KAAK,YAAY,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AAEtD,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GACrE,YAAY,GAAG;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,sDAAsD;IACtD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,oDAAoD;IACpD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB,CAAC;AAEJ,QAAA,MAAM,UAAU;cAjBF,OAAO;IACjB,iEAAiE;YACzD,KAAK,CAAC,SAAS;IACvB,sDAAsD;kBACxC,KAAK,CAAC,SAAS;IAC7B,0EAA0E;iBAC7D,KAAK,CAAC,SAAS;IAC5B,oDAAoD;cAC1C,KAAK,CAAC,SAAS;IACzB,+DAA+D;eACpD,MAAM;IACjB,6EAA6E;gBACjE,MAAM;IAClB,+CAA+C;WACxC,KAAK,CAAC,SAAS;+CAgExB,CAAC;AAKH,QAAA,MAAM,oBAAoB,2IAIzB,CAAC;AAKF,QAAA,MAAM,aAAa,2IAMlB,CAAC;AAKF,KAAK,yBAAyB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG;IACnF,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,QAAA,MAAM,oBAAoB,sIAmBzB,CAAC;AAgCF,KAAK,oBAAoB,GAAG,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,GAAG;IACrE,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAClB,CAAC;AAEF,QAAA,MAAM,eAAe;SAHd,IAAI,GAAG,IAAI;sDAUjB,CAAC;AAKF,QAAA,MAAM,eAAe,6IAIpB,CAAC;AAKF,QAAA,MAAM,iBAAiB,2IAMtB,CAAC;AAgBF,QAAA,MAAM,qBAAqB,uJAYzB,CAAC;AAKH,QAAA,MAAM,cAAc,2IAYnB,CAAC;AAGF,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,GACf,CAAC;AACF,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,CAAC"}
@@ -0,0 +1,140 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { createContext, forwardRef, useContext, useMemo } from "react";
4
+ import { Slot } from "@radix-ui/react-slot";
5
+ import { RiArrowLeftSLine } from "@remixicon/react";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@/lib/utils";
8
+ import { Button } from "./button";
9
+ const PageHeaderContext = createContext(null);
10
+ function usePageHeader() {
11
+ const ctx = useContext(PageHeaderContext);
12
+ if (!ctx)
13
+ throw new Error("PageHeader subcomponents must be used inside <PageHeader>");
14
+ return ctx;
15
+ }
16
+ // ---- Root ------------------------------------------------------------------
17
+ const rootVariants = cva("w-full", {
18
+ variants: {
19
+ variant: {
20
+ default: "",
21
+ compact: "",
22
+ splash: "",
23
+ },
24
+ size: {
25
+ sm: "",
26
+ md: "",
27
+ lg: "",
28
+ },
29
+ divider: { true: "border-b border-border", false: "" },
30
+ sticky: { true: "sticky top-0 z-sticky bg-background/95 backdrop-blur", false: "" },
31
+ },
32
+ compoundVariants: [
33
+ { variant: "default", size: "sm", class: "py-3 space-y-2" },
34
+ { variant: "default", size: "md", class: "py-4 space-y-3" },
35
+ { variant: "default", size: "lg", class: "py-6 space-y-4" },
36
+ { variant: "compact", size: "sm", class: "py-2 space-y-1" },
37
+ { variant: "compact", size: "md", class: "py-2.5 space-y-1" },
38
+ { variant: "compact", size: "lg", class: "py-3 space-y-2" },
39
+ { variant: "splash", size: "sm", class: "py-6 space-y-3" },
40
+ { variant: "splash", size: "md", class: "py-10 space-y-4" },
41
+ { variant: "splash", size: "lg", class: "py-14 space-y-6" },
42
+ ],
43
+ defaultVariants: { variant: "default", size: "md", divider: false, sticky: false },
44
+ });
45
+ const PageHeader = forwardRef(function PageHeader({ className, variant = "default", size = "md", divider = false, sticky = false, asChild = false, title, description, breadcrumb, actions, backHref, backLabel = "Back", tabs, children, ...props }, ref) {
46
+ const Comp = asChild ? Slot : "header";
47
+ const resolvedVariant = variant ?? "default";
48
+ const resolvedSize = size ?? "md";
49
+ const ctx = useMemo(() => ({ variant: resolvedVariant, size: resolvedSize }), [resolvedVariant, resolvedSize]);
50
+ const usingConvenience = title !== undefined ||
51
+ description !== undefined ||
52
+ breadcrumb !== undefined ||
53
+ actions !== undefined ||
54
+ backHref !== undefined ||
55
+ tabs !== undefined;
56
+ return (_jsx(PageHeaderContext.Provider, { value: ctx, children: _jsx(Comp, { ref: ref, className: cn(rootVariants({ variant, size, divider, sticky }), className), ...props, children: usingConvenience ? (_jsxs(_Fragment, { children: [breadcrumb ? _jsx(PageHeaderBreadcrumb, { children: breadcrumb }) : null, _jsxs(PageHeaderTop, { children: [backHref ? _jsx(PageHeaderBackButton, { href: backHref, label: backLabel }) : null, title ? _jsx(PageHeaderTitle, { children: title }) : null, _jsx("span", { className: "flex-1" }), actions ? _jsx(PageHeaderActions, { children: actions }) : null] }), description ? _jsx(PageHeaderDescription, { children: description }) : null, tabs ? _jsx(PageHeaderTabs, { children: tabs }) : null] })) : (children) }) }));
57
+ });
58
+ PageHeader.displayName = "PageHeader";
59
+ // ---- Breadcrumb slot -------------------------------------------------------
60
+ const PageHeaderBreadcrumb = forwardRef(function PageHeaderBreadcrumb({ className, ...props }, ref) {
61
+ return _jsx("div", { ref: ref, className: cn("text-sm", className), ...props });
62
+ });
63
+ PageHeaderBreadcrumb.displayName = "PageHeaderBreadcrumb";
64
+ // ---- Top (back + title + actions row) --------------------------------------
65
+ const PageHeaderTop = forwardRef(function PageHeaderTop({ className, ...props }, ref) {
66
+ return (_jsx("div", { ref: ref, className: cn("flex flex-wrap items-center gap-3", className), ...props }));
67
+ });
68
+ PageHeaderTop.displayName = "PageHeaderTop";
69
+ const PageHeaderBackButton = forwardRef(function PageHeaderBackButton({ className, href, label = "Back", children, ...props }, ref) {
70
+ return (_jsx(Button, { ref: ref, asChild: true, variant: "ghost", size: "icon-sm", "aria-label": label, className: cn(className), ...props, children: _jsxs("a", { href: href, children: [_jsx(RiArrowLeftSLine, { className: "rtl-mirror" }), children ? _jsx("span", { className: "ms-1", children: children }) : null] }) }));
71
+ });
72
+ PageHeaderBackButton.displayName = "PageHeaderBackButton";
73
+ // ---- Title -----------------------------------------------------------------
74
+ const titleVariants = cva("font-semibold tracking-tight text-foreground", {
75
+ variants: {
76
+ variant: {
77
+ default: "",
78
+ compact: "",
79
+ splash: "",
80
+ },
81
+ size: {
82
+ sm: "",
83
+ md: "",
84
+ lg: "",
85
+ },
86
+ },
87
+ compoundVariants: [
88
+ { variant: "default", size: "sm", class: "text-lg" },
89
+ { variant: "default", size: "md", class: "text-2xl" },
90
+ { variant: "default", size: "lg", class: "text-3xl" },
91
+ { variant: "compact", size: "sm", class: "text-base" },
92
+ { variant: "compact", size: "md", class: "text-lg" },
93
+ { variant: "compact", size: "lg", class: "text-xl" },
94
+ { variant: "splash", size: "sm", class: "text-2xl" },
95
+ { variant: "splash", size: "md", class: "text-4xl" },
96
+ { variant: "splash", size: "lg", class: "text-5xl" },
97
+ ],
98
+ defaultVariants: { variant: "default", size: "md" },
99
+ });
100
+ const PageHeaderTitle = forwardRef(function PageHeaderTitle({ as: Heading = "h1", className, ...props }, ref) {
101
+ const { variant, size } = usePageHeader();
102
+ return (_jsx(Heading, { ref: ref, className: cn(titleVariants({ variant, size }), className), ...props }));
103
+ });
104
+ PageHeaderTitle.displayName = "PageHeaderTitle";
105
+ // ---- Badge slot (next to title) -------------------------------------------
106
+ const PageHeaderBadge = forwardRef(function PageHeaderBadge({ className, ...props }, ref) {
107
+ return _jsx("span", { ref: ref, className: cn("inline-flex items-center", className), ...props });
108
+ });
109
+ PageHeaderBadge.displayName = "PageHeaderBadge";
110
+ // ---- Actions ---------------------------------------------------------------
111
+ const PageHeaderActions = forwardRef(function PageHeaderActions({ className, ...props }, ref) {
112
+ return (_jsx("div", { ref: ref, className: cn("flex flex-wrap items-center gap-2", className), ...props }));
113
+ });
114
+ PageHeaderActions.displayName = "PageHeaderActions";
115
+ // ---- Description -----------------------------------------------------------
116
+ const descriptionVariants = cva("text-muted-foreground", {
117
+ variants: {
118
+ size: {
119
+ sm: "text-xs",
120
+ md: "text-sm",
121
+ lg: "text-base",
122
+ },
123
+ },
124
+ defaultVariants: { size: "md" },
125
+ });
126
+ const PageHeaderDescription = forwardRef(function PageHeaderDescription({ className, ...props }, ref) {
127
+ const { size } = usePageHeader();
128
+ return (_jsx("p", { ref: ref, className: cn(descriptionVariants({ size }), "max-w-prose", className), ...props }));
129
+ });
130
+ PageHeaderDescription.displayName = "PageHeaderDescription";
131
+ // ---- Tabs slot (no padding underneath) ------------------------------------
132
+ const PageHeaderTabs = forwardRef(function PageHeaderTabs({ className, ...props }, ref) {
133
+ return (_jsx("div", { ref: ref,
134
+ // The slot sits flush with the bottom edge so a `divider` line passes
135
+ // under the active tab indicator.
136
+ className: cn("-mb-px", className), ...props }));
137
+ });
138
+ PageHeaderTabs.displayName = "PageHeaderTabs";
139
+ export { PageHeader, PageHeaderBreadcrumb, PageHeaderTop, PageHeaderBackButton, PageHeaderTitle, PageHeaderBadge, PageHeaderActions, PageHeaderDescription, PageHeaderTabs, };
140
+ //# sourceMappingURL=page-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header.js","sourceRoot":"","sources":["../../../components/ui/page-header.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ declare const Pagination: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
3
+ declare const PaginationContent: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLUListElement> & import("react").RefAttributes<HTMLUListElement>>;
4
+ declare const PaginationItem: import("react").ForwardRefExoticComponent<import("react").LiHTMLAttributes<HTMLLIElement> & import("react").RefAttributes<HTMLLIElement>>;
5
+ declare const paginationLinkVariants: (props?: ({
6
+ size?: "sm" | "md" | "lg" | null | undefined;
7
+ active?: boolean | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ type PaginationLinkProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof paginationLinkVariants> & {
10
+ isActive?: boolean;
11
+ };
12
+ declare const PaginationLink: import("react").ForwardRefExoticComponent<import("react").ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
13
+ size?: "sm" | "md" | "lg" | null | undefined;
14
+ active?: boolean | null | undefined;
15
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
16
+ isActive?: boolean;
17
+ } & import("react").RefAttributes<HTMLButtonElement>>;
18
+ type PaginationDirectionalProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof paginationLinkVariants> & {
19
+ label?: string;
20
+ };
21
+ declare const PaginationPrevious: import("react").ForwardRefExoticComponent<import("react").ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
22
+ size?: "sm" | "md" | "lg" | null | undefined;
23
+ active?: boolean | null | undefined;
24
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
25
+ label?: string;
26
+ } & import("react").RefAttributes<HTMLButtonElement>>;
27
+ declare const PaginationNext: import("react").ForwardRefExoticComponent<import("react").ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
28
+ size?: "sm" | "md" | "lg" | null | undefined;
29
+ active?: boolean | null | undefined;
30
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
31
+ label?: string;
32
+ } & import("react").RefAttributes<HTMLButtonElement>>;
33
+ declare const PaginationFirst: import("react").ForwardRefExoticComponent<import("react").ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
34
+ size?: "sm" | "md" | "lg" | null | undefined;
35
+ active?: boolean | null | undefined;
36
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
37
+ label?: string;
38
+ } & import("react").RefAttributes<HTMLButtonElement>>;
39
+ declare const PaginationLast: import("react").ForwardRefExoticComponent<import("react").ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
40
+ size?: "sm" | "md" | "lg" | null | undefined;
41
+ active?: boolean | null | undefined;
42
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
43
+ label?: string;
44
+ } & import("react").RefAttributes<HTMLButtonElement>>;
45
+ declare const PaginationEllipsis: import("react").ForwardRefExoticComponent<import("react").HTMLAttributes<HTMLSpanElement> & import("react").RefAttributes<HTMLSpanElement>>;
46
+ interface DataPaginationProps {
47
+ page: number;
48
+ pageCount: number;
49
+ onPageChange: (page: number) => void;
50
+ pageSize?: number;
51
+ pageSizeOptions?: number[];
52
+ onPageSizeChange?: (size: number) => void;
53
+ totalItems?: number;
54
+ siblingCount?: number;
55
+ boundaryCount?: number;
56
+ showInfo?: boolean;
57
+ showPageSize?: boolean;
58
+ showFirstLast?: boolean;
59
+ size?: "sm" | "md" | "lg";
60
+ disabled?: boolean;
61
+ loading?: boolean;
62
+ className?: string;
63
+ }
64
+ declare const DataPagination: import("react").ForwardRefExoticComponent<DataPaginationProps & import("react").RefAttributes<HTMLElement>>;
65
+ export { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationFirst, PaginationLast, PaginationEllipsis, DataPagination, paginationLinkVariants, };
66
+ export type { PaginationLinkProps, PaginationDirectionalProps, DataPaginationProps };
67
+ //# sourceMappingURL=pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../../components/ui/pagination.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYlE,QAAA,MAAM,UAAU,qIAad,CAAC;AAGH,QAAA,MAAM,iBAAiB,+IAMtB,CAAC;AAGF,QAAA,MAAM,cAAc,2IAInB,CAAC;AAGF,QAAA,MAAM,sBAAsB;;;8EAiB3B,CAAC;AAEF,KAAK,mBAAmB,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GACtE,YAAY,CAAC,OAAO,sBAAsB,CAAC,GAAG;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEJ,QAAA,MAAM,cAAc;;;;eAHL,OAAO;qDAiBpB,CAAC;AAKH,KAAK,0BAA0B,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAC7E,YAAY,CAAC,OAAO,sBAAsB,CAAC,GAAG;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEJ,QAAA,MAAM,kBAAkB;;;;YAHZ,MAAM;qDA0BjB,CAAC;AAGF,QAAA,MAAM,cAAc;;;;YA7BR,MAAM;qDAkDjB,CAAC;AAGF,QAAA,MAAM,eAAe;;;;YArDT,MAAM;qDA0EjB,CAAC;AAGF,QAAA,MAAM,cAAc;;;;YA7ER,MAAM;qDAkGjB,CAAC;AAGF,QAAA,MAAM,kBAAkB,6IAkBvB,CAAC;AAOF,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4CD,QAAA,MAAM,cAAc,6GA4HlB,CAAC;AAGH,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,sBAAsB,GACvB,CAAC;AACF,YAAY,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,109 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useMemo } from "react";
4
+ import { RiArrowLeftDoubleLine, RiArrowLeftSLine, RiArrowRightDoubleLine, RiArrowRightSLine, RiMoreLine, } from "@remixicon/react";
5
+ import { cva } from "class-variance-authority";
6
+ import { cn } from "@/lib/utils";
7
+ import { buttonVariants } from "./button";
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
9
+ // Per docs/emara-ui-phase-4-components.md §2.
10
+ // ===========================================================================
11
+ // 2.1 Primitives
12
+ // ===========================================================================
13
+ const Pagination = forwardRef(function Pagination({ className, ...props }, ref) {
14
+ return (_jsx("nav", { ref: ref, role: "navigation", "aria-label": "Pagination", className: cn("flex w-full items-center justify-between gap-3", className), ...props }));
15
+ });
16
+ Pagination.displayName = "Pagination";
17
+ const PaginationContent = forwardRef(function PaginationContent({ className, ...props }, ref) {
18
+ return (_jsx("ul", { ref: ref, className: cn("flex flex-row items-center gap-1", className), ...props }));
19
+ });
20
+ PaginationContent.displayName = "PaginationContent";
21
+ const PaginationItem = forwardRef(function PaginationItem({ className, ...props }, ref) {
22
+ return _jsx("li", { ref: ref, className: cn("", className), ...props });
23
+ });
24
+ PaginationItem.displayName = "PaginationItem";
25
+ const paginationLinkVariants = cva("inline-flex items-center justify-center select-none transition-colors gap-1 cursor-pointer disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", {
26
+ variants: {
27
+ size: {
28
+ sm: "h-8 min-w-8 text-xs rounded-md px-2.5",
29
+ md: "h-9 min-w-9 text-sm rounded-md px-3",
30
+ lg: "h-10 min-w-10 text-base rounded-md px-3.5",
31
+ },
32
+ active: {
33
+ true: "bg-primary text-primary-foreground hover:bg-primary/90",
34
+ false: "text-foreground hover:bg-accent hover:text-accent-foreground border border-input bg-background",
35
+ },
36
+ },
37
+ defaultVariants: { size: "md", active: false },
38
+ });
39
+ const PaginationLink = forwardRef(function PaginationLink({ className, size, active, isActive, type = "button", ...props }, ref) {
40
+ const resolvedActive = active ?? isActive ?? false;
41
+ return (_jsx("button", { ref: ref, type: type, "aria-current": resolvedActive ? "page" : undefined, className: cn(paginationLinkVariants({ size, active: resolvedActive }), className), ...props }));
42
+ });
43
+ PaginationLink.displayName = "PaginationLink";
44
+ const PaginationPrevious = forwardRef(function PaginationPrevious({ className, size, label = "Go to previous page", type = "button", ...props }, ref) {
45
+ // Use `buttonVariants` shape for outline look; primary visual is the link variant.
46
+ void buttonVariants;
47
+ return (_jsx("button", { ref: ref, type: type, "aria-label": label, className: cn(paginationLinkVariants({ size, active: false }), "[&_svg]:size-4 [&_svg]:shrink-0", className), ...props, children: _jsx(RiArrowLeftSLine, { className: "rtl-mirror" }) }));
48
+ });
49
+ PaginationPrevious.displayName = "PaginationPrevious";
50
+ const PaginationNext = forwardRef(function PaginationNext({ className, size, label = "Go to next page", type = "button", ...props }, ref) {
51
+ return (_jsx("button", { ref: ref, type: type, "aria-label": label, className: cn(paginationLinkVariants({ size, active: false }), "[&_svg]:size-4 [&_svg]:shrink-0", className), ...props, children: _jsx(RiArrowRightSLine, { className: "rtl-mirror" }) }));
52
+ });
53
+ PaginationNext.displayName = "PaginationNext";
54
+ const PaginationFirst = forwardRef(function PaginationFirst({ className, size, label = "Go to first page", type = "button", ...props }, ref) {
55
+ return (_jsx("button", { ref: ref, type: type, "aria-label": label, className: cn(paginationLinkVariants({ size, active: false }), "[&_svg]:size-4 [&_svg]:shrink-0", className), ...props, children: _jsx(RiArrowLeftDoubleLine, { className: "rtl-mirror" }) }));
56
+ });
57
+ PaginationFirst.displayName = "PaginationFirst";
58
+ const PaginationLast = forwardRef(function PaginationLast({ className, size, label = "Go to last page", type = "button", ...props }, ref) {
59
+ return (_jsx("button", { ref: ref, type: type, "aria-label": label, className: cn(paginationLinkVariants({ size, active: false }), "[&_svg]:size-4 [&_svg]:shrink-0", className), ...props, children: _jsx(RiArrowRightDoubleLine, { className: "rtl-mirror" }) }));
60
+ });
61
+ PaginationLast.displayName = "PaginationLast";
62
+ const PaginationEllipsis = forwardRef(function PaginationEllipsis({ className, ...props }, ref) {
63
+ return (_jsxs("span", { ref: ref, "aria-hidden": "true", className: cn("text-muted-foreground inline-flex h-9 min-w-9 items-center justify-center", "[&_svg]:size-4 [&_svg]:shrink-0", className), ...props, children: [_jsx(RiMoreLine, {}), _jsx("span", { className: "sr-only", children: "More pages" })] }));
64
+ });
65
+ PaginationEllipsis.displayName = "PaginationEllipsis";
66
+ /** Builds the list of page tokens to render. */
67
+ function buildPageList(page, pageCount, siblingCount, boundaryCount) {
68
+ if (pageCount <= 0)
69
+ return [];
70
+ const totalNumbers = siblingCount * 2 + boundaryCount * 2 + 3;
71
+ if (pageCount <= totalNumbers) {
72
+ return Array.from({ length: pageCount }, (_, i) => i + 1);
73
+ }
74
+ const startPages = Array.from({ length: boundaryCount }, (_, i) => i + 1);
75
+ const endPages = Array.from({ length: boundaryCount }, (_, i) => pageCount - boundaryCount + i + 1);
76
+ const siblingsStart = Math.max(Math.min(page - siblingCount, pageCount - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
77
+ const siblingsEnd = Math.min(Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2), pageCount - boundaryCount - 1);
78
+ const middle = Array.from({ length: Math.max(siblingsEnd - siblingsStart + 1, 0) }, (_, i) => siblingsStart + i);
79
+ const result = [...startPages];
80
+ if (siblingsStart > boundaryCount + 2)
81
+ result.push("ellipsis-start");
82
+ else if (boundaryCount + 1 < pageCount - boundaryCount)
83
+ result.push(boundaryCount + 1);
84
+ result.push(...middle);
85
+ if (siblingsEnd < pageCount - boundaryCount - 1)
86
+ result.push("ellipsis-end");
87
+ else if (pageCount - boundaryCount > boundaryCount)
88
+ result.push(pageCount - boundaryCount);
89
+ result.push(...endPages);
90
+ return Array.from(new Set(result));
91
+ }
92
+ const DataPagination = forwardRef(function DataPagination({ page, pageCount, onPageChange, pageSize, pageSizeOptions, onPageSizeChange, totalItems, siblingCount = 1, boundaryCount = 1, showInfo = true, showPageSize, showFirstLast = false, size = "md", disabled = false, loading = false, className, }, ref) {
93
+ const pages = useMemo(() => buildPageList(page, pageCount, siblingCount, boundaryCount), [page, pageCount, siblingCount, boundaryCount]);
94
+ const isDisabled = disabled || loading;
95
+ const onFirst = () => onPageChange(1);
96
+ const onPrev = () => onPageChange(Math.max(1, page - 1));
97
+ const onNext = () => onPageChange(Math.min(pageCount, page + 1));
98
+ const onLast = () => onPageChange(pageCount);
99
+ const start = pageSize && totalItems ? Math.min((page - 1) * pageSize + 1, totalItems) : null;
100
+ const end = pageSize && totalItems ? Math.min(page * pageSize, totalItems) : null;
101
+ const showSizeSelector = (showPageSize ?? Boolean(pageSizeOptions && pageSizeOptions.length > 0)) &&
102
+ pageSizeOptions &&
103
+ pageSize !== undefined &&
104
+ onPageSizeChange;
105
+ return (_jsxs(Pagination, { ref: ref, className: cn("flex-wrap gap-3", className), children: [showInfo && start !== null && end !== null && totalItems !== undefined ? (_jsxs("div", { className: "text-muted-foreground text-sm tabular-nums", "aria-live": "polite", "aria-atomic": "true", children: ["Showing ", start, "\u2013", end, " of ", totalItems] })) : (_jsx("span", {})), _jsxs(PaginationContent, { children: [showFirstLast ? (_jsx(PaginationItem, { children: _jsx(PaginationFirst, { size: size, onClick: onFirst, disabled: isDisabled || page <= 1 }) })) : null, _jsx(PaginationItem, { children: _jsx(PaginationPrevious, { size: size, onClick: onPrev, disabled: isDisabled || page <= 1 }) }), pages.map((p) => typeof p === "number" ? (_jsx(PaginationItem, { children: _jsx(PaginationLink, { size: size, isActive: p === page, "aria-label": `Go to page ${p}`, disabled: isDisabled, onClick: () => onPageChange(p), children: p }) }, p)) : (_jsx(PaginationItem, { children: _jsx(PaginationEllipsis, {}) }, p))), _jsx(PaginationItem, { children: _jsx(PaginationNext, { size: size, onClick: onNext, disabled: isDisabled || page >= pageCount }) }), showFirstLast ? (_jsx(PaginationItem, { children: _jsx(PaginationLast, { size: size, onClick: onLast, disabled: isDisabled || page >= pageCount }) })) : null] }), showSizeSelector ? (_jsxs(Select, { value: String(pageSize), onValueChange: (v) => onPageSizeChange?.(Number(v)), disabled: isDisabled, children: [_jsx(SelectTrigger, { size: size, "aria-label": "Rows per page", className: "w-auto", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: pageSizeOptions.map((opt) => (_jsxs(SelectItem, { value: String(opt), children: [opt, " per page"] }, opt))) })] })) : (_jsx("span", {}))] }));
106
+ });
107
+ DataPagination.displayName = "DataPagination";
108
+ export { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext, PaginationFirst, PaginationLast, PaginationEllipsis, DataPagination, paginationLinkVariants, };
109
+ //# sourceMappingURL=pagination.js.map