mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
chore: linting
This commit is contained in:
parent
08c75127f1
commit
634f6f24bf
50 changed files with 292 additions and 355 deletions
|
|
@ -271,7 +271,7 @@ def format_documents_for_context(documents: list[dict[str, Any]]) -> str:
|
|||
|
||||
# Live search connectors whose results should be cited by URL rather than
|
||||
# a numeric chunk_id (the numeric IDs are meaningless auto-incremented counters).
|
||||
_LIVE_SEARCH_CONNECTORS = {
|
||||
live_search_connectors = {
|
||||
"TAVILY_API",
|
||||
"SEARXNG_API",
|
||||
"LINKUP_API",
|
||||
|
|
@ -282,7 +282,7 @@ def format_documents_for_context(documents: list[dict[str, Any]]) -> str:
|
|||
parts: list[str] = []
|
||||
for g in grouped.values():
|
||||
metadata_json = json.dumps(g["metadata"], ensure_ascii=False)
|
||||
is_live_search = g["document_type"] in _LIVE_SEARCH_CONNECTORS
|
||||
is_live_search = g["document_type"] in live_search_connectors
|
||||
|
||||
parts.append("<document>")
|
||||
parts.append("<document_metadata>")
|
||||
|
|
|
|||
|
|
@ -89,9 +89,7 @@ class WebCrawlerConnector:
|
|||
return await self._crawl_with_firecrawl(url, formats), None
|
||||
except Exception as exc:
|
||||
errors.append(f"Firecrawl: {exc!s}")
|
||||
logger.warning(
|
||||
f"[webcrawler] Firecrawl failed for {url}: {exc!s}"
|
||||
)
|
||||
logger.warning(f"[webcrawler] Firecrawl failed for {url}: {exc!s}")
|
||||
|
||||
# --- 2. HTTP + Trafilatura (no subprocess required) ---
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -69,11 +69,7 @@ const categoryConfig: Record<
|
|||
// Announcement card
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function AnnouncementCard({
|
||||
announcement,
|
||||
}: {
|
||||
announcement: AnnouncementWithState;
|
||||
}) {
|
||||
function AnnouncementCard({ announcement }: { announcement: AnnouncementWithState }) {
|
||||
const config = categoryConfig[announcement.category] ?? categoryConfig.info;
|
||||
const Icon = config.icon;
|
||||
|
||||
|
|
@ -179,10 +175,7 @@ export default function AnnouncementsPage() {
|
|||
) : (
|
||||
<div className="flex flex-col gap-4">
|
||||
{announcements.map((announcement) => (
|
||||
<AnnouncementCard
|
||||
key={announcement.id}
|
||||
announcement={announcement}
|
||||
/>
|
||||
<AnnouncementCard key={announcement.id} announcement={announcement} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export function AnnouncementToastProvider() {
|
|||
const authed = isAuthenticated();
|
||||
const active = getActiveAnnouncements(announcements, authed);
|
||||
const importantUntoasted = active.filter(
|
||||
(a) => a.isImportant && !isAnnouncementToasted(a.id),
|
||||
(a) => a.isImportant && !isAnnouncementToasted(a.id)
|
||||
);
|
||||
|
||||
for (let i = 0; i < importantUntoasted.length; i++) {
|
||||
|
|
|
|||
|
|
@ -64,9 +64,7 @@ export const ConnectorConnectView: FC<ConnectorConnectViewProps> = ({
|
|||
const formId = FORM_ID_MAP[connectorType];
|
||||
const root = formContainerRef.current;
|
||||
const mappedForm =
|
||||
root && formId
|
||||
? (root.querySelector(`[id="${formId}"]`) as HTMLFormElement | null)
|
||||
: null;
|
||||
root && formId ? (root.querySelector(`[id="${formId}"]`) as HTMLFormElement | null) : null;
|
||||
// Fallback to currently rendered form to avoid silent no-op
|
||||
// when a connector type or form id mapping drifts.
|
||||
const fallbackForm = root?.querySelector("form") as HTMLFormElement | null;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { useState } from "react";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { SourceDetailPanel } from "@/components/new-chat/source-detail-panel";
|
||||
|
||||
interface InlineCitationProps {
|
||||
|
|
@ -14,10 +14,7 @@ interface InlineCitationProps {
|
|||
* Inline citation for knowledge-base chunks (numeric chunk IDs).
|
||||
* Renders a clickable badge showing the actual chunk ID that opens the SourceDetailPanel.
|
||||
*/
|
||||
export const InlineCitation: FC<InlineCitationProps> = ({
|
||||
chunkId,
|
||||
isDocsChunk = false,
|
||||
}) => {
|
||||
export const InlineCitation: FC<InlineCitationProps> = ({ chunkId, isDocsChunk = false }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function preprocessMarkdown(content: string): string {
|
|||
_pendingUrlCitations = new Map();
|
||||
_urlCiteIdx = 0;
|
||||
content = content.replace(
|
||||
/[[【]\u200B?citation:\s*(https?:\/\/[^\]\】\u200B]+)\s*\u200B?[\]】]/g,
|
||||
/[[【]\u200B?citation:\s*(https?:\/\/[^\]】\u200B]+)\s*\u200B?[\]】]/g,
|
||||
(_, url) => {
|
||||
const key = `urlcite${_urlCiteIdx++}`;
|
||||
_pendingUrlCitations.set(key, url.trim());
|
||||
|
|
@ -73,7 +73,7 @@ function preprocessMarkdown(content: string): string {
|
|||
// URL-based IDs from live web search, or urlciteN placeholders from preprocess.
|
||||
// Also matches Chinese brackets 【】 and handles zero-width spaces that LLM sometimes inserts.
|
||||
const CITATION_REGEX =
|
||||
/[[【]\u200B?citation:\s*(https?:\/\/[^\]\】\u200B]+|urlcite\d+|(?:doc-)?\d+(?:\s*,\s*(?:doc-)?\d+)*)\s*\u200B?[\]】]/g;
|
||||
/[[【]\u200B?citation:\s*(https?:\/\/[^\]】\u200B]+|urlcite\d+|(?:doc-)?\d+(?:\s*,\s*(?:doc-)?\d+)*)\s*\u200B?[\]】]/g;
|
||||
|
||||
/**
|
||||
* Parses text and replaces [citation:XXX] patterns with citation components.
|
||||
|
|
@ -100,16 +100,12 @@ function parseTextWithCitations(text: string): ReactNode[] {
|
|||
const captured = match[1];
|
||||
|
||||
if (captured.startsWith("http://") || captured.startsWith("https://")) {
|
||||
parts.push(
|
||||
<UrlCitation key={`citation-url-${instanceIndex}`} url={captured.trim()} />
|
||||
);
|
||||
parts.push(<UrlCitation key={`citation-url-${instanceIndex}`} url={captured.trim()} />);
|
||||
instanceIndex++;
|
||||
} else if (captured.startsWith("urlcite")) {
|
||||
const url = _pendingUrlCitations.get(captured);
|
||||
if (url) {
|
||||
parts.push(
|
||||
<UrlCitation key={`citation-url-${instanceIndex}`} url={url} />
|
||||
);
|
||||
parts.push(<UrlCitation key={`citation-url-${instanceIndex}`} url={url} />);
|
||||
}
|
||||
instanceIndex++;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import { MarkdownPlugin, remarkMdx } from "@platejs/markdown";
|
||||
import type { AnyPluginConfig } from "platejs";
|
||||
import { createPlatePlugin, Key, Plate, usePlateEditor } from "platejs/react";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import remarkMath from "remark-math";
|
||||
|
||||
import { type EditorPreset, presetMap } from "@/components/editor/presets";
|
||||
import { Editor, EditorContainer } from "@/components/ui/editor";
|
||||
import { escapeMdxExpressions } from "@/components/editor/utils/escape-mdx";
|
||||
import { EditorSaveContext } from "@/components/editor/editor-save-context";
|
||||
import { type EditorPreset, presetMap } from "@/components/editor/presets";
|
||||
import { escapeMdxExpressions } from "@/components/editor/utils/escape-mdx";
|
||||
import { Editor, EditorContainer } from "@/components/ui/editor";
|
||||
|
||||
export interface PlateEditorProps {
|
||||
/** Markdown string to load as initial content */
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
import type { AutoformatRule } from "@platejs/autoformat";
|
||||
|
||||
import {
|
||||
AutoformatPlugin,
|
||||
autoformatArrow,
|
||||
autoformatLegal,
|
||||
autoformatLegalHtml,
|
||||
autoformatMath,
|
||||
AutoformatPlugin,
|
||||
autoformatPunctuation,
|
||||
autoformatSmartQuotes,
|
||||
} from "@platejs/autoformat";
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { DndPlugin } from "@platejs/dnd";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
|
||||
import { DndPlugin } from "@platejs/dnd";
|
||||
|
||||
import { BlockDraggable } from "@/components/ui/block-draggable";
|
||||
|
||||
export const DndKit = [
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
"use client";
|
||||
|
||||
import type { PlateEditor } from "platejs/react";
|
||||
|
||||
import { insertCallout } from "@platejs/callout";
|
||||
import { insertCodeBlock, toggleCodeBlock } from "@platejs/code-block";
|
||||
import { triggerFloatingLink } from "@platejs/link/react";
|
||||
import { insertInlineEquation } from "@platejs/math";
|
||||
import { TablePlugin } from "@platejs/table/react";
|
||||
import { type NodeEntry, type Path, type TElement, KEYS, PathApi } from "platejs";
|
||||
import { KEYS, type NodeEntry, type Path, PathApi, type TElement } from "platejs";
|
||||
import type { PlateEditor } from "platejs/react";
|
||||
|
||||
const insertList = (editor: PlateEditor, type: string) => {
|
||||
editor.tf.insertNodes(
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ export function PostHogIdentify() {
|
|||
|
||||
// Only identify if this is a new user or different from previous
|
||||
if (previousUserIdRef.current !== userId) {
|
||||
identifyUser(userId, {
|
||||
email: user.email,
|
||||
name: user.display_name,
|
||||
is_superuser: user.is_superuser,
|
||||
is_verified: user.is_verified,
|
||||
});
|
||||
identifyUser(userId, {
|
||||
email: user.email,
|
||||
name: user.display_name,
|
||||
is_superuser: user.is_superuser,
|
||||
is_verified: user.is_verified,
|
||||
});
|
||||
previousUserIdRef.current = userId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,58 +300,58 @@ export function LLMConfigForm({
|
|||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0" align="start">
|
||||
<Command shouldFilter={false}>
|
||||
<CommandInput
|
||||
placeholder={selectedProvider?.example || "Type model name..."}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
<CommandList className="max-h-[300px]">
|
||||
<CommandEmpty>
|
||||
<div className="py-3 text-center text-sm text-muted-foreground">
|
||||
{field.value ? `Using: "${field.value}"` : "Type your model name"}
|
||||
</div>
|
||||
</CommandEmpty>
|
||||
{availableModels.length > 0 && (
|
||||
<CommandGroup heading="Suggested Models">
|
||||
{availableModels
|
||||
.filter(
|
||||
(model) =>
|
||||
!field.value ||
|
||||
model.value.toLowerCase().includes(field.value.toLowerCase()) ||
|
||||
model.label.toLowerCase().includes(field.value.toLowerCase())
|
||||
)
|
||||
.slice(0, 50)
|
||||
.map((model) => (
|
||||
<CommandItem
|
||||
key={model.value}
|
||||
value={model.value}
|
||||
onSelect={(value) => {
|
||||
field.onChange(value);
|
||||
setModelComboboxOpen(false);
|
||||
}}
|
||||
className="py-2"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
field.value === model.value ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{model.label}</div>
|
||||
{model.contextWindow && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Context: {model.contextWindow}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</CommandList>
|
||||
</Command>
|
||||
<Command shouldFilter={false}>
|
||||
<CommandInput
|
||||
placeholder={selectedProvider?.example || "Type model name..."}
|
||||
value={field.value}
|
||||
onValueChange={field.onChange}
|
||||
/>
|
||||
<CommandList className="max-h-[300px]">
|
||||
<CommandEmpty>
|
||||
<div className="py-3 text-center text-sm text-muted-foreground">
|
||||
{field.value ? `Using: "${field.value}"` : "Type your model name"}
|
||||
</div>
|
||||
</CommandEmpty>
|
||||
{availableModels.length > 0 && (
|
||||
<CommandGroup heading="Suggested Models">
|
||||
{availableModels
|
||||
.filter(
|
||||
(model) =>
|
||||
!field.value ||
|
||||
model.value.toLowerCase().includes(field.value.toLowerCase()) ||
|
||||
model.label.toLowerCase().includes(field.value.toLowerCase())
|
||||
)
|
||||
.slice(0, 50)
|
||||
.map((model) => (
|
||||
<CommandItem
|
||||
key={model.value}
|
||||
value={model.value}
|
||||
onSelect={(value) => {
|
||||
field.onChange(value);
|
||||
setModelComboboxOpen(false);
|
||||
}}
|
||||
className="py-2"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
field.value === model.value ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{model.label}</div>
|
||||
{model.contextWindow && (
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Context: {model.contextWindow}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
)}
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{selectedProvider?.example && (
|
||||
|
|
|
|||
|
|
@ -215,9 +215,9 @@ function ApprovalCard({
|
|||
onValueChange={(v) => {
|
||||
setSelectedWorkspaceId(v);
|
||||
setSelectedTeamId("");
|
||||
setSelectedStateId("__none__");
|
||||
setSelectedAssigneeId("__none__");
|
||||
setSelectedPriority("0");
|
||||
setSelectedStateId("__none__");
|
||||
setSelectedAssigneeId("__none__");
|
||||
setSelectedPriority("0");
|
||||
setSelectedLabelIds([]);
|
||||
}}
|
||||
>
|
||||
|
|
@ -243,13 +243,13 @@ function ApprovalCard({
|
|||
</div>
|
||||
<Select
|
||||
value={selectedTeamId}
|
||||
onValueChange={(v) => {
|
||||
setSelectedTeamId(v);
|
||||
const newTeam = selectedWorkspace.teams.find((t) => t.id === v);
|
||||
setSelectedStateId(newTeam?.states?.[0]?.id ?? "__none__");
|
||||
setSelectedAssigneeId("__none__");
|
||||
setSelectedLabelIds([]);
|
||||
}}
|
||||
onValueChange={(v) => {
|
||||
setSelectedTeamId(v);
|
||||
const newTeam = selectedWorkspace.teams.find((t) => t.id === v);
|
||||
setSelectedStateId(newTeam?.states?.[0]?.id ?? "__none__");
|
||||
setSelectedAssigneeId("__none__");
|
||||
setSelectedLabelIds([]);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a team" />
|
||||
|
|
|
|||
|
|
@ -415,134 +415,134 @@ function ApprovalCard({
|
|||
>
|
||||
New Title
|
||||
</label>
|
||||
<Input
|
||||
id="linear-update-title"
|
||||
value={editedArgs.title}
|
||||
onChange={(e) => setEditedArgs({ ...editedArgs, title: e.target.value })}
|
||||
placeholder="Issue title"
|
||||
/>
|
||||
</div>
|
||||
<Input
|
||||
id="linear-update-title"
|
||||
value={editedArgs.title}
|
||||
onChange={(e) => setEditedArgs({ ...editedArgs, title: e.target.value })}
|
||||
placeholder="Issue title"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="linear-update-description"
|
||||
className="text-xs font-medium text-muted-foreground mb-1.5 block"
|
||||
>
|
||||
Description
|
||||
</label>
|
||||
<Textarea
|
||||
id="linear-update-description"
|
||||
value={editedArgs.description}
|
||||
onChange={(e) => setEditedArgs({ ...editedArgs, description: e.target.value })}
|
||||
placeholder="Issue description"
|
||||
rows={5}
|
||||
className="resize-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="linear-update-description"
|
||||
className="text-xs font-medium text-muted-foreground mb-1.5 block"
|
||||
>
|
||||
Description
|
||||
</label>
|
||||
<Textarea
|
||||
id="linear-update-description"
|
||||
value={editedArgs.description}
|
||||
onChange={(e) => setEditedArgs({ ...editedArgs, description: e.target.value })}
|
||||
placeholder="Issue description"
|
||||
rows={5}
|
||||
className="resize-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{team && (
|
||||
<>
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">State</div>
|
||||
<Select
|
||||
value={editedArgs.stateId}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, stateId: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select state" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{team.states.map((s) => (
|
||||
<SelectItem key={s.id} value={s.id}>
|
||||
{s.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Assignee</div>
|
||||
<Select
|
||||
value={editedArgs.assigneeId}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, assigneeId: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select assignee" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none__">Unassigned</SelectItem>
|
||||
{team.members
|
||||
.filter((m) => m.active)
|
||||
.map((m) => (
|
||||
<SelectItem key={m.id} value={m.id}>
|
||||
{m.name} ({m.email})
|
||||
{team && (
|
||||
<>
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">State</div>
|
||||
<Select
|
||||
value={editedArgs.stateId}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, stateId: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select state" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{team.states.map((s) => (
|
||||
<SelectItem key={s.id} value={s.id}>
|
||||
{s.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Priority</div>
|
||||
<Select
|
||||
value={editedArgs.priority}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, priority: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select priority" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{priorities.map((p) => (
|
||||
<SelectItem key={p.priority} value={String(p.priority)}>
|
||||
{p.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{team.labels.length > 0 && (
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Labels</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{team.labels.map((label) => {
|
||||
const isSelected = editedArgs.labelIds.includes(label.id);
|
||||
return (
|
||||
<button
|
||||
key={label.id}
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setEditedArgs({
|
||||
...editedArgs,
|
||||
labelIds: isSelected
|
||||
? editedArgs.labelIds.filter((id) => id !== label.id)
|
||||
: [...editedArgs.labelIds, label.id],
|
||||
})
|
||||
}
|
||||
className={`inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium transition-opacity ${
|
||||
isSelected
|
||||
? "opacity-100 ring-2 ring-foreground/30"
|
||||
: "opacity-50 hover:opacity-80"
|
||||
}`}
|
||||
style={{
|
||||
backgroundColor: `${label.color}33`,
|
||||
color: label.color,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="size-1.5 rounded-full"
|
||||
style={{ backgroundColor: label.color }}
|
||||
/>
|
||||
{label.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Assignee</div>
|
||||
<Select
|
||||
value={editedArgs.assigneeId}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, assigneeId: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select assignee" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="__none__">Unassigned</SelectItem>
|
||||
{team.members
|
||||
.filter((m) => m.active)
|
||||
.map((m) => (
|
||||
<SelectItem key={m.id} value={m.id}>
|
||||
{m.name} ({m.email})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Priority</div>
|
||||
<Select
|
||||
value={editedArgs.priority}
|
||||
onValueChange={(v) => setEditedArgs({ ...editedArgs, priority: v })}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select priority" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{priorities.map((p) => (
|
||||
<SelectItem key={p.priority} value={String(p.priority)}>
|
||||
{p.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{team.labels.length > 0 && (
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-xs font-medium text-muted-foreground">Labels</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{team.labels.map((label) => {
|
||||
const isSelected = editedArgs.labelIds.includes(label.id);
|
||||
return (
|
||||
<button
|
||||
key={label.id}
|
||||
type="button"
|
||||
onClick={() =>
|
||||
setEditedArgs({
|
||||
...editedArgs,
|
||||
labelIds: isSelected
|
||||
? editedArgs.labelIds.filter((id) => id !== label.id)
|
||||
: [...editedArgs.labelIds, label.id],
|
||||
})
|
||||
}
|
||||
className={`inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium transition-opacity ${
|
||||
isSelected
|
||||
? "opacity-100 ring-2 ring-foreground/30"
|
||||
: "opacity-50 hover:opacity-80"
|
||||
}`}
|
||||
style={{
|
||||
backgroundColor: `${label.color}33`,
|
||||
color: label.color,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="size-1.5 rounded-full"
|
||||
style={{ backgroundColor: label.color }}
|
||||
/>
|
||||
{label.name}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -588,10 +588,10 @@ function ApprovalCard({
|
|||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setEditedArgs(initialEditState); // Reset to original args
|
||||
}}
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setEditedArgs(initialEditState); // Reset to original args
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { DndPlugin, useDraggable, useDropLine } from "@platejs/dnd";
|
||||
import { expandListItemsWithChildren } from "@platejs/list";
|
||||
import { BlockSelectionPlugin } from "@platejs/selection/react";
|
||||
import { GripVertical } from "lucide-react";
|
||||
import { type TElement, getPluginByType, isType, KEYS } from "platejs";
|
||||
import { getPluginByType, isType, KEYS, type TElement } from "platejs";
|
||||
import {
|
||||
MemoizedChildren,
|
||||
type PlateEditor,
|
||||
type PlateElementProps,
|
||||
type RenderNodeWrapper,
|
||||
MemoizedChildren,
|
||||
useEditorRef,
|
||||
useElement,
|
||||
usePluginOption,
|
||||
useSelected,
|
||||
} from "platejs/react";
|
||||
import { useSelected } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
import type { TListElement } from "platejs";
|
||||
|
||||
import { isOrderedList } from "@platejs/list";
|
||||
import { useTodoListElement, useTodoListElementState } from "@platejs/list/react";
|
||||
import type { TListElement } from "platejs";
|
||||
import { type PlateElementProps, type RenderNodeWrapper, useReadOnly } from "platejs/react";
|
||||
import type React from "react";
|
||||
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { DndPlugin } from "@platejs/dnd";
|
||||
import { useBlockSelected } from "@platejs/selection/react";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { type PlateElementProps, usePluginOption } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
export const blockSelectionVariants = cva(
|
||||
"pointer-events-none absolute inset-0 z-1 bg-brand/[.13] transition-opacity",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { type PlateElementProps, PlateElement } from "platejs/react";
|
||||
import { PlateElement, type PlateElementProps } from "platejs/react";
|
||||
|
||||
export function BlockquoteElement(props: PlateElementProps) {
|
||||
return <PlateElement as="blockquote" className="my-1 border-l-2 pl-6 italic" {...props} />;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { TCalloutElement } from "platejs";
|
||||
|
||||
import { CalloutPlugin } from "@platejs/callout/react";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { type PlateElementProps, PlateElement, useEditorPlugin } from "platejs/react";
|
||||
import type { TCalloutElement } from "platejs";
|
||||
import { PlateElement, type PlateElementProps, useEditorPlugin } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { CheckIcon } from "lucide-react";
|
||||
import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { formatCodeBlock, isLangSupported } from "@platejs/code-block";
|
||||
import { BracesIcon, Check, CheckIcon, CopyIcon } from "lucide-react";
|
||||
import { type TCodeBlockElement, type TCodeSyntaxLeaf, NodeApi } from "platejs";
|
||||
import { NodeApi, type TCodeBlockElement, type TCodeSyntaxLeaf } from "platejs";
|
||||
import {
|
||||
type PlateElementProps,
|
||||
type PlateLeafProps,
|
||||
PlateElement,
|
||||
type PlateElementProps,
|
||||
PlateLeaf,
|
||||
type PlateLeafProps,
|
||||
useEditorRef,
|
||||
useElement,
|
||||
useReadOnly,
|
||||
} from "platejs/react";
|
||||
import { useEditorRef, useElement, useReadOnly } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { PlateLeafProps } from "platejs/react";
|
||||
|
||||
import { PlateLeaf } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
export function CodeLeaf(props: PlateLeafProps) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
||||
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { VariantProps } from "class-variance-authority";
|
||||
import type { PlateContentProps, PlateViewProps } from "platejs/react";
|
||||
|
||||
import { cva } from "class-variance-authority";
|
||||
import type { PlateContentProps, PlateViewProps } from "platejs/react";
|
||||
import { PlateContainer, PlateContent, PlateView } from "platejs/react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { TEquationElement } from "platejs";
|
||||
|
||||
import { useEquationElement, useEquationInput } from "@platejs/math/react";
|
||||
import { RadicalIcon } from "lucide-react";
|
||||
import { type PlateElementProps, PlateElement, useSelected } from "platejs/react";
|
||||
import type { TEquationElement } from "platejs";
|
||||
import { PlateElement, type PlateElementProps, useSelected } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
BoldIcon,
|
||||
Code2Icon,
|
||||
|
|
@ -15,10 +13,11 @@ import {
|
|||
} from "lucide-react";
|
||||
import { KEYS } from "platejs";
|
||||
import { useEditorReadOnly, useEditorRef } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { useEditorSave } from "@/components/editor/editor-save-context";
|
||||
import { usePlatformShortcut } from "@/hooks/use-platform-shortcut";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { usePlatformShortcut } from "@/hooks/use-platform-shortcut";
|
||||
|
||||
import { InsertToolbarButton } from "./insert-toolbar-button";
|
||||
import { LinkToolbarButton } from "./link-toolbar-button";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { BoldIcon, Code2Icon, ItalicIcon, StrikethroughIcon, UnderlineIcon } from "lucide-react";
|
||||
import { KEYS } from "platejs";
|
||||
import { useEditorReadOnly } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { LinkToolbarButton } from "./link-toolbar-button";
|
||||
import { MarkToolbarButton } from "./mark-toolbar-button";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
type FloatingToolbarState,
|
||||
flip,
|
||||
|
|
@ -12,9 +10,9 @@ import {
|
|||
import { useComposedRef } from "@udecode/cn";
|
||||
import { KEYS } from "platejs";
|
||||
import { useEditorId, useEventEditorValue, usePluginOption } from "platejs/react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import type * as React from "react";
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { Toolbar } from "./toolbar";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
|
||||
import { type VariantProps, cva } from "class-variance-authority";
|
||||
import { PlateElement } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
const headingVariants = cva("relative mb-1", {
|
||||
variants: {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { PlateLeafProps } from "platejs/react";
|
||||
|
||||
import { PlateLeaf } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
export function HighlightLeaf(props: PlateLeafProps) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
|
||||
import { PlateElement, useFocused, useReadOnly, useSelected } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { Point, TElement } from "platejs";
|
||||
|
||||
import {
|
||||
type ComboboxItemProps,
|
||||
Combobox,
|
||||
ComboboxGroup,
|
||||
ComboboxGroupLabel,
|
||||
ComboboxItem,
|
||||
type ComboboxItemProps,
|
||||
ComboboxPopover,
|
||||
ComboboxProvider,
|
||||
ComboboxRow,
|
||||
|
|
@ -24,7 +20,9 @@ import {
|
|||
useHTMLInputCursorState,
|
||||
} from "@platejs/combobox/react";
|
||||
import { cva } from "class-variance-authority";
|
||||
import type { Point, TElement } from "platejs";
|
||||
import { useComposedRef, useEditorRef } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { DropdownMenuProps } from "@radix-ui/react-dropdown-menu";
|
||||
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
FileCodeIcon,
|
||||
|
|
@ -25,14 +22,14 @@ import {
|
|||
} from "lucide-react";
|
||||
import { KEYS } from "platejs";
|
||||
import { type PlateEditor, useEditorRef } from "platejs/react";
|
||||
|
||||
import * as React from "react";
|
||||
import { insertBlock, insertInlineElement } from "@/components/editor/transforms";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { insertBlock, insertInlineElement } from "@/components/editor/transforms";
|
||||
|
||||
import { ToolbarButton, ToolbarMenuGroup } from "./toolbar";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { getLinkAttributes } from "@platejs/link";
|
||||
|
||||
import type { TLinkElement } from "platejs";
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
|
||||
import { getLinkAttributes } from "@platejs/link";
|
||||
import { PlateElement } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { useLinkToolbarButton, useLinkToolbarButtonState } from "@platejs/link/react";
|
||||
import { Link } from "lucide-react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { ToolbarButton } from "./toolbar";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { TLinkElement } from "platejs";
|
||||
|
||||
import { type UseVirtualFloatingOptions, flip, offset } from "@platejs/floating";
|
||||
import { flip, offset, type UseVirtualFloatingOptions } from "@platejs/floating";
|
||||
import { getLinkAttributes } from "@platejs/link";
|
||||
import {
|
||||
type LinkFloatingToolbarState,
|
||||
FloatingLinkUrlInput,
|
||||
type LinkFloatingToolbarState,
|
||||
useFloatingLinkEdit,
|
||||
useFloatingLinkEditState,
|
||||
useFloatingLinkInsert,
|
||||
|
|
@ -16,6 +12,7 @@ import {
|
|||
} from "@platejs/link/react";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { ExternalLink, Link, Text, Unlink } from "lucide-react";
|
||||
import type { TLinkElement } from "platejs";
|
||||
import { KEYS } from "platejs";
|
||||
import {
|
||||
useEditorRef,
|
||||
|
|
@ -23,6 +20,7 @@ import {
|
|||
useFormInputProps,
|
||||
usePluginOption,
|
||||
} from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { useMarkToolbarButton, useMarkToolbarButtonState } from "platejs/react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { ToolbarButton } from "./toolbar";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
|
||||
import { PlateElement } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { VariantProps } from "class-variance-authority";
|
||||
|
||||
import {
|
||||
type ResizeHandle as ResizeHandlePrimitive,
|
||||
Resizable as ResizablePrimitive,
|
||||
type ResizeHandle as ResizeHandlePrimitive,
|
||||
useResizeHandle,
|
||||
useResizeHandleState,
|
||||
} from "@platejs/resizable";
|
||||
|
||||
import type { VariantProps } from "class-variance-authority";
|
||||
import { cva } from "class-variance-authority";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Separator as SeparatorPrimitive } from "radix-ui";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
|
||||
import { SlashInputPlugin } from "@platejs/slash-command/react";
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
|
|
@ -23,8 +19,10 @@ import {
|
|||
TableIcon,
|
||||
} from "lucide-react";
|
||||
import { KEYS } from "platejs";
|
||||
import type { PlateElementProps } from "platejs/react";
|
||||
import { PlateElement, useEditorRef } from "platejs/react";
|
||||
|
||||
import type * as React from "react";
|
||||
import { insertBlock, insertInlineElement } from "@/components/editor/transforms";
|
||||
import {
|
||||
InlineCombobox,
|
||||
InlineComboboxContent,
|
||||
|
|
@ -34,7 +32,6 @@ import {
|
|||
InlineComboboxInput,
|
||||
InlineComboboxItem,
|
||||
} from "@/components/ui/inline-combobox";
|
||||
import { insertBlock, insertInlineElement } from "@/components/editor/transforms";
|
||||
|
||||
interface SlashCommandItem {
|
||||
icon: React.ReactNode;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { useDraggable, useDropLine } from "@platejs/dnd";
|
||||
import { BlockSelectionPlugin, useBlockSelected } from "@platejs/selection/react";
|
||||
import {
|
||||
|
|
@ -26,21 +24,22 @@ import {
|
|||
XIcon,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
KEYS,
|
||||
PathApi,
|
||||
type TElement,
|
||||
type TTableCellElement,
|
||||
type TTableElement,
|
||||
type TTableRowElement,
|
||||
KEYS,
|
||||
PathApi,
|
||||
} from "platejs";
|
||||
import {
|
||||
type PlateElementProps,
|
||||
PlateElement,
|
||||
type PlateElementProps,
|
||||
useComposedRef,
|
||||
useEditorPlugin,
|
||||
useEditorRef,
|
||||
useEditorSelector,
|
||||
useElement,
|
||||
useElementSelector,
|
||||
useFocusedLast,
|
||||
usePluginOption,
|
||||
useReadOnly,
|
||||
|
|
@ -48,7 +47,7 @@ import {
|
|||
useSelected,
|
||||
withHOC,
|
||||
} from "platejs/react";
|
||||
import { useElementSelector } from "platejs/react";
|
||||
import type * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Popover, PopoverContent } from "@/components/ui/popover";
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { useToggleButton, useToggleButtonState } from "@platejs/toggle/react";
|
||||
import { ChevronRightIcon } from "lucide-react";
|
||||
import { type PlateElementProps, PlateElement } from "platejs/react";
|
||||
import { PlateElement, type PlateElementProps } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import * as ToolbarPrimitive from "@radix-ui/react-toolbar";
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||
import { type VariantProps, cva } from "class-variance-authority";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import {
|
||||
DropdownMenuLabel,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import type { DropdownMenuProps } from "@radix-ui/react-dropdown-menu";
|
||||
import type { TElement } from "platejs";
|
||||
|
||||
import { DropdownMenuItemIndicator } from "@radix-ui/react-dropdown-menu";
|
||||
import {
|
||||
CheckIcon,
|
||||
|
|
@ -23,16 +19,17 @@ import {
|
|||
QuoteIcon,
|
||||
SquareIcon,
|
||||
} from "lucide-react";
|
||||
import type { TElement } from "platejs";
|
||||
import { KEYS } from "platejs";
|
||||
import { useEditorRef, useSelectionFragmentProp } from "platejs/react";
|
||||
|
||||
import * as React from "react";
|
||||
import { getBlockType, setBlockType } from "@/components/editor/transforms";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { getBlockType, setBlockType } from "@/components/editor/transforms";
|
||||
|
||||
import { ToolbarButton, ToolbarMenuGroup } from "./toolbar";
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export function useAnnouncements(options: UseAnnouncementsOptions = {}) {
|
|||
(a) => ({
|
||||
...a,
|
||||
isRead: isAnnouncementRead(a.id),
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
if (category) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export function isAnnouncementActive(announcement: Announcement, now = new Date(
|
|||
*/
|
||||
export function announcementMatchesAudience(
|
||||
announcement: Announcement,
|
||||
isAuthenticated: boolean,
|
||||
isAuthenticated: boolean
|
||||
): boolean {
|
||||
switch (announcement.audience) {
|
||||
case "all":
|
||||
|
|
@ -44,10 +44,10 @@ export function announcementMatchesAudience(
|
|||
export function getActiveAnnouncements(
|
||||
announcements: Announcement[],
|
||||
isAuthenticated: boolean,
|
||||
now = new Date(),
|
||||
now = new Date()
|
||||
): Announcement[] {
|
||||
return announcements.filter(
|
||||
(a) => isAnnouncementActive(a, now) && announcementMatchesAudience(a, isAuthenticated),
|
||||
(a) => isAnnouncementActive(a, now) && announcementMatchesAudience(a, isAuthenticated)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ export function getActiveAnnouncements(
|
|||
*/
|
||||
export function msUntilNextTransition(
|
||||
announcements: Announcement[],
|
||||
now = new Date(),
|
||||
now = new Date()
|
||||
): number | null {
|
||||
const nowMs = now.getTime();
|
||||
let nearest: number | null = null;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue