Thanks to visit codestin.com
Credit goes to github.com

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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import {
CardSelector,
CardSelectorOption,
NumberStepper,
RichTextArea,
RichTextProvider,
RichTextToolbar,
Sheet,
SmartDateTimePicker,
Switch,
Expand Down Expand Up @@ -803,31 +806,45 @@ function BountySheetContent({ setIsOpen, bounty }: BountySheetProps) {
)}

<div>
<label
htmlFor="description"
className="text-sm font-medium text-neutral-800"
>
<label className="text-sm font-medium text-neutral-800">
Details
<span className="ml-1 font-normal text-neutral-500">
(optional)
</span>
</label>
<div className="mt-2">
<textarea
id="description"
rows={3}
maxLength={BOUNTY_DESCRIPTION_MAX_LENGTH}
className={cn(
"block w-full rounded-md border-neutral-300 text-neutral-900 placeholder-neutral-400 focus:border-neutral-500 focus:outline-none focus:ring-neutral-500 sm:text-sm",
errors.description &&
"border-red-600 focus:border-red-500 focus:ring-red-600",
<Controller
control={control}
name="description"
render={({ field }) => (
<RichTextProvider
features={["bold", "italic", "links"]}
markdown
placeholder="Provide any bounty requirements to the partner"
editorClassName="block max-h-24 overflow-hidden w-full resize-none border-none p-3 text-base sm:text-sm"
initialValue={field.value}
onChange={(editor) =>
field.onChange(
(editor as any).getMarkdown() || null,
)
}
>
<div
className={cn(
"border-border-subtle overflow-hidden rounded-md border border-neutral-300 focus-within:border-neutral-500 focus-within:ring-1 focus-within:ring-neutral-500",
errors.description &&
"border-red-600 focus-within:border-red-500 focus-within:ring-red-600",
)}
>
<div className="flex flex-col">
<RichTextArea />
<RichTextToolbar className="px-1 pb-1" />
</div>
</div>
</RichTextProvider>
)}
placeholder="Provide any bounty requirements to the partner"
{...register("description", {
setValueAs: (value) =>
value === "" ? null : value,
})}
/>

<div className="mt-1 text-left">
<span className="text-xs text-neutral-400">
{description?.length || 0} /{" "}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
Lock,
PaperPlane,
RichTextArea,
RichTextProvider,
RichTextToolbar,
SmartDateTimePicker,
StatusBadge,
Tooltip,
Expand Down Expand Up @@ -506,7 +508,7 @@ export function CampaignEditor({ campaign }: { campaign: Campaign }) {
control={control}
name="bodyJson"
render={({ field }) => (
<RichTextArea
<RichTextProvider
ref={editorRef}
editorClassName="-m-2 min-h-[200px] p-2"
initialValue={field.value}
Expand Down Expand Up @@ -548,7 +550,12 @@ export function CampaignEditor({ campaign }: { campaign: Campaign }) {

return null;
}}
/>
>
<div className="flex flex-col gap-4">
<RichTextToolbar />
<RichTextArea />
</div>
</RichTextProvider>
)}
/>
</div>
Expand Down
44 changes: 33 additions & 11 deletions apps/web/ui/messages/messages-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {
useMediaQuery,
} from "@dub/ui";
import { OG_AVATAR_URL, cn, formatDate } from "@dub/utils";
import Linkify from "linkify-react";
import { ChevronRight } from "lucide-react";
import { Fragment, useMemo, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { MessageInput } from "../shared/message-input";
import { MessageMarkdown } from "./message-markdown";

Expand Down Expand Up @@ -176,22 +177,43 @@ export function MessagesPanel({
{/* Message box */}
<div
className={cn(
"max-w-[min(100%,512px)] whitespace-pre-wrap break-words rounded-xl px-4 py-2.5 text-sm",
"max-w-[min(100%,512px)] rounded-xl px-4 py-2.5 text-sm",
isMySide
? "text-content-inverted rounded-br bg-neutral-700"
: "text-content-default rounded-bl bg-neutral-100",
? "rounded-br bg-neutral-700"
: "rounded-bl bg-neutral-100",
)}
>
<Linkify
as="p"
options={{
target: "_blank",
rel: "noopener noreferrer nofollow",
className: "underline underline-offset-4",
<ReactMarkdown
className={cn(
isMySide
? "text-content-inverted prose-invert prose-a:text-content-inverted"
: "text-content-default prose-a:text-content-emphasis",
"prose prose-sm prose-p:m-0 break-words",
"prose-a:font-medium prose-a:underline-offset-4",
)}
allowedElements={[
"p",
"a",
"code",
"strong",
"em",
"ul",
"ol",
"li",
]}
components={{
a: ({ node, ...props }) => (
<a
{...props}
target="_blank"
rel="noopener noreferrer"
/>
),
}}
remarkPlugins={[remarkGfm] as any}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix the type assertion.

The as any assertion bypasses TypeScript's type safety. The type mismatch between remarkGfm and the expected plugin type should be resolved properly.

This typically happens when the plugin types don't match the version of react-markdown. Consider:

remarkPlugins={[remarkGfm]}

If the type error persists, verify that the versions of react-markdown, remark-gfm, and their type definitions are compatible, or use a more specific type assertion like:

remarkPlugins={[remarkGfm] as PluggableList}
🤖 Prompt for AI Agents
In apps/web/ui/messages/messages-panel.tsx around line 213, the code uses a
broad `as any` for remarkPlugins which bypasses TypeScript safety; replace the
unsafe assertion with the correct plugin list type (e.g. use the PluggableList
type from the unified/react-markdown types) and import that type, i.e. cast the
array to the proper PluggableList instead of any; if the type error persists,
ensure react-markdown and remark-gfm versions (and their type defs) are
compatible and update/install matching types so the plugin type matches without
using `any`.

>
{message.text}
</Linkify>
</ReactMarkdown>
</div>
</div>
</div>
Expand Down
10 changes: 7 additions & 3 deletions apps/web/ui/partners/bounties/claim-bounty-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "@/lib/zod/schemas/bounties";
import { useConfirmModal } from "@/ui/modals/confirm-modal";
import { X } from "@/ui/shared/icons";
import { Markdown } from "@/ui/shared/markdown";
import {
AnimatedSizeContainer,
Button,
Expand Down Expand Up @@ -413,8 +414,8 @@ function ClaimBountyModalContent({ bounty }: ClaimBountyModalProps) {
<span className="text-content-emphasis font-semibold">
Details
</span>
<p className="text-content-subtle whitespace-pre-wrap font-medium">
{bounty.description}
<p className="text-content-subtle font-medium">
<Markdown className="p-0">{bounty.description}</Markdown>
</p>
Comment on lines +417 to 419
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove the <p> wrapper around Markdown output

Markdown can emit block elements (<p>, <ul>, etc.). Nesting those inside this <p> gives invalid markup and can break spacing/styling in browsers. Drop the wrapper and move the styling onto Markdown itself.

-                    <p className="text-content-subtle font-medium">
-                      <Markdown className="p-0">{bounty.description}</Markdown>
-                    </p>
+                    <Markdown className="text-content-subtle font-medium p-0">
+                      {bounty.description}
+                    </Markdown>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p className="text-content-subtle font-medium">
<Markdown className="p-0">{bounty.description}</Markdown>
</p>
<Markdown className="text-content-subtle font-medium p-0">
{bounty.description}
</Markdown>
🤖 Prompt for AI Agents
In apps/web/ui/partners/bounties/claim-bounty-modal.tsx around lines 417 to 419,
remove the outer <p> that wraps the <Markdown> output because Markdown can emit
block-level elements and nesting them inside a <p> produces invalid markup;
instead apply the current className and font styling directly to the <Markdown>
component (e.g., move "text-content-subtle font-medium p-0" onto <Markdown>) so
the same styling is preserved without illegal HTML nesting.

</div>
)}
Expand Down Expand Up @@ -587,7 +588,10 @@ function ClaimBountyModalContent({ bounty }: ClaimBountyModalProps) {
value={description}
onChange={(e) => {
const value = e.target.value;
if (value.length <= MAX_BOUNTY_SUBMISSION_DESCRIPTION_LENGTH) {
if (
value.length <=
MAX_BOUNTY_SUBMISSION_DESCRIPTION_LENGTH
) {
setDescription(value);
}
}}
Expand Down
11 changes: 1 addition & 10 deletions apps/web/ui/partners/partner-comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,16 +347,7 @@ function CommentCard({
toast.error("Failed to update comment");
});
}}
onMount={({ textarea }) => {
if (!textarea) return;

// Programmatically focus and move cursor to the end, since React's autoFocus is putting the cursor at the start
textarea.focus();
textarea.setSelectionRange(
textarea.value.length,
textarea.value.length,
);
}}
autoFocus
className="animate-fade-in"
placeholder="Edit comment"
sendButtonText="Save"
Expand Down
23 changes: 12 additions & 11 deletions apps/web/ui/shared/emoji-picker.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"use client";

import { Button, Popover } from "@dub/ui";
import { FaceSmile } from "@dub/ui/icons";
import { EmojiPicker as EmojiPickerBase } from "frimousse";
import { useState } from "react";
import { PropsWithChildren, useState } from "react";

export function EmojiPicker({
onSelect,
}: {
children,
}: PropsWithChildren<{
onSelect: (emoji: string) => void;
}) {
}>) {
const [isOpen, setIsOpen] = useState(false);

return (
Expand Down Expand Up @@ -65,12 +64,14 @@ export function EmojiPicker({
</EmojiPickerBase.Root>
}
>
<Button
type="button"
variant="outline"
icon={<FaceSmile className="size-4" />}
className="size-8 p-0"
/>
{children || (
<Button
type="button"
variant="outline"
icon={<FaceSmile className="size-4" />}
className="size-8 p-0"
/>
)}
</Popover>
);
}
Loading