create-newt-app 0.37.0 → 0.38.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/dist/index.js +1200 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { existsSync, promises, readdirSync } from "fs";
|
|
|
11
11
|
import path from "path";
|
|
12
12
|
import https from "node:https";
|
|
13
13
|
//#region package.json
|
|
14
|
-
var version = "0.
|
|
14
|
+
var version = "0.38.0";
|
|
15
15
|
var engines = { "node": ">=24.0.0" };
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/templates/root/index.ts
|
|
@@ -803,7 +803,7 @@ var manifest_default = {
|
|
|
803
803
|
const versions = {
|
|
804
804
|
"@babel/plugin-proposal-decorators": "^8.0.2",
|
|
805
805
|
"@babel/plugin-transform-class-properties": "^8.0.1",
|
|
806
|
-
"@base-ui/react": "^1.
|
|
806
|
+
"@base-ui/react": "^1.9.0",
|
|
807
807
|
"@eslint/js": "^9.39.1",
|
|
808
808
|
"@nestjs/cli": "^12.0.7",
|
|
809
809
|
"@nestjs/common": "^12.1.0",
|
|
@@ -815,7 +815,7 @@ const versions = {
|
|
|
815
815
|
"@next/eslint-plugin-next": "^16.4.0",
|
|
816
816
|
"@oxlint/plugins": "^1.74.0",
|
|
817
817
|
"@shadcn/lint": "^0.1.0",
|
|
818
|
-
"@shadcn/react": "^0.
|
|
818
|
+
"@shadcn/react": "^0.3.1",
|
|
819
819
|
"@stylexjs/babel-plugin": "0.19.0",
|
|
820
820
|
"@stylexjs/postcss-plugin": "0.19.0",
|
|
821
821
|
"@stylexjs/stylex": "0.19.0",
|
|
@@ -840,7 +840,7 @@ const versions = {
|
|
|
840
840
|
"class-variance-authority": "^0.7.1",
|
|
841
841
|
clsx: "^2.1.1",
|
|
842
842
|
cmdk: "^1.1.1",
|
|
843
|
-
cn: "^0.
|
|
843
|
+
cn: "^0.4.0",
|
|
844
844
|
"date-fns": "^4.2.1",
|
|
845
845
|
dotenv: "^17.3.1",
|
|
846
846
|
"dotenv-cli": "^11.0.0",
|
|
@@ -870,6 +870,7 @@ const versions = {
|
|
|
870
870
|
"reflect-metadata": "^0.2.2",
|
|
871
871
|
rxjs: "^7.8.1",
|
|
872
872
|
shadcn: "^4.7.0",
|
|
873
|
+
shiki: "^4.5.0",
|
|
873
874
|
sonner: "^2.0.7",
|
|
874
875
|
supertest: "^7.0.0",
|
|
875
876
|
"tailwind-merge": "^3.6.0",
|
|
@@ -1673,6 +1674,7 @@ const shadcnUi = {
|
|
|
1673
1674
|
"exports": {
|
|
1674
1675
|
"./globals.css": "./src/styles/globals.css",
|
|
1675
1676
|
"./postcss.config": "./postcss.config.mjs",
|
|
1677
|
+
"./lib/highlighter": "./src/lib/highlighter.tsx",
|
|
1676
1678
|
"./lib/*": "./src/lib/*.ts",
|
|
1677
1679
|
"./components/*": "./src/components/*.tsx",
|
|
1678
1680
|
"./hooks/*": "./src/hooks/*.ts",
|
|
@@ -1696,6 +1698,7 @@ const shadcnUi = {
|
|
|
1696
1698
|
"react-day-picker": "<%= versions["react-day-picker"] %>",
|
|
1697
1699
|
"react-resizable-panels": "<%= versions["react-resizable-panels"] %>",
|
|
1698
1700
|
"recharts": "<%= versions.recharts %>",
|
|
1701
|
+
"shiki": "<%= versions.shiki %>",
|
|
1699
1702
|
"sonner": "<%= versions.sonner %>",
|
|
1700
1703
|
"tw-animate-css": "<%= versions["tw-animate-css"] %>"
|
|
1701
1704
|
},
|
|
@@ -9892,6 +9895,1198 @@ export {
|
|
|
9892
9895
|
useMessageScrollerScrollable,
|
|
9893
9896
|
useMessageScrollerVisibility,
|
|
9894
9897
|
}
|
|
9898
|
+
`
|
|
9899
|
+
},
|
|
9900
|
+
{
|
|
9901
|
+
filename: "packages/ui/src/components/code-block.tsx",
|
|
9902
|
+
template: `"use client"
|
|
9903
|
+
|
|
9904
|
+
import * as React from "react"
|
|
9905
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
9906
|
+
import { cn } from "cn"
|
|
9907
|
+
|
|
9908
|
+
import { Button } from "@<%= projectName %>/ui/components/button"
|
|
9909
|
+
import { CheckIcon, CopyIcon } from "lucide-react"
|
|
9910
|
+
|
|
9911
|
+
const codeBlockVariants = cva(
|
|
9912
|
+
"group/code-block relative flex w-full min-w-0 flex-col overflow-hidden rounded-lg text-sm has-[>[data-slot=code-block-content]:focus-visible]:ring-3 has-[>[data-slot=code-block-content]:focus-visible]:ring-ring/50 data-[size=sm]:text-xs",
|
|
9913
|
+
{
|
|
9914
|
+
variants: {
|
|
9915
|
+
variant: {
|
|
9916
|
+
default:
|
|
9917
|
+
"border border-input text-foreground has-[>[data-slot=code-block-content]:focus-visible]:border-ring dark:bg-input/30",
|
|
9918
|
+
destructive:
|
|
9919
|
+
"border border-destructive/30 text-destructive dark:border-destructive/40",
|
|
9920
|
+
},
|
|
9921
|
+
},
|
|
9922
|
+
defaultVariants: {
|
|
9923
|
+
variant: "default",
|
|
9924
|
+
},
|
|
9925
|
+
}
|
|
9926
|
+
)
|
|
9927
|
+
|
|
9928
|
+
function CodeBlock({
|
|
9929
|
+
className,
|
|
9930
|
+
variant = "default",
|
|
9931
|
+
size = "default",
|
|
9932
|
+
...props
|
|
9933
|
+
}: React.ComponentProps<"div"> &
|
|
9934
|
+
VariantProps<typeof codeBlockVariants> & { size?: "default" | "sm" }) {
|
|
9935
|
+
return (
|
|
9936
|
+
<div
|
|
9937
|
+
data-slot="code-block"
|
|
9938
|
+
data-variant={variant}
|
|
9939
|
+
data-size={size}
|
|
9940
|
+
className={cn(codeBlockVariants({ variant }), className)}
|
|
9941
|
+
{...props}
|
|
9942
|
+
/>
|
|
9943
|
+
)
|
|
9944
|
+
}
|
|
9945
|
+
|
|
9946
|
+
function CodeBlockHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
9947
|
+
return (
|
|
9948
|
+
<div
|
|
9949
|
+
data-slot="code-block-header"
|
|
9950
|
+
className={cn(
|
|
9951
|
+
"flex min-w-0 shrink-0 items-center gap-2 px-3 pt-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pt-2.5 group-data-[variant=destructive]/code-block:text-destructive *:has-[>[data-slot=code-block-title]]:min-w-0",
|
|
9952
|
+
className
|
|
9953
|
+
)}
|
|
9954
|
+
{...props}
|
|
9955
|
+
/>
|
|
9956
|
+
)
|
|
9957
|
+
}
|
|
9958
|
+
|
|
9959
|
+
function CodeBlockTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
9960
|
+
return (
|
|
9961
|
+
<div
|
|
9962
|
+
data-slot="code-block-title"
|
|
9963
|
+
className={cn(
|
|
9964
|
+
"min-w-0 truncate font-sans text-sm font-medium text-foreground group-data-[size=sm]/code-block:text-xs group-data-[variant=destructive]/code-block:text-destructive [&_svg]:pointer-events-none [&_svg]:inline-block [&_svg]:align-middle [&_svg:not([class*='size-'])]:size-3.5 *:[svg]:me-1.5",
|
|
9965
|
+
className
|
|
9966
|
+
)}
|
|
9967
|
+
{...props}
|
|
9968
|
+
/>
|
|
9969
|
+
)
|
|
9970
|
+
}
|
|
9971
|
+
|
|
9972
|
+
function CodeBlockActions({
|
|
9973
|
+
className,
|
|
9974
|
+
...props
|
|
9975
|
+
}: React.ComponentProps<"div">) {
|
|
9976
|
+
return (
|
|
9977
|
+
<div
|
|
9978
|
+
data-slot="code-block-actions"
|
|
9979
|
+
className={cn(
|
|
9980
|
+
"-my-1 ms-auto -me-1.5 flex shrink-0 items-center gap-1 [[data-slot=code-block]>&]:absolute [[data-slot=code-block]>&]:end-2 [[data-slot=code-block]>&]:top-2 [[data-slot=code-block]>&]:z-10 [[data-slot=code-block]>&]:m-0 [[data-slot=code-block]>&]:opacity-0 [[data-slot=code-block]>&]:transition-opacity [[data-slot=code-block]>&]:group-focus-within/code-block:opacity-100 [[data-slot=code-block]>&]:group-hover/code-block:opacity-100 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:end-1.5 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:top-1.5 [[data-slot=code-block]>&]:pointer-coarse:opacity-100 [[data-slot=code-block]>&]:*:[button]:bg-background [[data-slot=code-block]>&]:*:[button]:ring-1 [[data-slot=code-block]>&]:*:[button]:ring-foreground/10",
|
|
9981
|
+
className
|
|
9982
|
+
)}
|
|
9983
|
+
{...props}
|
|
9984
|
+
/>
|
|
9985
|
+
)
|
|
9986
|
+
}
|
|
9987
|
+
|
|
9988
|
+
function CodeBlockCopyButton({
|
|
9989
|
+
value,
|
|
9990
|
+
variant = "ghost",
|
|
9991
|
+
size = "icon-xs",
|
|
9992
|
+
className,
|
|
9993
|
+
onClick,
|
|
9994
|
+
...props
|
|
9995
|
+
}: React.ComponentProps<typeof Button> & { value: string }) {
|
|
9996
|
+
const [copied, setCopied] = React.useState(false)
|
|
9997
|
+
|
|
9998
|
+
React.useEffect(() => {
|
|
9999
|
+
if (!copied) {
|
|
10000
|
+
return
|
|
10001
|
+
}
|
|
10002
|
+
|
|
10003
|
+
const timeout = setTimeout(() => setCopied(false), 2000)
|
|
10004
|
+
return () => clearTimeout(timeout)
|
|
10005
|
+
}, [copied])
|
|
10006
|
+
|
|
10007
|
+
return (
|
|
10008
|
+
<>
|
|
10009
|
+
<Button
|
|
10010
|
+
data-slot="code-block-copy-button"
|
|
10011
|
+
data-copied={copied || undefined}
|
|
10012
|
+
variant={variant}
|
|
10013
|
+
size={size}
|
|
10014
|
+
aria-label={copied ? "Copied" : "Copy"}
|
|
10015
|
+
className={cn(className)}
|
|
10016
|
+
onClick={(event) => {
|
|
10017
|
+
onClick?.(event)
|
|
10018
|
+
navigator.clipboard
|
|
10019
|
+
.writeText(value)
|
|
10020
|
+
.then(() => setCopied(true))
|
|
10021
|
+
.catch(() => {})
|
|
10022
|
+
}}
|
|
10023
|
+
{...props}
|
|
10024
|
+
>
|
|
10025
|
+
{copied ? (
|
|
10026
|
+
<CheckIcon
|
|
10027
|
+
/>
|
|
10028
|
+
) : (
|
|
10029
|
+
<CopyIcon
|
|
10030
|
+
/>
|
|
10031
|
+
)}
|
|
10032
|
+
</Button>
|
|
10033
|
+
<span aria-live="polite" className="sr-only">
|
|
10034
|
+
{copied ? "Copied" : ""}
|
|
10035
|
+
</span>
|
|
10036
|
+
</>
|
|
10037
|
+
)
|
|
10038
|
+
}
|
|
10039
|
+
|
|
10040
|
+
function CodeBlockContent({
|
|
10041
|
+
className,
|
|
10042
|
+
children,
|
|
10043
|
+
style,
|
|
10044
|
+
wrap = false,
|
|
10045
|
+
lineNumbers = false,
|
|
10046
|
+
startLine = 1,
|
|
10047
|
+
...props
|
|
10048
|
+
}: React.ComponentProps<"pre"> & {
|
|
10049
|
+
wrap?: boolean
|
|
10050
|
+
lineNumbers?: boolean
|
|
10051
|
+
startLine?: number
|
|
10052
|
+
}) {
|
|
10053
|
+
return (
|
|
10054
|
+
<pre
|
|
10055
|
+
data-slot="code-block-content"
|
|
10056
|
+
data-wrap={wrap || undefined}
|
|
10057
|
+
data-numbered={lineNumbers || undefined}
|
|
10058
|
+
dir="ltr"
|
|
10059
|
+
tabIndex={0}
|
|
10060
|
+
style={{ counterReset: \`line \${startLine - 1}\`, ...style }}
|
|
10061
|
+
className={cn(
|
|
10062
|
+
"min-h-0 min-w-0 scroll-fade-x scrollbar-thin overflow-auto px-3 py-3 text-start font-mono leading-relaxed outline-none group-has-data-[slot=code-block-footer]/code-block:pb-2 group-has-data-[slot=code-block-header]/code-block:pt-2 group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:py-2.5 group-data-[size=sm]/code-block:group-has-data-[slot=code-block-header]/code-block:pt-1.5 data-wrap:scroll-fade-y data-wrap:wrap-break-word data-wrap:whitespace-pre-wrap",
|
|
10063
|
+
className
|
|
10064
|
+
)}
|
|
10065
|
+
{...props}
|
|
10066
|
+
>
|
|
10067
|
+
<code
|
|
10068
|
+
data-slot="code-block-code"
|
|
10069
|
+
className="grid min-h-lh min-w-max content-start in-data-numbered:grid-cols-[auto_1fr] in-data-wrap:min-w-0"
|
|
10070
|
+
>
|
|
10071
|
+
{lineNumbers && typeof children === "string"
|
|
10072
|
+
? children
|
|
10073
|
+
.replace(/\\n$/, "")
|
|
10074
|
+
.split("\\n")
|
|
10075
|
+
.map((line, index) => (
|
|
10076
|
+
<CodeBlockLine key={index}>{line}</CodeBlockLine>
|
|
10077
|
+
))
|
|
10078
|
+
: children}
|
|
10079
|
+
</code>
|
|
10080
|
+
</pre>
|
|
10081
|
+
)
|
|
10082
|
+
}
|
|
10083
|
+
|
|
10084
|
+
const codeBlockLineVariants = cva(
|
|
10085
|
+
"relative -mx-3 block min-h-lh px-3 group-data-[size=sm]/code-block:-mx-2.5 group-data-[size=sm]/code-block:px-2.5 before:min-w-6 before:text-end before:text-muted-foreground after:absolute after:start-1 after:top-0 after:text-muted-foreground after:select-none in-data-numbered:col-span-2 in-data-numbered:grid in-data-numbered:grid-cols-subgrid in-data-numbered:gap-x-3 in-data-numbered:[counter-increment:line] in-data-numbered:before:content-[counter(line)] in-data-numbered:before:select-none in-data-numbered:supports-[content:counter(line)_/_'']:before:content-[counter(line)_/_'']",
|
|
10086
|
+
{
|
|
10087
|
+
variants: {
|
|
10088
|
+
variant: {
|
|
10089
|
+
default: "",
|
|
10090
|
+
added: "bg-muted after:content-['+']",
|
|
10091
|
+
removed: "bg-destructive/10 after:text-destructive after:content-['−']",
|
|
10092
|
+
highlighted: "bg-muted",
|
|
10093
|
+
},
|
|
10094
|
+
},
|
|
10095
|
+
defaultVariants: {
|
|
10096
|
+
variant: "default",
|
|
10097
|
+
},
|
|
10098
|
+
}
|
|
10099
|
+
)
|
|
10100
|
+
|
|
10101
|
+
function CodeBlockLine({
|
|
10102
|
+
className,
|
|
10103
|
+
variant = "default",
|
|
10104
|
+
children,
|
|
10105
|
+
...props
|
|
10106
|
+
}: React.ComponentProps<"span"> & VariantProps<typeof codeBlockLineVariants>) {
|
|
10107
|
+
// An empty line holds a newline so copying a selection keeps blank lines.
|
|
10108
|
+
const empty =
|
|
10109
|
+
children === undefined ||
|
|
10110
|
+
children === null ||
|
|
10111
|
+
children === "" ||
|
|
10112
|
+
(Array.isArray(children) && children.length === 0)
|
|
10113
|
+
|
|
10114
|
+
return (
|
|
10115
|
+
<span
|
|
10116
|
+
data-slot="code-block-line"
|
|
10117
|
+
data-variant={variant}
|
|
10118
|
+
className={cn(codeBlockLineVariants({ variant }), className)}
|
|
10119
|
+
{...props}
|
|
10120
|
+
>
|
|
10121
|
+
<span data-slot="code-block-line-content" className="min-w-0">
|
|
10122
|
+
{empty ? "\\n" : children}
|
|
10123
|
+
</span>
|
|
10124
|
+
</span>
|
|
10125
|
+
)
|
|
10126
|
+
}
|
|
10127
|
+
|
|
10128
|
+
function CodeBlockFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
10129
|
+
return (
|
|
10130
|
+
<div
|
|
10131
|
+
data-slot="code-block-footer"
|
|
10132
|
+
className={cn(
|
|
10133
|
+
"flex min-w-0 shrink-0 items-center gap-2 px-3 pb-3 text-muted-foreground group-data-[size=sm]/code-block:px-2.5 group-data-[size=sm]/code-block:pb-2.5",
|
|
10134
|
+
className
|
|
10135
|
+
)}
|
|
10136
|
+
{...props}
|
|
10137
|
+
/>
|
|
10138
|
+
)
|
|
10139
|
+
}
|
|
10140
|
+
|
|
10141
|
+
export {
|
|
10142
|
+
CodeBlock,
|
|
10143
|
+
CodeBlockHeader,
|
|
10144
|
+
CodeBlockTitle,
|
|
10145
|
+
CodeBlockActions,
|
|
10146
|
+
CodeBlockCopyButton,
|
|
10147
|
+
CodeBlockContent,
|
|
10148
|
+
CodeBlockLine,
|
|
10149
|
+
CodeBlockFooter,
|
|
10150
|
+
}
|
|
10151
|
+
`
|
|
10152
|
+
},
|
|
10153
|
+
{
|
|
10154
|
+
filename: "packages/ui/src/components/questionnaire.tsx",
|
|
10155
|
+
template: `"use client"
|
|
10156
|
+
|
|
10157
|
+
import * as React from "react"
|
|
10158
|
+
import { Questionnaire as QuestionnairePrimitive } from "@shadcn/react/questionnaire"
|
|
10159
|
+
import { cn } from "cn"
|
|
10160
|
+
|
|
10161
|
+
import { buttonVariants, type Button } from "@<%= projectName %>/ui/components/button"
|
|
10162
|
+
import { CheckIcon } from "lucide-react"
|
|
10163
|
+
|
|
10164
|
+
function Questionnaire({
|
|
10165
|
+
className,
|
|
10166
|
+
...props
|
|
10167
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Root>) {
|
|
10168
|
+
return (
|
|
10169
|
+
<QuestionnairePrimitive.Root
|
|
10170
|
+
data-slot="questionnaire"
|
|
10171
|
+
className={cn("flex w-full min-w-0 flex-col gap-4", className)}
|
|
10172
|
+
{...props}
|
|
10173
|
+
/>
|
|
10174
|
+
)
|
|
10175
|
+
}
|
|
10176
|
+
|
|
10177
|
+
function QuestionnaireProgress({
|
|
10178
|
+
className,
|
|
10179
|
+
...props
|
|
10180
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Progress>) {
|
|
10181
|
+
return (
|
|
10182
|
+
<QuestionnairePrimitive.Progress
|
|
10183
|
+
data-slot="questionnaire-progress"
|
|
10184
|
+
className={cn(
|
|
10185
|
+
"min-h-[1lh] w-fit min-w-[14ch] text-xs font-medium text-muted-foreground tabular-nums",
|
|
10186
|
+
className
|
|
10187
|
+
)}
|
|
10188
|
+
{...props}
|
|
10189
|
+
/>
|
|
10190
|
+
)
|
|
10191
|
+
}
|
|
10192
|
+
|
|
10193
|
+
function QuestionnaireItem({
|
|
10194
|
+
className,
|
|
10195
|
+
...props
|
|
10196
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Item>) {
|
|
10197
|
+
return (
|
|
10198
|
+
<QuestionnairePrimitive.Item
|
|
10199
|
+
data-slot="questionnaire-item"
|
|
10200
|
+
className={cn(
|
|
10201
|
+
"flex min-w-0 flex-col gap-4 border-0 p-0 outline-none",
|
|
10202
|
+
className
|
|
10203
|
+
)}
|
|
10204
|
+
{...props}
|
|
10205
|
+
/>
|
|
10206
|
+
)
|
|
10207
|
+
}
|
|
10208
|
+
|
|
10209
|
+
function QuestionnaireTitle({
|
|
10210
|
+
className,
|
|
10211
|
+
...props
|
|
10212
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Title>) {
|
|
10213
|
+
return (
|
|
10214
|
+
<QuestionnairePrimitive.Title
|
|
10215
|
+
data-slot="questionnaire-title"
|
|
10216
|
+
className={cn(
|
|
10217
|
+
"text-base leading-snug font-medium text-pretty [&:not(:has(~[data-slot=questionnaire-description]))]:mb-4",
|
|
10218
|
+
className
|
|
10219
|
+
)}
|
|
10220
|
+
{...props}
|
|
10221
|
+
/>
|
|
10222
|
+
)
|
|
10223
|
+
}
|
|
10224
|
+
|
|
10225
|
+
function QuestionnaireDescription({
|
|
10226
|
+
className,
|
|
10227
|
+
...props
|
|
10228
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Description>) {
|
|
10229
|
+
return (
|
|
10230
|
+
<QuestionnairePrimitive.Description
|
|
10231
|
+
data-slot="questionnaire-description"
|
|
10232
|
+
className={cn("text-sm text-pretty text-muted-foreground", className)}
|
|
10233
|
+
{...props}
|
|
10234
|
+
/>
|
|
10235
|
+
)
|
|
10236
|
+
}
|
|
10237
|
+
|
|
10238
|
+
function QuestionnaireChoices({
|
|
10239
|
+
className,
|
|
10240
|
+
...props
|
|
10241
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Choices>) {
|
|
10242
|
+
return (
|
|
10243
|
+
<QuestionnairePrimitive.Choices
|
|
10244
|
+
data-slot="questionnaire-choices"
|
|
10245
|
+
className={cn(
|
|
10246
|
+
"group/questionnaire-choices grid min-w-0 gap-2",
|
|
10247
|
+
className
|
|
10248
|
+
)}
|
|
10249
|
+
{...props}
|
|
10250
|
+
/>
|
|
10251
|
+
)
|
|
10252
|
+
}
|
|
10253
|
+
|
|
10254
|
+
function QuestionnaireChoice({
|
|
10255
|
+
children,
|
|
10256
|
+
className,
|
|
10257
|
+
...props
|
|
10258
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Choice>) {
|
|
10259
|
+
return (
|
|
10260
|
+
<QuestionnairePrimitive.Choice
|
|
10261
|
+
data-slot="questionnaire-choice"
|
|
10262
|
+
className={cn(
|
|
10263
|
+
"group/questionnaire-choice relative flex min-h-11 cursor-pointer items-start gap-2.5 rounded-lg border border-input bg-transparent px-3 py-2.5 text-start text-sm transition-colors outline-none select-none hover:bg-muted/50 has-[>input:focus-visible]:border-ring has-[>input:focus-visible]:ring-3 has-[>input:focus-visible]:ring-ring/50 data-invalid:border-destructive dark:bg-input/20 data-checked:border-primary/40 data-checked:bg-muted dark:data-checked:bg-muted",
|
|
10264
|
+
"data-disabled:pointer-events-none data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
10265
|
+
className
|
|
10266
|
+
)}
|
|
10267
|
+
{...props}
|
|
10268
|
+
>
|
|
10269
|
+
<QuestionnairePrimitive.ChoiceInput
|
|
10270
|
+
data-slot="questionnaire-choice-input"
|
|
10271
|
+
className="absolute inset-0 z-10 size-full cursor-pointer opacity-0"
|
|
10272
|
+
/>
|
|
10273
|
+
<span
|
|
10274
|
+
aria-hidden="true"
|
|
10275
|
+
data-slot="questionnaire-choice-indicator"
|
|
10276
|
+
className="pointer-events-none relative flex size-4 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-[4px] border border-input group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[type=radio]/questionnaire-choice:rounded-full group-data-checked/questionnaire-choice:border-primary group-data-checked/questionnaire-choice:bg-primary group-data-checked/questionnaire-choice:text-primary-foreground dark:bg-input/30 dark:group-data-checked/questionnaire-choice:bg-primary"
|
|
10277
|
+
>
|
|
10278
|
+
<span
|
|
10279
|
+
data-slot="questionnaire-choice-indicator-dot"
|
|
10280
|
+
className="hidden size-2 rounded-full bg-primary-foreground group-data-[type=checkbox]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block"
|
|
10281
|
+
/>
|
|
10282
|
+
<CheckIcon data-slot="questionnaire-choice-indicator-check" className="hidden size-3.5 group-data-[type=radio]/questionnaire-choice:hidden group-data-checked/questionnaire-choice:block" />
|
|
10283
|
+
</span>
|
|
10284
|
+
<QuestionnairePrimitive.ChoiceLabel
|
|
10285
|
+
data-slot="questionnaire-choice-label"
|
|
10286
|
+
className="flex min-w-0 flex-1 flex-col gap-0.5 leading-snug"
|
|
10287
|
+
>
|
|
10288
|
+
{children}
|
|
10289
|
+
</QuestionnairePrimitive.ChoiceLabel>
|
|
10290
|
+
<QuestionnairePrimitive.ChoiceShortcut
|
|
10291
|
+
data-slot="questionnaire-choice-shortcut"
|
|
10292
|
+
className="pointer-events-none ms-auto hidden size-5 shrink-0 translate-y-[--spacing(0.45)] items-center justify-center rounded-md border border-input bg-background font-mono text-[0.625rem] leading-none font-medium text-muted-foreground group-has-data-[slot=questionnaire-choice-description]/questionnaire-choice:translate-y-0.5 group-data-[shortcut]/questionnaire-choice:inline-flex"
|
|
10293
|
+
/>
|
|
10294
|
+
</QuestionnairePrimitive.Choice>
|
|
10295
|
+
)
|
|
10296
|
+
}
|
|
10297
|
+
|
|
10298
|
+
function QuestionnaireChoiceDescription({
|
|
10299
|
+
className,
|
|
10300
|
+
...props
|
|
10301
|
+
}: React.ComponentProps<"span">) {
|
|
10302
|
+
return (
|
|
10303
|
+
<span
|
|
10304
|
+
data-slot="questionnaire-choice-description"
|
|
10305
|
+
className={cn("text-muted-foreground", className)}
|
|
10306
|
+
{...props}
|
|
10307
|
+
/>
|
|
10308
|
+
)
|
|
10309
|
+
}
|
|
10310
|
+
|
|
10311
|
+
function QuestionnaireInput({
|
|
10312
|
+
className,
|
|
10313
|
+
...props
|
|
10314
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Input>) {
|
|
10315
|
+
return (
|
|
10316
|
+
<div
|
|
10317
|
+
data-slot="questionnaire-input-wrapper"
|
|
10318
|
+
className="group/questionnaire-input relative w-full min-w-0"
|
|
10319
|
+
>
|
|
10320
|
+
<QuestionnairePrimitive.Input
|
|
10321
|
+
data-slot="questionnaire-input"
|
|
10322
|
+
className={cn(
|
|
10323
|
+
"h-8 min-h-11 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-[color,box-shadow,background-color] outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 sm:min-h-0 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
10324
|
+
"selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground",
|
|
10325
|
+
className
|
|
10326
|
+
)}
|
|
10327
|
+
{...props}
|
|
10328
|
+
/>
|
|
10329
|
+
</div>
|
|
10330
|
+
)
|
|
10331
|
+
}
|
|
10332
|
+
|
|
10333
|
+
function QuestionnaireError({
|
|
10334
|
+
className,
|
|
10335
|
+
...props
|
|
10336
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Error>) {
|
|
10337
|
+
return (
|
|
10338
|
+
<QuestionnairePrimitive.Error
|
|
10339
|
+
data-slot="questionnaire-error"
|
|
10340
|
+
className={cn("mt-2 text-sm text-destructive", className)}
|
|
10341
|
+
{...props}
|
|
10342
|
+
/>
|
|
10343
|
+
)
|
|
10344
|
+
}
|
|
10345
|
+
|
|
10346
|
+
function QuestionnaireActions({
|
|
10347
|
+
className,
|
|
10348
|
+
...props
|
|
10349
|
+
}: React.ComponentProps<"div">) {
|
|
10350
|
+
return (
|
|
10351
|
+
<div
|
|
10352
|
+
data-slot="questionnaire-actions"
|
|
10353
|
+
className={cn(
|
|
10354
|
+
"grid min-h-11 w-full grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-2 sm:min-h-8",
|
|
10355
|
+
className
|
|
10356
|
+
)}
|
|
10357
|
+
{...props}
|
|
10358
|
+
/>
|
|
10359
|
+
)
|
|
10360
|
+
}
|
|
10361
|
+
|
|
10362
|
+
function QuestionnairePrevious({
|
|
10363
|
+
children,
|
|
10364
|
+
className,
|
|
10365
|
+
size = "default",
|
|
10366
|
+
variant = "outline",
|
|
10367
|
+
...props
|
|
10368
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Previous> &
|
|
10369
|
+
Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
|
|
10370
|
+
return (
|
|
10371
|
+
<QuestionnairePrimitive.Previous
|
|
10372
|
+
data-slot="questionnaire-previous"
|
|
10373
|
+
data-size={size}
|
|
10374
|
+
data-variant={variant}
|
|
10375
|
+
className={cn(
|
|
10376
|
+
buttonVariants({ size, variant }),
|
|
10377
|
+
"col-start-1 row-start-1 min-h-11 justify-self-start sm:min-h-0",
|
|
10378
|
+
className
|
|
10379
|
+
)}
|
|
10380
|
+
{...props}
|
|
10381
|
+
>
|
|
10382
|
+
{children ?? "Previous"}
|
|
10383
|
+
</QuestionnairePrimitive.Previous>
|
|
10384
|
+
)
|
|
10385
|
+
}
|
|
10386
|
+
|
|
10387
|
+
function QuestionnaireSkip({
|
|
10388
|
+
children,
|
|
10389
|
+
className,
|
|
10390
|
+
size = "default",
|
|
10391
|
+
variant = "outline",
|
|
10392
|
+
...props
|
|
10393
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Skip> &
|
|
10394
|
+
Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
|
|
10395
|
+
return (
|
|
10396
|
+
<QuestionnairePrimitive.Skip
|
|
10397
|
+
data-slot="questionnaire-skip"
|
|
10398
|
+
data-size={size}
|
|
10399
|
+
data-variant={variant}
|
|
10400
|
+
className={cn(
|
|
10401
|
+
buttonVariants({ size, variant }),
|
|
10402
|
+
"col-start-2 row-start-1 min-h-11 justify-self-end sm:min-h-0",
|
|
10403
|
+
className
|
|
10404
|
+
)}
|
|
10405
|
+
{...props}
|
|
10406
|
+
>
|
|
10407
|
+
{children ?? "Skip"}
|
|
10408
|
+
</QuestionnairePrimitive.Skip>
|
|
10409
|
+
)
|
|
10410
|
+
}
|
|
10411
|
+
|
|
10412
|
+
function QuestionnaireNext({
|
|
10413
|
+
children,
|
|
10414
|
+
className,
|
|
10415
|
+
size = "default",
|
|
10416
|
+
variant = "default",
|
|
10417
|
+
...props
|
|
10418
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Next> &
|
|
10419
|
+
Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
|
|
10420
|
+
return (
|
|
10421
|
+
<QuestionnairePrimitive.Next
|
|
10422
|
+
data-slot="questionnaire-next"
|
|
10423
|
+
data-size={size}
|
|
10424
|
+
data-variant={variant}
|
|
10425
|
+
className={cn(
|
|
10426
|
+
buttonVariants({ size, variant }),
|
|
10427
|
+
"col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0",
|
|
10428
|
+
className
|
|
10429
|
+
)}
|
|
10430
|
+
{...props}
|
|
10431
|
+
>
|
|
10432
|
+
{children ?? "Next"}
|
|
10433
|
+
</QuestionnairePrimitive.Next>
|
|
10434
|
+
)
|
|
10435
|
+
}
|
|
10436
|
+
|
|
10437
|
+
function QuestionnaireSubmit({
|
|
10438
|
+
children,
|
|
10439
|
+
className,
|
|
10440
|
+
size = "default",
|
|
10441
|
+
variant = "default",
|
|
10442
|
+
...props
|
|
10443
|
+
}: React.ComponentProps<typeof QuestionnairePrimitive.Submit> &
|
|
10444
|
+
Pick<React.ComponentProps<typeof Button>, "size" | "variant">) {
|
|
10445
|
+
return (
|
|
10446
|
+
<QuestionnairePrimitive.Submit
|
|
10447
|
+
data-slot="questionnaire-submit"
|
|
10448
|
+
data-size={size}
|
|
10449
|
+
data-variant={variant}
|
|
10450
|
+
className={cn(
|
|
10451
|
+
buttonVariants({ size, variant }),
|
|
10452
|
+
"col-start-3 row-start-1 min-h-11 justify-self-end sm:min-h-0",
|
|
10453
|
+
className
|
|
10454
|
+
)}
|
|
10455
|
+
{...props}
|
|
10456
|
+
>
|
|
10457
|
+
{children ?? "Submit"}
|
|
10458
|
+
</QuestionnairePrimitive.Submit>
|
|
10459
|
+
)
|
|
10460
|
+
}
|
|
10461
|
+
|
|
10462
|
+
export {
|
|
10463
|
+
Questionnaire,
|
|
10464
|
+
QuestionnaireActions,
|
|
10465
|
+
QuestionnaireChoice,
|
|
10466
|
+
QuestionnaireChoiceDescription,
|
|
10467
|
+
QuestionnaireChoices,
|
|
10468
|
+
QuestionnaireDescription,
|
|
10469
|
+
QuestionnaireError,
|
|
10470
|
+
QuestionnaireInput,
|
|
10471
|
+
QuestionnaireItem,
|
|
10472
|
+
QuestionnaireNext,
|
|
10473
|
+
QuestionnairePrevious,
|
|
10474
|
+
QuestionnaireProgress,
|
|
10475
|
+
QuestionnaireSkip,
|
|
10476
|
+
QuestionnaireSubmit,
|
|
10477
|
+
QuestionnaireTitle,
|
|
10478
|
+
}
|
|
10479
|
+
`
|
|
10480
|
+
},
|
|
10481
|
+
{
|
|
10482
|
+
filename: "packages/ui/src/components/trace.tsx",
|
|
10483
|
+
template: `import * as React from "react"
|
|
10484
|
+
import { cn } from "cn"
|
|
10485
|
+
|
|
10486
|
+
import {
|
|
10487
|
+
Collapsible,
|
|
10488
|
+
CollapsibleContent,
|
|
10489
|
+
CollapsibleTrigger,
|
|
10490
|
+
} from "@<%= projectName %>/ui/components/collapsible"
|
|
10491
|
+
import { ChevronRightIcon } from "lucide-react"
|
|
10492
|
+
|
|
10493
|
+
function Trace({ className, ...props }: React.ComponentProps<"div">) {
|
|
10494
|
+
return (
|
|
10495
|
+
<div
|
|
10496
|
+
data-slot="trace"
|
|
10497
|
+
className={cn(
|
|
10498
|
+
"flex w-full min-w-0 flex-col gap-2 *:has-[>[data-slot=trace-line]]:flex *:has-[>[data-slot=trace-line]]:w-fit *:has-[>[data-slot=trace-line]]:max-w-full *:has-[>[data-slot=trace-line]]:min-w-0 *:has-[>[data-slot=trace-line]]:rounded-md *:has-[>[data-slot=trace-line]]:text-left *:has-[>[data-slot=trace-line]]:outline-none *:has-[>[data-slot=trace-line]]:focus-visible:ring-3 *:has-[>[data-slot=trace-line]]:focus-visible:ring-ring/50",
|
|
10499
|
+
className
|
|
10500
|
+
)}
|
|
10501
|
+
{...props}
|
|
10502
|
+
/>
|
|
10503
|
+
)
|
|
10504
|
+
}
|
|
10505
|
+
|
|
10506
|
+
function TraceLine({
|
|
10507
|
+
className,
|
|
10508
|
+
status,
|
|
10509
|
+
...props
|
|
10510
|
+
}: React.ComponentProps<"span"> & {
|
|
10511
|
+
status?: "running" | "error" | "pending"
|
|
10512
|
+
}) {
|
|
10513
|
+
return (
|
|
10514
|
+
<span
|
|
10515
|
+
data-slot="trace-line"
|
|
10516
|
+
data-status={status}
|
|
10517
|
+
className={cn(
|
|
10518
|
+
"flex w-fit max-w-full min-w-0 items-center gap-2 text-sm text-muted-foreground transition-colors in-[a,button]:cursor-pointer in-[a:hover,button:hover]:text-foreground data-[status=error]:text-destructive data-[status=error]:in-[a:hover,button:hover]:text-destructive data-[status=pending]:opacity-60 data-[status=running]:*:data-[slot=trace-title]:shimmer",
|
|
10519
|
+
className
|
|
10520
|
+
)}
|
|
10521
|
+
{...props}
|
|
10522
|
+
/>
|
|
10523
|
+
)
|
|
10524
|
+
}
|
|
10525
|
+
|
|
10526
|
+
function TraceIcon({ className, ...props }: React.ComponentProps<"span">) {
|
|
10527
|
+
return (
|
|
10528
|
+
<span
|
|
10529
|
+
data-slot="trace-icon"
|
|
10530
|
+
aria-hidden="true"
|
|
10531
|
+
className={cn(
|
|
10532
|
+
"flex size-4 shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [[data-slot=trace-title]~&]:-ml-1",
|
|
10533
|
+
className
|
|
10534
|
+
)}
|
|
10535
|
+
{...props}
|
|
10536
|
+
/>
|
|
10537
|
+
)
|
|
10538
|
+
}
|
|
10539
|
+
|
|
10540
|
+
function TraceTitle({ className, ...props }: React.ComponentProps<"span">) {
|
|
10541
|
+
return (
|
|
10542
|
+
<span
|
|
10543
|
+
data-slot="trace-title"
|
|
10544
|
+
className={cn("min-w-0 truncate motion-reduce:shimmer-none", className)}
|
|
10545
|
+
{...props}
|
|
10546
|
+
/>
|
|
10547
|
+
)
|
|
10548
|
+
}
|
|
10549
|
+
|
|
10550
|
+
function TraceDescription({
|
|
10551
|
+
className,
|
|
10552
|
+
...props
|
|
10553
|
+
}: React.ComponentProps<"span">) {
|
|
10554
|
+
return (
|
|
10555
|
+
<span
|
|
10556
|
+
data-slot="trace-description"
|
|
10557
|
+
className={cn(
|
|
10558
|
+
"shrink-0 text-muted-foreground/70 tabular-nums",
|
|
10559
|
+
className
|
|
10560
|
+
)}
|
|
10561
|
+
{...props}
|
|
10562
|
+
/>
|
|
10563
|
+
)
|
|
10564
|
+
}
|
|
10565
|
+
|
|
10566
|
+
function TraceCollapsible({
|
|
10567
|
+
className,
|
|
10568
|
+
...props
|
|
10569
|
+
}: Omit<React.ComponentProps<typeof Collapsible>, "open"> &
|
|
10570
|
+
(
|
|
10571
|
+
| { open?: undefined }
|
|
10572
|
+
| {
|
|
10573
|
+
open: boolean
|
|
10574
|
+
onOpenChange: NonNullable<
|
|
10575
|
+
React.ComponentProps<typeof Collapsible>["onOpenChange"]
|
|
10576
|
+
>
|
|
10577
|
+
}
|
|
10578
|
+
)) {
|
|
10579
|
+
return (
|
|
10580
|
+
<Collapsible
|
|
10581
|
+
data-slot="trace-collapsible"
|
|
10582
|
+
className={cn("flex w-full min-w-0 flex-col", className)}
|
|
10583
|
+
{...props}
|
|
10584
|
+
/>
|
|
10585
|
+
)
|
|
10586
|
+
}
|
|
10587
|
+
|
|
10588
|
+
function TraceCollapsibleTrigger({
|
|
10589
|
+
className,
|
|
10590
|
+
children,
|
|
10591
|
+
...props
|
|
10592
|
+
}: React.ComponentProps<typeof CollapsibleTrigger>) {
|
|
10593
|
+
return (
|
|
10594
|
+
<CollapsibleTrigger
|
|
10595
|
+
data-slot="trace-collapsible-trigger"
|
|
10596
|
+
className={cn(
|
|
10597
|
+
"group/trace-collapsible-trigger flex w-fit max-w-full min-w-0 cursor-pointer items-center gap-1 rounded-md text-left text-muted-foreground transition-colors outline-none hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 has-[[data-status=error]]:text-destructive",
|
|
10598
|
+
className
|
|
10599
|
+
)}
|
|
10600
|
+
{...props}
|
|
10601
|
+
>
|
|
10602
|
+
{children}
|
|
10603
|
+
<TraceIcon className="transition-transform group-aria-expanded/trace-collapsible-trigger:rotate-90">
|
|
10604
|
+
<ChevronRightIcon
|
|
10605
|
+
/>
|
|
10606
|
+
</TraceIcon>
|
|
10607
|
+
</CollapsibleTrigger>
|
|
10608
|
+
)
|
|
10609
|
+
}
|
|
10610
|
+
|
|
10611
|
+
function TraceCollapsibleContent({
|
|
10612
|
+
className,
|
|
10613
|
+
children,
|
|
10614
|
+
...props
|
|
10615
|
+
}: React.ComponentProps<typeof CollapsibleContent>) {
|
|
10616
|
+
return (
|
|
10617
|
+
<CollapsibleContent
|
|
10618
|
+
data-slot="trace-collapsible-content"
|
|
10619
|
+
className="h-(--collapsible-panel-height) min-w-0 overflow-hidden transition-[height] duration-200 data-ending-style:h-0 data-starting-style:h-0"
|
|
10620
|
+
{...props}
|
|
10621
|
+
>
|
|
10622
|
+
<div
|
|
10623
|
+
data-slot="trace-collapsible-content-inner"
|
|
10624
|
+
className={cn(
|
|
10625
|
+
"mt-2 mb-1 ml-[calc(--spacing(2)-1px)] min-w-0 border-l pr-1 pl-4 leading-relaxed wrap-break-word text-muted-foreground",
|
|
10626
|
+
className
|
|
10627
|
+
)}
|
|
10628
|
+
>
|
|
10629
|
+
{children}
|
|
10630
|
+
</div>
|
|
10631
|
+
</CollapsibleContent>
|
|
10632
|
+
)
|
|
10633
|
+
}
|
|
10634
|
+
|
|
10635
|
+
export {
|
|
10636
|
+
Trace,
|
|
10637
|
+
TraceLine,
|
|
10638
|
+
TraceIcon,
|
|
10639
|
+
TraceTitle,
|
|
10640
|
+
TraceDescription,
|
|
10641
|
+
TraceCollapsible,
|
|
10642
|
+
TraceCollapsibleTrigger,
|
|
10643
|
+
TraceCollapsibleContent,
|
|
10644
|
+
}
|
|
10645
|
+
`
|
|
10646
|
+
},
|
|
10647
|
+
{
|
|
10648
|
+
filename: "packages/ui/src/components/toast.tsx",
|
|
10649
|
+
template: `"use client"
|
|
10650
|
+
|
|
10651
|
+
import * as React from "react"
|
|
10652
|
+
import { Toast as ToastPrimitive } from "@base-ui/react/toast"
|
|
10653
|
+
import { cn } from "cn"
|
|
10654
|
+
|
|
10655
|
+
import { Button } from "@<%= projectName %>/ui/components/button"
|
|
10656
|
+
import { XIcon, CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
|
|
10657
|
+
|
|
10658
|
+
const toast = ToastPrimitive.createToastManager()
|
|
10659
|
+
|
|
10660
|
+
function ToastProvider({ ...props }: ToastPrimitive.Provider.Props) {
|
|
10661
|
+
return <ToastPrimitive.Provider {...props} />
|
|
10662
|
+
}
|
|
10663
|
+
|
|
10664
|
+
function ToastPortal({ ...props }: ToastPrimitive.Portal.Props) {
|
|
10665
|
+
return <ToastPrimitive.Portal data-slot="toast-portal" {...props} />
|
|
10666
|
+
}
|
|
10667
|
+
|
|
10668
|
+
function ToastViewport({ className, ...props }: ToastPrimitive.Viewport.Props) {
|
|
10669
|
+
return (
|
|
10670
|
+
<ToastPrimitive.Viewport
|
|
10671
|
+
data-slot="toast-viewport"
|
|
10672
|
+
className={cn(
|
|
10673
|
+
"pointer-events-none fixed inset-x-4 bottom-4 z-50 mx-auto w-auto max-w-sm outline-none sm:right-4 sm:left-auto sm:mx-0 sm:w-full",
|
|
10674
|
+
className
|
|
10675
|
+
)}
|
|
10676
|
+
{...props}
|
|
10677
|
+
/>
|
|
10678
|
+
)
|
|
10679
|
+
}
|
|
10680
|
+
|
|
10681
|
+
function Toast({ className, ...props }: ToastPrimitive.Root.Props) {
|
|
10682
|
+
return (
|
|
10683
|
+
<ToastPrimitive.Root
|
|
10684
|
+
data-slot="toast"
|
|
10685
|
+
className={cn(
|
|
10686
|
+
"group/toast pointer-events-auto absolute right-0 bottom-0 z-[calc(1000-var(--toast-index))] w-full origin-bottom rounded-2xl border bg-popover text-popover-foreground shadow-lg will-change-transform outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
10687
|
+
"[--gap:0.75rem] [--height:var(--toast-frontmost-height,var(--toast-height))] [--offset-y:calc(var(--toast-offset-y)*-1+calc(var(--toast-index)*var(--gap)*-1)+var(--toast-swipe-movement-y))] [--peek:0.75rem] [--scale:calc(max(0,1-(var(--toast-index)*0.1)))] [--shrink:calc(1-var(--scale))]",
|
|
10688
|
+
"h-(--height) [transform:translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)-(var(--toast-index)*var(--peek))-(var(--shrink)*var(--height))))_scale(var(--scale))] [transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms]",
|
|
10689
|
+
"after:absolute after:top-full after:left-0 after:h-[calc(var(--gap)+1px)] after:w-full after:content-['']",
|
|
10690
|
+
"data-expanded:h-(--toast-height) data-expanded:[transform:translateX(var(--toast-swipe-movement-x))_translateY(var(--offset-y))]",
|
|
10691
|
+
"data-limited:opacity-0 data-starting-style:[transform:translateY(150%)]",
|
|
10692
|
+
"[&[data-ending-style]:not([data-limited]):not([data-swipe-direction])]:[transform:translateY(150%)]",
|
|
10693
|
+
"data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
|
|
10694
|
+
"data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
|
|
10695
|
+
"data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
|
|
10696
|
+
"data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
|
|
10697
|
+
"data-expanded:data-ending-style:data-[swipe-direction=down]:[transform:translateY(calc(var(--toast-swipe-movement-y)+150%))]",
|
|
10698
|
+
"data-expanded:data-ending-style:data-[swipe-direction=left]:[transform:translateX(calc(var(--toast-swipe-movement-x)-150%))_translateY(var(--offset-y))]",
|
|
10699
|
+
"data-expanded:data-ending-style:data-[swipe-direction=right]:[transform:translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--offset-y))]",
|
|
10700
|
+
"data-expanded:data-ending-style:data-[swipe-direction=up]:[transform:translateY(calc(var(--toast-swipe-movement-y)-150%))]",
|
|
10701
|
+
className
|
|
10702
|
+
)}
|
|
10703
|
+
{...props}
|
|
10704
|
+
/>
|
|
10705
|
+
)
|
|
10706
|
+
}
|
|
10707
|
+
|
|
10708
|
+
function ToastContent({ className, ...props }: ToastPrimitive.Content.Props) {
|
|
10709
|
+
return (
|
|
10710
|
+
<ToastPrimitive.Content
|
|
10711
|
+
data-slot="toast-content"
|
|
10712
|
+
className={cn(
|
|
10713
|
+
"flex h-full items-center gap-3 overflow-hidden p-4 transition-opacity duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] data-behind:opacity-0 data-expanded:opacity-100",
|
|
10714
|
+
className
|
|
10715
|
+
)}
|
|
10716
|
+
{...props}
|
|
10717
|
+
/>
|
|
10718
|
+
)
|
|
10719
|
+
}
|
|
10720
|
+
|
|
10721
|
+
function ToastTitle({ className, ...props }: ToastPrimitive.Title.Props) {
|
|
10722
|
+
return (
|
|
10723
|
+
<ToastPrimitive.Title
|
|
10724
|
+
data-slot="toast-title"
|
|
10725
|
+
className={cn("text-sm font-medium", className)}
|
|
10726
|
+
{...props}
|
|
10727
|
+
/>
|
|
10728
|
+
)
|
|
10729
|
+
}
|
|
10730
|
+
|
|
10731
|
+
function ToastDescription({
|
|
10732
|
+
className,
|
|
10733
|
+
...props
|
|
10734
|
+
}: ToastPrimitive.Description.Props) {
|
|
10735
|
+
return (
|
|
10736
|
+
<ToastPrimitive.Description
|
|
10737
|
+
data-slot="toast-description"
|
|
10738
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
10739
|
+
{...props}
|
|
10740
|
+
/>
|
|
10741
|
+
)
|
|
10742
|
+
}
|
|
10743
|
+
|
|
10744
|
+
function ToastAction({
|
|
10745
|
+
className,
|
|
10746
|
+
render = <Button variant="outline" size="sm" />,
|
|
10747
|
+
...props
|
|
10748
|
+
}: ToastPrimitive.Action.Props) {
|
|
10749
|
+
return (
|
|
10750
|
+
<ToastPrimitive.Action
|
|
10751
|
+
data-slot="toast-action"
|
|
10752
|
+
render={render}
|
|
10753
|
+
className={cn("shrink-0", className)}
|
|
10754
|
+
{...props}
|
|
10755
|
+
/>
|
|
10756
|
+
)
|
|
10757
|
+
}
|
|
10758
|
+
|
|
10759
|
+
function ToastClose({
|
|
10760
|
+
className,
|
|
10761
|
+
children,
|
|
10762
|
+
render = <Button variant="ghost" size="icon-sm" />,
|
|
10763
|
+
...props
|
|
10764
|
+
}: ToastPrimitive.Close.Props) {
|
|
10765
|
+
return (
|
|
10766
|
+
<ToastPrimitive.Close
|
|
10767
|
+
data-slot="toast-close"
|
|
10768
|
+
aria-label="Close toast"
|
|
10769
|
+
render={render}
|
|
10770
|
+
className={cn(
|
|
10771
|
+
"relative shrink-0 text-muted-foreground after:absolute after:-inset-2 after:content-[''] hover:text-foreground",
|
|
10772
|
+
className
|
|
10773
|
+
)}
|
|
10774
|
+
{...props}
|
|
10775
|
+
>
|
|
10776
|
+
{children ?? (
|
|
10777
|
+
<XIcon aria-hidden="true" />
|
|
10778
|
+
)}
|
|
10779
|
+
</ToastPrimitive.Close>
|
|
10780
|
+
)
|
|
10781
|
+
}
|
|
10782
|
+
|
|
10783
|
+
function ToastIcon({ type }: { type: string | undefined }) {
|
|
10784
|
+
let icon: React.ReactNode = null
|
|
10785
|
+
|
|
10786
|
+
if (type === "success") {
|
|
10787
|
+
icon = (
|
|
10788
|
+
<CircleCheckIcon aria-hidden="true" />
|
|
10789
|
+
)
|
|
10790
|
+
}
|
|
10791
|
+
|
|
10792
|
+
if (type === "info") {
|
|
10793
|
+
icon = (
|
|
10794
|
+
<InfoIcon aria-hidden="true" />
|
|
10795
|
+
)
|
|
10796
|
+
}
|
|
10797
|
+
|
|
10798
|
+
if (type === "warning") {
|
|
10799
|
+
icon = (
|
|
10800
|
+
<TriangleAlertIcon aria-hidden="true" />
|
|
10801
|
+
)
|
|
10802
|
+
}
|
|
10803
|
+
|
|
10804
|
+
if (type === "error") {
|
|
10805
|
+
icon = (
|
|
10806
|
+
<OctagonXIcon className="text-destructive" aria-hidden="true" />
|
|
10807
|
+
)
|
|
10808
|
+
}
|
|
10809
|
+
|
|
10810
|
+
if (type === "loading") {
|
|
10811
|
+
icon = (
|
|
10812
|
+
<Loader2Icon className="animate-spin" aria-hidden="true" />
|
|
10813
|
+
)
|
|
10814
|
+
}
|
|
10815
|
+
|
|
10816
|
+
if (!icon) {
|
|
10817
|
+
return null
|
|
10818
|
+
}
|
|
10819
|
+
|
|
10820
|
+
return (
|
|
10821
|
+
<span
|
|
10822
|
+
data-slot="toast-icon"
|
|
10823
|
+
className="shrink-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4"
|
|
10824
|
+
>
|
|
10825
|
+
{icon}
|
|
10826
|
+
</span>
|
|
10827
|
+
)
|
|
10828
|
+
}
|
|
10829
|
+
|
|
10830
|
+
function ToastList() {
|
|
10831
|
+
const { toasts } = ToastPrimitive.useToastManager()
|
|
10832
|
+
|
|
10833
|
+
return toasts.map((toastItem) => (
|
|
10834
|
+
<Toast key={toastItem.id} toast={toastItem}>
|
|
10835
|
+
<ToastContent>
|
|
10836
|
+
<ToastIcon type={toastItem.type} />
|
|
10837
|
+
<div className="flex min-w-0 flex-1 flex-col gap-1">
|
|
10838
|
+
<ToastTitle />
|
|
10839
|
+
<ToastDescription />
|
|
10840
|
+
</div>
|
|
10841
|
+
<ToastAction />
|
|
10842
|
+
<ToastClose />
|
|
10843
|
+
</ToastContent>
|
|
10844
|
+
</Toast>
|
|
10845
|
+
))
|
|
10846
|
+
}
|
|
10847
|
+
|
|
10848
|
+
function Toaster({
|
|
10849
|
+
children,
|
|
10850
|
+
toastManager = toast,
|
|
10851
|
+
...props
|
|
10852
|
+
}: ToastPrimitive.Provider.Props) {
|
|
10853
|
+
return (
|
|
10854
|
+
<ToastProvider toastManager={toastManager} {...props}>
|
|
10855
|
+
{children}
|
|
10856
|
+
<ToastPortal>
|
|
10857
|
+
<ToastViewport>
|
|
10858
|
+
<ToastList />
|
|
10859
|
+
</ToastViewport>
|
|
10860
|
+
</ToastPortal>
|
|
10861
|
+
</ToastProvider>
|
|
10862
|
+
)
|
|
10863
|
+
}
|
|
10864
|
+
|
|
10865
|
+
const createToastManager = ToastPrimitive.createToastManager
|
|
10866
|
+
const useToastManager = ToastPrimitive.useToastManager
|
|
10867
|
+
|
|
10868
|
+
export {
|
|
10869
|
+
Toaster,
|
|
10870
|
+
Toast,
|
|
10871
|
+
ToastAction,
|
|
10872
|
+
ToastClose,
|
|
10873
|
+
ToastContent,
|
|
10874
|
+
ToastDescription,
|
|
10875
|
+
ToastPortal,
|
|
10876
|
+
ToastProvider,
|
|
10877
|
+
ToastTitle,
|
|
10878
|
+
ToastViewport,
|
|
10879
|
+
createToastManager,
|
|
10880
|
+
toast,
|
|
10881
|
+
useToastManager,
|
|
10882
|
+
}
|
|
10883
|
+
`
|
|
10884
|
+
},
|
|
10885
|
+
{
|
|
10886
|
+
filename: "packages/ui/src/hooks/use-highlighted-code.ts",
|
|
10887
|
+
template: `import * as React from "react"
|
|
10888
|
+
|
|
10889
|
+
import { loadHighlighter } from "@<%= projectName %>/ui/lib/highlighter"
|
|
10890
|
+
|
|
10891
|
+
export function useHighlightedCode(value: string, language: string) {
|
|
10892
|
+
// A trailing newline would render as an extra empty line.
|
|
10893
|
+
const code = value.endsWith("\\n") ? value.slice(0, -1) : value
|
|
10894
|
+
const [loaded, setLoaded] = React.useState<{
|
|
10895
|
+
language: string
|
|
10896
|
+
highlighter: Awaited<ReturnType<typeof loadHighlighter>>
|
|
10897
|
+
} | null>(null)
|
|
10898
|
+
const highlighter = loaded?.language === language ? loaded.highlighter : null
|
|
10899
|
+
|
|
10900
|
+
React.useEffect(() => {
|
|
10901
|
+
let cancelled = false
|
|
10902
|
+
|
|
10903
|
+
loadHighlighter(language)
|
|
10904
|
+
.then((next) => {
|
|
10905
|
+
if (!cancelled) {
|
|
10906
|
+
setLoaded({ language, highlighter: next })
|
|
10907
|
+
}
|
|
10908
|
+
})
|
|
10909
|
+
.catch(() => {})
|
|
10910
|
+
|
|
10911
|
+
return () => {
|
|
10912
|
+
cancelled = true
|
|
10913
|
+
}
|
|
10914
|
+
}, [language])
|
|
10915
|
+
|
|
10916
|
+
// The complete lines, highlighted. While the code streams, only the new
|
|
10917
|
+
// lines are tokenized, starting from the grammar state of the last one.
|
|
10918
|
+
const [done, setDone] = React.useState<{
|
|
10919
|
+
highlighter: typeof highlighter
|
|
10920
|
+
text: string
|
|
10921
|
+
lines: React.ReactNode[]
|
|
10922
|
+
state?: Parameters<NonNullable<typeof highlighter>["highlight"]>[1]
|
|
10923
|
+
}>({ highlighter: null, text: "", lines: [] })
|
|
10924
|
+
|
|
10925
|
+
let next = done
|
|
10926
|
+
|
|
10927
|
+
if (next.highlighter !== highlighter || !code.startsWith(next.text)) {
|
|
10928
|
+
next = { highlighter, text: "", lines: [] }
|
|
10929
|
+
}
|
|
10930
|
+
|
|
10931
|
+
const end = code.lastIndexOf("\\n") + 1
|
|
10932
|
+
|
|
10933
|
+
if (highlighter && end > next.text.length) {
|
|
10934
|
+
const result = highlighter.highlight(
|
|
10935
|
+
code.slice(next.text.length, end - 1),
|
|
10936
|
+
next.state
|
|
10937
|
+
)
|
|
10938
|
+
|
|
10939
|
+
next = {
|
|
10940
|
+
highlighter,
|
|
10941
|
+
text: code.slice(0, end),
|
|
10942
|
+
lines: [...next.lines, ...result.lines],
|
|
10943
|
+
state: result.state,
|
|
10944
|
+
}
|
|
10945
|
+
}
|
|
10946
|
+
|
|
10947
|
+
if (next !== done) {
|
|
10948
|
+
setDone(next)
|
|
10949
|
+
}
|
|
10950
|
+
|
|
10951
|
+
// The last line is still being written, so it is tokenized on every render.
|
|
10952
|
+
const tail = code.slice(end)
|
|
10953
|
+
|
|
10954
|
+
return React.useMemo(() => {
|
|
10955
|
+
if (!highlighter) {
|
|
10956
|
+
return code.split("\\n")
|
|
10957
|
+
}
|
|
10958
|
+
|
|
10959
|
+
return [...next.lines, highlighter.highlight(tail, next.state).lines[0]]
|
|
10960
|
+
}, [code, highlighter, next, tail])
|
|
10961
|
+
}
|
|
10962
|
+
`
|
|
10963
|
+
},
|
|
10964
|
+
{
|
|
10965
|
+
filename: "packages/ui/src/lib/highlighter.tsx",
|
|
10966
|
+
template: `import * as React from "react"
|
|
10967
|
+
import {
|
|
10968
|
+
createHighlighterCore,
|
|
10969
|
+
type GrammarState,
|
|
10970
|
+
type HighlighterCore,
|
|
10971
|
+
} from "shiki/core"
|
|
10972
|
+
import { createJavaScriptRegexEngine } from "shiki/engine/javascript"
|
|
10973
|
+
|
|
10974
|
+
// Add the languages you need. Each one loads the first time it is used.
|
|
10975
|
+
const languages = {
|
|
10976
|
+
bash: () => import("shiki/langs/shellscript.mjs"),
|
|
10977
|
+
css: () => import("shiki/langs/css.mjs"),
|
|
10978
|
+
diff: () => import("shiki/langs/diff.mjs"),
|
|
10979
|
+
html: () => import("shiki/langs/html.mjs"),
|
|
10980
|
+
javascript: () => import("shiki/langs/javascript.mjs"),
|
|
10981
|
+
json: () => import("shiki/langs/json.mjs"),
|
|
10982
|
+
jsx: () => import("shiki/langs/jsx.mjs"),
|
|
10983
|
+
markdown: () => import("shiki/langs/markdown.mjs"),
|
|
10984
|
+
python: () => import("shiki/langs/python.mjs"),
|
|
10985
|
+
sql: () => import("shiki/langs/sql.mjs"),
|
|
10986
|
+
tsx: () => import("shiki/langs/tsx.mjs"),
|
|
10987
|
+
typescript: () => import("shiki/langs/typescript.mjs"),
|
|
10988
|
+
yaml: () => import("shiki/langs/yaml.mjs"),
|
|
10989
|
+
}
|
|
10990
|
+
|
|
10991
|
+
const aliases: Record<string, keyof typeof languages> = {
|
|
10992
|
+
js: "javascript",
|
|
10993
|
+
md: "markdown",
|
|
10994
|
+
py: "python",
|
|
10995
|
+
sh: "bash",
|
|
10996
|
+
shell: "bash",
|
|
10997
|
+
shellscript: "bash",
|
|
10998
|
+
ts: "typescript",
|
|
10999
|
+
yml: "yaml",
|
|
11000
|
+
zsh: "bash",
|
|
11001
|
+
}
|
|
11002
|
+
|
|
11003
|
+
let highlighter: Promise<HighlighterCore> | undefined
|
|
11004
|
+
|
|
11005
|
+
function getHighlighter() {
|
|
11006
|
+
highlighter ??= createHighlighterCore({
|
|
11007
|
+
themes: [
|
|
11008
|
+
import("shiki/themes/github-light.mjs"),
|
|
11009
|
+
import("shiki/themes/github-dark.mjs"),
|
|
11010
|
+
],
|
|
11011
|
+
langs: [],
|
|
11012
|
+
engine: createJavaScriptRegexEngine({ forgiving: true }),
|
|
11013
|
+
})
|
|
11014
|
+
|
|
11015
|
+
return highlighter
|
|
11016
|
+
}
|
|
11017
|
+
|
|
11018
|
+
function getLanguage(language: string) {
|
|
11019
|
+
const name = language.toLowerCase()
|
|
11020
|
+
|
|
11021
|
+
if (name === "ansi") {
|
|
11022
|
+
return name
|
|
11023
|
+
}
|
|
11024
|
+
|
|
11025
|
+
if (name in languages) {
|
|
11026
|
+
return name as keyof typeof languages
|
|
11027
|
+
}
|
|
11028
|
+
|
|
11029
|
+
return aliases[name] ?? null
|
|
11030
|
+
}
|
|
11031
|
+
|
|
11032
|
+
// Loads a language and returns a highlighter for it, or null for a language
|
|
11033
|
+
// that is not listed.
|
|
11034
|
+
export async function loadHighlighter(language: string) {
|
|
11035
|
+
const lang = getLanguage(language)
|
|
11036
|
+
|
|
11037
|
+
if (!lang) {
|
|
11038
|
+
return null
|
|
11039
|
+
}
|
|
11040
|
+
|
|
11041
|
+
const shiki = await getHighlighter()
|
|
11042
|
+
|
|
11043
|
+
if (lang !== "ansi" && !shiki.getLoadedLanguages().includes(lang)) {
|
|
11044
|
+
await shiki.loadLanguage(languages[lang])
|
|
11045
|
+
}
|
|
11046
|
+
|
|
11047
|
+
return {
|
|
11048
|
+
// Returns one React node per line, and the grammar state after the last
|
|
11049
|
+
// line. Pass that state back to continue where the code left off.
|
|
11050
|
+
highlight(code: string, state?: GrammarState) {
|
|
11051
|
+
const tokenize = (text: string) =>
|
|
11052
|
+
shiki.codeToTokens(text, {
|
|
11053
|
+
lang,
|
|
11054
|
+
themes: { light: "github-light", dark: "github-dark" },
|
|
11055
|
+
defaultColor: false,
|
|
11056
|
+
grammarState: state,
|
|
11057
|
+
}).tokens
|
|
11058
|
+
|
|
11059
|
+
// ANSI has no grammar state, so each line is tokenized on its own and
|
|
11060
|
+
// gets the same colors whether it arrives in one piece or streams.
|
|
11061
|
+
const tokens =
|
|
11062
|
+
lang === "ansi"
|
|
11063
|
+
? code.split("\\n").flatMap((line) => tokenize(line))
|
|
11064
|
+
: tokenize(code)
|
|
11065
|
+
|
|
11066
|
+
return {
|
|
11067
|
+
lines: tokens.map((line) =>
|
|
11068
|
+
line.map((token, index) => (
|
|
11069
|
+
<span
|
|
11070
|
+
key={index}
|
|
11071
|
+
style={token.htmlStyle as React.CSSProperties}
|
|
11072
|
+
className="text-(--shiki-light) dark:text-(--shiki-dark)"
|
|
11073
|
+
>
|
|
11074
|
+
{token.content}
|
|
11075
|
+
</span>
|
|
11076
|
+
))
|
|
11077
|
+
),
|
|
11078
|
+
state: shiki.getLastGrammarState(tokens),
|
|
11079
|
+
}
|
|
11080
|
+
},
|
|
11081
|
+
}
|
|
11082
|
+
}
|
|
11083
|
+
|
|
11084
|
+
// Returns one React node per line, or null for a language that is not listed.
|
|
11085
|
+
export async function highlightCode(code: string, language: string) {
|
|
11086
|
+
const highlighter = await loadHighlighter(language)
|
|
11087
|
+
|
|
11088
|
+
return highlighter ? highlighter.highlight(code).lines : null
|
|
11089
|
+
}
|
|
9895
11090
|
`
|
|
9896
11091
|
},
|
|
9897
11092
|
{
|
|
@@ -11222,7 +12417,7 @@ var oxlintrc_default = {
|
|
|
11222
12417
|
}<% } %><% if (shadcn) { %>,
|
|
11223
12418
|
"overrides": [
|
|
11224
12419
|
{
|
|
11225
|
-
"files": ["packages/ui/src/components/**"],
|
|
12420
|
+
"files": ["packages/ui/src/components/**", "packages/ui/src/lib/highlighter.tsx"],
|
|
11226
12421
|
"rules": {<% if (antiSlop) { %>
|
|
11227
12422
|
"anti-slop/no-chained-type-assertions": "off",
|
|
11228
12423
|
"anti-slop/no-conditional-empty-object-spread": "off",
|