Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .cursor/commands/add-test-for-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: "Add tests for a React component"
---

Add or update tests for the React component named $ARGUMENTS:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

⚠️ Додай top-level heading для markdown-валідності

Line 5: markdownlint MD041 валідно сигналізує, що після frontmatter має бути H1-заголовок.

As per coding guidelines: ".cursor/commands/*.md ... Файл містить чіткий опис, що команда робить" (для цього краще почати з явного H1).

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/add-test-for-component.md at line 5, Add a top-level H1
heading to the markdown (immediately after the frontmatter) to satisfy
markdownlint MD041; update the file containing the line "Add or update tests for
the React component named $ARGUMENTS:" by inserting a clear H1 like "# Add or
update tests for the React component" (or include $ARGUMENTS in the title) so
the document begins with an explicit H1 as required.


1. Locate the component and existing related tests in the same directory.
2. Follow `.cursor/rules/` and `AGENTS.md` conventions before editing.
3. Create or update a colocated `ComponentName.test.tsx` file.
4. Add basic render coverage plus key behavior/state interaction tests.
5. Reuse existing test utilities and patterns already used in this package.
6. Run relevant tests (or provide exact command) and summarize results.
14 changes: 14 additions & 0 deletions .cursor/commands/create-react-component-with-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: "Generate a new React component with tests"
---

Create a React component named $ARGUMENTS:

1. Create the component file following project conventions
2. Define a TypeScript props interface: `{Name}Props`
3. Use functional component with hooks
4. Use named export
5. Create a colocated test file with basic render test
6. Follow the patterns from existing components in the same directory
Comment on lines +7 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

⚠️ Додай явний крок запуску тестів після генерації

Line 7-12: команда створює компонент і тест, але не вимагає виконати nearest test suite/конкретну команду верифікації. Для воркфлоу це критично, інакше результат може лишитись неперевіреним.

Based on learnings: "Run the nearest relevant test file/suite after changes."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/create-react-component-with-test.md around lines 7 - 12,
Add an explicit step after step 5 to run the nearest relevant test suite for the
colocated test file created in step 5: invoke the project's test runner (e.g.,
pnpm/npm/yarn test or vitest/jest) targeting the generated test file or its
directory (so the runner verifies the new {Name}.test.*), and ensure the
generator fails/returns non‑zero if tests do not pass; reference the "colocated
test file" created in step 5 as the target to run.


Check .cursor/rules/ for architecture and convention constraints.
Comment on lines +5 to +14
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

⚠️ Є markdown-порушення (MD041, MD047)

Line 5-14: додай H1 після frontmatter і один trailing newline в кінці файлу.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)


