@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.
Files changed (193) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_internal/client.d.ts +7 -0
  3. package/dist/_internal/client.js +169 -0
  4. package/dist/_internal/server.d.ts +92 -0
  5. package/dist/_internal/server.js +181 -0
  6. package/dist/applet.d.ts +1 -0
  7. package/dist/applet.js +184 -0
  8. package/dist/batch-Qa4B4-Yp.d.ts +30 -0
  9. package/dist/build-BlmLiKro.js +90 -0
  10. package/dist/build-CcT-wNN9.js +2 -0
  11. package/dist/ci-0Q2mUh53.js +68 -0
  12. package/dist/client.d.ts +48 -0
  13. package/dist/client.js +38 -0
  14. package/dist/contract-QUvEGiRI.d.ts +23 -0
  15. package/dist/deploy-BbL3GObV.js +2579 -0
  16. package/dist/email-DBTVhNB_.js +62 -0
  17. package/dist/generate-XB-72Fzj.js +537 -0
  18. package/dist/generate-wIN3IYqL.js +2 -0
  19. package/dist/index.d.ts +185 -0
  20. package/dist/index.js +251 -0
  21. package/dist/init-DwsXRUk-.js +244 -0
  22. package/dist/lazy-client-x0DCI98S.js +64 -0
  23. package/dist/load-config-OKZU3UKn.js +27 -0
  24. package/dist/login-BBO74hPC.js +12 -0
  25. package/dist/logs-XvK6Zs5Y.js +183 -0
  26. package/dist/manifest-4ZAc6HUk.js +191 -0
  27. package/dist/manifest-I-9s8R36.d.ts +88 -0
  28. package/dist/me-BW7Paary.js +32 -0
  29. package/dist/project-B0qNXnFu.js +536 -0
  30. package/dist/prompt-ChS-grYO.js +29 -0
  31. package/dist/query-cache-CXmAyLv3.js +82 -0
  32. package/dist/react.d.ts +37 -0
  33. package/dist/react.js +515 -0
  34. package/dist/schedules-BkWZsbSs.js +42 -0
  35. package/dist/server.d.ts +46 -0
  36. package/dist/server.js +104 -0
  37. package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
  38. package/dist/telephony.d.ts +77 -0
  39. package/dist/telephony.js +607 -0
  40. package/dist/upload-DKZzz5kW.d.ts +112 -0
  41. package/dist/upload-DRbVhuDm.js +114 -0
  42. package/dist/variables-0tjnAeut.js +108 -0
  43. package/dist/vite.d.ts +63 -0
  44. package/dist/vite.js +816 -0
  45. package/dist/workflow-CTo2kZF1.js +51 -0
  46. package/dist/workflow-DurM6Fwx.d.ts +28 -0
  47. package/dist/workflow-engine-MogejNfF.js +117 -0
  48. package/dist/workspace-DruAZPmV.js +390 -0
  49. package/package.json +112 -0
  50. package/scaffold/.agents/skills/hitch-applets/SKILL.md +163 -0
  51. package/scaffold/.agents/skills/hitch-applets/references/client.md +73 -0
  52. package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
  53. package/scaffold/.agents/skills/hitch-applets/references/files.md +109 -0
  54. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +198 -0
  55. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +37 -0
  56. package/scaffold/.agents/skills/hitch-applets/references/performance.md +74 -0
  57. package/scaffold/.agents/skills/hitch-applets/references/records.md +176 -0
  58. package/scaffold/.agents/skills/hitch-applets/references/schedules.md +91 -0
  59. package/scaffold/.agents/skills/hitch-applets/references/server.md +95 -0
  60. package/scaffold/.agents/skills/hitch-applets/references/workflows.md +81 -0
  61. package/scaffold/.agents/skills/hitch-cli/SKILL.md +129 -0
  62. package/scaffold/.agents/skills/hitch-data/SKILL.md +52 -0
  63. package/scaffold/.agents/skills/hitch-data/references/attributes.md +127 -0
  64. package/scaffold/.agents/skills/hitch-data/references/limits.md +64 -0
  65. package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
  66. package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
  67. package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  68. package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  69. package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  70. package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  71. package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  72. package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
  73. package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
  74. package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
  75. package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
  76. package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
  77. package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
  78. package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
  79. package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
  80. package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
  81. package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  82. package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  83. package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  84. package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  85. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
  86. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  87. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
  88. package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  89. package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  90. package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  91. package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  92. package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  93. package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  94. package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  95. package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  96. package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  97. package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  98. package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  99. package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  100. package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  101. package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  102. package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  103. package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
  104. package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
  105. package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  106. package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
  107. package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  108. package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  109. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  110. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  111. package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  112. package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  113. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  114. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  115. package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  116. package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  117. package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  118. package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  119. package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  120. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  121. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  122. package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
  123. package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
  124. package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
  125. package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
  126. package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
  127. package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
  128. package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
  129. package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
  130. package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
  131. package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
  132. package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
  133. package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
  134. package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
  135. package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
  136. package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
  137. package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
  138. package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
  139. package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
  140. package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
  141. package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
  142. package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
  143. package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
  144. package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
  145. package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
  146. package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
  147. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
  148. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
  149. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
  150. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
  151. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
  152. package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
  153. package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
  154. package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
  155. package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
  156. package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
  157. package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
  158. package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
  159. package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
  160. package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
  161. package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
  162. package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
  163. package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
  164. package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
  165. package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
  166. package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
  167. package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
  168. package/scaffold/.github/workflows/hitch.yml +15 -0
  169. package/scaffold/AGENTS.md +38 -0
  170. package/scaffold/applet/components.json +25 -0
  171. package/scaffold/applet/src/client/components/ui/alert.tsx +73 -0
  172. package/scaffold/applet/src/client/components/ui/avatar.tsx +100 -0
  173. package/scaffold/applet/src/client/components/ui/badge.tsx +55 -0
  174. package/scaffold/applet/src/client/components/ui/button.tsx +90 -0
  175. package/scaffold/applet/src/client/components/ui/card.tsx +85 -0
  176. package/scaffold/applet/src/client/components/ui/checkbox.tsx +35 -0
  177. package/scaffold/applet/src/client/components/ui/dialog.tsx +164 -0
  178. package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +235 -0
  179. package/scaffold/applet/src/client/components/ui/input-group.tsx +144 -0
  180. package/scaffold/applet/src/client/components/ui/input.tsx +22 -0
  181. package/scaffold/applet/src/client/components/ui/label.tsx +29 -0
  182. package/scaffold/applet/src/client/components/ui/popover.tsx +74 -0
  183. package/scaffold/applet/src/client/components/ui/select.tsx +243 -0
  184. package/scaffold/applet/src/client/components/ui/separator.tsx +25 -0
  185. package/scaffold/applet/src/client/components/ui/sheet.tsx +177 -0
  186. package/scaffold/applet/src/client/components/ui/skeleton.tsx +13 -0
  187. package/scaffold/applet/src/client/components/ui/spinner.tsx +17 -0
  188. package/scaffold/applet/src/client/components/ui/switch.tsx +41 -0
  189. package/scaffold/applet/src/client/components/ui/table.tsx +114 -0
  190. package/scaffold/applet/src/client/components/ui/tabs.tsx +78 -0
  191. package/scaffold/applet/src/client/components/ui/textarea.tsx +23 -0
  192. package/scaffold/applet/src/client/lib/utils.ts +1 -0
  193. 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
+ };