@robomous/ui-core 0.1.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 (135) hide show
  1. package/README.md +19 -7
  2. package/dist/{primitives → components}/alert.js +1 -1
  3. package/dist/{primitives → components}/badge.js +1 -1
  4. package/dist/{primitives → components}/button.d.ts +1 -1
  5. package/dist/{primitives → components}/button.js +4 -1
  6. package/dist/{primitives → components}/card.d.ts +1 -1
  7. package/dist/{primitives → components}/card.js +2 -2
  8. package/dist/{primitives → components}/combobox.js +4 -4
  9. package/dist/{primitives → components}/dialog.js +1 -1
  10. package/dist/{primitives → components}/dropdown-menu.js +12 -7
  11. package/dist/{primitives → components}/field.js +2 -4
  12. package/dist/{primitives → components}/input-group.js +1 -1
  13. package/dist/{primitives → components}/input.js +1 -1
  14. package/dist/{primitives → components}/label.js +1 -1
  15. package/dist/components/progress.js +7 -0
  16. package/dist/{primitives → components}/select.d.ts +3 -1
  17. package/dist/{primitives → components}/select.js +7 -4
  18. package/dist/{primitives → components}/separator.js +1 -1
  19. package/dist/{primitives → components}/sheet.js +1 -1
  20. package/dist/{primitives → components}/skeleton.js +1 -1
  21. package/dist/{primitives → components}/sonner.js +17 -12
  22. package/dist/{primitives → components}/table.d.ts +1 -1
  23. package/dist/{primitives → components}/table.js +3 -3
  24. package/dist/{primitives → components}/tabs.js +1 -1
  25. package/dist/{primitives → components}/textarea.js +1 -1
  26. package/dist/{primitives → components}/tooltip.js +1 -1
  27. package/dist/gates/index.d.ts +28 -0
  28. package/dist/gates/index.js +142 -0
  29. package/dist/index.d.ts +31 -32
  30. package/dist/index.js +32 -33
  31. package/dist/{tokens.d.ts → theme/tokens.d.ts} +5 -5
  32. package/dist/{tokens.js → theme/tokens.js} +12 -12
  33. package/package.json +23 -12
  34. package/{shadcn → src/components}/alert.tsx +14 -21
  35. package/src/{primitives → components}/badge.tsx +15 -21
  36. package/src/{primitives → components}/button.tsx +13 -10
  37. package/{shadcn → src/components}/card.tsx +16 -31
  38. package/src/{primitives → components}/combobox.test.tsx +15 -2
  39. package/src/{primitives → components}/combobox.tsx +45 -74
  40. package/src/{primitives/primitives.test.tsx → components/components.test.tsx} +106 -69
  41. package/src/{primitives → components}/dialog.tsx +31 -54
  42. package/src/{primitives → components}/dropdown-menu.tsx +51 -65
  43. package/src/{primitives → components}/field.tsx +48 -62
  44. package/src/{primitives → components}/input-group.tsx +37 -49
  45. package/{shadcn → src/components}/input.tsx +5 -5
  46. package/{shadcn → src/components}/label.tsx +7 -10
  47. package/src/{primitives → components}/progress.tsx +7 -6
  48. package/{shadcn → src/components}/select.tsx +40 -40
  49. package/{shadcn → src/components}/separator.tsx +7 -7
  50. package/src/{primitives → components}/sheet.tsx +27 -44
  51. package/{shadcn → src/components}/skeleton.tsx +3 -3
  52. package/src/{primitives → components}/sonner.test.tsx +12 -4
  53. package/src/components/sonner.tsx +67 -0
  54. package/{shadcn → src/components}/table.tsx +17 -44
  55. package/{shadcn → src/components}/tabs.tsx +16 -26
  56. package/{shadcn → src/components}/textarea.tsx +5 -5
  57. package/{shadcn → src/components}/tooltip.tsx +12 -16
  58. package/src/gates/design.test.ts +188 -0
  59. package/src/gates/index.test.ts +11 -0
  60. package/src/gates/index.ts +165 -0
  61. package/src/gates/tokens.test.ts +215 -0
  62. package/src/harness.test.tsx +1 -1
  63. package/src/index.ts +63 -33
  64. package/src/theme/imports.test.ts +160 -0
  65. package/src/{statusTone.test.ts → theme/statusTone.test.ts} +5 -1
  66. package/src/{styles.css → theme/styles.css} +45 -31
  67. package/src/theme/tailwind.css +646 -0
  68. package/src/{tokens.test.ts → theme/tokens.test.ts} +30 -23
  69. package/src/{tokens.ts → theme/tokens.ts} +12 -12
  70. package/components.json +0 -13
  71. package/dist/lib/button.d.ts +0 -1
  72. package/dist/lib/button.js +0 -4
  73. package/dist/lib/cn.d.ts +0 -18
  74. package/dist/lib/cn.js +0 -21
  75. package/dist/lib/menu.d.ts +0 -1
  76. package/dist/lib/menu.js +0 -16
  77. package/dist/lib/progress.d.ts +0 -3
  78. package/dist/lib/progress.js +0 -6
  79. package/dist/lib/select.d.ts +0 -1
  80. package/dist/lib/select.js +0 -3
  81. package/dist/primitives/progress.js +0 -7
  82. package/gates/canonical.test.mjs +0 -71
  83. package/gates/extensions.test.mjs +0 -373
  84. package/gates/index.d.mts +0 -51
  85. package/gates/index.mjs +0 -514
  86. package/gates/tokens.test.mjs +0 -276
  87. package/shadcn/README.md +0 -13
  88. package/shadcn/badge.tsx +0 -49
  89. package/shadcn/button.tsx +0 -67
  90. package/shadcn/combobox.tsx +0 -299
  91. package/shadcn/dialog.tsx +0 -166
  92. package/shadcn/dropdown-menu.tsx +0 -267
  93. package/shadcn/field.tsx +0 -236
  94. package/shadcn/input-group.tsx +0 -154
  95. package/shadcn/progress.tsx +0 -29
  96. package/shadcn/sheet.tsx +0 -145
  97. package/shadcn/sonner.tsx +0 -49
  98. package/src/lib/button.ts +0 -4
  99. package/src/lib/cn.test.ts +0 -33
  100. package/src/lib/cn.ts +0 -23
  101. package/src/lib/menu.ts +0 -16
  102. package/src/lib/progress.ts +0 -6
  103. package/src/lib/select.ts +0 -4
  104. package/src/primitives/alert.tsx +0 -76
  105. package/src/primitives/card.tsx +0 -103
  106. package/src/primitives/input.tsx +0 -19
  107. package/src/primitives/label.tsx +0 -22
  108. package/src/primitives/select.tsx +0 -190
  109. package/src/primitives/separator.tsx +0 -28
  110. package/src/primitives/skeleton.tsx +0 -13
  111. package/src/primitives/sonner.tsx +0 -65
  112. package/src/primitives/table.tsx +0 -114
  113. package/src/primitives/tabs.tsx +0 -88
  114. package/src/primitives/textarea.tsx +0 -18
  115. package/src/primitives/tooltip.tsx +0 -57
  116. /package/dist/{primitives → components}/alert.d.ts +0 -0
  117. /package/dist/{primitives → components}/badge.d.ts +0 -0
  118. /package/dist/{primitives → components}/combobox.d.ts +0 -0
  119. /package/dist/{primitives → components}/dialog.d.ts +0 -0
  120. /package/dist/{primitives → components}/dropdown-menu.d.ts +0 -0
  121. /package/dist/{primitives → components}/field.d.ts +0 -0
  122. /package/dist/{primitives → components}/input-group.d.ts +0 -0
  123. /package/dist/{primitives → components}/input.d.ts +0 -0
  124. /package/dist/{primitives → components}/label.d.ts +0 -0
  125. /package/dist/{primitives → components}/progress.d.ts +0 -0
  126. /package/dist/{primitives → components}/separator.d.ts +0 -0
  127. /package/dist/{primitives → components}/sheet.d.ts +0 -0
  128. /package/dist/{primitives → components}/skeleton.d.ts +0 -0
  129. /package/dist/{primitives → components}/sonner.d.ts +0 -0
  130. /package/dist/{primitives → components}/tabs.d.ts +0 -0
  131. /package/dist/{primitives → components}/textarea.d.ts +0 -0
  132. /package/dist/{primitives → components}/tooltip.d.ts +0 -0
  133. /package/dist/{statusTone.d.ts → theme/statusTone.d.ts} +0 -0
  134. /package/dist/{statusTone.js → theme/statusTone.js} +0 -0
  135. /package/src/{statusTone.ts → theme/statusTone.ts} +0 -0
