@ttt-productions/ui-core 0.11.14 → 0.11.16

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 (98) hide show
  1. package/dist/react/components/alert-dialog.js +2 -2
  2. package/dist/react/components/alert-dialog.js.map +1 -1
  3. package/dist/react/components/avatar.js +1 -1
  4. package/dist/react/components/avatar.js.map +1 -1
  5. package/dist/react/components/badge.d.ts +2 -2
  6. package/dist/react/components/button.d.ts +11 -2
  7. package/dist/react/components/button.d.ts.map +1 -1
  8. package/dist/react/components/button.js +20 -7
  9. package/dist/react/components/button.js.map +1 -1
  10. package/dist/react/components/card.js +1 -1
  11. package/dist/react/components/card.js.map +1 -1
  12. package/dist/react/components/chunk-error-recovery.js +2 -2
  13. package/dist/react/components/chunk-error-recovery.js.map +1 -1
  14. package/dist/react/components/consequence-dialog.d.ts +1 -1
  15. package/dist/react/components/consequence-dialog.d.ts.map +1 -1
  16. package/dist/react/components/consequence-dialog.js +2 -3
  17. package/dist/react/components/consequence-dialog.js.map +1 -1
  18. package/dist/react/components/dialog.js +2 -2
  19. package/dist/react/components/dialog.js.map +1 -1
  20. package/dist/react/components/dropdown-menu.d.ts +8 -0
  21. package/dist/react/components/dropdown-menu.d.ts.map +1 -1
  22. package/dist/react/components/dropdown-menu.js +5 -3
  23. package/dist/react/components/dropdown-menu.js.map +1 -1
  24. package/dist/react/components/end-of-list-indicator.js +1 -1
  25. package/dist/react/components/end-of-list-indicator.js.map +1 -1
  26. package/dist/react/components/input.js +1 -1
  27. package/dist/react/components/input.js.map +1 -1
  28. package/dist/react/components/list-pagination.d.ts.map +1 -1
  29. package/dist/react/components/list-pagination.js +19 -1
  30. package/dist/react/components/list-pagination.js.map +1 -1
  31. package/dist/react/components/menubar.js +1 -1
  32. package/dist/react/components/menubar.js.map +1 -1
  33. package/dist/react/components/popover.js +1 -1
  34. package/dist/react/components/popover.js.map +1 -1
  35. package/dist/react/components/scroll-to-top-button.js +1 -1
  36. package/dist/react/components/scroll-to-top-button.js.map +1 -1
  37. package/dist/react/components/search-dropdown.d.ts.map +1 -1
  38. package/dist/react/components/search-dropdown.js +3 -2
  39. package/dist/react/components/search-dropdown.js.map +1 -1
  40. package/dist/react/components/select.d.ts +8 -1
  41. package/dist/react/components/select.d.ts.map +1 -1
  42. package/dist/react/components/select.js +3 -2
  43. package/dist/react/components/select.js.map +1 -1
  44. package/dist/react/components/sheet.js +2 -2
  45. package/dist/react/components/sheet.js.map +1 -1
  46. package/dist/react/components/spinner.d.ts +23 -0
  47. package/dist/react/components/spinner.d.ts.map +1 -0
  48. package/dist/react/components/spinner.js +27 -0
  49. package/dist/react/components/spinner.js.map +1 -0
  50. package/dist/react/components/switch.d.ts +8 -1
  51. package/dist/react/components/switch.d.ts.map +1 -1
  52. package/dist/react/components/switch.js +2 -1
  53. package/dist/react/components/switch.js.map +1 -1
  54. package/dist/react/components/table.js +1 -1
  55. package/dist/react/components/table.js.map +1 -1
  56. package/dist/react/components/tabs.js +1 -1
  57. package/dist/react/components/tabs.js.map +1 -1
  58. package/dist/react/components/textarea.js +1 -1
  59. package/dist/react/components/textarea.js.map +1 -1
  60. package/dist/react/components/toast.js +5 -5
  61. package/dist/react/components/toast.js.map +1 -1
  62. package/dist/react/components/tooltip.js +1 -1
  63. package/dist/react/components/tooltip.js.map +1 -1
  64. package/dist/react/hooks/use-async-action.d.ts +30 -0
  65. package/dist/react/hooks/use-async-action.d.ts.map +1 -0
  66. package/dist/react/hooks/use-async-action.js +39 -0
  67. package/dist/react/hooks/use-async-action.js.map +1 -0
  68. package/dist/react/index.d.ts +4 -0
  69. package/dist/react/index.d.ts.map +1 -1
  70. package/dist/react/index.js +2 -0
  71. package/dist/react/index.js.map +1 -1
  72. package/package.json +8 -4
  73. package/src/react/components/alert-dialog.tsx +2 -2
  74. package/src/react/components/avatar.tsx +1 -1
  75. package/src/react/components/button.tsx +48 -12
  76. package/src/react/components/card.tsx +1 -1
  77. package/src/react/components/chunk-error-recovery.tsx +2 -2
  78. package/src/react/components/consequence-dialog.tsx +4 -6
  79. package/src/react/components/dialog.tsx +2 -2
  80. package/src/react/components/dropdown-menu.tsx +21 -4
  81. package/src/react/components/end-of-list-indicator.tsx +1 -1
  82. package/src/react/components/input.tsx +1 -1
  83. package/src/react/components/list-pagination.tsx +24 -4
  84. package/src/react/components/menubar.tsx +1 -1
  85. package/src/react/components/popover.tsx +1 -1
  86. package/src/react/components/scroll-to-top-button.tsx +1 -1
  87. package/src/react/components/search-dropdown.tsx +5 -4
  88. package/src/react/components/select.tsx +20 -6
  89. package/src/react/components/sheet.tsx +2 -2
  90. package/src/react/components/spinner.tsx +49 -0
  91. package/src/react/components/switch.tsx +16 -4
  92. package/src/react/components/table.tsx +1 -1
  93. package/src/react/components/tabs.tsx +2 -2
  94. package/src/react/components/textarea.tsx +1 -1
  95. package/src/react/components/toast.tsx +5 -5
  96. package/src/react/components/tooltip.tsx +1 -1
  97. package/src/react/hooks/use-async-action.ts +63 -0
  98. package/src/react/index.ts +5 -0
