origin 2.1.2
origin: ^2.1.2 copied to clipboard
Interactive hero transitions framework for Flutter with composable gesture physics.
2.1.2 #
Fixed #
- Active placeholder is now pinned to the slot's pre-active size instead of
SizedBox.expand, so Origins inside unbounded parents (Column / SliverList) no longer push siblings off-screen during a gesture.
2.1.1 #
Fixed #
- Release decay zones are now size-aware. Small rects no longer always pick the past-display decay slot.
2.1.0 #
Release/settle physics is now pluggable. Decay and rubber-back motion are
driven by [Simulation]s, with velocity continuity across the decay→settle
boundary. dismiss() is spring-driven, so the configured settle visibly
shapes return-to-origin motion.
Breaking #
DecelerateConfig→DecayConfig(andBounds.decelerate→.decay).DecayConfigslots:Friction?→Decay?. Use.imageViewer(),.iosScroll(),.exponential(x), etc.DecayConfig.settle:Friction?→Settle?. Use.attract().FrictionCurve→SimulationCurve(accepts any [Simulation]).
Added #
Decayabstract class +ExponentialDecaywith const presets (.iosScroll,.iosFast,.imageViewer,.none) and parameterized factories (.halfLife,.perFrame).Settleabstract class +AttractSettle({stiffness})— critically-damped spring back to target.copyWithonFrictionConfigandDecayConfig.
Fixed #
- Cropper handles wired to the wrong corners under RTL locale.
- Spurious huge fling velocity on simultaneous two-finger lift.
- Active-drag friction triggered everywhere on zoomed-in rects (past-display zone now picked correctly for rects larger than display).
2.0.0 #
Large refactor of the gesture, release, and physics layers and a built-in cropper tool. Spans 15 commits since 1.5.2; many public APIs changed shape.
Breaking #
GestureBoundsreplacesMap<DragBound, DragBounds>everywherebounds:is used. Convenience constructors:.vertical,.horizontal,.symmetric,.all, plus per-side.top/.bottom/.left/.right.ScaleResponseuses twoScaleRampzones (end+curveonly) — consecutive ramps auto-stitch from1.0(or prior zone's end) so they can't be made discontinuous.FrictionConfigships three named constructors:.uniform,.byDirection,.byZone. Per-slot default constructor still works.CropConfig: singleratio: Ratio?replaced withminAspectRatio: double?+maxAspectRatio: double?(equal values = locked aspect).RectExt.cropBoundaries/moveSide/moveCornertakedouble? aspectRatio(or named min/max oncropBoundaries) instead ofRatio?.AxisStatecollapsesextending+pastDisplayinto a singleDragDirectionStateenum mirroringFrictionConfig's four slots.- Per-axis drag-update helpers reorganized —
dragScaleFactorremoved;computeDragRect/applyDragTransformare the supported entry points. axisStateX/axisStateYreturn shape changed to useDragDirectionState.
Added #
- Built-in
Cropperwidget withCropConfig— dim/grid/handles, aspect-range support, mid-mode crop-drag with pinned-edge image follow, chrome cross-fade on entry/dismiss. - Mode system on
Origin—modes: {key: DisplayConfig}switched viaStage.setMode(key). Per-mode merge over the Origin's defaultdisplayConfigfield-by-field. Mode transitions animate rect + crop rect in parallel. - Stage transition signals:
transitionProgressMin/Mean/Max(ValueListenable<double>) — aggregated progress across the rect/crop animation controllers, gated byopeningOrDismissing || changingMode. PlusStage.changingModeflag. - Hybrid pointer merger —
OriginandStagecooperate during a single gesture when pointers cross between their hit regions. - Arena-based gesture cascade — drag/scale resolution via priority
cascade (per-gesture →
DisplayConfig→Stage→ default). - Decomposed per-axis release plan with adaptive rubber settle — velocity-driven decay phases per axis followed by a snap-back simulation.
- Drag → scale promotion cascade —
DragGesture.promote/DisplayConfig.dragPromote/Stage.dragPromote. - Scale-velocity translation cancel —
scaleVelocityCancelcascade damps residual pan velocity proportional to pinch velocity at release. - Skia-based
cropImageBytes+displayRectToSourceRecthelpers for consumers that want to apply the crop rect to source bytes. Stage.animateWidth({to, height?})— optionalheightlets the height tween target a value other thanto / aspectRatio(smooth aspect transitions duringanimateRect).Origin.aspectRatio— explicit aspect override (falls back tocontext.size!.aspectRatio).- Per-axis primitives
boundForX/Y,directionStateForX/Yfor consumers building custom routing. - Opt-in tap recognizers —
onTap/onDoubleTapregister only when a handler is supplied; without one, deeperGestureDetectors win the arena withoutkDoubleTapTimeoutlatency.
1.5.2 #
- Send overlays now clip against the origin container, matching the main overlay's clipping during reorder.
- Container expansion tracks per-frame drag deltas (monotonic — only grows during drag). Animated shrink back to origin container on dismiss, synced with the rect animation.
1.5.1 #
- Only reject multi-pointer when the recognizer has explicit gestures. Keeps pinch working on Stage's root recognizer.
1.5.0 #
- Breaking:
dismisssignature changed fromdismiss([Object? tag])todismiss({Object? tag, Object? except}).exceptskips the given tag from the return-all loop (for preserving swap targets). - Breaking:
unregisternow requires theOriginEntryinstance. Identity-aware unregister only removes the tag from the registry if the stored entry matches, preventing transient duplicates during keyed-children reorders. registerno longer asserts on duplicate tags — transient duplicates are tolerated and later resolved via identity-aware unregister._displacenow returns other parked/sending items to home on hover change, cleaning up stale displacements proactively.StageScaleRecognizerrejects the arena when a second pointer joins a single-pointer-only recognizer — releases pointers so nested Origins with multi-pointer gestures can claim them.
1.4.0 #
onEndacceptsFutureOr<void>and is awaited beforereset().dismiss()returns all active sends to.returningstate.
1.3.1 #
- Guard
dismiss(tag)to prevent stale tag states when tag has no active send.
1.3.0 #
- Swap support:
swapTagsandonSwaponOriginfor drag-to-reorder between Origins. _SendLayeranimates displaced items to target and back.TagStateenum (idle,sending,parked,returning) tracks displacement state.Stage.stateOf(context, tag)andStage.isActiveOf(context, tag)accessors.displace,release,captureEntryonStageData.isTagOfnow returnstruefor displaced tags (not just the active tag). UseisActiveOffor the previous behavior.
1.2.1 #
- Fix
sendEntryusing stale origin rect instead of measured position.
1.2.0 #
- Container computed in
StageviaValueNotifier<OriginRect?>, expand-only during interaction, shrinks on dismiss. Stage.isDismissingOf(context)aspect-based accessor.dismissingfield onStageData.- Dismiss drag anchors rect to pointer — content stays pinned under finger while scaling.
1.1.0 #
- Breaking:
itemGesturing/setItemGesturingreplaced bylocked/setLocked. Stage defaults to locked, unlocks afteranimateToBasecompletes, relocks onreset. - Breaking:
origin,originContainer,display,displayContainer,aspectRatioonStageDatachanged fromValueNotifierto plain values with setters. - Breaking:
originContaineranddisplayContainerare now nullable.nullmeans full screen (no container clip). - Container clipping: overlay clips content to an animated container rect using
ClipPath. Container expands fromoriginContainertowarddisplayContaineras the item moves. Stage.isLockedOf(context)static accessor.containerTagno longer falls back towidget.tag— only explicit container tags are measured.
1.0.0 #
- Breaking:
OriginDisplay+OriginScopemerged intoStage. - Breaking:
OriginItemreplaced byOrigin. - Breaking:
triggerEntrysplit intoopenEntryandsendEntry. - Breaking:
effectTransformreplaced byRotationclass withtoMatrix4. InheritedModelaspects:widgetOf,hasWidgetOf,tagOf,isTagOf.originToBaseProgressnotifier for border radius and scrim interpolation.- Configurable
backgroundColorscrim on Stage. onEndoverridable viasetOnEndorsendEntryoptional parameter.perspectiveonRotationclass andrunEffect.
0.3.0 #
- Breaking:
OriginItem.buildersignature changed fromWidgetBuilder?toWidget Function(BuildContext, Widget)?— receives the child widget as second parameter. - Breaking:
OriginItem.buildernow acts as the gesture builder in the overlay. If noOriginGesture.builderis provided, the item's builder is used instead. OriginItem.builderno longer replaces the overlay widget —widget.childis always used. The builder wraps the clipped child in the overlay.- Overlay blocks gestures on content beneath when active (absorbs pointers between content and overlay layer).
0.2.0 #
- Breaking:
OriginScope.registerItemcallback changed fromVoidCallbacktoFuture<void> Function([Rect Function(Rect)?]). - Breaking:
OriginScope.triggerItemaccepts optionalsendcallback for programmatic dismiss to a computed rect. - Breaking: Scope maps moved from widget instance to display state, fixing registration loss on rebuild.
OriginItem.onTapreplacestap, providesOriginTapEventwithanimateToBaseandrunEffect.OriginItem.onEndcallback fires after dismiss animation, before reset.OriginItem.perspectivefield with fallback chain: runEffect param → item → 0.OriginRect.copyWithmethod.- Gesture
builderonOriginGestureapplied in overlay outside ClipRRect. runEffectwith individual params, back-and-forth animation.- Effect transform uses
Matrix4?with null check. - Removed
OriginEffectclass.
0.1.0 #
- Custom gesture recognizer for arena control.
- GlobalKey state preservation across overlay.
- Vertical shrink dismiss, multi-finger zoom.
- Early gesture acceptance, reduced slop.
0.0.3 #
- Add stackBuilder for showing builder on top of child.
0.0.2 #
- Add tag, visibility, dismiss, animateToBase.
- InheritedModel with aspect-based rebuilds.
- ClipRRect and borderRadius animation on items.
- Safe controller resets.
0.0.1 #
- Initial release.