@hitch42/applet 0.1.0-beta.10
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/LICENSE +21 -0
- package/dist/_internal/client.d.ts +7 -0
- package/dist/_internal/client.js +169 -0
- package/dist/_internal/server.d.ts +92 -0
- package/dist/_internal/server.js +181 -0
- package/dist/applet.d.ts +1 -0
- package/dist/applet.js +184 -0
- package/dist/batch-Qa4B4-Yp.d.ts +30 -0
- package/dist/build-BlmLiKro.js +90 -0
- package/dist/build-CcT-wNN9.js +2 -0
- package/dist/ci-0Q2mUh53.js +68 -0
- package/dist/client.d.ts +48 -0
- package/dist/client.js +38 -0
- package/dist/contract-QUvEGiRI.d.ts +23 -0
- package/dist/deploy-BbL3GObV.js +2579 -0
- package/dist/email-DBTVhNB_.js +62 -0
- package/dist/generate-XB-72Fzj.js +537 -0
- package/dist/generate-wIN3IYqL.js +2 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +251 -0
- package/dist/init-DwsXRUk-.js +244 -0
- package/dist/lazy-client-x0DCI98S.js +64 -0
- package/dist/load-config-OKZU3UKn.js +27 -0
- package/dist/login-BBO74hPC.js +12 -0
- package/dist/logs-XvK6Zs5Y.js +183 -0
- package/dist/manifest-4ZAc6HUk.js +191 -0
- package/dist/manifest-I-9s8R36.d.ts +88 -0
- package/dist/me-BW7Paary.js +32 -0
- package/dist/project-B0qNXnFu.js +536 -0
- package/dist/prompt-ChS-grYO.js +29 -0
- package/dist/query-cache-CXmAyLv3.js +82 -0
- package/dist/react.d.ts +37 -0
- package/dist/react.js +515 -0
- package/dist/schedules-BkWZsbSs.js +42 -0
- package/dist/server.d.ts +46 -0
- package/dist/server.js +104 -0
- package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
- package/dist/telephony.d.ts +77 -0
- package/dist/telephony.js +607 -0
- package/dist/upload-DKZzz5kW.d.ts +112 -0
- package/dist/upload-DRbVhuDm.js +114 -0
- package/dist/variables-0tjnAeut.js +108 -0
- package/dist/vite.d.ts +63 -0
- package/dist/vite.js +816 -0
- package/dist/workflow-CTo2kZF1.js +51 -0
- package/dist/workflow-DurM6Fwx.d.ts +28 -0
- package/dist/workflow-engine-MogejNfF.js +117 -0
- package/dist/workspace-DruAZPmV.js +390 -0
- package/package.json +112 -0
- package/scaffold/.agents/skills/hitch-applets/SKILL.md +163 -0
- package/scaffold/.agents/skills/hitch-applets/references/client.md +73 -0
- package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
- package/scaffold/.agents/skills/hitch-applets/references/files.md +109 -0
- package/scaffold/.agents/skills/hitch-applets/references/manifest.md +198 -0
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +37 -0
- package/scaffold/.agents/skills/hitch-applets/references/performance.md +74 -0
- package/scaffold/.agents/skills/hitch-applets/references/records.md +176 -0
- package/scaffold/.agents/skills/hitch-applets/references/schedules.md +91 -0
- package/scaffold/.agents/skills/hitch-applets/references/server.md +95 -0
- package/scaffold/.agents/skills/hitch-applets/references/workflows.md +81 -0
- package/scaffold/.agents/skills/hitch-cli/SKILL.md +129 -0
- package/scaffold/.agents/skills/hitch-data/SKILL.md +52 -0
- package/scaffold/.agents/skills/hitch-data/references/attributes.md +127 -0
- package/scaffold/.agents/skills/hitch-data/references/limits.md +64 -0
- package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
- package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
- package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
- package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
- package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
- package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
- package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
- package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
- package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
- package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
- package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
- package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
- package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
- package/scaffold/.github/workflows/hitch.yml +15 -0
- package/scaffold/AGENTS.md +38 -0
- package/scaffold/applet/components.json +25 -0
- package/scaffold/applet/src/client/components/ui/alert.tsx +73 -0
- package/scaffold/applet/src/client/components/ui/avatar.tsx +100 -0
- package/scaffold/applet/src/client/components/ui/badge.tsx +55 -0
- package/scaffold/applet/src/client/components/ui/button.tsx +90 -0
- package/scaffold/applet/src/client/components/ui/card.tsx +85 -0
- package/scaffold/applet/src/client/components/ui/checkbox.tsx +35 -0
- package/scaffold/applet/src/client/components/ui/dialog.tsx +164 -0
- package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +235 -0
- package/scaffold/applet/src/client/components/ui/input-group.tsx +144 -0
- package/scaffold/applet/src/client/components/ui/input.tsx +22 -0
- package/scaffold/applet/src/client/components/ui/label.tsx +29 -0
- package/scaffold/applet/src/client/components/ui/popover.tsx +74 -0
- package/scaffold/applet/src/client/components/ui/select.tsx +243 -0
- package/scaffold/applet/src/client/components/ui/separator.tsx +25 -0
- package/scaffold/applet/src/client/components/ui/sheet.tsx +177 -0
- package/scaffold/applet/src/client/components/ui/skeleton.tsx +13 -0
- package/scaffold/applet/src/client/components/ui/spinner.tsx +17 -0
- package/scaffold/applet/src/client/components/ui/switch.tsx +41 -0
- package/scaffold/applet/src/client/components/ui/table.tsx +114 -0
- package/scaffold/applet/src/client/components/ui/tabs.tsx +78 -0
- package/scaffold/applet/src/client/components/ui/textarea.tsx +23 -0
- package/scaffold/applet/src/client/lib/utils.ts +1 -0
- package/scaffold/applet/src/client/styles/globals.css +136 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Hitch Applet Workspace
|
|
2
|
+
|
|
3
|
+
Before any command or file edit, read and follow `.agents/skills/hitch-applets/SKILL.md`.
|
|
4
|
+
|
|
5
|
+
Use `pnpm` for package commands.
|
|
6
|
+
|
|
7
|
+
The applet CLI refreshes its generated support files.
|
|
8
|
+
The CLI adds missing MCP servers without changing existing entries.
|
|
9
|
+
|
|
10
|
+
## What makes a good applet
|
|
11
|
+
|
|
12
|
+
- A good applet does one job for one group of people. Ship the whole workflow for that job, and nothing else.
|
|
13
|
+
- Small applets win. Prefer two focused applets over one applet with modes.
|
|
14
|
+
- The organization's Hitch data is the single source of truth. Read and write Hitch objects. Do not build a parallel store, cache, or copy.
|
|
15
|
+
- Do not add sample business records, hard-coded business records, or in-memory business data.
|
|
16
|
+
- Access control belongs to the platform. Each call carries the caller's identity and grants. Do not gate data in applet code — a filter in the UI is a convenience, not a boundary.
|
|
17
|
+
- Stay client-first. A server half exists for secrets, external services, and schedules. When in doubt, leave it out.
|
|
18
|
+
- Use the platform's parts — records, files, schedules, the theme — before you build custom machinery.
|
|
19
|
+
- Design for the user in front of you. Their words name the routes, fields, and buttons. When the data model and their language disagree, raise it — do not paper over it.
|
|
20
|
+
|
|
21
|
+
## Before you build
|
|
22
|
+
|
|
23
|
+
- Do not create an applet until the first complete user workflow is clear.
|
|
24
|
+
- Treat thresholds, status rules, notification timing, notification channels, and recipients as product decisions.
|
|
25
|
+
- Ask one product question when a required decision is missing. Do not write files until the user answers it.
|
|
26
|
+
- Read generated Hitch types before you select objects or attributes.
|
|
27
|
+
- If generated types are unavailable, ask for access or ask for the exact object and attribute names.
|
|
28
|
+
- Start with the smallest complete workflow. Do not add dashboards, metrics, search, filters, or settings without a request.
|
|
29
|
+
|
|
30
|
+
## Work with the user
|
|
31
|
+
|
|
32
|
+
- You will be developing applets for non-technical users. You are a Forward Deployed Engineer for Hitch itself.
|
|
33
|
+
- Your job is to understand user requirements and implement the solution to their problems.
|
|
34
|
+
- Use plain language. Avoid overly technical jargon and focus on understanding.
|
|
35
|
+
- Do not ask the user how to do something or which technical option is better. Lead with value and trade-offs instead.
|
|
36
|
+
- Ask only for decisions that affect the app's behavior. Handle implementation details without asking when a safe default exists.
|
|
37
|
+
- Ask one clear question at a time. Give a recommended choice when the user must make a technical decision.
|
|
38
|
+
- Explain an error in plain language before you show technical details.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "aria-rhea",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/client/styles/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"iconLibrary": "lucide",
|
|
14
|
+
"rtl": false,
|
|
15
|
+
"aliases": {
|
|
16
|
+
"components": "@/client/components",
|
|
17
|
+
"utils": "@/client/lib/utils",
|
|
18
|
+
"ui": "@/client/components/ui",
|
|
19
|
+
"lib": "@/client/lib",
|
|
20
|
+
"hooks": "@/client/hooks"
|
|
21
|
+
},
|
|
22
|
+
"menuColor": "default",
|
|
23
|
+
"menuAccent": "subtle",
|
|
24
|
+
"registries": {}
|
|
25
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/client/lib/utils";
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"group/alert relative grid w-full gap-0.5 rounded-2xl border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: "bg-card text-card-foreground",
|
|
12
|
+
destructive:
|
|
13
|
+
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn(
|
|
42
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
data-slot="alert-description"
|
|
54
|
+
className={cn(
|
|
55
|
+
"text-sm text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
64
|
+
return (
|
|
65
|
+
<div
|
|
66
|
+
data-slot="alert-action"
|
|
67
|
+
className={cn("absolute top-2.5 right-3", className)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/client/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Avatar({
|
|
6
|
+
className,
|
|
7
|
+
size = "default",
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<"div"> & {
|
|
10
|
+
size?: "default" | "sm" | "lg";
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
data-slot="avatar"
|
|
15
|
+
data-size={size}
|
|
16
|
+
className={cn(
|
|
17
|
+
"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type ImageState = "loading" | "loaded" | "error";
|
|
26
|
+
|
|
27
|
+
function AvatarImage({ className, ...props }: React.ComponentProps<"img">) {
|
|
28
|
+
const [state, setState] = React.useState<ImageState>(props.src ? "loading" : "error");
|
|
29
|
+
return (
|
|
30
|
+
<img
|
|
31
|
+
data-slot="avatar-image"
|
|
32
|
+
alt={props.alt || ""}
|
|
33
|
+
data-state={state}
|
|
34
|
+
onLoad={() => setState("loaded")}
|
|
35
|
+
onError={() => setState("error")}
|
|
36
|
+
className={cn(
|
|
37
|
+
"peer aspect-square size-full rounded-full object-cover data-[state=error]:hidden",
|
|
38
|
+
className,
|
|
39
|
+
)}
|
|
40
|
+
{...props}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function AvatarFallback({ className, ...props }: React.ComponentProps<"div">) {
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
data-slot="avatar-fallback"
|
|
49
|
+
className={cn(
|
|
50
|
+
"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs peer-data-[state=error]:flex peer-[*]:hidden",
|
|
51
|
+
className,
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
|
|
59
|
+
return (
|
|
60
|
+
<span
|
|
61
|
+
data-slot="avatar-badge"
|
|
62
|
+
className={cn(
|
|
63
|
+
"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none",
|
|
64
|
+
"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
|
|
65
|
+
"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
|
|
66
|
+
"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
|
|
67
|
+
className,
|
|
68
|
+
)}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
75
|
+
return (
|
|
76
|
+
<div
|
|
77
|
+
data-slot="avatar-group"
|
|
78
|
+
className={cn(
|
|
79
|
+
"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
|
|
80
|
+
className,
|
|
81
|
+
)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function AvatarGroupCount({ className, ...props }: React.ComponentProps<"div">) {
|
|
88
|
+
return (
|
|
89
|
+
<div
|
|
90
|
+
data-slot="avatar-group-count"
|
|
91
|
+
className={cn(
|
|
92
|
+
"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
|
|
93
|
+
className,
|
|
94
|
+
)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { Avatar, AvatarImage, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarBadge };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/client/lib/utils";
|
|
4
|
+
|
|
5
|
+
const badgeVariants = cva(
|
|
6
|
+
"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-2xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
|
|
7
|
+
{
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
11
|
+
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
12
|
+
destructive:
|
|
13
|
+
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
|
|
14
|
+
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
|
15
|
+
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
16
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
variant: "default",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
function Badge({
|
|
26
|
+
className,
|
|
27
|
+
variant = "default",
|
|
28
|
+
render,
|
|
29
|
+
...props
|
|
30
|
+
}: React.ComponentProps<"span"> &
|
|
31
|
+
VariantProps<typeof badgeVariants> & {
|
|
32
|
+
render?: (props: React.HTMLAttributes<HTMLElement>) => React.ReactNode;
|
|
33
|
+
}) {
|
|
34
|
+
if (render) {
|
|
35
|
+
const renderProps = {
|
|
36
|
+
"data-slot": "badge",
|
|
37
|
+
"data-variant": variant,
|
|
38
|
+
className: cn(badgeVariants({ variant }), className),
|
|
39
|
+
...props,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return render(renderProps);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<span
|
|
47
|
+
data-slot="badge"
|
|
48
|
+
data-variant={variant}
|
|
49
|
+
className={cn(badgeVariants({ variant }), className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
import {
|
|
6
|
+
Button as ButtonPrimitive,
|
|
7
|
+
Link as LinkPrimitive,
|
|
8
|
+
type ButtonProps as ButtonPrimitiveProps,
|
|
9
|
+
type LinkProps as LinkPrimitiveProps,
|
|
10
|
+
} from "react-aria-components";
|
|
11
|
+
|
|
12
|
+
import { cn } from "@/client/lib/utils";
|
|
13
|
+
|
|
14
|
+
const buttonVariants = cva(
|
|
15
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-2xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
16
|
+
{
|
|
17
|
+
variants: {
|
|
18
|
+
variant: {
|
|
19
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
20
|
+
outline:
|
|
21
|
+
"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30",
|
|
22
|
+
secondary:
|
|
23
|
+
"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
24
|
+
ghost:
|
|
25
|
+
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
26
|
+
destructive:
|
|
27
|
+
"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
28
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
29
|
+
},
|
|
30
|
+
size: {
|
|
31
|
+
default:
|
|
32
|
+
"h-8 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
33
|
+
xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
|
|
34
|
+
sm: "h-7 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
35
|
+
lg: "h-9 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
36
|
+
icon: "size-8",
|
|
37
|
+
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
38
|
+
"icon-sm": "size-7",
|
|
39
|
+
"icon-lg": "size-9",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaultVariants: {
|
|
43
|
+
variant: "default",
|
|
44
|
+
size: "default",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
function Button({
|
|
50
|
+
className,
|
|
51
|
+
variant = "default",
|
|
52
|
+
size = "default",
|
|
53
|
+
...props
|
|
54
|
+
}: Omit<ButtonPrimitiveProps, "className"> &
|
|
55
|
+
React.RefAttributes<HTMLButtonElement> &
|
|
56
|
+
VariantProps<typeof buttonVariants> & {
|
|
57
|
+
className?: string;
|
|
58
|
+
}) {
|
|
59
|
+
return (
|
|
60
|
+
<ButtonPrimitive
|
|
61
|
+
data-slot="button"
|
|
62
|
+
data-variant={variant}
|
|
63
|
+
data-size={size}
|
|
64
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function LinkButton({
|
|
71
|
+
className,
|
|
72
|
+
variant = "default",
|
|
73
|
+
size = "default",
|
|
74
|
+
...props
|
|
75
|
+
}: Omit<LinkPrimitiveProps, "className"> &
|
|
76
|
+
VariantProps<typeof buttonVariants> & {
|
|
77
|
+
className?: string;
|
|
78
|
+
}) {
|
|
79
|
+
return (
|
|
80
|
+
<LinkPrimitive
|
|
81
|
+
data-slot="button"
|
|
82
|
+
data-variant={variant}
|
|
83
|
+
data-size={size}
|
|
84
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
85
|
+
{...props}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { Button, LinkButton, buttonVariants };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/client/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Card({
|
|
6
|
+
className,
|
|
7
|
+
size = "default",
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
data-slot="card"
|
|
13
|
+
data-size={size}
|
|
14
|
+
className={cn(
|
|
15
|
+
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-[min(var(--radius-4xl),24px)] bg-card py-(--card-spacing) text-sm text-card-foreground shadow-sm ring-1 ring-foreground/5 [--card-spacing:--spacing(5)] has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(4)] dark:ring-foreground/10 *:[img:first-child]:rounded-t-[min(var(--radius-4xl),24px)] *:[img:last-child]:rounded-b-[min(var(--radius-4xl),24px)]",
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
data-slot="card-header"
|
|
27
|
+
className={cn(
|
|
28
|
+
"group/card-header @container/card-header grid auto-rows-min items-start gap-1.5 rounded-t-[min(var(--radius-4xl),24px)] px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
data-slot="card-title"
|
|
40
|
+
className={cn("font-heading text-base font-medium", className)}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
47
|
+
return (
|
|
48
|
+
<div
|
|
49
|
+
data-slot="card-description"
|
|
50
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
57
|
+
return (
|
|
58
|
+
<div
|
|
59
|
+
data-slot="card-action"
|
|
60
|
+
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
67
|
+
return (
|
|
68
|
+
<div data-slot="card-content" className={cn("px-(--card-spacing)", className)} {...props} />
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
data-slot="card-footer"
|
|
76
|
+
className={cn(
|
|
77
|
+
"flex items-center rounded-b-[min(var(--radius-4xl),24px)] px-(--card-spacing) [.border-t]:pt-(--card-spacing)",
|
|
78
|
+
className,
|
|
79
|
+
)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CheckIcon } from "lucide-react";
|
|
2
|
+
import {
|
|
3
|
+
Checkbox as CheckboxPrimitive,
|
|
4
|
+
composeRenderProps,
|
|
5
|
+
type CheckboxProps,
|
|
6
|
+
} from "react-aria-components";
|
|
7
|
+
|
|
8
|
+
import { cn } from "@/client/lib/utils";
|
|
9
|
+
|
|
10
|
+
function Checkbox({ className, children, ...props }: CheckboxProps) {
|
|
11
|
+
return (
|
|
12
|
+
<CheckboxPrimitive
|
|
13
|
+
data-slot="checkbox"
|
|
14
|
+
className={cn(
|
|
15
|
+
"peer relative flex size-4 shrink-0 items-center justify-center rounded-[5px] border border-transparent bg-input/90 transition-shadow outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-transparent after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary data-focus-visible:border-ring data-focus-visible:ring-3 data-focus-visible:ring-ring/30 data-invalid:border-destructive data-invalid:ring-3 data-invalid:ring-destructive/20 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 dark:data-invalid:border-destructive/50 dark:data-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary data-selected:border-primary data-selected:bg-primary data-selected:text-primary-foreground data-invalid:data-selected:border-primary dark:data-selected:bg-primary",
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
>
|
|
20
|
+
{composeRenderProps(children, (children, { isSelected, isIndeterminate }) => (
|
|
21
|
+
<>
|
|
22
|
+
<span
|
|
23
|
+
data-slot="checkbox-indicator"
|
|
24
|
+
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
|
|
25
|
+
>
|
|
26
|
+
{(isSelected || isIndeterminate) && <CheckIcon />}
|
|
27
|
+
</span>
|
|
28
|
+
{children}
|
|
29
|
+
</>
|
|
30
|
+
))}
|
|
31
|
+
</CheckboxPrimitive>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { Checkbox };
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { XIcon } from "lucide-react";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import {
|
|
4
|
+
Dialog as DialogPrimitive,
|
|
5
|
+
DialogTrigger as DialogTriggerPrimitive,
|
|
6
|
+
Heading,
|
|
7
|
+
ModalOverlay as ModalOverlayPrimitive,
|
|
8
|
+
Modal as ModalPrimitive,
|
|
9
|
+
type DialogProps as DialogPrimitiveProps,
|
|
10
|
+
type DialogTriggerProps as DialogTriggerPrimitiveProps,
|
|
11
|
+
type ModalOverlayProps as ModalOverlayPrimitiveProps,
|
|
12
|
+
} from "react-aria-components";
|
|
13
|
+
|
|
14
|
+
import { Button } from "@/client/components/ui/button";
|
|
15
|
+
import { cn } from "@/client/lib/utils";
|
|
16
|
+
|
|
17
|
+
function DialogTrigger({ ...props }: DialogTriggerPrimitiveProps) {
|
|
18
|
+
return <DialogTriggerPrimitive data-slot="dialog-trigger" {...props} />;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function DialogClose({
|
|
22
|
+
className,
|
|
23
|
+
variant = "outline",
|
|
24
|
+
size = "default",
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof Button>) {
|
|
27
|
+
return (
|
|
28
|
+
<Button
|
|
29
|
+
slot="close"
|
|
30
|
+
data-slot="dialog-close"
|
|
31
|
+
variant={variant}
|
|
32
|
+
size={size}
|
|
33
|
+
className={cn(className)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function DialogOverlay({
|
|
40
|
+
className,
|
|
41
|
+
children,
|
|
42
|
+
...props
|
|
43
|
+
}: Omit<ModalOverlayPrimitiveProps, "className" | "children"> & {
|
|
44
|
+
className?: string;
|
|
45
|
+
children: React.ReactNode;
|
|
46
|
+
}) {
|
|
47
|
+
return (
|
|
48
|
+
<ModalOverlayPrimitive
|
|
49
|
+
data-slot="dialog-overlay"
|
|
50
|
+
className={cn(
|
|
51
|
+
"fixed inset-0 isolate z-50 bg-black/30 duration-100 data-entering:animate-in data-entering:fade-in-0 data-exiting:animate-out data-exiting:fade-out-0 supports-backdrop-filter:backdrop-blur-sm",
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</ModalOverlayPrimitive>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Dialog({
|
|
62
|
+
className,
|
|
63
|
+
children,
|
|
64
|
+
showCloseButton = true,
|
|
65
|
+
isDismissable = true,
|
|
66
|
+
...props
|
|
67
|
+
}: Omit<ModalOverlayPrimitiveProps, "className" | "children"> &
|
|
68
|
+
Pick<React.ComponentProps<typeof ModalPrimitive>, "isDismissable"> & {
|
|
69
|
+
className?: string;
|
|
70
|
+
children: React.ReactNode;
|
|
71
|
+
showCloseButton?: boolean;
|
|
72
|
+
}) {
|
|
73
|
+
return (
|
|
74
|
+
<DialogOverlay isDismissable={isDismissable} {...props}>
|
|
75
|
+
<ModalPrimitive
|
|
76
|
+
data-slot="dialog-content"
|
|
77
|
+
className={cn(
|
|
78
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 rounded-[min(var(--radius-4xl),24px)] bg-popover p-6 text-sm text-popover-foreground shadow-xl ring-1 ring-foreground/5 duration-100 outline-none data-entering:animate-in data-entering:fade-in-0 data-entering:zoom-in-95 data-exiting:animate-out data-exiting:fade-out-0 data-exiting:zoom-out-95 sm:max-w-md dark:ring-foreground/10",
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
>
|
|
82
|
+
<DialogPrimitive
|
|
83
|
+
data-slot="dialog"
|
|
84
|
+
className="[display:inherit] [gap:inherit] outline-none"
|
|
85
|
+
>
|
|
86
|
+
{children}
|
|
87
|
+
{showCloseButton && (
|
|
88
|
+
<DialogClose
|
|
89
|
+
variant="ghost"
|
|
90
|
+
className="absolute top-4 right-4 bg-secondary"
|
|
91
|
+
size="icon-sm"
|
|
92
|
+
>
|
|
93
|
+
<XIcon />
|
|
94
|
+
<span className="sr-only">Close</span>
|
|
95
|
+
</DialogClose>
|
|
96
|
+
)}
|
|
97
|
+
</DialogPrimitive>
|
|
98
|
+
</ModalPrimitive>
|
|
99
|
+
</DialogOverlay>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
104
|
+
return (
|
|
105
|
+
<div data-slot="dialog-header" className={cn("flex flex-col gap-1.5", className)} {...props} />
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function DialogFooter({
|
|
110
|
+
className,
|
|
111
|
+
showCloseButton = false,
|
|
112
|
+
children,
|
|
113
|
+
...props
|
|
114
|
+
}: React.ComponentProps<"div"> & {
|
|
115
|
+
showCloseButton?: boolean;
|
|
116
|
+
}) {
|
|
117
|
+
return (
|
|
118
|
+
<div
|
|
119
|
+
data-slot="dialog-footer"
|
|
120
|
+
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
|
121
|
+
{...props}
|
|
122
|
+
>
|
|
123
|
+
{children}
|
|
124
|
+
{showCloseButton && <DialogClose variant="outline">Close</DialogClose>}
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function DialogTitle({ className, ...props }: Omit<React.ComponentProps<typeof Heading>, "slot">) {
|
|
130
|
+
return (
|
|
131
|
+
<Heading
|
|
132
|
+
slot="title"
|
|
133
|
+
data-slot="dialog-title"
|
|
134
|
+
className={cn("font-heading text-base leading-none font-medium", className)}
|
|
135
|
+
{...props}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function DialogDescription({ className, ...props }: Omit<React.ComponentProps<"div">, "slot">) {
|
|
141
|
+
return (
|
|
142
|
+
<div
|
|
143
|
+
data-slot="dialog-description"
|
|
144
|
+
className={cn(
|
|
145
|
+
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
146
|
+
className,
|
|
147
|
+
)}
|
|
148
|
+
{...props}
|
|
149
|
+
/>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
type DialogPrimitiveProps,
|
|
155
|
+
type DialogTriggerPrimitiveProps,
|
|
156
|
+
Dialog,
|
|
157
|
+
DialogClose,
|
|
158
|
+
DialogDescription,
|
|
159
|
+
DialogFooter,
|
|
160
|
+
DialogHeader,
|
|
161
|
+
DialogOverlay,
|
|
162
|
+
DialogTitle,
|
|
163
|
+
DialogTrigger,
|
|
164
|
+
};
|