@arcfusionz/arc-primitive-ui 0.0.0 → 0.2.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 (136) hide show
  1. package/dist/components/AILoader/AILoader.d.ts +32 -0
  2. package/dist/components/AILoader/AILoader.js +157 -0
  3. package/dist/components/AILoader/index.d.ts +2 -0
  4. package/dist/components/AILoader/index.js +2 -0
  5. package/dist/components/Accordion/Accordion.d.ts +96 -0
  6. package/dist/components/Accordion/Accordion.js +149 -0
  7. package/dist/components/Accordion/index.d.ts +2 -0
  8. package/dist/components/Accordion/index.js +2 -0
  9. package/dist/components/Avatar/Avatar.d.ts +152 -0
  10. package/dist/components/Avatar/Avatar.js +216 -0
  11. package/dist/components/Avatar/index.d.ts +2 -0
  12. package/dist/components/Avatar/index.js +2 -0
  13. package/dist/components/Badge/Badge.d.ts +87 -0
  14. package/dist/components/Badge/Badge.js +118 -0
  15. package/dist/components/Badge/index.d.ts +2 -0
  16. package/dist/components/Badge/index.js +2 -0
  17. package/dist/components/Breadcrumb/Breadcrumb.d.ts +109 -0
  18. package/dist/components/Breadcrumb/Breadcrumb.js +182 -0
  19. package/dist/components/Breadcrumb/index.d.ts +2 -0
  20. package/dist/components/Breadcrumb/index.js +2 -0
  21. package/dist/components/Button/Button.d.ts +57 -0
  22. package/dist/components/Button/Button.js +177 -0
  23. package/dist/components/Button/index.d.ts +2 -0
  24. package/dist/components/Button/index.js +2 -0
  25. package/dist/components/Calendar/Calendar.d.ts +140 -0
  26. package/dist/components/Calendar/Calendar.js +468 -0
  27. package/dist/components/Calendar/index.d.ts +2 -0
  28. package/dist/components/Calendar/index.js +2 -0
  29. package/dist/components/Checkbox/Checkbox.d.ts +60 -0
  30. package/dist/components/Checkbox/Checkbox.js +129 -0
  31. package/dist/components/Checkbox/index.d.ts +2 -0
  32. package/dist/components/Checkbox/index.js +2 -0
  33. package/dist/components/Combobox/Combobox.d.ts +251 -0
  34. package/dist/components/Combobox/Combobox.js +354 -0
  35. package/dist/components/Combobox/index.d.ts +2 -0
  36. package/dist/components/Combobox/index.js +2 -0
  37. package/dist/components/ContextMenu/ContextMenu.d.ts +129 -0
  38. package/dist/components/ContextMenu/ContextMenu.js +93 -0
  39. package/dist/components/ContextMenu/index.d.ts +2 -0
  40. package/dist/components/ContextMenu/index.js +2 -0
  41. package/dist/components/DatePicker/DatePicker.d.ts +109 -0
  42. package/dist/components/DatePicker/DatePicker.js +145 -0
  43. package/dist/components/DatePicker/index.d.ts +2 -0
  44. package/dist/components/DatePicker/index.js +2 -0
  45. package/dist/components/DateRangePicker/DateRangePicker.d.ts +107 -0
  46. package/dist/components/DateRangePicker/DateRangePicker.js +161 -0
  47. package/dist/components/DateRangePicker/index.d.ts +2 -0
  48. package/dist/components/DateRangePicker/index.js +2 -0
  49. package/dist/components/Dialog/Dialog.d.ts +112 -0
  50. package/dist/components/Dialog/Dialog.js +141 -0
  51. package/dist/components/Dialog/index.d.ts +2 -0
  52. package/dist/components/Dialog/index.js +2 -0
  53. package/dist/components/Drawer/Drawer.d.ts +188 -0
  54. package/dist/components/Drawer/Drawer.js +268 -0
  55. package/dist/components/Drawer/index.d.ts +2 -0
  56. package/dist/components/Drawer/index.js +2 -0
  57. package/dist/components/Field/Field.d.ts +123 -0
  58. package/dist/components/Field/Field.js +241 -0
  59. package/dist/components/Field/FieldContext.d.ts +43 -0
  60. package/dist/components/Field/FieldContext.js +28 -0
  61. package/dist/components/Field/index.d.ts +3 -0
  62. package/dist/components/Field/index.js +3 -0
  63. package/dist/components/Fieldset/Fieldset.d.ts +43 -0
  64. package/dist/components/Fieldset/Fieldset.js +48 -0
  65. package/dist/components/Fieldset/index.d.ts +2 -0
  66. package/dist/components/Fieldset/index.js +2 -0
  67. package/dist/components/Form/Form.d.ts +54 -0
  68. package/dist/components/Form/Form.js +57 -0
  69. package/dist/components/Form/index.d.ts +2 -0
  70. package/dist/components/Form/index.js +2 -0
  71. package/dist/components/Input/Input.d.ts +64 -0
  72. package/dist/components/Input/Input.js +111 -0
  73. package/dist/components/Input/index.d.ts +2 -0
  74. package/dist/components/Input/index.js +2 -0
  75. package/dist/components/Menu/Menu.d.ts +212 -0
  76. package/dist/components/Menu/Menu.js +255 -0
  77. package/dist/components/Menu/index.d.ts +2 -0
  78. package/dist/components/Menu/index.js +2 -0
  79. package/dist/components/Popover/Popover.d.ts +122 -0
  80. package/dist/components/Popover/Popover.js +116 -0
  81. package/dist/components/Popover/index.d.ts +2 -0
  82. package/dist/components/Popover/index.js +2 -0
  83. package/dist/components/Progress/Progress.d.ts +87 -0
  84. package/dist/components/Progress/Progress.js +73 -0
  85. package/dist/components/Progress/index.d.ts +2 -0
  86. package/dist/components/Progress/index.js +2 -0
  87. package/dist/components/Radio/Radio.d.ts +65 -0
  88. package/dist/components/Radio/Radio.js +93 -0
  89. package/dist/components/Radio/index.d.ts +2 -0
  90. package/dist/components/Radio/index.js +2 -0
  91. package/dist/components/Select/Select.d.ts +136 -0
  92. package/dist/components/Select/Select.js +219 -0
  93. package/dist/components/Select/index.d.ts +2 -0
  94. package/dist/components/Select/index.js +2 -0
  95. package/dist/components/Skeleton/Skeleton.d.ts +39 -0
  96. package/dist/components/Skeleton/Skeleton.js +44 -0
  97. package/dist/components/Skeleton/index.d.ts +2 -0
  98. package/dist/components/Skeleton/index.js +2 -0
  99. package/dist/components/Stepper/Stepper.d.ts +161 -0
  100. package/dist/components/Stepper/Stepper.js +344 -0
  101. package/dist/components/Stepper/index.d.ts +2 -0
  102. package/dist/components/Stepper/index.js +2 -0
  103. package/dist/components/Switch/Switch.d.ts +56 -0
  104. package/dist/components/Switch/Switch.js +87 -0
  105. package/dist/components/Switch/index.d.ts +2 -0
  106. package/dist/components/Switch/index.js +2 -0
  107. package/dist/components/Table/Table.d.ts +116 -0
  108. package/dist/components/Table/Table.js +143 -0
  109. package/dist/components/Table/index.d.ts +2 -0
  110. package/dist/components/Table/index.js +2 -0
  111. package/dist/components/Tabs/Tabs.d.ts +116 -0
  112. package/dist/components/Tabs/Tabs.js +158 -0
  113. package/dist/components/Tabs/index.d.ts +2 -0
  114. package/dist/components/Tabs/index.js +2 -0
  115. package/dist/components/Timeline/Timeline.d.ts +137 -0
  116. package/dist/components/Timeline/Timeline.js +243 -0
  117. package/dist/components/Timeline/index.d.ts +2 -0
  118. package/dist/components/Timeline/index.js +2 -0
  119. package/dist/components/Toast/Toast.d.ts +135 -0
  120. package/dist/components/Toast/Toast.js +314 -0
  121. package/dist/components/Toast/index.d.ts +2 -0
  122. package/dist/components/Toast/index.js +2 -0
  123. package/dist/components/Tooltip/Tooltip.d.ts +104 -0
  124. package/dist/components/Tooltip/Tooltip.js +95 -0
  125. package/dist/components/Tooltip/index.d.ts +2 -0
  126. package/dist/components/Tooltip/index.js +2 -0
  127. package/dist/components/Typography/Typography.d.ts +38 -0
  128. package/dist/components/Typography/Typography.js +53 -0
  129. package/dist/components/Typography/index.d.ts +2 -0
  130. package/dist/components/Typography/index.js +2 -0
  131. package/dist/index.d.ts +66 -3398
  132. package/dist/index.js +34 -5343
  133. package/dist/lib/cn.d.ts +6 -0
  134. package/dist/lib/cn.js +9 -0
  135. package/package.json +6 -2
  136. package/src/styles/theme.css +341 -341
