@theruntime/components 0.0.0 → 0.0.1

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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +113 -4
  3. package/src/accordion.tsx +62 -0
  4. package/src/alert-dialog.tsx +177 -0
  5. package/src/alert.tsx +60 -0
  6. package/src/aspect-ratio.tsx +7 -0
  7. package/src/attachment.tsx +192 -0
  8. package/src/avatar.tsx +94 -0
  9. package/src/badge.tsx +46 -0
  10. package/src/breadcrumb.tsx +102 -0
  11. package/src/bubble.tsx +125 -0
  12. package/src/button-group.tsx +82 -0
  13. package/src/button.tsx +62 -0
  14. package/src/calendar.tsx +178 -0
  15. package/src/card.tsx +75 -0
  16. package/src/carousel.tsx +228 -0
  17. package/src/chart/container.tsx +72 -0
  18. package/src/chart/context.tsx +39 -0
  19. package/src/chart/index.ts +4 -0
  20. package/src/chart/legend.tsx +63 -0
  21. package/src/chart/payload.ts +31 -0
  22. package/src/chart/tooltip.tsx +149 -0
  23. package/src/checkbox.tsx +27 -0
  24. package/src/cn.ts +36 -0
  25. package/src/collapsible.tsx +19 -0
  26. package/src/combobox/chips.tsx +71 -0
  27. package/src/combobox/content.tsx +123 -0
  28. package/src/combobox/index.ts +13 -0
  29. package/src/combobox/input.tsx +39 -0
  30. package/src/combobox/trigger.tsx +44 -0
  31. package/src/command.tsx +153 -0
  32. package/src/context-menu.tsx +222 -0
  33. package/src/dialog.tsx +142 -0
  34. package/src/direction.tsx +18 -0
  35. package/src/drawer.tsx +122 -0
  36. package/src/dropdown-menu.tsx +226 -0
  37. package/src/empty.tsx +94 -0
  38. package/src/field.tsx +232 -0
  39. package/src/form.tsx +153 -0
  40. package/src/hover-card.tsx +36 -0
  41. package/src/index.ts +90 -0
  42. package/src/input-group.tsx +156 -0
  43. package/src/input-otp.tsx +68 -0
  44. package/src/input.tsx +21 -0
  45. package/src/item.tsx +172 -0
  46. package/src/kbd.tsx +28 -0
  47. package/src/label.tsx +19 -0
  48. package/src/marker.tsx +66 -0
  49. package/src/menubar.tsx +250 -0
  50. package/src/message-scroller.tsx +128 -0
  51. package/src/message.tsx +85 -0
  52. package/src/native-select.tsx +56 -0
  53. package/src/navigation-menu.tsx +161 -0
  54. package/src/pagination.tsx +106 -0
  55. package/src/popover.tsx +72 -0
  56. package/src/progress.tsx +26 -0
  57. package/src/questionnaire/actions.tsx +118 -0
  58. package/src/questionnaire/choices.tsx +113 -0
  59. package/src/questionnaire/index.ts +21 -0
  60. package/src/questionnaire/root.tsx +75 -0
  61. package/src/radio-group.tsx +43 -0
  62. package/src/resizable.tsx +45 -0
  63. package/src/scroll-area.tsx +54 -0
  64. package/src/select.tsx +173 -0
  65. package/src/separator.tsx +26 -0
  66. package/src/sheet.tsx +132 -0
  67. package/src/shell/app-tab.tsx +67 -0
  68. package/src/shell/entry-row.tsx +137 -0
  69. package/src/shell/field.tsx +83 -0
  70. package/src/shell/group-head.tsx +19 -0
  71. package/src/shell/scope-chip.tsx +32 -0
  72. package/src/shell/suggest-panel.tsx +92 -0
  73. package/src/sidebar/context.tsx +128 -0
  74. package/src/sidebar/index.ts +23 -0
  75. package/src/sidebar/menu.tsx +239 -0
  76. package/src/sidebar/sections.tsx +118 -0
  77. package/src/sidebar/sidebar.tsx +183 -0
  78. package/src/skeleton.tsx +13 -0
  79. package/src/slider.tsx +56 -0
  80. package/src/sonner.tsx +41 -0
  81. package/src/spinner.tsx +16 -0
  82. package/src/styles.css +149 -0
  83. package/src/switch.tsx +33 -0
  84. package/src/table.tsx +90 -0
  85. package/src/tabs.tsx +79 -0
  86. package/src/textarea.tsx +18 -0
  87. package/src/toggle-group.tsx +81 -0
  88. package/src/toggle.tsx +44 -0
  89. package/src/tooltip.tsx +51 -0
  90. package/src/use-mobile.ts +21 -0
  91. package/README.md +0 -3