@@ -29,8 +29,8 @@ const TabsTrigger = React.forwardRef<
29
29
  <TabsPrimitive.Trigger
30
30
  ref={ref}
31
31
  className={cn(
32
- "inline-flex items-center justify-center whitespace-nowrap rounded-xs px-3 py-1.5 text-sm !font-bold ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
33
- "data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:shadow-xs data-[state=active]:border-2 data-[state=active]:border-[hsl(var(--brand-primary-deep))]",
32
+ "tabs-trigger inline-flex items-center justify-center whitespace-nowrap rounded-xs px-3 py-1.5 text-sm !font-bold ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
33
+ "data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=active]:border-2 data-[state=active]:border-[hsl(var(--brand-primary-deep))]",
34
34
  "data-[state=inactive]:border data-[state=inactive]:border-border data-[state=inactive]:bg-background data-[state=inactive]:hover:bg-accent data-[state=inactive]:hover:text-accent-foreground",
35
35
  className
36
36
  )}
@@ -8,7 +8,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"tex
8
8
  return (
9
9
  <textarea
10
10
  className={cn(
11
- "flex min-h-[80px] w-full rounded-md border-2 border-border bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
+ "flex min-h-[80px] w-full rounded-md border-2 border-input bg-background px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
12
  className
13
13
  )}
14
14
  ref={ref}
@@ -25,7 +25,7 @@ function ToastKeyframes() {
25
25
  const toastVariants = cva(
26
26
  cn(
27
27
  // base
28
- "pointer-events-auto relative flex w-full items-start justify-between gap-2 overflow-hidden rounded-md border bg-background p-4 text-foreground shadow-lg transition-all",
28
+ "pointer-events-auto relative flex w-full items-start justify-between gap-2 overflow-hidden rounded-md border bg-background p-4 text-foreground elevation-raised transition-all",
29
29
  // radix state/animation
30
30
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
31
31
  "data-[state=closed]:fade-out-80 data-[state=open]:fade-in-80",
@@ -38,10 +38,10 @@ const toastVariants = cva(
38
38
  variants: {
39
39
  variant: {
40
40
  default: "",
41
- destructive: "border-red-700 bg-red-600 text-white",
42
- success: "border-emerald-700 bg-emerald-600 text-white",
43
- warning: "border-amber-600 bg-amber-500 text-black",
44
- error: "border-red-700 bg-red-600 text-white",
41
+ destructive: "border-[color:var(--toast-destructive-border)] bg-[color:var(--toast-destructive)] text-[color:var(--toast-destructive-foreground)]",
42
+ success: "border-[color:var(--toast-success-border)] bg-[color:var(--toast-success)] text-[color:var(--toast-success-foreground)]",
43
+ warning: "border-[color:var(--toast-warning-border)] bg-[color:var(--toast-warning)] text-[color:var(--toast-warning-foreground)]",
44
+ error: "border-[color:var(--toast-destructive-border)] bg-[color:var(--toast-destructive)] text-[color:var(--toast-destructive-foreground)]",
45
45
  },
46
46
  },
47
47
  defaultVariants: {
@@ -17,7 +17,7 @@ const TooltipContent = React.forwardRef<
17
17
  ref={ref}
18
18
  sideOffset={sideOffset}
19
19
  className={cn(
20
- "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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",
20
+ "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground elevation-popover animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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",
21
21
  className
22
22
  )}
23
23
  {...props}
@@ -0,0 +1,63 @@
1
+ "use client";
2
+
3
+ import { useCallback, useRef, useState } from "react";
4
+
5
+ export interface UseAsyncActionOptions {
6
+ /**
7
+ * Receives anything the action throws. REQUIRED, so every call site decides what a
8
+ * failure means (surface it, capture it, or accept that another layer already did):
9
+ * `run` itself never rejects, so a fire-and-forget `onClick={() => void run()}` can
10
+ * never become an unhandled rejection.
11
+ */
12
+ onError: (error: unknown) => void;
13
+ }
14
+
15
+ export interface AsyncAction<TArgs extends unknown[]> {
16
+ /**
17
+ * Starts the action unless one is already in flight — a repeat call while pending is
18
+ * ignored. Resolves once the action settles: `true` when it completed, `false` when it
19
+ * was ignored or threw. Never rejects.
20
+ */
21
+ run: (...args: TArgs) => Promise<boolean>;
22
+ /** True from the moment `run` starts the action until it settles. */
23
+ pending: boolean;
24
+ }
25
+
26
+ /**
27
+ * Pending state + repeat guard for async work that is NOT a React Query mutation
28
+ * (a local media step, a sign-out, an awaited navigation). Feed `pending` to the
29
+ * control's own `pending` prop. Server writes stay mutations — this hook does not
30
+ * replace the data layer's one mutation path.
31
+ *
32
+ * The guard is a ref, not the state, so two clicks inside one frame cannot both start
33
+ * the action.
34
+ */
35
+ export function useAsyncAction<TArgs extends unknown[]>(
36
+ action: (...args: TArgs) => Promise<unknown>,
37
+ options: UseAsyncActionOptions,
38
+ ): AsyncAction<TArgs> {
39
+ const [pending, setPending] = useState(false);
40
+ const inFlightRef = useRef(false);
41
+ const actionRef = useRef(action);
42
+ const onErrorRef = useRef(options.onError);
43
+ actionRef.current = action;
44
+ onErrorRef.current = options.onError;
45
+
46
+ const run = useCallback(async (...args: TArgs): Promise<boolean> => {
47
+ if (inFlightRef.current) return false;
48
+ inFlightRef.current = true;
49
+ setPending(true);
50
+ try {
51
+ await actionRef.current(...args);
52
+ return true;
53
+ } catch (error) {
54
+ onErrorRef.current(error);
55
+ return false;
56
+ } finally {
57
+ inFlightRef.current = false;
58
+ setPending(false);
59
+ }
60
+ }, []);
61
+
62
+ return { run, pending };
63
+ }
@@ -2,6 +2,8 @@
2
2
 
3
3
  export type { ButtonProps } from "./components/button.js";
4
4
  export { Button, buttonVariants } from "./components/button.js";
5
+ export type { SpinnerProps, SpinnerSize } from "./components/spinner.js";
6
+ export { Spinner } from "./components/spinner.js";
5
7
  export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from "./components/card.js";
6
8
  export { Label } from "./components/label.js";
7
9
  export { Textarea } from "./components/textarea.js";
@@ -49,6 +51,9 @@ export { ScreenAdaptiveView } from "./components/layout/screen-adaptive-view.js"
49
51
 
50
52
  export { useMediaQuery } from "./hooks/use-media-query.js";
51
53
 
54
+ export { useAsyncAction } from "./hooks/use-async-action.js";
55
+ export type { AsyncAction, UseAsyncActionOptions } from "./hooks/use-async-action.js";
56
+
52
57
  // Shared building blocks
53
58
  export { RelativeTime } from "./components/relative-time.js";
54
59
  export type { RelativeTimeProps } from "./components/relative-time.js";