Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e622b6e
improvement(tables): improve table filtering UX
waleedlatif1 Mar 29, 2026
bcc7974
fix(table-filter): use ref to stabilize handleRemove/handleApply call…
waleedlatif1 Mar 29, 2026
5d037ac
improvement(tables,kb): remove hacky patterns, fix KB filter popover …
waleedlatif1 Mar 29, 2026
2e67864
feat(knowledge): add sort and filter to KB list page
waleedlatif1 Mar 29, 2026
866e91d
feat(files): add sort and filter to files list page
waleedlatif1 Mar 29, 2026
6c18471
feat(scheduled-tasks): add sort and filter to scheduled tasks page
waleedlatif1 Mar 29, 2026
f46f83c
fix(table-filter): use explicit close handler instead of toggle
waleedlatif1 Mar 29, 2026
8a1f3dc
improvement(files,knowledge): replace manual debounce with useDebounc…
waleedlatif1 Mar 29, 2026
4899dc3
fix(resource): prevent popover from inheriting anchor min-width
waleedlatif1 Mar 29, 2026
f6edb88
feat(tables): add sort to tables list page
waleedlatif1 Mar 29, 2026
51c9df9
feat(knowledge): add content and owner filters to KB list
waleedlatif1 Mar 29, 2026
12ea734
feat(scheduled-tasks): add status and health filters
waleedlatif1 Mar 29, 2026
a3ffc2f
feat(files): add size and uploaded-by filters to files list
waleedlatif1 Mar 29, 2026
0142c69
feat(tables): add row count, owner, and column type filters
waleedlatif1 Mar 29, 2026
2553cac
improvement(scheduled-tasks): use combobox filter panel matching logs…
waleedlatif1 Mar 29, 2026
9dd3028
improvement(knowledge): use combobox filter panel matching logs UI style
waleedlatif1 Mar 29, 2026
446a665
improvement(files): use combobox filter panel matching logs UI style
waleedlatif1 Mar 29, 2026
c56e3ac
improvement(tables): use combobox filter panel matching logs UI style
waleedlatif1 Mar 29, 2026
f0e988d
feat(settings): add sort to recently deleted page
waleedlatif1 Mar 29, 2026
bf0bcf3
feat(logs): add sort to logs page
waleedlatif1 Mar 29, 2026
ffe6806
improvement(knowledge): upgrade document list filter to combobox style
waleedlatif1 Mar 29, 2026
483c35c
fix(resources): fix missing imports, memoization, and stale refs acro…
waleedlatif1 Mar 29, 2026
c8672f7
improvement(tables): remove column type filter
waleedlatif1 Mar 29, 2026
71794bb
fix(resources): fix filter/sort correctness issues from audit
waleedlatif1 Mar 29, 2026
aeeec6b
fix(chunks): add server-side sort to document chunks API
waleedlatif1 Mar 29, 2026
7b13a1a
perf(resources): memoize filterContent JSX across all resource pages
waleedlatif1 Mar 29, 2026
90bd958
fix(resources): add missing sort options for all visible columns
waleedlatif1 Mar 29, 2026
0318725
whitelabeling updates, sidebar fixes, files bug
waleedlatif1 Mar 29, 2026
432e4d0
increased type safety
waleedlatif1 Mar 29, 2026
f8a26a3
pr fixes
waleedlatif1 Mar 29, 2026
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
Prev Previous commit
Next Next commit
increased type safety
  • Loading branch information
waleedlatif1 committed Mar 29, 2026
commit 432e4d09ee45dd7234b171cbef8f62e95427d3a9
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client'

