@bubo-squared/ui-framework 0.2.19 → 0.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -93,10 +93,40 @@ function cn(...inputs) {
93
93
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
94
94
  }
95
95
 
96
+ // src/lib/ripple.ts
97
+ function removeExistingRipples(target) {
98
+ const ripples = target.querySelectorAll(".bubo-ripple");
99
+ ripples.forEach((node) => node.remove());
100
+ }
101
+ function spawnRipple(target, clientX, clientY, options = {}) {
102
+ if (typeof window === "undefined" || typeof document === "undefined") return;
103
+ const rect = target.getBoundingClientRect();
104
+ const x = clientX - rect.left;
105
+ const y = clientY - rect.top;
106
+ const radius = Math.sqrt(rect.width * rect.width + rect.height * rect.height);
107
+ const size = radius * 2;
108
+ removeExistingRipples(target);
109
+ const ripple = document.createElement("span");
110
+ ripple.className = "bubo-ripple";
111
+ ripple.style.width = `${size}px`;
112
+ ripple.style.height = `${size}px`;
113
+ ripple.style.left = `${x - radius}px`;
114
+ ripple.style.top = `${y - radius}px`;
115
+ const durationMs = options.durationMs ?? 500;
116
+ ripple.style.animationDuration = `${durationMs}ms`;
117
+ const cleanup = () => {
118
+ ripple.removeEventListener("animationend", cleanup);
119
+ ripple.remove();
120
+ };
121
+ ripple.addEventListener("animationend", cleanup);
122
+ target.appendChild(ripple);
123
+ window.setTimeout(cleanup, durationMs + 50);
124
+ }
125
+
96
126
  // src/components/Buttons/Button.tsx
97
127
  var import_jsx_runtime2 = require("react/jsx-runtime");
98
128
  var buttonVariants = (0, import_class_variance_authority.cva)(
99
- "inline-flex items-center justify-center whitespace-nowrap rounded-4 transition-colors disabled:pointer-events-none overflow-hidden cursor-pointer",
129
+ "relative inline-flex items-center justify-center whitespace-nowrap rounded-4 transition-colors disabled:pointer-events-none overflow-hidden cursor-pointer",
100
130
  {
101
131
  variants: {
102
132
  variant: {
@@ -163,14 +193,23 @@ var Button = React.forwardRef(
163
193
  children,
164
194
  trailingIcon,
165
195
  leadingIcon,
196
+ onPointerDown,
166
197
  ...rest
167
198
  } = props;
168
199
  const Comp = asChild ? import_react_slot.Slot : "button";
200
+ const handlePointerDown = (e) => {
201
+ onPointerDown?.(e);
202
+ if (e.defaultPrevented) return;
203
+ if (rest.disabled) return;
204
+ if (e.button !== 0 || !e.isPrimary) return;
205
+ spawnRipple(e.currentTarget, e.clientX, e.clientY);
206
+ };
169
207
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
170
208
  Comp,
171
209
  {
172
210
  className: cn(buttonVariants({ variant, size, className })),
173
211
  ref,
212
+ onPointerDown: handlePointerDown,
174
213
  ...rest,
175
214
  children: [
176
215
  leadingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn(buttonIconVariants({ size })), children: leadingIcon }),
@@ -223,7 +262,7 @@ var import_react_slot2 = require("@radix-ui/react-slot");
223
262
  var import_class_variance_authority3 = require("class-variance-authority");
224
263
  var import_jsx_runtime4 = require("react/jsx-runtime");
225
264
  var iconButtonVariants = (0, import_class_variance_authority3.cva)(
226
- "inline-flex items-center justify-center whitespace-nowrap transition-colors disabled:pointer-events-none overflow-hidden p-2 cursor-pointer",
265
+ "relative inline-flex items-center justify-center whitespace-nowrap transition-colors disabled:pointer-events-none overflow-hidden p-2 cursor-pointer",
227
266
  {
228
267
  variants: {
229
268
  variant: {
@@ -269,14 +308,23 @@ var IconButton = React2.forwardRef(
269
308
  asChild = false,
270
309
  icon,
271
310
  round = false,
311
+ onPointerDown,
272
312
  ...rest
273
313
  } = props;
274
314
  const Comp = asChild ? import_react_slot2.Slot : "button";
315
+ const handlePointerDown = (e) => {
316
+ onPointerDown?.(e);
317
+ if (e.defaultPrevented) return;
318
+ if (rest.disabled) return;
319
+ if (e.button !== 0 || !e.isPrimary) return;
320
+ spawnRipple(e.currentTarget, e.clientX, e.clientY);
321
+ };
275
322
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
276
323
  Comp,
277
324
  {
278
325
  className: cn(iconButtonVariants({ variant, size }), round ? "rounded-full" : "rounded-4", className),
279
326
  ref,
327
+ onPointerDown: handlePointerDown,
280
328
  ...rest,
281
329
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "buttonIcon flex items-center justify-center", children: icon })
282
330
  }
@@ -3213,10 +3261,11 @@ var Tooltip = (props) => {
3213
3261
  open,
3214
3262
  defaultOpen,
3215
3263
  onOpenChange,
3216
- children
3264
+ children,
3265
+ delayDuration = 200
3217
3266
  } = props;
3218
3267
  const { side, align } = mapPlacementToSideAndAlign(placement);
3219
- const tooltipClasses = "group bg-(--background-tooltip) max-w-[calc(100vw-2rem)] shadow-card-md border-none rounded-4 p-4 [&>span]:scale-200 data-[state=delayed-open]:animate-in data-[state=instant-open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0 data-[state=instant-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2";
3268
+ const tooltipClasses = "group bg-(--background-tooltip) max-w-[calc(100vw-2rem)] shadow-card-md border-none rounded-4 py-1.5 px-2.5 [&>span]:scale-200 data-[state=delayed-open]:animate-in data-[state=instant-open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0 data-[state=instant-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2";
3220
3269
  const tooltipArrowClasses = "relative fill-(--background-tooltip) transition-[filter,transform] group-data-[side=top]:top-[-2px] group-data-[side=top]:drop-shadow-[0px_1px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=bottom]:drop-shadow-[0px_1px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=left]:drop-shadow-[0px_2px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)] group-data-[side=right]:drop-shadow-[0px_2px_1px_color-mix(in_srgb,_var(--color-b-black-10)_66%,_transparent)]";
3221
3270
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
3222
3271
  TooltipPrimitive.Root,
@@ -3225,6 +3274,7 @@ var Tooltip = (props) => {
3225
3274
  defaultOpen,
3226
3275
  onOpenChange,
3227
3276
  disableHoverableContent,
3277
+ delayDuration,
3228
3278
  children: [
3229
3279
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TooltipPrimitive.Trigger, { asChild: true, children }),
3230
3280
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
@@ -3236,9 +3286,9 @@ var Tooltip = (props) => {
3236
3286
  className: cn(tooltipClasses, className),
3237
3287
  children: [
3238
3288
  showArrow && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TooltipArrow, { className: tooltipArrowClasses }),
3239
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid gap-2", children: [
3289
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid", children: [
3240
3290
  (strapline ?? "") !== "" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "caption text-secondary", children: strapline }),
3241
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h4", { className: "subtitle-medium text-primary", children: title }),
3291
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h4", { className: "paragraph-md text-primary", children: title }),
3242
3292
  (description ?? "") !== "" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "paragraph-sm text-primary", children: description })
3243
3293
  ] })
3244
3294
  ]