@@ -1,20 +1,16 @@
1
1
  /**
2
- * The component harness, proved on the primitives that carry a decision.
2
+ * The component harness, proved on the components that carry a decision.
3
3
  *
4
- * Not a snapshot of every class string that would pin the design system to
5
- * whatever it happened to be on the day. What is asserted here is the handful of behaviours a screen
6
- * would silently lose: the merge that makes `className` a real override and the
7
- * two geometry overrides that ride on it, `inlineLink` and `menuSurface`, whose
8
- * whole job is to beat a canonical utility the `asChild` that keeps a link a
9
- * link, and the role an error is announced with.
4
+ * Deliberately not an echo of every class string: pinning the design system to
5
+ * whatever it looked like on the day is the mistake this repository just spent
6
+ * a restructure undoing, and a restyle is coming. What is asserted here is the
7
+ * handful of behaviours a screen would silently lose the merge that makes
8
+ * `className` a real override, the `asChild` that keeps a link a link, the role
9
+ * an error is announced with, and the value a `Progress` reports without being
10
+ * asked.
10
11
  *
11
- * The button no longer defaults `type`, so nothing here stops a "Cancel"
12
- * submitting a form; that is a call-site property now, and
13
- * `tests/scripts/form_buttons.test.mjs` is what holds it.
14
- *
15
- * This file is also the reason the jsdom harness exists at all: standing the
16
- * environment up once here is cheaper than the first screen that needs it doing so
17
- * under deadline.
12
+ * The button does not default `type`, so nothing here stops a "Cancel"
13
+ * submitting a form; that is a call-site property, gated in the consumer.
18
14
  */
