Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/strong-suits-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"uploadthing": minor
"@uploadthing/react": minor
---

feat: add `generateReactHelpers.getRouteConfig`, `isValidFileSize` and `isValidFileType` helpers

💡 See https://github.com/pingdotgg/uploadthing/blob/main/examples/with-novel/uploadthing/novel-plugin.ts#L50-L61 for a live example utilizing these helpers.
16 changes: 16 additions & 0 deletions docs/src/pages/api/uploadthing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createRouteHandler, createUploadthing } from "uploadthing/next-legacy";

const f = createUploadthing();
const router = {
mockRoute: f(["image"])
.middleware(() => {
throw new Error("This is just a mock route, you cant use it");
return {};
})
.onUploadComplete(() => {}),
};

export default createRouteHandler({
router,
config: { uploadthingSecret: "sk_foo" },
});
18 changes: 17 additions & 1 deletion docs/src/pages/theming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ component match your design in the exact way you want.
```

<UploadButton
endpoint="mockRoute"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having these actually load instead of fetch failing helped reduce some impossible states we had weird paths for just to display in here

__internal_button_disabled
__internal_state="ready"
className="ut-button:bg-red-500 ut-button:ut-readying:bg-red-500/50 dark:ut-allowed-content:text-white mt-4"
Expand All @@ -252,6 +253,7 @@ component match your design in the exact way you want.
/>

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="readying"
className="ut-button:bg-red-500 ut-button:ut-readying:bg-red-500/50 dark:ut-allowed-content:text-white mt-4"
Expand Down Expand Up @@ -312,6 +314,7 @@ component.
```