@@ -0,0 +1,106 @@
1
+ import * as React from "react";
2
+ import { CaretLeftIcon, CaretRightIcon, DotsThreeIcon } from "@phosphor-icons/react";
3
+
4
+ import { cn } from "./cn";
5
+ import { buttonVariants, type Button } from "./button";
6
+
7
+ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
8
+ return (
9
+ <nav
10
+ role="navigation"
11
+ aria-label="pagination"
12
+ data-slot="pagination"
13
+ className={cn("mx-auto flex w-full justify-center", className)}
14
+ {...props}
15
+ />
16
+ );
17
+ }
18
+
19
+ function PaginationContent({ className, ...props }: React.ComponentProps<"ul">) {
20
+ return (
21
+ <ul
22
+ data-slot="pagination-content"
23
+ className={cn("flex flex-row items-center gap-1", className)}
24
+ {...props}
25
+ />
26
+ );
27
+ }
28
+
29
+ function PaginationItem({ ...props }: React.ComponentProps<"li">) {
30
+ return <li data-slot="pagination-item" {...props} />;
31
+ }
32
+
33
+ type PaginationLinkProps = {
34
+ isActive?: boolean;
35
+ } & Pick<React.ComponentProps<typeof Button>, "size"> &
36
+ React.ComponentProps<"a">;
37
+
38
+ function PaginationLink({ className, isActive, size = "icon", ...props }: PaginationLinkProps) {
39
+ return (
40
+ <a
41
+ aria-current={isActive ? "page" : undefined}
42
+ data-slot="pagination-link"
43
+ data-active={isActive}
44
+ className={cn(
45
+ buttonVariants({
46
+ variant: isActive ? "outline" : "ghost",
47
+ size,
48
+ }),
49
+ className,
50
+ )}
51
+ {...props}
52
+ />
53
+ );
54
+ }
55
+
56
+ function PaginationPrevious({ className, ...props }: React.ComponentProps<typeof PaginationLink>) {
57
+ return (
58
+ <PaginationLink
59
+ aria-label="Go to previous page"
60
+ size="default"
61
+ className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
62
+ {...props}
63
+ >
64
+ <CaretLeftIcon />
65
+ <span className="hidden sm:block">Previous</span>
66
+ </PaginationLink>
67
+ );
68
+ }
69
+
70
+ function PaginationNext({ className, ...props }: React.ComponentProps<typeof PaginationLink>) {
71
+ return (
72
+ <PaginationLink
73
+ aria-label="Go to next page"
74
+ size="default"
75
+ className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
76
+ {...props}
77
+ >
78
+ <span className="hidden sm:block">Next</span>
79
+ <CaretRightIcon />
80
+ </PaginationLink>
81
+ );
82
+ }
83
+
84
+ function PaginationEllipsis({ className, ...props }: React.ComponentProps<"span">) {
85
+ return (
86
+ <span
87
+ aria-hidden
88
+ data-slot="pagination-ellipsis"
89
+ className={cn("flex size-9 items-center justify-center", className)}
90
+ {...props}
91
+ >
92
+ <DotsThreeIcon className="size-4" />
93
+ <span className="sr-only">More pages</span>
94
+ </span>
95
+ );
96
+ }
97
+
98
+ export {
99
+ Pagination,
100
+ PaginationContent,
101
+ PaginationLink,
102
+ PaginationItem,
103
+ PaginationPrevious,
104
+ PaginationNext,
105
+ PaginationEllipsis,
106
+ };
@@ -0,0 +1,72 @@
1
+ import * as React from "react";
2
+ import { Popover as PopoverPrimitive } from "radix-ui";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
7
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />;
8
+ }
9
+
10
+ function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
11
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
12
+ }
13
+
14
+ function PopoverContent({
15
+ className,
16
+ align = "center",
17
+ sideOffset = 4,
18
+ ...props
19
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
20
+ return (
21
+ <PopoverPrimitive.Portal>
22
+ <PopoverPrimitive.Content
23
+ data-slot="popover-content"
24
+ align={align}
25
+ sideOffset={sideOffset}
26
+ className={cn(
27
+ "z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden 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 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
28
+ className,
29
+ )}
30
+ {...props}
31
+ />
32
+ </PopoverPrimitive.Portal>
33
+ );
34
+ }
35
+
36
+ function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
37
+ return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
38
+ }
39
+
40
+ function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
41
+ return (
42
+ <div
43
+ data-slot="popover-header"
44
+ className={cn("flex flex-col gap-1 text-sm", className)}
45
+ {...props}
46
+ />
47
+ );
48
+ }
49
+
50
+ function PopoverTitle({ className, ...props }: React.ComponentProps<"h2">) {
51
+ return <div data-slot="popover-title" className={cn("font-medium", className)} {...props} />;
52
+ }
53
+
54
+ function PopoverDescription({ className, ...props }: React.ComponentProps<"p">) {
55
+ return (
56
+ <p
57
+ data-slot="popover-description"
58
+ className={cn("text-muted-foreground", className)}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ export {
65
+ Popover,
66
+ PopoverTrigger,
67
+ PopoverContent,
68
+ PopoverAnchor,
69
+ PopoverHeader,
70
+ PopoverTitle,
71
+ PopoverDescription,
72
+ };
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+ import { Progress as ProgressPrimitive } from "radix-ui";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function Progress({
7
+ className,
8
+ value,
9
+ ...props
10
+ }: React.ComponentProps<typeof ProgressPrimitive.Root>) {
11
+ return (
12
+ <ProgressPrimitive.Root
13
+ data-slot="progress"
14
+ className={cn("relative h-2 w-full overflow-hidden rounded-full bg-primary/20", className)}
15
+ {...props}
16
+ >
17
+ <ProgressPrimitive.Indicator
18
+ data-slot="progress-indicator"
19
+ className="h-full w-full flex-1 bg-primary transition-all"
20
+ style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
21
+ />
22
+ </ProgressPrimitive.Root>
23
+ );
24
+ }
25
+
26
+ export { Progress };
@@ -0,0 +1,118 @@
1
+ import * as React from "react";
2
+ import { Questionnaire as QuestionnairePrimitive } from "@shadcn/react/questionnaire";
3
+
4
+ import { cn } from "../cn";
5
+ import { buttonVariants, type Button } from "../button";
6
+
7
+ export function QuestionnaireActions({ className, ...props }: React.ComponentProps<"div">) {
8
+ return (
9
+ <div
10
+ data-slot="questionnaire-actions"
11
+ className={cn(
12
+ "grid min-h-11 w-full grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-2 sm:min-h-8",
13
+ className,
14
+ )}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ export function QuestionnairePrevious({
21
+ children,
22
+ className,
23
+ size = "default",
24
+ variant = "outline",
25
+ ...props
26
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Previous> &
27
+ Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
28
+ return (
29
+ <QuestionnairePrimitive.Previous
30
+ data-slot="questionnaire-previous"
31
+ data-size={size}
32
+ data-variant={variant}
33
+ className={cn(
34
+ buttonVariants({ size, variant }),
35
+ "col-start-1 row-start-1 min-h-11 justify-self-start sm:min-h-0",
36
+ className,
37
+ )}
38
+ {...props}
39
+ >
40
+ {children ?? "Previous"}
41
+ </QuestionnairePrimitive.Previous>
42
+ );
43
+ }
44
+
45
+ export function QuestionnaireSkip({
46
+ children,
47
+ className,
48
+ size = "default",
49
+ variant = "outline",
50
+ ...props
51
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Skip> &
52
+ Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
53
+ return (
54
+ <QuestionnairePrimitive.Skip
55
+ data-slot="questionnaire-skip"
56
+ data-size={size}
57
+ data-variant={variant}
58
+ className={cn(
59
+ buttonVariants({ size, variant }),
60
+ "col-start-2 row-start-1 min-h-11 justify-self-end sm:min-h-0",
61
+ className,
62
+ )}
63
+ {...props}
64
+ >
65
+ {children ?? "Skip"}
66
+ </QuestionnairePrimitive.Skip>
67
+ );
68
+ }
69
+
70
+ export function QuestionnaireNext({
71
+ children,
72
+ className,
73
+ size = "default",
74
+ variant = "default",
75
+ ...props
76
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Next> &
77
+ Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
78
+ return (
79
+ <QuestionnairePrimitive.Next
80
+ data-slot="questionnaire-next"
81
+ data-size={size}
82
+ data-variant={variant}
83
+ className={cn(
84
+ buttonVariants({ size, variant }),
85
+ "col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0",
86
+ className,
87
+ )}
88
+ {...props}
89
+ >
90
+ {children ?? "Next"}
91
+ </QuestionnairePrimitive.Next>
92
+ );
93
+ }
94
+
95
+ export function QuestionnaireSubmit({
96
+ children,
97
+ className,
98
+ size = "default",
99
+ variant = "default",
100
+ ...props
101
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Submit> &
102
+ Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
103
+ return (
104
+ <QuestionnairePrimitive.Submit
105
+ data-slot="questionnaire-submit"
106
+ data-size={size}
107
+ data-variant={variant}
108
+ className={cn(
109
+ buttonVariants({ size, variant }),
110
+ "col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0",
111
+ className,
112
+ )}
113
+ {...props}
114
+ >
115
+ {children ?? "Submit"}
116
+ </QuestionnairePrimitive.Submit>
117
+ );
118
+ }
@@ -0,0 +1,113 @@
1
+ import * as React from "react";
2
+ import { Questionnaire as QuestionnairePrimitive } from "@shadcn/react/questionnaire";
3
+ import { CheckIcon } from "@phosphor-icons/react";
4
+
5
+ import { cn } from "../cn";
6
+
7
+ export function QuestionnaireChoices({
8
+ className,
9
+ ...props
10
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Choices>) {
11
+ return (
12
+ <QuestionnairePrimitive.Choices
13
+ data-slot="questionnaire-choices"
14
+ className={cn("group/questionnaire-choices grid min-w-0 gap-2", className)}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ export function QuestionnaireChoice({
21
+ children,
22
+ className,
23
+ ...props
24
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Choice>) {
25
+ return (
26
+ <QuestionnairePrimitive.Choice
27
+ data-slot="questionnaire-choice"
28
+ className={cn(
29
+ "group/questionnaire-choice relative flex min-h-11 cursor-pointer items-start gap-2.5 rounded-lg border border-input bg-transparent px-3 py-2.5 text-start text-sm transition-colors outline-none select-none hover:bg-muted/50 has-[>input:focus-visible]:border-ring has-[>input:focus-visible]:ring-3 has-[>input:focus-visible]:ring-ring/50 data-invalid:border-destructive dark:bg-input/20 data-checked:border-primary/40 data-checked:bg-muted dark:data-checked:bg-muted",
30
+ "data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-disabled:opacity-50",
31
+ className,
32
+ )}
33
+ {...props}
34
+ >
35
+ <QuestionnairePrimitive.ChoiceInput
36
+ data-slot="questionnaire-choice-input"
37
+ className="absolute inset-0 z-10 size-full cursor-pointer opacity-0"
38
+ />
39
+ <span
40
+ aria-hidden="true"
41
+ data-slot="questionnaire-choice-indicator"
42
+ className="pointer-events-none relative flex size-4 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-[4px] border border-input group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[type=radio]/questionnaire-choice:rounded-full group-data-checked/questionnaire-choice:border-primary group-data-checked/questionnaire-choice:bg-primary group-data-checked/questionnaire-choice:text-primary-foreground dark:bg-input/30 dark:group-data-checked/questionnaire-choice:bg-primary"
43
+ >
44
+ <span
45
+ data-slot="questionnaire-choice-indicator-dot"
46
+ className="hidden size-2 rounded-full bg-primary-foreground group-data-[type=checkbox]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block"
47
+ />
48
+ <CheckIcon
49
+ data-slot="questionnaire-choice-indicator-check"
50
+ className="hidden size-3.5 group-data-[type=radio]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block"
51
+ />
52
+ </span>
53
+ <QuestionnairePrimitive.ChoiceLabel
54
+ data-slot="questionnaire-choice-label"
55
+ className="flex min-w-0 flex-1 flex-col gap-0.5 leading-snug"
56
+ >
57
+ {children}
58
+ </QuestionnairePrimitive.ChoiceLabel>
59
+ <QuestionnairePrimitive.ChoiceShortcut
60
+ data-slot="questionnaire-choice-shortcut"
61
+ className="pointer-events-none ms-auto hidden size-5 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-md border border-input bg-background font-mono text-[0.625rem] leading-none font-medium text-muted-foreground group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[shortcut]/questionnaire-choice:inline-flex"
62
+ />
63
+ </QuestionnairePrimitive.Choice>
64
+ );
65
+ }
66
+
67
+ export function QuestionnaireChoiceDescription({
68
+ className,
69
+ ...props
70
+ }: React.ComponentProps<"span">) {
71
+ return (
72
+ <span
73
+ data-slot="questionnaire-choice-description"
74
+ className={cn("text-muted-foreground", className)}
75
+ {...props}
76
+ />
77
+ );
78
+ }
79
+
80
+ export function QuestionnaireInput({
81
+ className,
82
+ ...props
83
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Input>) {
84
+ return (
85
+ <div
86
+ data-slot="questionnaire-input-wrapper"
87
+ className="group/questionnaire-input relative w-full min-w-0"
88
+ >
89
+ <QuestionnairePrimitive.Input
90
+ data-slot="questionnaire-input"
91
+ className={cn(
92
+ "h-8 min-h-11 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-[color,box-shadow,background-color] outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 sm:min-h-0 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
93
+ "selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground",
94
+ className,
95
+ )}
96
+ {...props}
97
+ />
98
+ </div>
99
+ );
100
+ }
101
+
102
+ export function QuestionnaireError({
103
+ className,
104
+ ...props
105
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Error>) {
106
+ return (
107
+ <QuestionnairePrimitive.Error
108
+ data-slot="questionnaire-error"
109
+ className={cn("mt-2 text-sm text-destructive", className)}
110
+ {...props}
111
+ />
112
+ );
113
+ }
@@ -0,0 +1,21 @@
1
+ export {
2
+ Questionnaire,
3
+ QuestionnaireDescription,
4
+ QuestionnaireItem,
5
+ QuestionnaireProgress,
6
+ QuestionnaireTitle,
7
+ } from "./root";
8
+ export {
9
+ QuestionnaireChoice,
10
+ QuestionnaireChoiceDescription,
11
+ QuestionnaireChoices,
12
+ QuestionnaireError,
13
+ QuestionnaireInput,
14
+ } from "./choices";
15
+ export {
16
+ QuestionnaireActions,
17
+ QuestionnaireNext,
18
+ QuestionnairePrevious,
19
+ QuestionnaireSkip,
20
+ QuestionnaireSubmit,
21
+ } from "./actions";
@@ -0,0 +1,75 @@
1
+ import * as React from "react";
2
+ import { Questionnaire as QuestionnairePrimitive } from "@shadcn/react/questionnaire";
3
+
4
+ import { cn } from "../cn";
5
+
6
+ export function Questionnaire({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Root>) {
10
+ return (
11
+ <QuestionnairePrimitive.Root
12
+ data-slot="questionnaire"
13
+ className={cn("flex w-full min-w-0 flex-col gap-4", className)}
14
+ {...props}
15
+ />
16
+ );
17
+ }
18
+
19
+ export function QuestionnaireProgress({
20
+ className,
21
+ ...props
22
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Progress>) {
23
+ return (
24
+ <QuestionnairePrimitive.Progress
25
+ data-slot="questionnaire-progress"
26
+ className={cn(
27
+ "min-h-[1lh] w-fit min-w-[14ch] text-xs font-medium text-muted-foreground tabular-nums",
28
+ className,
29
+ )}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ export function QuestionnaireItem({
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Item>) {
39
+ return (
40
+ <QuestionnairePrimitive.Item
41
+ data-slot="questionnaire-item"
42
+ className={cn("flex min-w-0 flex-col gap-4 border-0 p-0 outline-none", className)}
43
+ {...props}
44
+ />
45
+ );
46
+ }
47
+
48
+ export function QuestionnaireTitle({
49
+ className,
50
+ ...props
51
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Title>) {
52
+ return (
53
+ <QuestionnairePrimitive.Title
54
+ data-slot="questionnaire-title"
55
+ className={cn(
56
+ "cn-font-heading text-base leading-snug font-medium text-pretty [&:not(:has(~[data-slot=questionnaire-description]))]:mb-4",
57
+ className,
58
+ )}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ export function QuestionnaireDescription({
65
+ className,
66
+ ...props
67
+ }: React.ComponentProps<typeof QuestionnairePrimitive.Description>) {
68
+ return (
69
+ <QuestionnairePrimitive.Description
70
+ data-slot="questionnaire-description"
71
+ className={cn("text-sm text-pretty text-muted-foreground", className)}
72
+ {...props}
73
+ />
74
+ );
75
+ }
@@ -0,0 +1,43 @@
1
+ import * as React from "react";
2
+ import { CircleIcon } from "@phosphor-icons/react";
3
+ import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
4
+
5
+ import { cn } from "./cn";
6
+
7
+ function RadioGroup({
8
+ className,
9
+ ...props
10
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
11
+ return (
12
+ <RadioGroupPrimitive.Root
13
+ data-slot="radio-group"
14
+ className={cn("grid gap-3", className)}
15
+ {...props}
16
+ />
17
+ );
18
+ }
19
+
20
+ function RadioGroupItem({
21
+ className,
22
+ ...props
23
+ }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
24
+ return (
25
+ <RadioGroupPrimitive.Item
26
+ data-slot="radio-group-item"
27
+ className={cn(
28
+ "aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
29
+ className,
30
+ )}
31
+ {...props}
32
+ >
33
+ <RadioGroupPrimitive.Indicator
34
+ data-slot="radio-group-indicator"
35
+ className="relative flex items-center justify-center"
36
+ >
37
+ <CircleIcon className="absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2 fill-primary" />
38
+ </RadioGroupPrimitive.Indicator>
39
+ </RadioGroupPrimitive.Item>
40
+ );
41
+ }
42
+
43
+ export { RadioGroup, RadioGroupItem };
@@ -0,0 +1,45 @@
1
+ import { DotsSixVerticalIcon } from "@phosphor-icons/react";
2
+ import * as ResizablePrimitive from "react-resizable-panels";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function ResizablePanelGroup({ className, ...props }: ResizablePrimitive.GroupProps) {
7
+ return (
8
+ <ResizablePrimitive.Group
9
+ data-slot="resizable-panel-group"
10
+ className={cn("flex h-full w-full aria-[orientation=vertical]:flex-col", className)}
11
+ {...props}
12
+ />
13
+ );
14
+ }
15
+
16
+ function ResizablePanel({ ...props }: ResizablePrimitive.PanelProps) {
17
+ return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />;
18
+ }
19
+
20
+ function ResizableHandle({
21
+ withHandle,
22
+ className,
23
+ ...props
24
+ }: ResizablePrimitive.SeparatorProps & {
25
+ withHandle?: boolean;
26
+ }) {
27
+ return (
28
+ <ResizablePrimitive.Separator
29
+ data-slot="resizable-handle"
30
+ className={cn(
31
+ "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90",
32
+ className,
33
+ )}
34
+ {...props}
35
+ >
36
+ {withHandle && (
37
+ <div className="z-10 flex h-4 w-3 items-center justify-center rounded-xs border bg-border">
38
+ <DotsSixVerticalIcon className="size-2.5" />
39
+ </div>
40
+ )}
41
+ </ResizablePrimitive.Separator>
42
+ );
43
+ }
44
+
45
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
3
+
4
+ import { cn } from "./cn";
5
+
6
+ function ScrollArea({
7
+ className,
8
+ children,
9
+ ...props
10
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
11
+ return (
12
+ <ScrollAreaPrimitive.Root
13
+ data-slot="scroll-area"
14
+ className={cn("relative", className)}
15
+ {...props}
16
+ >
17
+ <ScrollAreaPrimitive.Viewport
18
+ data-slot="scroll-area-viewport"
19
+ className="size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1"
20
+ >
21
+ {children}
22
+ </ScrollAreaPrimitive.Viewport>
23
+ <ScrollBar />
24
+ <ScrollAreaPrimitive.Corner />
25
+ </ScrollAreaPrimitive.Root>
26
+ );
27
+ }
28
+
29
+ function ScrollBar({
30
+ className,
31
+ orientation = "vertical",
32
+ ...props
33
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
34
+ return (
35
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
36
+ data-slot="scroll-area-scrollbar"
37
+ orientation={orientation}
38
+ className={cn(
39
+ "flex touch-none p-px transition-colors select-none",
40
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
41
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
42
+ className,
43
+ )}
44
+ {...props}
45
+ >
46
+ <ScrollAreaPrimitive.ScrollAreaThumb
47
+ data-slot="scroll-area-thumb"
48
+ className="relative flex-1 rounded-full bg-border"
49
+ />
50
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
51
+ );
52
+ }
53
+
54
+ export { ScrollArea, ScrollBar };