Skip to content

release: v19.0.0 — control schemes, connection flows, accessibility, unified connector#314

Merged
siarheihuzarevich merged 27 commits into
mainfrom
feature/shuzarevich/v19.0.0
Jul 5, 2026
Merged

release: v19.0.0 — control schemes, connection flows, accessibility, unified connector#314
siarheihuzarevich merged 27 commits into
mainfrom
feature/shuzarevich/v19.0.0

Conversation

@siarheihuzarevich

Copy link
Copy Markdown
Member

v19.0.0 — one story: who decides how the editor is driven

Until v19 there was exactly one way to drive a Foblex Flow editor: one gesture mapping, one way to create connections, one input device. This release opens all of it up — the pointer scheme, the connection gesture, the keyboard, and the AI agent writing code against the library are now first-class ways to drive the editor.

Features

  • Control SchemesprovideFFlow(withControlScheme(...)): the complete gesture-to-action mapping as one object driving fDraggable, fZoom and f-selection-area together. Presets: default, Miro-like (F_SCROLL_PAN_CONTROL_SCHEME), draw.io-like (F_DRAG_SELECT_CONTROL_SCHEME); runtime switching via FControlSchemeController; explicit trigger inputs still win. Closes [Feature]: fScrollPan and fPinchStep inputs for better trackpad support #312, enables [Feature]: enable mouse wheel scrolling #218.
  • Connection FlowswithConnectionFlow('click') adds click-to-connect alongside drag (closes discussion Start connection with a single click #264). Both gestures drive the new gesture-independent FCreateConnectionSession (preview, snapping, marking, target resolution, fCreateConnection emission); a custom Type<IFConnectionFlow> gets all of it for free.
  • Accessibility — ARIA semantics in every flow by default (roles, generated connection names that track endpoints, live-region announcements, aria-hidden helpers; consumer attributes are never overridden). The keyboard layer is opt-in via withA11y(): DOM focus stays on the host (aria-activedescendant), arrows drive the selection spatially over nodes and connections, Ctrl+arrow walks the topology, Space moves the selection (hold-and-release or tap-to-grab), C creates connections through the shared session, Delete emits the new fDeleteSelected, keys are remappable (IFA11yKeys), every string localizable (IFA11yMessages).
  • Unified Connector Model — one [fConnector] directive (fConnectorType: source | target | source-target | outlet) replaces the fNodeInput/fNodeOutput/fNodeOutlet trio; connections gain canonical fSourceId/fTargetId. Legacy directives and ids keep working, deprecated.
  • AI-Ready Toolchain — dev diagnostics FF1001FF1009 with documented causes at /docs/errors (stripped from prod builds); ng add writes a managed AGENTS.md block pointing agents at the version-matched AI.md inside the npm package; llms.txt/llms-full.txt validated in CI.

Fixes

⚠ Breaking changes

  • Every flow applies inert ARIA attributes by default (host role only with the keyboard layer on; items get role, aria-roledescription, generated ids/labels — consumer-set attributes always win). Behavior changes only after opting into withA11y().
  • FDraggableBase gains two abstract members (fDeleteSelected, fCreateConnectionTrigger) — affects direct subclasses only.
  • Migration notes for the connector model are in the changelog (fConnectorMultiple defaults to true; connector ids unique across types).

Docs & portal

  • New examples: Control Schemes, Click to Connect, Accessibility, Unified Connector; new guides: /docs/accessibility, /docs/control-scheme, /docs/errors, /docs/ai, /docs/f-connector-directive.
  • v19.0.0 release post + a new "Feature Deep Dives" blog section (3 design articles), SEO-differentiated from docs/examples.
  • Search index now builds as part of portal:build (cached, deterministic output) — it had silently drifted a full release cycle.

Verification

  • f-flow 172/172 unit tests; lint clean; f-flow and portal builds green; llms validator green (18 API symbols, 46 docs links).
  • Live-verified in the schema-designer reference app: all pointer gestures (drag parity), click-to-connect T1–T6, full keyboard suite (navigation/selection/move/connect/delete/zoom), input-hijack guards, hover-flicker fix, opt-in/opt-out matrix.

🤖 Generated with Claude Code

siarheihuzarevich and others added 25 commits July 2, 2026 16:47
…ossing

prepareDragSequence() ran against the pointermove that crossed the 3px drag
threshold, so onPointerDownPosition was captured several px from the grab
point and the first move was deferred to the next pointermove. On a fast
flick this offset the dragged item from the cursor for the entire drag and
produced a visible 20-50px lag before the item snapped to catch up (#309).

Store the original pointer-down event and prepare the drag against it, then
apply the threshold-crossing move within the same event. Node dragging,
canvas panning, resize, rotate and connection creation now track the cursor
from the first frame with the grab point preserved.

Verified in a live browser (node drag and canvas pan track from the first
move; sub-threshold clicks still do not start a drag) and via nx build f-flow.

Fixes #309.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The connection preview line is painted by an <svg overflow:visible> inside a
zero-size host (.f-connections-container is 0x0). Safari/WebKit does not
invalidate the ink painted outside that box on display:none, so on drop the
preview line - often several accumulated frames of it - stayed painted on the
canvas until an unrelated repaint occurred (e.g. moving the pointer off the
flow).

Force that repaint once in onPointerUp by toggling f-canvas - the element that
owns the compositing layer the ink is rasterized into - out of and back into
the render tree, which re-rasters the whole layer and clears the remnant. The
toggle is synchronous, so the canvas size is unchanged by the end of the frame
and no ResizeObserver fires; the canvas transform is untouched.

Emit ordering is unchanged: CreateConnectionFinalize emits the create event
before calling onPointerUp, so this cleanup cannot affect edge creation.
Confirmed fixed on Safari 26.5 / macOS; no regression in Chromium (canvas not
stuck hidden, transform preserved, nodes and connections intact) and nx build
f-flow passes.

Fixes #311.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add withControlScheme(...) for provideFFlow(...) - a provider feature that
installs a control scheme: the complete gesture-to-action mapping (node move,
canvas pan, selection, create/reassign connection, resize, rotate, and wheel
pan-vs-zoom) driving fDraggable, f-canvas[fZoom] and f-selection-area
together. FControlSchemeController switches or tweaks the scheme at runtime
via setScheme().

Ships three presets: F_DEFAULT_CONTROL_SCHEME (drag pans, wheel zooms,
Shift+drag selects; applied when the feature is absent, so existing apps are
unchanged), F_SCROLL_PAN_CONTROL_SCHEME (Miro-like: scroll pans,
Ctrl/Cmd+scroll or pinch zooms, drag on the empty canvas selects, middle-drag
pans) and F_DRAG_SELECT_CONTROL_SCHEME (draw.io-like: wheel zooms, drag on
the empty canvas selects, middle-drag pans).

- Trigger inputs keep their names and always-callable types and override the
  active scheme when set; fWheelTrigger also overrides scrollPan routing.
- Scroll-to-pan routes through a new ScrollCanvasRequest execution; the new
  fPinchStep input gives trackpad pinch its own zoom step. Closes #312 and
  enables the mouse-wheel scrolling use case from #218.
- The middle mouse button joins the drag pipeline only when the active
  scheme's canvasMove gesture claims it - inert without a scheme, as before.
- A pointer-down that only starts the selection rectangle still runs
  single-selection unless Shift is held, so drag-to-select schemes clear on
  an empty-canvas click and replace on marquee while Shift stays additive;
  the default Shift-gated behavior is unchanged.
- New helpers: primaryButtonEventTrigger, middleButtonEventTrigger,
  isOnFlowBackground.
- Docs: /docs/control-scheme guide, /examples/control-schemes demo with
  preview images, updated trigger defaults in the interaction guides,
  llms.txt/llms-full.txt entries.

Verified in a live browser for the default scheme (wheel zoom, left-drag pan,
inert middle button, Shift+click keeps selection, Shift+marquee adds) and the
scroll-pan scheme (wheel pan, Ctrl+wheel zoom, middle-drag pan, click clears,
marquee replaces); nx build f-flow and portal pass.

Closes #312.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump the docs version badge and the stats fallback (v18.6.0 -> v19.0.0,
stars 478 -> 496) and drop a stray blank line in the selection-area example
styles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ection API

Add a single [fConnector] directive that replaces the legacy
fNodeInput/fNodeOutput/fNodeOutlet trio:

- one id per connector (fConnectorId); behavior is controlled by
  fConnectorType: 'source' | 'target' | 'source-target' (default) | 'outlet'
- inputs: fConnectorDisabled, fConnectorMultiple (default true),
  fConnectorCategory, fConnectorConnectableSide, fConnectorSelfConnectable,
  fCanBeConnectedTo (replaces fCanBeConnectedInputs), fConnectionFromOutlet
- neutral .f-connector* CSS classes and data-f-connector-* host attributes;
  theme mixins in _connector.scss cover both legacy and new classes
- outlet keeps the shared-start-surface semantics: the emitted
  FCreateConnectionEvent.sourceId is always the resolved real source id

f-connection gets canonical fSourceId/fTargetId and fSourceSide/fTargetSide
inputs; fOutputId/fInputId/fOutputSide/fInputSide are deprecated but keep
working (a new input wins when set, otherwise the deprecated one is used).

Internals:

- unified FComponentsStore.connectors registry; legacy connectors stay in
  outputs/inputs/outlets (the same id may legally be both an input and an
  output there), all resolution goes through findSourceConnector/
  findTargetConnector fallback helpers and isSource/isTarget/isOutlet
  connector predicates
- create-connection gets a from-connector preparation branch; outlet
  resolution, reassign, resize/drag/rotate handlers and node connection
  calculators are unified-registry aware
- internal consumers read connection.sourceId()/targetId() instead of the
  deprecated fOutputId()/fInputId()
- specs: fallback resolution units plus a mounted-directive smoke test

Docs/portal:

- new f-connector-directive page (New badge) and unified-connector example
  mirroring connector-outlet; legacy connector pages get Deprecated badges
- migration notes: fConnectorMultiple defaults to true (legacy outputs were
  single-connection) and connector ids are unique across all types
- llms.txt / llms-full.txt updated

Legacy directives keep working unchanged and are deprecated via JSDoc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make the library reliable for LLMs and AI coding agents, which work against
the installed npm package and iterate on console/build output.

Diagnostics (dev-mode, stable FFxxxx codes linking to /docs/errors):
- FF1001: a <f-connection> endpoint id matching no rendered connector - the
  most common silent failure - now warns once per connection with the list of
  registered connector ids; suppressed while progressive rendering is pending.
- FF1002: zero-height f-flow host (invisible flow) warns after first paint.
- FF1003: a connector outside [fNode]/[fGroup] now throws an actionable error
  instead of a bare NullInjectorError (shared injectConnectorNode helper).
- Warnings are stripped from production builds via ngDevMode.
- JSDoc added to the previously undocumented FNodeBase and FConnectorBase
  public members, so the published .d.ts explains the API agents read first.

Agent rules shipped with the package:
- ng add @foblex/flow writes a marker-delimited Foblex Flow section into the
  workspace AGENTS.md (created if missing) pointing agents at the
  version-matched node_modules/@foblex/flow/AI.md, llms.txt/llms-full.txt and
  the FFxxxx reference; re-running refreshes only the managed block;
  --skip-agent-rules opts out.
- AI.md rewritten for the current API: unified fConnector, fSourceId/fTargetId,
  provider features, a minimal three-file working setup (including the
  imports: [FFlowModule] step) and a silent-failure checklist.

LLM docs freshness:
- llms-full.txt updated to v18.6.1 and gains reflow (withReflowOnResize,
  FReflowController, fReflowIgnore) and canvas layer ordering (EFCanvasLayer,
  fLayers, withFCanvas); llms.txt links every registered docs page.
- scripts/validate-llms-content.mjs (wired into seo:check/prebuild) fails the
  build when the llms files drift from the package version, the docs page
  list, or the REQUIRED_SYMBOLS API checklist.
- New /docs/errors and /docs/ai pages; quickstart gains the FFlowModule
  snippet; READMEs and robots.txt link the LLM docs; scripts/ai-eval scaffolds
  a web-codegen-scorer eval comparing baseline vs bundled-docs generation.

Verified: FF1001 reproduced live in schema-designer (broken seed id -> warning
with registered-id list), healthy app emits no FF warnings, f-flow and portal
builds pass, llms validator green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nodes, groups, or connections rendered inside nested @if/@for blocks (or a
wrapper element) are not projected into <f-canvas>: Angular creates the
instances - they register with the flow - but their elements stay detached
from the document, geometry collapses to 0x0, and nothing renders, with no
error anywhere. This is one of the most common integration mistakes and was
previously invisible even to the FF1001 endpoint check, because the detached
connectors still resolve by id.

Detect it directly: after each settled nodes change, warn once per registered
node/group/connection whose hostElement.isConnected is false, naming the item
and the exact fix (<ng-container ngProjectAs="[fNodes]"> / "[fGroups]" /
"[fConnections]"). Dev-mode only via ngDevMode.

Docs: FF1004 section with a before/after example in /docs/errors, a hard rule
plus silent-failure entry in the bundled AI.md, the pitfall in the quickstart
and in llms-full.txt's mental model, and ngProjectAs added to the llms
validator's required symbols.

Verified live in schema-designer: wrapping the nodes @for in @if(true) makes
all 10 nodes vanish silently on HEAD; with this change the console emits
FF1004 naming each node and the fix; adding the suggested ng-container
restores all nodes and connections; the healthy app emits no warnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A native <select> dropdown (and other OS-level popups) opened from inside a
node swallows the pointerup that ends a drag sequence. The document-level
mousemove/pointerup listeners stayed armed, so the next mouse move - with no
button pressed - crossed the 3px threshold and started a phantom drag that
glued the node or canvas to the cursor until an unrelated pointerup (e.g. a
right-click) was delivered.

Treat a buttonless mousemove as the missed pointerup: if a drag is already in
progress, finalize it at the last position the button was actually held at
(the current buttonless position would teleport the item), then end the
sequence and detach the listeners.

Verified in the browser against the drag pipeline: mousedown followed by
buttonless moves no longer drags nodes or pans the canvas; a drag in progress
ends at its last held position when the buttonless move arrives (finalize
grid-snap only); subsequent normal drags work; reproduced scenario matches
the Custom Nodes example's embedded select.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssues

Extract the settled-nodes dev checks into a RunDevDiagnostics execution
(FF1004 moved there from FFlowComponent) and add five new codes, each
targeting a silent failure that repeatedly appears in issues:

- FF1005: interaction features (fDragHandle, f-selection-area,
  f-connection-for-create, snap, resize/rotate handles) present while
  fDraggable is missing on <f-flow> - everything renders but every pointer
  interaction is inert. Warned once per feature.
- FF1006: a connector hidden with CSS (display:none) registers but its
  geometry is a 0x0 point, so connections attach wrongly (issue #207 class).
- FF1007: an fNode element nested inside another node element - the outer
  node wins the drag and inner bindings never fire (issue #101).
- FF1008: fNodeParentId/fGroupParentId referencing an id no rendered group
  has; the warning lists registered ids (FF1001-style resolution for
  hierarchy).
- FF1009: fitToScreen()/resetScaleAndCenter()/centerGroupOrNode() called
  before the first fFullRendered computes against an incomplete node set
  (issues #281/#28/#196); checked against RenderLifecycleState.

FF1001 now recognizes unresolved ids that look like unevaluated template
expressions (node.outputId) and suggests the missing property-binding
brackets (issue #69).

Docs: FF1005-FF1009 sections in /docs/errors; the bundled AI.md gains the
new checklist entries plus an Additional Rules section covering the
docs-only pitfalls (zone/OnPush mutation, stable ids, global styles,
autosize-vs-restore, multiple flows, SELECTED_* markers, category
allow-list semantics, fCache/fVirtualFor at scale); llms-full.txt lists all
diagnostic codes.

Verified live in schema-designer: each of the five codes reproduced with a
temporary breakage and emits an actionable one-shot warning; the healthy app
emits no warnings (no false positives across 86 connectors, groups, and the
fFullRendered-driven fitToScreen); f-flow build passes and the llms
validator is green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…F1009)

fitToScreen()/resetScaleAndCenter()/centerGroupOrNode() compute from the
nodes bounding box, so calling them once the nodes are rendered and measured
is already correct - connections do not affect the result. Warning on
"before fFullRendered" was too strict: (fNodesRendered) is a legitimate and
earlier moment for initial positioning.

Gate FF1009 on RenderLifecycleState.isNodesRendered instead of
isFullRendered, and point the message and docs at (fNodesRendered) as the
earliest safe hook, with (fFullRendered) as the alternative.

Verified live: fitToScreen() driven by (fNodesRendered) emits no warning;
the early-call path (ngAfterViewInit) still warns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nt create-connection session

Extract the connection-creation logic from the drag handler into
FCreateConnectionSession — begin/update/resolveTarget/complete/cancel — which
owns the preview line, snap highlighting, connectable marking, target
resolution and the fCreateConnection emission. The drag handler and finalize
step become thin delegates, so any gesture that drives the session gets
identical validation, snapping and events.

withConnectionFlow(...) in provideFFlow(...) selects the gesture: 'click'
installs the built-in click-to-connect (click a source connector to arm, the
preview follows the cursor with no button held, click a connectable target to
commit; Escape or clicking elsewhere cancels, clicking another source re-arms;
drag-to-connect keeps working alongside), and a custom Type<IFConnectionFlow>
installs your own strategy. The token carries the strategy type; fDraggable
instantiates it against the f-flow element injector so flow-scoped services
resolve even though the feature is registered at the consumer component.

Ships the Click to Connect example, llms/AI docs entries, and the validator
symbol.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the Click to Connect example from the Connectors group to
Connections - Editing (page markdown follows), and register the auto-pan
example as a lazy docs component so the f-auto-pan guide renders it live.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the pre-seeded connection so the example demonstrates the gesture
from a clean state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oard connection creation

Every flow now applies ARIA semantics automatically: roles and generated
accessible names on nodes, groups and connections (attributes the consumer
sets are never overridden, generated connection names track endpoint
changes), aria-hidden on the minimap and connection previews, and a
visually-hidden live region announcing selection, movement, connection and
deletion. Inert attributes only — no behavior changes without opting in.

provideFFlow(withA11y()) enables the keyboard layer. DOM focus stays on the
f-flow host (the single tab stop, role=application, transparent focus ring
that Windows High Contrast repaints); arrows drive the SELECTION directly
with the active item exposed via aria-activedescendant, so there is no
separate focus state. Navigation is spatial and edge-based, travels over
nodes and connections alike, extends the selection with Shift, walks the
topology with Ctrl+arrow, and returns to the source on the opposite arrow.
Space moves the whole selection both ways — hold-and-arrow with drop on
release, or tap-to-grab / tap-to-drop for users who cannot chord keys — and
emits the same fMoveNodes a pointer drag does. C starts a connection from
the single selected node through the shared FCreateConnectionSession,
defaulting to the nearest connector on another node that is not already
connected; Enter emits fCreateConnection. Delete/Backspace emits the new
fDeleteSelected event — the library never mutates the graph. +/-/0 zoom.

Native interactive content inside nodes is never hijacked, single-character
keys yield to OS shortcuts, and active modes invalidate when their items
leave the data. withA11y(config) tunes movement steps, per-action key
bindings (IFA11yKeys, empty array disables an action) and the fully
localizable announcement catalog (IFA11yMessages).

Ships the Accessibility example, the /docs/accessibility guide, llms/AI
docs entries and the validator symbol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e the repaint workaround to WebKit

Click-to-connect now obeys the same contracts as the drag gesture: it stays
inert when fDraggableDisabled is set and consults the createConnection
trigger of the active control scheme before arming. The remnant-ink canvas
repaint after a connection drop is WebKit-specific, so other engines now
skip the forced synchronous layout flush entirely.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New "Feature Deep Dives" blog group with standalone design stories for the
v19 headline features: keyboard accessibility (selection-instead-of-focus
model), the unified fConnector model, and control schemes. Titles and
descriptions are intent-distinct from the docs pages, examples and the
release post to avoid SEO overlap; each article embeds its live demo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ibility previews

The release post embeds the four feature demos as live ng-components (the
blog convention) instead of bare links; the accessibility example gets
generated light/dark preview images wired into its page entry. Markdown
italics normalized by prettier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1028 -> 1169 documents; the accessibility guide/example, click-to-connect,
control schemes, the unified connector pages, the v19.0.0 release post and
the three feature deep-dives are now searchable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
portal:build now depends on build-search-index (alongside
generate-artifacts), so the index can no longer silently drift from the
content — it had already missed an entire release cycle. The target is
cached on the markdown/sections/script inputs, so repeat builds and serve
are a no-op when content is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
While creating or reassigning a connection the pointer rides the edge of a
connection path — the preview line ends exactly at the cursor — so hover
hit-testing flipped between the path and the background every frame,
flickering :hover styles and the cursor type. The connection host was
already inert; the real hit targets are its children (.f-connection-group
with pointer-events: all, the stroke paths with pointer-events: stroke,
waypoint handles). Connections take no part in drop targeting, so those
targets now give up pointer events while the flow host carries the
f-dragging or f-connections-dragging class, and get them back on release.
Verified live: selection stroke goes stroke -> none -> stroke across
create-connection and node drags.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The generator writes minified JSON, but lint-staged prettified the 5 MB
artifact on commit, so every subsequent build left the tree dirty and
defeated the nx output cache. The file is now prettier-ignored and
committed byte-identical to what build-search-index produces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the builtAt wall-clock field from the index payload — it made every
regeneration differ by one byte-range, so the nx output cache kept
restoring a stale artifact over the committed one and every build left
the tree dirty. Same inputs now produce byte-identical output (verified
by hash across runs), so cache restores, fresh runs and the committed
file all agree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…croll-pan

PR #313 by @yaroslavyushchenko independently implemented scroll-pan and
fPinchStep against the pre-v19 zoom directive. It is merged to main so the
contribution stays in history; this merge resolves every touched file to
the v19 implementation, which covers the same behavior through the control
scheme with deltaMode-normalized pan deltas and the mediator scroll path.
Credited in the changelog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@siarheihuzarevich siarheihuzarevich self-assigned this Jul 5, 2026
@siarheihuzarevich siarheihuzarevich added bug Something isn't working documentation Improvements or additions to documentation examples Public examples and example docs labels Jul 5, 2026
@siarheihuzarevich siarheihuzarevich added area:zoom Zoom, scale, and wheel interaction behavior area:drag-and-drop Drag session lifecycle and pointer-based interactions area:connections Connection rendering, routing, and recalculation labels Jul 5, 2026
siarheihuzarevich and others added 2 commits July 5, 2026 20:57
…chor

The spec encoded the pre-#309 behavior: the drag anchored at the
threshold-crossing point and swallowed the first mousemove, so a single
move to clientX -250 left the node in place and the pointerup at 0 nudged
it by +250. Since #309 the drag anchors at the pointer-down position and
the threshold-crossing move applies immediately, so the node followed the
pointer off-viewport and Cypress failed the actionability check on the
next trigger. The spec now drags relative to the node center and asserts
the pointer-tracking delta.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…the base rules

The connection-limits branch returned the whitelist matches directly,
skipping the target.canBeConnected check and the self-connect rule — an
allow-list could offer a disabled or at-capacity target, or a connection
inside the same node. Target filtering now lives in a pure
filterConnectableTargets helper where the allow-list only NARROWS the
candidates and the base rules always apply, with unit specs covering the
bypass cases and category matching.

Also from the follow-up review:

- test noise: the library's own suites suppress FF dev warnings via a new
  fSuppressDevWarnings switch (module-load setup spec) — fixtures
  legitimately violate the checks and the noise buried real warnings
- FA11yController gets lifecycle specs (arrow selection, interactive
  content guard, OS shortcut passthrough, multi-node grab/drop/revert,
  quasimode release, fDeleteSelected gating, key rebinding/disable,
  inert-without-config)
- changelog: the host application-role semantics are correctly attributed
  to the opt-in keyboard layer, and the navigation description matches
  the shipped edge-gap algorithm instead of the discarded sector one
- examples: no non-null assertions after guards

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:connections Connection rendering, routing, and recalculation area:drag-and-drop Drag session lifecycle and pointer-based interactions area:zoom Zoom, scale, and wheel interaction behavior bug Something isn't working documentation Improvements or additions to documentation examples Public examples and example docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: fScrollPan and fPinchStep inputs for better trackpad support

1 participant