@@ -0,0 +1,182 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { forwardRef } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ //#region src/components/Breadcrumb/Breadcrumb.tsx
6
+ function ChevronRightIcon(props) {
7
+ return /* @__PURE__ */ jsx("svg", {
8
+ viewBox: "0 0 24 24",
9
+ fill: "none",
10
+ stroke: "currentColor",
11
+ strokeWidth: 2,
12
+ strokeLinecap: "round",
13
+ strokeLinejoin: "round",
14
+ ...props,
15
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
16
+ });
17
+ }
18
+ function EllipsisIcon(props) {
19
+ return /* @__PURE__ */ jsxs("svg", {
20
+ viewBox: "0 0 24 24",
21
+ fill: "none",
22
+ stroke: "currentColor",
23
+ strokeWidth: 2,
24
+ strokeLinecap: "round",
25
+ strokeLinejoin: "round",
26
+ ...props,
27
+ children: [
28
+ /* @__PURE__ */ jsx("circle", {
29
+ cx: "12",
30
+ cy: "12",
31
+ r: "1"
32
+ }),
33
+ /* @__PURE__ */ jsx("circle", {
34
+ cx: "19",
35
+ cy: "12",
36
+ r: "1"
37
+ }),
38
+ /* @__PURE__ */ jsx("circle", {
39
+ cx: "5",
40
+ cy: "12",
41
+ r: "1"
42
+ })
43
+ ]
44
+ });
45
+ }
46
+ const listClasses = "flex flex-wrap items-center gap-1.5 break-words font-sans text-sm text-muted-foreground sm:gap-2.5";
47
+ const itemClasses = "inline-flex items-center gap-1.5";
48
+ const linkClasses = "inline-flex items-center gap-1.5 rounded-md transition-colors duration-150 hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring aria-[current=page]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5";
49
+ const pageClasses = "font-normal text-foreground";
50
+ const separatorClasses = "select-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5";
51
+ const ellipsisClasses = "inline-flex items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
52
+ /**
53
+ * Navigation landmark that holds the trail. It defaults to
54
+ * `aria-label="Breadcrumb"`; pass a localized `aria-label` (or
55
+ * `aria-labelledby`) when the page language isn't English.
56
+ */
57
+ const Breadcrumb = forwardRef(({ render, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...rest }, ref) => useRender({
58
+ defaultTagName: "nav",
59
+ render,
60
+ ref,
61
+ props: {
62
+ "aria-label": ariaLabel ?? (ariaLabelledBy == null ? "Breadcrumb" : void 0),
63
+ "aria-labelledby": ariaLabelledBy,
64
+ ...rest,
65
+ className
66
+ }
67
+ }));
68
+ Breadcrumb.displayName = "Breadcrumb";
69
+ /**
70
+ * Ordered list of crumbs. It wraps onto new lines on narrow viewports; cap
71
+ * individual crumbs with a truncation `className` instead of letting the
72
+ * whole trail overflow.
73
+ */
74
+ const BreadcrumbList = forwardRef(({ render, className, ...rest }, ref) => useRender({
75
+ defaultTagName: "ol",
76
+ render,
77
+ ref,
78
+ props: {
79
+ ...rest,
80
+ className: cn(listClasses, className)
81
+ }
82
+ }));
83
+ BreadcrumbList.displayName = "BreadcrumbList";
84
+ /** One entry in the trail: wraps a link, the current page, or a composed control. */
85
+ const BreadcrumbItem = forwardRef(({ render, className, ...rest }, ref) => useRender({
86
+ defaultTagName: "li",
87
+ render,
88
+ ref,
89
+ props: {
90
+ ...rest,
91
+ className: cn(itemClasses, className)
92
+ }
93
+ }));
94
+ BreadcrumbItem.displayName = "BreadcrumbItem";
95
+ /**
96
+ * Class list for an element styled as a breadcrumb link.
97
+ *
98
+ * Use it to give non-anchor crumbs the same resting/hover/focus treatment —
99
+ * e.g. a Menu trigger button that reveals collapsed levels:
100
+ *
101
+ * <MenuTrigger
102
+ * render={<button aria-label="Show hidden levels" className={breadcrumbLinkVariants()} />}
103
+ * >
104
+ * <BreadcrumbEllipsis />
105
+ * </MenuTrigger>
106
+ */
107
+ function breadcrumbLinkVariants({ className } = {}) {
108
+ return cn(linkClasses, className);
109
+ }
110
+ /**
111
+ * Ancestor link in the trail. Inline text links are exempt from the WCAG
112
+ * 2.5.8 target-size floor, but keep the list's default gap so adjacent
113
+ * targets stay distinguishable on touch screens. For the APG variant where
114
+ * the current page stays a link, add `aria-current="page"` — the recipe
115
+ * restyles it to match `BreadcrumbPage`.
116
+ */
117
+ const BreadcrumbLink = forwardRef(({ render, className, ...rest }, ref) => useRender({
118
+ defaultTagName: "a",
119
+ render,
120
+ ref,
121
+ props: {
122
+ ...rest,
123
+ className: cn(linkClasses, className)
124
+ }
125
+ }));
126
+ BreadcrumbLink.displayName = "BreadcrumbLink";
127
+ /**
128
+ * The current page, rendered as plain text with `aria-current="page"` — an
129
+ * honest `span`, not a disabled fake link. Use `BreadcrumbLink` with
130
+ * `aria-current="page"` instead when the current page must stay navigable.
131
+ */
132
+ const BreadcrumbPage = forwardRef(({ render, className, ...rest }, ref) => useRender({
133
+ defaultTagName: "span",
134
+ render,
135
+ ref,
136
+ props: {
137
+ "aria-current": "page",
138
+ ...rest,
139
+ className: cn(pageClasses, className)
140
+ }
141
+ }));
142
+ BreadcrumbPage.displayName = "BreadcrumbPage";
143
+ /**
144
+ * Visual divider between crumbs. It is `aria-hidden` with
145
+ * `role="presentation"`, so screen readers hear only the crumbs and the
146
+ * list's item count — never the glyphs.
147
+ */
148
+ const BreadcrumbSeparator = forwardRef(({ render, className, children = /* @__PURE__ */ jsx(ChevronRightIcon, {}), ...rest }, ref) => useRender({
149
+ defaultTagName: "li",
150
+ render,
151
+ ref,
152
+ props: {
153
+ role: "presentation",
154
+ "aria-hidden": "true",
155
+ ...rest,
156
+ children,
157
+ className: cn(separatorClasses, className)
158
+ }
159
+ }));
160
+ BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
161
+ /**
162
+ * Marker for collapsed levels in a deep trail. It is decorative
163
+ * (`aria-hidden`); when the hidden levels must stay reachable, wrap it in a
164
+ * labelled trigger — e.g. a Menu trigger styled with
165
+ * `breadcrumbLinkVariants()` — so the control, not the glyph, carries the
166
+ * accessible name.
167
+ */
168
+ const BreadcrumbEllipsis = forwardRef(({ render, className, children = /* @__PURE__ */ jsx(EllipsisIcon, {}), ...rest }, ref) => useRender({
169
+ defaultTagName: "span",
170
+ render,
171
+ ref,
172
+ props: {
173
+ role: "presentation",
174
+ "aria-hidden": "true",
175
+ ...rest,
176
+ children,
177
+ className: cn(ellipsisClasses, className)
178
+ }
179
+ }));
180
+ BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
181
+ //#endregion
182
+ export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, breadcrumbLinkVariants };
@@ -0,0 +1,2 @@
1
+ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbEllipsisProps, BreadcrumbItem, BreadcrumbItemProps, BreadcrumbLink, BreadcrumbLinkProps, BreadcrumbLinkVariantsOptions, BreadcrumbList, BreadcrumbListProps, BreadcrumbPage, BreadcrumbPageProps, BreadcrumbProps, BreadcrumbSeparator, BreadcrumbSeparatorProps, breadcrumbLinkVariants } from "./Breadcrumb.js";
2
+ export { Breadcrumb, BreadcrumbEllipsis, type BreadcrumbEllipsisProps, BreadcrumbItem, type BreadcrumbItemProps, BreadcrumbLink, type BreadcrumbLinkProps, type BreadcrumbLinkVariantsOptions, BreadcrumbList, type BreadcrumbListProps, BreadcrumbPage, type BreadcrumbPageProps, type BreadcrumbProps, BreadcrumbSeparator, type BreadcrumbSeparatorProps, breadcrumbLinkVariants };
@@ -0,0 +1,2 @@
1
+ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, breadcrumbLinkVariants } from "./Breadcrumb.js";
2
+ export { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, breadcrumbLinkVariants };
@@ -0,0 +1,57 @@
1
+ import { ComponentPropsWithoutRef, ReactNode } from "react";
2
+ import { Button } from "@base-ui/react/button";
3
+ //#region src/components/Button/Button.d.ts
4
+ type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "destructive" | "link";
5
+ type ButtonSize = "sm" | "md" | "lg";
6
+ interface ButtonVariantsOptions {
7
+ variant?: ButtonVariant;
8
+ size?: ButtonSize;
9
+ fullWidth?: boolean;
10
+ iconOnly?: boolean;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * Class list for an element styled as a Button.
15
+ *
16
+ * Links must keep link semantics — never render an `<a>` through Button
17
+ * (it would receive `role="button"`). Style the anchor directly instead:
18
+ *
19
+ * <a href="/docs" className={buttonVariants({ variant: "primary" })}>Docs</a>
20
+ */
21
+ declare function buttonVariants({ variant, size, fullWidth, iconOnly, className }?: ButtonVariantsOptions): string;
22
+ interface ButtonBaseProps extends Omit<ComponentPropsWithoutRef<typeof Button>, "className"> {
23
+ /** Visual style of the button */
24
+ variant?: ButtonVariant;
25
+ /** Size of the button. `sm` (32px) meets the WCAG 2.5.8 AA target-size floor; prefer `md`/`lg` for touch-first surfaces. */
26
+ size?: ButtonSize;
27
+ /** Stretch to fill the container width */
28
+ fullWidth?: boolean;
29
+ /**
30
+ * Show a progress indicator and block interaction while keeping the button
31
+ * focusable, so keyboard/screen-reader focus is not lost mid-action.
32
+ * The button keeps its width; the label is swapped for a centered spinner
33
+ * unless `loadingText` is set.
34
+ */
35
+ loading?: boolean;
36
+ /** Visible label shown next to the spinner while `loading` (announced to screen readers). */
37
+ loadingText?: ReactNode;
38
+ /** Decorative icon before the label (hidden from assistive technology). */
39
+ startIcon?: ReactNode;
40
+ /** Decorative icon after the label (hidden from assistive technology). */
41
+ endIcon?: ReactNode;
42
+ className?: string;
43
+ }
44
+ /** Icon-only buttons have no visible label, so an accessible name is required. */
45
+ type ButtonIconOnlyProps = {
46
+ iconOnly: true;
47
+ "aria-label": string;
48
+ } | {
49
+ iconOnly: true;
50
+ "aria-labelledby": string;
51
+ } | {
52
+ iconOnly?: false;
53
+ };
54
+ type ButtonProps = ButtonBaseProps & ButtonIconOnlyProps;
55
+ declare const Button$1: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
56
+ //#endregion
57
+ export { Button$1 as Button, ButtonProps, ButtonSize, ButtonVariant, ButtonVariantsOptions, buttonVariants };
@@ -0,0 +1,177 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { forwardRef, useRef } from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import { Button } from "@base-ui/react/button";
5
+ //#region src/components/Button/Button.tsx
6
+ const baseClasses = "relative inline-flex items-center justify-center whitespace-nowrap select-none rounded-md font-sans font-semibold transition-colors duration-150 cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50";
7
+ const variantClasses = {
8
+ primary: "bg-primary text-primary-foreground hover:bg-primary-700 active:bg-primary-800",
9
+ secondary: "bg-secondary text-secondary-foreground hover:bg-primary-300 active:bg-primary-400",
10
+ outline: "border border-border bg-transparent text-foreground hover:bg-muted active:bg-slate-200",
11
+ ghost: "bg-transparent text-primary hover:bg-primary-50 active:bg-primary-100",
12
+ destructive: "bg-destructive text-destructive-foreground hover:bg-error-700 active:bg-error-800",
13
+ link: "bg-transparent text-primary underline-offset-4 hover:underline active:text-primary-800"
14
+ };
15
+ const sizeClasses = {
16
+ sm: "h-8 gap-1.5 px-3 text-sm",
17
+ md: "h-10 gap-2 px-4 text-sm",
18
+ lg: "h-12 gap-2 px-6 text-base [&_svg:not([class*='size-'])]:size-5"
19
+ };
20
+ const iconOnlySizeClasses = {
21
+ sm: "w-8 px-0",
22
+ md: "w-10 px-0",
23
+ lg: "w-12 px-0"
24
+ };
25
+ /**
26
+ * Class list for an element styled as a Button.
27
+ *
28
+ * Links must keep link semantics — never render an `<a>` through Button
29
+ * (it would receive `role="button"`). Style the anchor directly instead:
30
+ *
31
+ * <a href="/docs" className={buttonVariants({ variant: "primary" })}>Docs</a>
32
+ */
33
+ function buttonVariants({ variant = "primary", size = "md", fullWidth = false, iconOnly = false, className } = {}) {
34
+ return cn(baseClasses, variantClasses[variant], sizeClasses[size], iconOnly && iconOnlySizeClasses[size], fullWidth && "w-full", className);
35
+ }
36
+ const loadingDataAttributes = { "data-loading": "" };
37
+ const RIPPLE_DURATION_MS = 550;
38
+ const RIPPLE_EASING = "cubic-bezier(0.4, 0, 0.2, 1)";
39
+ const RIPPLE_OPACITY = .12;
40
+ const RIPPLE_TOUCH_DELAY_MS = 80;
41
+ let reducedMotionQuery;
42
+ function prefersReducedMotion() {
43
+ reducedMotionQuery ??= window.matchMedia("(prefers-reduced-motion: reduce)");
44
+ return reducedMotionQuery.matches;
45
+ }
46
+ /**
47
+ * Expand a ripple from the press point (or the center for keyboard presses).
48
+ *
49
+ * Built for cheap rendering: one geometry read followed by one style write
50
+ * (no interleaving that would force extra layouts), the circle is created at
51
+ * its final size so the Web Animation touches only compositor-friendly
52
+ * `transform`/`opacity`, and the node removes itself when the animation
53
+ * settles — WAAPI fires `finish` even for hidden elements, so unlike
54
+ * `animationend` this cannot leave orphaned nodes behind.
55
+ */
56
+ function spawnRipple(container, clientX, clientY) {
57
+ const rect = container.getBoundingClientRect();
58
+ const x = clientX === void 0 ? rect.width / 2 : clientX - rect.left;
59
+ const y = clientY === void 0 ? rect.height / 2 : clientY - rect.top;
60
+ const radius = Math.hypot(Math.max(x, rect.width - x), Math.max(y, rect.height - y));
61
+ const span = document.createElement("span");
62
+ span.style.cssText = `position:absolute;left:${x - radius}px;top:${y - radius}px;width:${radius * 2}px;height:${radius * 2}px;border-radius:50%;background-color:currentColor;pointer-events:none;`;
63
+ container.appendChild(span);
64
+ const animation = span.animate([
65
+ {
66
+ transform: "scale(0)",
67
+ opacity: RIPPLE_OPACITY
68
+ },
69
+ {
70
+ transform: "scale(1)",
71
+ opacity: RIPPLE_OPACITY,
72
+ offset: .6
73
+ },
74
+ {
75
+ transform: "scale(1)",
76
+ opacity: 0
77
+ }
78
+ ], {
79
+ duration: RIPPLE_DURATION_MS,
80
+ easing: RIPPLE_EASING
81
+ });
82
+ const cleanup = () => {
83
+ clearTimeout(fallback);
84
+ span.remove();
85
+ };
86
+ const fallback = setTimeout(cleanup, 650);
87
+ animation.onfinish = animation.oncancel = cleanup;
88
+ }
89
+ function Spinner() {
90
+ return /* @__PURE__ */ jsxs("svg", {
91
+ viewBox: "0 0 24 24",
92
+ fill: "none",
93
+ "aria-hidden": "true",
94
+ className: "animate-spin",
95
+ children: [/* @__PURE__ */ jsx("circle", {
96
+ cx: "12",
97
+ cy: "12",
98
+ r: "10",
99
+ stroke: "currentColor",
100
+ strokeWidth: "4",
101
+ className: "opacity-25"
102
+ }), /* @__PURE__ */ jsx("path", {
103
+ fill: "currentColor",
104
+ className: "opacity-75",
105
+ d: "M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
106
+ })]
107
+ });
108
+ }
109
+ const Button$1 = forwardRef(({ variant = "primary", size = "md", fullWidth = false, iconOnly = false, loading = false, loadingText, startIcon, endIcon, disabled = false, focusableWhenDisabled = false, onPointerDown, onClick, className, children, ...rest }, ref) => {
110
+ const rippleContainerRef = useRef(null);
111
+ const handleRipplePointerDown = (event) => {
112
+ const container = rippleContainerRef.current;
113
+ if (container && !prefersReducedMotion()) {
114
+ const { clientX, clientY, currentTarget } = event;
115
+ if (event.pointerType === "touch") {
116
+ let timer;
117
+ const cancel = () => clearTimeout(timer);
118
+ timer = setTimeout(() => {
119
+ currentTarget.removeEventListener("pointercancel", cancel);
120
+ spawnRipple(container, clientX, clientY);
121
+ }, RIPPLE_TOUCH_DELAY_MS);
122
+ currentTarget.addEventListener("pointercancel", cancel, { once: true });
123
+ } else spawnRipple(container, clientX, clientY);
124
+ }
125
+ onPointerDown?.(event);
126
+ };
127
+ const handleRippleClick = (event) => {
128
+ if (event.detail === 0 && rippleContainerRef.current && !prefersReducedMotion()) spawnRipple(rippleContainerRef.current);
129
+ onClick?.(event);
130
+ };
131
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
132
+ startIcon != null && /* @__PURE__ */ jsx("span", {
133
+ "aria-hidden": "true",
134
+ className: "inline-flex items-center",
135
+ children: startIcon
136
+ }),
137
+ children,
138
+ endIcon != null && /* @__PURE__ */ jsx("span", {
139
+ "aria-hidden": "true",
140
+ className: "inline-flex items-center",
141
+ children: endIcon
142
+ })
143
+ ] });
144
+ return /* @__PURE__ */ jsxs(Button, {
145
+ ref,
146
+ disabled: disabled || loading,
147
+ focusableWhenDisabled: focusableWhenDisabled || loading,
148
+ "aria-busy": loading || void 0,
149
+ onPointerDown: handleRipplePointerDown,
150
+ onClick: handleRippleClick,
151
+ className: cn(buttonVariants({
152
+ variant,
153
+ size,
154
+ fullWidth,
155
+ iconOnly
156
+ }), loading && "data-disabled:opacity-100", className),
157
+ ...loading ? loadingDataAttributes : void 0,
158
+ ...rest,
159
+ children: [/* @__PURE__ */ jsx("span", {
160
+ ref: rippleContainerRef,
161
+ "aria-hidden": "true",
162
+ className: "pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit] [contain:strict]"
163
+ }), loading ? loadingText != null ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Spinner, {}), loadingText] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
164
+ className: "absolute inset-0 flex items-center justify-center",
165
+ children: [/* @__PURE__ */ jsx(Spinner, {}), /* @__PURE__ */ jsx("span", {
166
+ className: "sr-only",
167
+ children: "Loading"
168
+ })]
169
+ }), /* @__PURE__ */ jsx("span", {
170
+ className: "invisible contents",
171
+ children: content
172
+ })] }) : content]
173
+ });
174
+ });
175
+ Button$1.displayName = "Button";
176
+ //#endregion
177
+ export { Button$1 as Button, buttonVariants };
@@ -0,0 +1,2 @@
1
+ import { Button, ButtonProps, ButtonSize, ButtonVariant, ButtonVariantsOptions, buttonVariants } from "./Button.js";
2
+ export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type ButtonVariantsOptions, buttonVariants };
@@ -0,0 +1,2 @@
1
+ import { Button, buttonVariants } from "./Button.js";
2
+ export { Button, buttonVariants };
@@ -0,0 +1,140 @@
1
+ import { ComponentPropsWithoutRef } from "react";
2
+ import { useRender } from "@base-ui/react/use-render";
3
+ //#region src/components/Calendar/Calendar.d.ts
4
+ type CalendarMode = "single" | "multiple" | "range";
5
+ /** Inclusive date range. `onValueChange` only ever emits complete ranges. */
6
+ interface CalendarDateRange {
7
+ start: Date;
8
+ end: Date;
9
+ }
10
+ /** State passed to the `render` callback (also exposed as root data-attributes). */
11
+ type CalendarState = {
12
+ mode: CalendarMode;
13
+ disabled: boolean;
14
+ readOnly: boolean;
15
+ };
16
+ interface CalendarBaseProps extends Omit<ComponentPropsWithoutRef<"div">, "className" | "children" | "defaultValue"> {
17
+ /**
18
+ * Month shown in the first grid (controlled). Any day of the month works;
19
+ * it is normalized to the first. Pair with `onMonthChange`.
20
+ */
21
+ month?: Date;
22
+ /**
23
+ * Initial visible month (uncontrolled). Defaults to the month of the first
24
+ * selected date, else the current month.
25
+ */
26
+ defaultMonth?: Date;
27
+ /** Called when the visible month changes (navigation buttons or keyboard paging). */
28
+ onMonthChange?: (month: Date) => void;
29
+ /**
30
+ * Months rendered side by side (wraps on narrow containers). Navigation
31
+ * pages by this amount so months never repeat across a page turn.
32
+ * @default 1
33
+ */
34
+ numberOfMonths?: number;
35
+ /**
36
+ * Earliest selectable day. Days before it are hard-disabled: dimmed,
37
+ * skipped by keyboard focus, and the previous-month button disables at
38
+ * the boundary.
39
+ */
40
+ minDate?: Date;
41
+ /** Latest selectable day — the `minDate` counterpart. */
42
+ maxDate?: Date;
43
+ /**
44
+ * Marks days as unavailable (e.g. sold out). Unlike `minDate`/`maxDate`,
45
+ * unavailable days stay keyboard-focusable and readable (WCAG 4.5:1) so
46
+ * screen-reader users can discover them — they just can't be selected.
47
+ * In `range` mode a pending selection is limited to the contiguous
48
+ * available run around its start date.
49
+ */
50
+ isDateUnavailable?: (date: Date) => boolean;
51
+ /** Disable the whole calendar: selection and navigation. */
52
+ disabled?: boolean;
53
+ /** Keep the calendar navigable but ignore selection — for display-only surfaces. */
54
+ readOnly?: boolean;
55
+ /**
56
+ * BCP-47 tag (e.g. `"en-US"`, `"th-TH"`) for the caption, weekday names,
57
+ * day numerals, and day-cell accessible labels via `Intl.DateTimeFormat`.
58
+ * Defaults to the runtime locale. Rendering stays Gregorian, but locales
59
+ * with a different default calendar display accordingly (Thai → Buddhist-era
60
+ * years).
61
+ */
62
+ locale?: string;
63
+ /**
64
+ * First day of the week: 0 = Sunday … 6 = Saturday. Defaults to the
65
+ * locale's week convention when the runtime exposes it, else Sunday.
66
+ */
67
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
68
+ /**
69
+ * Show the leading/trailing days of adjacent months. They are inert
70
+ * (visual continuity only) and hidden from assistive technology.
71
+ * @default true
72
+ */
73
+ showOutsideDays?: boolean;
74
+ /**
75
+ * Always render six weeks per month so the calendar height never changes
76
+ * while paging — recommended inside popovers.
77
+ * @default false
78
+ */
79
+ fixedWeeks?: boolean;
80
+ /**
81
+ * The day highlighted as "today" (`aria-current="date"`). Defaults to the
82
+ * current date; pin it in tests and visual baselines for determinism.
83
+ */
84
+ today?: Date;
85
+ /** Move focus to the focus-target day (selected → today → first enabled) on mount. */
86
+ autoFocus?: boolean;
87
+ /**
88
+ * Accessible label for the previous-month navigation button.
89
+ * @default "Previous month"
90
+ */
91
+ previousMonthLabel?: string;
92
+ /**
93
+ * Accessible label for the next-month navigation button.
94
+ * @default "Next month"
95
+ */
96
+ nextMonthLabel?: string;
97
+ className?: string;
98
+ /** Replace the root element — Base UI's composition prop. */
99
+ render?: useRender.RenderProp<CalendarState>;
100
+ }
101
+ /** Selection props follow `mode`, so a mismatched value shape fails to compile. */
102
+ type CalendarModeProps = {
103
+ /** Selection behavior. `single` picks one date. @default "single" */
104
+ mode?: "single";
105
+ /** Selected date (controlled). `null` = empty. */
106
+ value?: Date | null;
107
+ /** Initial selected date (uncontrolled). */
108
+ defaultValue?: Date | null;
109
+ /** Called with the new date, or `null` when deselected via `allowDeselect`. */
110
+ onValueChange?: (value: Date | null) => void;
111
+ /**
112
+ * Let clicking the selected date clear it — for optional filters.
113
+ * @default false
114
+ */
115
+ allowDeselect?: boolean;
116
+ } | {
117
+ /** `multiple` toggles any number of dates. */
118
+ mode: "multiple";
119
+ /** Selected dates (controlled), kept sorted ascending. */
120
+ value?: Date[];
121
+ /** Initial selected dates (uncontrolled). */
122
+ defaultValue?: Date[];
123
+ /** Called with the new sorted date list after every toggle. */
124
+ onValueChange?: (value: Date[]) => void;
125
+ allowDeselect?: never;
126
+ } | {
127
+ /** `range` picks a start and end with a live preview in between. */
128
+ mode: "range";
129
+ /** Selected range (controlled). `null` = empty. */
130
+ value?: CalendarDateRange | null;
131
+ /** Initial selected range (uncontrolled). */
132
+ defaultValue?: CalendarDateRange | null;
133
+ /** Called only with complete `{ start, end }` ranges (ends ordered, never inverted). */
134
+ onValueChange?: (value: CalendarDateRange | null) => void;
135
+ allowDeselect?: never;
136
+ };
137
+ type CalendarProps = CalendarBaseProps & CalendarModeProps;
138
+ declare const Calendar: import("react").ForwardRefExoticComponent<CalendarProps & import("react").RefAttributes<HTMLDivElement>>;
139
+ //#endregion
140
+ export { Calendar, CalendarDateRange, CalendarMode, CalendarProps, CalendarState };