Function bodies 471 total
getTypeLabel function · typescript · L33-L40 (8 LOC)components/project/PinnedItemCard.tsx
function getTypeLabel(type: PinnedItem['type']): string {
switch (type) {
case 'issue':
return 'Issue'
case 'doc':
return 'Doc'
}
}PinnedItemCard function · typescript · L42-L87 (46 LOC)components/project/PinnedItemCard.tsx
export function PinnedItemCard({
item,
isDragging,
onDragStart,
onDragOver,
onDragEnd,
onUnpin,
}: PinnedItemCardProps) {
const { createLink } = useAppLink()
const href = getItemHref(item, createLink)
return (
<div
className={`pinned-item-card ${isDragging ? 'dragging' : ''}`}
draggable
onDragStart={onDragStart}
onDragOver={onDragOver}
onDragEnd={onDragEnd}
>
<div className="pinned-item-drag-handle" title="Drag to reorder">
<span className="drag-handle-line"></span>
<span className="drag-handle-line"></span>
<span className="drag-handle-line"></span>
</div>
<span className={getTypeBadgeClass(item.type)}>
{getTypeLabel(item.type)}
</span>
<div className="pinned-item-content">
<Link href={href} className="pinned-item-link">
{item.title}
</Link>
{item.displayNumber != null && (
<div className="pinned-item-number">#{item.displayNPinnedItemsSection function · typescript · L13-L68 (56 LOC)components/project/PinnedItemsSection.tsx
export function PinnedItemsSection({
items,
onUnpin,
onReorder,
}: PinnedItemsSectionProps) {
const [draggedIndex, setDraggedIndex] = useState<number | null>(null)
const handleDragStart = (index: number) => {
setDraggedIndex(index)
}
const handleDragOver = (e: React.DragEvent, index: number) => {
e.preventDefault()
if (draggedIndex === null || draggedIndex === index) return
onReorder(draggedIndex, index)
setDraggedIndex(index)
}
const handleDragEnd = () => {
setDraggedIndex(null)
}
return (
<div className="pinned-items-section">
<div className="pinned-items-header">
<h2 className="pinned-items-title">Pinned</h2>
{items.length > 0 && (
<span className="pinned-items-count">{items.length}</span>
)}
</div>
{items.length === 0 ? (
<div className="pinned-items-empty">
<p className="pinned-items-empty-text">No pinned items yet</p>
<p className="pinned-items-hiProjectDashboard function · typescript · L9-L71 (63 LOC)components/project/ProjectDashboard.tsx
export function ProjectDashboard() {
const { projectName, isInitialized, isLoading, displayPath } =
usePathContext()
const { createLink } = useAppLink()
const { pinnedItems, unpinItem, reorderItems } = usePinnedItems()
if (isLoading) {
return (
<div className="project-dashboard-loading">
<p className="dashboard-loading-text">Loading project...</p>
</div>
)
}
if (isInitialized === false) {
return (
<div className="project-dashboard-not-initialized">
<p className="not-initialized-text">
Centy is not initialized in this directory
</p>
<Link href={createLink('/')}>Initialize Project</Link>
</div>
)
}
return (
<div className="project-dashboard">
<div className="project-dashboard-header">
<h1 className="project-dashboard-title">{projectName}</h1>
{displayPath && (
<div className="project-dashboard-path">{displayPath}</div>
)}
</div>
ProjectFlatList function · typescript · L16-L44 (29 LOC)components/project/ProjectSelector/ProjectFlatList.tsx
export function ProjectFlatList({
projects,
projectPath,
onSelect,
onToggleFavorite,
onArchive,
onFocusSearch,
}: ProjectFlatListProps) {
return (
<ul
id="project-listbox"
className="project-list"
role="listbox"
aria-label="Projects"
onKeyDown={makeListKeyboardHandler(onFocusSearch)}
>
{projects.map(project => (
<ProjectItem
key={project.path}
project={project}
isSelected={project.path === projectPath}
onSelect={onSelect}
onToggleFavorite={onToggleFavorite}
onArchive={onArchive}
/>
))}
</ul>
)
}ProjectGroupList function · typescript · L19-L79 (61 LOC)components/project/ProjectSelector/ProjectGroupList.tsx
export function ProjectGroupList({
groupedProjects,
projectPath,
collapsedOrgs,
toggleOrgCollapse,
onSelect,
onToggleFavorite,
onArchive,
onFocusSearch,
}: ProjectGroupListProps) {
return (
<div
id="project-listbox"
className="project-list-grouped"
role="listbox"
aria-label="Projects"
onKeyDown={makeListKeyboardHandler(onFocusSearch)}
>
{groupedProjects.map(([orgSlug, group]) => {
const isCollapsed = collapsedOrgs.has(orgSlug)
return (
<div key={orgSlug || '__ungrouped'} className="project-group">
<button
className="project-group-header"
onClick={() => toggleOrgCollapse(orgSlug)}
aria-expanded={!isCollapsed}
>
<span
className={`project-group-chevron ${isCollapsed ? 'collapsed' : ''}`}
>
{'\u25BC'}
</span>
<span className="project-group-name">
ProjectItem function · typescript · L17-L79 (63 LOC)components/project/ProjectSelector/ProjectItem.tsx
export function ProjectItem({
project,
isSelected,
onSelect,
onToggleFavorite,
onArchive,
}: ProjectItemProps) {
return (
<li
id={toOptionId(project.path)}
role="option"
aria-selected={isSelected}
tabIndex={0}
className={`project-item ${isSelected ? 'selected' : ''}`}
onClick={() => onSelect(project)}
onKeyDown={e => {
if (e.key !== 'Enter' && e.key !== ' ') return
e.preventDefault()
onSelect(project)
}}
>
<div className="project-item-main">
<button
className={`favorite-btn ${project.isFavorite ? 'active' : ''}`}
onClick={e => onToggleFavorite(e, project)}
title={
project.isFavorite ? 'Remove from favorites' : 'Add to favorites'
}
>
{project.isFavorite ? '\u2605' : '\u2606'}
</button>
<span className="project-item-name">{project.name}</span>
{!project.initialized && (
<span classPowered by Repobility — scan your code at https://repobility.com
ProjectSelectorDropdown function · typescript · L33-L103 (71 LOC)components/project/ProjectSelector/ProjectSelectorDropdown.tsx
export function ProjectSelectorDropdown(props: ProjectSelectorDropdownProps) {
const {
loading,
error,
searchQuery,
setSearchQuery,
searchInputRef,
visibleProjects,
groupedProjects,
projectPath,
collapsedOrgs,
manualPath,
setManualPath,
fetchProjects,
setIsOpen,
handleSelectProject,
handleManualSubmit,
handleToggleFavorite,
handleArchiveProject,
toggleOrgCollapse,
} = props
const focusSearch = () => {
if (searchInputRef.current) searchInputRef.current.focus()
}
return (
<>
<ProjectSelectorHeader loading={loading} onRefresh={fetchProjects} />
<ProjectSelectorSearch
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
searchInputRef={searchInputRef}
/>
{error && <div className="project-selector-error">{error}</div>}
<div className="project-selector-list-area">
{loading ? (
<div className="project-selector-loading">LoadingProjectSelectorEmptyState function · typescript · L7-L27 (21 LOC)components/project/ProjectSelector/ProjectSelectorEmptyState.tsx
export function ProjectSelectorEmptyState({
searchQuery,
}: ProjectSelectorEmptyStateProps) {
return (
<div className="project-selector-empty">
{searchQuery ? (
<>
<p className="empty-state-text">
No projects match "{searchQuery}"
</p>
<p className="hint">Try a different search term</p>
</>
) : (
<>
<p className="empty-state-text">No tracked projects found</p>
<p className="hint">Initialize a project with Centy to see it here</p>
</>
)}
</div>
)
}ProjectSelectorFooter function · typescript · L13-L57 (45 LOC)components/project/ProjectSelector/ProjectSelectorFooter.tsx
export function ProjectSelectorFooter({
manualPath,
setManualPath,
onManualSubmit,
setIsOpen,
}: ProjectSelectorFooterProps) {
return (
<>
<div className="project-selector-actions">
<Link
href={route({ pathname: '/' })}
className="init-project-btn"
onClick={() => setIsOpen(false)}
>
{'\u2728'} Init Project
</Link>
<Link
href={route({ pathname: '/archived' })}
className="view-archived-link"
onClick={() => setIsOpen(false)}
>
View Archived Projects
</Link>
</div>
<div className="project-selector-manual">
<form className="manual-path-form" onSubmit={onManualSubmit}>
<input
type="text"
value={manualPath}
onChange={e => setManualPath(e.target.value)}
placeholder="Or enter path manually..."
className="manual-path-input"
/>
<button
ProjectSelectorHeader function · typescript · L8-L25 (18 LOC)components/project/ProjectSelector/ProjectSelectorHeader.tsx
export function ProjectSelectorHeader({
loading,
onRefresh,
}: ProjectSelectorHeaderProps) {
return (
<div className="project-selector-header">
<h3 className="project-selector-title">Select Project</h3>
<button
className="refresh-btn"
onClick={onRefresh}
disabled={loading}
title="Refresh project list"
>
{'\u21BB'}
</button>
</div>
)
}ProjectSelectorSearch function · typescript · L11-L52 (42 LOC)components/project/ProjectSelector/ProjectSelectorSearch.tsx
export function ProjectSelectorSearch({
searchQuery,
setSearchQuery,
searchInputRef,
}: ProjectSelectorSearchProps) {
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
if (e.key !== 'ArrowDown') return
e.preventDefault()
const firstItem = document.querySelector<HTMLElement>(
'#project-listbox [role="option"]'
)
if (firstItem) firstItem.focus()
}
return (
<div className="project-selector-search">
<input
ref={searchInputRef}
role="combobox"
aria-expanded="true"
aria-controls="project-listbox"
aria-autocomplete="list"
aria-label="Search projects"
type="text"
value={searchQuery}
onChange={e => setSearchQuery(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Search projects..."
className="search-input"
/>
{searchQuery && (
<button
className="search-clear-btn"
onClick={() => setSearchQuery(ProjectSelector function · typescript · L12-L66 (55 LOC)components/project/ProjectSelector/ProjectSelector.tsx
export function ProjectSelector() {
const state = useProjectSelector()
return (
<PopoverRoot open={state.isOpen} onOpenChange={state.setIsOpen}>
<PopoverTrigger asChild>
<button
className="project-selector-trigger"
aria-haspopup="listbox"
aria-expanded={state.isOpen}
aria-controls="project-listbox"
>
<span className="project-icon">{'\uD83D\uDCC1'}</span>
<span className="project-name">{state.getCurrentProjectName()}</span>
<span className="dropdown-arrow">
{state.isOpen ? '\u25B2' : '\u25BC'}
</span>
</button>
</PopoverTrigger>
<PopoverPortal>
<PopoverContent
className="project-selector-dropdown"
align="start"
sideOffset={4}
onOpenAutoFocus={e => {
e.preventDefault()
if (state.searchInputRef.current)
state.searchInputRef.current.focus()
}}
>
makeListKeyboardHandler function · typescript · L9-L31 (23 LOC)components/project/ProjectSelector/useListKeyboardNav.ts
export function makeListKeyboardHandler(onFocusSearch: () => void) {
return (e: KeyboardEvent<HTMLElement>) => {
const items = Array.from(
e.currentTarget.querySelectorAll<HTMLElement>('[role="option"]')
)
const activeEl = document.activeElement
const idx = activeEl instanceof HTMLElement ? items.indexOf(activeEl) : -1
if (e.key === 'ArrowDown') {
e.preventDefault()
const next = items[idx === -1 ? 0 : Math.min(idx + 1, items.length - 1)]
if (next) next.focus()
} else if (e.key === 'ArrowUp') {
e.preventDefault()
if (idx <= 0) {
onFocusSearch()
} else {
const prev = items[idx - 1]
if (prev) prev.focus()
}
}
}
}useProjectActions function · typescript · L31-L135 (105 LOC)components/project/ProjectSelector/useProjectActions.ts
export function useProjectActions(params: UseProjectActionsParams) {
const router = useRouter()
const routeParams = useParams()
const pathname = usePathname()
const { projectPath, setProjectPath, setIsInitialized } = useProject()
const { archiveProject } = useArchivedProjects()
const getCurrentPage = useCallback(() => {
const orgP = routeParams ? routeParams.organization : undefined
const org = typeof orgP === 'string' ? orgP : undefined
const projP = routeParams ? routeParams.project : undefined
const proj = typeof projP === 'string' ? projP : undefined
const segments = pathname.split('/').filter(Boolean)
if (org && proj) return segments[2] || 'issues'
if (segments.length >= 2 && !ROOT_ROUTES.has(segments[0]))
return segments[2] || 'issues'
return segments[0] || 'issues'
}, [routeParams, pathname])
const handleSelectProject = (project: ProjectInfo) => {
const orgSlug = project.organizationSlug || UNGROUPED_ORG_MARKER
consOpen data scored by Repobility · https://repobility.com
useProjectSelector function · typescript · L17-L141 (125 LOC)components/project/ProjectSelector/useProjectSelector.ts
export function useProjectSelector() {
const { isArchived } = useArchivedProjects()
const { selectedOrgSlug, organizations } = useOrganization()
const [projects, setProjects] = useState<ProjectInfo[]>([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [isOpen, setIsOpen] = useState(false)
const [manualPath, setManualPath] = useState('')
const [searchQuery, setSearchQuery] = useState('')
const [collapsedOrgs, setCollapsedOrgs] = useState<Set<string>>(() => {
if (typeof window === 'undefined') return new Set()
try {
const s = localStorage.getItem(COLLAPSED_ORGS_KEY)
return s ? new Set(JSON.parse(s)) : new Set()
} catch {
return new Set()
}
})
const searchInputRef = useRef<HTMLInputElement>(null)
const actions = useProjectActions({
projects,
setProjects,
setIsOpen,
setSearchQuery,
setManualPath,
manualPath,
})
const fetchProjects = useCallbacgroupProjects function · typescript · L7-L45 (39 LOC)components/project/ProjectsGrid/groupProjects.ts
export function groupProjects(
projects: ProjectInfo[],
organizations: Organization[]
): GroupedProject[] {
const groups: Map<string, { name: string; projects: ProjectInfo[] }> =
new Map()
groups.set('', { name: 'Ungrouped', projects: [] })
for (const project of projects) {
const orgSlug = project.organizationSlug || ''
if (!groups.has(orgSlug)) {
const org = organizations.find(o => o.slug === orgSlug)
groups.set(orgSlug, {
name: (org ? org.name : '') || orgSlug,
projects: [],
})
}
groups.get(orgSlug)!.projects.push(project)
}
const sortedGroups = Array.from(groups.entries())
.filter(([, g]) => g.projects.length > 0)
.sort(([slugA], [slugB]) => {
if (slugA === '' && slugB !== '') return 1
if (slugA !== '' && slugB === '') return -1
return slugA.localeCompare(slugB)
})
sortedGroups.forEach(([, group]) => {
group.projects.sort((a, b) => {
if (a.isFavorite && !b.isFavorite) reOrgGroup function · typescript · L14-L54 (41 LOC)components/project/ProjectsGrid/OrgGroup.tsx
export function OrgGroup({
orgSlug,
groupName,
projects,
onProjectClick,
onToggleFavorite,
}: OrgGroupProps) {
return (
<div className="project-org-group">
<div className="org-group-header">
<h2 className="org-group-title">
{orgSlug ? (
<>
<span className="org-icon">{'\uD83C\uDFE2'}</span>
{groupName}
</>
) : (
<>
<span className="org-icon">{'\uD83D\uDCC1'}</span>
{groupName}
</>
)}
</h2>
<span className="org-project-count">{projects.length}</span>
</div>
<div className="projects-grid">
{projects.map(project => (
<ProjectCard
key={project.path}
project={project}
orgSlug={orgSlug}
orgName={groupName}
onClick={() => onProjectClick(project)}
onToggleFavorite={onToggleFavorite}
/>
))}
</dProjectCard function · typescript · L13-L69 (57 LOC)components/project/ProjectsGrid/ProjectCard.tsx
export function ProjectCard({
project,
orgSlug,
orgName,
onClick,
onToggleFavorite,
}: ProjectCardProps) {
return (
<div className="project-card" onClick={onClick}>
<div className="project-card-header">
<h3 className="project-name">{project.name}</h3>
<button
className={`favorite-btn ${project.isFavorite ? 'active' : ''}`}
onClick={e => onToggleFavorite(e, project)}
title={
project.isFavorite ? 'Remove from favorites' : 'Add to favorites'
}
>
{project.isFavorite ? '\u2605' : '\u2606'}
</button>
</div>
<div className="project-badges">
{orgSlug && (
<span
className="project-badge org-badge"
title={`Organization: ${orgName}`}
>
{'\uD83C\uDFE2'} {orgName}
</span>
)}
{!project.initialized && (
<span className="project-badge not-initialized">Not initialized</span>
ProjectsGridContent function · typescript · L16-L66 (51 LOC)components/project/ProjectsGrid/ProjectsGridContent.tsx
export function ProjectsGridContent({
fetchData,
groupedProjects,
onProjectClick,
onToggleFavorite,
}: ProjectsGridContentProps) {
return (
<div className="projects-grid-container">
<div className="projects-grid-header">
<h1 className="projects-grid-title">Projects</h1>
<div className="projects-grid-actions">
<button onClick={fetchData} className="refresh-btn">
Refresh
</button>
<Link
href={route({ pathname: '/project/init' })}
className="init-project-btn"
>
+ Init Project
</Link>
<Link
href={route({ pathname: '/organizations/new' })}
className="create-org-btn"
>
+ New Organization
</Link>
</div>
</div>
{groupedProjects.map(([orgSlug, group]) => (
<OrgGroup
key={orgSlug || '__ungrouped'}
orgSlug={orgSlug}
groupName={group.name}
ProjectsGrid function · typescript · L11-L80 (70 LOC)components/project/ProjectsGrid/ProjectsGrid.tsx
export function ProjectsGrid() {
const router = useRouter()
const {
projects,
loading,
error,
fetchData,
handleToggleFavorite,
groupedProjects,
} = useProjectsData()
const handleProjectClick = (project: ProjectInfo) => {
const orgSlug = project.organizationSlug || UNGROUPED_ORG_MARKER
router.push(
route({
pathname: '/[organization]/[project]/issues',
query: {
organization: orgSlug,
project: project.name,
},
})
)
}
if (loading) {
return (
<div className="projects-grid-loading">
<p className="projects-grid-loading-text">Loading projects...</p>
</div>
)
}
if (error) {
return (
<div className="projects-grid-error">
<p className="projects-grid-error-text">Error: {error}</p>
<button onClick={fetchData} className="retry-btn">
Retry
</button>
</div>
)
}
if (projects.length === 0) {
return (
useProjectsData function · typescript · L17-L95 (79 LOC)components/project/ProjectsGrid/useProjectsData.ts
export function useProjectsData() {
const { selectedOrgSlug } = useOrganization()
const [projects, setProjects] = useState<ProjectInfo[]>([])
const [organizations, setOrganizations] = useState<Organization[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const fetchData = useCallback(async () => {
setLoading(true)
setError(null)
try {
const [projectsResponse, orgsResponse] = await Promise.all([
centyClient.listProjects(
create(ListProjectsRequestSchema, {
includeStale: false,
})
),
centyClient.listOrganizations(
create(ListOrganizationsRequestSchema, {})
),
])
setProjects(projectsResponse.projects)
setOrganizations(orgsResponse.organizations)
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load data')
} finally {
setLoading(false)
}
}, [])
useEffect(()AutoFieldRenderer function · typescript · L20-L89 (70 LOC)components/proto-form/AutoFieldRenderer.tsx
export function AutoFieldRenderer({
field,
label,
description,
value,
onChange,
ProtoFormRenderer,
}: AutoFieldRendererProps) {
if (field.fieldKind === 'scalar') {
return (
<ScalarFieldRenderer
scalar={field.scalar}
label={label}
description={description}
value={value}
onChange={onChange}
/>
)
}
if (field.fieldKind === 'map') {
return (
<MapFieldRenderer
label={label}
description={description}
value={value}
onChange={onChange}
/>
)
}
if (field.fieldKind === 'list') {
return renderListField(field, {
label,
description,
value,
onChange,
ProtoFormRenderer,
})
}
if (field.fieldKind === 'message') {
return (
<MessageFieldRenderer
messageDesc={field.message}
label={label}
description={description}
value={value}
onChange={onChange}
ProtoFormRenderer={ProtoFormRepobility analyzer · published findings · https://repobility.com
ProtoFormRenderer function · typescript · L17-L80 (64 LOC)components/proto-form/ProtoFormRenderer.tsx
export function ProtoFormRenderer({
schema,
value,
onChange,
fieldGroups,
fieldOverrides,
}: ProtoFormRendererProps) {
const groups =
fieldGroups !== null && fieldGroups !== undefined ? fieldGroups : []
const overrides =
fieldOverrides !== null && fieldOverrides !== undefined
? fieldOverrides
: {}
const claimedFields = new Set<string>()
for (const group of groups) {
for (const f of group.claimedFields) {
claimedFields.add(f)
}
}
for (const [localName, override] of Object.entries(overrides)) {
if (override.hidden === true) claimedFields.add(localName)
}
const sortedGroups = [...groups].sort((a, b) => a.order - b.order)
const unclaimedFields = schema.fields.filter(
f => !claimedFields.has(f.localName)
)
return (
<>
{sortedGroups.map(group => (
<section key={group.key} className="settings-section">
<h3 className="settings-section-title">{group.title}</h3>
<div className="settListFieldRenderer function · typescript · L8-L81 (74 LOC)components/proto-form/renderers/ListFieldRenderer.tsx
export function ListFieldRenderer({
label,
description,
value,
onChange,
}: ListFieldProps) {
const rawItems = value !== null && value !== undefined ? value : []
const items = Array.isArray(rawItems) ? rawItems : []
const [newItem, setNewItem] = useState('')
const handleAdd = () => {
if (!newItem.trim()) return
onChange([...items, newItem.trim()])
setNewItem('')
}
const handleRemove = (index: number) => {
onChange(items.filter((_, i) => i !== index))
}
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key !== 'Enter') return
e.preventDefault()
handleAdd()
}
return (
<div className="proto-form-field">
<label className="proto-form-field-label">{label}</label>
{description && (
<p className="proto-form-field-description">{description}</p>
)}
{items.length > 0 && (
<div className="proto-form-tags">
{items.map((item, i) => (
<span key={i} className="proto-foMapAddRow function · typescript · L13-L50 (38 LOC)components/proto-form/renderers/MapAddRow.tsx
export function MapAddRow({
newKey,
newValue,
isKeyTaken,
onKeyChange,
onValueChange,
onKeyDown,
onAdd,
}: MapAddRowProps) {
return (
<div className="proto-form-add-row">
<input
type="text"
className="proto-form-input proto-form-map-key-input"
value={newKey}
onChange={e => onKeyChange(e.target.value)}
onKeyDown={onKeyDown}
placeholder="Key"
/>
<input
type="text"
className="proto-form-input proto-form-map-add-value-input"
value={newValue}
onChange={e => onValueChange(e.target.value)}
onKeyDown={onKeyDown}
placeholder="Value"
/>
<button
type="button"
className="proto-form-add-btn"
onClick={onAdd}
disabled={!newKey.trim() || isKeyTaken}
>
Add
</button>
</div>
)
}MapEntriesTable function · typescript · L9-L50 (42 LOC)components/proto-form/renderers/MapEntriesTable.tsx
export function MapEntriesTable({
entries,
onValueChange,
onRemove,
}: MapEntriesTableProps) {
return (
<table className="proto-form-map-table">
<thead className="proto-form-map-thead">
<tr className="proto-form-map-header-row">
<th className="proto-form-map-th">Key</th>
<th className="proto-form-map-th">Value</th>
<th className="proto-form-map-th-action" />
</tr>
</thead>
<tbody className="proto-form-map-tbody">
{entries.map(([k, v]) => (
<tr key={k} className="proto-form-map-row">
<td className="proto-form-map-key">{k}</td>
<td className="proto-form-map-value-cell">
<input
type="text"
className="proto-form-input proto-form-map-value-input"
value={String(v !== null && v !== undefined ? v : '')}
onChange={e => onValueChange(k, e.target.value)}
/>
</td>
<tdtoMap function · typescript · L13-L25 (13 LOC)components/proto-form/renderers/MapFieldRenderer.tsx
function toMap(v: unknown): Record<string, unknown> {
if (
v !== null &&
v !== undefined &&
typeof v === 'object' &&
!Array.isArray(v)
) {
const result: Record<string, unknown> = {}
Object.assign(result, v)
return result
}
return {}
}MapFieldRenderer function · typescript · L27-L81 (55 LOC)components/proto-form/renderers/MapFieldRenderer.tsx
export function MapFieldRenderer({
label,
description,
value,
onChange,
}: MapFieldProps) {
const map = toMap(value)
const entries = Object.entries(map)
const [newKey, setNewKey] = useState('')
const [newValue, setNewValue] = useState('')
const handleAdd = () => {
if (!newKey.trim() || map[newKey.trim()] !== undefined) return
onChange({ ...map, [newKey.trim()]: newValue })
setNewKey('')
setNewValue('')
}
const handleRemove = (key: string) => {
const entries = Object.entries(map).filter(([k]) => k !== key)
onChange(Object.fromEntries(entries))
}
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key !== 'Enter') return
e.preventDefault()
handleAdd()
}
return (
<div className="proto-form-field">
<label className="proto-form-field-label">{label}</label>
{description && (
<p className="proto-form-field-description">{description}</p>
)}
{entries.length > 0 && (
<MapEntrietoRecord function · typescript · L16-L28 (13 LOC)components/proto-form/renderers/MessageFieldRenderer.tsx
function toRecord(v: unknown): Record<string, unknown> {
if (
v !== null &&
v !== undefined &&
typeof v === 'object' &&
!Array.isArray(v)
) {
const result: Record<string, unknown> = {}
Object.assign(result, v)
return result
}
return {}
}MessageFieldRenderer function · typescript · L30-L60 (31 LOC)components/proto-form/renderers/MessageFieldRenderer.tsx
export function MessageFieldRenderer({
messageDesc,
label,
description,
value,
onChange,
ProtoFormRenderer,
}: MessageFieldProps) {
const msgValue = toRecord(value)
return (
<div className="proto-form-field">
<label className="proto-form-field-label">{label}</label>
{description && (
<p className="proto-form-field-description">{description}</p>
)}
<div className="proto-form-nested">
<ProtoFormRenderer
schema={messageDesc}
value={msgValue}
onChange={updates =>
onChange({
...msgValue,
...updates,
})
}
/>
</div>
</div>
)
}About: code-quality intelligence by Repobility · https://repobility.com
MessageItem function · typescript · L21-L65 (45 LOC)components/proto-form/renderers/MessageItem.tsx
export function MessageItem({
item,
index,
messageName,
isExpanded,
onToggle,
onRemove,
onItemChange,
messageDesc,
ProtoFormRenderer,
}: MessageItemProps) {
return (
<div className="proto-form-message-item">
<div className="proto-form-message-item-header">
<button
type="button"
className="proto-form-message-item-toggle"
onClick={() => onToggle(index)}
>
<span className="proto-form-message-item-arrow">
{isExpanded ? '▾' : '▸'}
</span>
{`${messageName} ${index + 1}`}
</button>
<button
type="button"
className="proto-form-remove-btn"
onClick={() => onRemove(index)}
aria-label={`Remove item ${index + 1}`}
>
×
</button>
</div>
{isExpanded && (
<div className="proto-form-message-item-body">
<ProtoFormRenderer
schema={messageDesc}
value={item}
toRecordArray function · typescript · L8-L19 (12 LOC)components/proto-form/renderers/MessageListFieldRenderer.tsx
function toRecordArray(v: unknown): Record<string, unknown>[] {
if (Array.isArray(v)) {
return v.filter(
item =>
item !== null &&
item !== undefined &&
typeof item === 'object' &&
!Array.isArray(item)
)
}
return []
}MessageListFieldRenderer function · typescript · L22-L105 (84 LOC)components/proto-form/renderers/MessageListFieldRenderer.tsx
export function MessageListFieldRenderer({
messageDesc,
label,
description,
value,
onChange,
ProtoFormRenderer,
}: MessageListFieldProps) {
const items = toRecordArray(value)
const [expanded, setExpanded] = useState<Set<number>>(new Set())
const handleAdd = () => {
const newItem: Record<string, unknown> = {}
Object.assign(newItem, create(messageDesc))
const next = [...items, newItem]
onChange(next)
setExpanded(prev => new Set([...prev, next.length - 1]))
}
const handleRemove = (index: number) => {
onChange(items.filter((_, i) => i !== index))
setExpanded(
prev =>
new Set(
Array.from(prev)
.filter(i => i !== index)
.map(i => (i > index ? i - 1 : i))
)
)
}
const handleItemChange = (
index: number,
updates: Record<string, unknown>
) => {
onChange(
items.map((item, i) => (i === index ? { ...item, ...updates } : item))
)
}
const toggleExpanded = (NumericField function · typescript · L11-L45 (35 LOC)components/proto-form/renderers/NumericField.tsx
export function NumericField({
label,
description,
value,
is64bit,
onChange,
}: NumericFieldProps) {
const displayValue = is64bit
? String(value !== null && value !== undefined ? value : '')
: value !== null && value !== undefined
? value
: ''
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value
if (is64bit) {
onChange(raw === '' ? BigInt(0) : BigInt(raw))
} else {
onChange(raw === '' ? 0 : Number(raw))
}
}
return (
<div className="proto-form-field">
<label className="proto-form-field-label">{label}</label>
{description && (
<p className="proto-form-field-description">{description}</p>
)}
<input
type="number"
className="proto-form-input"
value={String(displayValue)}
onChange={handleChange}
/>
</div>
)
}ScalarFieldRenderer function · typescript · L11-L81 (71 LOC)components/proto-form/renderers/ScalarFieldRenderer.tsx
export function ScalarFieldRenderer({
scalar,
label,
description,
value,
onChange,
}: ScalarFieldProps) {
if (scalar === ScalarType.BOOL) {
return (
<label className="proto-form-checkbox-label">
<input
type="checkbox"
className="proto-form-checkbox"
checked={Boolean(value)}
onChange={e => onChange(e.target.checked)}
/>
<span className="proto-form-checkbox-text">
<strong className="proto-form-field-label">{label}</strong>
{description && (
<span className="proto-form-field-description">{description}</span>
)}
</span>
</label>
)
}
const is64bit =
scalar === ScalarType.INT64 ||
scalar === ScalarType.UINT64 ||
scalar === ScalarType.SINT64 ||
scalar === ScalarType.FIXED64 ||
scalar === ScalarType.SFIXED64
const isNumeric =
is64bit ||
scalar === ScalarType.INT32 ||
scalar === ScalarType.UINT32 ||
scalar =renderListField function · typescript · L20-L45 (26 LOC)components/proto-form/renderListField.tsx
export function renderListField(
field: Extract<FieldRenderProps['field'], { fieldKind: 'list' }>,
shared: RenderListSharedProps
) {
const { label, description, value, onChange, ProtoFormRenderer } = shared
if (field.listKind === 'message') {
return (
<MessageListFieldRenderer
messageDesc={field.message}
label={label}
description={description}
value={value}
onChange={onChange}
ProtoFormRenderer={ProtoFormRenderer}
/>
)
}
return (
<ListFieldRenderer
label={label}
description={description}
value={value}
onChange={onChange}
/>
)
}applyDemoState function · typescript · L11-L19 (9 LOC)components/providers/applyDemoState.ts
export function applyDemoState(
setStatus: SetState<DaemonStatus>,
setVscode: SetState<boolean | null>,
setEds: SetState<EditorInfo[]>
) {
setStatus('demo')
setVscode(resolveVscodeAvailable(true))
setEds(createDemoEditors())
}buildAggregateContext function · typescript · L5-L19 (15 LOC)components/providers/buildAggregateContext.ts
export function buildAggregateContext(
navigateToProject: NavigateFn
): PathContextType {
return {
orgSlug: null,
projectName: null,
projectPath: '',
isInitialized: null,
displayPath: '',
isAggregateView: true,
isLoading: false,
error: null,
navigateToProject,
}
}Powered by Repobility — scan your code at https://repobility.com
buildDemoRedirectUrl function · typescript · L4-L9 (6 LOC)components/providers/buildDemoRedirectUrl.ts
export function buildDemoRedirectUrl(
orgSlug: string,
projectPath: string
): string {
return `/?org=${orgSlug}&project=${encodeURIComponent(projectPath)}`
}buildPendingContext function · typescript · L6-L29 (24 LOC)components/providers/buildPendingContext.ts
export function buildPendingContext(
urlOrg: string | undefined,
urlProject: string | undefined,
isLoading: boolean,
error: string | null,
navigateToProject: NavigateFn
): PathContextType {
return {
orgSlug:
urlOrg === UNGROUPED_ORG_MARKER
? null
: urlOrg !== undefined
? urlOrg
: null,
projectName: urlProject !== undefined ? urlProject : null,
projectPath: '',
isInitialized: null,
displayPath: '',
isAggregateView: false,
isLoading,
error,
navigateToProject,
}
}buildResolvedContext function · typescript · L6-L23 (18 LOC)components/providers/buildResolvedContext.ts
export function buildResolvedContext(
resolution: ProjectResolution,
isLoading: boolean,
error: string | null,
navigateToProject: NavigateFn
): PathContextType {
return {
orgSlug: resolution.orgSlug,
projectName: resolution.projectName,
projectPath: resolution.projectPath,
isInitialized: resolution.initialized,
displayPath: resolution.displayPath,
isAggregateView: false,
isLoading,
error,
navigateToProject,
}
}createDemoEditors function · typescript · L6-L27 (22 LOC)components/providers/createDemoEditors.ts
export function createDemoEditors(): EditorInfo[] {
return [
{
$typeName: 'centy.v1.EditorInfo',
editorType: EditorType.VSCODE,
name: 'VS Code',
description: 'Open in temporary VS Code workspace',
available: true,
editorId: 'vscode',
terminalWrapper: false,
},
{
$typeName: 'centy.v1.EditorInfo',
editorType: EditorType.TERMINAL,
name: 'Terminal',
description: 'Open in terminal',
available: true,
editorId: 'terminal',
terminalWrapper: true,
},
]
}createFallbackEditors function · typescript · L6-L27 (22 LOC)components/providers/createFallbackEditors.ts
export function createFallbackEditors(vscodeAvailable: boolean): EditorInfo[] {
return [
{
$typeName: 'centy.v1.EditorInfo',
editorType: EditorType.VSCODE,
name: 'VS Code',
description: 'Open in temporary VS Code workspace',
available: vscodeAvailable,
editorId: 'vscode',
terminalWrapper: false,
},
{
$typeName: 'centy.v1.EditorInfo',
editorType: EditorType.TERMINAL,
name: 'Terminal',
description: 'Open in terminal',
available: true,
editorId: 'terminal',
terminalWrapper: true,
},
]
}useDaemonStatusState function · typescript · L23-L97 (75 LOC)components/providers/DaemonStatusProvider.hooks.ts
export function useDaemonStatusState() {
const [status, setStatus] = useState<DaemonStatus>('checking')
const [lastChecked, setLastChecked] = useState<Date | null>(null)
const [hasMounted, setHasMounted] = useState(false)
const [vscodeAvailable, setVscodeAvailable] = useState<boolean | null>(null)
const [editors, setEditors] = useState<EditorInfo[]>([])
useEffect(() => {
const timeoutId = setTimeout(() => {
initializeDemoFromUrl(setStatus, setVscodeAvailable, setEditors)
setHasMounted(true)
}, 0)
return () => clearTimeout(timeoutId)
}, [])
const checkDaemonStatus = useCallback(async () => {
if (isDemoMode()) {
applyDemoState(setStatus, setVscodeAvailable, setEditors)
return
}
setStatus('checking')
try {
const daemonInfo = await centyClient.getDaemonInfo({})
setStatus('connected')
setVscodeAvailable(daemonInfo.vscodeAvailable)
trackDaemonConnection(true, false)
const resp = await centyCliDaemonStatusProvider function · typescript · L11-L38 (28 LOC)components/providers/DaemonStatusProvider.tsx
export function DaemonStatusProvider({ children }: { children: ReactNode }) {
const {
status,
lastChecked,
checkDaemonStatus,
enterDemoMode,
exitDemoMode,
vscodeAvailable,
editors,
} = useDaemonStatusState()
return (
<DaemonStatusContext.Provider
value={{
status,
lastChecked,
checkNow: checkDaemonStatus,
enterDemoMode,
exitDemoMode,
demoProjectPath: DEMO_PROJECT_PATH,
vscodeAvailable,
editors,
}}
>
{children}
</DaemonStatusContext.Provider>
)
}useDaemonStatus function · typescript · L40-L46 (7 LOC)components/providers/DaemonStatusProvider.tsx
export function useDaemonStatus() {
const context = useContext(DaemonStatusContext)
if (!context) {
throw new DaemonStatusProviderError()
}
return context
}Open data scored by Repobility · https://repobility.com
initializeDemoFromUrl function · typescript · L12-L26 (15 LOC)components/providers/initializeDemoFromUrl.ts
export function initializeDemoFromUrl(
setStatus: SetState<DaemonStatus>,
setVscodeAvailable: SetState<boolean | null>,
setEditors: SetState<EditorInfo[]>
) {
const urlParams = new URLSearchParams(window.location.search)
if (urlParams.get('demo') === 'true' && !isDemoMode()) {
enableDemoMode()
applyDemoState(setStatus, setVscodeAvailable, setEditors)
const newUrl = buildDemoUrl(DEMO_ORG_SLUG, DEMO_PROJECT_PATH)
window.history.replaceState({}, '', newUrl)
} else if (isDemoMode()) {
applyDemoState(setStatus, setVscodeAvailable, setEditors)
}
}OrganizationProvider function · typescript · L24-L87 (64 LOC)components/providers/OrganizationProvider.tsx
export function OrganizationProvider({ children }: { children: ReactNode }) {
const { urlOrg } = useUrlParams()
// Derive selected org from URL; allow local override without persistence
// undefined = not yet selected (initial), null = all orgs, string = specific org or ''
const [selectedOrgSlug, setSelectedOrgSlugState] = useState<
string | null | undefined
>(urlOrg)
const [organizations, setOrganizations] = useState<Organization[]>([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
// Sync selected org from URL whenever the URL org changes
useEffect(() => {
setSelectedOrgSlugState(urlOrg)
}, [urlOrg])
const refreshOrganizations = useCallback(async () => {
setLoading(true)
setError(null)
try {
const request = create(ListOrganizationsRequestSchema, {})
const response = await centyClient.listOrganizations(request)
setOrganizations(response.organizations)
} catch (useOrganization function · typescript · L89-L95 (7 LOC)components/providers/OrganizationProvider.tsx
export function useOrganization() {
const context = useContext(OrganizationContext)
if (!context) {
throw new OrganizationProviderError()
}
return context
}