@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.
- package/README.md +19 -7
- package/dist/{primitives → components}/alert.js +1 -1
- package/dist/{primitives → components}/badge.js +1 -1
- package/dist/{primitives → components}/button.d.ts +1 -1
- package/dist/{primitives → components}/button.js +4 -1
- package/dist/{primitives → components}/card.d.ts +1 -1
- package/dist/{primitives → components}/card.js +2 -2
- package/dist/{primitives → components}/combobox.js +4 -4
- package/dist/{primitives → components}/dialog.js +1 -1
- package/dist/{primitives → components}/dropdown-menu.js +12 -7
- package/dist/{primitives → components}/field.js +2 -4
- package/dist/{primitives → components}/input-group.js +1 -1
- package/dist/{primitives → components}/input.js +1 -1
- package/dist/{primitives → components}/label.js +1 -1
- package/dist/components/progress.js +7 -0
- package/dist/{primitives → components}/select.d.ts +3 -1
- package/dist/{primitives → components}/select.js +7 -4
- package/dist/{primitives → components}/separator.js +1 -1
- package/dist/{primitives → components}/sheet.js +1 -1
- package/dist/{primitives → components}/skeleton.js +1 -1
- package/dist/{primitives → components}/sonner.js +17 -12
- package/dist/{primitives → components}/table.d.ts +1 -1
- package/dist/{primitives → components}/table.js +3 -3
- package/dist/{primitives → components}/tabs.js +1 -1
- package/dist/{primitives → components}/textarea.js +1 -1
- package/dist/{primitives → components}/tooltip.js +1 -1
- package/dist/gates/index.d.ts +28 -0
- package/dist/gates/index.js +142 -0
- package/dist/index.d.ts +31 -32
- package/dist/index.js +32 -33
- package/dist/{tokens.d.ts → theme/tokens.d.ts} +5 -5
- package/dist/{tokens.js → theme/tokens.js} +12 -12
- package/package.json +23 -12
- package/{shadcn → src/components}/alert.tsx +14 -21
- package/src/{primitives → components}/badge.tsx +15 -21
- package/src/{primitives → components}/button.tsx +13 -10
- package/{shadcn → src/components}/card.tsx +16 -31
- package/src/{primitives → components}/combobox.test.tsx +15 -2
- package/src/{primitives → components}/combobox.tsx +45 -74
- package/src/{primitives/primitives.test.tsx → components/components.test.tsx} +106 -69
- package/src/{primitives → components}/dialog.tsx +31 -54
- package/src/{primitives → components}/dropdown-menu.tsx +51 -65
- package/src/{primitives → components}/field.tsx +48 -62
- package/src/{primitives → components}/input-group.tsx +37 -49
- package/{shadcn → src/components}/input.tsx +5 -5
- package/{shadcn → src/components}/label.tsx +7 -10
- package/src/{primitives → components}/progress.tsx +7 -6
- package/{shadcn → src/components}/select.tsx +40 -40
- package/{shadcn → src/components}/separator.tsx +7 -7
- package/src/{primitives → components}/sheet.tsx +27 -44
- package/{shadcn → src/components}/skeleton.tsx +3 -3
- package/src/{primitives → components}/sonner.test.tsx +12 -4
- package/src/components/sonner.tsx +67 -0
- package/{shadcn → src/components}/table.tsx +17 -44
- package/{shadcn → src/components}/tabs.tsx +16 -26
- package/{shadcn → src/components}/textarea.tsx +5 -5
- package/{shadcn → src/components}/tooltip.tsx +12 -16
- package/src/gates/design.test.ts +188 -0
- package/src/gates/index.test.ts +11 -0
- package/src/gates/index.ts +165 -0
- package/src/gates/tokens.test.ts +215 -0
- package/src/harness.test.tsx +1 -1
- package/src/index.ts +63 -33
- package/src/theme/imports.test.ts +160 -0
- package/src/{statusTone.test.ts → theme/statusTone.test.ts} +5 -1
- package/src/{styles.css → theme/styles.css} +45 -31
- package/src/theme/tailwind.css +646 -0
- package/src/{tokens.test.ts → theme/tokens.test.ts} +30 -23
- package/src/{tokens.ts → theme/tokens.ts} +12 -12
- package/components.json +0 -13
- package/dist/lib/button.d.ts +0 -1
- package/dist/lib/button.js +0 -4
- package/dist/lib/cn.d.ts +0 -18
- package/dist/lib/cn.js +0 -21
- package/dist/lib/menu.d.ts +0 -1
- package/dist/lib/menu.js +0 -16
- package/dist/lib/progress.d.ts +0 -3
- package/dist/lib/progress.js +0 -6
- package/dist/lib/select.d.ts +0 -1
- package/dist/lib/select.js +0 -3
- package/dist/primitives/progress.js +0 -7
- package/gates/canonical.test.mjs +0 -71
- package/gates/extensions.test.mjs +0 -373
- package/gates/index.d.mts +0 -51
- package/gates/index.mjs +0 -514
- package/gates/tokens.test.mjs +0 -276
- package/shadcn/README.md +0 -13
- package/shadcn/badge.tsx +0 -49
- package/shadcn/button.tsx +0 -67
- package/shadcn/combobox.tsx +0 -299
- package/shadcn/dialog.tsx +0 -166
- package/shadcn/dropdown-menu.tsx +0 -267
- package/shadcn/field.tsx +0 -236
- package/shadcn/input-group.tsx +0 -154
- package/shadcn/progress.tsx +0 -29
- package/shadcn/sheet.tsx +0 -145
- package/shadcn/sonner.tsx +0 -49
- package/src/lib/button.ts +0 -4
- package/src/lib/cn.test.ts +0 -33
- package/src/lib/cn.ts +0 -23
- package/src/lib/menu.ts +0 -16
- package/src/lib/progress.ts +0 -6
- package/src/lib/select.ts +0 -4
- package/src/primitives/alert.tsx +0 -76
- package/src/primitives/card.tsx +0 -103
- package/src/primitives/input.tsx +0 -19
- package/src/primitives/label.tsx +0 -22
- package/src/primitives/select.tsx +0 -190
- package/src/primitives/separator.tsx +0 -28
- package/src/primitives/skeleton.tsx +0 -13
- package/src/primitives/sonner.tsx +0 -65
- package/src/primitives/table.tsx +0 -114
- package/src/primitives/tabs.tsx +0 -88
- package/src/primitives/textarea.tsx +0 -18
- package/src/primitives/tooltip.tsx +0 -57
- /package/dist/{primitives → components}/alert.d.ts +0 -0
- /package/dist/{primitives → components}/badge.d.ts +0 -0
- /package/dist/{primitives → components}/combobox.d.ts +0 -0
- /package/dist/{primitives → components}/dialog.d.ts +0 -0
- /package/dist/{primitives → components}/dropdown-menu.d.ts +0 -0
- /package/dist/{primitives → components}/field.d.ts +0 -0
- /package/dist/{primitives → components}/input-group.d.ts +0 -0
- /package/dist/{primitives → components}/input.d.ts +0 -0
- /package/dist/{primitives → components}/label.d.ts +0 -0
- /package/dist/{primitives → components}/progress.d.ts +0 -0
- /package/dist/{primitives → components}/separator.d.ts +0 -0
- /package/dist/{primitives → components}/sheet.d.ts +0 -0
- /package/dist/{primitives → components}/skeleton.d.ts +0 -0
- /package/dist/{primitives → components}/sonner.d.ts +0 -0
- /package/dist/{primitives → components}/tabs.d.ts +0 -0
- /package/dist/{primitives → components}/textarea.d.ts +0 -0
- /package/dist/{primitives → components}/tooltip.d.ts +0 -0
- /package/dist/{statusTone.d.ts → theme/statusTone.d.ts} +0 -0
- /package/dist/{statusTone.js → theme/statusTone.js} +0 -0
- /package/src/{statusTone.ts → theme/statusTone.ts} +0 -0
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The component harness, proved on the
|
|
2
|
+
* The component harness, proved on the components that carry a decision.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* whatever it
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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
|
|
12
|
-
* submitting a form; that is a call-site property
|
|
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-
|
|
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-
|
|
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("
|
|
84
|
+
it("lets a caller's className outrank the inline size", () => {
|
|
99
85
|
render(
|
|
100
|
-
<Button variant="link" className=
|
|
86
|
+
<Button variant="link" size="inline" className="h-8">
|
|
101
87
|
More
|
|
102
88
|
</Button>,
|
|
103
89
|
);
|
|
104
90
|
|
|
105
|
-
// `
|
|
106
|
-
//
|
|
107
|
-
//
|
|
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-
|
|
110
|
-
expect(classes).toContain("
|
|
111
|
-
|
|
112
|
-
|
|
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)(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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 —
|
|
163
|
-
* which is why what is asserted here
|
|
164
|
-
*
|
|
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"
|
|
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
|
|
206
|
-
// one-line control
|
|
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
|
-
// `
|
|
212
|
-
//
|
|
213
|
-
//
|
|
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
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
//
|
|
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(
|
|
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
|
|
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
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
};
|