Grida Canvas - Aspect Ratio#473
Conversation
|
Caution Review failedThe pull request is closed. WalkthroughThis PR renames and extends layout fields across the codebase: Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–75 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
crates/grida-dev/examples/grida_blendmode.rs (1)
1-1: Address the FIXME comment - broken demo status needs verification.The FIXME comment indicates this demo might be broken and should be renamed to use a
golden_prefix instead ofgrida_. Since this is an example file demonstrating blend mode functionality, having a potentially broken demo is problematic, especially when verifying that the layout field changes work correctly.Would you like me to help verify whether this demo is actually broken and investigate the naming convention issue? I can generate scripts to check for similar examples and naming patterns.
supabase/drafts/20251214_grida_canvas_document_model.sql (1)
410-421: Update comments to reflect renamed fields.The comments in the shape parity checklist still reference
layout_width/layout_heightinstead of the newlayout_target_width/layout_target_heightfield names. Update these comments for consistency.Suggested fix for comment consistency
- - Node::Rectangle -> node_type='rectangle' + transform + layout_width/layout_height + rectangular_corner_radius_* + fill_paints/stroke_paints/effects + - Node::Rectangle -> node_type='rectangle' + transform + layout_target_width/layout_target_height + rectangular_corner_radius_* + fill_paints/stroke_paints/effectsApply similar changes to all other comments referencing the old field names on lines 410-421.
🧹 Nitpick comments (10)
editor/scaffolds/sidecontrol/controls/width-height.tsx (1)
31-42: Consider extracting magic numbers to constants.The hardcoded positioning values (
top: "0.5rem"andbottom: "0.5rem") could be extracted to named constants for better maintainability. This is a minor improvement and not required.Optional refactor to use constants
+const BRACKET_OFFSET = "0.5rem"; + export function WidthHeightControl({ ... }) { return ( <div className="relative flex flex-col gap-2 py-1"> <div className="absolute left-16 top-0 bottom-0 z-10 flex items-center justify-center"> <div className="absolute left-1/2 -translate-x-1/2 w-2.5 h-2.5 border-0 border-l-2 border-t-2 border-border rounded-tl-sm" - style={{ top: "0.5rem" }} + style={{ top: BRACKET_OFFSET }} /> <div className="absolute left-1/2 -translate-x-1/2 w-2.5 h-2.5 border-0 border-l-2 border-b-2 border-border rounded-bl-sm" - style={{ bottom: "0.5rem" }} + style={{ bottom: BRACKET_OFFSET }} />packages/grida-cmath/index.ts (2)
38-68: Normalizemax_denominatorto a sensible integer bound inaspectRatio
aspectRatiorelies onrational.approximateFraction’smax_denominatoras an upper bound, but currently accepts arbitrary positive reals. Values likemax_denominator = 0.5lead to degenerate results (e.g. a positive aspect ratio producing[0, 1]). Coercing to an integer ≥ 1 at the boundary keeps the API predictable.Proposed tweak: clamp & floor
max_denominatorbefore useexport function aspectRatio( width: number, height: number, max_denominator: number = 1000 ): [number, number] | undefined { if ( !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0 ) { return undefined; } + // Ensure we pass a sane integer bound to the rational helper. + max_denominator = Math.max(1, Math.floor(max_denominator)); + const r = width / height; const frac = rational.approximateFraction(r, max_denominator);
648-712:rational.approximateFractionlooks solid for bounded‑denominator aspect‑ratio useThe continued‑fraction implementation with
max_denominatorclamp, input validation, and sign handling is well structured and matches howaspectRatioconsumes it. With thegcdfix above in place, this should be robust for canvas/layout use cases.If you ever want to harden it further, you could (a) explicitly clamp
epsilonto a reasonable positive range, and/or (b) document thatmax_denominatoris interpreted as an integer bound (then align it with theaspectRationormalization above).packages/grida-cmath/__tests__/cmath.rational.test.ts (1)
1-35: Good test coverage for core functionality.The test suite covers the essential cases: exact fractions, zero, common rationals, max_denominator constraint, and invalid inputs. The tests are well-structured and clear.
Consider adding edge case tests for more comprehensive coverage:
Suggested additional test cases
test("should handle max_denominator boundary cases", () => { // Very small denominators const result1 = cmath.rational.approximateFraction(0.7, 1); expect(result1).toEqual([1, 1]); // closest to 0.7 with denom=1 // Exact hit on max_denominator const result2 = cmath.rational.approximateFraction(0.5, 2); expect(result2).toEqual([1, 2]); }); test("should handle floating point precision edge cases", () => { // Very large numbers const result = cmath.rational.approximateFraction(1e10 + 0.5); expect(result).toBeDefined(); // Very small numbers const result2 = cmath.rational.approximateFraction(1e-10); expect(result2).toBeDefined(); });editor/grida-canvas/reducers/methods/scale.ts (1)
245-258: Consider improving type safety forlayout_target_aspect_ratioaccess.The use of
(first_node as any).layout_target_aspect_ratiobypasses TypeScript's type checking. Iflayout_target_aspect_ratiois a legitimate property on certain node types, consider adding it to the appropriate type definition or using a type guard.🔎 Suggested improvement
- const first_node = draft.document.nodes[ - selection[0] - ] as grida.program.nodes.Node; - const target_ratio = (first_node as any).layout_target_aspect_ratio as - | [number, number] - | undefined; + const first_node = draft.document.nodes[ + selection[0] + ] as grida.program.nodes.Node; + const target_ratio = + "layout_target_aspect_ratio" in first_node + ? (first_node.layout_target_aspect_ratio as [number, number] | undefined) + : undefined;editor/grida-canvas/reducers/node-transform.reducer.ts (1)
59-64: Aspect‑ratio scaling branch looks correct; consider a small defensive guardThe new
targetAspectRatiohandling in thepreserveAspectRatiopath correctly:
- Picks a dominant axis from
movement- Derives a
(newWidth, newHeight)pair that matches the requested ratio- Converts back to scale factors relative to
rect.width/rect.height- Falls back to the previous “use current rect aspect ratio” behavior when
targetAspectRatiois absent.Given
targetAspectRatiois a free tuple, you might optionally add a simple validation (e.g. ignore or clamp iftargetAspectRatio[1] <= 0) to make this reducer robust against bad upstream data, but functionally this change is sound.Also applies to: 109-110, 121-151
editor/grida-canvas-react/viewport/surface.tsx (1)
93-93: Aspect‑ratio guide integration inNodeOverlayis sound; consider tightening visibility and reusing selection dataThe new logic in
NodeOverlay:
- Correctly derives rect dimensions from
useSingleSelection(node_id)and the current transform scale.- Shows the
AspectRatioGuideonly when:
- A scale gesture is active,
- The node is part of
gesture.selection, and- Either the node has
layout_target_aspect_ratio, the scale tool is in uniform mode (gesture.uniform_scale), or the preserve‑aspect‑ratio modifier is on.This matches the intended semantics for aspect‑ratio‑constrained resizing, and the way you feed
rectanddirectioninto<AspectRatioGuide>is consistent with how the overlay is sized.Two optional cleanups you might consider:
Limit the guide to the “primary” interactive overlay
Right now,
show_aspect_ratio_guideignoresfocused/readonly, so any overlay whose node is ingesture.selectioncan render the diagonal (e.g. per‑node overlays in multi‑selection). If you only want the main interactive overlay to show the guide, you could also requirefocused && !readonlyin the predicate.Avoid recomputing
useSingleSelectiontwice
SingleSelectionOverlayandNodeOverlayboth calluseSingleSelection(node_id). For heavier scenes this doubles geometry queries. A small refactor would be to compute the selection data once inSingleSelectionOverlayand pass it intoNodeOverlayas a prop, letting other callers (hover, remote cursors) keep using the hook directly.These are polish‑level; the current implementation is functionally correct.
Also applies to: 1194-1202, 1238-1249, 1250-1259, 1461-1473
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsx (1)
16-57: Codify direction → diagonal mapping with small unit testsThe corner/edge → endpoints mapping is non-trivial but pure; a couple of focused tests around
getDiagonalEndpoints(one case perCardinalDirection) would lock in the intended behavior and make future refactors safer.crates/grida-canvas/src/io/io_grida.rs (1)
756-771: New layout min/max and aspect-ratio fields are wired correctly; consider adding deserialization testsThe serde setup for
layout_min_*/layout_max_*(with aliases likeminWidth/maxWidth) andlayout_target_aspect_ratio(aliasaspectRatio) plus the mapping intoLayoutDimensionStyleinFrom<JSONContainerNode>all look consistent with the updated layout model.To avoid regressions, it would be worthwhile to add a small test that:
- Deserializes a
JSONContainerNodewith these fields set (using both canonical names and aliases), and- Asserts the resulting
ContainerNodeRec.layout_dimensionsmin/max andlayout_target_aspect_ratiovalues.Also applies to: 1368-1375
crates/grida-canvas/src/node/schema.rs (1)
324-405: UniformNodeLayout and LayoutDimensionStyle structure are coherent; consider a small API helper for aspect ratioThe expanded
UniformNodeLayout/LayoutDimensionStylesurface (target size, min/max, aspect ratio, container + child properties, and an explicitlayout_position) reads cleanly and lines up with howinto_taffy.rsconsumes it.To keep callsites from having to construct raw
(f32, f32)tuples and to centralize invariants (e.g., rejecting non‑positive or NaN values), you might consider adding a small builder-style helper like:
with_layout_aspect_ratio(width: f32, height: f32) -> Selfthat normalizes/validates the pair before assigning
layout_target_aspect_ratio.Also applies to: 407-537, 808-817, 819-831
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (65)
crates/csscascade/src/rcdom/mod.rs(0 hunks)crates/grida-canvas/examples/golden_container_stroke.rs(1 hunks)crates/grida-canvas/examples/golden_fe_noise.rs(1 hunks)crates/grida-canvas/examples/golden_layout_flex.rs(1 hunks)crates/grida-canvas/examples/golden_layout_flex_alignment.rs(1 hunks)crates/grida-canvas/examples/golden_layout_flex_padding.rs(1 hunks)crates/grida-canvas/examples/golden_layout_padding.rs(2 hunks)crates/grida-canvas/examples/golden_pdf.rs(1 hunks)crates/grida-canvas/examples/golden_sk_paragraph_path_vector.rs(1 hunks)crates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rs(1 hunks)crates/grida-canvas/examples/golden_svg.rs(1 hunks)crates/grida-canvas/examples/golden_vector_regions_fills.rs(1 hunks)crates/grida-canvas/examples/golden_vector_regions_strokes.rs(1 hunks)crates/grida-canvas/src/cache/geometry.rs(1 hunks)crates/grida-canvas/src/io/io_figma.rs(5 hunks)crates/grida-canvas/src/io/io_grida.rs(2 hunks)crates/grida-canvas/src/layout/engine.rs(16 hunks)crates/grida-canvas/src/layout/into_taffy.rs(4 hunks)crates/grida-canvas/src/node/factory.rs(1 hunks)crates/grida-canvas/src/node/schema.rs(6 hunks)crates/grida-canvas/src/shape/stroke_rect.rs(1 hunks)crates/grida-canvas/src/svg/pack.rs(1 hunks)crates/grida-canvas/tests/geometry_cache.rs(1 hunks)crates/grida-canvas/tests/hit_test.rs(2 hunks)crates/grida-canvas/tests/scene_cache.rs(1 hunks)crates/grida-dev/examples/grida_basic.rs(1 hunks)crates/grida-dev/examples/grida_blendmode.rs(1 hunks)crates/grida-dev/examples/grida_booleans.rs(1 hunks)crates/grida-dev/examples/grida_container.rs(1 hunks)crates/grida-dev/examples/grida_effects.rs(1 hunks)crates/grida-dev/examples/grida_fills.rs(2 hunks)crates/grida-dev/examples/grida_gradients.rs(1 hunks)crates/grida-dev/examples/grida_image.rs(1 hunks)crates/grida-dev/examples/grida_images.rs(1 hunks)crates/grida-dev/examples/grida_lines.rs(1 hunks)crates/grida-dev/examples/grida_mask.rs(2 hunks)crates/grida-dev/examples/grida_nested.rs(1 hunks)crates/grida-dev/examples/grida_paint.rs(1 hunks)crates/grida-dev/examples/grida_shapes.rs(1 hunks)crates/grida-dev/examples/grida_shapes_ellipse.rs(1 hunks)crates/grida-dev/examples/grida_strokes.rs(1 hunks)crates/grida-dev/examples/grida_texts.rs(1 hunks)crates/grida-dev/examples/grida_vector.rs(1 hunks)crates/grida-dev/examples/grida_webfonts.rs(1 hunks)crates/grida-dev/examples/wd_windowed_mode.rs(3 hunks)editor/grida-canvas-react/viewport/surface.tsx(5 hunks)editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsx(1 hunks)editor/grida-canvas/editor.i.ts(1 hunks)editor/grida-canvas/editor.ts(1 hunks)editor/grida-canvas/reducers/methods/scale.ts(4 hunks)editor/grida-canvas/reducers/node-transform.reducer.ts(3 hunks)editor/grida-canvas/reducers/node.reducer.ts(1 hunks)editor/grida-canvas/reducers/tools/__tests__/snap-resize.test.ts(0 hunks)editor/grida-canvas/reducers/tools/snap-resize.ts(9 hunks)editor/package.json(0 hunks)editor/scaffolds/sidecontrol/controls/ext-align.tsx(10 hunks)editor/scaffolds/sidecontrol/controls/width-height.tsx(1 hunks)editor/scaffolds/sidecontrol/sidecontrol-node-selection.tsx(2 hunks)packages/grida-canvas-io-figma/lib.ts(4 hunks)packages/grida-canvas-io-figma/package.json(1 hunks)packages/grida-canvas-schema/grida.ts(10 hunks)packages/grida-cmath/__tests__/cmath.rational.test.ts(1 hunks)packages/grida-cmath/__tests__/cmath.test.ts(1 hunks)packages/grida-cmath/index.ts(2 hunks)supabase/drafts/20251214_grida_canvas_document_model.sql(1 hunks)
💤 Files with no reviewable changes (3)
- crates/csscascade/src/rcdom/mod.rs
- editor/grida-canvas/reducers/tools/tests/snap-resize.test.ts
- editor/package.json
🧰 Additional context used
📓 Path-based instructions (9)
crates/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
crates/**/*.rs: Use Rust 2024 edition for wasm builds and graphics core
Use Skia graphics backend for 2D graphics, bound with skia-safe
Rust crates in /crates directory are under rapid development and serve as the new rendering backend; ensure high quality implementations
Files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_images.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-dev/examples/grida_effects.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_container_stroke.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_vector.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_layout_flex.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-canvas/examples/golden_layout_flex_alignment.rscrates/grida-canvas/examples/golden_layout_padding.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-canvas/examples/golden_layout_flex_padding.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_nested.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-canvas/src/io/io_figma.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/svg/pack.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
crates/grida-canvas/**/*.rs
📄 CodeRabbit inference engine (crates/grida-canvas/AGENTS.md)
crates/grida-canvas/**/*.rs: All internal structs (NodeRecs, SceneGraph, caches) must useNodeId(u64) for high-performance counter-based IDs in the rendering engine
Public APIs must accept and returnUserNodeId(String) instead ofNodeIdfor stability and serialization
UseIdConverterto handle conversion betweenNodeIdandUserNodeIdduring .grida file loading
NodeRepository must auto-generate IDs for factory-created nodes, assigning ID=0 as the default
Useskia-safecrate for all painting and rendering operations
Usemath2crate for all geometry and common math operations
Files:
crates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-canvas/src/layout/engine.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-canvas/examples/golden_container_stroke.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_layout_flex.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-canvas/examples/golden_layout_flex_alignment.rscrates/grida-canvas/examples/golden_layout_padding.rscrates/grida-canvas/examples/golden_layout_flex_padding.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-canvas/src/io/io_figma.rscrates/grida-canvas/src/svg/pack.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rs
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use TypeScript 5 as the main language for most apps
Use Lucide or Radix Icons for icons
Files:
packages/grida-cmath/__tests__/cmath.test.tseditor/grida-canvas/reducers/node.reducer.tseditor/scaffolds/sidecontrol/controls/ext-align.tsxeditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas/reducers/methods/scale.tseditor/scaffolds/sidecontrol/controls/width-height.tsxeditor/grida-canvas/reducers/node-transform.reducer.tseditor/grida-canvas/editor.i.tseditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsxpackages/grida-cmath/__tests__/cmath.rational.test.tseditor/grida-canvas/editor.tspackages/grida-canvas-io-figma/lib.tspackages/grida-canvas-schema/grida.tspackages/grida-cmath/index.tseditor/grida-canvas-react/viewport/surface.tsxeditor/grida-canvas/reducers/tools/snap-resize.ts
{editor/**/*.{ts,tsx},packages/grida-canvas-*/**/*.{ts,tsx}}
📄 CodeRabbit inference engine (AGENTS.md)
Use DOM (plain DOM as canvas) for website builder canvas, bound with React
Files:
editor/grida-canvas/reducers/node.reducer.tseditor/scaffolds/sidecontrol/controls/ext-align.tsxeditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas/reducers/methods/scale.tseditor/scaffolds/sidecontrol/controls/width-height.tsxeditor/grida-canvas/reducers/node-transform.reducer.tseditor/grida-canvas/editor.i.tseditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsxeditor/grida-canvas/editor.tspackages/grida-canvas-io-figma/lib.tspackages/grida-canvas-schema/grida.tseditor/grida-canvas-react/viewport/surface.tsxeditor/grida-canvas/reducers/tools/snap-resize.ts
editor/grida-*/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use /editor/grida-* directories to isolate domain-specific modules; promote well-defined modules to /packages
Files:
editor/grida-canvas/reducers/node.reducer.tseditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas/reducers/methods/scale.tseditor/grida-canvas/reducers/node-transform.reducer.tseditor/grida-canvas/editor.i.tseditor/grida-canvas/editor.tseditor/grida-canvas-react/viewport/surface.tsxeditor/grida-canvas/reducers/tools/snap-resize.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use React.js 19 for web applications
Files:
editor/scaffolds/sidecontrol/controls/ext-align.tsxeditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/scaffolds/sidecontrol/controls/width-height.tsxeditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsxeditor/grida-canvas-react/viewport/surface.tsx
editor/scaffolds/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use /editor/scaffolds for feature-specific larger components, pages, and editors
Files:
editor/scaffolds/sidecontrol/controls/ext-align.tsxeditor/scaffolds/sidecontrol/controls/width-height.tsxeditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsx
supabase/**/*.sql
📄 CodeRabbit inference engine (AGENTS.md)
Database heavily relies on Supabase (PostgreSQL); use Supabase for database, auth, and storage
Files:
supabase/drafts/20251214_grida_canvas_document_model.sql
packages/grida-canvas-*/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
Files:
packages/grida-canvas-io-figma/lib.tspackages/grida-canvas-schema/grida.ts
🧠 Learnings (32)
📓 Common learnings
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to packages/grida-canvas-*/**/*.{ts,tsx,js,jsx} : Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : Use `math2` crate for all geometry and common math operations
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_images.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-dev/examples/grida_effects.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_container_stroke.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_vector.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_layout_flex.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-canvas/examples/golden_layout_flex_alignment.rscrates/grida-canvas/examples/golden_layout_padding.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-canvas/examples/golden_layout_flex_padding.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_nested.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-canvas/src/io/io_figma.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/svg/pack.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : Use `skia-safe` crate for all painting and rendering operations
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_images.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-dev/examples/grida_effects.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_container_stroke.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_vector.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_layout_flex.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-canvas/examples/golden_layout_flex_alignment.rscrates/grida-canvas/examples/golden_layout_padding.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-canvas/examples/golden_layout_flex_padding.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_nested.rscrates/grida-canvas/src/io/io_figma.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/svg/pack.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : Public APIs must accept and return `UserNodeId` (String) instead of `NodeId` for stability and serialization
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_images.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_vector.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_nested.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-canvas/src/io/io_figma.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/svg/pack.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : All internal structs (NodeRecs, SceneGraph, caches) must use `NodeId` (u64) for high-performance counter-based IDs in the rendering engine
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_images.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-dev/examples/grida_effects.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_container_stroke.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_vector.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/svg/pack.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:19.083Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-wasm/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:19.083Z
Learning: Applies to crates/grida-canvas-wasm/**/main.rs : Update `grida-canvas-wasm.d.ts` TypeScript definitions file when new APIs are introduced via `main.rs`
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rspackages/grida-canvas-io-figma/package.jsoncrates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rseditor/grida-canvas/reducers/node.reducer.tscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rssupabase/drafts/20251214_grida_canvas_document_model.sqlcrates/grida-dev/examples/grida_basic.rscrates/grida-canvas/src/shape/stroke_rect.rseditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxcrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-canvas/examples/golden_fe_noise.rscrates/grida-canvas/examples/golden_layout_flex.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rseditor/grida-canvas/editor.tspackages/grida-canvas-io-figma/lib.tscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_nested.rspackages/grida-canvas-schema/grida.tscrates/grida-canvas/src/io/io_grida.rspackages/grida-cmath/index.tscrates/grida-canvas/src/io/io_figma.rscrates/grida-dev/examples/grida_texts.rseditor/grida-canvas/reducers/tools/snap-resize.tscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : Use `IdConverter` to handle conversion between `NodeId` and `UserNodeId` during .grida file loading
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-canvas/examples/golden_vector_regions_fills.rscrates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_basic.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_image.rscrates/grida-dev/examples/grida_mask.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/ui_parser_test.rs : High-level UI API tests should use `parse_ui` and be organized in `ui_parser_test.rs`
Applied to files:
crates/grida-dev/examples/grida_container.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-dev/examples/grida_basic.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_mask.rscrates/grida-dev/examples/grida_texts.rscrates/grida-dev/examples/wd_windowed_mode.rscrates/grida-canvas/src/layout/into_taffy.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:28.164Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:28.164Z
Learning: Applies to crates/grida-canvas/**/*.rs : NodeRepository must auto-generate IDs for factory-created nodes, assigning ID=0 as the default
Applied to files:
crates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/src/node/factory.rscrates/grida-canvas/src/cache/geometry.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_basic.rscrates/grida-canvas/examples/golden_pdf.rscrates/grida-dev/examples/grida_shapes.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-canvas/src/io/io_grida.rscrates/grida-dev/examples/grida_texts.rscrates/grida-canvas/src/node/schema.rscrates/grida-dev/examples/grida_strokes.rs
📚 Learning: 2025-12-01T00:22:36.510Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-dev/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:36.510Z
Learning: The `cg` crate must remain platform-agnostic; all winit/glutin integration code must live in the `grida-dev` crate
Applied to files:
crates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-dev/examples/grida_paint.rscrates/grida-dev/examples/grida_lines.rscrates/grida-dev/examples/grida_mask.rs
📚 Learning: 2025-12-01T00:22:36.510Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-dev/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:36.510Z
Learning: Applies to crates/grida-dev/grida-dev/Cargo.toml : The `grida-dev` crate is marked `publish = false` and is intended solely for local development workflows and devtools
Applied to files:
crates/grida-dev/examples/grida_gradients.rscrates/grida-dev/examples/grida_booleans.rscrates/grida-dev/examples/grida_lines.rscrates/grida-dev/examples/grida_blendmode.rscrates/grida-dev/examples/grida_texts.rs
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : Use Canvas 2D API with path commands for rendering geometric shapes (circle, square, triangle, etc.)
Applied to files:
crates/grida-canvas/examples/golden_sk_paragraph_path_vector.rseditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas-react/viewport/surface.tsx
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/*.rs : Run all tests with: `cargo test`
Applied to files:
crates/grida-canvas/examples/golden_sk_paragraph_path_vector.rscrates/grida-canvas/examples/golden_svg.rscrates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-dev/examples/grida_shapes_ellipse.rscrates/grida-canvas/src/layout/engine.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_fills.rscrates/grida-dev/examples/grida_texts.rs
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to packages/grida-canvas-*/**/*.{ts,tsx,js,jsx} : Packages under /packages/grida-canvas-* power the canvas; some are published to npm, refer to individual package README
Applied to files:
packages/grida-canvas-io-figma/package.jsonsupabase/drafts/20251214_grida_canvas_document_model.sqlpackages/grida-canvas-schema/grida.tseditor/grida-canvas-react/viewport/surface.tsx
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to crates/**/*.rs : Use Skia graphics backend for 2D graphics, bound with skia-safe
Applied to files:
crates/grida-canvas/src/cache/geometry.rscrates/grida-canvas/examples/golden_sk_text_backdrop_blur_path.rscrates/grida-canvas/src/shape/stroke_rect.rscrates/grida-dev/examples/grida_lines.rscrates/grida-canvas/examples/golden_vector_regions_strokes.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/scenario_*.rs : Scenario-specific comprehensive tests should be organized in files matching `scenario_*.rs`
Applied to files:
crates/grida-canvas/tests/geometry_cache.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/tests/hit_test.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/serde_test.rs : Run tests with serde feature using: `cargo test --features serde`
Applied to files:
crates/grida-canvas/tests/geometry_cache.rscrates/grida-dev/examples/grida_webfonts.rscrates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/tests/hit_test.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/serde_test.rs : JSON serialization tests should be organized in `serde_test.rs`
Applied to files:
crates/grida-canvas/tests/geometry_cache.rs
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : When adding new shape types, update the Shape type union, add cases in drawShape() function, add cases in shapeToSVG() function, and add SelectItem in UI
Applied to files:
editor/scaffolds/sidecontrol/controls/ext-align.tsxeditor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas-react/viewport/surface.tsx
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/Cargo.toml : Use `ttf-parser = "0.25"` as the required dependency for font parsing backend
Applied to files:
crates/grida-dev/examples/grida_webfonts.rscrates/grida-canvas/src/layout/into_taffy.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/Cargo.toml : Include optional `serde = "1.0"` with `derive` feature for JSON serialization support
Applied to files:
crates/grida-dev/examples/grida_webfonts.rscrates/grida-canvas/src/io/io_grida.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/italic_level1.rs : Core font selection and italic detection tests should be organized in `italic_level1.rs`
Applied to files:
crates/grida-dev/examples/grida_webfonts.rs
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to crates/**/*.rs : Use Rust 2024 edition for wasm builds and graphics core
Applied to files:
crates/grida-canvas/src/shape/stroke_rect.rs
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : For SVG export, convert circles to <circle> elements, rectangles to <rect> elements, and polygons to <polygon> elements with calculated points
Applied to files:
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsx
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : Use React hooks for state management (imageSrc, shape, grid, maxRadius, gamma, jitter, opacity, color, customShapeImage, imageDataRef, sizeRef)
Applied to files:
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsxeditor/grida-canvas-react/viewport/surface.tsx
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to {editor/**/*.{ts,tsx},packages/grida-canvas-*/**/*.{ts,tsx}} : Use DOM (plain DOM as canvas) for website builder canvas, bound with React
Applied to files:
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/grida-canvas-react/viewport/surface.tsx
📚 Learning: 2025-12-01T00:22:56.899Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: editor/app/(tools)/tools/halftone/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:56.899Z
Learning: Applies to editor/app/(tools)/tools/halftone/app/(tools)/tools/halftone/_page.tsx : When adding new parameters to the halftone tool, add state with useState, include in useEffect dependency array, pass to renderHalftone() function, use in rendering logic, and add UI control
Applied to files:
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsxeditor/scaffolds/sidecontrol/sidecontrol-node-selection.tsx
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/scenario_level2_*.rs : Level 2+ placeholder and limitation tests should be organized in files matching `scenario_level2_*.rs`
Applied to files:
crates/grida-canvas/tests/scene_cache.rscrates/grida-canvas/tests/hit_test.rscrates/grida-dev/examples/grida_fills.rs
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to **/components/ui/**/*.{ts,tsx} : Use Shadcn UI for UI component library
Applied to files:
editor/scaffolds/sidecontrol/sidecontrol-node-selection.tsx
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to editor/components/ui/**/*.{ts,tsx} : Use /editor/components/ui for shadcn UI components
Applied to files:
editor/scaffolds/sidecontrol/sidecontrol-node-selection.tsx
📚 Learning: 2025-12-14T23:30:42.112Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-14T23:30:42.112Z
Learning: Applies to crates/**/*.rs : Rust crates in /crates directory are under rapid development and serve as the new rendering backend; ensure high quality implementations
Applied to files:
crates/grida-canvas/examples/golden_pdf.rs
📚 Learning: 2025-12-01T00:22:06.800Z
Learnt from: CR
Repo: gridaco/grida PR: 0
File: crates/grida-canvas-fonts/AGENTS.md:0-0
Timestamp: 2025-12-01T00:22:06.800Z
Learning: Applies to crates/grida-canvas-fonts/**/Cargo.toml : Include dev-dependency `serde_json = "1.0"` for JSON testing
Applied to files:
crates/grida-canvas/src/io/io_grida.rs
🧬 Code graph analysis (21)
crates/grida-dev/examples/grida_container.rs (1)
editor/grida-canvas-react-renderer-dom/nodes/index.ts (1)
container(18-18)
crates/grida-canvas/examples/golden_vector_regions_fills.rs (1)
crates/grida-canvas/src/cg/color.rs (1)
from_rgba(44-46)
crates/grida-canvas/src/node/factory.rs (1)
crates/grida-canvas/src/node/schema.rs (6)
default(130-138)default(156-164)default(540-542)default(654-664)default(803-805)default(820-830)
crates/grida-canvas/src/shape/stroke_rect.rs (1)
.ref/canvaskit/canvaskit.d.ts (3)
PathEffect(3119-3119)PathOp(5010-5010)RRect(4806-4806)
editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsx (1)
packages/grida-cmath/index.ts (1)
CardinalDirection(219-227)
editor/grida-canvas/reducers/methods/scale.ts (1)
editor/grida-canvas/reducers/node-transform.reducer.ts (1)
updateNodeTransform(77-230)
editor/scaffolds/sidecontrol/controls/width-height.tsx (3)
packages/grida-canvas-schema/grida.ts (1)
LengthPercentage(1004-1004)editor/scaffolds/sidecontrol/ui/index.tsx (1)
PropertyLineLabel(43-59)editor/scaffolds/sidecontrol/controls/length-percentage.tsx (1)
LengthPercentageControl(27-81)
editor/grida-canvas/reducers/node-transform.reducer.ts (1)
editor/grida-canvas/editor.ts (1)
scale(139-184)
crates/grida-canvas/examples/golden_vector_regions_strokes.rs (1)
crates/grida-canvas/src/cg/color.rs (1)
from_rgba(44-46)
crates/grida-canvas/examples/golden_fe_noise.rs (1)
crates/grida-canvas/src/cg/color.rs (1)
from_rgba(44-46)
editor/grida-canvas/editor.i.ts (1)
packages/grida-canvas-schema/grida.ts (1)
NodeID(1101-1101)
crates/grida-canvas/examples/golden_layout_flex.rs (1)
crates/grida-canvas/src/node/schema.rs (6)
default(130-138)default(156-164)default(540-542)default(654-664)default(803-805)default(820-830)
crates/grida-canvas/examples/golden_layout_flex_alignment.rs (1)
crates/grida-canvas/src/node/schema.rs (6)
default(130-138)default(156-164)default(540-542)default(654-664)default(803-805)default(820-830)
crates/grida-canvas/examples/golden_layout_padding.rs (1)
crates/grida-canvas/src/node/schema.rs (6)
default(130-138)default(156-164)default(540-542)default(654-664)default(803-805)default(820-830)
crates/grida-canvas/examples/golden_layout_flex_padding.rs (1)
crates/grida-canvas/src/node/schema.rs (6)
default(130-138)default(156-164)default(540-542)default(654-664)default(803-805)default(820-830)
editor/grida-canvas/editor.ts (2)
crates/grida-canvas/src/node/schema.rs (9)
rect(941-941)rect(1003-1010)rect(1183-1190)rect(1340-1347)rect(1472-1479)rect(1680-1697)rect(1760-1762)rect(1874-1881)rect(1997-2004)editor/grida-canvas/backends/dom.ts (1)
rect(45-47)
editor/grida-canvas-react/viewport/surface.tsx (4)
editor/grida-canvas-react/viewport/surface-hooks.ts (1)
useSingleSelection(295-412)editor/grida-canvas-react/provider.tsx (1)
useGestureState(614-632)editor/grida-canvas-react/use-editor.tsx (1)
useEditorState(108-120)editor/grida-canvas-react/viewport/ui/aspect-ratio-guide.tsx (1)
AspectRatioGuide(67-105)
editor/grida-canvas/reducers/tools/snap-resize.ts (2)
crates/math2/src/rect.rs (1)
aspect_ratio(575-577)editor/app/(dev)/canvas/experimental/grid/core/state.ts (1)
initial(6-9)
crates/grida-canvas/src/svg/pack.rs (1)
crates/grida-canvas/examples/golden_container_stroke.rs (1)
scene(9-45)
crates/grida-canvas/src/layout/into_taffy.rs (2)
crates/grida-canvas/src/node/schema.rs (1)
layout(1071-1077)crates/grida-canvas/src/io/io_css.rs (1)
length(76-81)
crates/grida-canvas/src/node/schema.rs (2)
packages/grida-canvas-cg/lib.ts (3)
Axis(561-561)MainAxisAlignment(568-575)CrossAxisAlignment(582-582)crates/grida-canvas/src/cg/types.rs (12)
default(44-46)default(82-84)default(104-106)default(236-238)default(300-302)default(314-316)default(409-411)default(516-518)default(591-593)default(617-619)default(633-635)default(663-665)
Summary by CodeRabbit
New Features
Bug Fixes & Improvements
Style
✏️ Tip: You can customize this high-level summary in your review settings.