[warning] 14-14: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/create-react-component-with-test.md around lines 5 - 14,
The markdown file is missing a top-level H1 header after the frontmatter and a
final trailing newline; update
.cursor/commands/create-react-component-with-test.md to insert a single H1 line
immediately after the YAML frontmatter block (e.g., a descriptive "# Create
React component with test" header) and ensure the file ends with one newline
character so there is exactly one trailing blank line at EOF.

12 changes: 12 additions & 0 deletions .cursor/commands/refactor-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: "Refactoring for a component"
---

Refactor a React component named $ARGUMENTS:

1. Read a files
2. Check .cursor/rules to match it
3. Check for DRY and code smell
4. Propose changes regarding what was finded
5. Check that new code compiles
6. Describe what changes been done
Comment on lines +5 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

⚠️ Команда робоча, але формулювання занадто слабкі для практичного використання

Line 5-12: інструкції загальні, з граматичними помилками, і без чіткого expected result/прикладу запуску (що саме має бути на виході після рефакторингу).

As per coding guidelines: ".cursor/commands/*.md ... Інструкції конкретні та корисні ... Приклади використання або очікуваний результат описані."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/refactor-code.md around lines 5 - 12, The instructions in
.cursor/commands/refactor-code.md (the Refactor a React component named
$ARGUMENTS section) are too vague and grammatically weak; rewrite this command
to be specific, corrected for grammar, and include an explicit expected result
and example usage: replace the current steps with concrete actions (e.g., "1.
Read target file(s) specified by $ARGUMENTS; 2. Match patterns against
.cursor/rules and list rule hits; 3. Identify DRY/code-smell instances and list
suggested refactors; 4. Produce a proposed refactored code snippet and ensure it
compiles; 5. Provide a short changelog summarizing modifications"), add a sample
CLI invocation and a sample before/after output snippet, and ensure the command
description references $ARGUMENTS so the caller knows what to pass.

14 changes: 14 additions & 0 deletions .cursor/commands/security-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
description: "Run a project security check"
---

Perform a security check for this project:

1. Inspect current changes and identify security-sensitive files.
2. Scan for obvious secrets, unsafe patterns, and risky defaults.
3. Review auth, input handling, and data exposure paths in touched code.
4. Check dependencies and scripts for known risky usage.
5. Report findings by severity with file paths and concrete fixes.
6. If no issues are found, state that clearly and note residual risks.
Comment on lines +7 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

⚠️ Security workflow варто прив’язати до Excalidraw-кейсів

Line 7-12: зараз чекліст загальний. Додай явні перевірки для Excalidraw (SVG/XSS, імпорт .excalidraw/library даних, доступи/експозиція даних у collaborative flow) і окремий крок про обов’язковий security-callout у PR summary.

Based on learnings: "Flag security-sensitive behavior changes in PR/summary notes."

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 12-12: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/security-check.md around lines 7 - 12, Update the generic
security checklist to add explicit Excalidraw-specific checks: include a step to
validate SVG/XSS sanitization for embedded SVGs, a step to verify safe
import/handling of .excalidraw and library data (schema/whitelist/size checks),
a step to review collaborative flow for access controls and data exposure
(presence of per-room permissions and telemetry limits), and a required
"security-callout" entry in the PR summary that flags any security-sensitive
behavior changes; ensure these items are added alongside the existing numbered
checklist so reviewers must confirm them before sign-off.


Check `.cursor/rules/` and `AGENTS.md` for project guardrails before suggesting changes.
Comment on lines +5 to +14
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

⚠️ Виправ markdown lint (H1 + trailing newline)

Line 5-14: додай top-level heading після frontmatter і один newline в кінці файлу.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)


[warning] 12-12: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/commands/security-check.md around lines 5 - 14, Add a top-level H1
heading immediately after the existing frontmatter in the Markdown (insert a
single line starting with "# " and the document title or summary) and ensure the
file ends with exactly one newline character (no extra blank lines); locate the
frontmatter block and update the content following it to insert the H1 and
verify/trim the EOF so there's a single trailing newline.

25 changes: 25 additions & 0 deletions .cursor/rules/conventions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
description: "Code conventions for components and utilities"
globs: packages/**/*.ts,packages/**/*.tsx
alwaysApply: false
---

# Code Conventions

## Components

- Functional components + hooks ONLY (no class components)
- Props interface: `{ComponentName}Props`
- Named exports only (no default exports)
- Colocated tests: `ComponentName.test.tsx`

## TypeScript

- Strict mode — no `any`, no `@ts-ignore`
- Prefer `type` over `interface` for simple types
- Import types: `import type { X } from "..."`

## Files

- kebab-case for files: `element-utils.ts`
- PascalCase for components: `LayerUI.tsx`
Comment on lines +1 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

❌ Відсутня обов'язкова секція "How to verify"

Згідно з чеклістом завдання День 2, кожне правило має містити секцію "How to verify" — як перевірити, що правило працює. Це критична вимога для всіх файлів у .cursor/rules/.

⚠️ Правила занадто загальні

Поточні конвенції (functional components, named exports, strict TypeScript) — це універсальні практики для будь-якого React-проєкту. Для Excalidraw краще додати специфічні правила, наприклад:

  • Конвенції для element utilities (src/element/)
  • Правила роботи з canvas context
  • Naming для action creators
  • Структура для geometry/math utilities
📝 Приклад доповнення з секцією верифікації
 ## Files
 
 - kebab-case for files: `element-utils.ts`
 - PascalCase for components: `LayerUI.tsx`
+
+## Excalidraw-Specific Patterns
+
+- Element utilities: prefer pure functions in `packages/element/`
+- Canvas operations: wrap in try-catch, handle context loss
+- Action creators: use `actionManager.dispatch()`, not direct state mutation
+
+## How to Verify
+
+1. Run `yarn test:code` — має пройти без помилок
+2. Перевір, що нові компоненти експортуються named exports
+3. Перевір `git diff` — нові файли мають kebab-case/PascalCase відповідно
+4. Запусти `yarn test:typecheck` — не має бути `any` або `@ts-ignore`

Як per coding guidelines для .cursor/rules/*.mdc: правило має бути конкретним і перевірюваним, не generic "write clean code".

📝 Committable suggestion

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

Suggested change
---
description: "Code conventions for components and utilities"
globs: packages/**/*.ts,packages/**/*.tsx
alwaysApply: false
---
# Code Conventions
## Components
- Functional components + hooks ONLY (no class components)
- Props interface: `{ComponentName}Props`
- Named exports only (no default exports)
- Colocated tests: `ComponentName.test.tsx`
## TypeScript
- Strict mode — no `any`, no `@ts-ignore`
- Prefer `type` over `interface` for simple types
- Import types: `import type { X } from "..."`
## Files
- kebab-case for files: `element-utils.ts`
- PascalCase for components: `LayerUI.tsx`
---
description: "Code conventions for components and utilities"
globs: packages/**/*.ts,packages/**/*.tsx
alwaysApply: false
---
# Code Conventions
## Components
- Functional components + hooks ONLY (no class components)
- Props interface: `{ComponentName}Props`
- Named exports only (no default exports)
- Colocated tests: `ComponentName.test.tsx`
## TypeScript
- Strict mode — no `any`, no `@ts-ignore`
- Prefer `type` over `interface` for simple types
- Import types: `import type { X } from "..."`
## Files
- kebab-case for files: `element-utils.ts`
- PascalCase for components: `LayerUI.tsx`
## Excalidraw-Specific Patterns
- Element utilities: prefer pure functions in `packages/element/`
- Canvas operations: wrap in try-catch, handle context loss
- Action creators: use `actionManager.dispatch()`, not direct state mutation
## How to Verify
1. Run `yarn test:code` — має пройти без помилок
2. Перевір, що нові компоненти експортуються named exports
3. Перевір `git diff` — нові файли мають kebab-case/PascalCase відповідно
4. Запусти `yarn test:typecheck` — не має бути `any` або `@ts-ignore`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/conventions.mdc around lines 1 - 25, Add a mandatory "How to
verify" subsection to each rule in .cursor/rules/conventions.mdc that gives a
concrete, testable checklist or commands for validating the rule (e.g., lint
commands, unit-test names, or manual steps); replace generic items under
"Components", "TypeScript", and "Files" with Excalidraw-specific checks
(examples: conventions for element utilities in src/element/, rules for
interacting with canvas context, naming conventions for action creators, and
expected structure for geometry/math utilities) and include a verification step
for each new rule showing exactly how to confirm compliance (lint rule or grep
pattern, unit test name, or sample code snippet to run).

25 changes: 25 additions & 0 deletions .cursor/rules/css-conventions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
description: "CSS styling conventions and guardrails"
globs: **/*.css,**/*.scss
alwaysApply: false
---

# CSS Conventions

## Maintainability

- Keep selectors shallow; avoid deeply nested or overly specific selectors.
- Prefer class selectors over tag selectors for component styling.
- Keep related declarations grouped and ordered consistently.

## Tokens and Values

- Prefer CSS variables (design tokens) over hardcoded colors, spacing, and sizes.
- Avoid magic numbers unless they are clearly documented by context.
- Reuse existing utility classes and shared styles before adding new ones.

## Safety and Scope

- Avoid `!important` unless there is no safe alternative.
- Do not introduce global resets or broad overrides without explicit need.
- Keep styles scoped to the feature/component to reduce side effects.
Comment on lines +3 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

⚠️ Правило частково ок, але занадто generic і без верифікації

Line 3-25: правило корисне як база, але не прив’язане до реалій Excalidraw (editor/canvas-патерни) і не містить "How to verify". Також globs надто широкі для module-scoped правила.

As per coding guidelines: "Тіло правила конкретне та стосується Excalidraw", "Є секція 'How to verify'", "Якщо є globs — вони конкретні, не **/* або занадто широкі."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/css-conventions.mdc around lines 3 - 25, The CSS rule is too
generic and lacks verification steps; update the rule in the CSS Conventions
block to target Excalidraw-specific patterns (editor/canvas components) by
narrowing globs from "**/*.css,**/*.scss" to module-scoped patterns (e.g.,
component directories) and add a "How to verify" section with concrete checks
(examples: confirm no global resets, ensure variables used for Excalidraw
tokens, verify selectors are limited to .excalidraw- or component-specific
classes, and run a quick style smoke test on the editor/canvas). Also adjust the
Maintainability/Tokens and Values/Safety and Scope items to reference Excalidraw
conventions (e.g., prefer --excalidraw- variables, avoid !important in canvas
controls) so the rule is actionable and verifiable.

3 changes: 3 additions & 0 deletions .cursor/rules/do-not-touch.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
alwaysApply: true
---
Comment on lines +1 to +3
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

❌ Правило фактично порожнє і не проходить критерії Дня 2

Line 1-3: є лише alwaysApply, але немає description, змісту правила і секції "How to verify". У поточному вигляді це не перевірюване правило для Excalidraw.

As per coding guidelines: ".cursor/rules/*.mdc ... Перевір: 1) frontmatter з description ... 3) Є секція 'How to verify' ... 2) правило конкретне та стосується Excalidraw."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/do-not-touch.mdc around lines 1 - 3, The rule file contains
only frontmatter with alwaysApply and is missing required metadata and
verification steps; update the frontmatter to include a descriptive
"description" field, add meaningful rule content explaining the specific
Excalidraw constraint this rule enforces (make it concrete and testable), and
append a "How to verify" section with step-by-step verification steps that
confirm the rule applies to Excalidraw artifacts; ensure the rule text
references Excalidraw explicitly and that the frontmatter and body conform to
the `.cursor/rules/*.mdc` guidelines (include the existing alwaysApply key
alongside the new description and verification sections).

24 changes: 24 additions & 0 deletions .cursor/rules/project-architecture.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
description: "Architecture constraints for the project"
globs: packages/**
alwaysApply: false
---

# Project Architecture

## State Management

- Custom state via actionManager - NOT Redux/Zustand/MobX
- State updates: actionManager.dispatch() ONLY
- State type: AppState (src/types.ts)
Comment on lines +12 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

❌ Невірні API/шляхи: це зламає згенерований код

Line 12-13: actionManager.dispatch() відсутній у packages/excalidraw/actions/manager.tsxexecuteAction()), а AppState вказаний із хибного шляху (src/types.ts замість packages/excalidraw/types.ts). Це критична помилка в правилі архітектури.

Based on learnings: "Canvas rendering pipeline is authoritative for drawing; do not replace drawing flow with React DOM-based drawing" і "Read relevant files and existing local patterns first before implementing code changes."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/project-architecture.mdc around lines 12 - 13, The rule
references incorrect symbols: replace uses of actionManager.dispatch() with the
actual API executeAction() (refer to the actions manager implementation where
executeAction is exported) and correct the AppState type reference to use the
repository's Excalidraw types module (the exported AppState type from the
project types module) instead of the wrong src/types.ts; update the rule text to
name the real symbol executeAction and the real type symbol AppState from the
project's types module so generated code points to existing APIs.


## Rendering

- Canvas 2D rendering - NOT React DOM for drawing
- Render pipeline: Scene -> renderScene() -> canvas context
- DO NOT use react-konva, fabric.js, pixi.js

## Dependencies

- No new npm packages without explicit approval
- Check src/utils/ before adding external helpers
Comment on lines +18 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

⚠️ Опис рендер-пайплайну спрощений і без секції перевірки

Line 18-24: формулювання Scene -> renderScene() занадто спрощене для поточної архітектури, і в правилі відсутній розділ "How to verify". У такому вигляді агент отримує неточний орієнтир.

As per coding guidelines: "Тіло правила конкретне та стосується Excalidraw" і "Є секція 'How to verify'."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/project-architecture.mdc around lines 18 - 24, The "Render
pipeline: Scene -> renderScene()" rule is too vague and missing a "How to
verify" section; update the rule text to explicitly describe the
Excalidraw-specific render flow (e.g., Scene model -> layout/transform ->
renderScene() invocation -> canvas 2D context draw calls and any
post-processing), remove/keep the prohibition on react-konva/fabric.js/pixi.js
as-is, and add a concrete "How to verify" section that lists steps to validate
behavior (unit/integration test targets, manual verification steps in
Excalidraw, expected DOM/canvas outputs and performance checks). Reference the
existing rule header "Render pipeline: Scene -> renderScene()" and ensure the
new text mentions renderScene(), Scene, canvas context, and verification steps.

30 changes: 30 additions & 0 deletions .cursor/rules/security-rules.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
description: "Security guardrails for code and reviews"
globs: packages/**/*.ts,packages/**/*.tsx,excalidraw-app/**/*.ts,excalidraw-app/**/*.tsx
alwaysApply: false
---

# Security Rules

## Secrets and Sensitive Data

- Never hardcode secrets, tokens, passwords, or private keys.
- Do not commit credentials or `.env` values into source files or tests.
- Redact sensitive values in logs, test fixtures, and examples.

## Input and Output Safety

- Treat all external/user input as untrusted and validate/sanitize it.
- Avoid unsafe HTML injection patterns; do not bypass sanitization intentionally.
- Validate URLs and external resource identifiers before use.

## Access and Permissions

- Follow least-privilege principles when adding new capabilities.
- Do not broaden data access or permissions without explicit justification.

## Dependencies and Risky Changes

- No new dependencies without explicit approval.
- Flag security-sensitive behavior changes in PR/summary notes.
- Add tests for security-relevant logic (validation, sanitization, permissions).
Comment on lines +7 to +30
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

⚠️ Security-правило добре структуроване, але не прив’язане до Excalidraw і без "How to verify"

Line 7-30: зміст занадто загальний. Для цього репозиторію потрібні конкретні пункти про SVG/XSS, безпечний імпорт .excalidraw/library-файлів, collaboration encryption/Firebase rules, плюс верифікація правила.

As per coding guidelines: ".cursor/rules/security* ... Стосується реальних security-аспектів Excalidraw ... Має секцію 'How to verify'."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/security-rules.mdc around lines 7 - 30, The Security Rules
section is too generic for this repo and missing Excalidraw-specific controls
and a "How to verify" section; update the existing headings ("Secrets and
Sensitive Data", "Input and Output Safety", "Access and Permissions",
"Dependencies and Risky Changes") to include concrete rules for Excalidraw: add
explicit SVG/XSS mitigation guidance (sanitize imported SVGs, forbid unsafe
innerHTML, validate shape data), safe import/handling rules for .excalidraw and
library files (whitelist parsers, validate JSON structure and types),
collaboration/encryption and Firebase rules (require end-to-end encryption
flags, strict Firestore rules for drawing documents), and require tests/CI
checks for validation/sanitization; finally add a "How to verify" subsection
with reproducible verification steps and automated test expectations so
reviewers can validate each rule.

31 changes: 31 additions & 0 deletions .cursor/rules/testing-conventions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
description: "Testing standards for unit and component tests"
globs: **/*.test.ts,**/*.test.tsx
alwaysApply: false
---

# Testing Conventions

## Coverage Expectations

- Add or update tests for any behavior change.
- Prefer focused tests near the changed code over broad snapshot-only tests.
- Cover happy path and at least one failure/edge path when applicable.

## Test Quality

- Use clear test names that describe behavior, not implementation details.
- Assert observable outcomes (rendered output, callbacks, state effects).
- Keep tests deterministic; avoid real timers/network unless explicitly needed.
- Reuse existing test utilities from the package before adding new helpers.

## Safety

- Do not use `it.only`/`describe.only` or leave skipped tests unintentionally.
- Avoid overly broad snapshots that hide regressions.
- Keep test data minimal and readable.

## Agent Verification

- Run the nearest relevant test file/suite after changes.
- For shared/type-heavy changes, also run lint and typecheck.
Comment on lines +1 to +31
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

⚠️ Секція "Agent Verification" замість "How to verify"

Чеклист завдання вимагає секцію з назвою "How to verify". Хоча "Agent Verification" семантично близька, краще дотримуватись точної назви для консистентності з іншими правилами.

⚠️ Правила занадто загальні

Поточні конвенції (clear test names, deterministic tests, avoid snapshots) — універсальні для будь-якого проєкту. Для Excalidraw варто додати специфічні патерни тестування:

  • Як тестувати canvas rendering (використання getContext("2d"), mock canvas API)
  • Як тестувати action flows через actionManager.dispatch()
  • Як тестувати collaboration features (multi-user scenarios)
  • Patterns для geometry/math utilities testing
♻️ Приклад доповнення
 ## Safety
 
 - Do not use `it.only`/`describe.only` or leave skipped tests unintentionally.
 - Avoid overly broad snapshots that hide regressions.
 - Keep test data minimal and readable.
+
+## Excalidraw-Specific Testing Patterns
+
+- **Canvas rendering**: Mock `getContext("2d")` or use test utilities from `packages/excalidraw/tests/`
+- **Action flows**: Test via `actionManager.dispatch()`, verify state changes in `appState`/`elements`
+- **Geometry/math**: Use property-based testing for coordinate transforms where applicable
+- **Collaboration**: Test socket message handling, conflict resolution, multi-user state sync
 
-## Agent Verification
+## How to Verify
 
 - Run the nearest relevant test file/suite after changes.
 - For shared/type-heavy changes, also run lint and typecheck.
+- Example: After editing `LayerUI.tsx`, run `yarn test LayerUI.test.tsx`
+- Verify no `it.only` left: `rg "it\.only|describe\.only" --glob "**/*.test.{ts,tsx}"`

Як per coding guidelines для .cursor/rules/*.mdc: правило має бути конкретним та перевірюваним, з секцією "How to verify".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.cursor/rules/testing-conventions.mdc around lines 1 - 31, Rename the "Agent
Verification" section header to the exact "How to verify" header and replace its
contents with concrete, testable verification steps (run the nearest relevant
test file/suite, run lint and typecheck for shared/type-heavy changes);
additionally extend the rule with Excalidraw-specific patterns: explicit
guidance for canvas rendering tests (mocking getContext("2d") / canvas API),
action flow tests using actionManager.dispatch(), collaboration/multi-user
scenario patterns, and geometry/math utilities testing patterns (deterministic
inputs and edge cases); ensure each new item is framed as a verifiable check
(what to run/assert) so the rule in .cursor/rules/testing-conventions.mdc is
specific and testable.

115 changes: 115 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# AGENTS.md

This file provides project-specific guidance for coding agents working in this repository.

## Quick Facts

- Monorepo name: `excalidraw-monorepo`
- Package manager: `yarn@1.22.22` (use `yarn`, not `npm`)
- Node: `>=18.0.0`
- Main workspace areas:
- `excalidraw-app/` - app shell and app-specific runtime
- `packages/excalidraw/` - core editor package
- `packages/common/`, `packages/element/`, `packages/math/`, `packages/utils/` - shared modules
- `examples/` - integration examples
- `scripts/` - build/release/tooling scripts

Comment on lines +1 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

❌ Відсутня секція "Project Overview"

Згідно з вимогами завдання, AGENTS.md має містити короткий опис проєкту Excalidraw (2-5 речень). Це критично для AI-агентів, щоб розуміти контекст: що це за проєкт, яка його мета, основні особливості.

⚠️ Неповна секція "Tech Stack"

У "Quick Facts" згадується лише yarn та Node, але немає явного переліку ключових технологій:

  • React (UI framework)
  • TypeScript (мова)
  • Vite (bundler для dev/production)
  • Vitest (testing framework)
  • Yarn workspaces (monorepo management)
📋 Приклад доповнення

Додай на початку файлу (після заголовка):

 # AGENTS.md
 
 This file provides project-specific guidance for coding agents working in this repository.
+
+## Project Overview
+
+Excalidraw is an open-source virtual whiteboard for sketching hand-drawn diagrams and collaborating in real-time. The editor provides an infinite canvas with primitive shapes (rectangles, ellipses, arrows, text, freehand), supports multi-user collaboration via WebRTC/WebSocket, and renders everything to HTML5 Canvas. The project is built as a monorepo containing the core editor package, app shell, and shared utility libraries.
 
 ## Quick Facts
 
 - Monorepo name: `excalidraw-monorepo`
 - Package manager: `yarn@1.22.22` (use `yarn`, not `npm`)
 - Node: `>=18.0.0`
+
+## Tech Stack
+
+- **UI Framework**: React 18+ (functional components, hooks)
+- **Language**: TypeScript (strict mode)
+- **Build Tool**: Vite (dev server + production builds)
+- **Testing**: Vitest (unit/integration), React Testing Library
+- **Monorepo**: Yarn workspaces
+- **Rendering**: HTML5 Canvas API (native, no abstraction libraries)
+
 - Main workspace areas:

Як per coding guidelines для AGENTS.md: мінімум 5 з 7 секцій мають бути присутні та заповнені — у вас 5/7 ✅, але Project Overview та повний Tech Stack критичні для розуміння контексту.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 1 - 16, Add a new "Project Overview" section under
the "# AGENTS.md" header with a 2–5 sentence summary describing Excalidraw (what
the project is, its purpose, and key features) and expand the existing "Quick
Facts" / "Tech Stack" area to explicitly list core technologies (React,
TypeScript, Vite, Vitest, Yarn workspaces) so AI agents have clear context;
update the "Project Overview" and "Tech Stack" headings in AGENTS.md
accordingly.

## Most Used Commands

Run from repo root unless noted otherwise.

### Setup

- Install dependencies: `yarn install`
- Fresh reinstall: `yarn clean-install`

### Development

- Start app dev server: `yarn start`
- Start production-like app server: `yarn start:production`
- Build app: `yarn build`
- Build all packages: `yarn build:packages`
- Build only core package: `yarn build:excalidraw`

### Testing and Quality

- Main test run: `yarn test`
- Full CI-like checks: `yarn test:all`
- Unit/integration tests: `yarn test:app`
- Typecheck: `yarn test:typecheck`
- Lint: `yarn test:code`
- Format check: `yarn test:other`
- Coverage: `yarn test:coverage`
- Update snapshots: `yarn test:update`
- Auto-fix lint and format: `yarn fix`

### Cleanup and Maintenance

- Remove build artifacts: `yarn rm:build`
- Remove `node_modules`: `yarn rm:node_modules`

## Code Conventions

- TypeScript strict mode; avoid `any` and `@ts-ignore`.
- Use functional React components and hooks.
- Use named exports (no default exports).
- Name props as `{ComponentName}Props` for components.
- Keep tests colocated where practical (`ComponentName.test.tsx`).
- Use `import type { ... }` for type-only imports.

## Architecture Rules

- State management uses internal action flow:
- Use `actionManager.dispatch()` for state updates.
- Do not introduce Redux, Zustand, MobX, or similar global stores.
- Rendering architecture:
- Canvas rendering pipeline is authoritative for drawing.
- Do not replace drawing flow with React DOM-based drawing.
- Do not add canvas abstraction libraries (react-konva, fabric.js, pixi.js).

## Guardrails (Must Follow)

- Do not add new npm/yarn dependencies without explicit approval.
- Do not modify protected core files unless explicitly requested and validated:
- `src/core/renderer.ts`
- `src/data/restore.ts`
- `src/actions/manager.ts`
- `src/types.ts`
- If protected files are changed, run complete tests and perform manual verification.

## Agent Workflow Expectations

When implementing code changes:

1. Read relevant files and existing local patterns first.
2. Follow `.cursor/rules/*.mdc` and this file before editing.
3. Keep changes focused and avoid unrelated refactors.
4. Reuse existing utilities before introducing new abstractions.
5. After edits, run targeted checks first, then broader checks if needed.
6. Report what changed, why, and any residual risks.

## Testing Strategy for Agents

- For small isolated component changes:
- Run targeted tests first (nearest suite/file).
- Run lint/typecheck if types or shared interfaces changed.
- For broader/editor-impacting changes:
- Run `yarn test:all` when feasible.
- Minimum expected verification for most PR-sized changes:
- `yarn test:code`
- `yarn test:typecheck`
- Relevant `yarn test` coverage for touched areas

## Pull Request and Review Notes

- Keep PRs scoped and descriptive.
- Include rationale, not only a list of file changes.
- Flag behavior changes, migration implications, and follow-up tasks.
- Prefer adding or updating tests alongside behavior changes.

## Security and Reliability Basics

- Never commit secrets, credentials, or private tokens.
- Validate and sanitize untrusted inputs where relevant.
- Avoid risky defaults that can leak data or broaden permissions.
- Call out security-sensitive changes explicitly in summaries.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

⚠️ Відсутній trailing newline

Файл має закінчуватися одним порожнім рядком (newline character). Це стандарт POSIX та вимога більшості linters.

🔧 Виправлення

Додай порожній рядок в кінці файлу після останнього речення:

 - Call out security-sensitive changes explicitly in summaries.
+

Based on learnings from static analysis tools: markdownlint-cli2 flags MD047 (single-trailing-newline).

📝 Committable suggestion

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

Suggested change
- Call out security-sensitive changes explicitly in summaries.
- Call out security-sensitive changes explicitly in summaries.
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 115-115: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` at line 115, The file AGENTS.md is missing a trailing newline
(MD047); add a single newline character after the final line ("Call out
security-sensitive changes explicitly in summaries.") so the file ends with one
blank line, save and commit the change.

68 changes: 68 additions & 0 deletions packages/excalidraw/components/ElementPropertiesPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import clsx from "clsx";

import { CLASSES } from "@excalidraw/common";

import type {
NonDeletedElementsMap,
NonDeletedSceneElementsMap,
} from "@excalidraw/element/types";

import { CompactShapeActions, SelectedShapeActions } from "./Actions";
import { Island } from "./Island";
import { useStylesPanelMode } from "./App";

import type { ActionManager } from "../actions/manager";
import type { AppClassProperties, AppState, UIAppState } from "../types";

type ElementPropertiesPanelProps = {
appState: UIAppState;
elementsMap: NonDeletedElementsMap | NonDeletedSceneElementsMap;
renderAction: ActionManager["renderAction"];
app: AppClassProperties;
setAppState: React.Component<any, AppState>["setState"];
maxHeight: number;
};

export const ElementPropertiesPanel = ({
appState,
elementsMap,
renderAction,
app,
setAppState,
maxHeight,
}: ElementPropertiesPanelProps) => {
const isCompactStylesPanel = useStylesPanelMode() === "compact";

if (isCompactStylesPanel) {
return (
<Island
className={clsx("compact-shape-actions-island")}
padding={0}
style={{ maxHeight: `${maxHeight}px` }}
>
<CompactShapeActions
appState={appState}
elementsMap={elementsMap}
renderAction={renderAction}
app={app}
setAppState={setAppState}
/>
</Island>
);
}

return (
<Island
className={CLASSES.SHAPE_ACTIONS_MENU}
padding={2}
style={{ maxHeight: `${maxHeight}px` }}
>
<SelectedShapeActions
appState={appState}
elementsMap={elementsMap}
renderAction={renderAction}
app={app}
/>
</Island>
);
};
Loading