19
15
 
20
16
  import { render, screen } from "@testing-library/react";
@@ -22,10 +18,6 @@ import userEvent from "@testing-library/user-event";
22
18
  import type { JSX } from "react";
23
19
  import { describe, expect, it } from "vitest";
24
20
 
25
- import { inlineLink } from "../lib/button";
26
- import { menuSurface } from "../lib/menu";
27
- import { progressAria } from "../lib/progress";
28
- import { twoLineTrigger } from "../lib/select";
29
21
  import { Alert, AlertDescription, AlertTitle } from "./alert";
30
22
  import { Badge } from "./badge";
31
23
  import { Button } from "./button";
@@ -41,13 +33,7 @@ import { Progress } from "./progress";
41
33
  import { FieldError } from "./field";
42
34
  import { Input } from "./input";
43
35
  import { Label } from "./label";
44
- import {
45
- Select,
46
- SelectContent,
47
- SelectItem,
48
- SelectTrigger,
49
- SelectValue,
50
- } from "./select";
36
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
51
37
  import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "./sheet";
52
38
  import { Table, TableBody, TableHead, TableHeader, TableRow } from "./table";
53
39
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
@@ -59,14 +45,14 @@ describe("Button", () => {
59
45
  });
60
46
 
61
47
  it("lets a caller override a conflicting utility rather than emitting both", () => {
62
- // Without `tailwind-merge` both `px-4` and `px-6` survive and which one wins is
48
+ // Without `tailwind-merge` both `px-2.5` and `px-6` survive and which one wins is
63
49
  // decided by the order Tailwind wrote them into the stylesheet — a rule nobody
64
50
  // can see from the call site. This is what makes `className` an extension
65
51
  // point rather than a suggestion.
66
52
  render(<Button className="px-6">Wide</Button>);
67
53
  const className = screen.getByRole("button", { name: "Wide" }).className;
68
54
  expect(className).toContain("px-6");
69
- expect(className).not.toContain("px-4");
55
+ expect(className).not.toContain("px-2.5");
70
56
  });
71
57
 
