@gouno/ui 0.3.2

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 (231) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/LICENSE +21 -0
  3. package/README.md +144 -0
  4. package/dist/base.css +239 -0
  5. package/dist/bootstrap.js +22 -0
  6. package/dist/components/primitives/alert-dialog.d.ts +18 -0
  7. package/dist/components/primitives/alert-dialog.js +43 -0
  8. package/dist/components/primitives/alert.d.ts +9 -0
  9. package/dist/components/primitives/alert.js +25 -0
  10. package/dist/components/primitives/avatar.d.ts +14 -0
  11. package/dist/components/primitives/avatar.js +42 -0
  12. package/dist/components/primitives/badge.d.ts +9 -0
  13. package/dist/components/primitives/badge.js +25 -0
  14. package/dist/components/primitives/button.d.ts +10 -0
  15. package/dist/components/primitives/button.js +36 -0
  16. package/dist/components/primitives/checkbox.d.ts +4 -0
  17. package/dist/components/primitives/checkbox.js +10 -0
  18. package/dist/components/primitives/dialog.d.ts +20 -0
  19. package/dist/components/primitives/dialog.js +37 -0
  20. package/dist/components/primitives/dropdown-menu.d.ts +25 -0
  21. package/dist/components/primitives/dropdown-menu.js +51 -0
  22. package/dist/components/primitives/empty.d.ts +11 -0
  23. package/dist/components/primitives/empty.js +33 -0
  24. package/dist/components/primitives/field.d.ts +24 -0
  25. package/dist/components/primitives/field.js +75 -0
  26. package/dist/components/primitives/input.d.ts +3 -0
  27. package/dist/components/primitives/input.js +7 -0
  28. package/dist/components/primitives/label.d.ts +4 -0
  29. package/dist/components/primitives/label.js +8 -0
  30. package/dist/components/primitives/popover.d.ts +16 -0
  31. package/dist/components/primitives/popover.js +31 -0
  32. package/dist/components/primitives/radio-group.d.ts +5 -0
  33. package/dist/components/primitives/radio-group.js +13 -0
  34. package/dist/components/primitives/select.d.ts +15 -0
  35. package/dist/components/primitives/select.js +38 -0
  36. package/dist/components/primitives/separator.d.ts +4 -0
  37. package/dist/components/primitives/separator.js +8 -0
  38. package/dist/components/primitives/sheet.d.ts +17 -0
  39. package/dist/components/primitives/sheet.js +41 -0
  40. package/dist/components/primitives/skeleton.d.ts +2 -0
  41. package/dist/components/primitives/skeleton.js +6 -0
  42. package/dist/components/primitives/switch.d.ts +6 -0
  43. package/dist/components/primitives/switch.js +8 -0
  44. package/dist/components/primitives/table.d.ts +28 -0
  45. package/dist/components/primitives/table.js +44 -0
  46. package/dist/components/primitives/tabs.d.ts +11 -0
  47. package/dist/components/primitives/tabs.js +30 -0
  48. package/dist/components/primitives/textarea.d.ts +3 -0
  49. package/dist/components/primitives/textarea.js +7 -0
  50. package/dist/components/primitives/tooltip.d.ts +13 -0
  51. package/dist/components/primitives/tooltip.js +24 -0
  52. package/dist/core/affix.d.ts +14 -0
  53. package/dist/core/affix.js +29 -0
  54. package/dist/core/alert.d.ts +54 -0
  55. package/dist/core/alert.js +56 -0
  56. package/dist/core/anchor.d.ts +16 -0
  57. package/dist/core/anchor.js +31 -0
  58. package/dist/core/app.d.ts +5 -0
  59. package/dist/core/app.js +5 -0
  60. package/dist/core/aspect-ratio.d.ts +6 -0
  61. package/dist/core/aspect-ratio.js +6 -0
  62. package/dist/core/autocomplete.d.ts +24 -0
  63. package/dist/core/autocomplete.js +139 -0
  64. package/dist/core/avatar.d.ts +26 -0
  65. package/dist/core/avatar.js +20 -0
  66. package/dist/core/badge.d.ts +16 -0
  67. package/dist/core/badge.js +22 -0
  68. package/dist/core/breadcrumb.d.ts +55 -0
  69. package/dist/core/breadcrumb.js +69 -0
  70. package/dist/core/button.d.ts +49 -0
  71. package/dist/core/button.js +66 -0
  72. package/dist/core/calendar.d.ts +48 -0
  73. package/dist/core/calendar.js +179 -0
  74. package/dist/core/card.d.ts +30 -0
  75. package/dist/core/card.js +12 -0
  76. package/dist/core/carousel.d.ts +49 -0
  77. package/dist/core/carousel.js +166 -0
  78. package/dist/core/cascader.d.ts +19 -0
  79. package/dist/core/cascader.js +45 -0
  80. package/dist/core/code-block.d.ts +16 -0
  81. package/dist/core/code-block.js +47 -0
  82. package/dist/core/collapse.d.ts +49 -0
  83. package/dist/core/collapse.js +96 -0
  84. package/dist/core/color-picker.d.ts +9 -0
  85. package/dist/core/color-picker.js +8 -0
  86. package/dist/core/config-provider.d.ts +10 -0
  87. package/dist/core/config-provider.js +14 -0
  88. package/dist/core/control-types.d.ts +2 -0
  89. package/dist/core/control-types.js +7 -0
  90. package/dist/core/date-picker.d.ts +13 -0
  91. package/dist/core/date-picker.js +14 -0
  92. package/dist/core/date-range-picker.d.ts +26 -0
  93. package/dist/core/date-range-picker.js +10 -0
  94. package/dist/core/descriptions.d.ts +41 -0
  95. package/dist/core/descriptions.js +133 -0
  96. package/dist/core/drawer.d.ts +9 -0
  97. package/dist/core/drawer.js +58 -0
  98. package/dist/core/empty.d.ts +8 -0
  99. package/dist/core/empty.js +5 -0
  100. package/dist/core/feedback.d.ts +5 -0
  101. package/dist/core/feedback.js +5 -0
  102. package/dist/core/field.d.ts +15 -0
  103. package/dist/core/field.js +19 -0
  104. package/dist/core/float-button.d.ts +13 -0
  105. package/dist/core/float-button.js +22 -0
  106. package/dist/core/form.d.ts +19 -0
  107. package/dist/core/form.js +56 -0
  108. package/dist/core/icon-button.d.ts +7 -0
  109. package/dist/core/icon-button.js +4 -0
  110. package/dist/core/icon.d.ts +17 -0
  111. package/dist/core/icon.js +35 -0
  112. package/dist/core/image.d.ts +76 -0
  113. package/dist/core/image.js +189 -0
  114. package/dist/core/index.d.ts +79 -0
  115. package/dist/core/index.js +77 -0
  116. package/dist/core/input-number.d.ts +24 -0
  117. package/dist/core/input-number.js +70 -0
  118. package/dist/core/input-otp.d.ts +14 -0
  119. package/dist/core/input-otp.js +76 -0
  120. package/dist/core/input.d.ts +14 -0
  121. package/dist/core/input.js +51 -0
  122. package/dist/core/kbd.d.ts +8 -0
  123. package/dist/core/kbd.js +11 -0
  124. package/dist/core/layout-primitives.d.ts +11 -0
  125. package/dist/core/layout-primitives.js +8 -0
  126. package/dist/core/layout.d.ts +71 -0
  127. package/dist/core/layout.js +119 -0
  128. package/dist/core/list.d.ts +37 -0
  129. package/dist/core/list.js +35 -0
  130. package/dist/core/locale.d.ts +48 -0
  131. package/dist/core/locale.js +32 -0
  132. package/dist/core/mentions.d.ts +10 -0
  133. package/dist/core/mentions.js +112 -0
  134. package/dist/core/menu.d.ts +79 -0
  135. package/dist/core/menu.js +265 -0
  136. package/dist/core/message.d.ts +16 -0
  137. package/dist/core/message.js +36 -0
  138. package/dist/core/modal.d.ts +40 -0
  139. package/dist/core/modal.js +67 -0
  140. package/dist/core/notification.d.ts +15 -0
  141. package/dist/core/notification.js +39 -0
  142. package/dist/core/page-layout.d.ts +6 -0
  143. package/dist/core/page-layout.js +7 -0
  144. package/dist/core/pagination.d.ts +28 -0
  145. package/dist/core/pagination.js +69 -0
  146. package/dist/core/popconfirm.d.ts +13 -0
  147. package/dist/core/popconfirm.js +42 -0
  148. package/dist/core/progress.d.ts +6 -0
  149. package/dist/core/progress.js +8 -0
  150. package/dist/core/public-props.d.ts +82 -0
  151. package/dist/core/public-props.js +1 -0
  152. package/dist/core/qrcode.d.ts +14 -0
  153. package/dist/core/qrcode.js +17 -0
  154. package/dist/core/rate.d.ts +11 -0
  155. package/dist/core/rate.js +48 -0
  156. package/dist/core/result.d.ts +12 -0
  157. package/dist/core/result.js +19 -0
  158. package/dist/core/segmented.d.ts +29 -0
  159. package/dist/core/segmented.js +38 -0
  160. package/dist/core/select.d.ts +27 -0
  161. package/dist/core/select.js +143 -0
  162. package/dist/core/selection-controls.d.ts +12 -0
  163. package/dist/core/selection-controls.js +23 -0
  164. package/dist/core/separator.d.ts +24 -0
  165. package/dist/core/separator.js +17 -0
  166. package/dist/core/slider.d.ts +2 -0
  167. package/dist/core/slider.js +6 -0
  168. package/dist/core/spin.d.ts +7 -0
  169. package/dist/core/spin.js +7 -0
  170. package/dist/core/spinner.d.ts +3 -0
  171. package/dist/core/spinner.js +6 -0
  172. package/dist/core/splitter.d.ts +44 -0
  173. package/dist/core/splitter.js +208 -0
  174. package/dist/core/statistic.d.ts +12 -0
  175. package/dist/core/statistic.js +6 -0
  176. package/dist/core/steps.d.ts +54 -0
  177. package/dist/core/steps.js +106 -0
  178. package/dist/core/tabs.d.ts +40 -0
  179. package/dist/core/tabs.js +80 -0
  180. package/dist/core/tag.d.ts +19 -0
  181. package/dist/core/tag.js +29 -0
  182. package/dist/core/textarea.d.ts +8 -0
  183. package/dist/core/textarea.js +14 -0
  184. package/dist/core/time-picker.d.ts +9 -0
  185. package/dist/core/time-picker.js +8 -0
  186. package/dist/core/timeline.d.ts +37 -0
  187. package/dist/core/timeline.js +48 -0
  188. package/dist/core/tour.d.ts +18 -0
  189. package/dist/core/tour.js +51 -0
  190. package/dist/core/transfer.d.ts +16 -0
  191. package/dist/core/transfer.js +46 -0
  192. package/dist/core/tree-select.d.ts +19 -0
  193. package/dist/core/tree-select.js +19 -0
  194. package/dist/core/tree.d.ts +89 -0
  195. package/dist/core/tree.js +386 -0
  196. package/dist/core/typography.d.ts +20 -0
  197. package/dist/core/typography.js +12 -0
  198. package/dist/core/upload.d.ts +20 -0
  199. package/dist/core/upload.js +72 -0
  200. package/dist/core/watermark.d.ts +10 -0
  201. package/dist/core/watermark.js +21 -0
  202. package/dist/fonts/inter-LICENSE +93 -0
  203. package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
  204. package/dist/fonts/jetbrains-mono-LICENSE +93 -0
  205. package/dist/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  206. package/dist/gouno/app-shell.d.ts +22 -0
  207. package/dist/gouno/app-shell.js +27 -0
  208. package/dist/gouno/index.d.ts +4 -0
  209. package/dist/gouno/index.js +4 -0
  210. package/dist/gouno/page-container.d.ts +4 -0
  211. package/dist/gouno/page-container.js +6 -0
  212. package/dist/gouno/page-header.d.ts +8 -0
  213. package/dist/gouno/page-header.js +6 -0
  214. package/dist/hooks/use-overlay-body.d.ts +6 -0
  215. package/dist/hooks/use-overlay-body.js +18 -0
  216. package/dist/index.d.ts +5 -0
  217. package/dist/index.js +5 -0
  218. package/dist/lib/utils.d.ts +2 -0
  219. package/dist/lib/utils.js +5 -0
  220. package/dist/patterns/bulk-action-bar.d.ts +8 -0
  221. package/dist/patterns/bulk-action-bar.js +7 -0
  222. package/dist/patterns/index.d.ts +5 -0
  223. package/dist/patterns/index.js +5 -0
  224. package/dist/theme/index.d.ts +2 -0
  225. package/dist/theme/index.js +2 -0
  226. package/dist/theme/provider.d.ts +22 -0
  227. package/dist/theme/provider.js +76 -0
  228. package/dist/theme/theme-toggle.d.ts +6 -0
  229. package/dist/theme/theme-toggle.js +10 -0
  230. package/dist/tokens.css +164 -0
  231. package/package.json +111 -0