import { createContext, memo, useContext, useMemo, useRef } from 'react'
import type { Components, ExtraProps } from 'react-markdown'
import ReactMarkdown from 'react-markdown'
import remarkBreaks from 'remark-breaks'
import remarkGfm from 'remark-gfm'
Expand Down Expand Up @@ -83,33 +84,38 @@ const MarkdownCheckboxCtx = createContext<{
const CheckboxIndexCtx = createContext(-1)

const STATIC_MARKDOWN_COMPONENTS = {
p: ({ children }: any) => (
p: ({ children }: { children?: React.ReactNode }) => (
<p className='mb-3 break-words text-[14px] text-[var(--text-primary)] leading-[1.6] last:mb-0'>
{children}
</p>
),
h1: ({ children }: any) => (
h1: ({ children }: { children?: React.ReactNode }) => (
<h1 className='mt-6 mb-4 break-words font-semibold text-[24px] text-[var(--text-primary)] first:mt-0'>
{children}
</h1>
),
h2: ({ children }: any) => (
h2: ({ children }: { children?: React.ReactNode }) => (
<h2 className='mt-5 mb-3 break-words font-semibold text-[20px] text-[var(--text-primary)] first:mt-0'>
{children}
</h2>
),
h3: ({ children }: any) => (
h3: ({ children }: { children?: React.ReactNode }) => (
<h3 className='mt-4 mb-2 break-words font-semibold text-[16px] text-[var(--text-primary)] first:mt-0'>
{children}
</h3>
),
h4: ({ children }: any) => (
h4: ({ children }: { children?: React.ReactNode }) => (
<h4 className='mt-3 mb-2 break-words font-semibold text-[14px] text-[var(--text-primary)] first:mt-0'>
{children}
</h4>
),
code: ({ inline, className, children, ...props }: any) => {
const isInline = inline || !className?.includes('language-')
code: ({
className,
children,
node: _node,
...props
}: React.HTMLAttributes<HTMLElement> & ExtraProps) => {
const isInline = !className?.includes('language-')

if (isInline) {
return (
Expand All @@ -131,8 +137,8 @@ const STATIC_MARKDOWN_COMPONENTS = {
</code>
)
},
pre: ({ children }: any) => <>{children}</>,
a: ({ href, children }: any) => (
pre: ({ children }: { children?: React.ReactNode }) => <>{children}</>,
a: ({ href, children }: { href?: string; children?: React.ReactNode }) => (
<a
href={href}
target='_blank'
Expand All @@ -142,40 +148,44 @@ const STATIC_MARKDOWN_COMPONENTS = {
{children}
</a>
),
strong: ({ children }: any) => (
strong: ({ children }: { children?: React.ReactNode }) => (
<strong className='break-words font-semibold text-[var(--text-primary)]'>{children}</strong>
),
em: ({ children }: any) => (
em: ({ children }: { children?: React.ReactNode }) => (
<em className='break-words text-[var(--text-tertiary)]'>{children}</em>
),
blockquote: ({ children }: any) => (
blockquote: ({ children }: { children?: React.ReactNode }) => (
<blockquote className='my-4 break-words border-[var(--border-1)] border-l-4 py-1 pl-4 text-[var(--text-tertiary)] italic'>
{children}
</blockquote>
),
hr: () => <hr className='my-6 border-[var(--border)]' />,
img: ({ src, alt }: any) => (
img: ({ src, alt, node: _node }: React.ComponentPropsWithoutRef<'img'> & ExtraProps) => (
<img src={src} alt={alt ?? ''} className='my-3 max-w-full rounded-md' loading='lazy' />
),
table: ({ children }: any) => (
table: ({ children }: { children?: React.ReactNode }) => (
<div className='my-4 max-w-full overflow-x-auto'>
<table className='w-full border-collapse text-[13px]'>{children}</table>
</div>
),
thead: ({ children }: any) => <thead className='bg-[var(--surface-2)]'>{children}</thead>,
tbody: ({ children }: any) => <tbody>{children}</tbody>,
tr: ({ children }: any) => (
thead: ({ children }: { children?: React.ReactNode }) => (
<thead className='bg-[var(--surface-2)]'>{children}</thead>
),
tbody: ({ children }: { children?: React.ReactNode }) => <tbody>{children}</tbody>,
tr: ({ children }: { children?: React.ReactNode }) => (
<tr className='border-[var(--border)] border-b last:border-b-0'>{children}</tr>
),
th: ({ children }: any) => (
th: ({ children }: { children?: React.ReactNode }) => (
<th className='px-3 py-2 text-left font-semibold text-[12px] text-[var(--text-primary)]'>
{children}
</th>
),
td: ({ children }: any) => <td className='px-3 py-2 text-[var(--text-secondary)]'>{children}</td>,
td: ({ children }: { children?: React.ReactNode }) => (
<td className='px-3 py-2 text-[var(--text-secondary)]'>{children}</td>
),
}

function UlRenderer({ className, children }: any) {
function UlRenderer({ className, children }: React.ComponentPropsWithoutRef<'ul'> & ExtraProps) {
const isTaskList = typeof className === 'string' && className.includes('contains-task-list')
return (
<ul
Expand All @@ -189,7 +199,7 @@ function UlRenderer({ className, children }: any) {
)
}

function OlRenderer({ className, children }: any) {
function OlRenderer({ className, children }: React.ComponentPropsWithoutRef<'ol'> & ExtraProps) {
const isTaskList = typeof className === 'string' && className.includes('contains-task-list')
return (
<ol
Expand All @@ -203,24 +213,24 @@ function OlRenderer({ className, children }: any) {
)
}

function LiRenderer({ className, children, node }: any) {
function LiRenderer({
className,
children,
node,
}: React.ComponentPropsWithoutRef<'li'> & ExtraProps) {
const ctx = useContext(MarkdownCheckboxCtx)
const isTaskItem = typeof className === 'string' && className.includes('task-list-item')

if (isTaskItem) {
if (ctx) {
// Derive the index by counting task-list items before this node's source
// offset — a pure computation that produces the same value on every call,
// making it safe under React Strict Mode's intentional double-invocation.
const offset: number | undefined = node?.position?.start?.offset
let index = 0
if (offset !== undefined && offset > 0) {
const before = ctx.contentRef.current.slice(0, offset)
const prior = before.match(/^(\s*(?:[-*+]|\d+[.)]) +)\[([ xX])\]/gm)
index = prior ? prior.length : 0
const offset = node?.position?.start?.offset
if (offset === undefined) {
return <li className='flex items-start gap-2 break-words leading-[1.6]'>{children}</li>
}
const before = ctx.contentRef.current.slice(0, offset)
const prior = before.match(/^(\s*(?:[-*+]|\d+[.)]) +)\[([ xX])\]/gm)
return (
<CheckboxIndexCtx.Provider value={index}>
<CheckboxIndexCtx.Provider value={prior ? prior.length : 0}>
<li className='flex items-start gap-2 break-words leading-[1.6]'>{children}</li>
</CheckboxIndexCtx.Provider>
)
Expand All @@ -231,7 +241,12 @@ function LiRenderer({ className, children, node }: any) {
return <li className='break-words leading-[1.6]'>{children}</li>
}

function InputRenderer({ type, checked, ...props }: any) {
function InputRenderer({
type,
checked,
node: _node,
...props
}: React.ComponentPropsWithoutRef<'input'> & ExtraProps) {
const ctx = useContext(MarkdownCheckboxCtx)
const index = useContext(CheckboxIndexCtx)

Expand All @@ -258,7 +273,7 @@ const MARKDOWN_COMPONENTS = {
ol: OlRenderer,
li: LiRenderer,
input: InputRenderer,
}
} satisfies Components

const MarkdownPreview = memo(function MarkdownPreview({
content,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,6 @@ export const Sidebar = memo(function Sidebar() {

const isMac = useMemo(() => isMacPlatform(), [])

// Delay collapsed tooltips until the width transition finishes.
const [showCollapsedTooltips, setShowCollapsedTooltips] = useState(isCollapsed)

useLayoutEffect(() => {
Expand Down Expand Up @@ -1019,10 +1018,6 @@ export const Sidebar = memo(function Sidebar() {
[importWorkspace]
)

// ── Memoised elements & objects for collapsed menus ──
// Prevents new JSX/object references on every render, which would defeat
// React.memo on CollapsedSidebarMenu and its children.

const tasksCollapsedIcon = useMemo(
() => <Blimp className='h-[16px] w-[16px] flex-shrink-0 text-[var(--text-icon)]' />,
[]
Expand Down Expand Up @@ -1063,7 +1058,6 @@ export const Sidebar = memo(function Sidebar() {
[handleCreateWorkflow]
)

// Stable no-op for collapsed workflow context menu delete (never changes)
const noop = useCallback(() => {}, [])

const handleExpandSidebar = useCallback(
Expand All @@ -1074,16 +1068,13 @@ export const Sidebar = memo(function Sidebar() {
[toggleCollapsed]
)

// Stable callback for the "New task" button in expanded mode
const handleNewTask = useCallback(
() => navigateToPage(`/workspace/${workspaceId}/home`),
[navigateToPage, workspaceId]
)

// Stable callback for "See more" tasks
const handleSeeMoreTasks = useCallback(() => setVisibleTaskCount((prev) => prev + 5), [])

// Stable callback for DeleteModal close
const handleCloseTaskDeleteModal = useCallback(() => setIsTaskDeleteModalOpen(false), [])

const handleEdgeKeyDown = useCallback(
Expand All @@ -1096,16 +1087,13 @@ export const Sidebar = memo(function Sidebar() {
[isCollapsed, toggleCollapsed]
)

// Stable handler for help modal open from dropdown
const handleOpenHelpFromMenu = useCallback(() => setIsHelpModalOpen(true), [])

// Stable handler for opening docs
const handleOpenDocs = useCallback(
() => window.open('https://docs.sim.ai', '_blank', 'noopener,noreferrer'),
[]
)

// Stable blur handlers for inline rename inputs
const handleTaskRenameBlur = useCallback(
() => void taskFlyoutRename.saveRename(),
[taskFlyoutRename.saveRename]
Expand All @@ -1116,7 +1104,6 @@ export const Sidebar = memo(function Sidebar() {
[workflowFlyoutRename.saveRename]
)

// Stable style for hidden file inputs
const hiddenStyle = useMemo(() => ({ display: 'none' }) as const, [])

const resolveWorkspaceIdFromPath = useCallback((): string | undefined => {
Expand Down Expand Up @@ -1214,7 +1201,6 @@ export const Sidebar = memo(function Sidebar() {
onClick={handleSidebarClick}
>
<div className='flex h-full flex-col pt-3'>
{/* Top bar: Logo + Collapse toggle */}
<div className='flex flex-shrink-0 items-center pr-2 pb-2 pl-2.5'>
<div className='flex h-[30px] items-center'>
<div className='relative h-[30px]'>
Expand Down Expand Up @@ -1277,7 +1263,6 @@ export const Sidebar = memo(function Sidebar() {
</SidebarTooltip>
</div>

{/* Workspace Header */}
<div className='flex-shrink-0 pr-2.5 pl-[9px]'>
<WorkspaceHeader
activeWorkspace={activeWorkspace}
Expand Down Expand Up @@ -1309,7 +1294,6 @@ export const Sidebar = memo(function Sidebar() {
/>
) : (
<>
{/* Top Navigation: Home, Search */}
<div className='mt-2.5 flex flex-shrink-0 flex-col gap-0.5 px-2'>
{topNavItems.map((item) => (
<SidebarNavItem
Expand All @@ -1322,7 +1306,6 @@ export const Sidebar = memo(function Sidebar() {
))}
</div>

{/* Workspace */}
<div className='mt-3.5 flex flex-shrink-0 flex-col pb-2'>
<div className='px-4 pb-1.5'>
<div className='font-base text-[var(--text-icon)] text-small'>Workspace</div>
Expand All @@ -1340,15 +1323,13 @@ export const Sidebar = memo(function Sidebar() {
</div>
</div>

{/* Scrollable Tasks + Workflows */}
<div
ref={isCollapsed ? undefined : scrollContainerRef}
className={cn(
'flex flex-1 flex-col overflow-y-auto overflow-x-hidden border-t pt-2.5 transition-colors duration-150',
!hasOverflowTop && 'border-transparent'
)}
>
{/* Tasks */}
<div className='tasks-section flex flex-shrink-0 flex-col' data-tour='nav-tasks'>
<div className='flex h-[18px] flex-shrink-0 items-center justify-between px-4'>
<div className='font-base text-[var(--text-icon)] text-small'>All tasks</div>
Expand Down Expand Up @@ -1470,7 +1451,6 @@ export const Sidebar = memo(function Sidebar() {
)}
</div>

{/* Workflows */}
<div
className='workflows-section relative mt-3.5 flex flex-col'
data-tour='nav-workflows'
Expand Down Expand Up @@ -1622,14 +1602,12 @@ export const Sidebar = memo(function Sidebar() {
</div>
</div>

{/* Footer */}
<div
className={cn(
'flex flex-shrink-0 flex-col gap-0.5 border-t px-2 pt-[9px] pb-2 transition-colors duration-150',
!hasOverflowBottom && 'border-transparent'
)}
>
{/* Help dropdown */}
<DropdownMenu>
<SidebarTooltip label='Help' enabled={showCollapsedTooltips}>
<DropdownMenuTrigger asChild>
Expand Down Expand Up @@ -1672,7 +1650,6 @@ export const Sidebar = memo(function Sidebar() {
))}
</div>

{/* Nav Item Context Menu */}
<NavItemContextMenu
isOpen={isNavContextMenuOpen}
position={navContextMenuPosition}
Expand All @@ -1682,7 +1659,6 @@ export const Sidebar = memo(function Sidebar() {
onCopyLink={handleNavCopyLink}
/>

{/* Task Context Menu */}
<ContextMenu
isOpen={isTaskContextMenuOpen}
position={taskContextMenuPosition}
Expand All @@ -1707,7 +1683,6 @@ export const Sidebar = memo(function Sidebar() {
disableDelete={!canEdit}
/>

{/* Task Delete Confirmation Modal */}
<DeleteModal
isOpen={isTaskDeleteModalOpen}
onClose={handleCloseTaskDeleteModal}
Expand Down Expand Up @@ -1738,7 +1713,6 @@ export const Sidebar = memo(function Sidebar() {
)}
</div>

{/* Universal Search Modal */}
<SearchModal
open={isSearchModalOpen}
onOpenChange={setIsSearchModalOpen}
Expand All @@ -1751,14 +1725,12 @@ export const Sidebar = memo(function Sidebar() {
isOnWorkflowPage={!!workflowId}
/>

{/* Footer Navigation Modals */}
<HelpModal
open={isHelpModalOpen}
onOpenChange={setIsHelpModalOpen}
workflowId={workflowId}
workspaceId={workspaceId}
/>
{/* Hidden file input for workspace import */}
<input
ref={workspaceFileInputRef}
type='file'
Expand Down
8 changes: 4 additions & 4 deletions apps/sim/hooks/use-auto-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const STICK_THRESHOLD = 30
/** User must scroll back to within this distance to re-engage auto-scroll. */
const REATTACH_THRESHOLD = 5

interface UseAutoScrollOptions {
scrollOnMount?: boolean
}

/**
* Manages sticky auto-scroll for a streaming chat container.
*
Expand All @@ -16,10 +20,6 @@ const REATTACH_THRESHOLD = 5
* Returns `ref` (callback ref for the scroll container) and `scrollToBottom`
* for imperative use after layout-changing events like panel expansion.
*/
interface UseAutoScrollOptions {
scrollOnMount?: boolean
}

export function useAutoScroll(
isStreaming: boolean,
{ scrollOnMount = false }: UseAutoScrollOptions = {}
Expand Down
Loading