FE-504: Add copy/paste and select all to petrinaut editor#8533
FE-504: Add copy/paste and select all to petrinaut editor#8533
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Extract common filterable list pattern into createFilterableListSubView factory. Refactor nodes-list, types-list, parameters-list, and differential-equations-list to use the shared component, reducing duplication of selection handling, row styles, and empty state rendering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…is menu - Update list item styles: 32px height, 8px border radius, 14px font, semantic color tokens, neutral hover/selected backgrounds - Replace inline delete button with horizontal ellipsis (TbDots) that opens a Menu with a destructive "Delete" action - Ellipsis button fades in on row hover with subtle icon slide animation, stays visible while menu is open via data-state selector - Add text overflow ellipsis to all list item names - Update nodes-list font size and colors to match design tokens Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tons - Add getMenuItems config param so the container owns Menu rendering - Extract RowMenu component that skips rendering when items array is empty - Move menu item definitions from renderItem to getMenuItems in all subviews - Replace TbFilter with LuListFilter, add LuArrowDownWideNarrow (sort) and LuSearch (search) icon buttons in the header (no-ops for now) - Place filter/sort/search buttons before subview-specific actions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…hen menu open - Use stopPropagation on ellipsis button instead of DOM query guard - Show hover background on row when its menu is open via :has selector Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scope chevron hover to toggle section only, not full header row - Show header actions and info tooltip only on hover/focus-within with opacity animation - Add outlined variant to InfoIconTooltip, used in subview headers - Move item icons to FilterableListItem.icon prop with consistent rendering - Wrap list items in content/name containers in filterable-list-sub-view - Remove redundant wrapper styles from individual subview lists - Add alwaysShowHeaderAction option to SubView, used by visualizer - Align row menu to bottom-end Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional `icon` prop to SubView type and update VerticalSubViewsContainer to render distinct main vs collapsible header styles matching the Figma design. Main headers now show an outline icon + subtle text with a bottom border. All PropertiesPanel main SubViews (Place, Transition, Arc, Parameter, Type, Differential Equation) now include Lucide outline icons and use alwaysShowHeaderAction where applicable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create constants/entity-icons.tsx as the single source of truth for all Petri net entity icons (outline and filled variants). Update FilterableListSubView to control icon size and default color centrally, with an iconColor override used by TokenTypes for per-type coloring. All list subviews now show their entity icon consistently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… subviews Internalize listItemNameStyle within FilterableListSubView so renderItem returns plain text/nodes wrapped automatically. Simplify all list subview renderItem callbacks to return strings instead of styled spans. Reorder LEFT_SIDEBAR_SUBVIEWS to show Nodes first. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change SubView.icon from ReactNode to ComponentType<{ size: number }> so
the container controls the icon size (HEADER_ICON_SIZE = 16). All SubView
consumers now pass icon components directly instead of rendered elements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e entity icons Clicking in the list container but not on an item now calls clearSelection to deselect all. Also update Parameter/TokenType/DifferentialEquation icons. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Increase default panel content horizontal padding to 4 and use negative margin on FilterableListSubView to reduce its effective padding to 3. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…terable list and menu - Add Arrow Up/Down keyboard navigation with focused item tracking - Support Shift+Click and Shift+Arrow range selection via selectRange helper - Ctrl/Cmd+Click toggles multi-selection with anchor tracking - Escape clears selection and resets focus state - Clamp focus/anchor indices when item list shrinks - Auto-scroll focused items into view - Add ARIA listbox/option roles for accessibility - Suppress default browser focus outline on list container - Add _highlighted styles to Menu items and submenu triggers for keyboard focus Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert headerRowStyle to cva with isCollapsed variant that sets borderBottomColor to transparent, avoiding visual double-borders between collapsed sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace raw [44px] with token value for consistent sizing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clear focusedIndex and anchorIndex on blur when focus moves outside the list container, so stale keyboard state doesn't persist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fixed minWidth with flex: 1 so the title input expands to use all remaining space in the left section. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement clipboard support with a versioned JSON format (petrinaut-sdcpn v1) validated by zod. Copy serializes selected items (places, transitions, token types, differential equations, parameters) with arc preservation. Paste duplicates items with new UUIDs, deduplicates names, remaps internal references, and offsets node positions. Cmd+A selects all canvas nodes, Escape clears selection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97b4e36 to
7889b18
Compare
39823b5 to
44fe283
Compare
PR SummaryMedium Risk Overview Extends editor keyboard handling with Refactors left sidebar lists to a shared Written by Cursor Bugbot for commit 7889b18. This will update automatically on new commits. Configure here. |
🤖 Augment PR SummarySummary: Adds clipboard + selection keyboard shortcuts to the Petrinaut SDCPN editor, enabling users to copy/paste selections and quickly select/deselect canvas items. Changes:
Technical Notes: Clipboard payload is explicitly versioned, and paste performs ID remapping and reference preservation/remapping for types, equations, parameters, places, transitions, and arcs. 🤖 Was this summary useful? React with 👍 or 👎 |
| export async function pasteFromClipboard( | ||
| mutatePetriNetDefinition: (mutateFn: (sdcpn: SDCPN) => void) => void, | ||
| ): Promise<Array<{ type: string; id: string }> | null> { | ||
| const text = await navigator.clipboard.readText(); |
There was a problem hiding this comment.
navigator.clipboard.readText() / writeText() can throw (permissions, non-secure context, unsupported API), and right now that would surface as an unhandled rejection from the keyboard shortcut handler. Consider catching clipboard errors (and possibly checking navigator.clipboard existence) and returning null/no-op so paste/copy fails gracefully.
Severity: medium
Other Locations
libs/@hashintel/petrinaut/src/clipboard/clipboard.ts:22libs/@hashintel/petrinaut/src/views/Editor/components/BottomBar/use-keyboard-shortcuts.ts:77
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| </IconButton> | ||
| {renderExtraAction?.()} | ||
| </> | ||
| ); |
There was a problem hiding this comment.
Filter/sort/search buttons rendered without click handlers
Low Severity
FilterHeaderAction renders three IconButton components (filter, sort, search) with no onClick handlers and no disabled prop. These buttons appear on hover for every list subview (nodes, types, parameters, equations) but are completely non-functional — clicking them does nothing. This is confusing for users who will see interactive-looking buttons that produce no result. If these are scaffolding for future functionality, they need to either be disabled or removed until implemented.
| ), | ||
| ); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Clipboard async operations lack error handling
Medium Severity
Both copySelectionToClipboard and pasteFromClipboard are fired with void and no .catch() handler. The clipboard API (navigator.clipboard.readText/writeText) commonly throws when the document isn't focused or clipboard permission is denied. These unhandled rejections will surface as uncaught promise errors and potentially trigger error-tracking noise (e.g., Sentry).
| disabled: isReadOnly, | ||
| onClick: () => removeType(type.id), | ||
| }, | ||
| ]; |
There was a problem hiding this comment.
Hooks called inside callback violate Rules of Hooks
Medium Severity
The getMenuItems callbacks in types-list.tsx, differential-equations-list.tsx, and parameters-list.tsx call hooks (use(SDCPNContext), use(EditorContext), useIsReadOnly()) inside a plain callback function rather than at the top level of a React component. Although these execute during RowMenu's render and happen to work, this pattern violates React's Rules of Hooks and will be flagged by react-hooks/rules-of-hooks. It's fragile and confusing for future maintainers.



🌟 What is the purpose of this PR?
Add clipboard support and selection shortcuts to the petrinaut editor, enabling users to copy, paste, and select all items in the SDCPN canvas.
🔗 Related links
🔍 What does this change?
petrinaut-sdcpnv1). Arcs between selected nodes are preserved within their transitions; arcs to unselected nodes are stripped.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🐾 Next steps
🛡 What tests cover this?
deduplicate-name.test.ts— name suffix logic (12 tests)serialize.test.ts— serialization, arc stripping, payload parsing with zod validation (32 tests)paste.test.ts— ID generation, name deduplication, position offset, arc remapping, reference remapping, data preservation (33 tests)❓ How to test this?