Repository navigation
RigCheck: runtime for signatures, animations, sheets, wrap, scaled frames, record formulas and fixes - #81
Merged
Conversation
…up, pad Actions could read list items but not build or change one: there was no way to find an item's index, make a map, or copy a record with one field changed. These let a setVariable update one item of a list variable, e.g. set(defects, findIndex(defects, d => d.id == id), merge(d, obj(...))). group() formats 412908 as 412,908. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
Gradient fills use the paint's tileMode and scale the gradient so that one run is gradientExtent pixels long (the radius of a radial gradient), so a short gradient with hard stops paints stripes on rectangles, frames and anything else that builds its fills with buildFills. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PassiveSignatureTransformer draws a SignatureNode: background, border
(error border when its error binding is true), sign line with an x, the
placeholder while empty, and the strokes in round-cap ink smoothed with
quadratic curves. Drawing claims the pointer at once, so a scrolling
parent does not take a stroke. A finished stroke writes all strokes, as
[[[x, y], ...], ...], to the bound value variable (or the node value)
and fires changed; setting the variable to [] clears the pad.
Also fixes the isEmpty and isNotEmpty accessors of list variables, which
read the list as a map and gave null, so ${signature.isEmpty} works.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nodes with a loopAnimation build inside a LoopAnimationBox, which repeats a pulse, fade, scale or spin on its own ticker and disposes it with the node. A `loopAnimationEnabled` condition or variable turns it on and off without remounting the node, and under a disabled TickerMode (the editor's design canvas) it holds still at its start. Nodes with cursorEnter, cursorExit or hover reactions get a translucent MouseRegion that runs them, so hover state can be kept with set variable actions. Taps and regions behind still get through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sword fields isEmpty on a text variable holding "" was false: the empty text reads as null and isEmpty(null) returned false, so a form couldn't check that its error messages were cleared before submitting. A fixed-height text field expands, which leaves maxLines null, and only single-line fields were obscured, so a PIN or password field in a fixed box showed its text. An obscured field that isn't explicitly multi-line now keeps one line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
showLayoutDialog pushes a LayoutPresentationRoute that presents the canvas per ShowDialogAction.presentation: - dialog: centered at its design size, now scaling and fading in (0.96 to 1, 320 ms easeOutCubic). - bottomSheet: full width at the bottom, top corners radius 10, a 40x4 grab handle 8 px from the top, as tall as the canvas (its content when it shrink-wraps) up to maxHeightFactor of the screen; slides up. - sideSheet: full height on the right, sheetWidth (or the canvas's design width) wide, with a shadow; slides in from the right. The barrier color, barrier dismissal, route params and Navigate back results work as before. A new CanvasSizing.fillWidth sizes the bottom sheet's canvas. What a show-dialog's canvas passes back on Navigate back becomes the chain's result for the actions after it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
A text's ${...} preview on the design canvas (VariableSpan) read item
through the editor's scope resolver, which always picks the list's first
item, while the same row's fill, stroke and visible bindings read the
row's own item from IndexedItemProvider. On the render canvas each
preview row painted item 0's text with its own bindings, and
${= flags[item.id].note} showed the placeholder "Flags" in rows whose
own item had a flag but item 0 had none.
VariablePreview.textFor takes the IndexedItem of the build context; when
it carries data, item reads it. Lists built without item data keep the
resolver's first item.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntent The spacer transformer returned its own Expanded, and the row/column passed it through untouched. The editor's render canvas wraps every node in GeometryProbes (render objects), so the Expanded no longer sat directly under the Flex: its flex was dropped and the spacer kept its 100 px design size. The row/column now wraps the spacer like any other flexing child, outside everything built for it, and the transformer only builds its box. DesignCellGridDelegate turned a fixed cross-axis count into "as many design-size cells as fit", with the design cell taken from the node box, so a 100 wide grid from JSON got a dozen columns. A fixed count is now SliverGridDelegateWithFixedCrossAxisCount: the count is kept and the grid's width divided between cells. GridDelegateProperties.shrinkWrapRows builds the grid as a list of rows of Expanded cells in an IntrinsicHeight (IntrinsicWidth when horizontal), each as tall as its tallest item; items that can't report intrinsics keep their own size in a row as tall as the tallest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
…p, scaled frames, parent size
- Text fields evaluate their errorText binding (formulas included); an
empty message is no error, so the error border shows only while there is
one. An error binding (bool) gives the error borders without a message.
enabled, obscureText, readOnly, showCursor, maxLength, isCollapsed and
isDense follow their bindings too.
- Formulas: reverse, substring (negative indexes count from the end),
left, right and toMap(list, key, value). Lambdas take an optional index
parameter, (item, i) => ..., in every list function. All documented in
functionDocs.
- ConfirmAction.presentation: the built-in dialog and a dialogId canvas
show as a dialog, bottom sheet or side sheet through
LayoutPresentationRoute, like showDialog.
- Toasts draw an accentColor bar down the left edge and take iconColor,
fontFamily and cornerRadius.
- A node disabled through its disabled binding, with no Disabled state of
its own, fades to 40 %; it already ignored taps.
- RowColumnNode.wrap builds a Wrap with wrapSpacing and wrapRunSpacing.
Spacers and children hidden at runtime are left out.
- FrameNode.contentFit lays the children out at the frame's design size
and scales them into the frame (ScaledContent).
- The parent variable: ${parent.width} and ${parent.height} are the size
a node's parent gives it (ParentSizeScope), so a binding can switch a
layout on its container's width. Nodes that read it are built in a
LayoutBuilder and count as blocking intrinsics.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
Navigate, replace and showDialog find a canvas in any published layout, whatever page it was designed on; a layout group on another page picks the canvas for the width; app variables are shared across pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
Where master released the same feature, master's version stays and this branch's duplicate goes: - wrap: master's CodelesslyWrap (spacing, runSpacing); this branch's Wrap and wrapSpacing/wrapRunSpacing are gone. - repeating gradients: master's gradientRepeatEvery; tileMode, gradientExtent and GradientExtentTransform are gone. - formulas: master's object, merge, set, setAt, append, take, skip, reverse, indexOf (with a predicate), substring, padLeft and thousands replace findIndex, group and pad; this branch adds left, right, toMap and the lambda index (indexOf passes it too). - text fields: master's bindable flags, one-line obscured fields and empty errorText; this branch adds an errorText bound in variables and a boolean error binding that shows the error borders. - dialogs: master's presentCanvas (dialog, bottom sheet, adaptive, alignment); this branch adds side sheets (LayoutPresentationRoute), and drag handle and height cap options for bottom sheets, off by default so saved sheets look as before. A bottom sheet now hugs its canvas, so a tap above it dismisses it. - list item text on the design canvas: master's fix, falling back to the first item when the list item carries no data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
Measured with IntrinsicHeight / IntrinsicWidth when a non-spacer child fills the cross axis and another non-spacer child gives it a size, as the editor's solver lays it out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR is the runtime side of the RigCheck rebuild; the model fields are in Codelessly/CodelesslyAPI#46. Everything is listed under Unreleased in
CHANGELOG.md.Up to date with master (8.3.0). Where 8.3.0 already shipped the same thing, master's version stays and this branch's duplicate was removed:
CodelesslyWrap)gradientRepeatEvery)object,merge,set,setAt,append,take,skip,reverse,indexOf,substring,padLeft,thousandserrorTextpresentCanvas)Added on top of master
LoopAnimationBox);cursorEnter,cursorExitandhoverreactions.LayoutPresentationRoute).showDragHandleandmaxHeightFactor, both off by default.confirmcan open as a dialog, bottom sheet, adaptive or side sheet.disabledwith no Disabled state of its own fades to 40%.errorTextcan also be bound invariables, and a booleanerrorbinding shows the error borders without a message;left,right,toMap, and an index parameter in list lambdas (indexOfpasses it too);isEmpty(null)is true, and listisEmpty/isNotEmptywork.contentFit(ScaledContent);parentsize variable;shrinkWrapRows;IntrinsicHeight).Tests: locally, with
codelessly_apioverridden to the API branch, every CI step passes:dart format(0 changed),flutter analyze(no issues),flutter test(842 passed), and the exampleflutter build web --wasm.Merge order
CI here stays red until Codelessly/CodelesslyAPI#46 is released, because CI resolves
codelessly_api ^6.2.0from pub.codelessly_api: ^6.3.0, merge, and release ascodelessly_sdk8.4.0.Known Issues
🤖 Generated with Claude Code
https://claude.ai/code/session_011WedhUVWdWR5swqZYMuGfP