72
58
  it("renders the child element with asChild, so a link stays a link", () => {
@@ -95,21 +81,31 @@ describe("Button", () => {
95
81
  expect(classes).not.toMatch(/(^|\s)underline(\s|$)/);
96
82
  });
97
83
 
98
- it("hands back the height and padding a link button in prose cannot keep", () => {
84
+ it("lets a caller's className outrank the inline size", () => {
99
85
  render(
100
- <Button variant="link" className={inlineLink}>
86
+ <Button variant="link" size="inline" className="h-8">
101
87
  More
102
88
  </Button>,
103
89
  );
104
90
 
105
- // `Button` merges `className` over `buttonVariants` with tailwind-merge, so
106
- // this is the merge itself: canonical's `h-8 px-2.5` is gone from the
107
- // rendered attribute rather than merely outranked by a later rule.
91
+ // `h-auto` and `h-8` are the same utility group, so tailwind-merge has to
92
+ // drop the one the variant supplied. Without the merge both survive and
93
+ // which wins is decided by stylesheet order a rule the call site cannot see.
108
94
  const classes = screen.getByRole("button").className.split(" ");
109
- expect(classes).toContain("h-auto");
110
- expect(classes).toContain("p-0");
111
- expect(classes).not.toContain("h-8");
112
- expect(classes).not.toContain("px-2.5");
95
+ expect(classes).toContain("h-8");
96
+ expect(classes).not.toContain("h-auto");
97
+ });
98
+
99
+ it("has an inline size that keeps a link button inside a sentence", () => {
100
+ render(
101
+ <Button variant="link" size="inline">
102
+ Read the docs
103
+ </Button>,
104
+ );
105
+ const button = screen.getByRole("button", { name: "Read the docs" });
106
+ expect(button.getAttribute("data-size")).toBe("inline");
107
+ expect(button.className).toContain("h-auto");
108
+ expect(button.className).toContain("p-0");
113
109
  });
114
110
  });
115
111
 
@@ -132,13 +128,16 @@ describe("Alert and Badge", () => {
132
128
  expect(screen.getByText("done").getAttribute("data-slot")).toBe("badge");
133
129
  });
134
130
 
135
- it.each(["success", "warning", "info", "quiet"] as const)("%s is a Badge variant keyed on data", (variant) => {
136
- render(<Badge variant={variant}>x</Badge>);
137
- const el = screen.getByText("x");
138
- expect(el.getAttribute("data-variant")).toBe(variant);
139
- expect(el.className).toContain("border-transparent");
140
- expect(el.className).not.toMatch(/border-(emerald|amber|sky)/);
141
- });
131
+ it.each(["success", "warning", "info", "quiet"] as const)(
132
+ "%s is a Badge variant keyed on data",
133
+ (variant) => {
134
+ render(<Badge variant={variant}>x</Badge>);
135
+ const el = screen.getByText("x");
136
+ expect(el.getAttribute("data-variant")).toBe(variant);
137
+ expect(el.className).toContain("border-transparent");
138
+ expect(el.className).not.toMatch(/border-(emerald|amber|sky)/);
139
+ },
140
+ );
142
141
  });
143
142
 