<UploadButton
endpoint="mockRoute"
__internal_state="uploading"
__internal_button_disabled
appearance={{
Expand All @@ -327,6 +330,7 @@ component.
/>

<UploadButton
endpoint="mockRoute"
__internal_state="ready"
__internal_button_disabled
appearance={{
Expand Down Expand Up @@ -389,6 +393,7 @@ specific elements of components.
```

<UploadButton
endpoint="mockRoute"
__internal_state="ready"
__internal_button_disabled
className="custom-class dark:ut-allowed-content:text-white"
Expand All @@ -399,6 +404,7 @@ specific elements of components.
/>

<UploadButton
endpoint="mockRoute"
__internal_state="readying"
__internal_button_disabled
className="custom-class dark:ut-allowed-content:text-white"
Expand All @@ -414,6 +420,7 @@ specific elements of components.
/>

<UploadButton
endpoint="mockRoute"
__internal_state="uploading"
__internal_button_disabled
className="custom-class dark:ut-allowed-content:text-white"
Expand Down Expand Up @@ -492,6 +499,7 @@ and will return a string
```

<UploadButton
endpoint="mockRoute"
__internal_state="ready"
__internal_button_disabled
className="dark:ut-allowed-content:text-white"
Expand All @@ -511,6 +519,7 @@ and will return a string
/>

<UploadButton
endpoint="mockRoute"
__internal_state="readying"
__internal_button_disabled
className="dark:ut-allowed-content:text-white"
Expand All @@ -529,6 +538,7 @@ and will return a string
/>

<UploadButton
endpoint="mockRoute"
__internal_state="uploading"
__internal_button_disabled
className="dark:ut-allowed-content:text-white"
Expand Down Expand Up @@ -577,6 +587,7 @@ the component and will return a `CSSProperties` object
```

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="readying"
appearance={{
Expand All @@ -601,6 +612,7 @@ the component and will return a `CSSProperties` object
/>

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="ready"
appearance={{
Expand All @@ -625,6 +637,7 @@ the component and will return a `CSSProperties` object
/>

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="uploading"
appearance={{
Expand Down Expand Up @@ -694,6 +707,7 @@ type UploadDropzoneProps = {

```jsx
<UploadButton
endpoint="mockRoute"
content={{
button({ ready }) {
if (ready) return <div>Upload stuff</div>;
Expand All @@ -710,6 +724,7 @@ type UploadDropzoneProps = {
```

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="readying"
className="ut-allowed-content:text-zinc-500"
Expand All @@ -728,6 +743,7 @@ type UploadDropzoneProps = {
}} />

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="ready"
content={{
Expand All @@ -752,9 +768,9 @@ appearance={{
}} />

<UploadButton
endpoint="mockRoute"
__internal_button_disabled
__internal_state="uploading"
__internal_ready={true}
content={{
button({ ready }) {
if (ready) return <div>Upload stuff</div>;
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal-appdir/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function Home() {
onUploadBegin={() => {
console.log("upload begin");
}}
config={{ appendOnPaste: true }}
config={{ appendOnPaste: true, mode: "manual" }}
/>
<UploadDropzone
/**
Expand Down
3 changes: 3 additions & 0 deletions examples/with-novel/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Go to https://uploadthing.com/dashboard to get your API secret
UPLOADTHING_SECRET='sk_live_xxx'
UPLOADTHING_APP_ID='xxx'
27 changes: 27 additions & 0 deletions examples/with-novel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Integrating UploadThing with Novel

<a href="https://stackblitz.com/github/pingdotgg/uploadthing/tree/main/examples/with-novel">
<img height="64" src="https://github.com/pingdotgg/uploadthing/assets/51714798/45907a4e-aa64-401a-afb3-b6c6df6eb71f" />
</a>

This is a stripped down version of the Novel Web app. See the original full
source code at: https://github.com/steven-tey/novel/tree/main/apps/web

For the UploadThing specific code in this example, see
[uploadthing/novel-plugin.ts](./uploadthing/novel-plugin.ts).

## QuickStart

1. Grab an API key from the UploadThing dashboard:
https://uploadthing.com/dashboard
2. `cp .env.example .env` and paste in your API key in the newly created `.env`
file
3. `pnpm i && pnpm dev`
4. Use the editor and upload files!

## Further reference

Check out the docs at:

- https://docs.uploadthing.com/getting-started/appdir
- https://novel.sh/docs
Binary file not shown.
47 changes: 47 additions & 0 deletions examples/with-novel/app/_styles/fonts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Crimson_Text, Inconsolata, Inter } from "next/font/google";
import localFont from "next/font/local";

export const cal = localFont({
src: "./CalSans-SemiBold.otf",
variable: "--font-title",
});

export const crimsonBold = Crimson_Text({
weight: "700",
variable: "--font-title",
subsets: ["latin"],
});

export const inter = Inter({
variable: "--font-default",
subsets: ["latin"],
});

export const inconsolataBold = Inconsolata({
weight: "700",
variable: "--font-title",
subsets: ["latin"],
});

export const crimson = Crimson_Text({
weight: "400",
variable: "--font-default",
subsets: ["latin"],
});

export const inconsolata = Inconsolata({
variable: "--font-default",
subsets: ["latin"],
});

export const titleFontMapper = {
Default: cal.variable,
Serif: crimsonBold.variable,
Mono: inconsolataBold.variable,
};

export const defaultFontMapper = {
Default: inter.variable,
Serif: crimson.variable,
Mono: inconsolata.variable,
};
96 changes: 96 additions & 0 deletions examples/with-novel/app/_styles/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;

--radius: 0.5rem;

--novel-highlight-default: #ffffff;
--novel-highlight-purple: #f6f3f8;
--novel-highlight-red: #fdebeb;
--novel-highlight-yellow: #fbf4a2;
--novel-highlight-blue: #c1ecf9;
--novel-highlight-green: #acf79f;
--novel-highlight-orange: #faebdd;
--novel-highlight-pink: #faf1f5;
--novel-highlight-gray: #f1f1ef;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;

--novel-highlight-default: #000000;
--novel-highlight-purple: #3f2c4b;
--novel-highlight-red: #5c1a1a;
--novel-highlight-yellow: #5c4b1a;
--novel-highlight-blue: #1a3d5c;
--novel-highlight-green: #1a5c20;
--novel-highlight-orange: #5c3a1a;
--novel-highlight-pink: #5c1a3a;
--novel-highlight-gray: #3a3a3a;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
Loading