@discuss-ds/ui 0.1.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/CHANGELOG.md +35 -0
- package/dist/index.cjs +3497 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +876 -0
- package/dist/index.d.ts +876 -0
- package/dist/index.js +3351 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
- package/src/styles/globals.css +434 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3351 @@
|
|
|
1
|
+
// src/components/Buttons & Actions/Button.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Slot } from "radix-ui";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
|
|
6
|
+
// src/lib/utils.ts
|
|
7
|
+
import { clsx } from "clsx";
|
|
8
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
9
|
+
var twMerge = extendTailwindMerge({
|
|
10
|
+
extend: {
|
|
11
|
+
classGroups: {
|
|
12
|
+
"font-size": [
|
|
13
|
+
{
|
|
14
|
+
text: [
|
|
15
|
+
"heading-h1",
|
|
16
|
+
"heading-h2",
|
|
17
|
+
"heading-h3",
|
|
18
|
+
"heading-h4",
|
|
19
|
+
"body-section",
|
|
20
|
+
"body-base",
|
|
21
|
+
"body-small",
|
|
22
|
+
"body-xs",
|
|
23
|
+
"body-xxs",
|
|
24
|
+
"ui-label",
|
|
25
|
+
"ui-label-large",
|
|
26
|
+
"ui-badge",
|
|
27
|
+
"ui-caption",
|
|
28
|
+
"ui-overline",
|
|
29
|
+
"ui-code",
|
|
30
|
+
"ui-placeholder",
|
|
31
|
+
"ui-input-value"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"bg-image": [{ "bg-linear": ["to-t", "to-tr", "to-r", "to-br", "to-b", "to-bl", "to-l", "to-tl"] }]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
function cn(...inputs) {
|
|
40
|
+
return twMerge(clsx(inputs));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/components/Buttons & Actions/Button.tsx
|
|
44
|
+
import { jsx } from "react/jsx-runtime";
|
|
45
|
+
var subtle = "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground hover:bg-accent-soft hover:bg-none hover:text-accent-soft-foreground disabled:bg-muted disabled:bg-none disabled:text-muted-foreground";
|
|
46
|
+
var buttonVariants = cva(
|
|
47
|
+
"inline-flex shrink-0 items-center justify-center whitespace-nowrap text-ui-label transition-colors disabled:pointer-events-none disabled:opacity-50",
|
|
48
|
+
{
|
|
49
|
+
variants: {
|
|
50
|
+
variant: {
|
|
51
|
+
default: "bg-primary text-label hover:bg-primary-hover",
|
|
52
|
+
subtle,
|
|
53
|
+
// Alias of `subtle`, kept so existing consumers don't break.
|
|
54
|
+
secondary: subtle,
|
|
55
|
+
destructive: "bg-destructive text-label hover:bg-destructive-hover",
|
|
56
|
+
outline: "border border-border bg-surface text-surface-foreground hover:border-input hover:bg-accent-soft hover:text-accent-soft-foreground disabled:bg-transparent disabled:border-input disabled:text-muted-foreground",
|
|
57
|
+
ghost: "text-surface-foreground hover:bg-accent-soft hover:text-accent-soft-foreground disabled:text-muted-foreground",
|
|
58
|
+
link: "text-surface-foreground underline hover:text-accent-foreground"
|
|
59
|
+
},
|
|
60
|
+
size: {
|
|
61
|
+
md: "h-10 min-w-10 gap-2.5 rounded-md px-4 py-2",
|
|
62
|
+
sm: "h-8 min-w-8 gap-1 rounded-sm px-2.5 py-1.5",
|
|
63
|
+
lg: "h-12 gap-2.5 rounded-md px-6 py-3 text-ui-label-large",
|
|
64
|
+
icon: "size-10 rounded-md p-0",
|
|
65
|
+
"icon-sm": "size-8 rounded-sm p-0"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
compoundVariants: [
|
|
69
|
+
// Primary icon-only is a circle at 40px (and a rounded square at 32px).
|
|
70
|
+
{ variant: "default", size: "icon", className: "rounded-full" },
|
|
71
|
+
{
|
|
72
|
+
variant: "default",
|
|
73
|
+
size: ["icon", "icon-sm"],
|
|
74
|
+
className: "disabled:border disabled:border-border disabled:bg-transparent disabled:text-muted-foreground disabled:opacity-100"
|
|
75
|
+
},
|
|
76
|
+
// Destructive icon-only drops the fill and tints the glyph instead.
|
|
77
|
+
{
|
|
78
|
+
variant: "destructive",
|
|
79
|
+
size: ["icon", "icon-sm"],
|
|
80
|
+
className: "bg-transparent text-destructive hover:bg-destructive-soft-hover"
|
|
81
|
+
},
|
|
82
|
+
{ variant: "outline", size: ["icon", "icon-sm"], className: "disabled:border-border" },
|
|
83
|
+
// Links have no box of their own.
|
|
84
|
+
{ variant: "link", className: "rounded-md bg-transparent px-4" }
|
|
85
|
+
],
|
|
86
|
+
defaultVariants: {
|
|
87
|
+
variant: "default",
|
|
88
|
+
size: "md"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
var Button = React.forwardRef(
|
|
93
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
94
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
95
|
+
return /* @__PURE__ */ jsx(Comp, { ref, className: cn(buttonVariants({ variant, size }), className), ...props });
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
Button.displayName = "Button";
|
|
99
|
+
|
|
100
|
+
// src/components/Buttons & Actions/Switch.tsx
|
|
101
|
+
import * as React2 from "react";
|
|
102
|
+
import { Switch as SwitchPrimitive } from "radix-ui";
|
|
103
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
104
|
+
var Switch = React2.forwardRef(
|
|
105
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
|
|
106
|
+
SwitchPrimitive.Root,
|
|
107
|
+
{
|
|
108
|
+
ref,
|
|
109
|
+
className: cn(
|
|
110
|
+
"inline-flex h-6 w-11 shrink-0 items-center rounded-full p-0.5 transition-colors",
|
|
111
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
112
|
+
// Brand override: selected controls use `ring`, not `primary`/`accent`.
|
|
113
|
+
"data-[state=checked]:bg-ring data-[state=unchecked]:bg-muted",
|
|
114
|
+
className
|
|
115
|
+
),
|
|
116
|
+
...props,
|
|
117
|
+
children: /* @__PURE__ */ jsx2(
|
|
118
|
+
SwitchPrimitive.Thumb,
|
|
119
|
+
{
|
|
120
|
+
className: cn(
|
|
121
|
+
"block size-5 rounded-full bg-surface shadow-sm transition-transform",
|
|
122
|
+
"data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
Switch.displayName = "Switch";
|
|
130
|
+
|
|
131
|
+
// src/components/Buttons & Actions/Toggle.tsx
|
|
132
|
+
import * as React3 from "react";
|
|
133
|
+
import { Toggle as TogglePrimitive } from "radix-ui";
|
|
134
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
135
|
+
var Toggle = React3.forwardRef(
|
|
136
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx3(
|
|
137
|
+
TogglePrimitive.Root,
|
|
138
|
+
{
|
|
139
|
+
ref,
|
|
140
|
+
className: cn(
|
|
141
|
+
"inline-flex size-10 shrink-0 items-center justify-center rounded-md text-surface-foreground transition-colors",
|
|
142
|
+
"hover:bg-accent-soft hover:text-accent-soft-foreground",
|
|
143
|
+
"data-[state=on]:bg-secondary data-[state=on]:hover:bg-accent-soft",
|
|
144
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
145
|
+
className
|
|
146
|
+
),
|
|
147
|
+
...props
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
Toggle.displayName = "Toggle";
|
|
152
|
+
|
|
153
|
+
// src/components/Conversation & AI Chat/AIMiniAvatar.tsx
|
|
154
|
+
import * as React4 from "react";
|
|
155
|
+
|
|
156
|
+
// src/components/Conversation & AI Chat/aiGlyphPaths.ts
|
|
157
|
+
var AI_GLYPH_THINKING = {
|
|
158
|
+
viewBox: "0 0 23.5102 10.31",
|
|
159
|
+
d: "M20.7764 6.13895C20.8091 6.08935 20.9139 6.07477 20.9653 6.02535C21.1265 5.87047 21.227 5.79769 21.3523 5.6889L21.3349 5.70985C21.3757 5.67187 21.4194 5.629 21.4687 5.57648C21.7621 5.26894 22.4786 4.16096 22.8403 4.43013C22.8403 4.43014 22.8403 4.43014 22.8403 4.43015C22.8438 4.43279 22.8474 4.43556 22.8508 4.43847C22.9168 4.49352 22.9251 4.63928 22.993 4.71056C23.061 4.78185 23.5711 5.14655 23.5041 5.29532C23.4036 5.50831 22.9412 5.85678 22.8715 5.95956C22.8242 6.02999 22.8059 6.14803 22.7475 6.24057C22.6464 6.40032 22.5565 6.50906 22.4809 6.62923C22.4785 6.632 22.4718 6.64062 22.4693 6.64331C22.3989 6.74734 22.341 6.85851 22.2892 7.02244C22.1391 7.06575 21.9883 7.10631 21.8375 7.14262C21.7434 7.29292 21.476 7.39415 21.4003 7.4664C21.3382 7.52673 21.3404 7.6092 21.2705 7.66966C21.2189 7.71436 21.1282 7.74838 21.0302 7.79812C21.0228 7.80313 21.0008 7.8182 20.9928 7.8224C20.9494 7.83706 20.9028 7.85865 20.856 7.89199C20.6266 8.05556 20.6529 8.23489 20.4981 8.34362C20.4171 8.3997 20.2989 8.44071 20.1779 8.48367C20.0629 8.52373 19.9434 8.57023 19.8501 8.64564C19.8314 8.67452 19.8127 8.70339 19.7937 8.73228C19.83 8.76183 19.8664 8.79129 19.9028 8.82072C19.8037 8.88716 19.7221 8.82963 19.622 8.8719C19.5039 8.92146 19.4745 9.02208 19.3928 9.05557C19.3259 9.0829 19.2105 9.05922 19.1237 9.09701C18.9965 9.1516 19.0573 9.22895 18.9919 9.2717C18.9722 9.29205 18.4308 9.51795 18.3887 9.52197C18.1304 9.58812 18.0801 9.46546 17.8631 9.48595C17.8361 9.48814 17.8091 9.4903 17.782 9.49237C17.3207 9.52161 16.8743 9.67817 16.3789 9.7352C16.285 9.7455 16.1851 9.74966 16.0822 9.74684C15.9622 9.74345 15.8411 9.73294 15.7225 9.71759C16.0452 9.39607 15.3567 9.12062 15.6025 9.64387C15.3808 9.56394 15.2157 9.69807 14.9941 9.66267C14.8498 9.63874 14.7566 9.5627 14.5364 9.54137C14.3208 9.51495 14.0878 9.5587 13.7616 9.41848C13.6405 9.36165 13.5631 9.27393 13.5919 9.09969C13.4354 9.05602 13.2983 8.98697 13.1658 8.92556C13.0992 8.89457 13.0342 8.86595 12.9619 8.83793C12.8815 8.79834 12.8349 8.81997 12.6347 8.66553C12.5818 8.65788 12.5185 8.66138 12.4458 8.68578C12.3597 8.6238 12.3017 8.26898 12.2414 8.14791C12.1605 8.05685 11.7146 7.13701 11.7091 6.94414C11.7083 6.94093 11.7074 6.93768 11.7065 6.93438C11.6552 6.75979 11.6158 6.47257 11.5821 6.33303C11.5388 6.16728 11.1933 5.9876 11.6352 5.69928C11.6536 5.50058 11.6924 5.35814 11.7614 5.21539C11.7996 5.14267 11.8487 5.06108 11.9231 4.94138C11.9508 4.89665 12.0069 4.91427 12.0188 4.88607C12.0432 4.82851 12.0458 4.71199 12.0891 4.60378C12.1604 4.42562 12.3223 4.38132 12.1443 4.31661C12.1745 4.18591 12.2099 4.05361 12.2533 3.91918C12.3093 3.89617 12.3653 3.87434 12.4217 3.85356C12.4277 3.77084 12.4368 3.68676 12.4498 3.60124C12.6122 3.82914 12.8149 3.31965 12.5882 3.35167C12.6971 3.26408 12.8129 3.18134 12.936 3.10694C13.0432 3.05147 13.1502 2.9942 13.2575 2.93523C13.445 3.18433 13.6433 2.62036 13.4965 2.52782C13.5159 2.50978 13.5359 2.49118 13.5559 2.47273C13.6468 2.43151 13.7186 2.3762 13.8101 2.30215C13.9339 2.20399 14.0605 2.08848 14.2572 2.00205C14.5866 1.86654 14.5863 1.91818 14.7383 2.00328C14.8117 1.96386 14.8906 1.92778 14.9768 1.89808C15.2046 1.61986 15.3871 1.74917 15.5554 1.87821C15.6574 1.92057 15.8644 2.08723 15.9086 2.24717C15.9561 2.38086 15.9647 2.4401 16.0174 2.50589C16.0362 2.5325 16.059 2.56113 16.0862 2.59267C15.9089 2.83438 16.1252 3.33908 16.1251 3.71466C16.1272 3.75694 16.1742 3.7651 16.1787 3.82326C16.1923 3.96864 16.0396 4.27583 16.1879 4.30844C16.1104 4.40775 16.0302 4.50104 15.9487 4.58956C15.9485 4.59211 15.9483 4.59466 15.9481 4.59722C15.9434 4.68512 15.9381 4.77303 15.9326 4.86089C15.9773 4.87807 16.0219 4.89524 16.0666 4.91242C15.8514 5.01394 15.8076 5.2888 15.7201 5.39794C15.7026 5.41968 15.6395 5.39969 15.591 5.46924C15.5342 5.55031 15.482 5.72425 15.4171 5.82229C15.4664 5.89261 15.5154 5.96317 15.5642 6.03418C15.516 6.24242 15.3088 6.23112 15.2434 6.33666C15.2371 6.34685 15.1897 6.45661 15.1414 6.56252C15.1003 6.65319 15.0605 6.74017 15.0575 6.75026C14.9983 6.92736 15.1953 6.94548 14.8653 7.42471C14.8017 7.51174 14.7031 7.55363 14.6374 7.63359C14.5939 7.68676 14.5258 7.79471 14.4522 7.90588C14.359 8.0661 14.2337 8.27035 14.258 8.34435C13.9929 8.37671 13.5599 8.69876 13.4026 8.72273C13.3557 8.73114 13.3039 8.65181 13.1715 8.69189C13.1196 8.70739 13.0387 8.75964 12.9539 8.81245C12.8709 8.86549 12.783 8.9216 12.7186 8.94208C12.5852 8.98412 12.5082 8.92996 12.4483 8.94919C12.3923 8.9672 12.3668 9.04791 12.2925 9.07862C12.0591 9.1738 11.8082 9.16385 11.6213 9.23522C11.3502 9.33814 11.1776 9.60661 10.949 9.76888C10.9348 9.77067 10.9203 9.77115 10.9058 9.77095C10.8529 9.76975 10.7975 9.7598 10.7466 9.77439C9.99772 10.0005 9.00243 10.0857 8.1768 9.85282C8.13481 9.84174 8.09342 9.83033 8.0522 9.8185C7.65595 9.74342 6.84265 9.06031 6.88897 9.55865C6.80575 9.55556 6.53393 9.38444 6.29758 9.12608C6.231 9.02829 5.91504 8.73378 5.8576 8.6732C5.70806 8.5387 5.53716 8.47446 5.42743 8.35204C5.23871 8.13938 5.11803 7.9385 4.98784 7.72031C4.93094 7.62219 4.78289 7.41761 4.64906 7.18544C4.56629 7.04595 4.42492 6.92507 4.39704 6.84099C4.36359 6.73961 4.41467 6.60764 4.3839 6.48312C4.3266 6.25751 4.2228 5.90491 4.15903 5.6261C4.13709 5.5314 4.11932 5.43956 4.10919 5.36422C4.10191 5.30774 4.17499 5.27443 4.18647 5.19139C4.22915 4.86817 4.21424 4.52439 3.96715 4.59214C4.0923 4.18224 4.00781 3.80768 4.06914 3.4305C4.07049 3.42228 4.07191 3.41407 4.0734 3.40587C4.17848 2.77229 4.60265 1.62744 5.42728 1.02539C5.5388 0.936113 5.63885 0.851595 5.72033 0.774897C6.02466 0.499997 5.92843 0.404094 6.57046 0.168732C6.72019 0.118531 6.87745 0.0750992 7.10515 0.029663C7.44001 -0.0409616 8.00784 0.000885725 8.42487 0.305113C8.52342 0.370349 8.66824 0.438081 8.84918 0.507494C9.00601 0.701494 9.15341 0.965493 9.19962 1.24429C9.25461 1.59798 9.20706 1.9295 9.02072 2.15487C9.06272 2.2086 9.10331 2.26358 9.14209 2.32146C9.12853 2.38467 9.11273 2.44783 9.09564 2.50868C9.04342 2.51339 8.99124 2.51735 8.93911 2.52058C8.80099 2.92074 8.72119 3.45798 8.53257 3.73379C8.51917 3.75362 8.50452 3.77482 8.48864 3.79731C8.18299 4.22988 7.45145 5.14772 7.14208 5.47284C6.97081 5.65357 7.04778 5.72472 6.79141 5.71506C6.77155 5.76833 6.75129 5.82205 6.73113 5.87552C6.74881 5.93119 6.76688 5.98626 6.78446 6.04197C6.67655 6.19317 6.53517 6.34587 6.39918 6.49486C6.30179 6.60171 6.20676 6.7071 6.12771 6.80983C5.86753 7.16626 5.41116 7.79089 4.96904 8.10513C4.87549 8.1762 4.78037 8.24183 4.68809 8.2947C4.56491 8.36535 4.36563 8.39839 4.25536 8.48329C4.09377 8.60676 4.15002 8.76609 3.93397 8.92203C3.68203 9.10323 3.21465 9.30524 2.7946 9.44827C2.61334 9.50835 2.4488 9.5679 2.33086 9.62822C2.22328 9.68313 2.19724 9.76099 2.12265 9.80252C1.81329 9.9754 1.54922 10.089 1.27057 10.31C0.871376 10.3138 0.823743 10.1166 0.644008 9.97432C0.509878 9.86688 0.126525 9.63933 0.0856048 9.51058C0.0484623 9.42509 0.051783 9.29751 0 9.20711C0.311082 9.00323 0.527575 9.0048 0.893831 9.00304C1.355 8.7957 1.81246 8.57815 2.27037 8.35384C2.37271 8.30354 2.47492 8.24832 2.57658 8.1893C2.6503 8.2117 2.72528 8.23255 2.80124 8.252C2.8013 8.25211 2.80136 8.25221 2.80143 8.25232C3.03486 8.18581 3.03979 8.00743 3.12463 7.91046C3.36205 7.63959 3.68578 7.33424 4.07988 6.99574C4.53563 6.62516 4.89846 6.21727 5.32159 5.69439C5.74872 5.17021 6.15919 4.65793 6.46139 4.25093C6.64154 4.00919 7.13955 3.16034 7.33028 3.04133C7.34208 3.03408 7.35548 3.03074 7.36955 3.02924C7.41387 3.02544 7.46598 3.03904 7.49046 3.00739C7.70834 2.58993 7.86103 2.13779 7.83041 1.79989C7.8547 1.70941 7.86312 1.62307 7.85378 1.53151C7.87209 1.5287 7.84915 1.45435 7.69179 1.34775C7.77026 1.34362 7.49926 1.35778 7.23888 1.52474C6.97348 1.67631 6.69939 1.87603 6.42229 2.07271C6.36356 2.11454 6.30432 2.15719 6.24453 2.20056C5.85524 2.48354 5.60232 3.08823 5.49387 3.71498C5.39928 4.24892 5.42498 4.76811 5.56179 5.30683C5.73246 5.96207 5.84566 6.51339 6.19333 6.98921C6.31865 7.19227 6.46019 7.37337 6.62146 7.53296C6.79615 7.70852 6.92033 7.78019 7.25856 8.05634C7.33453 8.12545 7.42269 8.18946 7.52192 8.24799C7.75285 8.38685 8.10613 8.47857 8.4572 8.54593C8.61666 8.57713 8.77013 8.59963 8.91167 8.62268C9.08941 8.64956 9.17441 8.79085 9.4164 8.66989C9.42212 8.70681 9.42791 8.74373 9.43379 8.78063C9.65293 8.71479 9.77712 8.60908 10.021 8.54539C10.1203 8.51928 10.2997 8.46967 10.4831 8.41151C10.6699 8.35263 10.8737 8.27862 10.9746 8.24849C11.0761 8.21757 11.0641 8.29673 11.157 8.26042C11.3161 8.19806 11.6214 7.97025 11.8416 7.87728C12.0071 7.80802 12.2892 7.74718 12.4664 7.68389C12.5014 7.67152 12.5303 7.65958 12.5544 7.6466C12.9362 7.44059 13.2264 7.19551 13.4781 6.90736C13.5439 6.83289 13.5972 6.76236 13.6731 6.65907C13.7546 6.55024 13.9356 6.40299 13.9581 6.35458C14.0011 6.26124 13.9376 6.19233 13.9591 6.12514C13.9721 6.08459 13.9882 6.04256 14.0073 5.9983C14.1356 5.69579 14.4023 5.27933 14.5269 4.98849C14.6407 4.72311 14.7511 4.44958 14.8552 4.17601C14.9522 3.92097 15.0207 3.66979 15.0372 3.45937C15.0531 3.24138 15.027 3.11048 14.9379 2.78902C14.9187 2.70766 14.878 2.57482 14.9201 2.69356C14.9293 2.78057 15.2047 3.01121 15.3025 3.00426C15.3103 3.005 15.2823 2.99694 15.209 3.02009C15.1006 3.05115 14.8991 3.17087 14.6896 3.3475C14.4622 3.54526 14.1241 3.87681 13.8343 4.11513C13.7102 4.21459 13.5954 4.34064 13.4984 4.45314C13.4195 4.54661 13.3558 4.46837 13.2997 4.56139C13.2381 4.66643 13.2646 4.75718 13.2429 4.81048C13.1582 5.0115 13.0582 5.33059 12.8983 5.73083C12.8528 5.84656 12.829 6.11681 12.8105 6.25296C12.8013 6.311 12.7318 6.36264 12.7373 6.39885C12.74 6.41716 12.7967 6.44932 12.8133 6.49994C12.8239 6.53247 12.835 6.56327 12.8464 6.59222C13.0113 6.99361 13.2145 7.29577 13.6284 7.75962C13.6287 7.75995 13.629 7.76028 13.6292 7.7606C13.5327 7.66867 13.5735 7.71591 13.5864 7.71996C13.6067 7.73297 13.6364 7.74994 13.6682 7.76708C13.7325 7.8017 13.8061 7.838 13.8819 7.87409C14.0342 7.94645 14.1967 8.01873 14.3624 8.09149C14.4295 8.12341 14.8213 8.16242 15.1241 8.16799C15.4466 8.17777 15.7837 8.17904 16.12 8.1862C16.4042 8.19173 16.7364 8.16186 17.0675 8.14113C17.3555 8.12227 17.5732 8.24796 17.6136 8.24221C17.625 8.2406 17.6357 8.23751 17.6461 8.23323C17.7042 8.20464 17.7441 8.12089 17.8688 8.07355C18.3421 7.89885 19.1022 7.67963 19.5971 7.39003C19.6136 7.38042 19.6303 7.37015 19.6473 7.35931C19.8747 7.2155 20.0413 6.98443 20.2828 6.80153C20.3065 6.7842 20.3357 6.76481 20.3699 6.74391L20.298 6.79064C20.4619 6.66741 20.7621 6.44192 20.7839 6.34931C20.7993 6.28776 20.7412 6.19318 20.7764 6.13895ZM14.3029 9.42491C14.3405 9.34309 14.2314 9.3194 14.1139 9.3164C13.9993 9.31488 13.861 9.3268 13.9789 9.41542C14.0391 9.45982 14.2868 9.46988 14.3029 9.42491ZM9.59175 9.70184C9.60097 9.75063 9.61033 9.7994 9.61981 9.84815C9.67917 9.8212 9.73753 9.79318 9.79481 9.76425C9.75681 9.73961 9.71928 9.71456 9.68227 9.6891C9.65216 9.69362 9.62202 9.69787 9.59175 9.70184Z"
|
|
160
|
+
};
|
|
161
|
+
var AI_GLYPH_WORKING = {
|
|
162
|
+
viewBox: "0 0 21.6653 7.31887",
|
|
163
|
+
d: "M21.5195 2.20094C21.5632 2.27281 21.5435 2.40302 21.5694 2.49163C21.6275 2.6923 21.6417 2.82523 21.6527 2.95596C21.6564 2.97027 21.6628 3.01397 21.6653 3.02853C21.6641 3.13693 21.6598 3.24436 21.6586 3.38773C21.6816 3.85362 21.6618 5.13496 21.204 5.07451C21.204 5.0745 21.204 5.0745 21.204 5.0745C21.1996 5.074 21.1952 5.07338 21.1907 5.07263C21.1061 5.05815 21.0241 4.94601 20.929 4.92104C20.8337 4.89639 20.2098 4.84129 20.1872 4.70468C20.162 4.5075 20.3424 4.05165 20.3322 3.94693C20.3275 3.87626 20.2696 3.79112 20.2564 3.70362C20.2253 3.50095 20.228 3.36832 20.1618 3.22753L20.1705 3.27725C20.1408 3.22743 20.1002 3.17862 20.0419 3.13125C20.0967 3.02469 20.1456 2.91373 20.1862 2.79711C20.1085 2.70121 20.1178 2.49436 20.0701 2.43438C20.0329 2.38632 19.9603 2.39539 19.9218 2.35006C19.8787 2.3002 19.8633 2.1732 19.7612 2.09203C19.7034 2.0461 19.6466 2.03107 19.595 2.02843L19.7627 2.11426C19.6671 2.14605 19.6042 2.2088 19.5173 2.20366C19.3811 2.19547 19.1788 2.06914 18.9898 2.10943C18.9652 2.12544 18.9407 2.1416 18.9163 2.1579C18.9287 2.20111 18.9406 2.24436 18.9521 2.28762C18.8618 2.29819 18.8311 2.20964 18.7478 2.20237C18.6497 2.19419 18.5963 2.27357 18.5308 2.27097C18.4776 2.26885 18.4048 2.20215 18.3342 2.20612C18.2309 2.21188 18.2544 2.30623 18.2002 2.32458C18.1776 2.32896 17.7784 2.40078 17.7565 2.40615C17.5856 2.42463 17.557 2.29863 17.4163 2.30438C17.0252 2.32264 16.6544 2.50901 16.341 2.64771C16.2001 2.7096 16.0505 2.75491 15.9061 2.79231C16.0092 2.39243 15.4001 2.37041 15.7957 2.76269C15.7449 2.76246 15.7042 2.7768 15.67 2.79808C15.5564 2.86487 15.4802 2.97434 15.3466 3.01614C15.2272 3.05323 15.1197 3.02273 14.9627 3.09457C14.6814 3.2228 14.4809 3.53873 14.2487 3.24296C13.9703 3.44596 13.6586 3.47244 13.7401 3.80561C13.6873 3.86035 13.4234 3.80763 13.3424 3.84086C13.2469 3.85834 12.8209 4.21338 12.8015 4.30503C12.7577 4.37886 12.704 4.52293 12.7165 4.60386C12.7165 4.60456 12.7165 4.60525 12.7166 4.60594C12.7245 4.73675 13.038 4.86932 12.6198 5.00545C12.6218 5.24087 12.6062 5.31289 12.5709 5.505C12.5653 5.5391 12.5078 5.54892 12.51 5.56912C12.5148 5.61101 12.5679 5.67144 12.5899 5.73138C12.625 5.82708 12.5422 5.92847 12.7068 5.83917C12.7265 5.85366 12.7463 5.86629 12.7663 5.87733C12.8032 5.90096 12.8414 5.92124 12.8766 5.93338C12.8592 5.96968 12.8434 6.00666 12.8291 6.04399C12.8751 6.0348 12.9151 6.01504 12.9349 5.9805C12.8531 6.08998 12.8602 6.12516 12.8542 6.09438C12.8536 6.06287 12.7741 5.97616 12.8523 5.90639C12.814 5.91011 12.7686 5.91968 12.7291 5.93658C12.8704 5.95935 13.0187 5.97102 13.1668 5.97103C13.2458 6.27758 13.5375 5.8631 13.4165 5.7269C13.4322 5.71942 13.4481 5.7116 13.4633 5.70383C13.6382 5.70301 13.7156 5.57219 13.8729 5.49571C14.0312 5.4108 14.0391 5.43683 14.1889 5.47644C14.2098 5.43405 14.2279 5.39151 14.2438 5.3483C14.0282 5.01309 14.4813 5.23839 14.467 4.9003C14.4628 4.86036 14.4497 4.81226 14.424 4.75824C14.6924 4.64645 14.5813 4.22813 14.4827 3.98518C14.4718 3.95634 14.4244 3.95942 14.4063 3.92204C14.3646 3.8314 14.3895 3.57996 14.2385 3.6136C14.269 3.52481 14.297 3.43419 14.3224 3.34163C14.2805 3.27925 14.2374 3.21883 14.1932 3.15937C14.147 3.17171 14.1008 3.18404 14.0545 3.19636C14.1795 3.02404 14.0534 2.83228 14.0536 2.72057C14.0538 2.69796 14.1146 2.67123 14.1077 2.60167C14.1053 2.5772 14.097 2.54816 14.0858 2.51695C14.0606 2.4458 14.0206 2.3664 14.0068 2.30319C13.9256 2.30215 13.845 2.30379 13.7653 2.30835C13.664 2.19886 13.8037 2.06102 13.7674 1.97878C13.7632 1.95836 13.5836 1.76062 13.569 1.76088C13.4625 1.71319 13.3938 1.83751 13.1876 1.69055C13.1768 1.68378 13.1679 1.67414 13.1594 1.66314C13.1251 1.62875 13.0976 1.58516 13.0563 1.56847C12.9543 1.52205 12.6158 1.57037 12.5754 1.68805C12.488 1.51352 12.1471 1.54577 12.0499 1.50822C12.0197 1.49536 12.0125 1.39933 11.915 1.38294C11.8348 1.36858 11.641 1.46343 11.5414 1.4673C11.4886 1.46852 11.4499 1.45238 11.417 1.43601C11.379 1.41974 11.3502 1.40253 11.3222 1.40479C11.2702 1.40908 11.2364 1.48093 11.1663 1.49376C10.9506 1.53213 10.7369 1.4686 10.5668 1.5019C10.3215 1.54967 10.1495 1.7839 9.97459 1.91406C9.92313 1.91395 9.86479 1.88637 9.81474 1.89889C9.18393 2.05373 8.52084 2.24974 8.06049 2.55947C7.97673 2.61393 7.82886 2.68357 7.70707 2.77585C7.47457 2.96164 7.29957 3.141 7.58115 3.23461C7.55145 3.37335 6.85892 3.81217 6.75779 3.91528C6.65223 4.01974 6.62886 4.1568 6.55292 4.24037C6.3287 4.49052 6.12192 4.63806 5.97447 4.97688C5.93734 5.06497 5.97217 5.18888 5.95013 5.22858C5.92305 5.27641 5.81725 5.29086 5.78729 5.35168C5.72348 5.47691 5.72292 5.63535 5.74247 5.70235C5.7392 5.69015 5.73474 5.68324 5.73057 5.6806C5.7259 5.67767 5.6564 5.71443 5.64159 5.73607C5.59977 5.79621 5.66356 5.86599 5.71545 5.8044C5.74124 5.7781 5.76378 5.72791 5.79373 5.65487C5.7797 5.76571 5.84646 5.7256 5.86464 5.68044C5.89311 5.65904 5.9217 5.63652 5.95175 5.6189C6.02236 5.57879 6.10324 5.51868 6.14438 5.46754C6.52517 4.99861 6.93077 4.48918 7.03916 4.16128C7.131 3.87843 7.03817 3.83671 7.2777 3.53191C7.3285 3.46368 7.38339 3.39761 7.43515 3.31198C7.55556 3.123 7.78512 2.91105 7.53243 2.74719C7.53788 2.72612 7.54202 2.70518 7.54516 2.6844C7.57114 2.34511 7.5461 2.13531 7.71559 1.91428C7.66205 1.8939 7.6084 1.87498 7.55468 1.85784C7.54899 1.82465 7.54284 1.79249 7.53625 1.76174C7.58249 1.7438 7.62858 1.72536 7.6745 1.70638C7.66025 1.58943 7.57775 1.48171 7.50533 1.44831C7.42954 1.40963 7.39741 1.46692 7.42084 1.47901C7.42785 1.48323 7.43783 1.48634 7.4422 1.48541C7.17989 1.34605 6.43947 1.33364 6.13402 1.38718C5.94822 1.40777 5.97834 1.51041 5.80067 1.34866C5.76607 1.37821 5.73267 1.40807 5.6993 1.43868C5.69344 1.49226 5.68877 1.54561 5.68469 1.59899C5.60346 1.6368 5.51247 1.67081 5.41947 1.70715C5.25719 1.77218 5.08842 1.83937 4.95565 1.92193C4.5607 2.16343 4.07316 2.6724 3.66471 2.90149C3.56135 2.95829 3.38743 2.97861 3.30147 3.05515C3.17694 3.16659 3.25374 3.3124 3.10481 3.45557C2.97543 3.58045 2.7598 3.72772 2.55869 3.88391C2.36237 4.0352 2.17431 4.20354 2.0791 4.34155C2.02181 4.42439 2.04245 4.49771 2.00764 4.55703C1.86276 4.80728 1.7279 5.00722 1.67572 5.28395C1.40472 5.45513 1.24398 5.34517 1.02204 5.34271C0.85587 5.34339 0.443166 5.39397 0.298309 5.53289C0.195382 5.59242 0.114988 5.33164 0 5.398C0.0672404 4.97998 0.13697 4.91763 0.231708 4.78102C0.32599 4.66409 0.441105 4.57777 0.588846 4.47063C0.890159 3.96002 1.2295 3.4868 1.62503 3.03919C1.6425 3.01952 1.66013 2.99985 1.67793 2.98018C1.75746 2.97633 1.83576 2.97461 1.91436 2.97328C1.91444 2.97336 1.91453 2.97345 1.91462 2.97353C2.12092 2.85218 2.0899 2.68327 2.15819 2.5722C2.597 1.85461 3.67978 1.04205 4.76963 0.519159C5.32989 0.243909 5.91307 0.0975681 6.38788 0.0444249C6.6555 -0.0118234 7.54053 -0.0488161 7.88667 0.153048C7.94618 0.17965 7.98958 0.207339 8.01918 0.232423C8.08533 0.290805 8.06243 0.37677 8.1281 0.424204C8.788 0.858895 8.84837 1.50779 8.95406 1.97915C8.94198 2.20167 8.92957 2.41449 8.93075 2.60529C8.95493 3.51671 8.63286 4.38247 8.20801 5.05868C7.91193 5.53227 7.58085 5.95424 7.27747 6.35851C7.01913 6.69107 6.69575 6.90231 6.33432 7.03688C5.96029 7.1761 5.5056 7.15874 5.13666 6.97761C4.77988 6.8026 4.46111 6.49764 4.34143 6.02344C4.13016 4.94119 4.72195 4.23827 5.12818 3.69949C5.57383 3.15323 6.05227 2.7034 6.49909 2.26167C6.60356 2.1588 6.70991 2.04377 6.81333 1.92552C7.11534 1.5805 7.51671 1.27415 7.87436 1.12238C8.09128 1.03067 8.22986 1.1177 8.46139 0.914443C8.47778 0.948059 8.49413 0.981695 8.51042 1.01535C8.72666 0.884509 8.85128 0.753639 9.11283 0.667108C9.33416 0.590984 9.91261 0.445577 10.1078 0.420265C10.2081 0.405908 10.1856 0.481938 10.2787 0.461915C10.4358 0.427279 10.7555 0.265817 10.9724 0.225515C11.0344 0.213886 11.1095 0.207961 11.1911 0.203672C11.3902 0.189668 11.6101 0.200757 11.7294 0.184671C12.3244 0.0941229 13.0686 0.0795288 13.6887 0.360932C13.7173 0.373361 13.7452 0.386407 13.7732 0.400348C13.9935 0.504733 14.1863 0.761282 14.2374 0.804733C14.3459 0.889986 14.4353 0.85695 14.5099 0.917486C14.8544 1.19506 15.0555 1.7393 15.1651 2.08618C15.1811 2.13408 15.1962 2.17883 15.2114 2.2209C15.5209 3.10883 15.7231 4.06037 15.5398 5.11604C15.4759 5.44103 15.3468 5.76469 15.156 6.04424C14.7344 6.73319 13.702 7.23955 12.966 7.30853C12.4728 7.37179 12.1947 7.12924 12.0524 6.99922C11.8908 6.83031 12.009 6.80775 11.9034 6.68162C11.8329 6.59062 11.7694 6.53954 11.7184 6.49409C11.6899 6.46762 11.6662 6.44349 11.6504 6.41689C11.2557 5.85657 11.3479 4.693 11.5144 4.34149C11.5151 4.33971 11.5158 4.33796 11.5166 4.33623C11.5524 4.24664 11.6398 4.2033 11.6561 4.14998C11.6648 4.12266 11.6353 4.04477 11.6651 3.9555C11.9475 3.16456 12.4817 2.80074 13.0494 2.47332C13.7152 2.10344 14.4121 1.81425 15.0508 1.49401C15.5692 1.23861 16.1097 1.07617 16.6335 0.991567C16.9162 0.946369 17.1285 1.06931 17.1663 1.06219C17.2508 1.04785 17.2925 0.940458 17.4657 0.897656C18.0451 0.752637 18.8417 0.865944 19.4146 0.908582C19.6055 0.920524 19.8557 0.905474 20.0965 0.923509C20.1598 0.938582 20.3128 1.02252 20.3653 1.06104C20.4783 1.12075 20.5849 1.18937 20.6707 1.26172C20.897 1.42686 21.21 2.00184 21.2965 2.08728C21.3583 2.13718 21.4717 2.12365 21.5195 2.20094ZM14.7616 3.09249C14.7223 2.91995 14.4452 3.20284 14.6094 3.23071C14.6457 3.23713 14.7714 3.13732 14.7616 3.09249ZM8.90352 1.8629C8.92394 1.90808 8.94428 1.9533 8.96454 1.99855C8.99986 1.96338 9.03568 1.92859 9.07244 1.894C9.0381 1.87445 9.00388 1.85503 8.96929 1.83592C8.94712 1.84485 8.92519 1.85385 8.90352 1.8629Z"
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/components/Conversation & AI Chat/AIMiniAvatar.tsx
|
|
167
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
168
|
+
var defaultLabel = {
|
|
169
|
+
thinking: "Thinking...",
|
|
170
|
+
executing: "Executing...",
|
|
171
|
+
working: "Working on it..."
|
|
172
|
+
};
|
|
173
|
+
var AIMiniAvatar = React4.forwardRef(
|
|
174
|
+
({ className, status = "idle", label, elapsed, ...props }, ref) => {
|
|
175
|
+
const glyph = status === "working" ? AI_GLYPH_WORKING : AI_GLYPH_THINKING;
|
|
176
|
+
const busy = status !== "idle";
|
|
177
|
+
return /* @__PURE__ */ jsxs(
|
|
178
|
+
"div",
|
|
179
|
+
{
|
|
180
|
+
ref,
|
|
181
|
+
role: "status",
|
|
182
|
+
"aria-live": "polite",
|
|
183
|
+
className: cn("flex items-center gap-2.5", className),
|
|
184
|
+
...props,
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ jsx4(
|
|
187
|
+
"svg",
|
|
188
|
+
{
|
|
189
|
+
"aria-hidden": "true",
|
|
190
|
+
viewBox: glyph.viewBox,
|
|
191
|
+
fill: "none",
|
|
192
|
+
className: cn(
|
|
193
|
+
"h-5.75 shrink-0 fill-accent",
|
|
194
|
+
status === "working" ? "w-5" : "w-5.25",
|
|
195
|
+
busy && "motion-safe:animate-pulse"
|
|
196
|
+
),
|
|
197
|
+
children: /* @__PURE__ */ jsx4("path", { d: glyph.d })
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
busy && /* @__PURE__ */ jsx4(
|
|
201
|
+
"span",
|
|
202
|
+
{
|
|
203
|
+
className: cn(
|
|
204
|
+
"text-ui-caption whitespace-nowrap",
|
|
205
|
+
status === "executing" ? "bg-linear-to-r from-secondary-muted-foreground to-secondary-muted-foreground/40 bg-clip-text text-transparent" : "text-secondary-muted-foreground"
|
|
206
|
+
),
|
|
207
|
+
children: label ?? defaultLabel[status]
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
status === "working" && elapsed != null && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
211
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: "size-0.5 rounded-full bg-secondary-muted-foreground" }),
|
|
212
|
+
/* @__PURE__ */ jsx4("span", { className: "text-ui-caption whitespace-nowrap text-secondary-muted-foreground", children: elapsed })
|
|
213
|
+
] })
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
AIMiniAvatar.displayName = "AIMiniAvatar";
|
|
220
|
+
|
|
221
|
+
// src/components/Conversation & AI Chat/AIResponseContainer.tsx
|
|
222
|
+
import * as React5 from "react";
|
|
223
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
224
|
+
var AIResponseContainer = React5.forwardRef(
|
|
225
|
+
({ className, title, children, actions, feedback, ...props }, ref) => /* @__PURE__ */ jsxs2("div", { ref, className: cn("flex w-full max-w-188 flex-col items-start gap-4", className), ...props, children: [
|
|
226
|
+
title && /* @__PURE__ */ jsx5("h2", { className: "text-heading-h4 text-surface-foreground", children: title }),
|
|
227
|
+
/* @__PURE__ */ jsx5("div", { className: "flex w-full flex-col gap-4 text-body-base text-surface-foreground [&>p]:opacity-90", children }),
|
|
228
|
+
actions,
|
|
229
|
+
feedback
|
|
230
|
+
] })
|
|
231
|
+
);
|
|
232
|
+
AIResponseContainer.displayName = "AIResponseContainer";
|
|
233
|
+
|
|
234
|
+
// src/components/Conversation & AI Chat/AskAiToggle.tsx
|
|
235
|
+
import * as React6 from "react";
|
|
236
|
+
import { Sparkle } from "@phosphor-icons/react";
|
|
237
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
238
|
+
import { Toggle as TogglePrimitive2 } from "radix-ui";
|
|
239
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
240
|
+
var askAiToggleVariants = cva2(
|
|
241
|
+
"inline-flex shrink-0 items-center justify-center text-surface-foreground transition-colors disabled:pointer-events-none disabled:opacity-50",
|
|
242
|
+
{
|
|
243
|
+
variants: {
|
|
244
|
+
type: {
|
|
245
|
+
// 40px, filled with the subtle fill until pressed.
|
|
246
|
+
menu: "size-10 rounded-md bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 data-[state=on]:bg-accent-soft data-[state=on]:bg-none data-[state=on]:text-accent-soft-foreground",
|
|
247
|
+
// 32px, bare until pressed.
|
|
248
|
+
action: "size-8 rounded-sm hover:bg-accent-soft data-[state=on]:bg-accent-soft data-[state=on]:text-accent-soft-foreground"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
defaultVariants: { type: "menu" }
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
var AskAiToggle = React6.forwardRef(
|
|
255
|
+
({ className, type, "aria-label": ariaLabel = "Ask AI", pressed, defaultPressed, ...props }, ref) => {
|
|
256
|
+
const [internal, setInternal] = React6.useState(defaultPressed ?? false);
|
|
257
|
+
const on = pressed ?? internal;
|
|
258
|
+
return /* @__PURE__ */ jsx6(
|
|
259
|
+
TogglePrimitive2.Root,
|
|
260
|
+
{
|
|
261
|
+
ref,
|
|
262
|
+
"aria-label": ariaLabel,
|
|
263
|
+
pressed,
|
|
264
|
+
defaultPressed,
|
|
265
|
+
onPressedChange: (next) => {
|
|
266
|
+
setInternal(next);
|
|
267
|
+
props.onPressedChange?.(next);
|
|
268
|
+
},
|
|
269
|
+
className: cn(askAiToggleVariants({ type }), className),
|
|
270
|
+
...props,
|
|
271
|
+
children: /* @__PURE__ */ jsx6(Sparkle, { size: 16, weight: on ? "fill" : "regular", "aria-hidden": true })
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
AskAiToggle.displayName = "AskAiToggle";
|
|
277
|
+
|
|
278
|
+
// src/components/Conversation & AI Chat/ChatChoices.tsx
|
|
279
|
+
import * as React10 from "react";
|
|
280
|
+
|
|
281
|
+
// src/components/Forms & Data Entry/Checkbox.tsx
|
|
282
|
+
import * as React8 from "react";
|
|
283
|
+
import { Check, Minus } from "@phosphor-icons/react";
|
|
284
|
+
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
285
|
+
|
|
286
|
+
// src/components/Forms & Data Entry/Label.tsx
|
|
287
|
+
import * as React7 from "react";
|
|
288
|
+
import { Label as LabelPrimitive } from "radix-ui";
|
|
289
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
290
|
+
var Label = React7.forwardRef(
|
|
291
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
|
|
292
|
+
LabelPrimitive.Root,
|
|
293
|
+
{
|
|
294
|
+
ref,
|
|
295
|
+
className: cn(
|
|
296
|
+
"text-ui-label text-surface-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
297
|
+
className
|
|
298
|
+
),
|
|
299
|
+
...props
|
|
300
|
+
}
|
|
301
|
+
)
|
|
302
|
+
);
|
|
303
|
+
Label.displayName = "Label";
|
|
304
|
+
|
|
305
|
+
// src/components/Forms & Data Entry/Checkbox.tsx
|
|
306
|
+
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
307
|
+
var Checkbox = React8.forwardRef(
|
|
308
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
|
|
309
|
+
CheckboxPrimitive.Root,
|
|
310
|
+
{
|
|
311
|
+
ref,
|
|
312
|
+
className: cn(
|
|
313
|
+
"peer inline-flex size-4 shrink-0 items-center justify-center rounded-xxs border-2 border-input bg-surface transition-colors",
|
|
314
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
315
|
+
// Brand override: selected controls use `ring`, not `primary`/`accent`.
|
|
316
|
+
"data-[state=checked]:border-ring data-[state=checked]:bg-ring data-[state=checked]:text-label",
|
|
317
|
+
"data-[state=indeterminate]:border-ring data-[state=indeterminate]:bg-ring data-[state=indeterminate]:text-label",
|
|
318
|
+
className
|
|
319
|
+
),
|
|
320
|
+
...props,
|
|
321
|
+
children: /* @__PURE__ */ jsx8(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: props.checked === "indeterminate" ? /* @__PURE__ */ jsx8(Minus, { size: 12, weight: "bold", "aria-hidden": true }) : /* @__PURE__ */ jsx8(Check, { size: 12, weight: "bold", "aria-hidden": true }) })
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
Checkbox.displayName = "Checkbox";
|
|
326
|
+
var CheckboxField = React8.forwardRef(
|
|
327
|
+
({ label, description, id, className, disabled, ...props }, ref) => {
|
|
328
|
+
const generatedId = React8.useId();
|
|
329
|
+
const controlId = id ?? generatedId;
|
|
330
|
+
const descriptionId = `${controlId}-description`;
|
|
331
|
+
return /* @__PURE__ */ jsxs3(
|
|
332
|
+
"div",
|
|
333
|
+
{
|
|
334
|
+
className: cn("flex gap-2", description ? "items-start pt-0.5" : "items-center", disabled && "opacity-50", className),
|
|
335
|
+
children: [
|
|
336
|
+
/* @__PURE__ */ jsx8(
|
|
337
|
+
Checkbox,
|
|
338
|
+
{
|
|
339
|
+
ref,
|
|
340
|
+
id: controlId,
|
|
341
|
+
disabled,
|
|
342
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
343
|
+
className: description ? "mt-0.5" : void 0,
|
|
344
|
+
...props
|
|
345
|
+
}
|
|
346
|
+
),
|
|
347
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-0.5", children: [
|
|
348
|
+
/* @__PURE__ */ jsx8(Label, { htmlFor: controlId, className: cn(!description && "font-normal leading-5"), children: label }),
|
|
349
|
+
description && /* @__PURE__ */ jsx8("p", { id: descriptionId, className: "text-xs text-secondary-muted-foreground", children: description })
|
|
350
|
+
] })
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
CheckboxField.displayName = "CheckboxField";
|
|
357
|
+
|
|
358
|
+
// src/components/Forms & Data Entry/RadioGroup.tsx
|
|
359
|
+
import * as React9 from "react";
|
|
360
|
+
import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
|
|
361
|
+
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
362
|
+
var RadioGroup = React9.forwardRef(
|
|
363
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx9(RadioGroupPrimitive.Root, { ref, className: cn("flex flex-col gap-2", className), ...props })
|
|
364
|
+
);
|
|
365
|
+
RadioGroup.displayName = "RadioGroup";
|
|
366
|
+
var RadioGroupItem = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
|
|
367
|
+
RadioGroupPrimitive.Item,
|
|
368
|
+
{
|
|
369
|
+
ref,
|
|
370
|
+
className: cn(
|
|
371
|
+
"peer inline-flex size-5 shrink-0 items-center justify-center rounded-full border-2 border-input bg-surface transition-colors",
|
|
372
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
373
|
+
// Brand override: selected controls use `ring`, not `primary`/`accent`.
|
|
374
|
+
"data-[state=checked]:border-ring",
|
|
375
|
+
className
|
|
376
|
+
),
|
|
377
|
+
...props,
|
|
378
|
+
children: /* @__PURE__ */ jsx9(RadioGroupPrimitive.Indicator, { className: "size-2.5 rounded-full bg-ring" })
|
|
379
|
+
}
|
|
380
|
+
));
|
|
381
|
+
RadioGroupItem.displayName = "RadioGroupItem";
|
|
382
|
+
var RadioGroupFieldItem = React9.forwardRef(({ label, description, id, className, disabled, ...props }, ref) => {
|
|
383
|
+
const generatedId = React9.useId();
|
|
384
|
+
const controlId = id ?? generatedId;
|
|
385
|
+
const descriptionId = `${controlId}-description`;
|
|
386
|
+
return /* @__PURE__ */ jsxs4(
|
|
387
|
+
"div",
|
|
388
|
+
{
|
|
389
|
+
className: cn("flex gap-2", description ? "items-start pt-0.5" : "items-center", disabled && "opacity-50", className),
|
|
390
|
+
children: [
|
|
391
|
+
/* @__PURE__ */ jsx9(
|
|
392
|
+
RadioGroupItem,
|
|
393
|
+
{
|
|
394
|
+
ref,
|
|
395
|
+
id: controlId,
|
|
396
|
+
disabled,
|
|
397
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
398
|
+
...props
|
|
399
|
+
}
|
|
400
|
+
),
|
|
401
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-0.5", children: [
|
|
402
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: controlId, className: cn(!description && "font-normal leading-5"), children: label }),
|
|
403
|
+
description && /* @__PURE__ */ jsx9("p", { id: descriptionId, className: "text-xs text-secondary-muted-foreground", children: description })
|
|
404
|
+
] })
|
|
405
|
+
]
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
});
|
|
409
|
+
RadioGroupFieldItem.displayName = "RadioGroupFieldItem";
|
|
410
|
+
|
|
411
|
+
// src/components/Conversation & AI Chat/ChatChoices.tsx
|
|
412
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
413
|
+
var ChatChoices = React10.forwardRef(
|
|
414
|
+
({ className, title, children, ...props }, ref) => /* @__PURE__ */ jsxs5("div", { ref, className: cn("flex flex-col", className), ...props, children: [
|
|
415
|
+
/* @__PURE__ */ jsx10("div", { className: "border-b border-border px-6 pt-5 pb-4", children: /* @__PURE__ */ jsx10("p", { className: "text-body-section text-surface-foreground", children: title }) }),
|
|
416
|
+
children
|
|
417
|
+
] })
|
|
418
|
+
);
|
|
419
|
+
ChatChoices.displayName = "ChatChoices";
|
|
420
|
+
var rowClasses = "flex w-full flex-col gap-1 border-b border-border px-6 py-4 text-left text-body-small";
|
|
421
|
+
function ChatOption(props) {
|
|
422
|
+
const id = React10.useId();
|
|
423
|
+
const descriptionId = `${id}-description`;
|
|
424
|
+
if (props.kind === "radio" || props.kind === "checkbox") {
|
|
425
|
+
const { title: title2, description: description2, className: className2 } = props;
|
|
426
|
+
const control = props.kind === "radio" ? /* @__PURE__ */ jsx10(RadioGroupItem, { id, value: props.value, disabled: props.disabled, "aria-describedby": description2 ? descriptionId : void 0 }) : /* @__PURE__ */ jsx10(
|
|
427
|
+
Checkbox,
|
|
428
|
+
{
|
|
429
|
+
id,
|
|
430
|
+
checked: props.checked,
|
|
431
|
+
defaultChecked: props.defaultChecked,
|
|
432
|
+
onCheckedChange: (next) => props.onCheckedChange?.(next === true),
|
|
433
|
+
disabled: props.disabled,
|
|
434
|
+
"aria-describedby": description2 ? descriptionId : void 0
|
|
435
|
+
}
|
|
436
|
+
);
|
|
437
|
+
return /* @__PURE__ */ jsxs5("div", { className: cn(rowClasses, "cursor-default", className2), children: [
|
|
438
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2.5 py-1", children: [
|
|
439
|
+
control,
|
|
440
|
+
/* @__PURE__ */ jsx10("label", { htmlFor: id, className: "text-ui-label text-surface-foreground", children: title2 })
|
|
441
|
+
] }),
|
|
442
|
+
description2 && /* @__PURE__ */ jsx10("p", { id: descriptionId, className: "pl-7.75 text-sm leading-[1.4] text-secondary-muted-foreground", children: description2 })
|
|
443
|
+
] });
|
|
444
|
+
}
|
|
445
|
+
const { title, description, className, kind: _kind, ...buttonProps } = props;
|
|
446
|
+
return /* @__PURE__ */ jsxs5(
|
|
447
|
+
"button",
|
|
448
|
+
{
|
|
449
|
+
type: "button",
|
|
450
|
+
className: cn(rowClasses, "transition-colors hover:bg-accent-soft", className),
|
|
451
|
+
...buttonProps,
|
|
452
|
+
children: [
|
|
453
|
+
/* @__PURE__ */ jsx10("span", { className: "text-ui-label text-surface-foreground", children: title }),
|
|
454
|
+
description && /* @__PURE__ */ jsx10("span", { className: "text-body-small text-secondary-muted-foreground", children: description })
|
|
455
|
+
]
|
|
456
|
+
}
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/components/Conversation & AI Chat/ChatInput.tsx
|
|
461
|
+
import * as React11 from "react";
|
|
462
|
+
import { ArrowUp, Plus } from "@phosphor-icons/react";
|
|
463
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
464
|
+
var ChatInput = React11.forwardRef(
|
|
465
|
+
({
|
|
466
|
+
className,
|
|
467
|
+
value,
|
|
468
|
+
defaultValue = "",
|
|
469
|
+
onValueChange,
|
|
470
|
+
onSubmit,
|
|
471
|
+
placeholder = "Add context or ask for changes...",
|
|
472
|
+
"aria-label": ariaLabel = "Message",
|
|
473
|
+
attachments,
|
|
474
|
+
choices,
|
|
475
|
+
trailing,
|
|
476
|
+
onAdd,
|
|
477
|
+
addLabel = "Add",
|
|
478
|
+
sendLabel = "Send",
|
|
479
|
+
disabled,
|
|
480
|
+
...props
|
|
481
|
+
}, ref) => {
|
|
482
|
+
const [internal, setInternal] = React11.useState(defaultValue);
|
|
483
|
+
const text = value ?? internal;
|
|
484
|
+
const filled = text.trim() !== "" || attachments != null;
|
|
485
|
+
const submit = () => {
|
|
486
|
+
if (!text.trim() && attachments == null) return;
|
|
487
|
+
onSubmit?.(text);
|
|
488
|
+
};
|
|
489
|
+
return /* @__PURE__ */ jsxs6(
|
|
490
|
+
"div",
|
|
491
|
+
{
|
|
492
|
+
ref,
|
|
493
|
+
className: cn(
|
|
494
|
+
"flex w-full flex-col overflow-hidden rounded-2xl border border-border bg-surface shadow-xs",
|
|
495
|
+
"focus-within:border-input-accent",
|
|
496
|
+
className
|
|
497
|
+
),
|
|
498
|
+
...props,
|
|
499
|
+
children: [
|
|
500
|
+
choices,
|
|
501
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-4 p-4", children: [
|
|
502
|
+
attachments && /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-4", children: attachments }),
|
|
503
|
+
/* @__PURE__ */ jsx11(
|
|
504
|
+
"textarea",
|
|
505
|
+
{
|
|
506
|
+
rows: 1,
|
|
507
|
+
"aria-label": ariaLabel,
|
|
508
|
+
value: text,
|
|
509
|
+
disabled,
|
|
510
|
+
placeholder,
|
|
511
|
+
onChange: (event) => {
|
|
512
|
+
setInternal(event.target.value);
|
|
513
|
+
onValueChange?.(event.target.value);
|
|
514
|
+
},
|
|
515
|
+
onKeyDown: (event) => {
|
|
516
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
517
|
+
event.preventDefault();
|
|
518
|
+
submit();
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
className: "field-sizing-content max-h-60 min-h-7 w-full resize-none bg-transparent text-body-base text-surface-foreground outline-none placeholder:text-muted-foreground"
|
|
522
|
+
}
|
|
523
|
+
)
|
|
524
|
+
] }),
|
|
525
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5 px-2.5 pt-2 pb-2.5", children: [
|
|
526
|
+
onAdd && /* @__PURE__ */ jsx11(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": addLabel, disabled, onClick: onAdd, children: /* @__PURE__ */ jsx11(Plus, { size: 16, "aria-hidden": true }) }),
|
|
527
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-1 items-center justify-end gap-1.5", children: [
|
|
528
|
+
trailing,
|
|
529
|
+
/* @__PURE__ */ jsx11(
|
|
530
|
+
Button,
|
|
531
|
+
{
|
|
532
|
+
type: "button",
|
|
533
|
+
variant: filled ? "default" : "outline",
|
|
534
|
+
size: "icon",
|
|
535
|
+
"aria-label": sendLabel,
|
|
536
|
+
disabled: disabled || !filled,
|
|
537
|
+
onClick: submit,
|
|
538
|
+
className: cn(!filled && "disabled:opacity-100 disabled:border-border disabled:text-muted-foreground"),
|
|
539
|
+
children: /* @__PURE__ */ jsx11(ArrowUp, { size: 16, "aria-hidden": true })
|
|
540
|
+
}
|
|
541
|
+
)
|
|
542
|
+
] })
|
|
543
|
+
] })
|
|
544
|
+
]
|
|
545
|
+
}
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
ChatInput.displayName = "ChatInput";
|
|
550
|
+
var AskAiInput = React11.forwardRef(
|
|
551
|
+
({ className, value, defaultValue = "", onValueChange, onSubmit, sendLabel = "Send", placeholder = "Ask for changes", disabled, ...props }, ref) => {
|
|
552
|
+
const [internal, setInternal] = React11.useState(defaultValue);
|
|
553
|
+
const text = value ?? internal;
|
|
554
|
+
const filled = text.trim() !== "";
|
|
555
|
+
return /* @__PURE__ */ jsxs6(
|
|
556
|
+
"form",
|
|
557
|
+
{
|
|
558
|
+
className: cn(
|
|
559
|
+
"flex min-h-10 w-full items-center gap-2 rounded-full border border-border bg-surface py-1.5 pr-1.5 pl-2 shadow-sm",
|
|
560
|
+
"focus-within:border-input-accent",
|
|
561
|
+
className
|
|
562
|
+
),
|
|
563
|
+
onSubmit: (event) => {
|
|
564
|
+
event.preventDefault();
|
|
565
|
+
if (filled) onSubmit?.(text);
|
|
566
|
+
},
|
|
567
|
+
children: [
|
|
568
|
+
/* @__PURE__ */ jsx11(
|
|
569
|
+
"input",
|
|
570
|
+
{
|
|
571
|
+
ref,
|
|
572
|
+
value: text,
|
|
573
|
+
disabled,
|
|
574
|
+
placeholder,
|
|
575
|
+
onChange: (event) => {
|
|
576
|
+
setInternal(event.target.value);
|
|
577
|
+
onValueChange?.(event.target.value);
|
|
578
|
+
},
|
|
579
|
+
className: "min-w-0 flex-1 bg-transparent text-body-small text-surface-foreground outline-none placeholder:text-muted-foreground",
|
|
580
|
+
...props
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
/* @__PURE__ */ jsx11(
|
|
584
|
+
Button,
|
|
585
|
+
{
|
|
586
|
+
type: "submit",
|
|
587
|
+
variant: filled ? "default" : "outline",
|
|
588
|
+
size: "icon",
|
|
589
|
+
"aria-label": sendLabel,
|
|
590
|
+
disabled: disabled || !filled,
|
|
591
|
+
className: cn(!filled && "disabled:opacity-100 disabled:border-border disabled:text-muted-foreground"),
|
|
592
|
+
children: /* @__PURE__ */ jsx11(ArrowUp, { size: 16, "aria-hidden": true })
|
|
593
|
+
}
|
|
594
|
+
)
|
|
595
|
+
]
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
AskAiInput.displayName = "AskAiInput";
|
|
601
|
+
|
|
602
|
+
// src/components/Conversation & AI Chat/FileAttachment.tsx
|
|
603
|
+
import * as React12 from "react";
|
|
604
|
+
import { X } from "@phosphor-icons/react";
|
|
605
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
606
|
+
var FileAttachment = React12.forwardRef(
|
|
607
|
+
({ className, name, type, onRemove, removeLabel, ...props }, ref) => /* @__PURE__ */ jsxs7("div", { ref, className: cn("group/file relative w-32 shrink-0", className), ...props, children: [
|
|
608
|
+
/* @__PURE__ */ jsxs7(
|
|
609
|
+
"div",
|
|
610
|
+
{
|
|
611
|
+
className: cn(
|
|
612
|
+
"flex flex-col gap-1.5 border border-border bg-surface px-2.5 pt-2.5 pb-3",
|
|
613
|
+
onRemove ? "rounded-xl" : "rounded-lg"
|
|
614
|
+
),
|
|
615
|
+
children: [
|
|
616
|
+
/* @__PURE__ */ jsx12("p", { className: "line-clamp-2 min-h-8 break-all text-ui-caption text-surface-foreground", title: name, children: name }),
|
|
617
|
+
type && /* @__PURE__ */ jsx12("span", { className: "w-fit rounded-xs bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 px-1.5 py-px text-body-xxs font-semibold tracking-wider text-secondary-muted-foreground uppercase", children: type })
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
),
|
|
621
|
+
onRemove && /* @__PURE__ */ jsx12(
|
|
622
|
+
Button,
|
|
623
|
+
{
|
|
624
|
+
type: "button",
|
|
625
|
+
variant: "outline",
|
|
626
|
+
size: "icon-sm",
|
|
627
|
+
"aria-label": removeLabel ?? `Remove ${name}`,
|
|
628
|
+
onClick: onRemove,
|
|
629
|
+
className: "absolute right-0 bottom-0 rounded-full opacity-0 transition-opacity group-hover/file:opacity-100 group-focus-within/file:opacity-100",
|
|
630
|
+
children: /* @__PURE__ */ jsx12(X, { size: 16, "aria-hidden": true })
|
|
631
|
+
}
|
|
632
|
+
)
|
|
633
|
+
] })
|
|
634
|
+
);
|
|
635
|
+
FileAttachment.displayName = "FileAttachment";
|
|
636
|
+
|
|
637
|
+
// src/components/Conversation & AI Chat/ProjectSelector.tsx
|
|
638
|
+
import * as React14 from "react";
|
|
639
|
+
import { CaretDown, FolderOpen, FolderSimple } from "@phosphor-icons/react";
|
|
640
|
+
|
|
641
|
+
// src/components/Overlays & Feedback/DropdownMenu.tsx
|
|
642
|
+
import * as React13 from "react";
|
|
643
|
+
import { CaretRight, Check as Check2, Trash } from "@phosphor-icons/react";
|
|
644
|
+
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
645
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
646
|
+
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
647
|
+
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
648
|
+
var DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
649
|
+
var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
650
|
+
var DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
651
|
+
var contentClasses = "min-w-80 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md";
|
|
652
|
+
function useKeyboardModality(onKeyDown, onPointerMove) {
|
|
653
|
+
const [keyboard, setKeyboard] = React13.useState(false);
|
|
654
|
+
return {
|
|
655
|
+
"data-keyboard": keyboard ? "" : void 0,
|
|
656
|
+
onKeyDown: (event) => {
|
|
657
|
+
setKeyboard(true);
|
|
658
|
+
onKeyDown?.(event);
|
|
659
|
+
},
|
|
660
|
+
onPointerMove: (event) => {
|
|
661
|
+
setKeyboard(false);
|
|
662
|
+
onPointerMove?.(event);
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
var DropdownMenuContent = React13.forwardRef(({ className, sideOffset = 4, onKeyDown, onPointerMove, ...props }, ref) => /* @__PURE__ */ jsx13(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx13(
|
|
667
|
+
DropdownMenuPrimitive.Content,
|
|
668
|
+
{
|
|
669
|
+
ref,
|
|
670
|
+
sideOffset,
|
|
671
|
+
style: { zIndex: "var(--sys-z-30)" },
|
|
672
|
+
className: cn(contentClasses, "group/menu flex flex-col gap-0.5", className),
|
|
673
|
+
...useKeyboardModality(onKeyDown, onPointerMove),
|
|
674
|
+
...props
|
|
675
|
+
}
|
|
676
|
+
) }));
|
|
677
|
+
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
678
|
+
var itemBase = "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-body-base text-surface-foreground outline-none select-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
|
|
679
|
+
var itemHover = "data-[highlighted]:bg-accent-soft group-data-[keyboard]/menu:data-[highlighted]:outline-solid group-data-[keyboard]/menu:data-[highlighted]:outline-2 group-data-[keyboard]/menu:data-[highlighted]:-outline-offset-2 group-data-[keyboard]/menu:data-[highlighted]:outline-ring";
|
|
680
|
+
var selectedItem = "data-[state=checked]:text-ui-label-large data-[state=checked]:text-accent-foreground";
|
|
681
|
+
function ItemBody({ children, description }) {
|
|
682
|
+
return /* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
683
|
+
/* @__PURE__ */ jsx13("span", { children }),
|
|
684
|
+
description && /* @__PURE__ */ jsx13("span", { className: "text-xs leading-normal text-secondary-muted-foreground", children: description })
|
|
685
|
+
] });
|
|
686
|
+
}
|
|
687
|
+
var DropdownMenuItem = React13.forwardRef(({ className, children, description, variant = "default", icon, ...props }, ref) => /* @__PURE__ */ jsxs8(
|
|
688
|
+
DropdownMenuPrimitive.Item,
|
|
689
|
+
{
|
|
690
|
+
ref,
|
|
691
|
+
className: cn(
|
|
692
|
+
itemBase,
|
|
693
|
+
variant === "destructive" ? "text-ui-label-large text-destructive data-[highlighted]:bg-destructive-soft-hover group-data-[keyboard]/menu:data-[highlighted]:outline-solid group-data-[keyboard]/menu:data-[highlighted]:outline-2 group-data-[keyboard]/menu:data-[highlighted]:-outline-offset-2 group-data-[keyboard]/menu:data-[highlighted]:outline-ring" : itemHover,
|
|
694
|
+
className
|
|
695
|
+
),
|
|
696
|
+
...props,
|
|
697
|
+
children: [
|
|
698
|
+
variant === "destructive" && !icon ? /* @__PURE__ */ jsx13(Trash, { size: 16, "aria-hidden": true, className: "shrink-0" }) : icon,
|
|
699
|
+
/* @__PURE__ */ jsx13(ItemBody, { description, children })
|
|
700
|
+
]
|
|
701
|
+
}
|
|
702
|
+
));
|
|
703
|
+
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
704
|
+
var DropdownMenuCheckboxItem = React13.forwardRef(({ className, children, description, ...props }, ref) => /* @__PURE__ */ jsxs8(DropdownMenuPrimitive.CheckboxItem, { ref, className: cn(itemBase, itemHover, selectedItem, className), ...props, children: [
|
|
705
|
+
/* @__PURE__ */ jsx13(ItemBody, { description, children }),
|
|
706
|
+
/* @__PURE__ */ jsx13(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx13(Check2, { size: 16, "aria-hidden": true }) })
|
|
707
|
+
] }));
|
|
708
|
+
DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
|
|
709
|
+
var DropdownMenuRadioItem = React13.forwardRef(({ className, children, description, ...props }, ref) => /* @__PURE__ */ jsxs8(DropdownMenuPrimitive.RadioItem, { ref, className: cn(itemBase, itemHover, selectedItem, className), ...props, children: [
|
|
710
|
+
/* @__PURE__ */ jsx13(ItemBody, { description, children }),
|
|
711
|
+
/* @__PURE__ */ jsx13(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx13(Check2, { size: 16, "aria-hidden": true }) })
|
|
712
|
+
] }));
|
|
713
|
+
DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
|
|
714
|
+
var DropdownMenuSubTrigger = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs8(
|
|
715
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
716
|
+
{
|
|
717
|
+
ref,
|
|
718
|
+
className: cn(itemBase, itemHover, "data-[state=open]:bg-accent-soft", className),
|
|
719
|
+
...props,
|
|
720
|
+
children: [
|
|
721
|
+
/* @__PURE__ */ jsx13("span", { className: "flex-1", children }),
|
|
722
|
+
/* @__PURE__ */ jsx13(CaretRight, { size: 16, "aria-hidden": true })
|
|
723
|
+
]
|
|
724
|
+
}
|
|
725
|
+
));
|
|
726
|
+
DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
|
|
727
|
+
var DropdownMenuSubContent = React13.forwardRef(({ className, onKeyDown, onPointerMove, ...props }, ref) => /* @__PURE__ */ jsx13(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx13(
|
|
728
|
+
DropdownMenuPrimitive.SubContent,
|
|
729
|
+
{
|
|
730
|
+
ref,
|
|
731
|
+
style: { zIndex: "var(--sys-z-30)" },
|
|
732
|
+
className: cn(contentClasses, "group/menu flex flex-col gap-0.5", className),
|
|
733
|
+
...useKeyboardModality(onKeyDown, onPointerMove),
|
|
734
|
+
...props
|
|
735
|
+
}
|
|
736
|
+
) }));
|
|
737
|
+
DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
|
|
738
|
+
var DropdownMenuLabel = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
|
|
739
|
+
DropdownMenuPrimitive.Label,
|
|
740
|
+
{
|
|
741
|
+
ref,
|
|
742
|
+
className: cn("px-2 py-1.5 text-ui-caption text-secondary-muted-foreground", className),
|
|
743
|
+
...props
|
|
744
|
+
}
|
|
745
|
+
));
|
|
746
|
+
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
|
747
|
+
var DropdownMenuSeparator = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(DropdownMenuPrimitive.Separator, { ref, className: cn("-mx-1 my-1 h-px bg-border", className), ...props }));
|
|
748
|
+
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
749
|
+
|
|
750
|
+
// src/components/Conversation & AI Chat/ProjectSelector.tsx
|
|
751
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
752
|
+
var NEW_PROJECT = "__new__";
|
|
753
|
+
var ProjectSelector = React14.forwardRef(
|
|
754
|
+
({ className, project, projects, onProjectChange, newProjectLabel = "New Project", selected = false, children, ...props }, ref) => {
|
|
755
|
+
const label = children ?? project ?? newProjectLabel;
|
|
756
|
+
const classes = cn(
|
|
757
|
+
"inline-flex h-10 items-center gap-2 rounded-full border bg-surface px-3 py-2 text-ui-label whitespace-nowrap text-surface-foreground transition-colors",
|
|
758
|
+
selected ? "border-border" : "border-input hover:border-input hover:bg-accent-soft hover:text-accent-soft-foreground data-[state=open]:bg-accent-soft data-[state=open]:text-accent-soft-foreground",
|
|
759
|
+
className
|
|
760
|
+
);
|
|
761
|
+
const content = /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
762
|
+
project ? /* @__PURE__ */ jsx14(FolderOpen, { size: 16, weight: "fill", "aria-hidden": true, className: "shrink-0" }) : /* @__PURE__ */ jsx14(FolderSimple, { size: 16, "aria-hidden": true, className: "shrink-0" }),
|
|
763
|
+
/* @__PURE__ */ jsx14("span", { children: label }),
|
|
764
|
+
!selected && /* @__PURE__ */ jsx14(CaretDown, { size: 16, "aria-hidden": true, className: "shrink-0" })
|
|
765
|
+
] });
|
|
766
|
+
if (selected) {
|
|
767
|
+
return /* @__PURE__ */ jsx14("span", { className: classes, title: typeof label === "string" ? label : void 0, children: content });
|
|
768
|
+
}
|
|
769
|
+
const trigger = /* @__PURE__ */ jsx14("button", { ref, type: "button", "aria-haspopup": "menu", className: classes, ...props, children: content });
|
|
770
|
+
if (!projects) return trigger;
|
|
771
|
+
return /* @__PURE__ */ jsxs9(DropdownMenu, { children: [
|
|
772
|
+
/* @__PURE__ */ jsx14(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
773
|
+
/* @__PURE__ */ jsx14(DropdownMenuContent, { side: "top", align: "end", className: "min-w-60", children: /* @__PURE__ */ jsxs9(
|
|
774
|
+
DropdownMenuRadioGroup,
|
|
775
|
+
{
|
|
776
|
+
value: project ?? NEW_PROJECT,
|
|
777
|
+
onValueChange: (next) => onProjectChange?.(next === NEW_PROJECT ? void 0 : next),
|
|
778
|
+
children: [
|
|
779
|
+
/* @__PURE__ */ jsx14(DropdownMenuRadioItem, { value: NEW_PROJECT, children: newProjectLabel }),
|
|
780
|
+
projects.map((name) => /* @__PURE__ */ jsx14(DropdownMenuRadioItem, { value: name, children: name }, name))
|
|
781
|
+
]
|
|
782
|
+
}
|
|
783
|
+
) })
|
|
784
|
+
] });
|
|
785
|
+
}
|
|
786
|
+
);
|
|
787
|
+
ProjectSelector.displayName = "ProjectSelector";
|
|
788
|
+
|
|
789
|
+
// src/components/Conversation & AI Chat/Timestamp.tsx
|
|
790
|
+
import * as React15 from "react";
|
|
791
|
+
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
792
|
+
var Timestamp = React15.forwardRef(
|
|
793
|
+
({ className, time, children, timePosition = "before", ...props }, ref) => {
|
|
794
|
+
const timeNode = /* @__PURE__ */ jsx15("time", { className: "text-ui-caption whitespace-nowrap text-secondary-muted-foreground", children: time });
|
|
795
|
+
return /* @__PURE__ */ jsxs10(
|
|
796
|
+
"div",
|
|
797
|
+
{
|
|
798
|
+
ref,
|
|
799
|
+
className: cn("flex items-center gap-2", timePosition === "before" && "justify-end", className),
|
|
800
|
+
...props,
|
|
801
|
+
children: [
|
|
802
|
+
timePosition === "before" && timeNode,
|
|
803
|
+
children && /* @__PURE__ */ jsx15("div", { role: "toolbar", "aria-label": "Message actions", className: "flex items-center", children }),
|
|
804
|
+
timePosition === "after" && timeNode
|
|
805
|
+
]
|
|
806
|
+
}
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
);
|
|
810
|
+
Timestamp.displayName = "Timestamp";
|
|
811
|
+
|
|
812
|
+
// src/components/Conversation & AI Chat/TopicCard.tsx
|
|
813
|
+
import * as React16 from "react";
|
|
814
|
+
import { CaretRight as CaretRight2, Check as Check3 } from "@phosphor-icons/react";
|
|
815
|
+
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
816
|
+
var TopicCard = React16.forwardRef(
|
|
817
|
+
({ className, icon, title, badge, description, tags, meta, ...props }, ref) => /* @__PURE__ */ jsxs11(
|
|
818
|
+
"div",
|
|
819
|
+
{
|
|
820
|
+
ref,
|
|
821
|
+
className: cn("flex w-full flex-col gap-4 overflow-hidden rounded-xl border border-border bg-surface p-4", className),
|
|
822
|
+
...props,
|
|
823
|
+
children: [
|
|
824
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4", children: [
|
|
825
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4 text-primary", children: [
|
|
826
|
+
icon && /* @__PURE__ */ jsx16("span", { className: "flex size-6 shrink-0 items-center justify-center [&>svg]:size-6", children: icon }),
|
|
827
|
+
/* @__PURE__ */ jsx16("h3", { className: "text-heading-h3 whitespace-nowrap", children: title })
|
|
828
|
+
] }),
|
|
829
|
+
badge
|
|
830
|
+
] }),
|
|
831
|
+
/* @__PURE__ */ jsx16("p", { className: "text-body-base text-surface-foreground", children: description }),
|
|
832
|
+
tags && /* @__PURE__ */ jsx16("div", { className: "flex flex-wrap items-center gap-2", children: tags }),
|
|
833
|
+
meta && /* @__PURE__ */ jsx16("div", { className: "flex items-center gap-2 text-ui-caption text-secondary-muted-foreground", children: meta })
|
|
834
|
+
]
|
|
835
|
+
}
|
|
836
|
+
)
|
|
837
|
+
);
|
|
838
|
+
TopicCard.displayName = "TopicCard";
|
|
839
|
+
function TopicCardMetaItem({ icon, children, className, ...props }) {
|
|
840
|
+
return /* @__PURE__ */ jsxs11("span", { className: cn("flex items-center gap-1", className), ...props, children: [
|
|
841
|
+
/* @__PURE__ */ jsx16("span", { "aria-hidden": "true", className: "flex size-4 items-center justify-center [&>svg]:size-4", children: icon }),
|
|
842
|
+
children
|
|
843
|
+
] });
|
|
844
|
+
}
|
|
845
|
+
function TopicCardTag({ className, ...props }) {
|
|
846
|
+
return /* @__PURE__ */ jsx16(
|
|
847
|
+
"span",
|
|
848
|
+
{
|
|
849
|
+
className: cn(
|
|
850
|
+
"rounded-sm bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 px-2 py-1 text-ui-caption text-surface-foreground",
|
|
851
|
+
className
|
|
852
|
+
),
|
|
853
|
+
...props
|
|
854
|
+
}
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
var TopicActivityRow = React16.forwardRef(
|
|
858
|
+
({ className, status, children, ...props }, ref) => /* @__PURE__ */ jsxs11(
|
|
859
|
+
"button",
|
|
860
|
+
{
|
|
861
|
+
ref,
|
|
862
|
+
type: "button",
|
|
863
|
+
className: cn(
|
|
864
|
+
"flex w-full items-center gap-4 border-b border-border bg-surface p-4 text-left text-body-small text-surface-foreground",
|
|
865
|
+
className
|
|
866
|
+
),
|
|
867
|
+
...props,
|
|
868
|
+
children: [
|
|
869
|
+
/* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 whitespace-nowrap", children: [
|
|
870
|
+
/* @__PURE__ */ jsx16(Check3, { size: 16, "aria-hidden": true, className: "text-accent" }),
|
|
871
|
+
status
|
|
872
|
+
] }),
|
|
873
|
+
/* @__PURE__ */ jsx16("span", { className: "min-w-0 flex-1 truncate", children }),
|
|
874
|
+
/* @__PURE__ */ jsx16(CaretRight2, { size: 16, "aria-hidden": true })
|
|
875
|
+
]
|
|
876
|
+
}
|
|
877
|
+
)
|
|
878
|
+
);
|
|
879
|
+
TopicActivityRow.displayName = "TopicActivityRow";
|
|
880
|
+
|
|
881
|
+
// src/components/Conversation & AI Chat/UserMessageBubble.tsx
|
|
882
|
+
import * as React17 from "react";
|
|
883
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
884
|
+
var UserMessageBubble = React17.forwardRef(
|
|
885
|
+
({ className, children, attachments, footer, ...props }, ref) => /* @__PURE__ */ jsxs12("div", { ref, className: cn("flex w-full max-w-125 flex-col items-end gap-2.5", className), ...props, children: [
|
|
886
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex w-full flex-col gap-4 rounded-tl-xl rounded-tr-xl rounded-br-xs rounded-bl-xl bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 p-4 text-body-base text-surface-foreground", children: [
|
|
887
|
+
attachments && /* @__PURE__ */ jsx17("div", { className: "flex flex-wrap gap-4", children: attachments }),
|
|
888
|
+
/* @__PURE__ */ jsx17("p", { className: "break-words", children })
|
|
889
|
+
] }),
|
|
890
|
+
footer && /* @__PURE__ */ jsx17("div", { className: "w-full", children: footer })
|
|
891
|
+
] })
|
|
892
|
+
);
|
|
893
|
+
UserMessageBubble.displayName = "UserMessageBubble";
|
|
894
|
+
|
|
895
|
+
// src/components/Forms & Data Entry/Calendar.tsx
|
|
896
|
+
import { CaretDown as CaretDown2, CaretLeft, CaretRight as CaretRight3 } from "@phosphor-icons/react";
|
|
897
|
+
import { DayPicker } from "react-day-picker";
|
|
898
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
899
|
+
var subtleFill = "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5";
|
|
900
|
+
function Calendar({
|
|
901
|
+
className,
|
|
902
|
+
classNames,
|
|
903
|
+
showOutsideDays = true,
|
|
904
|
+
captionLayout = "dropdown",
|
|
905
|
+
recommendedDates,
|
|
906
|
+
modifiers,
|
|
907
|
+
modifiersClassNames,
|
|
908
|
+
startMonth,
|
|
909
|
+
endMonth,
|
|
910
|
+
...props
|
|
911
|
+
}) {
|
|
912
|
+
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
913
|
+
return /* @__PURE__ */ jsx18(
|
|
914
|
+
DayPicker,
|
|
915
|
+
{
|
|
916
|
+
showOutsideDays,
|
|
917
|
+
captionLayout,
|
|
918
|
+
startMonth: startMonth ?? new Date(year - 10, 0),
|
|
919
|
+
endMonth: endMonth ?? new Date(year + 10, 11),
|
|
920
|
+
className: cn("w-71 text-surface-foreground", className),
|
|
921
|
+
modifiers: { ...recommendedDates ? { recommended: recommendedDates } : {}, ...modifiers },
|
|
922
|
+
modifiersClassNames: {
|
|
923
|
+
recommended: "border border-dashed border-border *:text-surface-foreground",
|
|
924
|
+
...modifiersClassNames
|
|
925
|
+
},
|
|
926
|
+
classNames: {
|
|
927
|
+
root: "relative",
|
|
928
|
+
months: "flex flex-col",
|
|
929
|
+
month: "flex flex-col items-center gap-4",
|
|
930
|
+
nav: "absolute inset-x-0 top-0 flex h-8 items-center justify-between",
|
|
931
|
+
button_previous: "inline-flex size-8 items-center justify-center rounded-sm text-surface-foreground hover:bg-accent-soft hover:text-accent-soft-foreground disabled:opacity-50",
|
|
932
|
+
button_next: "inline-flex size-8 items-center justify-center rounded-sm text-surface-foreground hover:bg-accent-soft hover:text-accent-soft-foreground disabled:opacity-50",
|
|
933
|
+
month_caption: "flex h-8 items-center justify-center",
|
|
934
|
+
dropdowns: "flex items-center gap-1",
|
|
935
|
+
dropdown_root: "relative inline-flex items-center rounded-md border border-input bg-surface px-3 py-1.5 text-body-small shadow-xs hover:border-input-accent",
|
|
936
|
+
dropdown: "absolute inset-0 cursor-pointer opacity-0",
|
|
937
|
+
caption_label: "flex items-center gap-2 text-body-small text-surface-foreground",
|
|
938
|
+
month_grid: "w-full border-collapse",
|
|
939
|
+
weekdays: "flex gap-1",
|
|
940
|
+
weekday: "flex h-8 w-9 items-center justify-center text-ui-caption text-muted-foreground",
|
|
941
|
+
weeks: "flex flex-col gap-1",
|
|
942
|
+
week: "flex gap-1",
|
|
943
|
+
day: "size-9 rounded-full p-0 text-center",
|
|
944
|
+
day_button: "flex size-full items-center justify-center rounded-full text-ui-caption text-secondary-muted-foreground transition-colors hover:bg-accent-soft hover:text-accent-soft-foreground",
|
|
945
|
+
selected: cn(subtleFill, "*:text-surface-foreground"),
|
|
946
|
+
today: "font-semibold",
|
|
947
|
+
outside: "opacity-60 *:text-muted-foreground",
|
|
948
|
+
disabled: "opacity-60 *:pointer-events-none *:text-muted-foreground",
|
|
949
|
+
hidden: "invisible",
|
|
950
|
+
...classNames
|
|
951
|
+
},
|
|
952
|
+
components: {
|
|
953
|
+
Chevron: ({ orientation }) => orientation === "left" ? /* @__PURE__ */ jsx18(CaretLeft, { size: 16, "aria-hidden": true }) : orientation === "right" ? /* @__PURE__ */ jsx18(CaretRight3, { size: 16, "aria-hidden": true }) : /* @__PURE__ */ jsx18(CaretDown2, { size: 16, "aria-hidden": true })
|
|
954
|
+
},
|
|
955
|
+
...props
|
|
956
|
+
}
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
Calendar.displayName = "Calendar";
|
|
960
|
+
|
|
961
|
+
// src/components/Forms & Data Entry/DateTimePicker.tsx
|
|
962
|
+
import * as React22 from "react";
|
|
963
|
+
import { CalendarBlank } from "@phosphor-icons/react";
|
|
964
|
+
import { Popover as PopoverPrimitive } from "radix-ui";
|
|
965
|
+
|
|
966
|
+
// src/components/Forms & Data Entry/Field.tsx
|
|
967
|
+
import * as React18 from "react";
|
|
968
|
+
import { CheckCircle, WarningCircle } from "@phosphor-icons/react";
|
|
969
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
970
|
+
function fieldSurfaceClasses(status = "default") {
|
|
971
|
+
return cn(
|
|
972
|
+
"border bg-surface text-surface-foreground transition-colors",
|
|
973
|
+
status === "success" && "border-success-foreground",
|
|
974
|
+
status === "error" && "border-destructive",
|
|
975
|
+
status === "default" && "border-input hover:border-input-accent"
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
function Field({ label, description, message, status = "default", id, className, children }) {
|
|
979
|
+
const generatedId = React18.useId();
|
|
980
|
+
const controlId = id ?? generatedId;
|
|
981
|
+
const messageId = `${controlId}-message`;
|
|
982
|
+
const showStatus = status !== "default" && message != null;
|
|
983
|
+
const text = showStatus ? message : description;
|
|
984
|
+
return /* @__PURE__ */ jsxs13("div", { className: cn("flex w-full flex-col gap-1.5", className), children: [
|
|
985
|
+
label != null && /* @__PURE__ */ jsx19(Label, { htmlFor: controlId, children: label }),
|
|
986
|
+
children({
|
|
987
|
+
id: controlId,
|
|
988
|
+
"aria-describedby": text != null ? messageId : void 0,
|
|
989
|
+
"aria-invalid": status === "error" ? true : void 0
|
|
990
|
+
}),
|
|
991
|
+
text != null && /* @__PURE__ */ jsxs13(
|
|
992
|
+
"p",
|
|
993
|
+
{
|
|
994
|
+
id: messageId,
|
|
995
|
+
className: cn(
|
|
996
|
+
"flex gap-2 text-ui-caption",
|
|
997
|
+
status === "default" && "text-secondary-muted-foreground",
|
|
998
|
+
status === "success" && "items-center text-success-foreground",
|
|
999
|
+
status === "error" && "items-start text-destructive"
|
|
1000
|
+
),
|
|
1001
|
+
children: [
|
|
1002
|
+
showStatus && (status === "error" ? /* @__PURE__ */ jsx19(WarningCircle, { size: 16, "aria-hidden": true, className: "shrink-0" }) : /* @__PURE__ */ jsx19(CheckCircle, { size: 16, "aria-hidden": true, className: "shrink-0" })),
|
|
1003
|
+
text
|
|
1004
|
+
]
|
|
1005
|
+
}
|
|
1006
|
+
)
|
|
1007
|
+
] });
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// src/components/Forms & Data Entry/formatDateTime.ts
|
|
1011
|
+
function formatDateTime(date, showTime = true) {
|
|
1012
|
+
const day = date.toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
|
|
1013
|
+
if (!showTime) return day;
|
|
1014
|
+
return `${day} - ${date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" })}`;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/components/Forms & Data Entry/TimePicker.tsx
|
|
1018
|
+
import * as React21 from "react";
|
|
1019
|
+
import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
|
|
1020
|
+
|
|
1021
|
+
// src/components/Navigation/TabItem.tsx
|
|
1022
|
+
import * as React20 from "react";
|
|
1023
|
+
import { Tabs as TabsPrimitive2 } from "radix-ui";
|
|
1024
|
+
|
|
1025
|
+
// src/components/Navigation/TabNavigation.tsx
|
|
1026
|
+
import * as React19 from "react";
|
|
1027
|
+
import { Tabs as TabsPrimitive } from "radix-ui";
|
|
1028
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
1029
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1030
|
+
var TabNavigationContext = React19.createContext("filter");
|
|
1031
|
+
var tabNavigationVariants = cva3("inline-flex items-start gap-1 p-0.5", {
|
|
1032
|
+
variants: {
|
|
1033
|
+
variant: {
|
|
1034
|
+
filter: "rounded-full border border-border bg-surface",
|
|
1035
|
+
toggle: "rounded-md bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5"
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
defaultVariants: { variant: "filter" }
|
|
1039
|
+
});
|
|
1040
|
+
var Tabs = TabsPrimitive.Root;
|
|
1041
|
+
var TabsContent = TabsPrimitive.Content;
|
|
1042
|
+
var TabNavigation = React19.forwardRef(
|
|
1043
|
+
({ className, variant = "filter", ...props }, ref) => /* @__PURE__ */ jsx20(TabNavigationContext.Provider, { value: variant ?? "filter", children: /* @__PURE__ */ jsx20(TabsPrimitive.List, { ref, className: cn(tabNavigationVariants({ variant }), className), ...props }) })
|
|
1044
|
+
);
|
|
1045
|
+
TabNavigation.displayName = "TabNavigation";
|
|
1046
|
+
|
|
1047
|
+
// src/components/Navigation/TabItem.tsx
|
|
1048
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
1049
|
+
var base = "inline-flex h-7 items-center justify-center gap-1 whitespace-nowrap px-2.5 py-1 text-ui-label transition-colors disabled:pointer-events-none disabled:opacity-50";
|
|
1050
|
+
var filter = "rounded-full text-surface-foreground hover:text-accent data-[state=active]:bg-secondary data-[state=active]:bg-linear-to-r data-[state=active]:from-overlay-dark-5 data-[state=active]:to-overlay-dark-5 data-[state=active]:hover:bg-accent-soft data-[state=active]:hover:bg-none data-[state=active]:hover:text-accent-soft-foreground disabled:text-muted-foreground";
|
|
1051
|
+
var toggle = "rounded-sm text-secondary-muted-foreground hover:text-surface-foreground data-[state=active]:bg-surface data-[state=active]:text-surface-foreground";
|
|
1052
|
+
var TabItem = React20.forwardRef(
|
|
1053
|
+
({ className, ...props }, ref) => {
|
|
1054
|
+
const variant = React20.useContext(TabNavigationContext);
|
|
1055
|
+
return /* @__PURE__ */ jsx21(
|
|
1056
|
+
TabsPrimitive2.Trigger,
|
|
1057
|
+
{
|
|
1058
|
+
ref,
|
|
1059
|
+
className: cn(base, variant === "toggle" ? toggle : filter, className),
|
|
1060
|
+
...props
|
|
1061
|
+
}
|
|
1062
|
+
);
|
|
1063
|
+
}
|
|
1064
|
+
);
|
|
1065
|
+
TabItem.displayName = "TabItem";
|
|
1066
|
+
|
|
1067
|
+
// src/components/Forms & Data Entry/TimePicker.tsx
|
|
1068
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1069
|
+
var TimeItem = React21.forwardRef(
|
|
1070
|
+
({ className, recommended, ...props }, ref) => /* @__PURE__ */ jsx22(
|
|
1071
|
+
ToggleGroupPrimitive.Item,
|
|
1072
|
+
{
|
|
1073
|
+
ref,
|
|
1074
|
+
className: cn(
|
|
1075
|
+
"flex w-full justify-center rounded-sm px-2.5 py-1.5 text-ui-caption text-secondary-muted-foreground transition-colors",
|
|
1076
|
+
"hover:bg-accent-soft hover:text-accent-soft-foreground",
|
|
1077
|
+
"data-[state=on]:bg-secondary data-[state=on]:bg-linear-to-r data-[state=on]:from-overlay-dark-5 data-[state=on]:to-overlay-dark-5 data-[state=on]:text-surface-foreground",
|
|
1078
|
+
"data-[state=on]:hover:bg-accent-soft data-[state=on]:hover:bg-none data-[state=on]:hover:text-accent-soft-foreground",
|
|
1079
|
+
"disabled:pointer-events-none disabled:opacity-60 disabled:text-muted-foreground",
|
|
1080
|
+
recommended && "border border-dashed border-border text-surface-foreground",
|
|
1081
|
+
className
|
|
1082
|
+
),
|
|
1083
|
+
...props
|
|
1084
|
+
}
|
|
1085
|
+
)
|
|
1086
|
+
);
|
|
1087
|
+
TimeItem.displayName = "TimeItem";
|
|
1088
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
1089
|
+
function TimePicker({
|
|
1090
|
+
value,
|
|
1091
|
+
onValueChange,
|
|
1092
|
+
minuteStep = 5,
|
|
1093
|
+
isHourDisabled,
|
|
1094
|
+
isMinuteDisabled,
|
|
1095
|
+
isHourRecommended,
|
|
1096
|
+
isMinuteRecommended,
|
|
1097
|
+
className
|
|
1098
|
+
}) {
|
|
1099
|
+
const current = value ?? { hour: 12, minute: 0, period: "AM" };
|
|
1100
|
+
const root = React21.useRef(null);
|
|
1101
|
+
React21.useEffect(() => {
|
|
1102
|
+
root.current?.querySelectorAll('[data-state="on"]').forEach((item) => {
|
|
1103
|
+
const column = item.parentElement;
|
|
1104
|
+
if (column) column.scrollTop = Math.max(0, item.offsetTop - column.offsetTop - column.clientHeight / 2 + item.clientHeight / 2);
|
|
1105
|
+
});
|
|
1106
|
+
}, []);
|
|
1107
|
+
const hours = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
1108
|
+
const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => i * minuteStep);
|
|
1109
|
+
return /* @__PURE__ */ jsxs14("div", { ref: root, className: cn("flex w-45 flex-col gap-4 pt-2", className), children: [
|
|
1110
|
+
/* @__PURE__ */ jsx22("p", { className: "text-ui-label text-surface-foreground", children: "Select Time" }),
|
|
1111
|
+
/* @__PURE__ */ jsx22(
|
|
1112
|
+
Tabs,
|
|
1113
|
+
{
|
|
1114
|
+
value: current.period,
|
|
1115
|
+
onValueChange: (period) => onValueChange?.({ ...current, period }),
|
|
1116
|
+
children: /* @__PURE__ */ jsx22(TabNavigation, { variant: "toggle", "aria-label": "AM or PM", className: "self-start", children: ["AM", "PM"].map((period) => /* @__PURE__ */ jsx22(TabItem, { value: period, children: period }, period)) })
|
|
1117
|
+
}
|
|
1118
|
+
),
|
|
1119
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex h-47.5 w-full items-start gap-3", children: [
|
|
1120
|
+
/* @__PURE__ */ jsx22(
|
|
1121
|
+
ToggleGroupPrimitive.Root,
|
|
1122
|
+
{
|
|
1123
|
+
type: "single",
|
|
1124
|
+
"aria-label": "Hour",
|
|
1125
|
+
value: String(current.hour),
|
|
1126
|
+
onValueChange: (next) => next && onValueChange?.({ ...current, hour: Number(next) }),
|
|
1127
|
+
className: "flex h-full min-w-0 flex-1 flex-col gap-1 overflow-y-auto",
|
|
1128
|
+
children: hours.map((hour) => /* @__PURE__ */ jsx22(
|
|
1129
|
+
TimeItem,
|
|
1130
|
+
{
|
|
1131
|
+
value: String(hour),
|
|
1132
|
+
disabled: isHourDisabled?.(hour, current.period),
|
|
1133
|
+
recommended: isHourRecommended?.(hour, current.period),
|
|
1134
|
+
children: pad(hour)
|
|
1135
|
+
},
|
|
1136
|
+
hour
|
|
1137
|
+
))
|
|
1138
|
+
}
|
|
1139
|
+
),
|
|
1140
|
+
/* @__PURE__ */ jsx22("div", { className: "flex h-full items-center text-ui-label-large text-surface-foreground", "aria-hidden": "true", children: ":" }),
|
|
1141
|
+
/* @__PURE__ */ jsx22(
|
|
1142
|
+
ToggleGroupPrimitive.Root,
|
|
1143
|
+
{
|
|
1144
|
+
type: "single",
|
|
1145
|
+
"aria-label": "Minute",
|
|
1146
|
+
value: String(current.minute),
|
|
1147
|
+
onValueChange: (next) => next && onValueChange?.({ ...current, minute: Number(next) }),
|
|
1148
|
+
className: "flex h-full min-w-0 flex-1 flex-col gap-1 overflow-y-auto",
|
|
1149
|
+
children: minutes.map((minute) => /* @__PURE__ */ jsx22(
|
|
1150
|
+
TimeItem,
|
|
1151
|
+
{
|
|
1152
|
+
value: String(minute),
|
|
1153
|
+
disabled: isMinuteDisabled?.(minute, current.hour, current.period),
|
|
1154
|
+
recommended: isMinuteRecommended?.(minute, current.hour, current.period),
|
|
1155
|
+
children: pad(minute)
|
|
1156
|
+
},
|
|
1157
|
+
minute
|
|
1158
|
+
))
|
|
1159
|
+
}
|
|
1160
|
+
)
|
|
1161
|
+
] })
|
|
1162
|
+
] });
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// src/components/Forms & Data Entry/DateTimePicker.tsx
|
|
1166
|
+
import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1167
|
+
function toTimeValue(date) {
|
|
1168
|
+
if (!date) return void 0;
|
|
1169
|
+
const hours = date.getHours();
|
|
1170
|
+
return { hour: hours % 12 === 0 ? 12 : hours % 12, minute: date.getMinutes(), period: hours >= 12 ? "PM" : "AM" };
|
|
1171
|
+
}
|
|
1172
|
+
function combine(date, time) {
|
|
1173
|
+
const next = new Date(date);
|
|
1174
|
+
next.setHours(time.hour % 12 + (time.period === "PM" ? 12 : 0), time.minute, 0, 0);
|
|
1175
|
+
return next;
|
|
1176
|
+
}
|
|
1177
|
+
function DateTimePicker({
|
|
1178
|
+
value,
|
|
1179
|
+
defaultValue,
|
|
1180
|
+
onApply,
|
|
1181
|
+
onReset,
|
|
1182
|
+
showTime = true,
|
|
1183
|
+
calendarProps,
|
|
1184
|
+
timePickerProps,
|
|
1185
|
+
className
|
|
1186
|
+
}) {
|
|
1187
|
+
const [date, setDate] = React22.useState(value ?? defaultValue);
|
|
1188
|
+
const [time, setTime] = React22.useState(toTimeValue(value ?? defaultValue));
|
|
1189
|
+
const apply = () => {
|
|
1190
|
+
if (!date) return onApply?.(void 0);
|
|
1191
|
+
onApply?.(showTime ? combine(date, time ?? { hour: 12, minute: 0, period: "AM" }) : date);
|
|
1192
|
+
};
|
|
1193
|
+
return /* @__PURE__ */ jsxs15(
|
|
1194
|
+
"div",
|
|
1195
|
+
{
|
|
1196
|
+
className: cn(
|
|
1197
|
+
"inline-flex flex-col gap-4 rounded-lg border border-border bg-surface p-4 shadow-md",
|
|
1198
|
+
className
|
|
1199
|
+
),
|
|
1200
|
+
children: [
|
|
1201
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-6", children: [
|
|
1202
|
+
/* @__PURE__ */ jsx23(Calendar, { mode: "single", selected: date, onSelect: setDate, defaultMonth: date, ...calendarProps }),
|
|
1203
|
+
showTime && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
1204
|
+
/* @__PURE__ */ jsx23("div", { className: "h-70 w-px self-center bg-border", "aria-hidden": "true" }),
|
|
1205
|
+
/* @__PURE__ */ jsx23(TimePicker, { value: time, onValueChange: setTime, ...timePickerProps })
|
|
1206
|
+
] })
|
|
1207
|
+
] }),
|
|
1208
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-end gap-2", children: [
|
|
1209
|
+
/* @__PURE__ */ jsx23(
|
|
1210
|
+
Button,
|
|
1211
|
+
{
|
|
1212
|
+
type: "button",
|
|
1213
|
+
variant: "ghost",
|
|
1214
|
+
size: "sm",
|
|
1215
|
+
onClick: () => {
|
|
1216
|
+
setDate(void 0);
|
|
1217
|
+
setTime(void 0);
|
|
1218
|
+
onReset?.();
|
|
1219
|
+
},
|
|
1220
|
+
children: "Reset"
|
|
1221
|
+
}
|
|
1222
|
+
),
|
|
1223
|
+
/* @__PURE__ */ jsx23(Button, { type: "button", variant: "outline", size: "sm", onClick: apply, children: "Apply" })
|
|
1224
|
+
] })
|
|
1225
|
+
]
|
|
1226
|
+
}
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
var DatePicker = React22.forwardRef(
|
|
1230
|
+
({ label, placeholder = "Select date and time", value, defaultValue, onValueChange, showTime = true, className, ...pickerProps }, ref) => {
|
|
1231
|
+
const [open, setOpen] = React22.useState(false);
|
|
1232
|
+
const [internal, setInternal] = React22.useState(defaultValue);
|
|
1233
|
+
const current = value ?? internal;
|
|
1234
|
+
return /* @__PURE__ */ jsx23(Field, { label, className: cn("w-75", className), children: (control) => /* @__PURE__ */ jsxs15(PopoverPrimitive.Root, { open, onOpenChange: setOpen, children: [
|
|
1235
|
+
/* @__PURE__ */ jsx23(PopoverPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs15(
|
|
1236
|
+
"button",
|
|
1237
|
+
{
|
|
1238
|
+
ref,
|
|
1239
|
+
type: "button",
|
|
1240
|
+
...control,
|
|
1241
|
+
className: "flex h-10 w-full items-center gap-3 rounded-md border border-input bg-surface px-3 py-2.5 text-left shadow-xs transition-colors hover:border-input-accent data-[state=open]:border-input-accent",
|
|
1242
|
+
children: [
|
|
1243
|
+
/* @__PURE__ */ jsx23(CalendarBlank, { size: 24, "aria-hidden": true, className: "shrink-0 text-surface-foreground" }),
|
|
1244
|
+
/* @__PURE__ */ jsx23("span", { className: cn("truncate", current ? "text-ui-label-large text-surface-foreground" : "text-body-base text-muted-foreground"), children: current ? formatDateTime(current, showTime) : placeholder })
|
|
1245
|
+
]
|
|
1246
|
+
}
|
|
1247
|
+
) }),
|
|
1248
|
+
/* @__PURE__ */ jsx23(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx23(PopoverPrimitive.Content, { align: "start", sideOffset: 8, style: { zIndex: "var(--sys-z-20)" }, children: /* @__PURE__ */ jsx23(
|
|
1249
|
+
DateTimePicker,
|
|
1250
|
+
{
|
|
1251
|
+
...pickerProps,
|
|
1252
|
+
showTime,
|
|
1253
|
+
value: current,
|
|
1254
|
+
onApply: (next) => {
|
|
1255
|
+
setInternal(next);
|
|
1256
|
+
onValueChange?.(next);
|
|
1257
|
+
setOpen(false);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
) }) })
|
|
1261
|
+
] }) });
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
DatePicker.displayName = "DatePicker";
|
|
1265
|
+
|
|
1266
|
+
// src/components/Forms & Data Entry/Form.tsx
|
|
1267
|
+
import * as React23 from "react";
|
|
1268
|
+
import { Slot as Slot2 } from "radix-ui";
|
|
1269
|
+
import {
|
|
1270
|
+
Controller,
|
|
1271
|
+
FormProvider,
|
|
1272
|
+
useFormContext,
|
|
1273
|
+
useFormState
|
|
1274
|
+
} from "react-hook-form";
|
|
1275
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1276
|
+
var Form = FormProvider;
|
|
1277
|
+
var FormFieldContext = React23.createContext(null);
|
|
1278
|
+
function FormField(props) {
|
|
1279
|
+
return /* @__PURE__ */ jsx24(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx24(Controller, { ...props }) });
|
|
1280
|
+
}
|
|
1281
|
+
var FormItemContext = React23.createContext(null);
|
|
1282
|
+
function useFormField() {
|
|
1283
|
+
const fieldContext = React23.useContext(FormFieldContext);
|
|
1284
|
+
const itemContext = React23.useContext(FormItemContext);
|
|
1285
|
+
const { getFieldState } = useFormContext();
|
|
1286
|
+
const formState = useFormState({ name: fieldContext?.name });
|
|
1287
|
+
if (!fieldContext) {
|
|
1288
|
+
throw new Error("useFormField must be used within <FormField>");
|
|
1289
|
+
}
|
|
1290
|
+
if (!itemContext) {
|
|
1291
|
+
throw new Error("useFormField must be used within <FormItem>");
|
|
1292
|
+
}
|
|
1293
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
1294
|
+
const { id } = itemContext;
|
|
1295
|
+
return {
|
|
1296
|
+
id,
|
|
1297
|
+
name: fieldContext.name,
|
|
1298
|
+
formItemId: `${id}-form-item`,
|
|
1299
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
1300
|
+
formMessageId: `${id}-form-item-message`,
|
|
1301
|
+
...fieldState
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
var FormItem = React23.forwardRef(({ className, ...props }, ref) => {
|
|
1305
|
+
const id = React23.useId();
|
|
1306
|
+
return /* @__PURE__ */ jsx24(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx24("div", { ref, className: cn("flex flex-col gap-2", className), ...props }) });
|
|
1307
|
+
});
|
|
1308
|
+
FormItem.displayName = "FormItem";
|
|
1309
|
+
var FormLabel = React23.forwardRef(
|
|
1310
|
+
({ className, ...props }, ref) => {
|
|
1311
|
+
const { error, formItemId } = useFormField();
|
|
1312
|
+
return /* @__PURE__ */ jsx24(
|
|
1313
|
+
Label,
|
|
1314
|
+
{
|
|
1315
|
+
ref,
|
|
1316
|
+
htmlFor: formItemId,
|
|
1317
|
+
className: cn(error && "text-destructive-foreground", className),
|
|
1318
|
+
...props
|
|
1319
|
+
}
|
|
1320
|
+
);
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
FormLabel.displayName = "FormLabel";
|
|
1324
|
+
var FormControl = React23.forwardRef((props, ref) => {
|
|
1325
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
1326
|
+
return /* @__PURE__ */ jsx24(
|
|
1327
|
+
Slot2.Root,
|
|
1328
|
+
{
|
|
1329
|
+
ref,
|
|
1330
|
+
id: formItemId,
|
|
1331
|
+
"aria-describedby": error ? `${formDescriptionId} ${formMessageId}` : formDescriptionId,
|
|
1332
|
+
"aria-invalid": !!error,
|
|
1333
|
+
...props
|
|
1334
|
+
}
|
|
1335
|
+
);
|
|
1336
|
+
});
|
|
1337
|
+
FormControl.displayName = "FormControl";
|
|
1338
|
+
var FormDescription = React23.forwardRef(
|
|
1339
|
+
({ className, ...props }, ref) => {
|
|
1340
|
+
const { formDescriptionId } = useFormField();
|
|
1341
|
+
return /* @__PURE__ */ jsx24(
|
|
1342
|
+
"p",
|
|
1343
|
+
{
|
|
1344
|
+
ref,
|
|
1345
|
+
id: formDescriptionId,
|
|
1346
|
+
className: cn("text-sm text-secondary-muted-foreground", className),
|
|
1347
|
+
...props
|
|
1348
|
+
}
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
FormDescription.displayName = "FormDescription";
|
|
1353
|
+
var FormMessage = React23.forwardRef(
|
|
1354
|
+
({ className, children, ...props }, ref) => {
|
|
1355
|
+
const { error, formMessageId } = useFormField();
|
|
1356
|
+
const body = error ? String(error?.message ?? "") : children;
|
|
1357
|
+
if (!body) {
|
|
1358
|
+
return null;
|
|
1359
|
+
}
|
|
1360
|
+
return /* @__PURE__ */ jsx24("p", { ref, id: formMessageId, className: cn("text-sm text-destructive-foreground", className), ...props, children: body });
|
|
1361
|
+
}
|
|
1362
|
+
);
|
|
1363
|
+
FormMessage.displayName = "FormMessage";
|
|
1364
|
+
|
|
1365
|
+
// src/components/Forms & Data Entry/Input.tsx
|
|
1366
|
+
import * as React24 from "react";
|
|
1367
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
1368
|
+
var inputClasses = (status, className) => cn(
|
|
1369
|
+
"flex h-10 w-full rounded-md px-3 py-2 text-ui-input-value placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
1370
|
+
fieldSurfaceClasses(status),
|
|
1371
|
+
className
|
|
1372
|
+
);
|
|
1373
|
+
var Input = React24.forwardRef(
|
|
1374
|
+
({ className, status = "default", label, description, message, id, ...props }, ref) => {
|
|
1375
|
+
if (label == null && description == null && message == null) {
|
|
1376
|
+
return /* @__PURE__ */ jsx25(
|
|
1377
|
+
"input",
|
|
1378
|
+
{
|
|
1379
|
+
ref,
|
|
1380
|
+
id,
|
|
1381
|
+
"aria-invalid": status === "error" ? true : void 0,
|
|
1382
|
+
className: inputClasses(status, className),
|
|
1383
|
+
...props
|
|
1384
|
+
}
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
return /* @__PURE__ */ jsx25(Field, { label, description, message, status, id, children: (control) => /* @__PURE__ */ jsx25("input", { ref, className: inputClasses(status, className), ...control, ...props }) });
|
|
1388
|
+
}
|
|
1389
|
+
);
|
|
1390
|
+
Input.displayName = "Input";
|
|
1391
|
+
|
|
1392
|
+
// src/components/Forms & Data Entry/InputWithAction.tsx
|
|
1393
|
+
import * as React25 from "react";
|
|
1394
|
+
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1395
|
+
var InputWithAction = React25.forwardRef(
|
|
1396
|
+
({ className, actionLabel, onAction, tags, status = "default", label, description, message, id, disabled, placeholder, ...props }, ref) => /* @__PURE__ */ jsx26(Field, { label, description, message, status, id, children: (control) => /* @__PURE__ */ jsxs16(
|
|
1397
|
+
"div",
|
|
1398
|
+
{
|
|
1399
|
+
className: cn(
|
|
1400
|
+
"flex min-h-10 w-full items-center gap-2 rounded-md border bg-surface py-2 pr-1 pl-3 transition-colors",
|
|
1401
|
+
"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring",
|
|
1402
|
+
status === "error" ? "border-destructive" : "border-input hover:border-input-accent focus-within:border-input",
|
|
1403
|
+
tags ? "pl-1" : null,
|
|
1404
|
+
disabled && "opacity-50",
|
|
1405
|
+
className
|
|
1406
|
+
),
|
|
1407
|
+
children: [
|
|
1408
|
+
tags && /* @__PURE__ */ jsx26("div", { className: "flex shrink-0 items-center gap-1", children: tags }),
|
|
1409
|
+
/* @__PURE__ */ jsx26(
|
|
1410
|
+
"input",
|
|
1411
|
+
{
|
|
1412
|
+
ref,
|
|
1413
|
+
disabled,
|
|
1414
|
+
placeholder: tags ? void 0 : placeholder,
|
|
1415
|
+
className: "min-w-0 flex-1 truncate bg-transparent text-body-small text-surface-foreground outline-none placeholder:text-muted-foreground",
|
|
1416
|
+
...control,
|
|
1417
|
+
...props
|
|
1418
|
+
}
|
|
1419
|
+
),
|
|
1420
|
+
/* @__PURE__ */ jsx26(Button, { type: "button", variant: "subtle", size: "sm", disabled, onClick: onAction, children: actionLabel })
|
|
1421
|
+
]
|
|
1422
|
+
}
|
|
1423
|
+
) })
|
|
1424
|
+
);
|
|
1425
|
+
InputWithAction.displayName = "InputWithAction";
|
|
1426
|
+
|
|
1427
|
+
// src/components/Forms & Data Entry/NumberInput.tsx
|
|
1428
|
+
import * as React26 from "react";
|
|
1429
|
+
import { Minus as Minus2, Plus as Plus2 } from "@phosphor-icons/react";
|
|
1430
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1431
|
+
var NumberInput = React26.forwardRef(
|
|
1432
|
+
({
|
|
1433
|
+
className,
|
|
1434
|
+
value,
|
|
1435
|
+
defaultValue = 0,
|
|
1436
|
+
onValueChange,
|
|
1437
|
+
min = Number.NEGATIVE_INFINITY,
|
|
1438
|
+
max = Number.POSITIVE_INFINITY,
|
|
1439
|
+
step = 1,
|
|
1440
|
+
unit,
|
|
1441
|
+
status = "default",
|
|
1442
|
+
label,
|
|
1443
|
+
description,
|
|
1444
|
+
message,
|
|
1445
|
+
id,
|
|
1446
|
+
disabled,
|
|
1447
|
+
...props
|
|
1448
|
+
}, ref) => {
|
|
1449
|
+
const [internal, setInternal] = React26.useState(defaultValue);
|
|
1450
|
+
const current = value ?? internal;
|
|
1451
|
+
const clamp = (next) => Math.min(max, Math.max(min, next));
|
|
1452
|
+
const commit = (next) => {
|
|
1453
|
+
const clamped = clamp(next);
|
|
1454
|
+
setInternal(clamped);
|
|
1455
|
+
onValueChange?.(clamped);
|
|
1456
|
+
};
|
|
1457
|
+
return /* @__PURE__ */ jsx27(Field, { label, description, message, status, id, className: "w-50", children: (control) => /* @__PURE__ */ jsxs17(
|
|
1458
|
+
"div",
|
|
1459
|
+
{
|
|
1460
|
+
className: cn(
|
|
1461
|
+
"flex h-10 w-full items-center justify-between rounded-md border bg-surface p-1 transition-colors",
|
|
1462
|
+
"has-[input:focus-visible]:outline-2 has-[input:focus-visible]:outline-offset-2 has-[input:focus-visible]:outline-ring",
|
|
1463
|
+
status === "error" ? "border-destructive" : status === "success" ? "border-success-foreground" : "border-border",
|
|
1464
|
+
disabled && "opacity-50",
|
|
1465
|
+
className
|
|
1466
|
+
),
|
|
1467
|
+
children: [
|
|
1468
|
+
/* @__PURE__ */ jsx27(
|
|
1469
|
+
Button,
|
|
1470
|
+
{
|
|
1471
|
+
type: "button",
|
|
1472
|
+
variant: "subtle",
|
|
1473
|
+
size: "icon-sm",
|
|
1474
|
+
"aria-label": "Decrease",
|
|
1475
|
+
disabled: disabled || current <= min,
|
|
1476
|
+
onClick: () => commit(current - step),
|
|
1477
|
+
children: /* @__PURE__ */ jsx27(Minus2, { size: 16, "aria-hidden": true })
|
|
1478
|
+
}
|
|
1479
|
+
),
|
|
1480
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-center gap-1 text-center", children: [
|
|
1481
|
+
/* @__PURE__ */ jsx27(
|
|
1482
|
+
"input",
|
|
1483
|
+
{
|
|
1484
|
+
ref,
|
|
1485
|
+
role: "spinbutton",
|
|
1486
|
+
inputMode: "numeric",
|
|
1487
|
+
"aria-valuenow": current,
|
|
1488
|
+
"aria-valuemin": Number.isFinite(min) ? min : void 0,
|
|
1489
|
+
"aria-valuemax": Number.isFinite(max) ? max : void 0,
|
|
1490
|
+
disabled,
|
|
1491
|
+
value: String(current),
|
|
1492
|
+
size: Math.max(1, String(current).length),
|
|
1493
|
+
onChange: (event) => {
|
|
1494
|
+
const parsed = Number(event.target.value.replace(/[^\d.-]/g, ""));
|
|
1495
|
+
if (!Number.isNaN(parsed)) commit(parsed);
|
|
1496
|
+
},
|
|
1497
|
+
onKeyDown: (event) => {
|
|
1498
|
+
if (event.key === "ArrowUp") {
|
|
1499
|
+
event.preventDefault();
|
|
1500
|
+
commit(current + step);
|
|
1501
|
+
} else if (event.key === "ArrowDown") {
|
|
1502
|
+
event.preventDefault();
|
|
1503
|
+
commit(current - step);
|
|
1504
|
+
}
|
|
1505
|
+
},
|
|
1506
|
+
className: "min-w-0 bg-transparent text-center text-ui-label text-surface-foreground outline-none",
|
|
1507
|
+
...control,
|
|
1508
|
+
...props
|
|
1509
|
+
}
|
|
1510
|
+
),
|
|
1511
|
+
unit && /* @__PURE__ */ jsx27("span", { className: "text-body-small text-secondary-muted-foreground", children: unit })
|
|
1512
|
+
] }),
|
|
1513
|
+
/* @__PURE__ */ jsx27(
|
|
1514
|
+
Button,
|
|
1515
|
+
{
|
|
1516
|
+
type: "button",
|
|
1517
|
+
variant: "subtle",
|
|
1518
|
+
size: "icon-sm",
|
|
1519
|
+
"aria-label": "Increase",
|
|
1520
|
+
disabled: disabled || current >= max,
|
|
1521
|
+
onClick: () => commit(current + step),
|
|
1522
|
+
children: /* @__PURE__ */ jsx27(Plus2, { size: 16, "aria-hidden": true })
|
|
1523
|
+
}
|
|
1524
|
+
)
|
|
1525
|
+
]
|
|
1526
|
+
}
|
|
1527
|
+
) });
|
|
1528
|
+
}
|
|
1529
|
+
);
|
|
1530
|
+
NumberInput.displayName = "NumberInput";
|
|
1531
|
+
|
|
1532
|
+
// src/components/Forms & Data Entry/SearchBar.tsx
|
|
1533
|
+
import * as React27 from "react";
|
|
1534
|
+
import { MagnifyingGlass, X as X2 } from "@phosphor-icons/react";
|
|
1535
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1536
|
+
var SearchBar = React27.forwardRef(
|
|
1537
|
+
({ className, value, defaultValue, onChange, onClear, clearLabel = "Clear search", disabled, ...props }, ref) => {
|
|
1538
|
+
const innerRef = React27.useRef(null);
|
|
1539
|
+
React27.useImperativeHandle(ref, () => innerRef.current);
|
|
1540
|
+
const [uncontrolled, setUncontrolled] = React27.useState(String(defaultValue ?? ""));
|
|
1541
|
+
const current = value !== void 0 ? String(value) : uncontrolled;
|
|
1542
|
+
const clear = () => {
|
|
1543
|
+
const input = innerRef.current;
|
|
1544
|
+
if (input) {
|
|
1545
|
+
const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
|
1546
|
+
setter?.call(input, "");
|
|
1547
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1548
|
+
input.focus();
|
|
1549
|
+
}
|
|
1550
|
+
onClear?.();
|
|
1551
|
+
};
|
|
1552
|
+
return /* @__PURE__ */ jsxs18(
|
|
1553
|
+
"div",
|
|
1554
|
+
{
|
|
1555
|
+
className: cn(
|
|
1556
|
+
"flex h-10 w-full items-center gap-2 rounded-md border bg-surface px-3 py-2 transition-colors",
|
|
1557
|
+
"border-input focus-within:border-input-accent focus-within:ring-1 focus-within:ring-input-accent",
|
|
1558
|
+
current !== "" && "border-input-accent ring-1 ring-input-accent",
|
|
1559
|
+
disabled && "opacity-50",
|
|
1560
|
+
className
|
|
1561
|
+
),
|
|
1562
|
+
children: [
|
|
1563
|
+
/* @__PURE__ */ jsx28(MagnifyingGlass, { size: 16, "aria-hidden": true, className: "shrink-0 text-surface-foreground" }),
|
|
1564
|
+
/* @__PURE__ */ jsx28(
|
|
1565
|
+
"input",
|
|
1566
|
+
{
|
|
1567
|
+
ref: innerRef,
|
|
1568
|
+
type: "text",
|
|
1569
|
+
role: "searchbox",
|
|
1570
|
+
value,
|
|
1571
|
+
defaultValue,
|
|
1572
|
+
disabled,
|
|
1573
|
+
onChange: (event) => {
|
|
1574
|
+
setUncontrolled(event.target.value);
|
|
1575
|
+
onChange?.(event);
|
|
1576
|
+
},
|
|
1577
|
+
className: "min-w-0 flex-1 bg-transparent text-ui-input-value text-surface-foreground outline-none placeholder:text-muted-foreground",
|
|
1578
|
+
...props
|
|
1579
|
+
}
|
|
1580
|
+
),
|
|
1581
|
+
current !== "" && !disabled && /* @__PURE__ */ jsx28(
|
|
1582
|
+
"button",
|
|
1583
|
+
{
|
|
1584
|
+
type: "button",
|
|
1585
|
+
"aria-label": clearLabel,
|
|
1586
|
+
onClick: clear,
|
|
1587
|
+
className: "inline-flex size-4 shrink-0 items-center justify-center rounded-xs text-surface-foreground",
|
|
1588
|
+
children: /* @__PURE__ */ jsx28(X2, { size: 16, "aria-hidden": true })
|
|
1589
|
+
}
|
|
1590
|
+
)
|
|
1591
|
+
]
|
|
1592
|
+
}
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
);
|
|
1596
|
+
SearchBar.displayName = "SearchBar";
|
|
1597
|
+
|
|
1598
|
+
// src/components/Forms & Data Entry/Select.tsx
|
|
1599
|
+
import * as React28 from "react";
|
|
1600
|
+
import { CaretDown as CaretDown3 } from "@phosphor-icons/react";
|
|
1601
|
+
import { Select as SelectPrimitive } from "radix-ui";
|
|
1602
|
+
import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1603
|
+
var Select = SelectPrimitive.Root;
|
|
1604
|
+
var SelectValue = SelectPrimitive.Value;
|
|
1605
|
+
var SelectGroup = SelectPrimitive.Group;
|
|
1606
|
+
var CheckIcon = () => /* @__PURE__ */ jsx29("svg", { width: "10", height: "8", viewBox: "0 0 10 8", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx29("path", { d: "M1 4L3.5 6.5L9 1", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
1607
|
+
var SelectTrigger = React28.forwardRef(
|
|
1608
|
+
({ className, children, icon, ...props }, ref) => /* @__PURE__ */ jsxs19(
|
|
1609
|
+
SelectPrimitive.Trigger,
|
|
1610
|
+
{
|
|
1611
|
+
ref,
|
|
1612
|
+
className: cn(
|
|
1613
|
+
"flex h-10 w-full items-center gap-2 rounded-md border border-input bg-surface px-3 py-2 text-left text-ui-input-value text-surface-foreground transition-colors",
|
|
1614
|
+
"hover:border-input-accent data-[state=open]:border-input-accent",
|
|
1615
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1616
|
+
"data-[placeholder]:text-muted-foreground",
|
|
1617
|
+
className
|
|
1618
|
+
),
|
|
1619
|
+
...props,
|
|
1620
|
+
children: [
|
|
1621
|
+
icon && /* @__PURE__ */ jsx29("span", { className: "flex shrink-0 text-surface-foreground", children: icon }),
|
|
1622
|
+
/* @__PURE__ */ jsx29("span", { className: "min-w-0 flex-1 truncate", children }),
|
|
1623
|
+
/* @__PURE__ */ jsx29(SelectPrimitive.Icon, { className: "shrink-0 text-surface-foreground", children: /* @__PURE__ */ jsx29(CaretDown3, { size: 16, "aria-hidden": true }) })
|
|
1624
|
+
]
|
|
1625
|
+
}
|
|
1626
|
+
)
|
|
1627
|
+
);
|
|
1628
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
1629
|
+
var SelectContent = React28.forwardRef(
|
|
1630
|
+
({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx29(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx29(
|
|
1631
|
+
SelectPrimitive.Content,
|
|
1632
|
+
{
|
|
1633
|
+
ref,
|
|
1634
|
+
position,
|
|
1635
|
+
style: {
|
|
1636
|
+
zIndex: "var(--sys-z-20)",
|
|
1637
|
+
width: position === "popper" ? "var(--radix-select-trigger-width)" : void 0
|
|
1638
|
+
},
|
|
1639
|
+
className: cn(
|
|
1640
|
+
"overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md",
|
|
1641
|
+
className
|
|
1642
|
+
),
|
|
1643
|
+
...props,
|
|
1644
|
+
children: /* @__PURE__ */ jsx29(SelectPrimitive.Viewport, { className: "p-1", children })
|
|
1645
|
+
}
|
|
1646
|
+
) })
|
|
1647
|
+
);
|
|
1648
|
+
SelectContent.displayName = "SelectContent";
|
|
1649
|
+
var SelectItem = React28.forwardRef(
|
|
1650
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs19(
|
|
1651
|
+
SelectPrimitive.Item,
|
|
1652
|
+
{
|
|
1653
|
+
ref,
|
|
1654
|
+
className: cn(
|
|
1655
|
+
"relative flex cursor-default items-center gap-2 rounded-sm py-2 pr-4 pl-8 text-sm text-popover-foreground select-none",
|
|
1656
|
+
"outline-none data-[highlighted]:bg-accent-soft data-[highlighted]:text-accent-soft-foreground",
|
|
1657
|
+
className
|
|
1658
|
+
),
|
|
1659
|
+
...props,
|
|
1660
|
+
children: [
|
|
1661
|
+
/* @__PURE__ */ jsx29("span", { className: "absolute left-2 flex h-4 w-4 items-center justify-center", children: /* @__PURE__ */ jsx29(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx29(CheckIcon, {}) }) }),
|
|
1662
|
+
/* @__PURE__ */ jsx29(SelectPrimitive.ItemText, { children })
|
|
1663
|
+
]
|
|
1664
|
+
}
|
|
1665
|
+
)
|
|
1666
|
+
);
|
|
1667
|
+
SelectItem.displayName = "SelectItem";
|
|
1668
|
+
|
|
1669
|
+
// src/components/Forms & Data Entry/Slider.tsx
|
|
1670
|
+
import * as React29 from "react";
|
|
1671
|
+
import { Slider as SliderPrimitive } from "radix-ui";
|
|
1672
|
+
import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1673
|
+
var Slider = React29.forwardRef(
|
|
1674
|
+
({
|
|
1675
|
+
className,
|
|
1676
|
+
value,
|
|
1677
|
+
defaultValue,
|
|
1678
|
+
onValueChange,
|
|
1679
|
+
min = 0,
|
|
1680
|
+
max = 100,
|
|
1681
|
+
label,
|
|
1682
|
+
showRange,
|
|
1683
|
+
showValue,
|
|
1684
|
+
"aria-label": ariaLabel,
|
|
1685
|
+
"aria-labelledby": ariaLabelledBy,
|
|
1686
|
+
...props
|
|
1687
|
+
}, ref) => {
|
|
1688
|
+
const [internal, setInternal] = React29.useState(defaultValue ?? [min]);
|
|
1689
|
+
const thumbValues = value ?? internal;
|
|
1690
|
+
const hasHeader = label != null || showRange;
|
|
1691
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("flex w-full flex-col gap-2", className), children: [
|
|
1692
|
+
hasHeader && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between text-secondary-muted-foreground", children: [
|
|
1693
|
+
label != null ? /* @__PURE__ */ jsx30("span", { className: "text-ui-label text-surface-foreground", children: label }) : /* @__PURE__ */ jsx30("span", { className: "text-ui-caption", children: min }),
|
|
1694
|
+
/* @__PURE__ */ jsx30("span", { className: "text-body-small", children: max })
|
|
1695
|
+
] }),
|
|
1696
|
+
/* @__PURE__ */ jsxs20(
|
|
1697
|
+
SliderPrimitive.Root,
|
|
1698
|
+
{
|
|
1699
|
+
ref,
|
|
1700
|
+
value,
|
|
1701
|
+
defaultValue,
|
|
1702
|
+
min,
|
|
1703
|
+
max,
|
|
1704
|
+
onValueChange: (next) => {
|
|
1705
|
+
setInternal(next);
|
|
1706
|
+
onValueChange?.(next);
|
|
1707
|
+
},
|
|
1708
|
+
className: "relative flex h-4 w-full touch-none items-center select-none",
|
|
1709
|
+
...props,
|
|
1710
|
+
children: [
|
|
1711
|
+
/* @__PURE__ */ jsx30(SliderPrimitive.Track, { className: "relative h-1 w-full grow overflow-hidden rounded-xxs bg-muted", children: /* @__PURE__ */ jsx30(SliderPrimitive.Range, { className: "absolute h-full bg-input-accent" }) }),
|
|
1712
|
+
thumbValues.map((thumbValue, index) => (
|
|
1713
|
+
// The accessible name belongs on each individual thumb (the actual
|
|
1714
|
+
// role="slider" element) — Root is just a group container. With
|
|
1715
|
+
// more than one thumb this applies the same label to each; give a
|
|
1716
|
+
// range slider distinct per-thumb labels via aria-labelledby instead.
|
|
1717
|
+
/* @__PURE__ */ jsx30(
|
|
1718
|
+
SliderPrimitive.Thumb,
|
|
1719
|
+
{
|
|
1720
|
+
"aria-label": ariaLabel,
|
|
1721
|
+
"aria-labelledby": ariaLabelledBy,
|
|
1722
|
+
className: "group relative block size-4 rounded-full border-2 border-surface bg-input-accent shadow-sm transition-colors disabled:pointer-events-none disabled:opacity-50",
|
|
1723
|
+
children: showValue && /* @__PURE__ */ jsx30(
|
|
1724
|
+
"span",
|
|
1725
|
+
{
|
|
1726
|
+
"aria-hidden": "true",
|
|
1727
|
+
className: cn(
|
|
1728
|
+
"pointer-events-none absolute bottom-full left-1/2 mb-2 flex min-w-4 -translate-x-1/2 items-center justify-center rounded-xs bg-primary p-0.5 text-ui-caption text-label",
|
|
1729
|
+
showValue !== "always" && "invisible group-hover:visible group-focus-visible:visible group-active:visible"
|
|
1730
|
+
),
|
|
1731
|
+
children: thumbValue
|
|
1732
|
+
}
|
|
1733
|
+
)
|
|
1734
|
+
},
|
|
1735
|
+
index
|
|
1736
|
+
)
|
|
1737
|
+
))
|
|
1738
|
+
]
|
|
1739
|
+
}
|
|
1740
|
+
)
|
|
1741
|
+
] });
|
|
1742
|
+
}
|
|
1743
|
+
);
|
|
1744
|
+
Slider.displayName = "Slider";
|
|
1745
|
+
|
|
1746
|
+
// src/components/Forms & Data Entry/Textarea.tsx
|
|
1747
|
+
import * as React30 from "react";
|
|
1748
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1749
|
+
var textareaClasses = (status, className) => cn(
|
|
1750
|
+
"flex field-sizing-content min-h-25 w-full rounded-md px-3 py-2.5 text-body-base placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
1751
|
+
fieldSurfaceClasses(status),
|
|
1752
|
+
className
|
|
1753
|
+
);
|
|
1754
|
+
var Textarea = React30.forwardRef(
|
|
1755
|
+
({ className, status = "default", label, description, message, id, ...props }, ref) => {
|
|
1756
|
+
if (label == null && description == null && message == null) {
|
|
1757
|
+
return /* @__PURE__ */ jsx31(
|
|
1758
|
+
"textarea",
|
|
1759
|
+
{
|
|
1760
|
+
ref,
|
|
1761
|
+
id,
|
|
1762
|
+
"aria-invalid": status === "error" ? true : void 0,
|
|
1763
|
+
className: textareaClasses(status, className),
|
|
1764
|
+
...props
|
|
1765
|
+
}
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
return /* @__PURE__ */ jsx31(Field, { label, description, message, status, id, children: (control) => /* @__PURE__ */ jsx31("textarea", { ref, className: textareaClasses(status, className), ...control, ...props }) });
|
|
1769
|
+
}
|
|
1770
|
+
);
|
|
1771
|
+
Textarea.displayName = "Textarea";
|
|
1772
|
+
|
|
1773
|
+
// src/components/Overlays & Feedback/Dialog.tsx
|
|
1774
|
+
import * as React31 from "react";
|
|
1775
|
+
import { X as X3 } from "@phosphor-icons/react";
|
|
1776
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
1777
|
+
import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1778
|
+
var Dialog = DialogPrimitive.Root;
|
|
1779
|
+
var DialogTrigger = DialogPrimitive.Trigger;
|
|
1780
|
+
var DialogClose = DialogPrimitive.Close;
|
|
1781
|
+
var DialogContent = React31.forwardRef(
|
|
1782
|
+
({ className, children, closeLabel = "Close", hideClose, ...props }, ref) => /* @__PURE__ */ jsxs21(DialogPrimitive.Portal, { children: [
|
|
1783
|
+
/* @__PURE__ */ jsx32(
|
|
1784
|
+
DialogPrimitive.Overlay,
|
|
1785
|
+
{
|
|
1786
|
+
style: { zIndex: "var(--sys-z-30)" },
|
|
1787
|
+
className: "fixed inset-0 bg-primary/30"
|
|
1788
|
+
}
|
|
1789
|
+
),
|
|
1790
|
+
/* @__PURE__ */ jsxs21(
|
|
1791
|
+
DialogPrimitive.Content,
|
|
1792
|
+
{
|
|
1793
|
+
ref,
|
|
1794
|
+
style: { zIndex: "var(--sys-z-30)" },
|
|
1795
|
+
className: cn(
|
|
1796
|
+
"fixed top-1/2 left-1/2 flex w-150 max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-lg border border-border bg-surface shadow-lg",
|
|
1797
|
+
className
|
|
1798
|
+
),
|
|
1799
|
+
...props,
|
|
1800
|
+
children: [
|
|
1801
|
+
children,
|
|
1802
|
+
!hideClose && /* @__PURE__ */ jsx32(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx32(Button, { variant: "ghost", size: "icon-sm", "aria-label": closeLabel, className: "absolute top-4 right-6", children: /* @__PURE__ */ jsx32(X3, { size: 16, "aria-hidden": true }) }) })
|
|
1803
|
+
]
|
|
1804
|
+
}
|
|
1805
|
+
)
|
|
1806
|
+
] })
|
|
1807
|
+
);
|
|
1808
|
+
DialogContent.displayName = "DialogContent";
|
|
1809
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx32("div", { className: cn("flex flex-col gap-1.5 border-b border-border px-6 py-4 pr-16", className), ...props });
|
|
1810
|
+
var DialogTitle = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
|
|
1811
|
+
DialogPrimitive.Title,
|
|
1812
|
+
{
|
|
1813
|
+
ref,
|
|
1814
|
+
className: cn("text-lg leading-6 font-semibold text-surface-foreground", className),
|
|
1815
|
+
...props
|
|
1816
|
+
}
|
|
1817
|
+
));
|
|
1818
|
+
DialogTitle.displayName = "DialogTitle";
|
|
1819
|
+
var DialogDescription = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
|
|
1820
|
+
DialogPrimitive.Description,
|
|
1821
|
+
{
|
|
1822
|
+
ref,
|
|
1823
|
+
className: cn("text-body-small text-secondary-muted-foreground", className),
|
|
1824
|
+
...props
|
|
1825
|
+
}
|
|
1826
|
+
));
|
|
1827
|
+
DialogDescription.displayName = "DialogDescription";
|
|
1828
|
+
var DialogBody = ({ className, ...props }) => /* @__PURE__ */ jsx32("div", { className: cn("flex flex-col gap-4 p-6", className), ...props });
|
|
1829
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx32("div", { className: cn("flex items-center justify-end gap-3 border-t border-border px-6 py-4", className), ...props });
|
|
1830
|
+
|
|
1831
|
+
// src/components/Overlays & Feedback/Toast.tsx
|
|
1832
|
+
import * as React32 from "react";
|
|
1833
|
+
import { CheckCircle as CheckCircle2, Info, Warning, WarningCircle as WarningCircle2, X as X4 } from "@phosphor-icons/react";
|
|
1834
|
+
import { cva as cva4 } from "class-variance-authority";
|
|
1835
|
+
import { Toast as ToastPrimitive } from "radix-ui";
|
|
1836
|
+
import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1837
|
+
var toastVariants = cva4("border", {
|
|
1838
|
+
variants: {
|
|
1839
|
+
variant: {
|
|
1840
|
+
info: "border-info-border bg-surface",
|
|
1841
|
+
success: "border-success-soft-border bg-success-soft",
|
|
1842
|
+
warning: "border-warning-soft-border bg-warning-soft",
|
|
1843
|
+
destructive: "border-destructive-soft-border bg-destructive-soft"
|
|
1844
|
+
}
|
|
1845
|
+
},
|
|
1846
|
+
defaultVariants: { variant: "info" }
|
|
1847
|
+
});
|
|
1848
|
+
var iconColour = {
|
|
1849
|
+
info: "text-surface-foreground",
|
|
1850
|
+
success: "text-success-soft-foreground",
|
|
1851
|
+
warning: "text-warning-soft-foreground",
|
|
1852
|
+
destructive: "text-destructive-soft-foreground"
|
|
1853
|
+
};
|
|
1854
|
+
var titleColour = {
|
|
1855
|
+
info: "text-surface-foreground",
|
|
1856
|
+
success: "text-success-soft-foreground",
|
|
1857
|
+
warning: "text-warning-soft-foreground",
|
|
1858
|
+
destructive: "text-destructive-soft-foreground"
|
|
1859
|
+
};
|
|
1860
|
+
function VariantIcon({ variant, size }) {
|
|
1861
|
+
const props = { size, "aria-hidden": true, className: cn("shrink-0", iconColour[variant]) };
|
|
1862
|
+
if (variant === "success") return /* @__PURE__ */ jsx33(CheckCircle2, { ...props });
|
|
1863
|
+
if (variant === "warning") return /* @__PURE__ */ jsx33(Warning, { ...props });
|
|
1864
|
+
if (variant === "destructive") return /* @__PURE__ */ jsx33(WarningCircle2, { ...props });
|
|
1865
|
+
return /* @__PURE__ */ jsx33(Info, { ...props });
|
|
1866
|
+
}
|
|
1867
|
+
var ToastProvider = ToastPrimitive.Provider;
|
|
1868
|
+
var ToastViewport = React32.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx33(
|
|
1869
|
+
ToastPrimitive.Viewport,
|
|
1870
|
+
{
|
|
1871
|
+
ref,
|
|
1872
|
+
style: { zIndex: "var(--sys-z-50)" },
|
|
1873
|
+
className: cn("fixed right-4 bottom-4 flex w-89 max-w-full flex-col gap-3 outline-none", className),
|
|
1874
|
+
...props
|
|
1875
|
+
}
|
|
1876
|
+
));
|
|
1877
|
+
ToastViewport.displayName = "ToastViewport";
|
|
1878
|
+
var Toast = React32.forwardRef(
|
|
1879
|
+
({ className, variant = "info", title, description, action, closeLabel = "Close", children, ...props }, ref) => {
|
|
1880
|
+
const v = variant ?? "info";
|
|
1881
|
+
return /* @__PURE__ */ jsxs22(
|
|
1882
|
+
ToastPrimitive.Root,
|
|
1883
|
+
{
|
|
1884
|
+
ref,
|
|
1885
|
+
type: v === "destructive" ? "foreground" : "background",
|
|
1886
|
+
className: cn("flex items-start gap-3 rounded-lg p-4 shadow-lg", toastVariants({ variant: v }), className),
|
|
1887
|
+
...props,
|
|
1888
|
+
children: [
|
|
1889
|
+
/* @__PURE__ */ jsx33(VariantIcon, { variant: v, size: 20 }),
|
|
1890
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex min-w-0 flex-1 flex-col gap-1 text-body-small", children: [
|
|
1891
|
+
title != null && /* @__PURE__ */ jsx33(ToastPrimitive.Title, { className: cn("font-semibold", titleColour[v]), children: title }),
|
|
1892
|
+
description != null && /* @__PURE__ */ jsx33(ToastPrimitive.Description, { className: "text-secondary-muted-foreground", children: description }),
|
|
1893
|
+
children,
|
|
1894
|
+
action
|
|
1895
|
+
] }),
|
|
1896
|
+
/* @__PURE__ */ jsx33(
|
|
1897
|
+
ToastPrimitive.Close,
|
|
1898
|
+
{
|
|
1899
|
+
"aria-label": closeLabel,
|
|
1900
|
+
className: "inline-flex size-4 shrink-0 items-center justify-center rounded-xs text-surface-foreground",
|
|
1901
|
+
children: /* @__PURE__ */ jsx33(X4, { size: 16, "aria-hidden": true })
|
|
1902
|
+
}
|
|
1903
|
+
)
|
|
1904
|
+
]
|
|
1905
|
+
}
|
|
1906
|
+
);
|
|
1907
|
+
}
|
|
1908
|
+
);
|
|
1909
|
+
Toast.displayName = "Toast";
|
|
1910
|
+
var ToastAction = ToastPrimitive.Action;
|
|
1911
|
+
var ToastInline = React32.forwardRef(
|
|
1912
|
+
({ className, variant = "info", onClose, closeLabel = "Close", children, ...props }, ref) => {
|
|
1913
|
+
const v = variant ?? "info";
|
|
1914
|
+
return /* @__PURE__ */ jsxs22(
|
|
1915
|
+
"div",
|
|
1916
|
+
{
|
|
1917
|
+
ref,
|
|
1918
|
+
role: v === "destructive" ? "alert" : "status",
|
|
1919
|
+
className: cn("flex items-center gap-2 rounded-sm px-2 py-1.5", toastVariants({ variant: v }), className),
|
|
1920
|
+
...props,
|
|
1921
|
+
children: [
|
|
1922
|
+
/* @__PURE__ */ jsx33(VariantIcon, { variant: v, size: 16 }),
|
|
1923
|
+
/* @__PURE__ */ jsx33("p", { className: "min-w-0 flex-1 text-body-small text-secondary-muted-foreground", children }),
|
|
1924
|
+
onClose && /* @__PURE__ */ jsx33(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": closeLabel, onClick: onClose, children: /* @__PURE__ */ jsx33(X4, { size: 16, "aria-hidden": true }) })
|
|
1925
|
+
]
|
|
1926
|
+
}
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
);
|
|
1930
|
+
ToastInline.displayName = "ToastInline";
|
|
1931
|
+
|
|
1932
|
+
// src/components/Overlays & Feedback/Tooltip.tsx
|
|
1933
|
+
import * as React33 from "react";
|
|
1934
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
1935
|
+
import { Fragment as Fragment4, jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1936
|
+
var TooltipProvider = TooltipPrimitive.Provider;
|
|
1937
|
+
var Tooltip = TooltipPrimitive.Root;
|
|
1938
|
+
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
1939
|
+
var TooltipContent = React33.forwardRef(
|
|
1940
|
+
({ className, sideOffset = 4, title, description, action, arrow = true, children, ...props }, ref) => {
|
|
1941
|
+
const detailed = title != null || description != null;
|
|
1942
|
+
return /* @__PURE__ */ jsx34(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs23(
|
|
1943
|
+
TooltipPrimitive.Content,
|
|
1944
|
+
{
|
|
1945
|
+
ref,
|
|
1946
|
+
sideOffset,
|
|
1947
|
+
style: { zIndex: "var(--sys-z-40)" },
|
|
1948
|
+
className: cn(
|
|
1949
|
+
"rounded-sm bg-primary-soft-foreground text-label shadow-md",
|
|
1950
|
+
detailed ? "flex max-w-60 min-w-50 flex-col gap-1 px-3 py-2.5" : "px-2.5 py-1.5 text-ui-caption",
|
|
1951
|
+
action != null && "max-w-65 min-w-55",
|
|
1952
|
+
className
|
|
1953
|
+
),
|
|
1954
|
+
...props,
|
|
1955
|
+
children: [
|
|
1956
|
+
detailed ? /* @__PURE__ */ jsxs23(Fragment4, { children: [
|
|
1957
|
+
title != null && /* @__PURE__ */ jsx34("p", { className: "text-xs leading-4 font-semibold text-label", children: title }),
|
|
1958
|
+
description != null && /* @__PURE__ */ jsx34("p", { className: "text-xs leading-4.5 text-plum-200", children: description }),
|
|
1959
|
+
action != null && /* @__PURE__ */ jsx34("div", { className: "mt-1 text-ui-caption text-plum-300 underline *:underline", children: action })
|
|
1960
|
+
] }) : children,
|
|
1961
|
+
arrow && /* @__PURE__ */ jsx34(TooltipPrimitive.Arrow, { width: 12, height: 8, className: "fill-primary-soft-foreground" })
|
|
1962
|
+
]
|
|
1963
|
+
}
|
|
1964
|
+
) });
|
|
1965
|
+
}
|
|
1966
|
+
);
|
|
1967
|
+
TooltipContent.displayName = "TooltipContent";
|
|
1968
|
+
|
|
1969
|
+
// src/components/Question Types/FileUpload.tsx
|
|
1970
|
+
import * as React35 from "react";
|
|
1971
|
+
import { FileText, X as X5 } from "@phosphor-icons/react";
|
|
1972
|
+
import { Progress as ProgressPrimitive } from "radix-ui";
|
|
1973
|
+
|
|
1974
|
+
// src/components/Tags & Badges/Tag.tsx
|
|
1975
|
+
import * as React34 from "react";
|
|
1976
|
+
import { cva as cva5 } from "class-variance-authority";
|
|
1977
|
+
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1978
|
+
var tagVariants = cva5(
|
|
1979
|
+
"inline-flex items-center gap-1.5 whitespace-nowrap rounded-sm border px-2.5 py-1 text-ui-caption",
|
|
1980
|
+
{
|
|
1981
|
+
variants: {
|
|
1982
|
+
variant: {
|
|
1983
|
+
neutral: "border-accent-soft-border bg-accent-soft text-accent-soft-foreground",
|
|
1984
|
+
default: "border-border bg-surface text-surface-foreground",
|
|
1985
|
+
success: "border-success-soft-border bg-success-soft text-success-soft-foreground",
|
|
1986
|
+
warning: "border-warning-soft-border bg-warning-soft text-warning-soft-foreground",
|
|
1987
|
+
destructive: "border-destructive-soft-border bg-destructive-soft text-destructive-soft-foreground"
|
|
1988
|
+
}
|
|
1989
|
+
},
|
|
1990
|
+
defaultVariants: { variant: "neutral" }
|
|
1991
|
+
}
|
|
1992
|
+
);
|
|
1993
|
+
var Tag = React34.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx35("span", { ref, className: cn(tagVariants({ variant }), className), ...props }));
|
|
1994
|
+
Tag.displayName = "Tag";
|
|
1995
|
+
var statusDotVariants = cva5("size-1.5 shrink-0 rounded-full", {
|
|
1996
|
+
variants: {
|
|
1997
|
+
status: {
|
|
1998
|
+
active: "bg-success-800",
|
|
1999
|
+
inactive: "bg-accent",
|
|
2000
|
+
pending: "bg-warning",
|
|
2001
|
+
error: "bg-destructive"
|
|
2002
|
+
}
|
|
2003
|
+
},
|
|
2004
|
+
defaultVariants: { status: "active" }
|
|
2005
|
+
});
|
|
2006
|
+
var StatusTag = React34.forwardRef(
|
|
2007
|
+
({ className, status, children, ...props }, ref) => /* @__PURE__ */ jsxs24("span", { ref, className: cn(tagVariants({ variant: "default" }), className), ...props, children: [
|
|
2008
|
+
/* @__PURE__ */ jsx35("span", { className: statusDotVariants({ status }), "aria-hidden": "true" }),
|
|
2009
|
+
children
|
|
2010
|
+
] })
|
|
2011
|
+
);
|
|
2012
|
+
StatusTag.displayName = "StatusTag";
|
|
2013
|
+
|
|
2014
|
+
// src/components/Question Types/FileUpload.tsx
|
|
2015
|
+
import { Fragment as Fragment5, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2016
|
+
var FileUploadZone = React35.forwardRef(
|
|
2017
|
+
({ className, title = "Upload document", hint, icon, onFiles, ...props }, ref) => {
|
|
2018
|
+
const [over, setOver] = React35.useState(false);
|
|
2019
|
+
return /* @__PURE__ */ jsxs25(
|
|
2020
|
+
"label",
|
|
2021
|
+
{
|
|
2022
|
+
className: cn(
|
|
2023
|
+
"flex min-h-35.75 w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-md border-2 border-dashed border-border px-4 text-center transition-colors",
|
|
2024
|
+
"hover:bg-background has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-ring",
|
|
2025
|
+
over && "border-input-accent bg-accent-soft",
|
|
2026
|
+
className
|
|
2027
|
+
),
|
|
2028
|
+
onDragOver: (event) => {
|
|
2029
|
+
event.preventDefault();
|
|
2030
|
+
setOver(true);
|
|
2031
|
+
},
|
|
2032
|
+
onDragLeave: () => setOver(false),
|
|
2033
|
+
onDrop: (event) => {
|
|
2034
|
+
event.preventDefault();
|
|
2035
|
+
setOver(false);
|
|
2036
|
+
onFiles?.(Array.from(event.dataTransfer.files));
|
|
2037
|
+
},
|
|
2038
|
+
children: [
|
|
2039
|
+
/* @__PURE__ */ jsx36("span", { className: "flex size-10 items-center justify-center rounded-full bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground", children: icon ?? /* @__PURE__ */ jsx36(FileText, { size: 24, "aria-hidden": true }) }),
|
|
2040
|
+
/* @__PURE__ */ jsxs25("span", { className: "flex flex-col gap-1", children: [
|
|
2041
|
+
/* @__PURE__ */ jsx36("span", { className: "text-body-small text-surface-foreground", children: title }),
|
|
2042
|
+
hint && /* @__PURE__ */ jsx36("span", { className: "text-ui-caption text-secondary-muted-foreground", children: hint })
|
|
2043
|
+
] }),
|
|
2044
|
+
/* @__PURE__ */ jsx36(
|
|
2045
|
+
"input",
|
|
2046
|
+
{
|
|
2047
|
+
ref,
|
|
2048
|
+
type: "file",
|
|
2049
|
+
className: "sr-only",
|
|
2050
|
+
onChange: (event) => onFiles?.(Array.from(event.target.files ?? [])),
|
|
2051
|
+
...props
|
|
2052
|
+
}
|
|
2053
|
+
)
|
|
2054
|
+
]
|
|
2055
|
+
}
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
2058
|
+
);
|
|
2059
|
+
FileUploadZone.displayName = "FileUploadZone";
|
|
2060
|
+
var FileUploadItem = React35.forwardRef(
|
|
2061
|
+
({ className, name, size, status = "uploading", progress = 0, timeLeft, icon, onRemove, removeLabel, ...props }, ref) => {
|
|
2062
|
+
const uploading = status === "uploading";
|
|
2063
|
+
return /* @__PURE__ */ jsxs25(
|
|
2064
|
+
"div",
|
|
2065
|
+
{
|
|
2066
|
+
ref,
|
|
2067
|
+
className: cn("flex w-full flex-col justify-center gap-2 overflow-hidden rounded-sm border border-border p-2", className),
|
|
2068
|
+
...props,
|
|
2069
|
+
children: [
|
|
2070
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
|
|
2071
|
+
/* @__PURE__ */ jsx36("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-full bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground", children: icon ?? /* @__PURE__ */ jsx36(FileText, { size: 24, "aria-hidden": true }) }),
|
|
2072
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
2073
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2074
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
2075
|
+
/* @__PURE__ */ jsx36("p", { className: "truncate text-ui-label text-surface-foreground", children: name }),
|
|
2076
|
+
status === "complete" && /* @__PURE__ */ jsx36(Tag, { variant: "success", children: "Complete" }),
|
|
2077
|
+
status === "error" && /* @__PURE__ */ jsx36(Tag, { variant: "destructive", children: "Error" })
|
|
2078
|
+
] }),
|
|
2079
|
+
onRemove && /* @__PURE__ */ jsx36(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": removeLabel ?? `Remove ${name}`, onClick: onRemove, children: /* @__PURE__ */ jsx36(X5, { size: 16, "aria-hidden": true }) })
|
|
2080
|
+
] }),
|
|
2081
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between text-ui-caption text-secondary-muted-foreground", children: [
|
|
2082
|
+
/* @__PURE__ */ jsxs25("span", { className: "flex items-center gap-2", children: [
|
|
2083
|
+
size,
|
|
2084
|
+
uploading && timeLeft && /* @__PURE__ */ jsxs25(Fragment5, { children: [
|
|
2085
|
+
/* @__PURE__ */ jsx36("span", { "aria-hidden": "true", className: "size-0.5 rounded-full bg-secondary-muted-foreground" }),
|
|
2086
|
+
timeLeft
|
|
2087
|
+
] })
|
|
2088
|
+
] }),
|
|
2089
|
+
uploading && /* @__PURE__ */ jsxs25("span", { className: "text-body-xxs font-normal", children: [
|
|
2090
|
+
Math.round(progress),
|
|
2091
|
+
"%"
|
|
2092
|
+
] })
|
|
2093
|
+
] })
|
|
2094
|
+
] })
|
|
2095
|
+
] }),
|
|
2096
|
+
uploading && /* @__PURE__ */ jsx36(
|
|
2097
|
+
ProgressPrimitive.Root,
|
|
2098
|
+
{
|
|
2099
|
+
value: progress,
|
|
2100
|
+
"aria-label": `Uploading ${name}`,
|
|
2101
|
+
className: "h-0.75 w-full overflow-hidden rounded-sm bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5",
|
|
2102
|
+
children: /* @__PURE__ */ jsx36(ProgressPrimitive.Indicator, { className: "h-full bg-accent transition-[width]", style: { width: `${progress}%` } })
|
|
2103
|
+
}
|
|
2104
|
+
)
|
|
2105
|
+
]
|
|
2106
|
+
}
|
|
2107
|
+
);
|
|
2108
|
+
}
|
|
2109
|
+
);
|
|
2110
|
+
FileUploadItem.displayName = "FileUploadItem";
|
|
2111
|
+
|
|
2112
|
+
// src/components/Question Types/Media.tsx
|
|
2113
|
+
import * as React36 from "react";
|
|
2114
|
+
import { CornersOut, DotsThree, Image as ImageIcon, Pause, Play, SpeakerSimpleHigh, SpeakerSimpleX, Trash as Trash2 } from "@phosphor-icons/react";
|
|
2115
|
+
import { Slider as SliderPrimitive2, ToggleGroup as ToggleGroupPrimitive2 } from "radix-ui";
|
|
2116
|
+
import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2117
|
+
function MediaInfo({ name, details, onRemove, removeLabel, large, className, ...props }) {
|
|
2118
|
+
return /* @__PURE__ */ jsxs26("div", { className: cn("flex items-center justify-between border-t border-border bg-surface px-6 py-4", className), ...props, children: [
|
|
2119
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
|
|
2120
|
+
/* @__PURE__ */ jsx37("p", { className: cn("truncate text-surface-foreground", large ? "text-body-section" : "text-ui-label"), children: name }),
|
|
2121
|
+
details && /* @__PURE__ */ jsx37("p", { className: cn("flex items-center gap-2 text-secondary-muted-foreground", large ? "text-body-small" : "text-ui-caption"), children: details.map((part, index) => /* @__PURE__ */ jsxs26(React36.Fragment, { children: [
|
|
2122
|
+
index > 0 && /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "size-0.5 rounded-full bg-secondary-muted-foreground" }),
|
|
2123
|
+
part
|
|
2124
|
+
] }, part)) })
|
|
2125
|
+
] }),
|
|
2126
|
+
onRemove && /* @__PURE__ */ jsx37(Button, { type: "button", variant: "destructive", size: "icon", "aria-label": removeLabel ?? `Remove ${name}`, onClick: onRemove, children: /* @__PURE__ */ jsx37(Trash2, { size: 16, "aria-hidden": true }) })
|
|
2127
|
+
] });
|
|
2128
|
+
}
|
|
2129
|
+
var ImagePreview = React36.forwardRef(
|
|
2130
|
+
({ className, children, name, details, onRemove, ...props }, ref) => /* @__PURE__ */ jsxs26("div", { ref, className: cn("flex w-full flex-col overflow-hidden rounded-lg border border-border", className), ...props, children: [
|
|
2131
|
+
/* @__PURE__ */ jsx37("div", { className: "flex h-84 w-full items-center justify-center bg-accent-soft [&>img]:size-full [&>img]:object-contain", children }),
|
|
2132
|
+
/* @__PURE__ */ jsx37(MediaInfo, { name, details, onRemove, large: true })
|
|
2133
|
+
] })
|
|
2134
|
+
);
|
|
2135
|
+
ImagePreview.displayName = "ImagePreview";
|
|
2136
|
+
var ImageThumbnails = React36.forwardRef(
|
|
2137
|
+
({ className, max, images, value, onValueChange, ...props }, ref) => /* @__PURE__ */ jsx37(
|
|
2138
|
+
ToggleGroupPrimitive2.Root,
|
|
2139
|
+
{
|
|
2140
|
+
ref,
|
|
2141
|
+
type: "single",
|
|
2142
|
+
value: value ?? "",
|
|
2143
|
+
onValueChange: (next) => next && onValueChange?.(next),
|
|
2144
|
+
className: cn("flex w-full gap-2", className),
|
|
2145
|
+
...props,
|
|
2146
|
+
children: Array.from({ length: max }, (_, index) => {
|
|
2147
|
+
const image = images[index];
|
|
2148
|
+
if (!image) {
|
|
2149
|
+
return /* @__PURE__ */ jsx37(
|
|
2150
|
+
"span",
|
|
2151
|
+
{
|
|
2152
|
+
"aria-hidden": "true",
|
|
2153
|
+
className: "flex h-20 min-w-0 flex-1 items-center justify-center rounded-sm border border-dashed border-border text-accent-foreground",
|
|
2154
|
+
children: /* @__PURE__ */ jsx37(ImageIcon, { size: 24 })
|
|
2155
|
+
},
|
|
2156
|
+
`empty-${index}`
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
return /* @__PURE__ */ jsx37(
|
|
2160
|
+
ToggleGroupPrimitive2.Item,
|
|
2161
|
+
{
|
|
2162
|
+
value: image.id,
|
|
2163
|
+
"aria-label": image.alt,
|
|
2164
|
+
className: cn(
|
|
2165
|
+
"flex h-20 min-w-0 flex-1 items-center justify-center overflow-hidden rounded-sm border border-border bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 p-2 text-surface-foreground transition-colors",
|
|
2166
|
+
"hover:bg-accent-soft hover:bg-none",
|
|
2167
|
+
"data-[state=on]:border-accent-foreground data-[state=on]:bg-accent-soft data-[state=on]:bg-none data-[state=on]:text-accent-foreground"
|
|
2168
|
+
),
|
|
2169
|
+
children: image.src ? /* @__PURE__ */ jsx37("img", { src: image.src, alt: "", className: "size-full object-cover" }) : /* @__PURE__ */ jsx37(ImageIcon, { size: 24, "aria-hidden": true })
|
|
2170
|
+
},
|
|
2171
|
+
image.id
|
|
2172
|
+
);
|
|
2173
|
+
})
|
|
2174
|
+
}
|
|
2175
|
+
)
|
|
2176
|
+
);
|
|
2177
|
+
ImageThumbnails.displayName = "ImageThumbnails";
|
|
2178
|
+
var formatTime = (seconds) => {
|
|
2179
|
+
const total = Math.max(0, Math.floor(Number.isFinite(seconds) ? seconds : 0));
|
|
2180
|
+
return `${Math.floor(total / 60)}:${String(total % 60).padStart(2, "0")}`;
|
|
2181
|
+
};
|
|
2182
|
+
var VideoPlayer = React36.forwardRef(
|
|
2183
|
+
({ className, src, name, details, onRemove, onMore, initialTime = 0, initialDuration = 0, ...props }, ref) => {
|
|
2184
|
+
const video = React36.useRef(null);
|
|
2185
|
+
const [playing, setPlaying] = React36.useState(false);
|
|
2186
|
+
const [time, setTime] = React36.useState(initialTime);
|
|
2187
|
+
const [duration, setDuration] = React36.useState(initialDuration);
|
|
2188
|
+
const [volume, setVolume] = React36.useState(1);
|
|
2189
|
+
const muted = volume === 0;
|
|
2190
|
+
const toggle2 = () => {
|
|
2191
|
+
const el = video.current;
|
|
2192
|
+
if (!el) return setPlaying((p) => !p);
|
|
2193
|
+
if (el.paused) void el.play();
|
|
2194
|
+
else el.pause();
|
|
2195
|
+
};
|
|
2196
|
+
return /* @__PURE__ */ jsxs26("div", { ref, className: cn("flex w-full flex-col overflow-hidden rounded-lg border border-border bg-surface", className), ...props, children: [
|
|
2197
|
+
/* @__PURE__ */ jsxs26("div", { className: "relative flex h-60.5 w-full items-end bg-accent-soft", children: [
|
|
2198
|
+
src && /* @__PURE__ */ jsx37(
|
|
2199
|
+
"video",
|
|
2200
|
+
{
|
|
2201
|
+
ref: video,
|
|
2202
|
+
src,
|
|
2203
|
+
className: "absolute inset-0 size-full object-contain",
|
|
2204
|
+
onPlay: () => setPlaying(true),
|
|
2205
|
+
onPause: () => setPlaying(false),
|
|
2206
|
+
onTimeUpdate: (event) => setTime(event.currentTarget.currentTime),
|
|
2207
|
+
onLoadedMetadata: (event) => setDuration(event.currentTarget.duration),
|
|
2208
|
+
onVolumeChange: (event) => setVolume(event.currentTarget.muted ? 0 : event.currentTarget.volume)
|
|
2209
|
+
}
|
|
2210
|
+
),
|
|
2211
|
+
/* @__PURE__ */ jsxs26("div", { className: "relative flex w-full flex-col gap-2 bg-surface-foreground bg-linear-to-r from-primary/30 to-primary/30 px-4 pt-3 pb-4 text-surface", children: [
|
|
2212
|
+
/* @__PURE__ */ jsxs26(
|
|
2213
|
+
SliderPrimitive2.Root,
|
|
2214
|
+
{
|
|
2215
|
+
min: 0,
|
|
2216
|
+
max: duration || 1,
|
|
2217
|
+
step: 0.1,
|
|
2218
|
+
value: [Math.min(time, duration || 1)],
|
|
2219
|
+
onValueChange: ([next]) => {
|
|
2220
|
+
if (next === void 0) return;
|
|
2221
|
+
setTime(next);
|
|
2222
|
+
if (video.current) video.current.currentTime = next;
|
|
2223
|
+
},
|
|
2224
|
+
className: "relative flex h-4 w-full touch-none items-center select-none",
|
|
2225
|
+
children: [
|
|
2226
|
+
/* @__PURE__ */ jsx37(SliderPrimitive2.Track, { className: "relative h-1 w-full grow overflow-hidden rounded-xxs bg-surface/20", children: /* @__PURE__ */ jsx37(SliderPrimitive2.Range, { className: "absolute h-full bg-accent-foreground" }) }),
|
|
2227
|
+
/* @__PURE__ */ jsx37(SliderPrimitive2.Thumb, { "aria-label": "Seek", className: "block size-3 rounded-full border-2 border-surface bg-surface shadow-sm" })
|
|
2228
|
+
]
|
|
2229
|
+
}
|
|
2230
|
+
),
|
|
2231
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between", children: [
|
|
2232
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-4", children: [
|
|
2233
|
+
/* @__PURE__ */ jsx37(
|
|
2234
|
+
"button",
|
|
2235
|
+
{
|
|
2236
|
+
type: "button",
|
|
2237
|
+
"aria-label": playing ? "Pause" : "Play",
|
|
2238
|
+
onClick: toggle2,
|
|
2239
|
+
className: "inline-flex size-10 items-center justify-center rounded-full bg-surface/12 text-surface transition-colors hover:bg-surface/20",
|
|
2240
|
+
children: playing ? /* @__PURE__ */ jsx37(Pause, { size: 16, weight: "fill", "aria-hidden": true }) : /* @__PURE__ */ jsx37(Play, { size: 16, weight: "fill", "aria-hidden": true })
|
|
2241
|
+
}
|
|
2242
|
+
),
|
|
2243
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-ui-label whitespace-nowrap text-surface/80", children: [
|
|
2244
|
+
formatTime(time),
|
|
2245
|
+
" / ",
|
|
2246
|
+
formatTime(duration)
|
|
2247
|
+
] })
|
|
2248
|
+
] }),
|
|
2249
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2", children: [
|
|
2250
|
+
/* @__PURE__ */ jsx37(
|
|
2251
|
+
VolumeControl,
|
|
2252
|
+
{
|
|
2253
|
+
volume,
|
|
2254
|
+
onVolumeChange: (next) => {
|
|
2255
|
+
setVolume(next);
|
|
2256
|
+
if (video.current) {
|
|
2257
|
+
video.current.volume = next;
|
|
2258
|
+
video.current.muted = next === 0;
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
),
|
|
2263
|
+
/* @__PURE__ */ jsx37(
|
|
2264
|
+
"button",
|
|
2265
|
+
{
|
|
2266
|
+
type: "button",
|
|
2267
|
+
"aria-label": "Full screen",
|
|
2268
|
+
onClick: () => void video.current?.requestFullscreen?.(),
|
|
2269
|
+
className: "inline-flex size-10 items-center justify-center rounded-md text-surface transition-colors hover:bg-surface/12",
|
|
2270
|
+
children: /* @__PURE__ */ jsx37(CornersOut, { size: 16, "aria-hidden": true })
|
|
2271
|
+
}
|
|
2272
|
+
),
|
|
2273
|
+
/* @__PURE__ */ jsx37(
|
|
2274
|
+
"button",
|
|
2275
|
+
{
|
|
2276
|
+
type: "button",
|
|
2277
|
+
"aria-label": "More",
|
|
2278
|
+
onClick: onMore,
|
|
2279
|
+
className: "inline-flex size-10 items-center justify-center rounded-md text-surface transition-colors hover:bg-surface/12",
|
|
2280
|
+
children: /* @__PURE__ */ jsx37(DotsThree, { size: 16, "aria-hidden": true })
|
|
2281
|
+
}
|
|
2282
|
+
)
|
|
2283
|
+
] })
|
|
2284
|
+
] })
|
|
2285
|
+
] })
|
|
2286
|
+
] }),
|
|
2287
|
+
name && /* @__PURE__ */ jsx37(MediaInfo, { name, details, onRemove }),
|
|
2288
|
+
/* @__PURE__ */ jsx37("span", { className: "sr-only", "aria-live": "polite", children: muted ? "Muted" : "" })
|
|
2289
|
+
] });
|
|
2290
|
+
}
|
|
2291
|
+
);
|
|
2292
|
+
VideoPlayer.displayName = "VideoPlayer";
|
|
2293
|
+
function VolumeControl({ volume, onVolumeChange, className }) {
|
|
2294
|
+
const last = React36.useRef(volume || 1);
|
|
2295
|
+
if (volume > 0) last.current = volume;
|
|
2296
|
+
return /* @__PURE__ */ jsxs26("div", { className: cn("group/volume flex items-center", className), children: [
|
|
2297
|
+
/* @__PURE__ */ jsx37("div", { className: "w-0 overflow-hidden opacity-0 transition-all group-focus-within/volume:w-16 group-focus-within/volume:opacity-100 group-hover/volume:w-16 group-hover/volume:opacity-100", children: /* @__PURE__ */ jsxs26(
|
|
2298
|
+
SliderPrimitive2.Root,
|
|
2299
|
+
{
|
|
2300
|
+
min: 0,
|
|
2301
|
+
max: 1,
|
|
2302
|
+
step: 0.05,
|
|
2303
|
+
value: [volume],
|
|
2304
|
+
onValueChange: ([next]) => next !== void 0 && onVolumeChange(next),
|
|
2305
|
+
className: "relative flex h-4 w-14 touch-none items-center select-none",
|
|
2306
|
+
children: [
|
|
2307
|
+
/* @__PURE__ */ jsx37(SliderPrimitive2.Track, { className: "relative h-1 w-full grow overflow-hidden rounded-xxs bg-surface/20", children: /* @__PURE__ */ jsx37(SliderPrimitive2.Range, { className: "absolute h-full bg-surface" }) }),
|
|
2308
|
+
/* @__PURE__ */ jsx37(SliderPrimitive2.Thumb, { "aria-label": "Volume", className: "block size-3 rounded-full bg-surface shadow-sm" })
|
|
2309
|
+
]
|
|
2310
|
+
}
|
|
2311
|
+
) }),
|
|
2312
|
+
/* @__PURE__ */ jsx37(
|
|
2313
|
+
"button",
|
|
2314
|
+
{
|
|
2315
|
+
type: "button",
|
|
2316
|
+
"aria-label": volume === 0 ? "Unmute" : "Mute",
|
|
2317
|
+
onClick: () => onVolumeChange(volume === 0 ? last.current : 0),
|
|
2318
|
+
className: "inline-flex size-10 items-center justify-center rounded-md text-surface transition-colors hover:bg-surface/12",
|
|
2319
|
+
children: volume === 0 ? /* @__PURE__ */ jsx37(SpeakerSimpleX, { size: 16, "aria-hidden": true }) : /* @__PURE__ */ jsx37(SpeakerSimpleHigh, { size: 16, "aria-hidden": true })
|
|
2320
|
+
}
|
|
2321
|
+
)
|
|
2322
|
+
] });
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
// src/components/Question Types/OpenEndAnswer.tsx
|
|
2326
|
+
import * as React37 from "react";
|
|
2327
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2328
|
+
var OpenEndAnswer = React37.forwardRef(
|
|
2329
|
+
({ value, defaultValue, onChange, maxLength = 1e3, placeholder = "Write your answer", ...props }, ref) => {
|
|
2330
|
+
const [internal, setInternal] = React37.useState(String(defaultValue ?? ""));
|
|
2331
|
+
const text = value !== void 0 ? String(value) : internal;
|
|
2332
|
+
return /* @__PURE__ */ jsx38(
|
|
2333
|
+
Textarea,
|
|
2334
|
+
{
|
|
2335
|
+
ref,
|
|
2336
|
+
value: text,
|
|
2337
|
+
maxLength,
|
|
2338
|
+
placeholder,
|
|
2339
|
+
description: `${text.length}/${maxLength} characters`,
|
|
2340
|
+
onChange: (event) => {
|
|
2341
|
+
setInternal(event.target.value);
|
|
2342
|
+
onChange?.(event);
|
|
2343
|
+
},
|
|
2344
|
+
...props
|
|
2345
|
+
}
|
|
2346
|
+
);
|
|
2347
|
+
}
|
|
2348
|
+
);
|
|
2349
|
+
OpenEndAnswer.displayName = "OpenEndAnswer";
|
|
2350
|
+
|
|
2351
|
+
// src/components/Question Types/QuestionCard.tsx
|
|
2352
|
+
import * as React38 from "react";
|
|
2353
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
2354
|
+
var QuestionCard = React38.forwardRef(
|
|
2355
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx39(
|
|
2356
|
+
"div",
|
|
2357
|
+
{
|
|
2358
|
+
ref,
|
|
2359
|
+
className: cn("flex w-120 max-w-200 flex-col gap-4 rounded-lg bg-surface p-6", className),
|
|
2360
|
+
...props
|
|
2361
|
+
}
|
|
2362
|
+
)
|
|
2363
|
+
);
|
|
2364
|
+
QuestionCard.displayName = "QuestionCard";
|
|
2365
|
+
|
|
2366
|
+
// src/components/Question Types/QuestionEditorCard.tsx
|
|
2367
|
+
import * as React40 from "react";
|
|
2368
|
+
import {
|
|
2369
|
+
Clipboard,
|
|
2370
|
+
Copy,
|
|
2371
|
+
Eye,
|
|
2372
|
+
Plus as Plus3,
|
|
2373
|
+
Sparkle as Sparkle2,
|
|
2374
|
+
Trash as Trash3
|
|
2375
|
+
} from "@phosphor-icons/react";
|
|
2376
|
+
|
|
2377
|
+
// src/components/Question Types/QuestionHeader.tsx
|
|
2378
|
+
import * as React39 from "react";
|
|
2379
|
+
import { DotsSixVertical } from "@phosphor-icons/react";
|
|
2380
|
+
import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2381
|
+
var eyebrow = "text-ui-caption uppercase text-secondary-muted-foreground";
|
|
2382
|
+
var QuestionHeader = React39.forwardRef(
|
|
2383
|
+
({ className, number, title, required, error, onDismissError, editor, onTitleChange, actions, maxLength = 2e3, active, showCounter = true, ...props }, ref) => {
|
|
2384
|
+
const label = String(number).padStart(2, "0");
|
|
2385
|
+
const showError = error !== void 0 && error !== false;
|
|
2386
|
+
if (editor) {
|
|
2387
|
+
const text = typeof title === "string" ? title : "";
|
|
2388
|
+
return /* @__PURE__ */ jsxs27("div", { ref, className: cn("group/header flex w-full flex-col gap-2", className), ...props, children: [
|
|
2389
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between", children: [
|
|
2390
|
+
/* @__PURE__ */ jsxs27(
|
|
2391
|
+
"span",
|
|
2392
|
+
{
|
|
2393
|
+
className: cn(
|
|
2394
|
+
"group/handle inline-flex h-6 items-center gap-1 rounded-sm px-2.5 text-ui-caption hover:pl-1",
|
|
2395
|
+
active ? "bg-accent-soft text-accent-soft-foreground" : "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground"
|
|
2396
|
+
),
|
|
2397
|
+
children: [
|
|
2398
|
+
/* @__PURE__ */ jsx40(DotsSixVertical, { size: 16, "aria-hidden": true, className: "hidden shrink-0 group-hover/handle:block" }),
|
|
2399
|
+
"Question ",
|
|
2400
|
+
number
|
|
2401
|
+
]
|
|
2402
|
+
}
|
|
2403
|
+
),
|
|
2404
|
+
actions && /* @__PURE__ */ jsx40("div", { className: "flex items-center gap-2 opacity-0 transition-opacity group-focus-within/header:opacity-100 group-hover/header:opacity-100", children: actions })
|
|
2405
|
+
] }),
|
|
2406
|
+
/* @__PURE__ */ jsx40(
|
|
2407
|
+
"textarea",
|
|
2408
|
+
{
|
|
2409
|
+
rows: 1,
|
|
2410
|
+
"aria-label": "Question title",
|
|
2411
|
+
value: text,
|
|
2412
|
+
maxLength,
|
|
2413
|
+
onChange: (event) => onTitleChange?.(event.target.value),
|
|
2414
|
+
className: "field-sizing-content w-full resize-none bg-transparent text-heading-h4 text-surface-foreground outline-none"
|
|
2415
|
+
}
|
|
2416
|
+
),
|
|
2417
|
+
showCounter && /* @__PURE__ */ jsxs27("p", { className: "text-ui-caption text-secondary-muted-foreground", children: [
|
|
2418
|
+
text.length,
|
|
2419
|
+
"/",
|
|
2420
|
+
maxLength,
|
|
2421
|
+
" characters"
|
|
2422
|
+
] })
|
|
2423
|
+
] });
|
|
2424
|
+
}
|
|
2425
|
+
return /* @__PURE__ */ jsxs27("div", { ref, className: cn("flex w-full flex-col gap-2", className), ...props, children: [
|
|
2426
|
+
showError && /* @__PURE__ */ jsx40(ToastInline, { variant: "destructive", onClose: onDismissError, className: "min-h-10", children: /* @__PURE__ */ jsx40("span", { className: "text-ui-label text-destructive", children: error === true ? "This question is mandatory." : error }) }),
|
|
2427
|
+
/* @__PURE__ */ jsxs27("p", { className: eyebrow, children: [
|
|
2428
|
+
"Question ",
|
|
2429
|
+
label
|
|
2430
|
+
] }),
|
|
2431
|
+
/* @__PURE__ */ jsxs27("h3", { className: "text-heading-h4 text-surface-foreground", children: [
|
|
2432
|
+
title,
|
|
2433
|
+
required && /* @__PURE__ */ jsx40("span", { "aria-hidden": "true", className: "text-destructive", children: "*" }),
|
|
2434
|
+
required && /* @__PURE__ */ jsx40("span", { className: "sr-only", children: " (required)" })
|
|
2435
|
+
] })
|
|
2436
|
+
] });
|
|
2437
|
+
}
|
|
2438
|
+
);
|
|
2439
|
+
QuestionHeader.displayName = "QuestionHeader";
|
|
2440
|
+
|
|
2441
|
+
// src/components/Question Types/QuestionEditorCard.tsx
|
|
2442
|
+
import { Fragment as Fragment7, jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2443
|
+
var QuestionEditorCard = React40.forwardRef(
|
|
2444
|
+
({
|
|
2445
|
+
className,
|
|
2446
|
+
number,
|
|
2447
|
+
title,
|
|
2448
|
+
onTitleChange,
|
|
2449
|
+
active,
|
|
2450
|
+
maxLength,
|
|
2451
|
+
countLabel,
|
|
2452
|
+
actions,
|
|
2453
|
+
onDuplicate,
|
|
2454
|
+
onDelete,
|
|
2455
|
+
onPreview,
|
|
2456
|
+
onAskAi,
|
|
2457
|
+
onAdd,
|
|
2458
|
+
onPaste,
|
|
2459
|
+
note,
|
|
2460
|
+
children,
|
|
2461
|
+
...props
|
|
2462
|
+
}, ref) => {
|
|
2463
|
+
const footer = active && (countLabel != null || onAdd || onPaste);
|
|
2464
|
+
return /* @__PURE__ */ jsxs28(
|
|
2465
|
+
"div",
|
|
2466
|
+
{
|
|
2467
|
+
ref,
|
|
2468
|
+
className: cn("group/editor flex w-full items-start gap-2", className),
|
|
2469
|
+
...props,
|
|
2470
|
+
children: [
|
|
2471
|
+
/* @__PURE__ */ jsxs28(
|
|
2472
|
+
"div",
|
|
2473
|
+
{
|
|
2474
|
+
className: cn(
|
|
2475
|
+
"flex w-full max-w-200 flex-col overflow-hidden rounded-xl border bg-surface transition-shadow group-hover/editor:shadow-lg group-focus-within/editor:shadow-lg",
|
|
2476
|
+
active ? "border-accent" : "border-border"
|
|
2477
|
+
),
|
|
2478
|
+
children: [
|
|
2479
|
+
/* @__PURE__ */ jsxs28("div", { className: cn("flex flex-col p-6", footer ? "gap-5" : "gap-4"), children: [
|
|
2480
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col gap-4", children: [
|
|
2481
|
+
/* @__PURE__ */ jsx41(
|
|
2482
|
+
QuestionHeader,
|
|
2483
|
+
{
|
|
2484
|
+
editor: true,
|
|
2485
|
+
number,
|
|
2486
|
+
title,
|
|
2487
|
+
onTitleChange,
|
|
2488
|
+
active,
|
|
2489
|
+
showCounter: !!active,
|
|
2490
|
+
maxLength,
|
|
2491
|
+
actions: actions ?? /* @__PURE__ */ jsxs28(Fragment7, { children: [
|
|
2492
|
+
/* @__PURE__ */ jsx41(
|
|
2493
|
+
Button,
|
|
2494
|
+
{
|
|
2495
|
+
type: "button",
|
|
2496
|
+
variant: "ghost",
|
|
2497
|
+
size: "icon-sm",
|
|
2498
|
+
"aria-label": "Duplicate question",
|
|
2499
|
+
onClick: onDuplicate,
|
|
2500
|
+
children: /* @__PURE__ */ jsx41(Copy, { size: 16, "aria-hidden": true })
|
|
2501
|
+
}
|
|
2502
|
+
),
|
|
2503
|
+
/* @__PURE__ */ jsx41(
|
|
2504
|
+
Button,
|
|
2505
|
+
{
|
|
2506
|
+
type: "button",
|
|
2507
|
+
variant: "destructive",
|
|
2508
|
+
size: "icon-sm",
|
|
2509
|
+
"aria-label": "Delete question",
|
|
2510
|
+
onClick: onDelete,
|
|
2511
|
+
children: /* @__PURE__ */ jsx41(Trash3, { size: 16, "aria-hidden": true })
|
|
2512
|
+
}
|
|
2513
|
+
),
|
|
2514
|
+
/* @__PURE__ */ jsx41(
|
|
2515
|
+
Button,
|
|
2516
|
+
{
|
|
2517
|
+
type: "button",
|
|
2518
|
+
variant: "ghost",
|
|
2519
|
+
size: "icon-sm",
|
|
2520
|
+
"aria-label": "Preview question",
|
|
2521
|
+
onClick: onPreview,
|
|
2522
|
+
children: /* @__PURE__ */ jsx41(Eye, { size: 16, "aria-hidden": true })
|
|
2523
|
+
}
|
|
2524
|
+
)
|
|
2525
|
+
] })
|
|
2526
|
+
}
|
|
2527
|
+
),
|
|
2528
|
+
children
|
|
2529
|
+
] }),
|
|
2530
|
+
footer && /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between", children: [
|
|
2531
|
+
/* @__PURE__ */ jsx41("p", { className: "text-ui-caption text-secondary-muted-foreground", children: countLabel }),
|
|
2532
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
2533
|
+
onAdd && /* @__PURE__ */ jsx41(
|
|
2534
|
+
Button,
|
|
2535
|
+
{
|
|
2536
|
+
type: "button",
|
|
2537
|
+
variant: "ghost",
|
|
2538
|
+
size: "icon",
|
|
2539
|
+
"aria-label": "Add choice",
|
|
2540
|
+
onClick: onAdd,
|
|
2541
|
+
children: /* @__PURE__ */ jsx41(Plus3, { size: 16, "aria-hidden": true })
|
|
2542
|
+
}
|
|
2543
|
+
),
|
|
2544
|
+
onPaste && /* @__PURE__ */ jsx41(
|
|
2545
|
+
Button,
|
|
2546
|
+
{
|
|
2547
|
+
type: "button",
|
|
2548
|
+
variant: "ghost",
|
|
2549
|
+
size: "icon",
|
|
2550
|
+
"aria-label": "Paste choices",
|
|
2551
|
+
onClick: onPaste,
|
|
2552
|
+
children: /* @__PURE__ */ jsx41(Clipboard, { size: 16, "aria-hidden": true })
|
|
2553
|
+
}
|
|
2554
|
+
)
|
|
2555
|
+
] })
|
|
2556
|
+
] })
|
|
2557
|
+
] }),
|
|
2558
|
+
note && /* @__PURE__ */ jsx41("div", { className: "border-t border-border px-2 py-2 text-body-small text-surface-foreground", children: note })
|
|
2559
|
+
]
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
onAskAi && /* @__PURE__ */ jsx41(
|
|
2563
|
+
Button,
|
|
2564
|
+
{
|
|
2565
|
+
type: "button",
|
|
2566
|
+
variant: "ghost",
|
|
2567
|
+
size: "icon-sm",
|
|
2568
|
+
"aria-label": "Ask AI",
|
|
2569
|
+
onClick: onAskAi,
|
|
2570
|
+
className: "shrink-0 opacity-0 transition-opacity group-hover/editor:opacity-100 group-focus-within/editor:opacity-100 focus-visible:opacity-100",
|
|
2571
|
+
children: /* @__PURE__ */ jsx41(Sparkle2, { size: 16, "aria-hidden": true })
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2574
|
+
]
|
|
2575
|
+
}
|
|
2576
|
+
);
|
|
2577
|
+
}
|
|
2578
|
+
);
|
|
2579
|
+
QuestionEditorCard.displayName = "QuestionEditorCard";
|
|
2580
|
+
|
|
2581
|
+
// src/components/Question Types/QuestionNavItem.tsx
|
|
2582
|
+
import * as React42 from "react";
|
|
2583
|
+
import { DotsSixVertical as DotsSixVertical2, Warning as Warning2 } from "@phosphor-icons/react";
|
|
2584
|
+
import { Slot as Slot3 } from "radix-ui";
|
|
2585
|
+
|
|
2586
|
+
// src/components/Question Types/QuestionTypeIcon.tsx
|
|
2587
|
+
import "react";
|
|
2588
|
+
import { ChatsCircle, CheckSquare, FileArrowUp, ListNumbers, RadioButton, StarHalf } from "@phosphor-icons/react";
|
|
2589
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2590
|
+
var icons = {
|
|
2591
|
+
"select-one": RadioButton,
|
|
2592
|
+
"select-multiple": CheckSquare,
|
|
2593
|
+
ranking: ListNumbers,
|
|
2594
|
+
upload: FileArrowUp,
|
|
2595
|
+
rating: StarHalf,
|
|
2596
|
+
"open-end": ChatsCircle
|
|
2597
|
+
};
|
|
2598
|
+
function QuestionTypeIcon({ type, size = 22.5, className, ...props }) {
|
|
2599
|
+
const Icon = icons[type];
|
|
2600
|
+
return /* @__PURE__ */ jsx42(Icon, { size, weight: "duotone", "aria-hidden": true, className: className ?? "text-accent-foreground", ...props });
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
// src/components/Question Types/QuestionNavItem.tsx
|
|
2604
|
+
import { jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2605
|
+
var QuestionNavItem = React42.forwardRef(
|
|
2606
|
+
({ className, questionType = "select-one", selected, error, asChild, children, ...props }, ref) => {
|
|
2607
|
+
const Comp = asChild ? Slot3.Root : "button";
|
|
2608
|
+
return /* @__PURE__ */ jsxs29(
|
|
2609
|
+
Comp,
|
|
2610
|
+
{
|
|
2611
|
+
ref,
|
|
2612
|
+
type: asChild ? void 0 : "button",
|
|
2613
|
+
"aria-current": selected ? "true" : void 0,
|
|
2614
|
+
className: cn(
|
|
2615
|
+
"group/nav flex h-9.5 w-full max-w-106.5 items-center gap-2 rounded-sm border bg-surface p-2 text-left text-body-small text-surface-foreground transition-colors focus-visible:outline-none",
|
|
2616
|
+
error ? ["hover:bg-destructive-soft focus-visible:border-destructive", selected ? "border-destructive" : "border-border"] : [
|
|
2617
|
+
"hover:border-input-accent hover:bg-accent-soft focus-visible:border-input-accent",
|
|
2618
|
+
selected ? "border-input-accent" : "border-border"
|
|
2619
|
+
],
|
|
2620
|
+
className
|
|
2621
|
+
),
|
|
2622
|
+
...props,
|
|
2623
|
+
children: [
|
|
2624
|
+
/* @__PURE__ */ jsxs29("span", { "aria-hidden": "true", className: "relative flex size-4 shrink-0 items-center justify-center", children: [
|
|
2625
|
+
/* @__PURE__ */ jsx43(DotsSixVertical2, { size: 16, className: "hidden group-hover/nav:block" }),
|
|
2626
|
+
/* @__PURE__ */ jsx43("span", { className: "group-hover/nav:hidden", children: error ? /* @__PURE__ */ jsx43(Warning2, { size: 16, className: "text-destructive" }) : /* @__PURE__ */ jsx43(QuestionTypeIcon, { type: questionType, size: 16 }) })
|
|
2627
|
+
] }),
|
|
2628
|
+
/* @__PURE__ */ jsx43("span", { className: "min-w-0 flex-1 truncate", children }),
|
|
2629
|
+
error && /* @__PURE__ */ jsx43("span", { className: "sr-only", children: ", has errors" })
|
|
2630
|
+
]
|
|
2631
|
+
}
|
|
2632
|
+
);
|
|
2633
|
+
}
|
|
2634
|
+
);
|
|
2635
|
+
QuestionNavItem.displayName = "QuestionNavItem";
|
|
2636
|
+
|
|
2637
|
+
// src/components/Question Types/QuestionOption.tsx
|
|
2638
|
+
import * as React43 from "react";
|
|
2639
|
+
import { Check as Check4, DotsSixVertical as DotsSixVertical3, Plus as Plus4, Trash as Trash4 } from "@phosphor-icons/react";
|
|
2640
|
+
import { jsx as jsx44, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2641
|
+
var optionClasses = "flex w-full max-w-150 cursor-pointer items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 text-body-base text-surface-foreground transition-colors hover:border-input hover:bg-accent-soft hover:shadow-md has-[[data-state=checked]]:border-accent-foreground has-[[data-state=checked]]:hover:border-accent-foreground has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50";
|
|
2642
|
+
function QuestionOption(props) {
|
|
2643
|
+
const id = React43.useId();
|
|
2644
|
+
return /* @__PURE__ */ jsxs30("label", { htmlFor: id, className: cn(optionClasses, props.className), children: [
|
|
2645
|
+
props.kind === "checkbox" ? /* @__PURE__ */ jsx44(
|
|
2646
|
+
Checkbox,
|
|
2647
|
+
{
|
|
2648
|
+
id,
|
|
2649
|
+
checked: props.checked,
|
|
2650
|
+
defaultChecked: props.defaultChecked,
|
|
2651
|
+
onCheckedChange: (next) => props.onCheckedChange?.(next === true),
|
|
2652
|
+
disabled: props.disabled
|
|
2653
|
+
}
|
|
2654
|
+
) : /* @__PURE__ */ jsx44(RadioGroupItem, { id, value: props.value, disabled: props.disabled }),
|
|
2655
|
+
/* @__PURE__ */ jsx44("span", { className: "min-w-0 flex-1", children: props.label })
|
|
2656
|
+
] });
|
|
2657
|
+
}
|
|
2658
|
+
var QuestionOtherOption = React43.forwardRef(
|
|
2659
|
+
({ className, onSubmit, confirmLabel = "Confirm answer", placeholder = "Type your answer", ...props }, ref) => {
|
|
2660
|
+
const inner = React43.useRef(null);
|
|
2661
|
+
React43.useImperativeHandle(ref, () => inner.current);
|
|
2662
|
+
const submit = () => onSubmit?.(inner.current?.value ?? "");
|
|
2663
|
+
return /* @__PURE__ */ jsxs30(
|
|
2664
|
+
"div",
|
|
2665
|
+
{
|
|
2666
|
+
className: cn(
|
|
2667
|
+
"inline-flex items-center gap-2 rounded-md border border-border bg-surface py-2 pr-2 pl-4 focus-within:border-input-accent",
|
|
2668
|
+
className
|
|
2669
|
+
),
|
|
2670
|
+
children: [
|
|
2671
|
+
/* @__PURE__ */ jsx44(
|
|
2672
|
+
"input",
|
|
2673
|
+
{
|
|
2674
|
+
ref: inner,
|
|
2675
|
+
type: "text",
|
|
2676
|
+
placeholder,
|
|
2677
|
+
onKeyDown: (event) => {
|
|
2678
|
+
if (event.key === "Enter") {
|
|
2679
|
+
event.preventDefault();
|
|
2680
|
+
submit();
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
2683
|
+
className: "min-w-0 bg-transparent text-body-base text-surface-foreground outline-none placeholder:text-muted-foreground",
|
|
2684
|
+
...props
|
|
2685
|
+
}
|
|
2686
|
+
),
|
|
2687
|
+
/* @__PURE__ */ jsx44(Button, { type: "button", variant: "subtle", size: "icon-sm", "aria-label": confirmLabel, onClick: submit, children: /* @__PURE__ */ jsx44(Check4, { size: 16, "aria-hidden": true }) })
|
|
2688
|
+
]
|
|
2689
|
+
}
|
|
2690
|
+
);
|
|
2691
|
+
}
|
|
2692
|
+
);
|
|
2693
|
+
QuestionOtherOption.displayName = "QuestionOtherOption";
|
|
2694
|
+
function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className }) {
|
|
2695
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn("flex w-full items-center gap-2", className), children: [
|
|
2696
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex h-11.5 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 focus-within:border-input-accent hover:border-input hover:shadow-md", children: [
|
|
2697
|
+
/* @__PURE__ */ jsx44(DotsSixVertical3, { size: 20, "aria-hidden": true, className: "shrink-0 text-surface-foreground" }),
|
|
2698
|
+
/* @__PURE__ */ jsx44(
|
|
2699
|
+
"input",
|
|
2700
|
+
{
|
|
2701
|
+
"aria-label": "Option label",
|
|
2702
|
+
value: label,
|
|
2703
|
+
onChange: (event) => onLabelChange?.(event.target.value),
|
|
2704
|
+
className: "min-w-0 flex-1 bg-transparent text-body-base text-surface-foreground outline-none"
|
|
2705
|
+
}
|
|
2706
|
+
)
|
|
2707
|
+
] }),
|
|
2708
|
+
/* @__PURE__ */ jsx44(Button, { type: "button", variant: "destructive", size: "icon-sm", "aria-label": "Remove option", onClick: onRemove, children: /* @__PURE__ */ jsx44(Trash4, { size: 16, "aria-hidden": true }) }),
|
|
2709
|
+
/* @__PURE__ */ jsx44(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Add option", onClick: onAdd, children: /* @__PURE__ */ jsx44(Plus4, { size: 16, "aria-hidden": true }) })
|
|
2710
|
+
] });
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
// src/components/Question Types/RankList.tsx
|
|
2714
|
+
import * as React44 from "react";
|
|
2715
|
+
import { DotsSixVertical as DotsSixVertical4 } from "@phosphor-icons/react";
|
|
2716
|
+
import { Fragment as Fragment8, jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2717
|
+
function move(list, from, to) {
|
|
2718
|
+
if (from === to || to < 0 || to >= list.length) return list;
|
|
2719
|
+
const next = list.slice();
|
|
2720
|
+
const [item] = next.splice(from, 1);
|
|
2721
|
+
next.splice(to, 0, item);
|
|
2722
|
+
return next;
|
|
2723
|
+
}
|
|
2724
|
+
var RankList = React44.forwardRef(
|
|
2725
|
+
({ className, items, onItemsChange, ...props }, ref) => {
|
|
2726
|
+
const [dragIndex, setDragIndex] = React44.useState(null);
|
|
2727
|
+
const [announcement, setAnnouncement] = React44.useState("");
|
|
2728
|
+
const handles = React44.useRef(/* @__PURE__ */ new Map());
|
|
2729
|
+
const refocus = React44.useRef(null);
|
|
2730
|
+
React44.useEffect(() => {
|
|
2731
|
+
if (refocus.current) {
|
|
2732
|
+
handles.current.get(refocus.current)?.focus();
|
|
2733
|
+
refocus.current = null;
|
|
2734
|
+
}
|
|
2735
|
+
});
|
|
2736
|
+
const reorder = (from, to, id) => {
|
|
2737
|
+
const next = move(items, from, to);
|
|
2738
|
+
if (next === items) return;
|
|
2739
|
+
refocus.current = id;
|
|
2740
|
+
setAnnouncement(`Moved to position ${to + 1} of ${items.length}`);
|
|
2741
|
+
onItemsChange(next);
|
|
2742
|
+
};
|
|
2743
|
+
return /* @__PURE__ */ jsxs31(Fragment8, { children: [
|
|
2744
|
+
/* @__PURE__ */ jsx45("ol", { ref, className: cn("flex w-full max-w-150 flex-col gap-4", className), ...props, children: items.map((item, index) => /* @__PURE__ */ jsxs31(
|
|
2745
|
+
"li",
|
|
2746
|
+
{
|
|
2747
|
+
draggable: true,
|
|
2748
|
+
onDragStart: () => setDragIndex(index),
|
|
2749
|
+
onDragOver: (event) => event.preventDefault(),
|
|
2750
|
+
onDrop: () => {
|
|
2751
|
+
if (dragIndex !== null) reorder(dragIndex, index, item.id);
|
|
2752
|
+
setDragIndex(null);
|
|
2753
|
+
},
|
|
2754
|
+
onDragEnd: () => setDragIndex(null),
|
|
2755
|
+
className: cn(
|
|
2756
|
+
"group/rank flex items-center gap-3 overflow-hidden rounded-sm border border-border bg-surface px-4 py-2.5 text-body-base text-surface-foreground transition-colors",
|
|
2757
|
+
"hover:border-accent-foreground hover:shadow-md",
|
|
2758
|
+
dragIndex === index && "opacity-50"
|
|
2759
|
+
),
|
|
2760
|
+
children: [
|
|
2761
|
+
/* @__PURE__ */ jsx45(
|
|
2762
|
+
"button",
|
|
2763
|
+
{
|
|
2764
|
+
type: "button",
|
|
2765
|
+
ref: (el) => {
|
|
2766
|
+
if (el) handles.current.set(item.id, el);
|
|
2767
|
+
else handles.current.delete(item.id);
|
|
2768
|
+
},
|
|
2769
|
+
"aria-label": `Reorder, position ${index + 1} of ${items.length}. Use the up and down arrow keys to move.`,
|
|
2770
|
+
onKeyDown: (event) => {
|
|
2771
|
+
if (event.key === "ArrowUp") {
|
|
2772
|
+
event.preventDefault();
|
|
2773
|
+
reorder(index, index - 1, item.id);
|
|
2774
|
+
} else if (event.key === "ArrowDown") {
|
|
2775
|
+
event.preventDefault();
|
|
2776
|
+
reorder(index, index + 1, item.id);
|
|
2777
|
+
}
|
|
2778
|
+
},
|
|
2779
|
+
className: "inline-flex shrink-0 cursor-grab rounded-xs text-surface-foreground",
|
|
2780
|
+
children: /* @__PURE__ */ jsx45(DotsSixVertical4, { size: 16, "aria-hidden": true })
|
|
2781
|
+
}
|
|
2782
|
+
),
|
|
2783
|
+
/* @__PURE__ */ jsx45(
|
|
2784
|
+
"span",
|
|
2785
|
+
{
|
|
2786
|
+
"aria-hidden": "true",
|
|
2787
|
+
className: "flex size-6 shrink-0 items-center justify-center rounded-full border border-border bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-ui-caption text-surface-foreground group-hover/rank:border-accent-foreground group-hover/rank:bg-accent-soft group-hover/rank:bg-none group-hover/rank:text-accent-soft-foreground",
|
|
2788
|
+
children: index + 1
|
|
2789
|
+
}
|
|
2790
|
+
),
|
|
2791
|
+
/* @__PURE__ */ jsx45("span", { className: "min-w-0 flex-1", children: item.label })
|
|
2792
|
+
]
|
|
2793
|
+
},
|
|
2794
|
+
item.id
|
|
2795
|
+
)) }),
|
|
2796
|
+
/* @__PURE__ */ jsx45("span", { role: "status", "aria-live": "polite", className: "sr-only", children: announcement })
|
|
2797
|
+
] });
|
|
2798
|
+
}
|
|
2799
|
+
);
|
|
2800
|
+
RankList.displayName = "RankList";
|
|
2801
|
+
|
|
2802
|
+
// src/components/Question Types/RatingScale.tsx
|
|
2803
|
+
import * as React45 from "react";
|
|
2804
|
+
import { ToggleGroup as ToggleGroupPrimitive3 } from "radix-ui";
|
|
2805
|
+
import { jsx as jsx46, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2806
|
+
var RatingScale = React45.forwardRef(
|
|
2807
|
+
({ className, max = 5, value, defaultValue, onValueChange, lowLabel, highLabel, ...props }, ref) => {
|
|
2808
|
+
const [internal, setInternal] = React45.useState(defaultValue);
|
|
2809
|
+
const current = value !== void 0 ? value : internal;
|
|
2810
|
+
return /* @__PURE__ */ jsxs32("div", { className: cn("flex w-full max-w-150 flex-col gap-2", className), children: [
|
|
2811
|
+
/* @__PURE__ */ jsx46(
|
|
2812
|
+
ToggleGroupPrimitive3.Root,
|
|
2813
|
+
{
|
|
2814
|
+
ref,
|
|
2815
|
+
type: "single",
|
|
2816
|
+
value: current ? String(current) : "",
|
|
2817
|
+
onValueChange: (next) => {
|
|
2818
|
+
const parsed = next ? Number(next) : void 0;
|
|
2819
|
+
setInternal(parsed);
|
|
2820
|
+
onValueChange?.(parsed);
|
|
2821
|
+
},
|
|
2822
|
+
className: "flex gap-2",
|
|
2823
|
+
...props,
|
|
2824
|
+
children: Array.from({ length: max }, (_, i) => i + 1).map((n) => /* @__PURE__ */ jsx46(
|
|
2825
|
+
ToggleGroupPrimitive3.Item,
|
|
2826
|
+
{
|
|
2827
|
+
value: String(n),
|
|
2828
|
+
"aria-label": `${n}`,
|
|
2829
|
+
className: cn(
|
|
2830
|
+
"flex h-12 min-w-0 flex-1 items-center justify-center rounded-sm border-2 border-border bg-surface text-ui-label-large text-surface-foreground transition-colors",
|
|
2831
|
+
"hover:bg-accent-soft",
|
|
2832
|
+
"data-[state=on]:border-accent-foreground data-[state=on]:text-accent-foreground"
|
|
2833
|
+
),
|
|
2834
|
+
children: n
|
|
2835
|
+
},
|
|
2836
|
+
n
|
|
2837
|
+
))
|
|
2838
|
+
}
|
|
2839
|
+
),
|
|
2840
|
+
(lowLabel != null || highLabel != null) && /* @__PURE__ */ jsxs32("div", { className: "flex justify-between text-ui-caption text-secondary-muted-foreground", "aria-hidden": "true", children: [
|
|
2841
|
+
/* @__PURE__ */ jsx46("span", { children: lowLabel }),
|
|
2842
|
+
/* @__PURE__ */ jsx46("span", { children: highLabel })
|
|
2843
|
+
] })
|
|
2844
|
+
] });
|
|
2845
|
+
}
|
|
2846
|
+
);
|
|
2847
|
+
RatingScale.displayName = "RatingScale";
|
|
2848
|
+
|
|
2849
|
+
// src/components/Data Display/Progress.tsx
|
|
2850
|
+
import * as React46 from "react";
|
|
2851
|
+
import { Progress as ProgressPrimitive2 } from "radix-ui";
|
|
2852
|
+
import { jsx as jsx47, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2853
|
+
var Progress = React46.forwardRef(
|
|
2854
|
+
({ className, value = 0, label, valueLabel, detailsStart, detailsEnd, ...props }, ref) => {
|
|
2855
|
+
const hasHeader = label != null || valueLabel != null;
|
|
2856
|
+
const hasDetails = detailsStart != null || detailsEnd != null;
|
|
2857
|
+
const clamped = Math.min(100, Math.max(0, value ?? 0));
|
|
2858
|
+
return /* @__PURE__ */ jsxs33("div", { className: cn("flex w-full flex-col gap-2", className), children: [
|
|
2859
|
+
hasHeader && /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between text-ui-label text-surface-foreground", children: [
|
|
2860
|
+
/* @__PURE__ */ jsx47("span", { children: label }),
|
|
2861
|
+
/* @__PURE__ */ jsx47("span", { children: valueLabel === true ? `${Math.round(clamped)}%` : valueLabel })
|
|
2862
|
+
] }),
|
|
2863
|
+
/* @__PURE__ */ jsx47(
|
|
2864
|
+
ProgressPrimitive2.Root,
|
|
2865
|
+
{
|
|
2866
|
+
ref,
|
|
2867
|
+
value: clamped,
|
|
2868
|
+
className: "relative h-2 w-full overflow-hidden rounded-full bg-secondary",
|
|
2869
|
+
...props,
|
|
2870
|
+
children: /* @__PURE__ */ jsx47(
|
|
2871
|
+
ProgressPrimitive2.Indicator,
|
|
2872
|
+
{
|
|
2873
|
+
className: "h-full rounded-full bg-accent transition-[width]",
|
|
2874
|
+
style: { width: `${clamped}%` }
|
|
2875
|
+
}
|
|
2876
|
+
)
|
|
2877
|
+
}
|
|
2878
|
+
),
|
|
2879
|
+
hasDetails && /* @__PURE__ */ jsxs33("div", { className: "flex items-start justify-between text-ui-label leading-5 text-secondary-muted-foreground", children: [
|
|
2880
|
+
/* @__PURE__ */ jsx47("span", { children: detailsStart }),
|
|
2881
|
+
/* @__PURE__ */ jsx47("span", { children: detailsEnd })
|
|
2882
|
+
] })
|
|
2883
|
+
] });
|
|
2884
|
+
}
|
|
2885
|
+
);
|
|
2886
|
+
Progress.displayName = "Progress";
|
|
2887
|
+
|
|
2888
|
+
// src/components/Data Display/Table.tsx
|
|
2889
|
+
import * as React47 from "react";
|
|
2890
|
+
import { CaretDown as CaretDown4, CaretUp } from "@phosphor-icons/react";
|
|
2891
|
+
import { jsx as jsx48, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2892
|
+
var Table = React47.forwardRef(
|
|
2893
|
+
({ className, containerClassName, striped, ...props }, ref) => /* @__PURE__ */ jsx48("div", { className: cn("relative w-full overflow-auto rounded-lg border border-border bg-surface", containerClassName), children: /* @__PURE__ */ jsx48(
|
|
2894
|
+
"table",
|
|
2895
|
+
{
|
|
2896
|
+
ref,
|
|
2897
|
+
"data-striped": striped ? "" : void 0,
|
|
2898
|
+
className: cn("group/table w-full border-collapse text-body-small text-surface-foreground", className),
|
|
2899
|
+
...props
|
|
2900
|
+
}
|
|
2901
|
+
) })
|
|
2902
|
+
);
|
|
2903
|
+
Table.displayName = "Table";
|
|
2904
|
+
var TableHeader = React47.forwardRef(
|
|
2905
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx48("thead", { ref, className, ...props })
|
|
2906
|
+
);
|
|
2907
|
+
TableHeader.displayName = "TableHeader";
|
|
2908
|
+
var TableBody = React47.forwardRef(
|
|
2909
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx48("tbody", { ref, className, ...props })
|
|
2910
|
+
);
|
|
2911
|
+
TableBody.displayName = "TableBody";
|
|
2912
|
+
var TableRow = React47.forwardRef(
|
|
2913
|
+
({ className, selected, ...props }, ref) => /* @__PURE__ */ jsx48(
|
|
2914
|
+
"tr",
|
|
2915
|
+
{
|
|
2916
|
+
ref,
|
|
2917
|
+
"data-state": selected ? "selected" : void 0,
|
|
2918
|
+
"aria-selected": selected || void 0,
|
|
2919
|
+
className: cn(
|
|
2920
|
+
"group/row border-b border-border transition-colors last:border-b-0",
|
|
2921
|
+
"group-data-[striped]/table:even:bg-background hover:bg-accent-soft group-data-[striped]/table:even:hover:bg-accent-soft",
|
|
2922
|
+
className
|
|
2923
|
+
),
|
|
2924
|
+
...props
|
|
2925
|
+
}
|
|
2926
|
+
)
|
|
2927
|
+
);
|
|
2928
|
+
TableRow.displayName = "TableRow";
|
|
2929
|
+
var ariaSort = { none: "none", asc: "ascending", desc: "descending" };
|
|
2930
|
+
var TableHead = React47.forwardRef(
|
|
2931
|
+
({ className, align = "left", sortable, sort = "none", onSort, checkbox, children, ...props }, ref) => {
|
|
2932
|
+
const caret = sort === "asc" ? /* @__PURE__ */ jsx48(CaretUp, { size: 16, "aria-hidden": true, className: "shrink-0" }) : /* @__PURE__ */ jsx48(CaretDown4, { size: 16, "aria-hidden": true, className: "shrink-0" });
|
|
2933
|
+
return /* @__PURE__ */ jsx48(
|
|
2934
|
+
"th",
|
|
2935
|
+
{
|
|
2936
|
+
ref,
|
|
2937
|
+
scope: "col",
|
|
2938
|
+
"aria-sort": sortable ? ariaSort[sort] : void 0,
|
|
2939
|
+
className: cn(
|
|
2940
|
+
"h-10 border-b border-border text-ui-label whitespace-nowrap",
|
|
2941
|
+
checkbox ? "w-13 px-0 text-center" : "px-4 py-3",
|
|
2942
|
+
align === "right" ? "text-right" : "text-left",
|
|
2943
|
+
className
|
|
2944
|
+
),
|
|
2945
|
+
...props,
|
|
2946
|
+
children: sortable ? /* @__PURE__ */ jsxs34(
|
|
2947
|
+
"button",
|
|
2948
|
+
{
|
|
2949
|
+
type: "button",
|
|
2950
|
+
onClick: onSort,
|
|
2951
|
+
className: cn("inline-flex items-center gap-1 rounded-xs", align === "right" && "flex-row-reverse"),
|
|
2952
|
+
children: [
|
|
2953
|
+
children,
|
|
2954
|
+
caret
|
|
2955
|
+
]
|
|
2956
|
+
}
|
|
2957
|
+
) : checkbox ? /* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center", children }) : children
|
|
2958
|
+
}
|
|
2959
|
+
);
|
|
2960
|
+
}
|
|
2961
|
+
);
|
|
2962
|
+
TableHead.displayName = "TableHead";
|
|
2963
|
+
var TableCell = React47.forwardRef(
|
|
2964
|
+
({ className, align = "left", muted, checkbox, actions, children, ...props }, ref) => /* @__PURE__ */ jsx48(
|
|
2965
|
+
"td",
|
|
2966
|
+
{
|
|
2967
|
+
ref,
|
|
2968
|
+
className: cn(
|
|
2969
|
+
"h-10 text-body-small",
|
|
2970
|
+
"group-data-[state=selected]/row:first:border-l-2 group-data-[state=selected]/row:first:border-l-input-accent",
|
|
2971
|
+
checkbox ? "w-13 px-0 text-center" : actions ? "px-4 py-1.5 text-right" : "px-4 py-3",
|
|
2972
|
+
align === "right" && "text-right",
|
|
2973
|
+
muted ? "text-secondary-muted-foreground" : "text-surface-foreground",
|
|
2974
|
+
className
|
|
2975
|
+
),
|
|
2976
|
+
...props,
|
|
2977
|
+
children: checkbox ? /* @__PURE__ */ jsx48("div", { className: "flex items-center justify-center", children }) : actions ? /* @__PURE__ */ jsx48("div", { className: "flex items-start justify-end gap-1", children }) : children
|
|
2978
|
+
}
|
|
2979
|
+
)
|
|
2980
|
+
);
|
|
2981
|
+
TableCell.displayName = "TableCell";
|
|
2982
|
+
function TableCellTwoLines({ primary, secondary, avatar, className, ...props }) {
|
|
2983
|
+
return /* @__PURE__ */ jsxs34("div", { className: cn("flex items-center gap-2", className), ...props, children: [
|
|
2984
|
+
avatar,
|
|
2985
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-0.5 whitespace-nowrap", children: [
|
|
2986
|
+
/* @__PURE__ */ jsx48("span", { className: "text-ui-label text-surface-foreground", children: primary }),
|
|
2987
|
+
secondary && /* @__PURE__ */ jsx48("span", { className: "text-ui-caption text-secondary-muted-foreground", children: secondary })
|
|
2988
|
+
] })
|
|
2989
|
+
] });
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
// src/components/Data Display/StatCard.tsx
|
|
2993
|
+
import * as React48 from "react";
|
|
2994
|
+
import { cva as cva6 } from "class-variance-authority";
|
|
2995
|
+
import { jsx as jsx49, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2996
|
+
var statCardVariants = cva6("flex min-w-0 flex-col gap-2 rounded-md border p-3", {
|
|
2997
|
+
variants: {
|
|
2998
|
+
variant: {
|
|
2999
|
+
default: "border-border bg-transparent",
|
|
3000
|
+
warning: "border-warning-soft-border bg-warning-soft"
|
|
3001
|
+
}
|
|
3002
|
+
},
|
|
3003
|
+
defaultVariants: { variant: "default" }
|
|
3004
|
+
});
|
|
3005
|
+
var StatCard = React48.forwardRef(
|
|
3006
|
+
({ className, variant, label, value, icon, ...props }, ref) => /* @__PURE__ */ jsxs35("div", { ref, className: cn(statCardVariants({ variant }), className), ...props, children: [
|
|
3007
|
+
/* @__PURE__ */ jsx49("p", { className: "truncate text-ui-caption text-secondary-muted-foreground", children: label }),
|
|
3008
|
+
/* @__PURE__ */ jsxs35("p", { className: "flex items-center gap-2 text-body-base text-surface-foreground", children: [
|
|
3009
|
+
icon && /* @__PURE__ */ jsx49("span", { "aria-hidden": "true", className: "inline-flex size-6 shrink-0 items-center justify-center", children: icon }),
|
|
3010
|
+
value
|
|
3011
|
+
] })
|
|
3012
|
+
] })
|
|
3013
|
+
);
|
|
3014
|
+
StatCard.displayName = "StatCard";
|
|
3015
|
+
|
|
3016
|
+
// src/components/Research-Specific/ActivityStructure.tsx
|
|
3017
|
+
import * as React50 from "react";
|
|
3018
|
+
|
|
3019
|
+
// src/components/Tags & Badges/EditableTag.tsx
|
|
3020
|
+
import * as React49 from "react";
|
|
3021
|
+
import { Crown, Plus as Plus5, X as X6 } from "@phosphor-icons/react";
|
|
3022
|
+
import { cva as cva7 } from "class-variance-authority";
|
|
3023
|
+
import { jsx as jsx50, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3024
|
+
var editableTagVariants = cva7(
|
|
3025
|
+
"inline-flex h-6.5 items-center whitespace-nowrap rounded-sm py-1 text-ui-caption transition-colors",
|
|
3026
|
+
{
|
|
3027
|
+
variants: {
|
|
3028
|
+
type: {
|
|
3029
|
+
default: "gap-1 bg-accent-muted pl-2.5 pr-1.5 text-primary",
|
|
3030
|
+
editable: "gap-1 bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 pl-2.5 pr-1.5 text-surface-foreground hover:bg-accent-soft hover:bg-none hover:text-accent-soft-foreground",
|
|
3031
|
+
add: "gap-1 border border-dashed border-border pl-2.5 pr-1.5 text-surface-foreground hover:bg-accent-soft hover:text-accent-soft-foreground",
|
|
3032
|
+
multiple: "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 px-2.5 text-surface-foreground hover:bg-accent-soft hover:bg-none hover:text-accent-soft-foreground"
|
|
3033
|
+
}
|
|
3034
|
+
},
|
|
3035
|
+
defaultVariants: { type: "default" }
|
|
3036
|
+
}
|
|
3037
|
+
);
|
|
3038
|
+
var EditableTag = React49.forwardRef(
|
|
3039
|
+
({ className, type = "default", icon, onRemove, onClick, children, ...props }, ref) => {
|
|
3040
|
+
const classes = cn(editableTagVariants({ type }), className);
|
|
3041
|
+
const leading = type === "add" ? /* @__PURE__ */ jsx50(Plus5, { size: 12, "aria-hidden": true }) : icon !== void 0 ? icon : type === "default" ? /* @__PURE__ */ jsx50(Crown, { size: 12, weight: "fill", "aria-hidden": true }) : null;
|
|
3042
|
+
if (type === "add" || type === "multiple" && onClick) {
|
|
3043
|
+
return /* @__PURE__ */ jsxs36("button", { ref, type: "button", className: classes, onClick, ...props, children: [
|
|
3044
|
+
leading,
|
|
3045
|
+
children
|
|
3046
|
+
] });
|
|
3047
|
+
}
|
|
3048
|
+
return /* @__PURE__ */ jsxs36("span", { ref, className: classes, ...props, children: [
|
|
3049
|
+
leading,
|
|
3050
|
+
children,
|
|
3051
|
+
onRemove && /* @__PURE__ */ jsx50(
|
|
3052
|
+
"button",
|
|
3053
|
+
{
|
|
3054
|
+
type: "button",
|
|
3055
|
+
"aria-label": typeof children === "string" ? `Remove ${children}` : "Remove",
|
|
3056
|
+
onClick: onRemove,
|
|
3057
|
+
className: "inline-flex size-3 items-center justify-center rounded-xs",
|
|
3058
|
+
children: /* @__PURE__ */ jsx50(X6, { size: 12, "aria-hidden": true })
|
|
3059
|
+
}
|
|
3060
|
+
)
|
|
3061
|
+
] });
|
|
3062
|
+
}
|
|
3063
|
+
);
|
|
3064
|
+
EditableTag.displayName = "EditableTag";
|
|
3065
|
+
|
|
3066
|
+
// src/components/Research-Specific/ActivityStructure.tsx
|
|
3067
|
+
import { jsx as jsx51, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3068
|
+
var ActivityStructure = React50.forwardRef(
|
|
3069
|
+
({ className, title = "Activity Structure", stats, sections, onRemoveTag, onAddTag, addTagLabel = "Add tag", ...props }, ref) => /* @__PURE__ */ jsxs37(
|
|
3070
|
+
"section",
|
|
3071
|
+
{
|
|
3072
|
+
ref,
|
|
3073
|
+
className: cn("flex w-full max-w-96.5 flex-col gap-4 rounded-2xl border border-border bg-surface p-4", className),
|
|
3074
|
+
...props,
|
|
3075
|
+
children: [
|
|
3076
|
+
/* @__PURE__ */ jsx51("h3", { className: "text-heading-h3 text-surface-foreground", children: title }),
|
|
3077
|
+
/* @__PURE__ */ jsx51("div", { className: "grid grid-cols-2 gap-3", children: stats.map(({ id, ...stat }) => /* @__PURE__ */ jsx51(StatCard, { ...stat }, id)) }),
|
|
3078
|
+
sections?.map(({ id, heading, body, tags }) => /* @__PURE__ */ jsxs37("div", { className: "flex flex-col gap-2", children: [
|
|
3079
|
+
/* @__PURE__ */ jsx51("h4", { className: "text-heading-h4 text-surface-foreground", children: heading }),
|
|
3080
|
+
/* @__PURE__ */ jsx51("p", { className: "text-body-base text-surface-foreground", children: body }),
|
|
3081
|
+
(tags?.length || onAddTag) && /* @__PURE__ */ jsxs37("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3082
|
+
tags?.map((tag) => /* @__PURE__ */ jsx51(EditableTag, { type: "editable", onRemove: onRemoveTag && (() => onRemoveTag(id, tag)), children: tag }, tag)),
|
|
3083
|
+
onAddTag && /* @__PURE__ */ jsx51(EditableTag, { type: "add", onClick: () => onAddTag(id), children: addTagLabel })
|
|
3084
|
+
] })
|
|
3085
|
+
] }, id))
|
|
3086
|
+
]
|
|
3087
|
+
}
|
|
3088
|
+
)
|
|
3089
|
+
);
|
|
3090
|
+
ActivityStructure.displayName = "ActivityStructure";
|
|
3091
|
+
|
|
3092
|
+
// src/components/Tags & Badges/RoleTag.tsx
|
|
3093
|
+
import * as React51 from "react";
|
|
3094
|
+
import { DotsSixVertical as DotsSixVertical5, RadioButton as RadioButton2 } from "@phosphor-icons/react";
|
|
3095
|
+
import { cva as cva8 } from "class-variance-authority";
|
|
3096
|
+
import { jsx as jsx52, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3097
|
+
var roleTagVariants = cva8(
|
|
3098
|
+
"group inline-flex h-6 items-center whitespace-nowrap rounded-sm py-1 text-ui-caption transition-colors",
|
|
3099
|
+
{
|
|
3100
|
+
variants: {
|
|
3101
|
+
type: {
|
|
3102
|
+
primary: "bg-primary-soft px-2.5 text-primary-soft-foreground",
|
|
3103
|
+
secondary: "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 px-2.5 text-secondary-muted-foreground",
|
|
3104
|
+
question: "gap-1 bg-primary-soft pl-1 pr-2.5 text-plum-500",
|
|
3105
|
+
interactable: "gap-1 pl-2.5 pr-2.5 hover:pl-1"
|
|
3106
|
+
},
|
|
3107
|
+
selected: { true: "", false: "" }
|
|
3108
|
+
},
|
|
3109
|
+
compoundVariants: [
|
|
3110
|
+
{
|
|
3111
|
+
type: "interactable",
|
|
3112
|
+
selected: false,
|
|
3113
|
+
className: "bg-secondary bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground"
|
|
3114
|
+
},
|
|
3115
|
+
{ type: "interactable", selected: true, className: "bg-accent-soft text-accent-foreground" }
|
|
3116
|
+
],
|
|
3117
|
+
defaultVariants: { type: "primary", selected: false }
|
|
3118
|
+
}
|
|
3119
|
+
);
|
|
3120
|
+
var RoleTag = React51.forwardRef(
|
|
3121
|
+
({ className, type = "primary", selected = false, onClick, children, ...props }, ref) => {
|
|
3122
|
+
const classes = cn(roleTagVariants({ type, selected: type === "interactable" ? selected : false }), className);
|
|
3123
|
+
if (type === "interactable") {
|
|
3124
|
+
return /* @__PURE__ */ jsxs38(
|
|
3125
|
+
"button",
|
|
3126
|
+
{
|
|
3127
|
+
ref,
|
|
3128
|
+
type: "button",
|
|
3129
|
+
"aria-pressed": selected,
|
|
3130
|
+
className: classes,
|
|
3131
|
+
onClick,
|
|
3132
|
+
...props,
|
|
3133
|
+
children: [
|
|
3134
|
+
/* @__PURE__ */ jsx52(DotsSixVertical5, { size: 16, "aria-hidden": true, className: "hidden shrink-0 group-hover:block" }),
|
|
3135
|
+
children
|
|
3136
|
+
]
|
|
3137
|
+
}
|
|
3138
|
+
);
|
|
3139
|
+
}
|
|
3140
|
+
return /* @__PURE__ */ jsxs38("span", { ref, className: classes, ...props, children: [
|
|
3141
|
+
type === "question" && /* @__PURE__ */ jsx52(RadioButton2, { size: 16, weight: "fill", "aria-hidden": true }),
|
|
3142
|
+
children
|
|
3143
|
+
] });
|
|
3144
|
+
}
|
|
3145
|
+
);
|
|
3146
|
+
RoleTag.displayName = "RoleTag";
|
|
3147
|
+
|
|
3148
|
+
// src/components/Utility/Pagination.tsx
|
|
3149
|
+
import * as React52 from "react";
|
|
3150
|
+
import { ArrowLeft, ArrowRight, DotsThree as DotsThree2 } from "@phosphor-icons/react";
|
|
3151
|
+
import { jsx as jsx53, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3152
|
+
function getPaginationItems(page, pageCount, siblings = 1) {
|
|
3153
|
+
const keep = /* @__PURE__ */ new Set([1, pageCount]);
|
|
3154
|
+
for (let p = page - siblings; p <= page + siblings; p++) if (p >= 1 && p <= pageCount) keep.add(p);
|
|
3155
|
+
const sorted = [...keep].sort((a, b) => a - b);
|
|
3156
|
+
const items = [];
|
|
3157
|
+
sorted.forEach((p, index) => {
|
|
3158
|
+
const previous = sorted[index - 1];
|
|
3159
|
+
if (previous !== void 0 && p - previous === 2) items.push(previous + 1);
|
|
3160
|
+
else if (previous !== void 0 && p - previous > 2) items.push("ellipsis");
|
|
3161
|
+
items.push(p);
|
|
3162
|
+
});
|
|
3163
|
+
return items;
|
|
3164
|
+
}
|
|
3165
|
+
var Pagination = React52.forwardRef(
|
|
3166
|
+
({ className, page, pageCount, onPageChange, variant = "full", siblings = 1, ...props }, ref) => {
|
|
3167
|
+
const go = (next2) => onPageChange(Math.min(pageCount, Math.max(1, next2)));
|
|
3168
|
+
const previous = /* @__PURE__ */ jsx53(
|
|
3169
|
+
Button,
|
|
3170
|
+
{
|
|
3171
|
+
type: "button",
|
|
3172
|
+
variant: "outline",
|
|
3173
|
+
size: "icon-sm",
|
|
3174
|
+
"aria-label": "Previous page",
|
|
3175
|
+
disabled: page <= 1,
|
|
3176
|
+
onClick: () => go(page - 1),
|
|
3177
|
+
children: /* @__PURE__ */ jsx53(ArrowLeft, { size: 16, "aria-hidden": true })
|
|
3178
|
+
}
|
|
3179
|
+
);
|
|
3180
|
+
const next = /* @__PURE__ */ jsx53(
|
|
3181
|
+
Button,
|
|
3182
|
+
{
|
|
3183
|
+
type: "button",
|
|
3184
|
+
variant: "outline",
|
|
3185
|
+
size: "icon-sm",
|
|
3186
|
+
"aria-label": "Next page",
|
|
3187
|
+
disabled: page >= pageCount,
|
|
3188
|
+
onClick: () => go(page + 1),
|
|
3189
|
+
children: /* @__PURE__ */ jsx53(ArrowRight, { size: 16, "aria-hidden": true })
|
|
3190
|
+
}
|
|
3191
|
+
);
|
|
3192
|
+
return /* @__PURE__ */ jsxs39(
|
|
3193
|
+
"nav",
|
|
3194
|
+
{
|
|
3195
|
+
ref,
|
|
3196
|
+
"aria-label": "Pagination",
|
|
3197
|
+
className: cn("flex items-center", variant === "compact" ? "w-35 justify-between" : "gap-2", className),
|
|
3198
|
+
...props,
|
|
3199
|
+
children: [
|
|
3200
|
+
previous,
|
|
3201
|
+
variant === "compact" ? /* @__PURE__ */ jsxs39("span", { className: "text-body-small text-surface-foreground", "aria-live": "polite", children: [
|
|
3202
|
+
page,
|
|
3203
|
+
"/",
|
|
3204
|
+
pageCount
|
|
3205
|
+
] }) : /* @__PURE__ */ jsx53("ul", { className: "flex items-center gap-2", children: getPaginationItems(page, pageCount, siblings).map((item, index) => /* @__PURE__ */ jsx53("li", { children: item === "ellipsis" ? /* @__PURE__ */ jsxs39("span", { className: "inline-flex size-8 items-center justify-center rounded-sm border border-border bg-surface text-surface-foreground", children: [
|
|
3206
|
+
/* @__PURE__ */ jsx53(DotsThree2, { size: 16, "aria-hidden": true }),
|
|
3207
|
+
/* @__PURE__ */ jsx53("span", { className: "sr-only", children: "More pages" })
|
|
3208
|
+
] }) : /* @__PURE__ */ jsx53(
|
|
3209
|
+
Button,
|
|
3210
|
+
{
|
|
3211
|
+
type: "button",
|
|
3212
|
+
variant: item === page ? "subtle" : "outline",
|
|
3213
|
+
size: "sm",
|
|
3214
|
+
"aria-label": `Page ${item}`,
|
|
3215
|
+
"aria-current": item === page ? "page" : void 0,
|
|
3216
|
+
onClick: () => go(item),
|
|
3217
|
+
children: item
|
|
3218
|
+
}
|
|
3219
|
+
) }, item === "ellipsis" ? `ellipsis-${index}` : item)) }),
|
|
3220
|
+
next
|
|
3221
|
+
]
|
|
3222
|
+
}
|
|
3223
|
+
);
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
Pagination.displayName = "Pagination";
|
|
3227
|
+
export {
|
|
3228
|
+
AIMiniAvatar,
|
|
3229
|
+
AIResponseContainer,
|
|
3230
|
+
ActivityStructure,
|
|
3231
|
+
AskAiInput,
|
|
3232
|
+
AskAiToggle,
|
|
3233
|
+
Button,
|
|
3234
|
+
Calendar,
|
|
3235
|
+
ChatChoices,
|
|
3236
|
+
ChatInput,
|
|
3237
|
+
ChatOption,
|
|
3238
|
+
Checkbox,
|
|
3239
|
+
CheckboxField,
|
|
3240
|
+
DatePicker,
|
|
3241
|
+
DateTimePicker,
|
|
3242
|
+
Dialog,
|
|
3243
|
+
DialogBody,
|
|
3244
|
+
DialogClose,
|
|
3245
|
+
DialogContent,
|
|
3246
|
+
DialogDescription,
|
|
3247
|
+
DialogFooter,
|
|
3248
|
+
DialogHeader,
|
|
3249
|
+
DialogTitle,
|
|
3250
|
+
DialogTrigger,
|
|
3251
|
+
DropdownMenu,
|
|
3252
|
+
DropdownMenuCheckboxItem,
|
|
3253
|
+
DropdownMenuContent,
|
|
3254
|
+
DropdownMenuGroup,
|
|
3255
|
+
DropdownMenuItem,
|
|
3256
|
+
DropdownMenuLabel,
|
|
3257
|
+
DropdownMenuRadioGroup,
|
|
3258
|
+
DropdownMenuRadioItem,
|
|
3259
|
+
DropdownMenuSeparator,
|
|
3260
|
+
DropdownMenuSub,
|
|
3261
|
+
DropdownMenuSubContent,
|
|
3262
|
+
DropdownMenuSubTrigger,
|
|
3263
|
+
DropdownMenuTrigger,
|
|
3264
|
+
EditableTag,
|
|
3265
|
+
Field,
|
|
3266
|
+
FileAttachment,
|
|
3267
|
+
FileUploadItem,
|
|
3268
|
+
FileUploadZone,
|
|
3269
|
+
Form,
|
|
3270
|
+
FormControl,
|
|
3271
|
+
FormDescription,
|
|
3272
|
+
FormField,
|
|
3273
|
+
FormItem,
|
|
3274
|
+
FormLabel,
|
|
3275
|
+
FormMessage,
|
|
3276
|
+
ImagePreview,
|
|
3277
|
+
ImageThumbnails,
|
|
3278
|
+
Input,
|
|
3279
|
+
InputWithAction,
|
|
3280
|
+
Label,
|
|
3281
|
+
MediaInfo,
|
|
3282
|
+
NumberInput,
|
|
3283
|
+
OpenEndAnswer,
|
|
3284
|
+
Pagination,
|
|
3285
|
+
Progress,
|
|
3286
|
+
ProjectSelector,
|
|
3287
|
+
QuestionCard,
|
|
3288
|
+
QuestionEditorCard,
|
|
3289
|
+
QuestionHeader,
|
|
3290
|
+
QuestionNavItem,
|
|
3291
|
+
QuestionOption,
|
|
3292
|
+
QuestionOptionEditor,
|
|
3293
|
+
QuestionOtherOption,
|
|
3294
|
+
QuestionTypeIcon,
|
|
3295
|
+
RadioGroup,
|
|
3296
|
+
RadioGroupFieldItem,
|
|
3297
|
+
RadioGroupItem,
|
|
3298
|
+
RankList,
|
|
3299
|
+
RatingScale,
|
|
3300
|
+
RoleTag,
|
|
3301
|
+
SearchBar,
|
|
3302
|
+
Select,
|
|
3303
|
+
SelectContent,
|
|
3304
|
+
SelectGroup,
|
|
3305
|
+
SelectItem,
|
|
3306
|
+
SelectTrigger,
|
|
3307
|
+
SelectValue,
|
|
3308
|
+
Slider,
|
|
3309
|
+
StatCard,
|
|
3310
|
+
StatusTag,
|
|
3311
|
+
Switch,
|
|
3312
|
+
TabItem,
|
|
3313
|
+
TabNavigation,
|
|
3314
|
+
TabNavigationContext,
|
|
3315
|
+
Table,
|
|
3316
|
+
TableBody,
|
|
3317
|
+
TableCell,
|
|
3318
|
+
TableCellTwoLines,
|
|
3319
|
+
TableHead,
|
|
3320
|
+
TableHeader,
|
|
3321
|
+
TableRow,
|
|
3322
|
+
Tabs,
|
|
3323
|
+
TabsContent,
|
|
3324
|
+
Tag,
|
|
3325
|
+
Textarea,
|
|
3326
|
+
TimeItem,
|
|
3327
|
+
TimePicker,
|
|
3328
|
+
Timestamp,
|
|
3329
|
+
Toast,
|
|
3330
|
+
ToastAction,
|
|
3331
|
+
ToastInline,
|
|
3332
|
+
ToastProvider,
|
|
3333
|
+
ToastViewport,
|
|
3334
|
+
Toggle,
|
|
3335
|
+
Tooltip,
|
|
3336
|
+
TooltipContent,
|
|
3337
|
+
TooltipProvider,
|
|
3338
|
+
TooltipTrigger,
|
|
3339
|
+
TopicActivityRow,
|
|
3340
|
+
TopicCard,
|
|
3341
|
+
TopicCardMetaItem,
|
|
3342
|
+
TopicCardTag,
|
|
3343
|
+
UserMessageBubble,
|
|
3344
|
+
VideoPlayer,
|
|
3345
|
+
VolumeControl,
|
|
3346
|
+
fieldSurfaceClasses,
|
|
3347
|
+
formatDateTime,
|
|
3348
|
+
getPaginationItems,
|
|
3349
|
+
useFormField
|
|
3350
|
+
};
|
|
3351
|
+
//# sourceMappingURL=index.js.map
|