@@ -0,0 +1,96 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useMemo, useState, } from "react";
3
+ import { ChevronRight } from "lucide-react";
4
+ import { cn } from "../lib/utils.js";
5
+ function isKeyArray(value) {
6
+ return Array.isArray(value);
7
+ }
8
+ function normalizeActiveKeys(value, accordion) {
9
+ const keys = value === undefined ? [] : isKeyArray(value) ? [...value] : [value];
10
+ return accordion ? keys.slice(0, 1) : keys;
11
+ }
12
+ function includesKey(keys, key) {
13
+ return keys.some((candidate) => candidate === key);
14
+ }
15
+ function sameKeys(a, b) {
16
+ return a.length === b.length && a.every((key, index) => key === b[index]);
17
+ }
18
+ function keyToken(key) {
19
+ return `${typeof key === "number" ? "n" : "s"}-${String(key)}`.replace(/[^a-zA-Z0-9_-]/g, "-");
20
+ }
21
+ const sizeClasses = {
22
+ small: {
23
+ header: "min-h-9 px-3 py-2 text-sm",
24
+ body: "px-3 pb-3 text-sm",
25
+ },
26
+ middle: {
27
+ header: "min-h-11 px-4 py-3 text-sm",
28
+ body: "px-4 pb-4 text-sm",
29
+ },
30
+ large: {
31
+ header: "min-h-13 px-5 py-4 text-base",
32
+ body: "px-5 pb-5 text-sm",
33
+ },
34
+ };
35
+ export function Collapse({ items, activeKey, defaultActiveKey, accordion = false, bordered = true, collapsible = "header", destroyOnHidden = false, expandIcon, expandIconPlacement = "start", ghost = false, size = "middle", onChange, classNames, styles, className, style, ref, ...props }) {
36
+ const instanceId = useId();
37
+ const [internalActiveKeys, setInternalActiveKeys] = useState(() => normalizeActiveKeys(defaultActiveKey, accordion));
38
+ const controlledActiveKeys = useMemo(() => normalizeActiveKeys(activeKey, accordion), [activeKey, accordion]);
39
+ const activeKeys = activeKey === undefined ? internalActiveKeys : controlledActiveKeys;
40
+ const [renderedKeys, setRenderedKeys] = useState(() => [
41
+ ...new Set([
42
+ ...normalizeActiveKeys(defaultActiveKey, accordion),
43
+ ...normalizeActiveKeys(activeKey, accordion),
44
+ ...items.filter((item) => item.forceRender).map((item) => item.key),
45
+ ]),
46
+ ]);
47
+ useEffect(() => {
48
+ const newlyVisible = [
49
+ ...activeKeys,
50
+ ...items.filter((item) => item.forceRender).map((item) => item.key),
51
+ ];
52
+ setRenderedKeys((keys) => {
53
+ const nextKeys = [...new Set([...keys, ...newlyVisible])];
54
+ return sameKeys(keys, nextKeys) ? keys : nextKeys;
55
+ });
56
+ }, [activeKeys, items]);
57
+ const semanticInfo = {
58
+ props: { accordion, bordered, ghost, size },
59
+ };
60
+ const semanticClassNames = typeof classNames === "function" ? classNames(semanticInfo) : (classNames ?? {});
61
+ const semanticStyles = typeof styles === "function" ? styles(semanticInfo) : (styles ?? {});
62
+ const commitActiveKeys = (nextKeys) => {
63
+ if (activeKey === undefined)
64
+ setInternalActiveKeys(nextKeys);
65
+ onChange?.(accordion ? (nextKeys[0] ?? []) : nextKeys);
66
+ };
67
+ const toggleItem = (item) => {
68
+ const active = includesKey(activeKeys, item.key);
69
+ const nextKeys = active
70
+ ? activeKeys.filter((key) => key !== item.key)
71
+ : accordion
72
+ ? [item.key]
73
+ : [...activeKeys, item.key];
74
+ if (!active) {
75
+ setRenderedKeys((keys) => includesKey(keys, item.key) ? keys : [...keys, item.key]);
76
+ }
77
+ commitActiveKeys(nextKeys);
78
+ };
79
+ return (_jsx("div", { ...props, ref: ref, "data-slot": "collapse", "data-accordion": accordion || undefined, "data-size": size, "data-ghost": ghost || undefined, className: cn("min-w-0 overflow-hidden rounded-lg", bordered && !ghost && "border", !ghost && "bg-background", semanticClassNames.root, className), style: { ...semanticStyles.root, ...style }, children: items.map((item, index) => {
80
+ const active = includesKey(activeKeys, item.key);
81
+ const itemCollapsible = item.collapsible ?? collapsible;
82
+ const showArrow = item.showArrow ?? true;
83
+ const iconOnly = itemCollapsible === "icon";
84
+ const disabled = itemCollapsible === "disabled" || (iconOnly && !showArrow);
85
+ const token = keyToken(item.key);
86
+ const headerId = `${instanceId}-header-${token}`;
87
+ const labelId = `${instanceId}-label-${token}`;
88
+ const bodyId = `${instanceId}-body-${token}`;
89
+ const shouldRender = item.forceRender ||
90
+ active ||
91
+ (!destroyOnHidden && includesKey(renderedKeys, item.key));
92
+ const arrow = showArrow ? (_jsx("span", { "aria-hidden": "true", className: "flex size-5 shrink-0 items-center justify-center [&_svg]:size-4", children: expandIcon ? (expandIcon({ active, item })) : (_jsx(ChevronRight, { className: cn("transition-transform duration-200", active && "rotate-90") })) })) : null;
93
+ const headerContent = (_jsxs(_Fragment, { children: [expandIconPlacement === "start" ? arrow : null, _jsx("span", { id: labelId, className: "min-w-0 flex-1 text-left font-medium", children: item.label }), expandIconPlacement === "end" ? arrow : null] }));
94
+ return (_jsxs("section", { "data-slot": "collapse-item", "data-active": active || undefined, className: cn("min-w-0", index > 0 && !ghost && "border-t", ghost && index > 0 && "border-t border-transparent", semanticClassNames.item), style: semanticStyles.item, children: [_jsxs("div", { "data-slot": "collapse-header", className: cn("flex min-w-0 items-center", sizeClasses[size].header, semanticClassNames.header, item.classNames?.header), style: { ...semanticStyles.header, ...item.styles?.header }, children: [iconOnly ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", id: headerId, "aria-expanded": active, "aria-controls": bodyId, disabled: disabled, "aria-label": active ? "Collapse panel" : "Expand panel", onClick: () => toggleItem(item), className: "mr-2 inline-flex size-7 shrink-0 items-center justify-center rounded-md outline-none transition-colors hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", children: arrow }), _jsx("span", { id: labelId, className: "min-w-0 flex-1 font-medium", children: item.label })] })) : (_jsx("button", { type: "button", id: headerId, "aria-expanded": active, "aria-controls": bodyId, disabled: disabled, onClick: () => toggleItem(item), className: "flex min-w-0 flex-1 items-center gap-2 rounded-sm text-inherit outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", children: headerContent })), item.extra !== undefined && item.extra !== null ? (_jsx("div", { "data-slot": "collapse-extra", className: "ml-3 shrink-0", onClick: (event) => event.stopPropagation(), children: item.extra })) : null] }), shouldRender ? (_jsx("div", { id: bodyId, role: "region", "aria-labelledby": labelId, hidden: !active, "data-slot": "collapse-body", className: cn("text-muted-foreground", sizeClasses[size].body, semanticClassNames.body, item.classNames?.body), style: { ...semanticStyles.body, ...item.styles?.body }, children: item.children })) : null] }, item.key));
95
+ }) }));
96
+ }
@@ -0,0 +1,9 @@
1
+ import { type InputHTMLAttributes } from "react";
2
+ import { type ControlSize } from "./control-types.js";
3
+ export interface ColorPickerProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
4
+ /** Gouno control size. Native input's numeric size attribute is intentionally not exposed. */
5
+ size?: ControlSize;
6
+ /** Validation state only; business copy remains caller-owned. */
7
+ status?: "error" | "warning";
8
+ }
9
+ export declare const ColorPicker: import("react").ForwardRefExoticComponent<ColorPickerProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../lib/utils.js";
4
+ import { controlSizeClass } from "./control-types.js";
5
+ export const ColorPicker = forwardRef(function ColorPicker({ size = "middle", status, className, disabled, ...props }, ref) {
6
+ const ariaInvalid = status === "error" ? true : props["aria-invalid"];
7
+ return (_jsx("input", { ...props, ref: ref, type: "color", disabled: disabled, "aria-invalid": ariaInvalid, "data-slot": "color-picker", "data-status": status, className: cn("inline-block w-14 cursor-pointer rounded-md border border-border bg-input p-1 outline-none transition-[border-color,box-shadow] focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", controlSizeClass(size), status === "error" && "border-destructive", status === "warning" && "border-warning", className) }));
8
+ });
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from "react";
2
+ import { type ComponentLocale } from "./locale.js";
3
+ export interface ConfigProviderProps {
4
+ children?: ReactNode;
5
+ /** Complete language pack. An omitted pack inherits the nearest provider. */
6
+ locale?: ComponentLocale;
7
+ }
8
+ export declare function ConfigProvider({ children, locale }: ConfigProviderProps): import("react").JSX.Element;
9
+ /** Internal component integration; not a second public configuration API. */
10
+ export declare function useComponentLocale<K extends Exclude<keyof ComponentLocale, "locale">>(component: K, override?: Partial<ComponentLocale[K]>): ComponentLocale[K];
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ import { enUS } from "./locale.js";
4
+ const LocaleContext = createContext(enUS);
5
+ export function ConfigProvider({ children, locale }) {
6
+ const parent = useContext(LocaleContext);
7
+ return _jsx(LocaleContext.Provider, { value: locale ?? parent, children: children });
8
+ }
9
+ /** Internal component integration; not a second public configuration API. */
10
+ export function useComponentLocale(component, override) {
11
+ const pack = useContext(LocaleContext);
12
+ const definedOverride = Object.fromEntries(Object.entries(override ?? {}).filter(([, value]) => value !== undefined));
13
+ return { ...enUS[component], ...pack[component], ...definedOverride };
14
+ }
@@ -0,0 +1,2 @@
1
+ export type ControlSize = "small" | "middle" | "large";
2
+ export declare function controlSizeClass(size: ControlSize): string;
@@ -0,0 +1,7 @@
1
+ export function controlSizeClass(size) {
2
+ return {
3
+ small: "h-8 text-sm",
4
+ middle: "h-9 text-sm",
5
+ large: "h-11 text-base",
6
+ }[size];
7
+ }
@@ -0,0 +1,13 @@
1
+ import type { DatePickerLocale } from "./locale.js";
2
+ import { type InputHTMLAttributes } from "react";
3
+ import { type ControlSize } from "./control-types.js";
4
+ export interface DatePickerProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "size" | "value" | "defaultValue" | "onChange"> {
5
+ locale?: Partial<DatePickerLocale>;
6
+ value?: string;
7
+ defaultValue?: string;
8
+ size?: ControlSize;
9
+ status?: "error" | "warning";
10
+ allowClear?: boolean;
11
+ onChange?: (value: string, date: Date | null) => void;
12
+ }
13
+ export declare const DatePicker: import("react").ForwardRefExoticComponent<DatePickerProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useComponentLocale } from "./config-provider.js";
3
+ import { forwardRef, useState } from "react";
4
+ import { CalendarDays, X } from "lucide-react";
5
+ import { cn } from "../lib/utils.js";
6
+ import { controlSizeClass } from "./control-types.js";
7
+ export const DatePicker = forwardRef(function DatePicker({ locale, value, defaultValue = "", size = "middle", status, allowClear = true, onChange, className, disabled, readOnly, ...props }, ref) {
8
+ const text = useComponentLocale("datePicker", locale);
9
+ const [inner, setInner] = useState(defaultValue);
10
+ const current = value === undefined ? inner : value;
11
+ const update = (next) => { if (value === undefined)
12
+ setInner(next); onChange?.(next, next ? new Date(`${next}T00:00:00`) : null); };
13
+ return _jsxs("span", { "data-slot": "date-picker", "data-status": status, className: cn("relative inline-flex w-full min-w-0 items-center rounded-md border border-border bg-input focus-within:ring-2 focus-within:ring-ring", status === "error" && "border-destructive", status === "warning" && "border-warning", disabled && "opacity-50", className), children: [_jsx(CalendarDays, { "aria-hidden": "true", className: "pointer-events-none absolute left-3 size-4 text-muted-foreground" }), _jsx("input", { ...props, ref: ref, type: "date", value: current, disabled: disabled, readOnly: readOnly, "aria-invalid": status === "error" || props["aria-invalid"] || undefined, className: cn("w-full min-w-0 appearance-none border-0 bg-transparent pl-9 outline-none", controlSizeClass(size), allowClear && current && !disabled && !readOnly ? "pr-9" : "pr-3"), onChange: (event) => update(event.target.value) }), allowClear && current && !disabled && !readOnly ? _jsx("button", { type: "button", "aria-label": text.clearLabel, className: "absolute right-2 flex size-6 items-center justify-center rounded text-muted-foreground hover:bg-muted hover:text-foreground", onClick: () => update(""), children: _jsx(X, { className: "size-3.5" }) }) : null] });
14
+ });
@@ -0,0 +1,26 @@
1
+ import { type ComponentPropsWithRef, type HTMLAttributes, type ReactNode } from "react";
2
+ import { type ControlSize } from "./control-types.js";
3
+ export type DateRange = {
4
+ start?: string;
5
+ end?: string;
6
+ };
7
+ export type DateRangePickerInputProps = Omit<ComponentPropsWithRef<"input">, "type" | "value" | "defaultValue" | "onChange" | "size">;
8
+ export interface DateRangePickerProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
9
+ /** Controlled start date in native yyyy-mm-dd form. */
10
+ start?: string;
11
+ /** Controlled end date in native yyyy-mm-dd form. */
12
+ end?: string;
13
+ /** Reports the complete proposed range whenever either native input changes. */
14
+ onChange?: (range: DateRange) => void;
15
+ /** Shared Gouno control size for both date inputs. */
16
+ size?: ControlSize;
17
+ /** Shared validation state; error marks both inputs aria-invalid. */
18
+ status?: "error" | "warning";
19
+ /** Native attributes, ARIA naming and optional ref for the start input only. */
20
+ startInputProps?: DateRangePickerInputProps;
21
+ /** Native attributes, ARIA naming and optional ref for the end input only. */
22
+ endInputProps?: DateRangePickerInputProps;
23
+ /** Visual separator between the two date inputs. */
24
+ separator?: ReactNode;
25
+ }
26
+ export declare const DateRangePicker: import("react").ForwardRefExoticComponent<DateRangePickerProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, } from "react";
3
+ import { cn } from "../lib/utils.js";
4
+ import { controlSizeClass } from "./control-types.js";
5
+ const dateInputClass = "min-w-0 flex-1 rounded-md border border-border bg-input px-3 text-foreground outline-none transition-[border-color,box-shadow] focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
6
+ export const DateRangePicker = forwardRef(function DateRangePicker({ start, end, onChange, size = "middle", status, startInputProps, endInputProps, separator = "–", className, ...rootProps }, ref) {
7
+ const { className: startClassName, "aria-invalid": startAriaInvalid, ...startNativeProps } = startInputProps ?? {};
8
+ const { className: endClassName, "aria-invalid": endAriaInvalid, ...endNativeProps } = endInputProps ?? {};
9
+ return (_jsxs("div", { ...rootProps, ref: ref, "data-slot": "date-range-picker", "data-status": status, className: cn("flex w-full items-center gap-2", className), children: [_jsx("input", { ...startNativeProps, type: "date", value: start ?? "", "aria-invalid": status === "error" ? true : startAriaInvalid, "data-slot": "date-range-picker-start", className: cn(dateInputClass, controlSizeClass(size), status === "error" && "border-destructive", status === "warning" && "border-warning", startClassName), onChange: (event) => onChange?.({ start: event.currentTarget.value || undefined, end }) }), _jsx("span", { "aria-hidden": "true", "data-slot": "date-range-picker-separator", children: separator }), _jsx("input", { ...endNativeProps, type: "date", value: end ?? "", "aria-invalid": status === "error" ? true : endAriaInvalid, "data-slot": "date-range-picker-end", className: cn(dateInputClass, controlSizeClass(size), status === "error" && "border-destructive", status === "warning" && "border-warning", endClassName), onChange: (event) => onChange?.({ start, end: event.currentTarget.value || undefined }) })] }));
10
+ });
@@ -0,0 +1,41 @@
1
+ import { type CSSProperties, type HTMLAttributes, type Key, type ReactNode, type Ref } from "react";
2
+ export type DescriptionsSize = "small" | "medium" | "large";
3
+ export type DescriptionsLayout = "horizontal" | "vertical";
4
+ export type DescriptionsBreakpoint = "xs" | "sm" | "md" | "lg" | "xl" | "xxl";
5
+ export type DescriptionsColumnCount = 1 | 2 | 3 | 4 | 5 | 6;
6
+ export type DescriptionsColumn = DescriptionsColumnCount | Partial<Record<DescriptionsBreakpoint, DescriptionsColumnCount>>;
7
+ export type DescriptionsSpanValue = DescriptionsColumnCount | "filled";
8
+ export type DescriptionsSpan = DescriptionsSpanValue | Partial<Record<DescriptionsBreakpoint, DescriptionsSpanValue>>;
9
+ export type DescriptionsSemantic = "root" | "header" | "title" | "extra" | "body" | "item" | "label" | "content";
10
+ export interface DescriptionsItem {
11
+ key: Key;
12
+ label: ReactNode;
13
+ children: ReactNode;
14
+ span?: DescriptionsSpan;
15
+ className?: string;
16
+ style?: CSSProperties;
17
+ }
18
+ export interface DescriptionsSemanticInfo {
19
+ props: Readonly<{
20
+ bordered: boolean;
21
+ colon: boolean;
22
+ layout: DescriptionsLayout;
23
+ size: DescriptionsSize;
24
+ }>;
25
+ }
26
+ export type DescriptionsClassNames = Partial<Record<DescriptionsSemantic, string>> | ((info: DescriptionsSemanticInfo) => Partial<Record<DescriptionsSemantic, string>>);
27
+ export type DescriptionsStyles = Partial<Record<DescriptionsSemantic, CSSProperties>> | ((info: DescriptionsSemanticInfo) => Partial<Record<DescriptionsSemantic, CSSProperties>>);
28
+ export interface DescriptionsProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "title"> {
29
+ title?: ReactNode;
30
+ extra?: ReactNode;
31
+ items?: readonly DescriptionsItem[];
32
+ bordered?: boolean;
33
+ colon?: boolean;
34
+ column?: DescriptionsColumn;
35
+ layout?: DescriptionsLayout;
36
+ size?: DescriptionsSize;
37
+ classNames?: DescriptionsClassNames;
38
+ styles?: DescriptionsStyles;
39
+ ref?: Ref<HTMLDivElement>;
40
+ }
41
+ export declare function Descriptions({ title, extra, items, bordered, colon, column, layout, size, classNames, styles, className, style, ref, ...props }: DescriptionsProps): import("react").JSX.Element;
@@ -0,0 +1,133 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import {} from "react";
3
+ import { cn } from "../lib/utils.js";
4
+ const baseColumns = {
5
+ 1: "grid-cols-1",
6
+ 2: "grid-cols-2",
7
+ 3: "grid-cols-3",
8
+ 4: "grid-cols-4",
9
+ 5: "grid-cols-5",
10
+ 6: "grid-cols-6",
11
+ };
12
+ const smColumns = {
13
+ 1: "sm:grid-cols-1",
14
+ 2: "sm:grid-cols-2",
15
+ 3: "sm:grid-cols-3",
16
+ 4: "sm:grid-cols-4",
17
+ 5: "sm:grid-cols-5",
18
+ 6: "sm:grid-cols-6",
19
+ };
20
+ const mdColumns = {
21
+ 1: "md:grid-cols-1",
22
+ 2: "md:grid-cols-2",
23
+ 3: "md:grid-cols-3",
24
+ 4: "md:grid-cols-4",
25
+ 5: "md:grid-cols-5",
26
+ 6: "md:grid-cols-6",
27
+ };
28
+ const lgColumns = {
29
+ 1: "lg:grid-cols-1",
30
+ 2: "lg:grid-cols-2",
31
+ 3: "lg:grid-cols-3",
32
+ 4: "lg:grid-cols-4",
33
+ 5: "lg:grid-cols-5",
34
+ 6: "lg:grid-cols-6",
35
+ };
36
+ const xlColumns = {
37
+ 1: "xl:grid-cols-1",
38
+ 2: "xl:grid-cols-2",
39
+ 3: "xl:grid-cols-3",
40
+ 4: "xl:grid-cols-4",
41
+ 5: "xl:grid-cols-5",
42
+ 6: "xl:grid-cols-6",
43
+ };
44
+ const xxlColumns = {
45
+ 1: "2xl:grid-cols-1",
46
+ 2: "2xl:grid-cols-2",
47
+ 3: "2xl:grid-cols-3",
48
+ 4: "2xl:grid-cols-4",
49
+ 5: "2xl:grid-cols-5",
50
+ 6: "2xl:grid-cols-6",
51
+ };
52
+ const baseSpans = {
53
+ 1: "col-span-1",
54
+ 2: "col-span-2",
55
+ 3: "col-span-3",
56
+ 4: "col-span-4",
57
+ 5: "col-span-5",
58
+ 6: "col-span-6",
59
+ };
60
+ const smSpans = {
61
+ 1: "sm:col-span-1",
62
+ 2: "sm:col-span-2",
63
+ 3: "sm:col-span-3",
64
+ 4: "sm:col-span-4",
65
+ 5: "sm:col-span-5",
66
+ 6: "sm:col-span-6",
67
+ };
68
+ const mdSpans = {
69
+ 1: "md:col-span-1",
70
+ 2: "md:col-span-2",
71
+ 3: "md:col-span-3",
72
+ 4: "md:col-span-4",
73
+ 5: "md:col-span-5",
74
+ 6: "md:col-span-6",
75
+ };
76
+ const lgSpans = {
77
+ 1: "lg:col-span-1",
78
+ 2: "lg:col-span-2",
79
+ 3: "lg:col-span-3",
80
+ 4: "lg:col-span-4",
81
+ 5: "lg:col-span-5",
82
+ 6: "lg:col-span-6",
83
+ };
84
+ const xlSpans = {
85
+ 1: "xl:col-span-1",
86
+ 2: "xl:col-span-2",
87
+ 3: "xl:col-span-3",
88
+ 4: "xl:col-span-4",
89
+ 5: "xl:col-span-5",
90
+ 6: "xl:col-span-6",
91
+ };
92
+ const xxlSpans = {
93
+ 1: "2xl:col-span-1",
94
+ 2: "2xl:col-span-2",
95
+ 3: "2xl:col-span-3",
96
+ 4: "2xl:col-span-4",
97
+ 5: "2xl:col-span-5",
98
+ 6: "2xl:col-span-6",
99
+ };
100
+ const paddingBySize = {
101
+ small: "px-3 py-2",
102
+ medium: "px-4 py-3",
103
+ large: "px-5 py-4",
104
+ };
105
+ function columnClassName(column) {
106
+ if (typeof column === "number")
107
+ return baseColumns[column];
108
+ return cn(baseColumns[column.xs ?? 1], column.sm && smColumns[column.sm], column.md && mdColumns[column.md], column.lg && lgColumns[column.lg], column.xl && xlColumns[column.xl], column.xxl && xxlColumns[column.xxl]);
109
+ }
110
+ function spanClassName(span) {
111
+ if (!span)
112
+ return baseSpans[1];
113
+ if (span === "filled")
114
+ return "col-span-full";
115
+ if (typeof span === "number")
116
+ return baseSpans[span];
117
+ const base = span.xs ?? 1;
118
+ return cn(base === "filled" ? "col-span-full" : baseSpans[base], span.sm && (span.sm === "filled" ? "sm:col-span-full" : smSpans[span.sm]), span.md && (span.md === "filled" ? "md:col-span-full" : mdSpans[span.md]), span.lg && (span.lg === "filled" ? "lg:col-span-full" : lgSpans[span.lg]), span.xl && (span.xl === "filled" ? "xl:col-span-full" : xlSpans[span.xl]), span.xxl &&
119
+ (span.xxl === "filled" ? "2xl:col-span-full" : xxlSpans[span.xxl]));
120
+ }
121
+ export function Descriptions({ title, extra, items = [], bordered = false, colon = true, column = 3, layout = "horizontal", size = "large", classNames, styles, className, style, ref, ...props }) {
122
+ const semanticInfo = {
123
+ props: { bordered, colon, layout, size },
124
+ };
125
+ const semanticClassNames = typeof classNames === "function" ? classNames(semanticInfo) : (classNames ?? {});
126
+ const semanticStyles = typeof styles === "function" ? styles(semanticInfo) : (styles ?? {});
127
+ const padding = paddingBySize[size];
128
+ return (_jsxs("div", { ...props, ref: ref, "data-slot": "descriptions", "data-size": size, "data-layout": layout, "data-bordered": bordered || undefined, className: cn("w-full min-w-0", semanticClassNames.root, className), style: { ...semanticStyles.root, ...style }, children: [title !== undefined || extra !== undefined ? (_jsxs("div", { "data-slot": "descriptions-header", className: cn("mb-4 flex min-w-0 items-start justify-between gap-4", semanticClassNames.header), style: semanticStyles.header, children: [_jsx("div", { "data-slot": "descriptions-title", className: cn("min-w-0 text-base font-semibold", semanticClassNames.title), style: semanticStyles.title, children: title }), extra !== undefined && extra !== null ? (_jsx("div", { "data-slot": "descriptions-extra", className: cn("shrink-0", semanticClassNames.extra), style: semanticStyles.extra, children: extra })) : null] })) : null, _jsx("dl", { "data-slot": "descriptions-body", className: cn("grid min-w-0", columnClassName(column), bordered
129
+ ? "gap-px overflow-hidden rounded-lg border bg-border"
130
+ : "gap-x-6 gap-y-4", semanticClassNames.body), style: semanticStyles.body, children: items.map((item) => (_jsxs("div", { "data-slot": "descriptions-item", className: cn("min-w-0", spanClassName(item.span), layout === "horizontal"
131
+ ? "grid grid-cols-[minmax(0,auto)_minmax(0,1fr)] items-stretch"
132
+ : "flex flex-col", bordered && "bg-background", semanticClassNames.item, item.className), style: { ...semanticStyles.item, ...item.style }, children: [_jsxs("dt", { "data-slot": "descriptions-label", className: cn("min-w-0 text-muted-foreground", bordered ? cn(padding, "bg-muted/50 font-medium") : "font-medium", layout === "vertical" && !bordered && "mb-1", semanticClassNames.label), style: semanticStyles.label, children: [item.label, colon && layout === "horizontal" ? _jsx("span", { "aria-hidden": "true", children: ":" }) : null] }), _jsx("dd", { "data-slot": "descriptions-content", className: cn("min-w-0 break-words text-foreground", bordered && padding, semanticClassNames.content), style: semanticStyles.content, children: item.children })] }, item.key))) })] }));
133
+ }
@@ -0,0 +1,9 @@
1
+ import type { ModalProps } from "./modal.js";
2
+ export type DrawerPlacement = "top" | "right" | "bottom" | "left";
3
+ export interface DrawerProps extends Omit<ModalProps, "maxWidth" | "size" | "centered" | "onOk" | "onCancel" | "okText" | "cancelText" | "confirmLoading" | "okButtonProps" | "cancelButtonProps"> {
4
+ extra?: import("react").ReactNode;
5
+ placement?: DrawerPlacement;
6
+ width?: number | string;
7
+ height?: number | string;
8
+ }
9
+ export declare function Drawer({ open, defaultOpen, title, description, children, footer, onClose, onOpenChange, afterOpenChange, className, closeOnEsc, closeOnBackdrop, showCloseButton, "aria-label": ariaLabel, contentStyle, placement, width, height, loading, mask, zIndex, destroyOnClose, extra, styles, }: DrawerProps): import("react").JSX.Element;
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useEffectEvent, useRef, useState, } from "react";
3
+ import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, } from "../components/primitives/sheet.js";
4
+ import { useOverlayBody } from "../hooks/use-overlay-body.js";
5
+ import { cn } from "../lib/utils.js";
6
+ const closeText = () => typeof document !== "undefined" &&
7
+ document.documentElement.lang.startsWith("en")
8
+ ? "Close"
9
+ : "关闭";
10
+ export function Drawer({ open, defaultOpen = false, title, description, children, footer, onClose, onOpenChange, afterOpenChange, className, closeOnEsc = true, closeOnBackdrop = true, showCloseButton = true, "aria-label": ariaLabel, contentStyle, placement = "right", width = 378, height = 378, loading = false, mask = true, zIndex = 50, destroyOnClose = true, extra, styles, }) {
11
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
12
+ const previousFocus = useRef(null);
13
+ const controlled = open !== undefined;
14
+ const visible = open ?? internalOpen;
15
+ const retained = useOverlayBody(children, visible, destroyOnClose);
16
+ const changeOpen = (next) => {
17
+ if (!controlled)
18
+ setInternalOpen(next);
19
+ onOpenChange?.(next);
20
+ if (!next)
21
+ onClose?.();
22
+ };
23
+ useEffect(() => {
24
+ if (visible)
25
+ previousFocus.current =
26
+ document.activeElement instanceof HTMLElement
27
+ ? document.activeElement
28
+ : null;
29
+ return () => {
30
+ if (previousFocus.current?.isConnected)
31
+ previousFocus.current.focus();
32
+ };
33
+ }, [visible]);
34
+ const notifyOpenChange = useEffectEvent((next) => afterOpenChange?.(next));
35
+ useEffect(() => {
36
+ notifyOpenChange(visible);
37
+ }, [visible]);
38
+ const sidePlacement = placement === "left" || placement === "right";
39
+ const dimensionStyle = sidePlacement ? { width } : { height };
40
+ return (_jsxs(_Fragment, { children: [retained.portal, _jsx(Sheet, { open: visible, onOpenChange: changeOpen, children: _jsxs(SheetContent, { side: placement, showCloseButton: showCloseButton, className: cn("flex flex-col gap-0", sidePlacement ? "max-w-[calc(100vw-1rem)]" : "max-w-none", className), style: {
41
+ ...dimensionStyle,
42
+ maxWidth: sidePlacement ? "calc(100vw - 1rem)" : "100vw",
43
+ maxHeight: "100dvh",
44
+ zIndex,
45
+ ...contentStyle,
46
+ }, mask: mask, zIndex: zIndex, maskStyle: styles?.mask, onEscapeKeyDown: (event) => {
47
+ if (!closeOnEsc)
48
+ event.preventDefault();
49
+ }, onPointerDownOutside: (event) => {
50
+ if (!closeOnBackdrop)
51
+ event.preventDefault();
52
+ }, onCloseAutoFocus: (event) => {
53
+ if (previousFocus.current?.isConnected) {
54
+ event.preventDefault();
55
+ previousFocus.current.focus();
56
+ }
57
+ }, children: [_jsxs(SheetHeader, { className: "border-b p-5 pr-12", style: styles?.header, children: [extra && _jsx("div", { className: "flex justify-end", children: extra }), _jsx(SheetTitle, { children: title || ariaLabel || closeText() }), description ? (_jsx(SheetDescription, { children: description })) : null] }), _jsxs("div", { className: "min-h-0 flex-1 overflow-auto p-5", style: styles?.body, "aria-busy": loading || undefined, children: [loading && (_jsx("div", { role: "status", className: "py-8 text-center text-sm text-muted-foreground", children: "\u52A0\u8F7D\u4E2D\u2026" })), _jsx("div", { hidden: loading, children: retained.body })] }), footer != null && (_jsx("div", { className: "flex flex-wrap justify-end gap-3 border-t p-5", style: styles?.footer, children: footer }))] }) })] }));
58
+ }
@@ -0,0 +1,8 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+ export interface EmptyProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
3
+ title?: ReactNode;
4
+ description?: ReactNode;
5
+ action?: ReactNode;
6
+ icon?: ReactNode;
7
+ }
8
+ export declare function Empty({ title, description, action, icon, className, ...props }: EmptyProps): import("react").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ export function Empty({ title, description, action, icon, className, ...props }) {
4
+ return (_jsxs("div", { ...props, "data-slot": "empty", className: cn("flex min-h-32 flex-col items-center justify-center gap-2 py-8 text-center", className), children: [icon ? _jsx("div", { "data-slot": "empty-icon", children: icon }) : null, title != null ? (_jsx("div", { "data-slot": "empty-title", className: "font-semibold text-foreground", children: title })) : null, description != null ? (_jsx("div", { "data-slot": "empty-description", className: "max-w-lg text-sm text-muted-foreground", children: description })) : null, action != null ? (_jsx("div", { "data-slot": "empty-action", className: "pt-1", children: action })) : null] }));
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { ComponentProps } from "react";
2
+ import { Skeleton as PrimitiveSkeleton } from "../components/primitives/skeleton.js";
3
+ type SkeletonProps = ComponentProps<typeof PrimitiveSkeleton>;
4
+ export declare function Skeleton({ "aria-hidden": ariaHidden, ...props }: SkeletonProps): import("react").JSX.Element;
5
+ export {};
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Skeleton as PrimitiveSkeleton } from "../components/primitives/skeleton.js";
3
+ export function Skeleton({ "aria-hidden": ariaHidden, ...props }) {
4
+ return _jsx(PrimitiveSkeleton, { ...props, "aria-hidden": ariaHidden ?? true });
5
+ }
@@ -0,0 +1,15 @@
1
+ import { type ReactNode } from "react";
2
+ import { FieldGroup, FieldLabel, FieldLegend, FieldSet } from "../components/primitives/field.js";
3
+ export { FieldGroup, FieldSet, FieldLegend, FieldLabel };
4
+ export interface FieldProps {
5
+ label: ReactNode;
6
+ children: ReactNode;
7
+ id?: string;
8
+ hint?: ReactNode;
9
+ error?: ReactNode;
10
+ required?: boolean;
11
+ className?: string;
12
+ hideLabel?: boolean;
13
+ }
14
+ export declare function Field({ label, children, id, hint, error, required, className, hideLabel }: FieldProps): import("react").JSX.Element;
15
+ export declare const FormField: typeof Field;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cloneElement, isValidElement, useId } from "react";
3
+ import { Field as FieldRoot, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSet } from "../components/primitives/field.js";
4
+ import { cn } from "../lib/utils.js";
5
+ export { FieldGroup, FieldSet, FieldLegend, FieldLabel };
6
+ export function Field({ label, children, id, hint, error, required = false, className, hideLabel = false }) {
7
+ const generated = useId();
8
+ const child = isValidElement(children) ? children : null;
9
+ const controlId = id || child?.props.id || `field-${generated}`;
10
+ const hintId = hint ? `${controlId}-hint` : undefined;
11
+ const errorId = error ? `${controlId}-error` : undefined;
12
+ return (_jsxs(FieldRoot, { "data-invalid": error ? true : undefined, className: cn("field min-w-0", className), children: [_jsxs(FieldLabel, { htmlFor: controlId, className: hideLabel ? "sr-only" : undefined, children: [label, required ? _jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" }) : null] }), child ? cloneElement(child, {
13
+ id: controlId,
14
+ required: child.props.required ?? required,
15
+ "aria-describedby": [child.props["aria-describedby"], hintId, errorId].filter(Boolean).join(" ") || undefined,
16
+ "aria-invalid": child.props["aria-invalid"] || Boolean(error) || undefined,
17
+ }) : children, hint ? _jsx(FieldDescription, { id: hintId, children: hint }) : null, error ? _jsx(FieldError, { id: errorId, role: "alert", children: error }) : null] }));
18
+ }
19
+ export const FormField = Field;
@@ -0,0 +1,13 @@
1
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode, Ref } from "react";
2
+ export interface FloatButtonProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
3
+ icon: ReactNode;
4
+ tooltip?: ReactNode;
5
+ href?: string;
6
+ target?: AnchorHTMLAttributes<HTMLAnchorElement>["target"];
7
+ rel?: string;
8
+ download?: boolean | string;
9
+ disabled?: boolean;
10
+ type?: ButtonHTMLAttributes<HTMLButtonElement>["type"];
11
+ ref?: Ref<HTMLButtonElement | HTMLAnchorElement>;
12
+ }
13
+ export declare function FloatButton({ icon, tooltip, href, target, rel, download, disabled, type, ref, className, onClick, tabIndex, ...props }: FloatButtonProps): import("react").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/primitives/tooltip.js";
3
+ import { cn } from "../lib/utils.js";
4
+ const floatButtonClass = "fixed right-6 bottom-6 z-40 inline-flex size-12 items-center justify-center rounded-full border bg-popover text-foreground shadow-overlay transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background";
5
+ function withTooltip(trigger, tooltip) {
6
+ if (tooltip === undefined || tooltip === null)
7
+ return trigger;
8
+ return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: trigger }), _jsx(TooltipContent, { children: tooltip })] }) }));
9
+ }
10
+ export function FloatButton({ icon, tooltip, href, target, rel, download, disabled = false, type = "button", ref, className, onClick, tabIndex, ...props }) {
11
+ const content = (_jsx("span", { "data-slot": "float-button-icon", "aria-hidden": "true", children: icon }));
12
+ if (href !== undefined) {
13
+ return withTooltip(_jsx("a", { ...props, ref: ref, href: href, target: target, rel: rel, download: download, "aria-disabled": disabled ? true : props["aria-disabled"], tabIndex: disabled ? -1 : tabIndex, onClick: (event) => {
14
+ if (disabled) {
15
+ event.preventDefault();
16
+ return;
17
+ }
18
+ onClick?.(event);
19
+ }, "data-slot": "float-button", className: cn(floatButtonClass, disabled && "pointer-events-none opacity-50", className), children: content }), tooltip);
20
+ }
21
+ return withTooltip(_jsx("button", { ...props, ref: ref, type: type, disabled: disabled, tabIndex: tabIndex, onClick: (event) => onClick?.(event), "data-slot": "float-button", className: cn(floatButtonClass, "disabled:pointer-events-none disabled:opacity-50", className), children: content }), tooltip);
22
+ }
@@ -0,0 +1,19 @@
1
+ import { type FormEvent, type FormHTMLAttributes, type HTMLAttributes, type ReactNode } from "react";
2
+ export interface FormProps extends FormHTMLAttributes<HTMLFormElement> {
3
+ layout?: "vertical" | "horizontal" | "inline";
4
+ disabled?: boolean;
5
+ loading?: boolean;
6
+ validateMessages?: Record<string, string>;
7
+ onFinish?: (formData: FormData, values: Record<string, FormDataEntryValue>) => void;
8
+ onFinishFailed?: (event: FormEvent<HTMLFormElement>) => void;
9
+ }
10
+ export declare function Form({ layout, disabled, loading, onFinish, onFinishFailed, onSubmit, className, children, validateMessages, ...props }: FormProps): import("react").JSX.Element;
11
+ export declare function FormLayout({ className, ...props }: FormHTMLAttributes<HTMLFormElement>): import("react").JSX.Element;
12
+ export declare function FormGrid({ columns, className, ...props }: HTMLAttributes<HTMLDivElement> & {
13
+ columns?: 1 | 2 | 3 | 4 | 5;
14
+ }): import("react").JSX.Element;
15
+ export declare function FormActions({ className, ...props }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
16
+ export declare function OverlayForm({ actions, actionClassName, children, ...props }: FormHTMLAttributes<HTMLFormElement> & {
17
+ actions: ReactNode;
18
+ actionClassName?: string;
19
+ }): import("react").JSX.Element;