144
143
  describe("fields", () => {
@@ -159,9 +158,10 @@ describe("fields", () => {
159
158
  });
160
159
 
161
160
  /**
162
- * The two-line option — composed at the call site rather than a primitive prop,
163
- * which is why what is asserted here is the trigger's own behaviour and not a
164
- * layout this file would otherwise have to keep in step with a call site.
161
+ * The two-line option — a `multiline` prop on the trigger itself rather than a
162
+ * class string composed at the call site, which is why what is asserted here
163
+ * is the trigger's own behaviour and not a layout this file would otherwise
164
+ * have to keep in step with a call site.
165
165
  *
166
166
  * The claim worth a test is the one that is easy to lose: the trigger shows the
167
167
  * *same* two lines the list does, because Radix renders the selected item's own
@@ -172,7 +172,7 @@ describe("Select", () => {
172
172
  function pickOne(): JSX.Element {
173
173
  return (
174
174
  <Select defaultValue="a">
175
- <SelectTrigger data-testid="model" className={twoLineTrigger}>
175
+ <SelectTrigger data-testid="model" multiline>
176
176
  <SelectValue />
177
177
  </SelectTrigger>
178
178
  <SelectContent>
@@ -202,15 +202,16 @@ describe("Select", () => {
202
202
 
203
203
  it("grows rather than clipping, and leaves a one-line option where it was", () => {
204
204
  render(pickOne());
205
- // `h-8` would fix the height and squash the second line; `min-h-8` keeps the
206
- // one-line control on Nova's contract height and lets a two-line one grow.
205
+ // `h-8` would fix the height and squash the second line; `min-h-8` keeps a
206
+ // one-line control at the trigger's usual height and lets a two-line one grow.
207
207
  const trigger = screen.getByTestId("model");
208
208
  expect(trigger.className).toContain("min-h-8");
209
209
  // Nothing truncates: half a model id is not a model id.
210
210
  expect(trigger.className).not.toContain("truncate");
211
- // `twoLineTrigger` names canonical's own modifier chains, so `cn`'s merge
212
- // replaces the fixed height and the value clamp rather than stacking beside
213
- // them a real check of the merge at render, not an echo of the constant.
211
+ // `multiline` is a prop, not a class string arriving from outside, so it
212
+ // does not need to outrank anything but `cn`'s merge still has to replace
213
+ // the fixed height and the value clamp rather than stack beside them, which
214
+ // is what this checks at render, not an echo of the prop's own classes.
214
215
  expect(trigger.className).toContain("data-[size=default]:h-auto");
215
216
  expect(trigger.className).toContain("line-clamp-none");
216
217
  expect(trigger.className).not.toContain("data-[size=default]:h-8");
@@ -226,6 +227,21 @@ describe("Select", () => {
226
227
  expect(className).toContain("w-full");
227
228
  expect(className).toContain("min-w-(--radix-select-trigger-width)");
228
229
  });
230
+
231
+ it("grows and stops clamping its value when multiline", () => {
232
+ render(
233
+ <Select>
234
+ <SelectTrigger multiline aria-label="Export target">
235
+ <SelectValue placeholder="Pick one" />
236
+ </SelectTrigger>
237
+ </Select>,
238
+ );
239
+ const trigger = screen.getByRole("combobox", { name: "Export target" });
240
+ expect(trigger.className).toContain("data-[size=default]:h-auto");
241
+ expect(trigger.className).not.toContain("data-[size=default]:h-8");
242
+ expect(trigger.className).toContain("line-clamp-none");
243
+ expect(trigger.className).not.toContain("line-clamp-1");
244
+ });
229
245
  });
230
246
 
231
247
  describe("Card and Table", () => {
@@ -323,18 +339,15 @@ describe("Tabs", () => {
323
339
  });
324
340
 
325
341
  describe("Progress", () => {
326
- it("reports its value to assistive technology, not only as a width", () => {
327
- // Canonical `Progress` reads `value` only to size the indicator and never
328
- // forwards it to Radix's `Root`, so `progressAria` says it again — every
329
- // caller in the product spreads it beside `value` for exactly this reason.
330
- render(<Progress value={42} {...progressAria(42)} aria-label="Ingest" />);
331
- expect(screen.getByRole("progressbar", { name: "Ingest" }).getAttribute("aria-valuenow")).toBe(
332
- "42",
333
- );
342
+ it("reports its value to assistive technology without help from the caller", () => {
343
+ render(<Progress value={42} aria-label="Ingest" />);
344
+ const bar = screen.getByRole("progressbar", { name: "Ingest" });
345
+ expect(bar.getAttribute("aria-valuenow")).toBe("42");
346
+ expect(bar.getAttribute("data-state")).not.toBe("indeterminate");
334
347
  });
335
348
 
336
349
  it("fills with the functional colour, and carries the data-slot a caller can restyle from", () => {
337
- // Canonical `Progress` has no `variant` prop and no notion of status — a
350
+ // `Progress` has no `variant` prop and no notion of status — a
338
351
  // batch's completion is an amount, not a polarity, so the indicator is
339
352
  // always `bg-primary`. A caller who needs to reach it targets the
340
353
  // `data-slot` it renders with, from its own `className` on `Root`.
@@ -402,7 +415,16 @@ describe("Dialog", () => {
402
415
 
403
416
  describe("sheet", () => {
404
417
  it("renders a dialog with its title and description wired by Radix", async () => {
405
- render(<Sheet open><SheetContent><SheetHeader><SheetTitle>Filters</SheetTitle><SheetDescription>Narrow the list</SheetDescription></SheetHeader></SheetContent></Sheet>);
418
+ render(
419
+ <Sheet open>
420
+ <SheetContent>
421
+ <SheetHeader>
422
+ <SheetTitle>Filters</SheetTitle>
423
+ <SheetDescription>Narrow the list</SheetDescription>
424
+ </SheetHeader>
425
+ </SheetContent>
426
+ </Sheet>,
427
+ );
406
428
  const dialog = await screen.findByRole("dialog");
407
429
  expect(dialog.getAttribute("data-slot")).toBe("sheet-content");
408
430
  expect(dialog.getAttribute("data-side")).toBe("right");
@@ -418,23 +440,38 @@ describe("DropdownMenu", () => {
418
440
  <DropdownMenuTrigger asChild>
419
441
  <Button variant="ghost" size="icon" aria-label="Actions" />
420
442
  </DropdownMenuTrigger>
421
- <DropdownMenuContent className={menuSurface}>
443
+ <DropdownMenuContent>
422
444
  <DropdownMenuItem>Check integrity of this connection</DropdownMenuItem>
423
445
  </DropdownMenuContent>
424
446
  </DropdownMenu>,
425
447
  );
426
448
  await user.click(screen.getByRole("button", { name: "Actions" }));
427
449
  const classes = (await screen.findByRole("menu")).className.split(" ");
428
- // Canonical pins the surface to the trigger with
429
- // `w-(--radix-dropdown-menu-trigger-width)`, which behind this icon-sized
430
- // button is the 128px floor — long items wrap. `menuSurface` is in the same
431
- // utility group, so tailwind-merge drops canonical's at render and the
432
- // rendered class list is the assertion: this is the merge, not a hope about
433
- // cascade order.
450
+ // The default sizes to items, not to the trigger: behind this icon-sized
451
+ // button, pinning to the trigger width would be a 128px ceiling that wraps
452
+ // every longer item. `min-w-32` is what is asserted below, surviving as
453
+ // the floor it was meant to be.
434
454
  expect(classes).toContain("w-auto");
435
455
  expect(classes).not.toContain("w-(--radix-dropdown-menu-trigger-width)");
436
456
  // The floor is a different group and survives, which is what keeps a
437
457
  // one-word menu from collapsing to its widest item.
438
458
  expect(classes).toContain("min-w-32");
439
459
  });
460
+
461
+ it("sizes to its items and leaves on the frame it is dismissed", async () => {
462
+ const user = userEvent.setup();
463
+ render(
464
+ <DropdownMenu>
465
+ <DropdownMenuTrigger>Actions</DropdownMenuTrigger>
466
+ <DropdownMenuContent>
467
+ <DropdownMenuItem>Duplicate this model</DropdownMenuItem>
468
+ </DropdownMenuContent>
469
+ </DropdownMenu>,
470
+ );
471
+ await user.click(screen.getByRole("button", { name: "Actions" }));
472
+ const menu = await screen.findByRole("menu");
473
+ expect(menu.className).toContain("w-auto");
474
+ expect(menu.className).not.toContain("--radix-dropdown-menu-trigger-width");
475
+ expect(menu.className).not.toContain("data-closed:animate-out");
476
+ });
440
477
  });
@@ -1,32 +1,24 @@
1
- import * as React from "react"
2
- import { Dialog as DialogPrimitive } from "radix-ui"
1
+ import * as React from "react";
2
+ import { Dialog as DialogPrimitive } from "radix-ui";
3
3
 
4
- import { cn } from "../lib/cn.js"
5
- import { Button } from "./button.js"
6
- import { XIcon } from "lucide-react"
4
+ import { cn } from "cn";
5
+ import { Button } from "./button.js";
6
+ import { XIcon } from "lucide-react";
7
7
 
8
- function Dialog({
9
- ...props
10
- }: React.ComponentProps<typeof DialogPrimitive.Root>) {
11
- return <DialogPrimitive.Root data-slot="dialog" {...props} />
8
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
9
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />;
12
10
  }
13
11
 
14
- function DialogTrigger({
15
- ...props
16
- }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
17
- return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
12
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
13
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
18
14
  }
19
15
 
20
- function DialogPortal({
21
- ...props
22
- }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
23
- return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
16
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
17
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
24
18
  }
25
19
 
26
- function DialogClose({
27
- ...props
28
- }: React.ComponentProps<typeof DialogPrimitive.Close>) {
29
- return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
20
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
21
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
30
22
  }
31
23
 
32
24
  function DialogOverlay({
@@ -38,11 +30,11 @@ function DialogOverlay({
38
30
  data-slot="dialog-overlay"
39
31
  className={cn(
40
32
  "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
41
- className
33
+ className,
42
34
  )}
43
35
  {...props}
44
36
  />
45
- )
37
+ );
46
38
  }
47
39
 
48
40
  function DialogContent({
@@ -51,7 +43,7 @@ function DialogContent({
51
43
  showCloseButton = true,
52
44
  ...props
53
45
  }: React.ComponentProps<typeof DialogPrimitive.Content> & {
54
- showCloseButton?: boolean
46
+ showCloseButton?: boolean;
55
47
  }) {
56
48
  return (
57
49
  <DialogPortal>
@@ -60,37 +52,28 @@ function DialogContent({
60
52
  data-slot="dialog-content"
61
53
  className={cn(
62
54
  "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
63
- className
55
+ className,
64
56
  )}
65
57
  {...props}
66
58
  >
67
59
  {children}
68
60
  {showCloseButton && (
69
61
  <DialogPrimitive.Close data-slot="dialog-close" asChild>
70
- <Button
71
- variant="ghost"
72
- className="absolute top-2 right-2"
73
- size="icon-sm"
74
- >
75
- <XIcon
76
- />
62
+ <Button variant="ghost" className="absolute top-2 right-2" size="icon-sm">
63
+ <XIcon />
77
64
  <span className="sr-only">Close</span>
78
65
  </Button>
79
66
  </DialogPrimitive.Close>
80
67
  )}
81
68
  </DialogPrimitive.Content>
82
69
  </DialogPortal>
83
- )
70
+ );
84
71
  }
85
72
 
86
73
  function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
87
74
  return (
88
- <div
89
- data-slot="dialog-header"
90
- className={cn("flex flex-col gap-2", className)}
91
- {...props}
92
- />
93
- )
75
+ <div data-slot="dialog-header" className={cn("flex flex-col gap-2", className)} {...props} />
76
+ );
94
77
  }
95
78
 
96
79
  function DialogFooter({
@@ -99,14 +82,14 @@ function DialogFooter({
99
82
  children,
100
83
  ...props
101
84
  }: React.ComponentProps<"div"> & {
102
- showCloseButton?: boolean
85
+ showCloseButton?: boolean;
103
86
  }) {
104
87
  return (
105
88
  <div
106
89
  data-slot="dialog-footer"
107
90
  className={cn(
108
91
  "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end",
109
- className
92
+ className,
110
93
  )}
111
94
  {...props}
112
95
  >
@@ -117,23 +100,17 @@ function DialogFooter({
117
100
  </DialogPrimitive.Close>
118
101
  )}
119
102
  </div>
120
- )
103
+ );
121
104
  }
122
105
 
123
- function DialogTitle({
124
- className,
125
- ...props
126
- }: React.ComponentProps<typeof DialogPrimitive.Title>) {
106
+ function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
127
107
  return (
128
108
  <DialogPrimitive.Title
129
109
  data-slot="dialog-title"
130
- className={cn(
131
- "font-heading text-base leading-none font-medium",
132
- className
133
- )}
110
+ className={cn("font-heading text-base leading-none font-medium", className)}
134
111
  {...props}
135
112
  />
136
- )
113
+ );
137
114
  }
138
115
 
139
116
  function DialogDescription({
@@ -145,11 +122,11 @@ function DialogDescription({
145
122
  data-slot="dialog-description"
146
123
  className={cn(
147
124
  "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
148
- className
125
+ className,
149
126
  )}
150
127
  {...props}
151
128
  />
152
- )
129
+ );
153
130
  }
154
131
 
155
132
  export {
@@ -163,4 +140,4 @@ export {
163
140
  DialogPortal,
164
141
  DialogTitle,
165
142
  DialogTrigger,
166
- }
143
+ };