@@ -3698,10 +3748,10 @@ var TextArea = (props) => {
3698
3748
  success: "border-(--border-success)",
3699
3749
  error: "border-(--border-error)"
3700
3750
  };
3701
- const statusFocusClass = {
3702
- default: "focus-within:border-(--border-brand) focus-within:hover:border-(--border-brand) focus-within:shadow-[0_0_0_var(--focus-ring-spread)_var(--focus-primary)]",
3703
- success: "focus-within:border-(--border-success) focus-within:hover:border-(--border-success) focus-within:shadow-[0_0_0_var(--focus-ring-spread)_var(--focus-success)]",
3704
- error: "focus-within:border-(--border-error) focus-within:hover:border-(--border-error) focus-within:shadow-[0_0_0_var(--focus-ring-spread)_var(--focus-error)]"
3751
+ const statusShellClass = {
3752
+ default: "input-default",
3753
+ success: "input-success",
3754
+ error: "input-error"
3705
3755
  };
3706
3756
  const counterColorClass = disabled ? "text-primary-disabled" : status === "success" ? "text-(--color-success)" : status === "error" ? "text-(--color-error)" : "text-primary";
3707
3757
  const handleResizePointerDown = (event) => {
@@ -3741,11 +3791,11 @@ var TextArea = (props) => {
3741
3791
  "div",
3742
3792
  {
3743
3793
  className: cn(
3744
- "relative flex w-full rounded-4 border bg-(--background-primary) cursor-text transition-colors",
3745
- "border-(--border-secondary) hover:border-(--border-secondary-hover) hover:bg-(--background-primary-hover)",
3794
+ "relative flex w-full rounded-4 border bg-(--background-primary) cursor-text",
3795
+ "border-(--border-secondary)",
3796
+ statusShellClass[status],
3746
3797
  disabled && "bg-(--background-primary-disabled) border-(--border-secondary-disabled) cursor-default",
3747
3798
  statusBorderClass[status],
3748
- !disabled && statusFocusClass[status],
3749
3799
  className
3750
3800
  ),
3751
3801
  ref: containerRef,