feat: edit view properties (title, description, tags)#2976
Conversation
…ndler Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…g handling Rename `operators` to `ops`, `print` to `printOperation`, `printTabIndent` to `printWithTabIndent` for clarity. Clean up viewChange handler: remove dead code, make handlers synchronous, fix tag collection ordering, support array-form tag add/remove, and add comprehensive tag tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 30945a7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 22 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds change-property to ViewChange and implements CST-aware title/description/tag edits in the language server; refactors the diagram editor into typed XState actors with a sync queue; replaces react-shadow with a native ShadowRoot and updates overlays/search; renames generator printing APIs; upgrades pnpm/workspace and various build/tooling and tests. ChangesDiagram runtime, editor actors, overlays, and shadow DOM
Language server: change-property and tests
Generators API rename and tests
Workspace, tooling, e2e, SPA, and misc manifests
Estimated code review effort Possibly related PRs
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/generators/src/likec4/generate-likec4.ts (1)
26-37:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate JSDoc examples to the renamed API (
ops) and instantiated operations.Examples still use
operators.*, and one example passes an operator reference instead of an instantiated operation, which no longer matches the new public API.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/generators/src/likec4/generate-likec4.ts` around lines 26 - 37, Update the JSDoc examples to use the renamed public API 'ops' instead of 'operators' and pass instantiated operations (call the operation factory) rather than operator references; for example replace uses of operators.expression and operators.model() with ops.expression() and ops.model() respectively, and adjust the example that passed a ref to ensure it calls the operation factory so printOperation receives an instantiated operation (refer to printOperation and ops.* symbols in the diff).packages/language-server/src/filesystem/LikeC4FileSystem.ts (1)
26-31:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRefine:
WithFileSystem()default affects only direct no-arg usage; runtime watcher enablement is already explicitFile: packages/language-server/src/filesystem/LikeC4FileSystem.ts (Lines 26-31)
The current default (
enableWatcher = false) only impacts callsites that invokeWithFileSystem()with no arguments. In this repo, production code paths pass an explicit boolean (e.g.,startLanguageServerdefaultsenableWatchertotrueand callsWithFileSystem(opts.enableWatcher)), and the onlyWithFileSystem()no-arg call found is inpackages/language-server/src/model-change/viewChange.spec.ts(tests). SinceWithFileSystemis exported publicly, changing the default would still break external consumers who call it directly with no args—update docs/semantics accordingly.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/language-server/src/filesystem/LikeC4FileSystem.ts` around lines 26 - 31, Summary: WithFileSystem's default parameter (enableWatcher = false) only affects callers who omit the arg (tests), but runtime callers already pass an explicit boolean; exported API should not silently default and must be clarified. Fix: remove the default value from the WithFileSystem signature so callers must supply enableWatcher explicitly (change "WithFileSystem(enableWatcher = false)" to "WithFileSystem(enableWatcher: boolean)"), update the test(s) that call WithFileSystem() no-arg (e.g., viewChange.spec.ts) to pass an explicit boolean, and add a short JSDoc above WithFileSystem explaining that watcher behavior is controlled by the enableWatcher argument; reference the startLanguageServer callsite which already passes opts.enableWatcher to verify callers are explicit.
🧹 Nitpick comments (7)
packages/core/src/types/view-changes.ts (1)
37-54: ⚡ Quick winRequire at least one property in
change-propertypayload.
ChangePropertycurrently permits{ op: 'change-property' }, which creates a valid but meaningless operation. Tightening this contract prevents silent no-ops in downstream handlers.Suggested type-shape tightening
export namespace ViewChange { + type AtLeastOne<T> = { + [K in keyof T]-?: Required<Pick<T, K>> & Partial<Omit<T, K>> + }[keyof T] + - export interface ChangeProperty { - op: 'change-property' - /** - * Change title - */ - title?: string - /** - * Change description - */ - description?: scalar.MarkdownOrString - /** - * Add or remove tags - */ - tag?: { - add?: scalar.Tag | scalar.Tag[] - remove?: scalar.Tag | scalar.Tag[] - } - } + export type ChangeProperty = { + op: 'change-property' + } & AtLeastOne<{ + /** Change title */ + title: string + /** Change description */ + description: scalar.MarkdownOrString + /** Add or remove tags */ + tag: { + add?: scalar.Tag | scalar.Tag[] + remove?: scalar.Tag | scalar.Tag[] + } + }> }Also applies to: 57-62
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/types/view-changes.ts` around lines 37 - 54, The ChangeProperty interface allows an empty payload ({ op: 'change-property' }), so tighten the type to require at least one of title, description, or tag be present: replace the current optional-all interface with a discriminated union or intersection that enforces at least one of { title }, { description }, or { tag } (referencing ChangeProperty and the tag shape inside it) so consumers cannot dispatch a no-op; apply the same non-empty requirement to the analogous interface declared at the other location referenced (lines ~57-62).packages/diagram/src/editor/actor/state.sync-queue.ts (2)
270-283: ⚡ Quick winRemove commented-out code.
This substantial commented block appears to be unused exploration code. Consider removing it to improve readability, or if it represents planned functionality, track it in an issue instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/diagram/src/editor/actor/state.sync-queue.ts` around lines 270 - 283, Remove the large commented-out exploratory block that tries to find a 'save-view-snapshot' (the commented calls to find([...context.processing, ...context.syncQueue], p => !!p && isViewChange(p) && p.op === 'save-view-snapshot') and the subsequent enqueue.sendTo(typedSystem.diagramActor, { type: 'update.view-bounds', bounds: snapshot.layout.bounds }) code); either delete it entirely from state.sync-queue.ts to improve readability or move the logic into a tracked issue if it represents planned work, leaving no commented implementation in the file.
185-191: ⚡ Quick winUse optional chaining for cleaner conditional.
The condition
current && current._layout === 'manual'can be simplified with optional chaining.♻️ Proposed fix
input: ({ context }) => { const current = context.history?.head.change.layout return ({ - current: current && current._layout === 'manual' ? current : undefined, + current: current?._layout === 'manual' ? current : undefined, viewId: context.viewId, }) },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/diagram/src/editor/actor/state.sync-queue.ts` around lines 185 - 191, The conditional `current && current._layout === 'manual'` should use optional chaining for clarity; in the input arrow function (the input: ({ context }) => { ... } block in state.sync-queue.ts) replace that expression with `current?._layout === 'manual'` so the returned object sets current to current when its _layout equals 'manual', otherwise undefined, leaving viewId unchanged.packages/diagram/src/editor/actor/actions.ts (1)
83-99: 💤 Low valueInconsistent action definition pattern.
pushHistorywrapsmachine.assignin an extra function, unlikesaveBeforeEditing(line 67) which directly assigns. This creates an unnecessary closure and diverges from the pattern used elsewhere in this file.♻️ Proposed fix for consistency
-export const pushHistory = () => - machine.assign(({ context }) => { +export const pushHistory = machine.assign(({ context }) => { const editing = context.editing if (import.meta.env.DEV) { console.log('pushHistory', editing) } if (editing) { return { editing: null, history: { head: editing.before, tail: context.history, }, } } return {} })Then update the call site in
state.editor.tsfrompushHistory()topushHistory.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/diagram/src/editor/actor/actions.ts` around lines 83 - 99, pushHistory currently returns a function that calls machine.assign, creating an unnecessary closure and breaking the file's consistent action pattern (see saveBeforeEditing which directly assigns). Change pushHistory to be the direct result of machine.assign (i.e., export const pushHistory = machine.assign(...)) and update the call site in state.editor.ts to use pushHistory (no parentheses) so the action is referenced consistently with other actions like saveBeforeEditing.packages/diagram/src/editor/actor/setup.ts (1)
2-8: 💤 Low valueConsider consolidating imports from the same module.
Multiple separate import statements from
./typescould be combined into a single statement.♻️ Proposed consolidation
-import { hotkey } from './hotkey' -import type { EditorActorEvent } from './types' -import type { EditorActorContext } from './types' -import type { EditorActorEmitedEvent } from './types' -import type { EditorActorInput } from './types' -import type { EditorActorStateTag } from './types' +import { hotkey } from './hotkey' +import type { + EditorActorContext, + EditorActorEmitedEvent, + EditorActorEvent, + EditorActorInput, + EditorActorStateTag, +} from './types'🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/diagram/src/editor/actor/setup.ts` around lines 2 - 8, Multiple type imports (EditorActorEvent, EditorActorContext, EditorActorEmitedEvent, EditorActorInput, EditorActorStateTag) are imported separately from the same module; consolidate them into a single import statement that imports all these types together (keep the other import from 'xstate' as-is), updating the existing import lines in setup.ts to use one combined import for the listed EditorActor* types.packages/diagram/src/search/Search.tsx (1)
130-139: 💤 Low valueMark props as read-only for type safety.
Per static analysis, the props type should be marked as read-only to prevent accidental mutation.
🔧 Proposed fix
-function SearchOverlayBody({ searchActorRef }: { searchActorRef: SearchActorRef }) { +function SearchOverlayBody({ searchActorRef }: Readonly<{ searchActorRef: SearchActorRef }>) {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/diagram/src/search/Search.tsx` around lines 130 - 139, The props for SearchOverlayBody should be marked readonly to prevent mutation; update the function signature for SearchOverlayBody so the parameter type uses a readonly prop type (e.g., wrap the inline props type in Readonly<...> or declare a Readonly interface) for the searchActorRef prop, ensuring the type references SearchActorRef and that the JSX usage of SearchPanelContent and ref remain unchanged.packages/language-server/src/model-change/viewChange.spec.ts (1)
67-614: ⚡ Quick winAdd one idempotent/no-op
change-propertyregression test.Current coverage is great for mutating edits, but it should also assert behavior when the requested property change produces no text edit (e.g., same title/description or removing a non-existing tag).
As per coding guidelines, “Aim to cover new features with relevant tests; keep test names descriptive.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/language-server/src/model-change/viewChange.spec.ts` around lines 67 - 614, Add a new test under the existing "change-property" describe that verifies idempotent/no-op edits: use testDoc to create a fixture, capture the initial read(), then call change(...) (the change helper) with a no-op change-property (e.g., setting title to the same value and/or removing a tag that isn't present) and assert that read() is strictly unchanged and that no text edits occurred; name the test something like "should be idempotent for no-op changes" and place it alongside the other it(...) cases in the viewChange spec.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/generators-api-rename.md:
- Around line 2-9: The changeset currently declares a patch release but lists
breaking public API renames (operators → ops, print → printOperation,
printTabIndent → printWithTabIndent) which require a non-patch bump; update the
release type from "patch" to at least "minor" (or "major" per your policy) in
the changeset so the package '`@likec4/generators`' is published with the
appropriate breaking-release level for the renamed symbols.
In `@packages/diagram/src/editor/actor/actions.ts`:
- Around line 154-161: The length check uses loose equality; update the
condition in the block that checks syncQueue.length (the if that currently reads
"if (syncQueue.length == 0)") to use strict equality (`===`) so it becomes "if
(syncQueue.length === 0)"; ensure the surrounding logic that returns {
syncQueue: [nextOp] } and the dev console.log remain unchanged and still
reference nextOp.
In `@packages/diagram/src/overlays/overlay/Overlay.tsx`:
- Around line 166-171: The backdrop click detection in the onClick handler of
Overlay.tsx currently uses a cast ((e.target as any)?.nodeName) — remove the
cast and replace the logic with a proper event target check (use e.target ===
e.currentTarget) so clicks on the dialog backdrop trigger cancelMe() while
clicks on content do not; update the onClick closure where cancelMe() is invoked
to use this comparison instead of nodeName inspection.
In `@packages/language-server/src/model-change/ModelChanges.ts`:
- Around line 24-44: The code currently calls changePropertyHandler and applies
its edits unconditionally; gate that call with a check that change.op ===
'change-property' (using the destructured change from changeView) so only
property-change operations run changePropertyHandler and applyTextEdits; if
change.op !== 'change-property' skip the handler and keep the invariant check
moved/adjusted so invariant(change.op !== 'change-property', ...) only runs when
you expect the operation to have been handled earlier (or remove the invariant
and instead early-return/continue for non-property ops). Ensure you reference
changePropertyHandler, change.op, preparePayload, applyTextEdits and invariant
in the updated control flow.
In `@packages/language-server/src/model-change/viewChange.ts`:
- Line 10: Remove the unused import named "space" from the import list in
viewChange.ts to satisfy linting; locate the import statement that includes
"space" (e.g., the import that currently lists "space,") and delete "space" from
that list (or remove the entire import line if it becomes empty) so no unused
symbol remains.
- Around line 259-267: The current handling of tag.add/tag.remove silently uses
only the first array element, causing dropped values; update the logic in
viewChange (around the code that calls addTag(viewAst, body, name) and
removeTag(body, name)) to explicitly handle arrays by iterating over tag.add and
tag.remove when Array.isArray(...) and invoking addTag/removeTag for each item
(or, if you prefer stricter behavior, validate and throw a descriptive error
when arrays are passed), ensuring every value is processed rather than only the
first.
In `@packages/likec4-spa/README.md`:
- Line 27: Update the README sentence that currently reads "To test webcomponent
(that one is generated from `likec4 gen`)" to use the two-word term "web
component" instead of "webcomponent" so the user-facing line becomes "To test
web component (that one is generated from `likec4 gen`)" — edit the README.md
content where that sentence appears.
---
Outside diff comments:
In `@packages/generators/src/likec4/generate-likec4.ts`:
- Around line 26-37: Update the JSDoc examples to use the renamed public API
'ops' instead of 'operators' and pass instantiated operations (call the
operation factory) rather than operator references; for example replace uses of
operators.expression and operators.model() with ops.expression() and ops.model()
respectively, and adjust the example that passed a ref to ensure it calls the
operation factory so printOperation receives an instantiated operation (refer to
printOperation and ops.* symbols in the diff).
In `@packages/language-server/src/filesystem/LikeC4FileSystem.ts`:
- Around line 26-31: Summary: WithFileSystem's default parameter (enableWatcher
= false) only affects callers who omit the arg (tests), but runtime callers
already pass an explicit boolean; exported API should not silently default and
must be clarified. Fix: remove the default value from the WithFileSystem
signature so callers must supply enableWatcher explicitly (change
"WithFileSystem(enableWatcher = false)" to "WithFileSystem(enableWatcher:
boolean)"), update the test(s) that call WithFileSystem() no-arg (e.g.,
viewChange.spec.ts) to pass an explicit boolean, and add a short JSDoc above
WithFileSystem explaining that watcher behavior is controlled by the
enableWatcher argument; reference the startLanguageServer callsite which already
passes opts.enableWatcher to verify callers are explicit.
---
Nitpick comments:
In `@packages/core/src/types/view-changes.ts`:
- Around line 37-54: The ChangeProperty interface allows an empty payload ({ op:
'change-property' }), so tighten the type to require at least one of title,
description, or tag be present: replace the current optional-all interface with
a discriminated union or intersection that enforces at least one of { title }, {
description }, or { tag } (referencing ChangeProperty and the tag shape inside
it) so consumers cannot dispatch a no-op; apply the same non-empty requirement
to the analogous interface declared at the other location referenced (lines
~57-62).
In `@packages/diagram/src/editor/actor/actions.ts`:
- Around line 83-99: pushHistory currently returns a function that calls
machine.assign, creating an unnecessary closure and breaking the file's
consistent action pattern (see saveBeforeEditing which directly assigns). Change
pushHistory to be the direct result of machine.assign (i.e., export const
pushHistory = machine.assign(...)) and update the call site in state.editor.ts
to use pushHistory (no parentheses) so the action is referenced consistently
with other actions like saveBeforeEditing.
In `@packages/diagram/src/editor/actor/setup.ts`:
- Around line 2-8: Multiple type imports (EditorActorEvent, EditorActorContext,
EditorActorEmitedEvent, EditorActorInput, EditorActorStateTag) are imported
separately from the same module; consolidate them into a single import statement
that imports all these types together (keep the other import from 'xstate'
as-is), updating the existing import lines in setup.ts to use one combined
import for the listed EditorActor* types.
In `@packages/diagram/src/editor/actor/state.sync-queue.ts`:
- Around line 270-283: Remove the large commented-out exploratory block that
tries to find a 'save-view-snapshot' (the commented calls to
find([...context.processing, ...context.syncQueue], p => !!p && isViewChange(p)
&& p.op === 'save-view-snapshot') and the subsequent
enqueue.sendTo(typedSystem.diagramActor, { type: 'update.view-bounds', bounds:
snapshot.layout.bounds }) code); either delete it entirely from
state.sync-queue.ts to improve readability or move the logic into a tracked
issue if it represents planned work, leaving no commented implementation in the
file.
- Around line 185-191: The conditional `current && current._layout === 'manual'`
should use optional chaining for clarity; in the input arrow function (the
input: ({ context }) => { ... } block in state.sync-queue.ts) replace that
expression with `current?._layout === 'manual'` so the returned object sets
current to current when its _layout equals 'manual', otherwise undefined,
leaving viewId unchanged.
In `@packages/diagram/src/search/Search.tsx`:
- Around line 130-139: The props for SearchOverlayBody should be marked readonly
to prevent mutation; update the function signature for SearchOverlayBody so the
parameter type uses a readonly prop type (e.g., wrap the inline props type in
Readonly<...> or declare a Readonly interface) for the searchActorRef prop,
ensuring the type references SearchActorRef and that the JSX usage of
SearchPanelContent and ref remain unchanged.
In `@packages/language-server/src/model-change/viewChange.spec.ts`:
- Around line 67-614: Add a new test under the existing "change-property"
describe that verifies idempotent/no-op edits: use testDoc to create a fixture,
capture the initial read(), then call change(...) (the change helper) with a
no-op change-property (e.g., setting title to the same value and/or removing a
tag that isn't present) and assert that read() is strictly unchanged and that no
text edits occurred; name the test something like "should be idempotent for
no-op changes" and place it alongside the other it(...) cases in the viewChange
spec.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 70a205a4-5eac-4d60-879c-4a42108bab1b
⛔ Files ignored due to path filters (18)
e2e/tests/__screenshots__/chromium-darwin/e2e-amazon-lambdas.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-amazon-rds.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-amazon-sqs.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-amazon.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-backend.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-cloud-legacy-backend.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-cloud-legacy.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-cloud-next.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-cloud-to-amazon-sequence.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-cloud.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-deploy-1.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-dynamic-view-1.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-graphql.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-index.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-multiple-expanded.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-multiple-explicit.pngis excluded by!**/*.pnge2e/tests/__screenshots__/chromium-darwin/e2e-multiple-merged.pngis excluded by!**/*.pngpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (92)
.changeset/fix-overlay-animations.md.changeset/generators-api-rename.md.changeset/react-shadow-removed.md.changeset/upgrade-pnpm-11.md.tool-versionsdevops/package.jsone2e/bootstrap.mjse2e/package.jsone2e/playwright.config.tse2e/pnpm-workspace.yamlpackage.jsonpackages/core/src/types/view-changes.tspackages/core/src/utils/mnemonist.tspackages/core/src/utils/set.tspackages/diagram/package.jsonpackages/diagram/src/LikeC4View.tsxpackages/diagram/src/adhoc-editor/ElementsTree.tsxpackages/diagram/src/custom/index.tspackages/diagram/src/editor/actor/actions.tspackages/diagram/src/editor/actor/hotkey.tspackages/diagram/src/editor/actor/machine.tspackages/diagram/src/editor/actor/setup.tspackages/diagram/src/editor/actor/state.editor.tspackages/diagram/src/editor/actor/state.sync-queue.tspackages/diagram/src/editor/actor/types.tspackages/diagram/src/editor/editorActor.actions.tspackages/diagram/src/editor/editorActor.states.tspackages/diagram/src/editor/index.tspackages/diagram/src/editor/useEditorActorLogic.tspackages/diagram/src/hooks/useDiagramCompareLayout.tspackages/diagram/src/hooks/useEditorActor.tspackages/diagram/src/hooks/useLikeC4ElementsTree.tspackages/diagram/src/likec4diagram/DiagramUI.tsxpackages/diagram/src/likec4diagram/DiagramXYFlow.tsxpackages/diagram/src/likec4diagram/state/DiagramActorProvider.tsxpackages/diagram/src/likec4diagram/state/diagram-api.tspackages/diagram/src/likec4diagram/state/machine.actions.tspackages/diagram/src/likec4diagram/state/machine.setup.tspackages/diagram/src/likec4diagram/state/machine.state.ready.tspackages/diagram/src/likec4diagram/state/machine.tspackages/diagram/src/likec4diagram/state/types.tspackages/diagram/src/likec4diagram/state/utils.tspackages/diagram/src/navigationpanel/editorpanel/ApplySemanticLayout.tsxpackages/diagram/src/overlays/overlay/Overlay.tsxpackages/diagram/src/overlays/overlaysActor.tspackages/diagram/src/overlays/relationships-browser/SelectElement.tsxpackages/diagram/src/search/Search.tsxpackages/diagram/src/search/components/ElementsColumn.tsxpackages/diagram/src/search/searchActor.tspackages/diagram/src/shadowroot/ShadowRoot.tsxpackages/diagram/src/shadowroot/styles.css.tspackages/generators/src/likec4/generate-likec4.spec.tspackages/generators/src/likec4/generate-likec4.tspackages/generators/src/likec4/index.tspackages/language-server/package.jsonpackages/language-server/src/__mocks__/fs.cjspackages/language-server/src/__mocks__/fs/promises.cjspackages/language-server/src/filesystem/LikeC4FileSystem.tspackages/language-server/src/model-change/ModelChanges.tspackages/language-server/src/model-change/viewChange.spec.tspackages/language-server/src/model-change/viewChange.tspackages/language-server/src/test/testServices.tspackages/language-server/src/validation/specification.spec.tspackages/language-server/tsconfig.jsonpackages/language-server/vitest.config.tspackages/likec4-spa/README.mdpackages/likec4-spa/codegen/react.htmlpackages/likec4-spa/codegen/webcomponent.htmlpackages/likec4-spa/codegen/webcomponent.tsxpackages/likec4-spa/package.jsonpackages/likec4-spa/panda.config.tspackages/likec4-spa/src/page-title.spec.tspackages/likec4-spa/start-dev.tspackages/likec4-spa/tsconfig.src.jsonpackages/likec4-spa/tsdown.config.mtspackages/likec4/package.jsonpackages/log/package.jsonpackages/lsp/package.jsonpackages/mcp/package.jsonpackages/react/package.jsonpackages/react/panda.config.mjspackages/react/src/react-dom-server-mock.tspackages/react/tsconfig.jsonpackages/react/vite.config.mjspackages/vite-plugin/package.jsonpackages/vite-plugin/src/plugin.tspackages/vscode/package.jsonpackages/vscode/tsdown.config.tspatches/mnemonist@0.40.3.patchpnpm-workspace.yamlstyled-system/styles/panda.config.tsvitest.config.ts
💤 Files with no reviewable changes (7)
- packages/diagram/src/custom/index.ts
- packages/react/src/react-dom-server-mock.ts
- packages/diagram/src/likec4diagram/state/DiagramActorProvider.tsx
- packages/diagram/src/editor/editorActor.actions.ts
- patches/mnemonist@0.40.3.patch
- packages/language-server/vitest.config.ts
- packages/diagram/src/editor/editorActor.states.ts
- ModelChanges: gate change-property handler behind matching op - viewChange: handle tag.add/tag.remove arrays fully instead of dropping all but the first entry; drop unused space import - viewChange.spec: drop unused afterAll import and fs destructure - Overlay: use e.target === e.currentTarget for backdrop click (removes `as any`) - editor/actions: use strict equality on syncQueue.length - editor/setup: consolidate type imports from ./types - editor/state.sync-queue: drop dead commented block; use optional chaining - generators: update JSDoc examples to renamed ops API - likec4-spa README: "webcomponent" -> "web component"
Adds three tests for the change-property handler: - add multiple tags from an array - remove multiple tags from an array - add and remove tags in the same change
Summary
change-propertyview-change op in@likec4/corefor editing viewtitle,description, andtag(add/remove); applied as text edits by@likec4/language-serverwith formatting preservedactor/{machine,setup,actions,state.editor,state.sync-queue,types}.ts)@likec4/generators: renameoperators→ops,print→printOperation,printTabIndent→printWithTabIndent@likec4/react: dropreact-shadow, markuse-sync-external-storeexternal, inline shadow-root styles@likec4/diagram: fix overlay animationspackageManager,.tool-versions); move overrides /allowBuilds/patchedDependenciesintopnpm-workspace.yamlTest plan
pnpm generate && pnpm typecheckpnpm test(language-serverviewChangesuite green).c4sourcereact-shadowremoval🤖 Generated with Claude Code