Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Unreleased
## 6.2.0

### Layout

Expand All @@ -7,10 +7,39 @@
- Row/column `wrap` and `runSpacing`: children wrap onto further runs, like
Flutter's `Wrap`.

### Variables

- A variable whose value is a `${= ...}` formula keeps it for every type
(computed variables).
### Nodes

- `GaugeNode` (`gauge`): an arc or bar gauge, continuous or segmented, with
scale ticks, a solid or dashed limit marker and an optional fill fade and
meniscus. `value`, `limit`, `color` and `limitColor` are bindable.
- `BarChartNode` (`barChart`): bars with null "future" slots, a highlighted
bar, grid lines with labels and per-bar labels. `values`, `labels`,
`highlight` and `color` are bindable.
- `SliderNode`: a rectangle fader thumb with grip, fill from the thumb to the
end, notch tick marks every N divisions, a marker at a bindable
`markerValue`, a bindable `activeTrackColor`, and a selectable range.
- `TextNode` exposes `textColor` for bindings and conditions.
- `BlendMixin.transition` (`NodeTransition`: duration and curve): runtime
opacity changes from bindings and conditions animate.
- `SpacerNode` reads minimal JSON (`positioningMode`, `aspectRatioLock` and
`reactions` are optional).
- `CanvasProperties.previewParams`: sample route params the design canvas
shows a canvas with (a confirm dialog's `${route.title}`); the runtime
never reads them.
- `CornerRadius.fromJson` reads a number (every corner) and four numbers
(top-left, top-right, bottom-right, bottom-left), so `cornerRadius` can be
bound: `${= screen.isMobile ? [6, 6, 0, 0] : 6}`.

### Triggers, actions and variables

- `TriggerType.interval` with `TriggerModel.intervalMillis`, and
`TriggerType.changeEnd` for sliders.
- `ShowDialogAction.placement` (center, bottom sheet, adaptive, anchored) and
`anchorGap`; `ConfirmAction.placement` for canvas confirms.
- `ShowToastAction`: alignment, side margin, max width, corner radius,
action color, close button and font size.
- Computed variables: `VariableData.formula` and `isComputed`; a variable
whose value is a `${= ...}` formula keeps it for every type.

## 6.1.0

Expand Down
3 changes: 3 additions & 0 deletions lib/src/api/mixins.dart
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ mixin BlendMixin on BaseNode {
/// Whether to use ink well on this node, along with its properties.
late InkWellModel? inkWell;

/// How the node animates when its style changes at runtime. Null jumps.
NodeTransition? transition;

/// Sets the blend properties of the node.
void setBlendMixin({
required double opacity,
Expand Down
7 changes: 7 additions & 0 deletions lib/src/api/models/action/confirm_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class ConfirmAction extends ActionModel with Equatable, SerializableMixin {
/// Corner radius of the built-in dialog. Null follows the app's buttons.
final double? cornerRadius;

/// Where a [dialogId] dialog shows, as for [ShowDialogAction.placement].
final DialogPlacement placement;

/// The key of the "Navigate back" params that answers a [dialogId] dialog.
static const String resultKey = 'confirmed';

Expand Down Expand Up @@ -107,6 +110,7 @@ class ConfirmAction extends ActionModel with Equatable, SerializableMixin {
this.textColor,
this.confirmColor,
this.cornerRadius,
this.placement = DialogPlacement.center,
super.nonBlocking,
super.enabled,
}) : actions = actions ?? [],
Expand Down Expand Up @@ -137,6 +141,7 @@ class ConfirmAction extends ActionModel with Equatable, SerializableMixin {
bool clearConfirmColor = false,
double? cornerRadius,
bool clearCornerRadius = false,
DialogPlacement? placement,
}) => ConfirmAction(
title: title ?? this.title,
message: message ?? this.message,
Expand All @@ -155,6 +160,7 @@ class ConfirmAction extends ActionModel with Equatable, SerializableMixin {
textColor: clearTextColor ? null : textColor ?? this.textColor,
confirmColor: clearConfirmColor ? null : confirmColor ?? this.confirmColor,
cornerRadius: clearCornerRadius ? null : cornerRadius ?? this.cornerRadius,
placement: placement ?? this.placement,
nonBlocking: nonBlocking,
enabled: enabled,
);
Expand All @@ -176,6 +182,7 @@ class ConfirmAction extends ActionModel with Equatable, SerializableMixin {
textColor,
confirmColor,
cornerRadius,
placement,
];

/// Creates an instance from a JSON object.
Expand Down
13 changes: 13 additions & 0 deletions lib/src/api/models/action/confirm_action.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions lib/src/api/models/action/show_dialog_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@ import '../models.dart';

part 'show_dialog_action.g.dart';

/// Where a [ShowDialogAction] puts its canvas.
enum DialogPlacement {
/// Centered over the screen at its design size.
center,

/// Pinned to the bottom edge, full width, sliding up.
bottomSheet,

/// A bottom sheet on screens narrower than 600 (mobile), centered
/// otherwise.
adaptive,

/// A popover just below the widget that opened it, like a menu, kept on
/// screen. Falls back to [center] when the opener has no position.
anchored;

/// Displayable label.
String get prettify => switch (this) {
DialogPlacement.center => 'Center',
DialogPlacement.bottomSheet => 'Bottom sheet',
DialogPlacement.adaptive => 'Sheet on mobile',
DialogPlacement.anchored => 'Below trigger',
};
}

/// An action that navigates to a new page.
@JsonSerializable()
class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
Expand All @@ -24,13 +49,21 @@ class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
/// Whether to show a close button on the dialog.
final bool showCloseButton;

/// Where the dialog shows.
final DialogPlacement placement;

/// Space between the opener and an [DialogPlacement.anchored] dialog.
final double anchorGap;

/// Creates a new [ShowDialogAction].
ShowDialogAction({
required this.destinationId,
Map<String, String>? params,
this.barrierColor = ColorRGBA.black54,
this.barrierDismissible = true,
this.showCloseButton = false,
this.placement = DialogPlacement.center,
this.anchorGap = 6,
super.nonBlocking,
super.enabled,
}) : params = {...params ?? {}},
Expand All @@ -43,6 +76,8 @@ class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
barrierDismissible,
barrierColor,
showCloseButton,
placement,
anchorGap,
];

/// Duplicates this [ShowDialogAction] with given data overrides.
Expand All @@ -52,12 +87,16 @@ class ShowDialogAction extends ActionModel with Equatable, SerializableMixin {
bool? barrierDismissible,
ColorRGBA? barrierColor,
bool? showCloseButton,
DialogPlacement? placement,
double? anchorGap,
}) => ShowDialogAction(
destinationId: destinationId ?? this.destinationId,
params: {...this.params, ...params ?? {}},
barrierDismissible: barrierDismissible ?? this.barrierDismissible,
barrierColor: barrierColor ?? this.barrierColor,
showCloseButton: showCloseButton ?? this.showCloseButton,
placement: placement ?? this.placement,
anchorGap: anchorGap ?? this.anchorGap,
);

/// Creates a new [ShowDialogAction] instance from a JSON data.
Expand Down
16 changes: 16 additions & 0 deletions lib/src/api/models/action/show_dialog_action.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 76 additions & 0 deletions lib/src/api/models/action/show_toast_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,29 @@ enum ToastPosition {
};
}

/// Where a toast sits across the screen.
enum ToastAlignment {
/// Centered, as wide as its content.
center,

/// Against the left margin.
start,

/// Against the right margin.
end,

/// As wide as the space between the margins.
stretch;

/// Label for the editor.
String get prettify => switch (this) {
ToastAlignment.center => 'Center',
ToastAlignment.start => 'Left',
ToastAlignment.end => 'Right',
ToastAlignment.stretch => 'Stretch',
};
}

/// An action that shows a short message near the bottom or top of the screen,
/// then hides it. The toast can carry a button, e.g. Undo, that runs
/// [actions].
Expand Down Expand Up @@ -91,6 +114,29 @@ class ShowToastAction extends ActionModel with Equatable, SerializableMixin {
/// [ToastPosition.bottom].
final double bottomOffset;

/// Where the toast sits across the screen.
@JsonKey(unknownEnumValue: ToastAlignment.center)
final ToastAlignment alignment;

/// Space between the toast and the screen's sides.
final double sideMargin;

/// The widest the toast gets.
final double maxWidth;

/// Corner radius. Null: a pill without a button, the app's button radius
/// (at least 8) with one.
final double? cornerRadius;

/// Color of the button's label. Null uses the message color.
final ColorRGBA? actionColor;

/// Whether the toast has a close (✕) button.
final bool showCloseButton;

/// Font size of the message.
final double fontSize;

/// Creates a new [ShowToastAction].
ShowToastAction({
required this.message,
Expand All @@ -103,6 +149,13 @@ class ShowToastAction extends ActionModel with Equatable, SerializableMixin {
List<ActionModel>? actions,
this.icon,
this.bottomOffset = 104,
this.alignment = ToastAlignment.center,
this.sideMargin = 16,
this.maxWidth = 560,
this.cornerRadius,
this.actionColor,
this.showCloseButton = false,
this.fontSize = 14,
super.nonBlocking,
super.enabled,
}) : actions = actions ?? [],
Expand All @@ -123,6 +176,13 @@ class ShowToastAction extends ActionModel with Equatable, SerializableMixin {
actions,
icon,
bottomOffset,
alignment,
sideMargin,
maxWidth,
cornerRadius,
actionColor,
showCloseButton,
fontSize,
];

/// Duplicates this [ShowToastAction] with given data overrides.
Expand All @@ -140,6 +200,15 @@ class ShowToastAction extends ActionModel with Equatable, SerializableMixin {
MultiSourceIconModel? icon,
bool clearIcon = false,
double? bottomOffset,
ToastAlignment? alignment,
double? sideMargin,
double? maxWidth,
double? cornerRadius,
ColorRGBA? actionColor,
bool clearActionColor = false,
bool clearCornerRadius = false,
bool? showCloseButton,
double? fontSize,
}) => ShowToastAction(
message: message ?? this.message,
duration: duration ?? this.duration,
Expand All @@ -153,6 +222,13 @@ class ShowToastAction extends ActionModel with Equatable, SerializableMixin {
actions: actions ?? this.actions,
icon: clearIcon ? null : icon ?? this.icon,
bottomOffset: bottomOffset ?? this.bottomOffset,
alignment: alignment ?? this.alignment,
sideMargin: sideMargin ?? this.sideMargin,
maxWidth: maxWidth ?? this.maxWidth,
cornerRadius: clearCornerRadius ? null : cornerRadius ?? this.cornerRadius,
actionColor: clearActionColor ? null : actionColor ?? this.actionColor,
showCloseButton: showCloseButton ?? this.showCloseButton,
fontSize: fontSize ?? this.fontSize,
nonBlocking: nonBlocking,
enabled: enabled,
);
Expand Down
Loading
Loading